From d54bcb2b62fe6cc7212bf370bcd257aaf1dfff8b Mon Sep 17 00:00:00 2001 From: Vexu Date: Mon, 16 Dec 2019 23:54:16 +0200 Subject: [PATCH] translate-c-2 break and continue --- src-self-hosted/translate_c.zig | 43 ++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index accbef9214..91c96756e0 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -54,6 +54,7 @@ const Scope = struct { const Switch = struct { base: Scope, + label: []const u8, }; /// used when getting a member `a.b` @@ -190,6 +191,7 @@ const Scope = struct { .Ref => null, .FnDef => @fieldParentPtr(FnDef, "base", scope).getAlias(name), .Block => @fieldParentPtr(Block, "base", scope).getAlias(name), + .Condition => scope.parent.?.getAlias(name), else => @panic("TODO Scope.getAlias"), }; } @@ -200,9 +202,15 @@ const Scope = struct { .Root => @fieldParentPtr(Root, "base", scope).contains(name), .FnDef => @fieldParentPtr(FnDef, "base", scope).contains(name), .Block => @fieldParentPtr(Block, "base", scope).contains(name), + .Condition => scope.parent.?.contains(name), else => @panic("TODO Scope.contains"), }; } + + fn getBreakableScope(scope: *Scope) *Scope { + var scope = inner; + while (scope.id != .Switch and scope.id != .Root) : (scope = scope.parent.?) {} + } }; const Context = struct { @@ -613,6 +621,13 @@ fn transStmt( .IfStmtClass => return transIfStmt(rp, scope, @ptrCast(*const ZigClangIfStmt, stmt)), .WhileStmtClass => return transWhileLoop(rp, scope, @ptrCast(*const ZigClangWhileStmt, stmt)), .DoStmtClass => return transDoWhileLoop(rp, scope, @ptrCast(*const ZigClangDoStmt, stmt)), + .NullStmtClass => { + const block = try transCreateNodeBlock(rp.c, null); + block.rbrace = try appendToken(rp.c, .RBrace, "}"); + return &block.base; + }, + .ContinueStmtClass => return transCreateNodeContinue(rp.c), + .BreakStmtClass => return transBreak(rp, scope), else => { return revertAndWarn( rp, @@ -1241,7 +1256,7 @@ fn transDoWhileLoop( _ = try appendToken(rp.c, .RParen, ")"); var new = false; - const body_node = if (ZigClangStmt_getStmtClass(ZigClangDoStmt_getBody(stmt)) == .CompoundStmtClass) + const body_node = if (ZigClangStmt_getStmtClass(ZigClangDoStmt_getBody(stmt)) == .CompoundStmtClass) blk: { // there's already a block in C, so we'll append our condition to it. // c: do { // c: a; @@ -1252,8 +1267,8 @@ fn transDoWhileLoop( // zig: b; // zig: if (!cond) break; // zig: } - (try transStmt(rp, scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).? - else blk: { + 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 // c: a; @@ -1262,7 +1277,6 @@ fn transDoWhileLoop( // zig: a; // zig: if (!cond) break; // zig: } - new = true; const block = try transCreateNodeBlock(rp.c, null); try block.statements.push(try transStmt(rp, scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)); @@ -1328,6 +1342,15 @@ fn transCPtrCast( return &ptrcast_node.base; } +fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node { + const break_scope = scope.getBreakableScope(); + const br = try transCreateNodeBreak(rp.c, if (break_scope.id == .Switch) + @fieldParentPtr(Scope.Switch, "base", break_scope).label + else + null); + return &br.base; +} + fn maybeSuppressResult( rp: RestorePoint, scope: *Scope, @@ -2165,6 +2188,18 @@ fn transCreateNodeWhile(c: *Context) !*ast.Node.While { return node; } +fn transCreateNodeContinue(c: *Context) !*ast.Node { + const ltoken = try appendToken(c, .Keyword_continue, "continue"); + const node = try c.a().create(ast.Node.ControlFlowExpression); + node.* = .{ + .ltoken = ltoken, + .kind = .{ .Continue = null }, + .rhs = null, + }; + _ = try appendToken(rp.c, .Semicolon, ";"); + return &node.base; +} + const RestorePoint = struct { c: *Context, token_index: ast.TokenIndex,