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