| ... | @@ -107,6 +107,7 @@ const Scope = struct { | ... | @@ -107,6 +107,7 @@ const Scope = struct { |
| 107 | // do while, we want to put `if (cond) break;` at the end. | 107 | // do while, we want to put `if (cond) break;` at the end. |
| 108 | const alloc_len = self.statements.items.len + @boolToInt(self.base.parent.?.id == .Loop); | 108 | const alloc_len = self.statements.items.len + @boolToInt(self.base.parent.?.id == .Loop); |
| 109 | const stmts = try c.arena.alloc(Node, alloc_len); | 109 | const stmts = try c.arena.alloc(Node, alloc_len); |
| | 110 | stmts.len -= 1; |
| 110 | mem.copy(Node, stmts, self.statements.items); | 111 | mem.copy(Node, stmts, self.statements.items); |
| 111 | return Node.block.create(c.arena, .{ | 112 | return Node.block.create(c.arena, .{ |
| 112 | .lable = self.label, | 113 | .lable = self.label, |
| ... | @@ -1748,7 +1749,7 @@ fn transCCast( | ... | @@ -1748,7 +1749,7 @@ fn transCCast( |
| 1748 | if (dst_type.eq(src_type)) return expr; | 1749 | if (dst_type.eq(src_type)) return expr; |
| 1749 | if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type)) | 1750 | if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type)) |
| 1750 | return transCPtrCast(c, loc, dst_type, src_type, expr); | 1751 | return transCPtrCast(c, loc, dst_type, src_type, expr); |
| 1751 | | 1752 | |
| 1752 | const dst_node = try transQualType(c, dst_type, loc); | 1753 | const dst_node = try transQualType(c, dst_type, loc); |
| 1753 | if (cIsInteger(dst_type) and (cIsInteger(src_type) or cIsEnum(src_type))) { | 1754 | if (cIsInteger(dst_type) and (cIsInteger(src_type) or cIsEnum(src_type))) { |
| 1754 | // 1. If src_type is an enum, determine the underlying signed int type | 1755 | // 1. If src_type is an enum, determine the underlying signed int type |
| ... | @@ -1931,7 +1932,7 @@ fn transInitListExprArray( | ... | @@ -1931,7 +1932,7 @@ fn transInitListExprArray( |
| 1931 | if (all_count == 0) { | 1932 | if (all_count == 0) { |
| 1932 | return Node.empty_array.create(c.arena, try transQualType(c, child_qt, source_loc)); | 1933 | return Node.empty_array.create(c.arena, try transQualType(c, child_qt, source_loc)); |
| 1933 | } | 1934 | } |
| 1934 | | 1935 | |
| 1935 | const ty_node = try transType(ty); | 1936 | const ty_node = try transType(ty); |
| 1936 | const init_node = if (init_count != 0) blk: { | 1937 | const init_node = if (init_count != 0) blk: { |
| 1937 | const init_list = try c.arena.alloc(Node, init_count); | 1938 | const init_list = try c.arena.alloc(Node, init_count); |
| ... | @@ -2058,14 +2059,12 @@ fn transImplicitValueInitExpr( | ... | @@ -2058,14 +2059,12 @@ fn transImplicitValueInitExpr( |
| 2058 | } | 2059 | } |
| 2059 | | 2060 | |
| 2060 | fn transIfStmt( | 2061 | fn transIfStmt( |
| 2061 | rp: RestorePoint, | 2062 | c: *Context, |
| 2062 | scope: *Scope, | 2063 | scope: *Scope, |
| 2063 | stmt: *const clang.IfStmt, | 2064 | stmt: *const clang.IfStmt, |
| 2064 | ) TransError!*ast.Node { | 2065 | ) TransError!Node { |
| 2065 | // if (c) t | 2066 | // if (c) t |
| 2066 | // if (c) t else e | 2067 | // if (c) t else e |
| 2067 | const if_node = try transCreateNodeIf(rp.c); | | |
| 2068 | | | |
| 2069 | var cond_scope = Scope.Condition{ | 2068 | var cond_scope = Scope.Condition{ |
| 2070 | .base = .{ | 2069 | .base = .{ |
| 2071 | .parent = scope, | 2070 | .parent = scope, |
| ... | @@ -2074,26 +2073,21 @@ fn transIfStmt( | ... | @@ -2074,26 +2073,21 @@ fn transIfStmt( |
| 2074 | }; | 2073 | }; |
| 2075 | defer cond_scope.deinit(); | 2074 | defer cond_scope.deinit(); |
| 2076 | const cond_expr = @ptrCast(*const clang.Expr, stmt.getCond()); | 2075 | const cond_expr = @ptrCast(*const clang.Expr, stmt.getCond()); |
| 2077 | if_node.condition = try transBoolExpr(rp, &cond_scope.base, cond_expr, .used, .r_value, false); | 2076 | const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used, .r_value); |
| 2078 | _ = try appendToken(rp.c, .RParen, ")"); | | |
| 2079 | | | |
| 2080 | if_node.body = try transStmt(rp, scope, stmt.getThen(), .unused, .r_value); | | |
| 2081 | | 2077 | |
| 2082 | if (stmt.getElse()) |expr| { | 2078 | const then_body = try transStmt(c, scope, stmt.getThen(), .unused, .r_value); |
| 2083 | if_node.@"else" = try transCreateNodeElse(rp.c); | 2079 | const else_body = if (stmt.getElse()) |expr| |
| 2084 | if_node.@"else".?.body = try transStmt(rp, scope, expr, .unused, .r_value); | 2080 | try transStmt(c, scope, expr, .unused, .r_value) |
| 2085 | } | 2081 | else |
| 2086 | _ = try appendToken(rp.c, .Semicolon, ";"); | 2082 | null; |
| 2087 | return &if_node.base; | 2083 | return Node.@"if".create(c.arena, .{ .cond = cond, .then = then_body, .@"else" = else_body }); |
| 2088 | } | 2084 | } |
| 2089 | | 2085 | |
| 2090 | fn transWhileLoop( | 2086 | fn transWhileLoop( |
| 2091 | rp: RestorePoint, | 2087 | c: *Context, |
| 2092 | scope: *Scope, | 2088 | scope: *Scope, |
| 2093 | stmt: *const clang.WhileStmt, | 2089 | stmt: *const clang.WhileStmt, |
| 2094 | ) TransError!*ast.Node { | 2090 | ) TransError!Node { |
| 2095 | const while_node = try transCreateNodeWhile(rp.c); | | |
| 2096 | | | |
| 2097 | var cond_scope = Scope.Condition{ | 2091 | var cond_scope = Scope.Condition{ |
| 2098 | .base = .{ | 2092 | .base = .{ |
| 2099 | .parent = scope, | 2093 | .parent = scope, |
| ... | @@ -2102,35 +2096,28 @@ fn transWhileLoop( | ... | @@ -2102,35 +2096,28 @@ fn transWhileLoop( |
| 2102 | }; | 2096 | }; |
| 2103 | defer cond_scope.deinit(); | 2097 | defer cond_scope.deinit(); |
| 2104 | const cond_expr = @ptrCast(*const clang.Expr, stmt.getCond()); | 2098 | const cond_expr = @ptrCast(*const clang.Expr, stmt.getCond()); |
| 2105 | while_node.condition = try transBoolExpr(rp, &cond_scope.base, cond_expr, .used, .r_value, false); | 2099 | const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used, .r_value); |
| 2106 | _ = try appendToken(rp.c, .RParen, ")"); | | |
| 2107 | | 2100 | |
| 2108 | var loop_scope = Scope{ | 2101 | var loop_scope = Scope{ |
| 2109 | .parent = scope, | 2102 | .parent = scope, |
| 2110 | .id = .Loop, | 2103 | .id = .Loop, |
| 2111 | }; | 2104 | }; |
| 2112 | while_node.body = try transStmt(rp, &loop_scope, stmt.getBody(), .unused, .r_value); | 2105 | const body = try transStmt(c, &loop_scope, stmt.getBody(), .unused, .r_value); |
| 2113 | _ = try appendToken(rp.c, .Semicolon, ";"); | 2106 | return Node.@"while".create(c.arena, .{ .cond = cond, .body = body, .cont_expr = null }); |
| 2114 | return &while_node.base; | | |
| 2115 | } | 2107 | } |
| 2116 | | 2108 | |
| 2117 | fn transDoWhileLoop( | 2109 | fn transDoWhileLoop( |
| 2118 | rp: RestorePoint, | 2110 | c: *Context, |
| 2119 | scope: *Scope, | 2111 | scope: *Scope, |
| 2120 | stmt: *const clang.DoStmt, | 2112 | stmt: *const clang.DoStmt, |
| 2121 | ) TransError!*ast.Node { | 2113 | ) TransError!Node { |
| 2122 | const while_node = try transCreateNodeWhile(rp.c); | | |
| 2123 | | | |
| 2124 | while_node.condition = try transCreateNodeBoolLiteral(rp.c, true); | | |
| 2125 | _ = try appendToken(rp.c, .RParen, ")"); | | |
| 2126 | var new = false; | | |
| 2127 | var loop_scope = Scope{ | 2114 | var loop_scope = Scope{ |
| 2128 | .parent = scope, | 2115 | .parent = scope, |
| 2129 | .id = .Loop, | 2116 | .id = .Loop, |
| 2130 | }; | 2117 | }; |
| 2131 | | 2118 | |
| 2132 | // if (!cond) break; | 2119 | // if (!cond) break; |
| 2133 | const if_node = try transCreateNodeIf(rp.c); | 2120 | const if_node = try transCreateNodeIf(c); |
| 2134 | var cond_scope = Scope.Condition{ | 2121 | var cond_scope = Scope.Condition{ |
| 2135 | .base = .{ | 2122 | .base = .{ |
| 2136 | .parent = scope, | 2123 | .parent = scope, |
| ... | @@ -2138,12 +2125,8 @@ fn transDoWhileLoop( | ... | @@ -2138,12 +2125,8 @@ fn transDoWhileLoop( |
| 2138 | }, | 2125 | }, |
| 2139 | }; | 2126 | }; |
| 2140 | defer cond_scope.deinit(); | 2127 | defer cond_scope.deinit(); |
| 2141 | const prefix_op = try transCreateNodeSimplePrefixOp(rp.c, .BoolNot, .Bang, "!"); | 2128 | const cond = try transBoolExpr(c, &cond_scope.base, @ptrCast(*const clang.Expr, stmt.getCond()), .used, .r_value); |
| 2142 | prefix_op.rhs = try transBoolExpr(rp, &cond_scope.base, @ptrCast(*const clang.Expr, stmt.getCond()), .used, .r_value, true); | 2129 | const if_not_break = try Node.if_not_break.create(c.arena, cond); |
| 2143 | _ = try appendToken(rp.c, .RParen, ")"); | | |
| 2144 | if_node.condition = &prefix_op.base; | | |
| 2145 | if_node.body = &(try transCreateNodeBreak(rp.c, null, null)).base; | | |
| 2146 | _ = try appendToken(rp.c, .Semicolon, ";"); | | |
| 2147 | | 2130 | |
| 2148 | const body_node = if (stmt.getBody().getStmtClass() == .CompoundStmtClass) blk: { | 2131 | const body_node = if (stmt.getBody().getStmtClass() == .CompoundStmtClass) blk: { |
| 2149 | // there's already a block in C, so we'll append our condition to it. | 2132 | // there's already a block in C, so we'll append our condition to it. |
| ... | @@ -2156,8 +2139,12 @@ fn transDoWhileLoop( | ... | @@ -2156,8 +2139,12 @@ fn transDoWhileLoop( |
| 2156 | // zig: b; | 2139 | // zig: b; |
| 2157 | // zig: if (!cond) break; | 2140 | // zig: if (!cond) break; |
| 2158 | // zig: } | 2141 | // zig: } |
| 2159 | const node = try transStmt(rp, &loop_scope, stmt.getBody(), .unused, .r_value); | 2142 | const node = try transStmt(c, &loop_scope, stmt.getBody(), .unused, .r_value); |
| 2160 | break :blk node.castTag(.Block).?; | 2143 | const block = node.castTag(.block); |
| | 2144 | block.data.stmts.len += 1; // This is safe since we reserve one extra space in Scope.Block.complete. |
| | 2145 | block.data.stmts[block.data.stmts.len - 1] = if_not_break; |
| | 2146 | break :blk node; |
| | 2147 | |
| 2161 | } else blk: { | 2148 | } else blk: { |
| 2162 | // the C statement is without a block, so we need to create a block to contain it. | 2149 | // the C statement is without a block, so we need to create a block to contain it. |
| 2163 | // c: do | 2150 | // c: do |
| ... | @@ -2167,27 +2154,19 @@ fn transDoWhileLoop( | ... | @@ -2167,27 +2154,19 @@ fn transDoWhileLoop( |
| 2167 | // zig: a; | 2154 | // zig: a; |
| 2168 | // zig: if (!cond) break; | 2155 | // zig: if (!cond) break; |
| 2169 | // zig: } | 2156 | // zig: } |
| 2170 | new = true; | 2157 | const statements = try c.arena.create(Node, 2); |
| 2171 | const block = try rp.c.createBlock(2); | 2158 | statements[0] = try transStmt(c, &loop_scope, stmt.getBody(), .unused, .r_value); |
| 2172 | block.statements_len = 1; // over-allocated so we can add another below | 2159 | statements[1] = if_not_break; |
| 2173 | block.statements()[0] = try transStmt(rp, &loop_scope, stmt.getBody(), .unused, .r_value); | 2160 | break :blk try Node.block.create(c.arena, .{ .label = null, .stmts = statements }); |
| 2174 | break :blk block; | | |
| 2175 | }; | 2161 | }; |
| 2176 | | 2162 | return Node.while_true.create(c.arena, body_node); |
| 2177 | // In both cases above, we reserved 1 extra statement. | | |
| 2178 | body_node.statements_len += 1; | | |
| 2179 | body_node.statements()[body_node.statements_len - 1] = &if_node.base; | | |
| 2180 | if (new) | | |
| 2181 | body_node.rbrace = try appendToken(rp.c, .RBrace, "}"); | | |
| 2182 | while_node.body = &body_node.base; | | |
| 2183 | return &while_node.base; | | |
| 2184 | } | 2163 | } |
| 2185 | | 2164 | |
| 2186 | fn transForLoop( | 2165 | fn transForLoop( |
| 2187 | rp: RestorePoint, | 2166 | c: *Context, |
| 2188 | scope: *Scope, | 2167 | scope: *Scope, |
| 2189 | stmt: *const clang.ForStmt, | 2168 | stmt: *const clang.ForStmt, |
| 2190 | ) TransError!*ast.Node { | 2169 | ) TransError!Node { |
| 2191 | var loop_scope = Scope{ | 2170 | var loop_scope = Scope{ |
| 2192 | .parent = scope, | 2171 | .parent = scope, |
| 2193 | .id = .Loop, | 2172 | .id = .Loop, |
| ... | @@ -2197,9 +2176,9 @@ fn transForLoop( | ... | @@ -2197,9 +2176,9 @@ fn transForLoop( |
| 2197 | defer if (block_scope) |*bs| bs.deinit(); | 2176 | defer if (block_scope) |*bs| bs.deinit(); |
| 2198 | | 2177 | |
| 2199 | if (stmt.getInit()) |init| { | 2178 | if (stmt.getInit()) |init| { |
| 2200 | block_scope = try Scope.Block.init(rp.c, scope, false); | 2179 | block_scope = try Scope.Block.init(c, scope, false); |
| 2201 | loop_scope.parent = &block_scope.?.base; | 2180 | loop_scope.parent = &block_scope.?.base; |
| 2202 | const init_node = try transStmt(rp, &block_scope.?.base, init, .unused, .r_value); | 2181 | const init_node = try transStmt(c, &block_scope.?.base, init, .unused, .r_value); |
| 2203 | try block_scope.?.statements.append(init_node); | 2182 | try block_scope.?.statements.append(init_node); |
| 2204 | } | 2183 | } |
| 2205 | var cond_scope = Scope.Condition{ | 2184 | var cond_scope = Scope.Condition{ |
| ... | @@ -2210,27 +2189,23 @@ fn transForLoop( | ... | @@ -2210,27 +2189,23 @@ fn transForLoop( |
| 2210 | }; | 2189 | }; |
| 2211 | defer cond_scope.deinit(); | 2190 | defer cond_scope.deinit(); |
| 2212 | | 2191 | |
| 2213 | const while_node = try transCreateNodeWhile(rp.c); | 2192 | const cond = if (stmt.getCond()) |cond| |
| 2214 | while_node.condition = if (stmt.getCond()) |cond| | 2193 | try transBoolExpr(c, &cond_scope.base, cond, .used, .r_value) |
| 2215 | try transBoolExpr(rp, &cond_scope.base, cond, .used, .r_value, false) | | |
| 2216 | else | 2194 | else |
| 2217 | try transCreateNodeBoolLiteral(rp.c, true); | 2195 | Node.true_literal.init(); |
| 2218 | _ = try appendToken(rp.c, .RParen, ")"); | | |
| 2219 | | 2196 | |
| 2220 | if (stmt.getInc()) |incr| { | 2197 | const cont_expr = if (stmt.getInc()) |incr| |
| 2221 | _ = try appendToken(rp.c, .Colon, ":"); | 2198 | try transExpr(c, &cond_scope.base, incr, .unused, .r_value) |
| 2222 | _ = try appendToken(rp.c, .LParen, "("); | 2199 | else |
| 2223 | while_node.continue_expr = try transExpr(rp, &cond_scope.base, incr, .unused, .r_value); | 2200 | null; |
| 2224 | _ = try appendToken(rp.c, .RParen, ")"); | | |
| 2225 | } | | |
| 2226 | | 2201 | |
| 2227 | while_node.body = try transStmt(rp, &loop_scope, stmt.getBody(), .unused, .r_value); | 2202 | const body = try transStmt(c, &loop_scope, stmt.getBody(), .unused, .r_value); |
| | 2203 | const while_node = try Node.@"while".create(c.arena, .{ .cond = cond, .body = body, .cont_expr = cont_expr }); |
| 2228 | if (block_scope) |*bs| { | 2204 | if (block_scope) |*bs| { |
| 2229 | try bs.statements.append(&while_node.base); | 2205 | try bs.statements.append(while_node); |
| 2230 | return try bs.complete(rp.c); | 2206 | return try bs.complete(c); |
| 2231 | } else { | 2207 | } else { |
| 2232 | _ = try appendToken(rp.c, .Semicolon, ";"); | 2208 | return while_node; |
| 2233 | return &while_node.base; | | |
| 2234 | } | 2209 | } |
| 2235 | } | 2210 | } |
| 2236 | | 2211 | |