mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
translate-c-2 break and continue
This commit is contained in:
parent
6a3d48353b
commit
d54bcb2b62
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user