authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-16 15:22:37+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-16 18:19:24+02:00
logd9527edfe0f017cd397de7ed947e47600092f929
tree9afbe4c73c3eaf232acea35c0104b9258a4bdaf9
parentfe0e8c87b762aba6eb5ff1fad8ad7d37404476f1
signature Commit is signed but in an unrecognized format.

translate-c-2 comma operator


2 files changed, 75 insertions(+), 15 deletions(-)

src-self-hosted/translate_c.zig+60-15
......@@ -47,7 +47,7 @@ const Scope = struct {
4747 Switch,
4848 Block,
4949 Root,
50 While,
50 Condition,
5151 FnDef,
5252 Ref,
5353 };
......@@ -65,9 +65,13 @@ const Scope = struct {
6565 base: Scope,
6666 block_node: *ast.Node.Block,
6767 variables: AliasList,
68 label: ?[]const u8,
6869
6970 /// Don't forget to set rbrace token later
70 fn init(c: *Context, parent: *Scope, block_node: *ast.Node.Block) !*Block {
71 fn init(c: *Context, parent: *Scope, want_label: bool) !*Block {
72 // TODO removing `?[]const u8` here causes LLVM error
73 const label: ?[]const u8 = if (want_label) try std.fmt.allocPrint(c.a(), "blk_{}", .{c.getMangle()}) else null;
74 const block_node = try transCreateNodeBlock(c, label);
7175 const block = try c.a().create(Block);
7276 block.* = .{
7377 .base = .{
......@@ -76,6 +80,7 @@ const Scope = struct {
7680 },
7781 .block_node = block_node,
7882 .variables = AliasList.init(c.a()),
83 .label = label,
7984 };
8085 return block;
8186 }
......@@ -120,7 +125,8 @@ const Scope = struct {
120125 }
121126 };
122127
123 const While = struct {
128 const Condition = struct {
129 expr: *ast.Node,
124130 base: Scope,
125131 };
126132
......@@ -157,10 +163,19 @@ const Scope = struct {
157163 }
158164 };
159165
160 fn findBlockScope(inner: *Scope) *Scope.Block {
166 fn findBlockScope(inner: *Scope, c: *Context) !*Scope.Block {
161167 var scope = inner;
162 while (true) : (scope = scope.parent orelse unreachable) {
163 if (scope.id == .Block) return @fieldParentPtr(Scope.Block, "base", scope);
168 while (true) {
169 switch (scope.id) {
170 .Root => unreachable,
171 .Block => return @fieldParentPtr(Block, "base", scope),
172 .Condition => {
173 const cond = @fieldParentPtr(Condition, "base", scope);
174 // comma operator used
175 return try Block.init(c, scope, true);
176 },
177 else => scope = inner,
178 }
164179 }
165180 }
166181
......@@ -751,7 +766,6 @@ fn transBinaryOperator(
751766 .Or,
752767 .LAnd,
753768 .LOr,
754 .Comma,
755769 => return revertAndWarn(
756770 rp,
757771 error.UnsupportedTranslation,
......@@ -759,6 +773,23 @@ fn transBinaryOperator(
759773 "TODO: handle more C binary operators: {}",
760774 .{op},
761775 ),
776 .Comma => {
777 const block_scope = try scope.findBlockScope(rp.c);
778
779 const lhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getLHS(stmt), .unused, .r_value);
780 try block_scope.block_node.statements.push(lhs);
781
782 const rhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
783 if (block_scope.base.parent == scope) {
784 const break_node = try transCreateNodeBreak(rp.c, block_scope.label);
785 _ = try appendToken(rp.c, .Semicolon, ";");
786 try block_scope.block_node.statements.push(&break_node.base);
787 block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
788 return maybeSuppressResult(rp, scope, result_used, &block_scope.block_node.base);
789 } else {
790 return maybeSuppressResult(rp, scope, result_used, rhs);
791 }
792 },
762793 .MulAssign,
763794 .DivAssign,
764795 .RemAssign,
......@@ -790,11 +821,10 @@ fn transCompoundStmtInline(
790821}
791822
792823fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node {
793 const block_node = try transCreateNodeBlock(rp.c, null);
794 const block_scope = try Scope.Block.init(rp.c, scope, block_node);
795 try transCompoundStmtInline(rp, &block_scope.base, stmt, block_node);
796 block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
797 return &block_node.base;
824 const block_scope = try Scope.Block.init(rp.c, scope, false);
825 try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node);
826 block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
827 return &block_scope.block_node.base;
798828}
799829
800830fn transCStyleCastExprClass(
......@@ -818,7 +848,7 @@ fn transCStyleCastExprClass(
818848
819849fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt) TransError!*ast.Node {
820850 const c = rp.c;
821 const block_scope = scope.findBlockScope();
851 const block_scope = try scope.findBlockScope(c);
822852
823853 var it = ZigClangDeclStmt_decl_begin(stmt);
824854 const end_it = ZigClangDeclStmt_decl_end(stmt);
......@@ -927,7 +957,7 @@ fn transImplicitCastExpr(
927957 return transExpr(rp, scope, sub_expr, .used, .r_value);
928958 },
929959 .NullToPointer => {
930 return transCreateNodeNullLiteral(rp.c);
960 return try transCreateNodeNullLiteral(rp.c);
931961 },
932962 else => |kind| return revertAndWarn(
933963 rp,
......@@ -1185,7 +1215,7 @@ fn transImplicitValueInitExpr(
11851215 .Builtin => blk: {
11861216 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
11871217 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
1188 .Bool => return transCreateNodeBoolLiteral(rp.c, false),
1218 .Bool => return try transCreateNodeBoolLiteral(rp.c, false),
11891219 .Char_U,
11901220 .UChar,
11911221 .Char_S,
......@@ -2046,6 +2076,21 @@ fn transCreateNodeBlock(c: *Context, label: ?[]const u8) !*ast.Node.Block {
20462076 return block_node;
20472077}
20482078
2079fn transCreateNodeBreak(c: *Context, label: ?[]const u8) !*ast.Node.ControlFlowExpression {
2080 const ltoken = try appendToken(c, .Keyword_break, "break");
2081 const label_node = if (label) |l| blk: {
2082 _ = try appendToken(c, .Colon, ":");
2083 break :blk try transCreateNodeIdentifier(c, l);
2084 } else null;
2085 const node = try c.a().create(ast.Node.ControlFlowExpression);
2086 node.* = ast.Node.ControlFlowExpression{
2087 .ltoken = ltoken,
2088 .kind = .{ .Break = label_node },
2089 .rhs = null,
2090 };
2091 return node;
2092}
2093
20492094const RestorePoint = struct {
20502095 c: *Context,
20512096 token_index: ast.TokenIndex,
test/translate_c.zig+15
......@@ -699,6 +699,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
699699 \\}
700700 });
701701
702 cases.add_2("comma operator",
703 \\int foo(char c) {
704 \\ 2, 4;
705 \\ return 2, 4, 6;
706 \\}
707 , &[_][]const u8{
708 \\pub export fn foo(c: u8) c_int {
709 \\ _ = 2;
710 \\ _ = 4;
711 \\ _ = 2;
712 \\ _ = 4;
713 \\ return 6;
714 \\}
715 });
716
702717 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
703718
704719 if (builtin.os != builtin.Os.windows) {