Commit e3f1bfe483

Vexu <git@vexu.eu>
2019-12-16 16:55:51
translate-c-2 if statements
1 parent 6265625
Changed files (3)
src-self-hosted/clang.zig
@@ -1036,3 +1036,7 @@ pub extern fn ZigClangPreprocessedEntity_getKind(*const ZigClangPreprocessedEnti
 pub extern fn ZigClangMacroDefinitionRecord_getName_getNameStart(*const ZigClangMacroDefinitionRecord) [*:0]const u8;
 pub extern fn ZigClangMacroDefinitionRecord_getSourceRange_getBegin(*const ZigClangMacroDefinitionRecord) ZigClangSourceLocation;
 pub extern fn ZigClangMacroDefinitionRecord_getSourceRange_getEnd(*const ZigClangMacroDefinitionRecord) ZigClangSourceLocation;
+
+pub extern fn ZigClangIfStmt_getThen(*const ZigClangIfStmt) *const ZigClangStmt;
+pub extern fn ZigClangIfStmt_getElse(*const ZigClangIfStmt) ?*const ZigClangStmt;
+pub extern fn ZigClangIfStmt_getCond(*const ZigClangIfStmt) *const ZigClangStmt;
src-self-hosted/translate_c.zig
@@ -67,18 +67,17 @@ const Scope = struct {
         variables: AliasList,
         label: ?[]const u8,
 
-        /// Don't forget to set rbrace token later
+        /// Don't forget to set rbrace token and block_node later
         fn init(c: *Context, parent: *Scope, want_label: bool) !*Block {
             // TODO removing `?[]const u8` here causes LLVM error
             const label: ?[]const u8 = if (want_label) try std.fmt.allocPrint(c.a(), "blk_{}", .{c.getMangle()}) else null;
-            const block_node = try transCreateNodeBlock(c, label);
             const block = try c.a().create(Block);
             block.* = .{
                 .base = .{
                     .id = .Block,
                     .parent = parent,
                 },
-                .block_node = block_node,
+                .block_node = undefined,
                 .variables = AliasList.init(c.a()),
                 .label = label,
             };
@@ -126,7 +125,6 @@ const Scope = struct {
     };
 
     const Condition = struct {
-        expr: *ast.Node,
         base: Scope,
     };
 
@@ -612,6 +610,7 @@ fn transStmt(
         .ParenExprClass => return transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue),
         .InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const ZigClangInitListExpr, stmt), result_used),
         .ImplicitValueInitExprClass => return transImplicitValueInitExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used),
+        .IfStmtClass => return transIfStmt(rp, scope, @ptrCast(*const ZigClangIfStmt, stmt), result_used),
         else => {
             return revertAndWarn(
                 rp,
@@ -718,18 +717,31 @@ fn transBinaryOperator(
         ),
         .Comma => {
             const block_scope = try scope.findBlockScope(rp.c);
+            const expr = block_scope.base.parent == scope;
+            const lparen = if (expr) blk: {
+                const l = try appendToken(rp.c, .LParen, "(");
+                block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label);
+                break :blk l;
+            } else undefined;
 
             const lhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getLHS(stmt), .unused, .r_value);
             try block_scope.block_node.statements.push(lhs);
 
             const rhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
-            if (block_scope.base.parent == scope) {
+            if (expr) {
+                _ = try appendToken(rp.c, .Semicolon, ";");
                 const break_node = try transCreateNodeBreak(rp.c, block_scope.label);
                 break_node.rhs = rhs;
-                _ = try appendToken(rp.c, .Semicolon, ";");
                 try block_scope.block_node.statements.push(&break_node.base);
                 block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
-                return maybeSuppressResult(rp, scope, result_used, &block_scope.block_node.base);
+                const rparen = try appendToken(rp.c, .RParen, ")");
+                const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
+                grouped_expr.* = .{
+                    .lparen = lparen,
+                    .expr = &block_scope.block_node.base,
+                    .rparen = rparen,
+                };
+                return maybeSuppressResult(rp, scope, result_used, &grouped_expr.base);
             } else {
                 return maybeSuppressResult(rp, scope, result_used, rhs);
             }
@@ -766,6 +778,7 @@ fn transCompoundStmtInline(
 
 fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node {
     const block_scope = try Scope.Block.init(rp.c, scope, false);
+    block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label);
     try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node);
     block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
     return &block_scope.block_node.base;
@@ -792,7 +805,7 @@ fn transCStyleCastExprClass(
 
 fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt) TransError!*ast.Node {
     const c = rp.c;
-    const block_scope = try scope.findBlockScope(c);
+    const block_scope = scope.findBlockScope(c) catch unreachable;
 
     var it = ZigClangDeclStmt_decl_begin(stmt);
     const end_it = ZigClangDeclStmt_decl_end(stmt);
@@ -1167,6 +1180,35 @@ fn transImplicitValueInitExpr(
     };
 }
 
+fn transIfStmt(
+    rp: RestorePoint,
+    scope: *Scope,
+    stmt: *const ZigClangIfStmt,
+    used: ResultUsed,
+) TransError!*ast.Node {
+    // if (c) t
+    // if (c) t else e
+    const if_node = try transCreateNodeIf(rp.c);
+
+    var cond_scope = Scope.Condition{
+        .base = .{
+            .parent = scope,
+            .id = .Condition,
+        },
+    };
+    if_node.condition = try transBoolExpr(rp, &cond_scope.base, @ptrCast(*const ZigClangExpr, ZigClangIfStmt_getCond(stmt)), .used, .r_value);
+    _ = try appendToken(rp.c, .RParen, ")");
+
+    if_node.body = try transStmt(rp, scope, ZigClangIfStmt_getThen(stmt), .used, .r_value);
+
+    if (ZigClangIfStmt_getElse(stmt)) |expr| {
+        if_node.@"else" = try transCreateNodeElse(rp.c);
+        if_node.@"else".?.body = try transStmt(rp, scope, expr, .used, .r_value);
+    }
+    _ = try appendToken(rp.c, .Semicolon, ";");
+    return &if_node.base;
+}
+
 fn transCPtrCast(
     rp: RestorePoint,
     loc: ZigClangSourceLocation,
@@ -1602,6 +1644,7 @@ fn transCreateNodeAssign(
     // zig: })
     _ = try appendToken(rp.c, .LParen, "(");
     const block_scope = try Scope.Block.init(rp.c, scope, true);
+    block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label);
     const tmp = try std.fmt.allocPrint(rp.c.a(), "_tmp_{}", .{rp.c.getMangle()});
 
     const node = try transCreateNodeVarDecl(rp.c, false, true, tmp);
test/translate_c.zig
@@ -732,6 +732,29 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\}
     });
 
+    cases.add_2("if statements",
+        \\int foo(char c) {
+        \\    if (2) {
+        \\        int a = 2;
+        \\    }
+        \\    if (2, 5) {
+        \\        int a = 2;
+        \\    }
+        \\}
+    , &[_][]const u8{
+        \\pub export fn foo(c: u8) c_int {
+        \\    if (2 != 0) {
+        \\        var a: c_int = 2;
+        \\    }
+        \\    if ((blk_1: {
+        \\        _ = 2;
+        \\        break :blk_1 5;
+        \\    }) != 0) {
+        \\        var a: c_int = 2;
+        \\    }
+        \\}
+    });
+
     /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
 
     if (builtin.os != builtin.Os.windows) {