| ... | ... | @@ -82,6 +82,7 @@ struct TransScopeSwitch { |
| 82 | 82 | AstNode *switch_node; |
| 83 | 83 | uint32_t case_index; |
| 84 | 84 | bool found_default; |
| 85 | Buf *end_label_name; |
| 85 | 86 | }; |
| 86 | 87 | |
| 87 | 88 | struct TransScopeVar { |
| ... | ... | @@ -248,6 +249,18 @@ static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_vol |
| 248 | 249 | return node; |
| 249 | 250 | } |
| 250 | 251 | |
| 252 | static AstNode *trans_create_node_goto(Context *c, Buf *label_name) { |
| 253 | AstNode *goto_node = trans_create_node(c, NodeTypeGoto); |
| 254 | goto_node->data.goto_expr.name = label_name; |
| 255 | return goto_node; |
| 256 | } |
| 257 | |
| 258 | static AstNode *trans_create_node_label(Context *c, Buf *label_name) { |
| 259 | AstNode *label_node = trans_create_node(c, NodeTypeLabel); |
| 260 | label_node->data.label.name = label_name; |
| 261 | return label_node; |
| 262 | } |
| 263 | |
| 251 | 264 | static AstNode *trans_create_node_bool(Context *c, bool value) { |
| 252 | 265 | AstNode *bool_node = trans_create_node(c, NodeTypeBoolLiteral); |
| 253 | 266 | bool_node->data.bool_literal.value = value; |
| ... | ... | @@ -2283,11 +2296,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt |
| 2283 | 2296 | } |
| 2284 | 2297 | |
| 2285 | 2298 | static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const SwitchStmt *stmt) { |
| 2286 | | TransScopeWhile *while_scope = trans_scope_while_create(c, parent_scope); |
| 2287 | | while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true); |
| 2288 | | |
| 2289 | | TransScopeBlock *block_scope = trans_scope_block_create(c, &while_scope->base); |
| 2290 | | while_scope->node->data.while_expr.body = block_scope->node; |
| 2299 | TransScopeBlock *block_scope = trans_scope_block_create(c, parent_scope); |
| 2291 | 2300 | |
| 2292 | 2301 | TransScopeSwitch *switch_scope; |
| 2293 | 2302 | |
| ... | ... | @@ -2305,6 +2314,10 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw |
| 2305 | 2314 | } |
| 2306 | 2315 | block_scope->node->data.block.statements.append(switch_scope->switch_node); |
| 2307 | 2316 | |
| 2317 | // TODO avoid name collisions |
| 2318 | Buf *end_label_name = buf_create_from_str("end"); |
| 2319 | switch_scope->end_label_name = end_label_name; |
| 2320 | |
| 2308 | 2321 | const Expr *cond_expr = stmt->getCond(); |
| 2309 | 2322 | assert(cond_expr != nullptr); |
| 2310 | 2323 | |
| ... | ... | @@ -2336,9 +2349,11 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw |
| 2336 | 2349 | } |
| 2337 | 2350 | |
| 2338 | 2351 | // This is necessary if the last switch case "falls through" the end of the switch block |
| 2339 | | block_scope->node->data.block.statements.append(trans_create_node(c, NodeTypeBreak)); |
| 2352 | block_scope->node->data.block.statements.append(trans_create_node_goto(c, end_label_name)); |
| 2340 | 2353 | |
| 2341 | | return while_scope->node; |
| 2354 | block_scope->node->data.block.statements.append(trans_create_node_label(c, end_label_name)); |
| 2355 | |
| 2356 | return block_scope->node; |
| 2342 | 2357 | } |
| 2343 | 2358 | |
| 2344 | 2359 | static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStmt *stmt, AstNode **out_node, |
| ... | ... | @@ -2365,18 +2380,13 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStm |
| 2365 | 2380 | return ErrorUnexpected; |
| 2366 | 2381 | prong_node->data.switch_prong.items.append(item_node); |
| 2367 | 2382 | |
| 2368 | | AstNode *goto_node = trans_create_node(c, NodeTypeGoto); |
| 2369 | | goto_node->data.goto_expr.name = label_name; |
| 2370 | | prong_node->data.switch_prong.expr = goto_node; |
| 2383 | prong_node->data.switch_prong.expr = trans_create_node_goto(c, label_name); |
| 2371 | 2384 | |
| 2372 | 2385 | switch_scope->switch_node->data.switch_expr.prongs.append(prong_node); |
| 2373 | 2386 | } |
| 2374 | 2387 | |
| 2375 | | AstNode *label_node = trans_create_node(c, NodeTypeLabel); |
| 2376 | | label_node->data.label.name = label_name; |
| 2377 | | |
| 2378 | 2388 | TransScopeBlock *scope_block = trans_scope_block_find(parent_scope); |
| 2379 | | scope_block->node->data.block.statements.append(label_node); |
| 2389 | scope_block->node->data.block.statements.append(trans_create_node_label(c, label_name)); |
| 2380 | 2390 | |
| 2381 | 2391 | AstNode *sub_stmt_node; |
| 2382 | 2392 | TransScope *new_scope = trans_stmt(c, parent_scope, stmt->getSubStmt(), &sub_stmt_node); |
| ... | ... | @@ -2399,23 +2409,19 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const Defa |
| 2399 | 2409 | |
| 2400 | 2410 | Buf *label_name = buf_sprintf("default"); |
| 2401 | 2411 | |
| 2402 | | AstNode *label_node = trans_create_node(c, NodeTypeLabel); |
| 2403 | | label_node->data.label.name = label_name; |
| 2404 | | |
| 2405 | 2412 | { |
| 2406 | 2413 | // Add the prong |
| 2407 | 2414 | AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng); |
| 2408 | 2415 | |
| 2409 | | AstNode *goto_node = trans_create_node(c, NodeTypeGoto); |
| 2410 | | goto_node->data.goto_expr.name = label_name; |
| 2411 | | prong_node->data.switch_prong.expr = goto_node; |
| 2416 | prong_node->data.switch_prong.expr = trans_create_node_goto(c, label_name); |
| 2412 | 2417 | |
| 2413 | 2418 | switch_scope->switch_node->data.switch_expr.prongs.append(prong_node); |
| 2414 | 2419 | switch_scope->found_default = true; |
| 2415 | 2420 | } |
| 2416 | 2421 | |
| 2417 | 2422 | TransScopeBlock *scope_block = trans_scope_block_find(parent_scope); |
| 2418 | | scope_block->node->data.block.statements.append(label_node); |
| 2423 | scope_block->node->data.block.statements.append(trans_create_node_label(c, label_name)); |
| 2424 | |
| 2419 | 2425 | |
| 2420 | 2426 | AstNode *sub_stmt_node; |
| 2421 | 2427 | TransScope *new_scope = trans_stmt(c, parent_scope, stmt->getSubStmt(), &sub_stmt_node); |
| ... | ... | @@ -2500,7 +2506,17 @@ static AstNode *trans_string_literal(Context *c, TransScope *scope, const String |
| 2500 | 2506 | } |
| 2501 | 2507 | |
| 2502 | 2508 | static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt *stmt) { |
| 2503 | | return trans_create_node(c, NodeTypeBreak); |
| 2509 | TransScope *cur_scope = scope; |
| 2510 | while (cur_scope != nullptr) { |
| 2511 | if (cur_scope->id == TransScopeIdWhile) { |
| 2512 | return trans_create_node(c, NodeTypeBreak); |
| 2513 | } else if (cur_scope->id == TransScopeIdSwitch) { |
| 2514 | TransScopeSwitch *switch_scope = (TransScopeSwitch *)cur_scope; |
| 2515 | return trans_create_node_goto(c, switch_scope->end_label_name); |
| 2516 | } |
| 2517 | cur_scope = cur_scope->parent; |
| 2518 | } |
| 2519 | zig_unreachable(); |
| 2504 | 2520 | } |
| 2505 | 2521 | |
| 2506 | 2522 | static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const ContinueStmt *stmt) { |