translate-c-2 comma operator
parent
fe0e8c87b7
commit
d9527edfe0
|
@ -47,7 +47,7 @@ const Scope = struct {
|
|||
Switch,
|
||||
Block,
|
||||
Root,
|
||||
While,
|
||||
Condition,
|
||||
FnDef,
|
||||
Ref,
|
||||
};
|
||||
|
@ -65,9 +65,13 @@ const Scope = struct {
|
|||
base: Scope,
|
||||
block_node: *ast.Node.Block,
|
||||
variables: AliasList,
|
||||
label: ?[]const u8,
|
||||
|
||||
/// Don't forget to set rbrace token later
|
||||
fn init(c: *Context, parent: *Scope, block_node: *ast.Node.Block) !*Block {
|
||||
fn init(c: *Context, parent: *Scope, want_label: bool) !*Block {
|
||||
// TODO removing `?[]const u8` here causes LLVM error
|
||||
const label: ?[]const u8 = if (want_label) try std.fmt.allocPrint(c.a(), "blk_{}", .{c.getMangle()}) else null;
|
||||
const block_node = try transCreateNodeBlock(c, label);
|
||||
const block = try c.a().create(Block);
|
||||
block.* = .{
|
||||
.base = .{
|
||||
|
@ -76,6 +80,7 @@ const Scope = struct {
|
|||
},
|
||||
.block_node = block_node,
|
||||
.variables = AliasList.init(c.a()),
|
||||
.label = label,
|
||||
};
|
||||
return block;
|
||||
}
|
||||
|
@ -120,7 +125,8 @@ const Scope = struct {
|
|||
}
|
||||
};
|
||||
|
||||
const While = struct {
|
||||
const Condition = struct {
|
||||
expr: *ast.Node,
|
||||
base: Scope,
|
||||
};
|
||||
|
||||
|
@ -157,10 +163,19 @@ const Scope = struct {
|
|||
}
|
||||
};
|
||||
|
||||
fn findBlockScope(inner: *Scope) *Scope.Block {
|
||||
fn findBlockScope(inner: *Scope, c: *Context) !*Scope.Block {
|
||||
var scope = inner;
|
||||
while (true) : (scope = scope.parent orelse unreachable) {
|
||||
if (scope.id == .Block) return @fieldParentPtr(Scope.Block, "base", scope);
|
||||
while (true) {
|
||||
switch (scope.id) {
|
||||
.Root => unreachable,
|
||||
.Block => return @fieldParentPtr(Block, "base", scope),
|
||||
.Condition => {
|
||||
const cond = @fieldParentPtr(Condition, "base", scope);
|
||||
// comma operator used
|
||||
return try Block.init(c, scope, true);
|
||||
},
|
||||
else => scope = inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -751,7 +766,6 @@ fn transBinaryOperator(
|
|||
.Or,
|
||||
.LAnd,
|
||||
.LOr,
|
||||
.Comma,
|
||||
=> return revertAndWarn(
|
||||
rp,
|
||||
error.UnsupportedTranslation,
|
||||
|
@ -759,6 +773,23 @@ fn transBinaryOperator(
|
|||
"TODO: handle more C binary operators: {}",
|
||||
.{op},
|
||||
),
|
||||
.Comma => {
|
||||
const block_scope = try scope.findBlockScope(rp.c);
|
||||
|
||||
const lhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getLHS(stmt), .unused, .r_value);
|
||||
try block_scope.block_node.statements.push(lhs);
|
||||
|
||||
const rhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
|
||||
if (block_scope.base.parent == scope) {
|
||||
const break_node = try transCreateNodeBreak(rp.c, block_scope.label);
|
||||
_ = try appendToken(rp.c, .Semicolon, ";");
|
||||
try block_scope.block_node.statements.push(&break_node.base);
|
||||
block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
|
||||
return maybeSuppressResult(rp, scope, result_used, &block_scope.block_node.base);
|
||||
} else {
|
||||
return maybeSuppressResult(rp, scope, result_used, rhs);
|
||||
}
|
||||
},
|
||||
.MulAssign,
|
||||
.DivAssign,
|
||||
.RemAssign,
|
||||
|
@ -790,11 +821,10 @@ fn transCompoundStmtInline(
|
|||
}
|
||||
|
||||
fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node {
|
||||
const block_node = try transCreateNodeBlock(rp.c, null);
|
||||
const block_scope = try Scope.Block.init(rp.c, scope, block_node);
|
||||
try transCompoundStmtInline(rp, &block_scope.base, stmt, block_node);
|
||||
block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
|
||||
return &block_node.base;
|
||||
const block_scope = try Scope.Block.init(rp.c, scope, false);
|
||||
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;
|
||||
}
|
||||
|
||||
fn transCStyleCastExprClass(
|
||||
|
@ -818,7 +848,7 @@ fn transCStyleCastExprClass(
|
|||
|
||||
fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt) TransError!*ast.Node {
|
||||
const c = rp.c;
|
||||
const block_scope = scope.findBlockScope();
|
||||
const block_scope = try scope.findBlockScope(c);
|
||||
|
||||
var it = ZigClangDeclStmt_decl_begin(stmt);
|
||||
const end_it = ZigClangDeclStmt_decl_end(stmt);
|
||||
|
@ -927,7 +957,7 @@ fn transImplicitCastExpr(
|
|||
return transExpr(rp, scope, sub_expr, .used, .r_value);
|
||||
},
|
||||
.NullToPointer => {
|
||||
return transCreateNodeNullLiteral(rp.c);
|
||||
return try transCreateNodeNullLiteral(rp.c);
|
||||
},
|
||||
else => |kind| return revertAndWarn(
|
||||
rp,
|
||||
|
@ -1185,7 +1215,7 @@ fn transImplicitValueInitExpr(
|
|||
.Builtin => blk: {
|
||||
const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
|
||||
switch (ZigClangBuiltinType_getKind(builtin_ty)) {
|
||||
.Bool => return transCreateNodeBoolLiteral(rp.c, false),
|
||||
.Bool => return try transCreateNodeBoolLiteral(rp.c, false),
|
||||
.Char_U,
|
||||
.UChar,
|
||||
.Char_S,
|
||||
|
@ -2046,6 +2076,21 @@ fn transCreateNodeBlock(c: *Context, label: ?[]const u8) !*ast.Node.Block {
|
|||
return block_node;
|
||||
}
|
||||
|
||||
fn transCreateNodeBreak(c: *Context, label: ?[]const u8) !*ast.Node.ControlFlowExpression {
|
||||
const ltoken = try appendToken(c, .Keyword_break, "break");
|
||||
const label_node = if (label) |l| blk: {
|
||||
_ = try appendToken(c, .Colon, ":");
|
||||
break :blk try transCreateNodeIdentifier(c, l);
|
||||
} else null;
|
||||
const node = try c.a().create(ast.Node.ControlFlowExpression);
|
||||
node.* = ast.Node.ControlFlowExpression{
|
||||
.ltoken = ltoken,
|
||||
.kind = .{ .Break = label_node },
|
||||
.rhs = null,
|
||||
};
|
||||
return node;
|
||||
}
|
||||
|
||||
const RestorePoint = struct {
|
||||
c: *Context,
|
||||
token_index: ast.TokenIndex,
|
||||
|
|
|
@ -699,6 +699,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\}
|
||||
});
|
||||
|
||||
cases.add_2("comma operator",
|
||||
\\int foo(char c) {
|
||||
\\ 2, 4;
|
||||
\\ return 2, 4, 6;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo(c: u8) c_int {
|
||||
\\ _ = 2;
|
||||
\\ _ = 4;
|
||||
\\ _ = 2;
|
||||
\\ _ = 4;
|
||||
\\ return 6;
|
||||
\\}
|
||||
});
|
||||
|
||||
/////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
|
||||
|
||||
if (builtin.os != builtin.Os.windows) {
|
||||
|
|
Loading…
Reference in New Issue