Commit dda711ba0d

Vexu <git@vexu.eu>
2020-03-12 13:18:41
translate-c treat c bools as ints
1 parent f58705b
Changed files (2)
src-self-hosted
test
src-self-hosted/translate_c.zig
@@ -560,7 +560,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
 
     // TODO https://github.com/ziglang/zig/issues/3756
     // TODO https://github.com/ziglang/zig/issues/1802
-    const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{var_name, c.getMangle()}) else var_name;
+    const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ var_name, c.getMangle() }) else var_name;
     const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);
 
     const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
@@ -677,7 +677,7 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l
 
     // TODO https://github.com/ziglang/zig/issues/3756
     // TODO https://github.com/ziglang/zig/issues/1802
-    const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{typedef_name, c.getMangle()}) else typedef_name;
+    const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ typedef_name, c.getMangle() }) else typedef_name;
 
     if (mem.eql(u8, checked_name, "uint8_t"))
         return transTypeDefAsBuiltin(c, typedef_decl, "u8")
@@ -4871,7 +4871,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
                 const name = try c.str(raw_name);
                 // TODO https://github.com/ziglang/zig/issues/3756
                 // TODO https://github.com/ziglang/zig/issues/1802
-                const mangled_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{name, c.getMangle()}) else name;
+                const mangled_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, c.getMangle() }) else name;
                 if (scope.containsNow(mangled_name)) {
                     continue;
                 }
@@ -5560,12 +5560,63 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
     }
 }
 
+fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node {
+    if (!isBoolRes(node)) {
+        if (node.id != .InfixOp) return node;
+
+        const group_node = try c.a().create(ast.Node.GroupedExpression);
+        group_node.* = .{
+            .lparen = try appendToken(c, .LParen, "("),
+            .expr = node,
+            .rparen = try appendToken(c, .RParen, ")"),
+        };
+        return &group_node.base;
+    }
+
+    const builtin_node = try transCreateNodeBuiltinFnCall(c, "@boolToInt");
+    try builtin_node.params.push(node);
+    builtin_node.rparen_token = try appendToken(c, .RParen, ")");
+    return &builtin_node.base;
+}
+
+fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node {
+    if (isBoolRes(node)) {
+        if (node.id != .InfixOp) return node;
+
+        const group_node = try c.a().create(ast.Node.GroupedExpression);
+        group_node.* = .{
+            .lparen = try appendToken(c, .LParen, "("),
+            .expr = node,
+            .rparen = try appendToken(c, .RParen, ")"),
+        };
+        return &group_node.base;
+    }
+
+    const op_token = try appendToken(c, .BangEqual, "!=");
+    const zero = try transCreateNodeInt(c, 0);
+    const res = try c.a().create(ast.Node.InfixOp);
+    res.* = .{
+        .op_token = op_token,
+        .lhs = node,
+        .op = .BangEqual,
+        .rhs = zero,
+    };
+    const group_node = try c.a().create(ast.Node.GroupedExpression);
+    group_node.* = .{
+        .lparen = try appendToken(c, .LParen, "("),
+        .expr = &res.base,
+        .rparen = try appendToken(c, .RParen, ")"),
+    };
+    return &group_node.base;
+}
+
 fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {
     var node = try parseCPrimaryExpr(c, it, source, source_loc, scope);
     while (true) {
         const tok = it.next().?;
         var op_token: ast.TokenIndex = undefined;
         var op_id: ast.Node.InfixOp.Op = undefined;
+        var bool_op = false;
         switch (tok.id) {
             .Period => {
                 const name_tok = it.next().?;
@@ -5654,10 +5705,12 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
             .AmpersandAmpersand => {
                 op_token = try appendToken(c, .Keyword_and, "and");
                 op_id = .BoolAnd;
+                bool_op = true;
             },
             .PipePipe => {
                 op_token = try appendToken(c, .Keyword_or, "or");
                 op_id = .BoolOr;
+                bool_op = true;
             },
             .AngleBracketRight => {
                 op_token = try appendToken(c, .AngleBracketRight, ">");
@@ -5740,12 +5793,14 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
                 return node;
             },
         }
+        const rhs_node = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
         const op_node = try c.a().create(ast.Node.InfixOp);
+        const cast_fn = if (bool_op) macroIntToBool else macroBoolToInt;
         op_node.* = .{
             .op_token = op_token,
-            .lhs = node,
+            .lhs = try cast_fn(c, node),
             .op = op_id,
-            .rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope),
+            .rhs = try cast_fn(c, rhs_node),
         };
         node = &op_node.base;
     }
test/translate_c.zig
@@ -3,6 +3,17 @@ const std = @import("std");
 const CrossTarget = std.zig.CrossTarget;
 
 pub fn addCases(cases: *tests.TranslateCContext) void {
+    cases.add("c booleans are just ints",
+        \\#define FOO(x) ((x >= 0) + (x >= 0))
+        \\#define BAR 1 && 2 > 4
+    , &[_][]const u8{
+        \\pub inline fn FOO(x: var) @TypeOf(@boolToInt(x >= 0) + @boolToInt(x >= 0)) {
+        \\    return @boolToInt(x >= 0) + @boolToInt(x >= 0);
+        \\}
+    ,
+        \\pub const BAR = (1 != 0) and (2 > 4);
+    });
+
     cases.add("struct with aligned fields",
         \\struct foo {
         \\    __attribute__((aligned(1))) short bar;