Commit ab6fe57462
Changed files (3)
src-self-hosted
test
src-self-hosted/clang.zig
@@ -1047,5 +1047,7 @@ pub extern fn ZigClangWhileStmt_getBody(*const ZigClangWhileStmt) *const ZigClan
pub extern fn ZigClangDoStmt_getCond(*const ZigClangDoStmt) *const ZigClangExpr;
pub extern fn ZigClangDoStmt_getBody(*const ZigClangDoStmt) *const ZigClangStmt;
-pub extern fn ZigClangDoStmt_getCond(*const ZigClangDoStmt) *const ZigClangExpr;
-pub extern fn ZigClangDoStmt_getBody(*const ZigClangDoStmt) *const ZigClangStmt;
+pub extern fn ZigClangForStmt_getInit(*const ZigClangForStmt) ?*const ZigClangStmt;
+pub extern fn ZigClangForStmt_getCond(*const ZigClangForStmt) ?*const ZigClangExpr;
+pub extern fn ZigClangForStmt_getInc(*const ZigClangForStmt) ?*const ZigClangExpr;
+pub extern fn ZigClangForStmt_getBody(*const ZigClangForStmt) *const ZigClangStmt;
src-self-hosted/translate_c.zig
@@ -207,9 +207,10 @@ const Scope = struct {
};
}
- fn getBreakableScope(scope: *Scope) *Scope {
+ fn getBreakableScope(inner: *Scope) *Scope {
var scope = inner;
while (scope.id != .Switch and scope.id != .Root) : (scope = scope.parent.?) {}
+ return scope;
}
};
@@ -626,8 +627,9 @@ fn transStmt(
block.rbrace = try appendToken(rp.c, .RBrace, "}");
return &block.base;
},
- .ContinueStmtClass => return transCreateNodeContinue(rp.c),
+ .ContinueStmtClass => return try transCreateNodeContinue(rp.c),
.BreakStmtClass => return transBreak(rp, scope),
+ .ForStmtClass => return transForLoop(rp, scope, @ptrCast(*const ZigClangForStmt, stmt)),
else => {
return revertAndWarn(
rp,
@@ -795,7 +797,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);
+ block_scope.block_node = try transCreateNodeBlock(rp.c, null);
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;
@@ -1267,7 +1269,7 @@ fn transDoWhileLoop(
// zig: b;
// zig: if (!cond) break;
// zig: }
- break :blk (try transStmt(rp, scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).?
+ break :blk (try transStmt(rp, scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).?;
} else blk: {
// the C statement is without a block, so we need to create a block to contain it.
// c: do
@@ -1305,6 +1307,50 @@ fn transDoWhileLoop(
return &while_node.base;
}
+fn transForLoop(
+ rp: RestorePoint,
+ scope: *Scope,
+ stmt: *const ZigClangForStmt,
+) TransError!*ast.Node {
+ var inner = scope;
+ var block = false;
+ var block_scope: ?*Scope.Block = null;
+ if (ZigClangForStmt_getInit(stmt)) |init| {
+ block_scope = try Scope.Block.init(rp.c, scope, false);
+ block_scope.?.block_node = try transCreateNodeBlock(rp.c, null);
+ inner = &block_scope.?.base;
+ _ = try transStmt(rp, inner, init, .unused, .r_value);
+ }
+ var cond_scope = Scope.Condition{
+ .base = .{
+ .parent = inner,
+ .id = .Condition,
+ },
+ };
+
+ const while_node = try transCreateNodeWhile(rp.c);
+ while_node.condition = if (ZigClangForStmt_getCond(stmt)) |cond|
+ try transBoolExpr(rp, &cond_scope.base, cond, .used, .r_value, false)
+ else
+ try transCreateNodeBoolLiteral(rp.c, true);
+ _ = try appendToken(rp.c, .RParen, ")");
+
+ if (ZigClangForStmt_getInc(stmt)) |incr| {
+ _ = try appendToken(rp.c, .Colon, ":");
+ _ = try appendToken(rp.c, .LParen, "(");
+ while_node.continue_expr = try transExpr(rp, &cond_scope.base, incr, .unused, .r_value);
+ _ = try appendToken(rp.c, .RParen, ")");
+ }
+
+ while_node.body = try transStmt(rp, inner, ZigClangForStmt_getBody(stmt), .unused, .r_value);
+ if (block_scope != null) {
+ try block_scope.?.block_node.statements.push(&while_node.base);
+ block_scope.?.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
+ return &block_scope.?.block_node.base;
+ } else
+ return &while_node.base;
+}
+
fn transCPtrCast(
rp: RestorePoint,
loc: ZigClangSourceLocation,
@@ -1358,12 +1404,20 @@ fn maybeSuppressResult(
result: *ast.Node,
) TransError!*ast.Node {
if (used == .used) return result;
- // NOTE: This is backwards, but the semicolon must immediately follow the node.
- _ = try appendToken(rp.c, .Semicolon, ";");
+ if (scope.id != .Condition) {
+ // NOTE: This is backwards, but the semicolon must immediately follow the node.
+ _ = try appendToken(rp.c, .Semicolon, ";");
+ } else { // TODO is there a way to avoid this hack?
+ // this parenthesis must come immediately following the node
+ _ = try appendToken(rp.c, .RParen, ")");
+ // these need to come before _
+ _ = try appendToken(rp.c, .Colon, ":");
+ _ = try appendToken(rp.c, .LParen, "(");
+ }
const lhs = try transCreateNodeIdentifier(rp.c, "_");
const op_token = try appendToken(rp.c, .Equal, "=");
const op_node = try rp.c.a().create(ast.Node.InfixOp);
- op_node.* = ast.Node.InfixOp{
+ op_node.* = .{
.op_token = op_token,
.lhs = lhs,
.op = .Assign,
@@ -1728,7 +1782,8 @@ fn transCreateNodeAssign(
const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
const eq_token = try appendToken(rp.c, .Equal, "=");
const rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
- _ = try appendToken(rp.c, .Semicolon, ";");
+ if (scope.id != .Condition)
+ _ = try appendToken(rp.c, .Semicolon, ";");
const node = try rp.c.a().create(ast.Node.InfixOp);
node.* = .{
@@ -2196,7 +2251,7 @@ fn transCreateNodeContinue(c: *Context) !*ast.Node {
.kind = .{ .Continue = null },
.rhs = null,
};
- _ = try appendToken(rp.c, .Semicolon, ";");
+ _ = try appendToken(c, .Semicolon, ";");
return &node.base;
}
test/translate_c.zig
@@ -795,6 +795,30 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
});
+ cases.add_2("for loops",
+ \\int foo() {
+ \\ for (int i = 2, b = 4; i + 2; i = 2) {
+ \\ int a = 2;
+ \\ a = 6, 5, 7;
+ \\ }
+ \\ char i = 2;
+ \\}
+ , &[_][]const u8{
+ \\pub export fn foo() c_int {
+ \\ {
+ \\ var i: c_int = 2;
+ \\ var b: c_int = 4;
+ \\ while ((i + 2) != 0) : (i = 2) {
+ \\ var a: c_int = 2;
+ \\ a = 6;
+ \\ _ = 5;
+ \\ _ = 7;
+ \\ }
+ \\ }
+ \\ var i: u8 = @as(u8, 2);
+ \\}
+ });
+
/////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
if (builtin.os != builtin.Os.windows) {