| ... | ... | @@ -47,7 +47,7 @@ const Scope = struct { |
| 47 | 47 | Switch, |
| 48 | 48 | Block, |
| 49 | 49 | Root, |
| 50 | | While, |
| 50 | Condition, |
| 51 | 51 | FnDef, |
| 52 | 52 | Ref, |
| 53 | 53 | }; |
| ... | ... | @@ -65,9 +65,13 @@ const Scope = struct { |
| 65 | 65 | base: Scope, |
| 66 | 66 | block_node: *ast.Node.Block, |
| 67 | 67 | variables: AliasList, |
| 68 | label: ?[]const u8, |
| 68 | 69 | |
| 69 | 70 | /// 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); |
| 71 | 75 | const block = try c.a().create(Block); |
| 72 | 76 | block.* = .{ |
| 73 | 77 | .base = .{ |
| ... | ... | @@ -76,6 +80,7 @@ const Scope = struct { |
| 76 | 80 | }, |
| 77 | 81 | .block_node = block_node, |
| 78 | 82 | .variables = AliasList.init(c.a()), |
| 83 | .label = label, |
| 79 | 84 | }; |
| 80 | 85 | return block; |
| 81 | 86 | } |
| ... | ... | @@ -120,7 +125,8 @@ const Scope = struct { |
| 120 | 125 | } |
| 121 | 126 | }; |
| 122 | 127 | |
| 123 | | const While = struct { |
| 128 | const Condition = struct { |
| 129 | expr: *ast.Node, |
| 124 | 130 | base: Scope, |
| 125 | 131 | }; |
| 126 | 132 | |
| ... | ... | @@ -157,10 +163,19 @@ const Scope = struct { |
| 157 | 163 | } |
| 158 | 164 | }; |
| 159 | 165 | |
| 160 | | fn findBlockScope(inner: *Scope) *Scope.Block { |
| 166 | fn findBlockScope(inner: *Scope, c: *Context) !*Scope.Block { |
| 161 | 167 | 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 | } |
| 164 | 179 | } |
| 165 | 180 | } |
| 166 | 181 | |
| ... | ... | @@ -751,7 +766,6 @@ fn transBinaryOperator( |
| 751 | 766 | .Or, |
| 752 | 767 | .LAnd, |
| 753 | 768 | .LOr, |
| 754 | | .Comma, |
| 755 | 769 | => return revertAndWarn( |
| 756 | 770 | rp, |
| 757 | 771 | error.UnsupportedTranslation, |
| ... | ... | @@ -759,6 +773,23 @@ fn transBinaryOperator( |
| 759 | 773 | "TODO: handle more C binary operators: {}", |
| 760 | 774 | .{op}, |
| 761 | 775 | ), |
| 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 | }, |
| 762 | 793 | .MulAssign, |
| 763 | 794 | .DivAssign, |
| 764 | 795 | .RemAssign, |
| ... | ... | @@ -790,11 +821,10 @@ fn transCompoundStmtInline( |
| 790 | 821 | } |
| 791 | 822 | |
| 792 | 823 | fn 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; |
| 798 | 828 | } |
| 799 | 829 | |
| 800 | 830 | fn transCStyleCastExprClass( |
| ... | ... | @@ -818,7 +848,7 @@ fn transCStyleCastExprClass( |
| 818 | 848 | |
| 819 | 849 | fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt) TransError!*ast.Node { |
| 820 | 850 | const c = rp.c; |
| 821 | | const block_scope = scope.findBlockScope(); |
| 851 | const block_scope = try scope.findBlockScope(c); |
| 822 | 852 | |
| 823 | 853 | var it = ZigClangDeclStmt_decl_begin(stmt); |
| 824 | 854 | const end_it = ZigClangDeclStmt_decl_end(stmt); |
| ... | ... | @@ -927,7 +957,7 @@ fn transImplicitCastExpr( |
| 927 | 957 | return transExpr(rp, scope, sub_expr, .used, .r_value); |
| 928 | 958 | }, |
| 929 | 959 | .NullToPointer => { |
| 930 | | return transCreateNodeNullLiteral(rp.c); |
| 960 | return try transCreateNodeNullLiteral(rp.c); |
| 931 | 961 | }, |
| 932 | 962 | else => |kind| return revertAndWarn( |
| 933 | 963 | rp, |
| ... | ... | @@ -1185,7 +1215,7 @@ fn transImplicitValueInitExpr( |
| 1185 | 1215 | .Builtin => blk: { |
| 1186 | 1216 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty); |
| 1187 | 1217 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { |
| 1188 | | .Bool => return transCreateNodeBoolLiteral(rp.c, false), |
| 1218 | .Bool => return try transCreateNodeBoolLiteral(rp.c, false), |
| 1189 | 1219 | .Char_U, |
| 1190 | 1220 | .UChar, |
| 1191 | 1221 | .Char_S, |
| ... | ... | @@ -2046,6 +2076,21 @@ fn transCreateNodeBlock(c: *Context, label: ?[]const u8) !*ast.Node.Block { |
| 2046 | 2076 | return block_node; |
| 2047 | 2077 | } |
| 2048 | 2078 | |
| 2079 | fn 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 | |
| 2049 | 2094 | const RestorePoint = struct { |
| 2050 | 2095 | c: *Context, |
| 2051 | 2096 | token_index: ast.TokenIndex, |