| ... | @@ -47,7 +47,7 @@ const Scope = struct { | ... | @@ -47,7 +47,7 @@ const Scope = struct { |
| 47 | Switch, | 47 | Switch, |
| 48 | Block, | 48 | Block, |
| 49 | Root, | 49 | Root, |
| 50 | While, | 50 | Condition, |
| 51 | FnDef, | 51 | FnDef, |
| 52 | Ref, | 52 | Ref, |
| 53 | }; | 53 | }; |
| ... | @@ -65,9 +65,13 @@ const Scope = struct { | ... | @@ -65,9 +65,13 @@ const Scope = struct { |
| 65 | base: Scope, | 65 | base: Scope, |
| 66 | block_node: *ast.Node.Block, | 66 | block_node: *ast.Node.Block, |
| 67 | variables: AliasList, | 67 | variables: AliasList, |
| | 68 | label: ?[]const u8, |
| 68 | | 69 | |
| 69 | /// Don't forget to set rbrace token later | 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 | const block = try c.a().create(Block); | 75 | const block = try c.a().create(Block); |
| 72 | block.* = .{ | 76 | block.* = .{ |
| 73 | .base = .{ | 77 | .base = .{ |
| ... | @@ -76,6 +80,7 @@ const Scope = struct { | ... | @@ -76,6 +80,7 @@ const Scope = struct { |
| 76 | }, | 80 | }, |
| 77 | .block_node = block_node, | 81 | .block_node = block_node, |
| 78 | .variables = AliasList.init(c.a()), | 82 | .variables = AliasList.init(c.a()), |
| | 83 | .label = label, |
| 79 | }; | 84 | }; |
| 80 | return block; | 85 | return block; |
| 81 | } | 86 | } |
| ... | @@ -120,7 +125,8 @@ const Scope = struct { | ... | @@ -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 | base: Scope, | 130 | base: Scope, |
| 125 | }; | 131 | }; |
| 126 | | 132 | |
| ... | @@ -157,10 +163,19 @@ const Scope = struct { | ... | @@ -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 | var scope = inner; | 167 | var scope = inner; |
| 162 | while (true) : (scope = scope.parent orelse unreachable) { | 168 | while (true) { |
| 163 | if (scope.id == .Block) return @fieldParentPtr(Scope.Block, "base", scope); | 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,7 +766,6 @@ fn transBinaryOperator( |
| 751 | .Or, | 766 | .Or, |
| 752 | .LAnd, | 767 | .LAnd, |
| 753 | .LOr, | 768 | .LOr, |
| 754 | .Comma, | | |
| 755 | => return revertAndWarn( | 769 | => return revertAndWarn( |
| 756 | rp, | 770 | rp, |
| 757 | error.UnsupportedTranslation, | 771 | error.UnsupportedTranslation, |
| ... | @@ -759,6 +773,23 @@ fn transBinaryOperator( | ... | @@ -759,6 +773,23 @@ fn transBinaryOperator( |
| 759 | "TODO: handle more C binary operators: {}", | 773 | "TODO: handle more C binary operators: {}", |
| 760 | .{op}, | 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 | .MulAssign, | 793 | .MulAssign, |
| 763 | .DivAssign, | 794 | .DivAssign, |
| 764 | .RemAssign, | 795 | .RemAssign, |
| ... | @@ -790,11 +821,10 @@ fn transCompoundStmtInline( | ... | @@ -790,11 +821,10 @@ fn transCompoundStmtInline( |
| 790 | } | 821 | } |
| 791 | | 822 | |
| 792 | fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node { | 823 | fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node { |
| 793 | const block_node = try transCreateNodeBlock(rp.c, null); | 824 | const block_scope = try Scope.Block.init(rp.c, scope, false); |
| 794 | const block_scope = try Scope.Block.init(rp.c, scope, block_node); | 825 | try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node); |
| 795 | try transCompoundStmtInline(rp, &block_scope.base, stmt, block_node); | 826 | block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}"); |
| 796 | block_node.rbrace = try appendToken(rp.c, .RBrace, "}"); | 827 | return &block_scope.block_node.base; |
| 797 | return &block_node.base; | | |
| 798 | } | 828 | } |
| 799 | | 829 | |
| 800 | fn transCStyleCastExprClass( | 830 | fn transCStyleCastExprClass( |
| ... | @@ -818,7 +848,7 @@ fn transCStyleCastExprClass( | ... | @@ -818,7 +848,7 @@ fn transCStyleCastExprClass( |
| 818 | | 848 | |
| 819 | fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt) TransError!*ast.Node { | 849 | fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt) TransError!*ast.Node { |
| 820 | const c = rp.c; | 850 | const c = rp.c; |
| 821 | const block_scope = scope.findBlockScope(); | 851 | const block_scope = try scope.findBlockScope(c); |
| 822 | | 852 | |
| 823 | var it = ZigClangDeclStmt_decl_begin(stmt); | 853 | var it = ZigClangDeclStmt_decl_begin(stmt); |
| 824 | const end_it = ZigClangDeclStmt_decl_end(stmt); | 854 | const end_it = ZigClangDeclStmt_decl_end(stmt); |
| ... | @@ -927,7 +957,7 @@ fn transImplicitCastExpr( | ... | @@ -927,7 +957,7 @@ fn transImplicitCastExpr( |
| 927 | return transExpr(rp, scope, sub_expr, .used, .r_value); | 957 | return transExpr(rp, scope, sub_expr, .used, .r_value); |
| 928 | }, | 958 | }, |
| 929 | .NullToPointer => { | 959 | .NullToPointer => { |
| 930 | return transCreateNodeNullLiteral(rp.c); | 960 | return try transCreateNodeNullLiteral(rp.c); |
| 931 | }, | 961 | }, |
| 932 | else => |kind| return revertAndWarn( | 962 | else => |kind| return revertAndWarn( |
| 933 | rp, | 963 | rp, |
| ... | @@ -1185,7 +1215,7 @@ fn transImplicitValueInitExpr( | ... | @@ -1185,7 +1215,7 @@ fn transImplicitValueInitExpr( |
| 1185 | .Builtin => blk: { | 1215 | .Builtin => blk: { |
| 1186 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty); | 1216 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty); |
| 1187 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { | 1217 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { |
| 1188 | .Bool => return transCreateNodeBoolLiteral(rp.c, false), | 1218 | .Bool => return try transCreateNodeBoolLiteral(rp.c, false), |
| 1189 | .Char_U, | 1219 | .Char_U, |
| 1190 | .UChar, | 1220 | .UChar, |
| 1191 | .Char_S, | 1221 | .Char_S, |
| ... | @@ -2046,6 +2076,21 @@ fn transCreateNodeBlock(c: *Context, label: ?[]const u8) !*ast.Node.Block { | ... | @@ -2046,6 +2076,21 @@ fn transCreateNodeBlock(c: *Context, label: ?[]const u8) !*ast.Node.Block { |
| 2046 | return block_node; | 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 | const RestorePoint = struct { | 2094 | const RestorePoint = struct { |
| 2050 | c: *Context, | 2095 | c: *Context, |
| 2051 | token_index: ast.TokenIndex, | 2096 | token_index: ast.TokenIndex, |