| ... | ... | @@ -2204,43 +2204,10 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt |
| 2204 | 2204 | return ErrorNone; |
| 2205 | 2205 | } |
| 2206 | 2206 | |
| 2207 | | static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) { |
| 2208 | | TransScopeWhile *while_scope = trans_scope_while_create(c, scope); |
| 2209 | | |
| 2210 | | while_scope->node->data.while_expr.condition = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); |
| 2211 | | if (while_scope->node->data.while_expr.condition == nullptr) |
| 2212 | | return nullptr; |
| 2213 | | |
| 2214 | | TransScope *body_scope = trans_stmt(c, &while_scope->base, stmt->getBody(), |
| 2215 | | &while_scope->node->data.while_expr.body); |
| 2216 | | if (body_scope == nullptr) |
| 2217 | | return nullptr; |
| 2218 | | |
| 2219 | | return while_scope->node; |
| 2220 | | } |
| 2221 | | |
| 2222 | | static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) { |
| 2223 | | // if (c) t |
| 2224 | | // if (c) t else e |
| 2225 | | AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 2226 | | |
| 2227 | | TransScope *then_scope = trans_stmt(c, scope, stmt->getThen(), &if_node->data.if_bool_expr.then_block); |
| 2228 | | if (then_scope == nullptr) |
| 2229 | | return nullptr; |
| 2230 | | |
| 2231 | | if (stmt->getElse() != nullptr) { |
| 2232 | | TransScope *else_scope = trans_stmt(c, scope, stmt->getElse(), &if_node->data.if_bool_expr.else_node); |
| 2233 | | if (else_scope == nullptr) |
| 2234 | | return nullptr; |
| 2235 | | } |
| 2236 | | |
| 2237 | | AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); |
| 2238 | | if (condition_node == nullptr) |
| 2239 | | return nullptr; |
| 2240 | | |
| 2241 | | switch (condition_node->type) { |
| 2207 | static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr) { |
| 2208 | switch (expr->type) { |
| 2242 | 2209 | case NodeTypeBinOpExpr: |
| 2243 | | switch (condition_node->data.bin_op_expr.bin_op) { |
| 2210 | switch (expr->data.bin_op_expr.bin_op) { |
| 2244 | 2211 | case BinOpTypeBoolOr: |
| 2245 | 2212 | case BinOpTypeBoolAnd: |
| 2246 | 2213 | case BinOpTypeCmpEq: |
| ... | ... | @@ -2249,43 +2216,42 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * |
| 2249 | 2216 | case BinOpTypeCmpGreaterThan: |
| 2250 | 2217 | case BinOpTypeCmpLessOrEq: |
| 2251 | 2218 | case BinOpTypeCmpGreaterOrEq: |
| 2252 | | if_node->data.if_bool_expr.condition = condition_node; |
| 2253 | | return if_node; |
| 2219 | return expr; |
| 2254 | 2220 | default: |
| 2255 | 2221 | goto convert_to_bitcast; |
| 2256 | 2222 | } |
| 2257 | 2223 | |
| 2258 | 2224 | case NodeTypePrefixOpExpr: |
| 2259 | | switch (condition_node->data.prefix_op_expr.prefix_op) { |
| 2225 | switch (expr->data.prefix_op_expr.prefix_op) { |
| 2260 | 2226 | case PrefixOpBoolNot: |
| 2261 | | if_node->data.if_bool_expr.condition = condition_node; |
| 2262 | | return if_node; |
| 2227 | return expr; |
| 2263 | 2228 | default: |
| 2264 | 2229 | goto convert_to_bitcast; |
| 2265 | 2230 | } |
| 2266 | 2231 | |
| 2267 | 2232 | case NodeTypeBoolLiteral: |
| 2268 | | if_node->data.if_bool_expr.condition = condition_node; |
| 2269 | | return if_node; |
| 2233 | return expr; |
| 2270 | 2234 | |
| 2271 | 2235 | default: { |
| 2272 | | // In Zig, float, int and pointer does not work in if statements. |
| 2273 | | // To make it work, we bitcast any value we get to an int of the right size |
| 2274 | | // and comp it to 0 |
| 2275 | | // TODO: This doesn't work for pointers, as they become nullable on |
| 2276 | | // translate |
| 2277 | | // c: if (cond) { } |
| 2278 | | // zig: { |
| 2279 | | // zig: const _tmp = cond; |
| 2280 | | // zig: if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { } |
| 2281 | | // zig: } |
| 2282 | | convert_to_bitcast: |
| 2236 | // In Zig, float, int and pointer does not implicitly cast to bool. |
| 2237 | // To make it work, we bitcast any value we get to an int of the right size |
| 2238 | // and comp it to 0 |
| 2239 | // TODO: This doesn't work for pointers, as they become nullable on |
| 2240 | // translate |
| 2241 | // c: expr |
| 2242 | // zig: __to_bool_expr: { |
| 2243 | // zig: const _tmp = cond; |
| 2244 | // zig: break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0; |
| 2245 | // zig: } |
| 2246 | convert_to_bitcast: |
| 2283 | 2247 | TransScopeBlock *child_scope = trans_scope_block_create(c, scope); |
| 2248 | Buf *label_name = buf_create_from_str("__to_bool_expr"); |
| 2249 | child_scope->node->data.block.name = label_name; |
| 2284 | 2250 | |
| 2285 | 2251 | // const _tmp = cond; |
| 2286 | 2252 | // TODO: avoid name collisions with generated variable names |
| 2287 | | Buf* tmp_var_name = buf_create_from_str("_tmp"); |
| 2288 | | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, condition_node); |
| 2253 | Buf *tmp_var_name = buf_create_from_str("_tmp"); |
| 2254 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, expr); |
| 2289 | 2255 | child_scope->node->data.block.statements.append(tmp_var_decl); |
| 2290 | 2256 | |
| 2291 | 2257 | // @sizeOf(@typeOf(_tmp)) * 8 |
| ... | ... | @@ -2294,8 +2260,8 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * |
| 2294 | 2260 | AstNode *sizeof_tmp = trans_create_node_builtin_fn_call_str(c, "sizeOf"); |
| 2295 | 2261 | sizeof_tmp->data.fn_call_expr.params.append(typeof_tmp); |
| 2296 | 2262 | AstNode *sizeof_tmp_in_bits = trans_create_node_bin_op( |
| 2297 | | c, sizeof_tmp, BinOpTypeMult, |
| 2298 | | trans_create_node_unsigned_negative(c, 8, false)); |
| 2263 | c, sizeof_tmp, BinOpTypeMult, |
| 2264 | trans_create_node_unsigned_negative(c, 8, false)); |
| 2299 | 2265 | |
| 2300 | 2266 | // @IntType(false, @sizeOf(@typeOf(_tmp)) * 8) |
| 2301 | 2267 | AstNode *int_type = trans_create_node_builtin_fn_call_str(c, "IntType"); |
| ... | ... | @@ -2307,16 +2273,53 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * |
| 2307 | 2273 | bit_cast->data.fn_call_expr.params.append(int_type); |
| 2308 | 2274 | bit_cast->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name)); |
| 2309 | 2275 | |
| 2310 | | // if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { } |
| 2276 | // break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0 |
| 2311 | 2277 | AstNode *not_eql_zero = trans_create_node_bin_op(c, bit_cast, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false)); |
| 2312 | | if_node->data.if_bool_expr.condition = not_eql_zero; |
| 2313 | | child_scope->node->data.block.statements.append(if_node); |
| 2278 | child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, not_eql_zero)); |
| 2314 | 2279 | |
| 2315 | 2280 | return child_scope->node; |
| 2316 | 2281 | } |
| 2317 | 2282 | } |
| 2318 | 2283 | } |
| 2319 | 2284 | |
| 2285 | static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) { |
| 2286 | TransScopeWhile *while_scope = trans_scope_while_create(c, scope); |
| 2287 | |
| 2288 | while_scope->node->data.while_expr.condition = trans_to_bool_expr(c, scope, trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue)); |
| 2289 | if (while_scope->node->data.while_expr.condition == nullptr) |
| 2290 | return nullptr; |
| 2291 | |
| 2292 | TransScope *body_scope = trans_stmt(c, &while_scope->base, stmt->getBody(), |
| 2293 | &while_scope->node->data.while_expr.body); |
| 2294 | if (body_scope == nullptr) |
| 2295 | return nullptr; |
| 2296 | |
| 2297 | return while_scope->node; |
| 2298 | } |
| 2299 | |
| 2300 | static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) { |
| 2301 | // if (c) t |
| 2302 | // if (c) t else e |
| 2303 | AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 2304 | |
| 2305 | TransScope *then_scope = trans_stmt(c, scope, stmt->getThen(), &if_node->data.if_bool_expr.then_block); |
| 2306 | if (then_scope == nullptr) |
| 2307 | return nullptr; |
| 2308 | |
| 2309 | if (stmt->getElse() != nullptr) { |
| 2310 | TransScope *else_scope = trans_stmt(c, scope, stmt->getElse(), &if_node->data.if_bool_expr.else_node); |
| 2311 | if (else_scope == nullptr) |
| 2312 | return nullptr; |
| 2313 | } |
| 2314 | |
| 2315 | AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); |
| 2316 | if (condition_node == nullptr) |
| 2317 | return nullptr; |
| 2318 | |
| 2319 | if_node->data.if_bool_expr.condition = trans_to_bool_expr(c, scope, condition_node); |
| 2320 | return if_node; |
| 2321 | } |
| 2322 | |
| 2320 | 2323 | static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) { |
| 2321 | 2324 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); |
| 2322 | 2325 | |
| ... | ... | @@ -2503,6 +2506,8 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt |
| 2503 | 2506 | &while_scope->node->data.while_expr.condition); |
| 2504 | 2507 | if (end_cond_scope == nullptr) |
| 2505 | 2508 | return nullptr; |
| 2509 | |
| 2510 | while_scope->node->data.while_expr.condition = trans_to_bool_expr(c, cond_scope, while_scope->node->data.while_expr.condition); |
| 2506 | 2511 | } |
| 2507 | 2512 | |
| 2508 | 2513 | const Stmt *inc_stmt = stmt->getInc(); |