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