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...@@ -1047,5 +1047,7 @@ pub extern fn ZigClangWhileStmt_getBody(*const ZigClangWhileStmt) *const ZigClan
1047pub extern fn ZigClangDoStmt_getCond(*const ZigClangDoStmt) *const ZigClangExpr;1047pub extern fn ZigClangDoStmt_getCond(*const ZigClangDoStmt) *const ZigClangExpr;
1048pub extern fn ZigClangDoStmt_getBody(*const ZigClangDoStmt) *const ZigClangStmt;1048pub extern fn ZigClangDoStmt_getBody(*const ZigClangDoStmt) *const ZigClangStmt;
10491049
1050pub extern fn ZigClangDoStmt_getCond(*const ZigClangDoStmt) *const ZigClangExpr;1050pub extern fn ZigClangForStmt_getInit(*const ZigClangForStmt) ?*const ZigClangStmt;
1051pub extern fn ZigClangDoStmt_getBody(*const ZigClangDoStmt) *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 {...@@ -207,9 +207,10 @@ const Scope = struct {
207 };207 };
208 }208 }
209209
210 fn getBreakableScope(scope: *Scope) *Scope {210 fn getBreakableScope(inner: *Scope) *Scope {
211 var scope = inner;211 var scope = inner;
212 while (scope.id != .Switch and scope.id != .Root) : (scope = scope.parent.?) {}212 while (scope.id != .Switch and scope.id != .Root) : (scope = scope.parent.?) {}
213 return scope;
213 }214 }
214};215};
215216
...@@ -626,8 +627,9 @@ fn transStmt(...@@ -626,8 +627,9 @@ fn transStmt(
626 block.rbrace = try appendToken(rp.c, .RBrace, "}");627 block.rbrace = try appendToken(rp.c, .RBrace, "}");
627 return &block.base;628 return &block.base;
628 },629 },
629 .ContinueStmtClass => return transCreateNodeContinue(rp.c),630 .ContinueStmtClass => return try transCreateNodeContinue(rp.c),
630 .BreakStmtClass => return transBreak(rp, scope),631 .BreakStmtClass => return transBreak(rp, scope),
632 .ForStmtClass => return transForLoop(rp, scope, @ptrCast(*const ZigClangForStmt, stmt)),
631 else => {633 else => {
632 return revertAndWarn(634 return revertAndWarn(
633 rp,635 rp,
...@@ -795,7 +797,7 @@ fn transCompoundStmtInline(...@@ -795,7 +797,7 @@ fn transCompoundStmtInline(
795797
796fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node {798fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node {
797 const block_scope = try Scope.Block.init(rp.c, scope, false);799 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);
799 try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node);801 try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node);
800 block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");802 block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
801 return &block_scope.block_node.base;803 return &block_scope.block_node.base;
...@@ -1267,7 +1269,7 @@ fn transDoWhileLoop(...@@ -1267,7 +1269,7 @@ fn transDoWhileLoop(
1267 // zig: b;1269 // zig: b;
1268 // zig: if (!cond) break;1270 // zig: if (!cond) break;
1269 // zig: }1271 // 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).?;
1271 } else blk: {1273 } else blk: {
1272 // the C statement is without a block, so we need to create a block to contain it.1274 // the C statement is without a block, so we need to create a block to contain it.
1273 // c: do1275 // c: do
...@@ -1305,6 +1307,50 @@ fn transDoWhileLoop(...@@ -1305,6 +1307,50 @@ fn transDoWhileLoop(
1305 return &while_node.base;1307 return &while_node.base;
1306}1308}
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
1308fn transCPtrCast(1354fn transCPtrCast(
1309 rp: RestorePoint,1355 rp: RestorePoint,
1310 loc: ZigClangSourceLocation,1356 loc: ZigClangSourceLocation,
...@@ -1358,12 +1404,20 @@ fn maybeSuppressResult(...@@ -1358,12 +1404,20 @@ fn maybeSuppressResult(
1358 result: *ast.Node,1404 result: *ast.Node,
1359) TransError!*ast.Node {1405) TransError!*ast.Node {
1360 if (used == .used) return result;1406 if (used == .used) return result;
1361 // NOTE: This is backwards, but the semicolon must immediately follow the node.1407 if (scope.id != .Condition) {
1362 _ = try appendToken(rp.c, .Semicolon, ";");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 }
1363 const lhs = try transCreateNodeIdentifier(rp.c, "_");1417 const lhs = try transCreateNodeIdentifier(rp.c, "_");
1364 const op_token = try appendToken(rp.c, .Equal, "=");1418 const op_token = try appendToken(rp.c, .Equal, "=");
1365 const op_node = try rp.c.a().create(ast.Node.InfixOp);1419 const op_node = try rp.c.a().create(ast.Node.InfixOp);
1366 op_node.* = ast.Node.InfixOp{1420 op_node.* = .{
1367 .op_token = op_token,1421 .op_token = op_token,
1368 .lhs = lhs,1422 .lhs = lhs,
1369 .op = .Assign,1423 .op = .Assign,
...@@ -1728,7 +1782,8 @@ fn transCreateNodeAssign(...@@ -1728,7 +1782,8 @@ fn transCreateNodeAssign(
1728 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);1782 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
1729 const eq_token = try appendToken(rp.c, .Equal, "=");1783 const eq_token = try appendToken(rp.c, .Equal, "=");
1730 const rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);1784 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
1733 const node = try rp.c.a().create(ast.Node.InfixOp);1788 const node = try rp.c.a().create(ast.Node.InfixOp);
1734 node.* = .{1789 node.* = .{
...@@ -2196,7 +2251,7 @@ fn transCreateNodeContinue(c: *Context) !*ast.Node {...@@ -2196,7 +2251,7 @@ fn transCreateNodeContinue(c: *Context) !*ast.Node {
2196 .kind = .{ .Continue = null },2251 .kind = .{ .Continue = null },
2197 .rhs = null,2252 .rhs = null,
2198 };2253 };
2199 _ = try appendToken(rp.c, .Semicolon, ";");2254 _ = try appendToken(c, .Semicolon, ";");
2200 return &node.base;2255 return &node.base;
2201}2256}
22022257
test/translate_c.zig+24
...@@ -795,6 +795,30 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -795,6 +795,30 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
795 \\}795 \\}
796 });796 });
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
798 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////822 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
799823
800 if (builtin.os != builtin.Os.windows) {824 if (builtin.os != builtin.Os.windows) {