authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-17 01:08:08+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-17 01:40:06+02:00
logab6fe57462374d59b20ac46eeb4eefbf2f6938a0
treed59800e0a95a22da3b386d3fc943c15c062691b7
parentd54bcb2b62fe6cc7212bf370bcd257aaf1dfff8b
signature Commit is signed but in an unrecognized format.

translate-c-2 for loops


3 files changed, 92 insertions(+), 11 deletions(-)

src-self-hosted/clang.zig+4-2
......@@ -1047,5 +1047,7 @@ pub extern fn ZigClangWhileStmt_getBody(*const ZigClangWhileStmt) *const ZigClan
10471047pub extern fn ZigClangDoStmt_getCond(*const ZigClangDoStmt) *const ZigClangExpr;
10481048pub extern fn ZigClangDoStmt_getBody(*const ZigClangDoStmt) *const ZigClangStmt;
10491049
1050pub extern fn ZigClangDoStmt_getCond(*const ZigClangDoStmt) *const ZigClangExpr;
1051pub extern fn ZigClangDoStmt_getBody(*const ZigClangDoStmt) *const ZigClangStmt;
1050pub extern fn ZigClangForStmt_getInit(*const ZigClangForStmt) ?*const ZigClangStmt;
1051pub extern fn ZigClangForStmt_getCond(*const ZigClangForStmt) ?*const ZigClangExpr;
1052pub extern fn ZigClangForStmt_getInc(*const ZigClangForStmt) ?*const ZigClangExpr;
1053pub extern fn ZigClangForStmt_getBody(*const ZigClangForStmt) *const ZigClangStmt;
src-self-hosted/translate_c.zig+64-9
......@@ -207,9 +207,10 @@ const Scope = struct {
207207 };
208208 }
209209
210 fn getBreakableScope(scope: *Scope) *Scope {
210 fn getBreakableScope(inner: *Scope) *Scope {
211211 var scope = inner;
212212 while (scope.id != .Switch and scope.id != .Root) : (scope = scope.parent.?) {}
213 return scope;
213214 }
214215};
215216
......@@ -626,8 +627,9 @@ fn transStmt(
626627 block.rbrace = try appendToken(rp.c, .RBrace, "}");
627628 return &block.base;
628629 },
629 .ContinueStmtClass => return transCreateNodeContinue(rp.c),
630 .ContinueStmtClass => return try transCreateNodeContinue(rp.c),
630631 .BreakStmtClass => return transBreak(rp, scope),
632 .ForStmtClass => return transForLoop(rp, scope, @ptrCast(*const ZigClangForStmt, stmt)),
631633 else => {
632634 return revertAndWarn(
633635 rp,
......@@ -795,7 +797,7 @@ fn transCompoundStmtInline(
795797
796798fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node {
797799 const block_scope = try Scope.Block.init(rp.c, scope, false);
798 block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label);
800 block_scope.block_node = try transCreateNodeBlock(rp.c, null);
799801 try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node);
800802 block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
801803 return &block_scope.block_node.base;
......@@ -1267,7 +1269,7 @@ fn transDoWhileLoop(
12671269 // zig: b;
12681270 // zig: if (!cond) break;
12691271 // zig: }
1270 break :blk (try transStmt(rp, scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).?
1272 break :blk (try transStmt(rp, scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).?;
12711273 } else blk: {
12721274 // the C statement is without a block, so we need to create a block to contain it.
12731275 // c: do
......@@ -1305,6 +1307,50 @@ fn transDoWhileLoop(
13051307 return &while_node.base;
13061308}
13071309
1310fn transForLoop(
1311 rp: RestorePoint,
1312 scope: *Scope,
1313 stmt: *const ZigClangForStmt,
1314) TransError!*ast.Node {
1315 var inner = scope;
1316 var block = false;
1317 var block_scope: ?*Scope.Block = null;
1318 if (ZigClangForStmt_getInit(stmt)) |init| {
1319 block_scope = try Scope.Block.init(rp.c, scope, false);
1320 block_scope.?.block_node = try transCreateNodeBlock(rp.c, null);
1321 inner = &block_scope.?.base;
1322 _ = try transStmt(rp, inner, init, .unused, .r_value);
1323 }
1324 var cond_scope = Scope.Condition{
1325 .base = .{
1326 .parent = inner,
1327 .id = .Condition,
1328 },
1329 };
1330
1331 const while_node = try transCreateNodeWhile(rp.c);
1332 while_node.condition = if (ZigClangForStmt_getCond(stmt)) |cond|
1333 try transBoolExpr(rp, &cond_scope.base, cond, .used, .r_value, false)
1334 else
1335 try transCreateNodeBoolLiteral(rp.c, true);
1336 _ = try appendToken(rp.c, .RParen, ")");
1337
1338 if (ZigClangForStmt_getInc(stmt)) |incr| {
1339 _ = try appendToken(rp.c, .Colon, ":");
1340 _ = try appendToken(rp.c, .LParen, "(");
1341 while_node.continue_expr = try transExpr(rp, &cond_scope.base, incr, .unused, .r_value);
1342 _ = try appendToken(rp.c, .RParen, ")");
1343 }
1344
1345 while_node.body = try transStmt(rp, inner, ZigClangForStmt_getBody(stmt), .unused, .r_value);
1346 if (block_scope != null) {
1347 try block_scope.?.block_node.statements.push(&while_node.base);
1348 block_scope.?.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
1349 return &block_scope.?.block_node.base;
1350 } else
1351 return &while_node.base;
1352}
1353
13081354fn transCPtrCast(
13091355 rp: RestorePoint,
13101356 loc: ZigClangSourceLocation,
......@@ -1358,12 +1404,20 @@ fn maybeSuppressResult(
13581404 result: *ast.Node,
13591405) TransError!*ast.Node {
13601406 if (used == .used) return result;
1361 // NOTE: This is backwards, but the semicolon must immediately follow the node.
1362 _ = try appendToken(rp.c, .Semicolon, ";");
1407 if (scope.id != .Condition) {
1408 // NOTE: This is backwards, but the semicolon must immediately follow the node.
1409 _ = try appendToken(rp.c, .Semicolon, ";");
1410 } else { // TODO is there a way to avoid this hack?
1411 // this parenthesis must come immediately following the node
1412 _ = try appendToken(rp.c, .RParen, ")");
1413 // these need to come before _
1414 _ = try appendToken(rp.c, .Colon, ":");
1415 _ = try appendToken(rp.c, .LParen, "(");
1416 }
13631417 const lhs = try transCreateNodeIdentifier(rp.c, "_");
13641418 const op_token = try appendToken(rp.c, .Equal, "=");
13651419 const op_node = try rp.c.a().create(ast.Node.InfixOp);
1366 op_node.* = ast.Node.InfixOp{
1420 op_node.* = .{
13671421 .op_token = op_token,
13681422 .lhs = lhs,
13691423 .op = .Assign,
......@@ -1728,7 +1782,8 @@ fn transCreateNodeAssign(
17281782 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
17291783 const eq_token = try appendToken(rp.c, .Equal, "=");
17301784 const rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
1731 _ = try appendToken(rp.c, .Semicolon, ";");
1785 if (scope.id != .Condition)
1786 _ = try appendToken(rp.c, .Semicolon, ";");
17321787
17331788 const node = try rp.c.a().create(ast.Node.InfixOp);
17341789 node.* = .{
......@@ -2196,7 +2251,7 @@ fn transCreateNodeContinue(c: *Context) !*ast.Node {
21962251 .kind = .{ .Continue = null },
21972252 .rhs = null,
21982253 };
2199 _ = try appendToken(rp.c, .Semicolon, ";");
2254 _ = try appendToken(c, .Semicolon, ";");
22002255 return &node.base;
22012256}
22022257
test/translate_c.zig+24
......@@ -795,6 +795,30 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
795795 \\}
796796 });
797797
798 cases.add_2("for loops",
799 \\int foo() {
800 \\ for (int i = 2, b = 4; i + 2; i = 2) {
801 \\ int a = 2;
802 \\ a = 6, 5, 7;
803 \\ }
804 \\ char i = 2;
805 \\}
806 , &[_][]const u8{
807 \\pub export fn foo() c_int {
808 \\ {
809 \\ var i: c_int = 2;
810 \\ var b: c_int = 4;
811 \\ while ((i + 2) != 0) : (i = 2) {
812 \\ var a: c_int = 2;
813 \\ a = 6;
814 \\ _ = 5;
815 \\ _ = 7;
816 \\ }
817 \\ }
818 \\ var i: u8 = @as(u8, 2);
819 \\}
820 });
821
798822 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
799823
800824 if (builtin.os != builtin.Os.windows) {