| ... | @@ -82,6 +82,7 @@ struct TransScopeSwitch { | ... | @@ -82,6 +82,7 @@ struct TransScopeSwitch { |
| 82 | AstNode *switch_node; | 82 | AstNode *switch_node; |
| 83 | uint32_t case_index; | 83 | uint32_t case_index; |
| 84 | bool found_default; | 84 | bool found_default; |
| | 85 | Buf *end_label_name; |
| 85 | }; | 86 | }; |
| 86 | | 87 | |
| 87 | struct TransScopeVar { | 88 | struct TransScopeVar { |
| ... | @@ -248,6 +249,18 @@ static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_vol | ... | @@ -248,6 +249,18 @@ static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_vol |
| 248 | return node; | 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 | static AstNode *trans_create_node_bool(Context *c, bool value) { | 264 | static AstNode *trans_create_node_bool(Context *c, bool value) { |
| 252 | AstNode *bool_node = trans_create_node(c, NodeTypeBoolLiteral); | 265 | AstNode *bool_node = trans_create_node(c, NodeTypeBoolLiteral); |
| 253 | bool_node->data.bool_literal.value = value; | 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,11 +2296,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt |
| 2283 | } | 2296 | } |
| 2284 | | 2297 | |
| 2285 | static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const SwitchStmt *stmt) { | 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); | 2299 | TransScopeBlock *block_scope = trans_scope_block_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; | | |
| 2291 | | 2300 | |
| 2292 | TransScopeSwitch *switch_scope; | 2301 | TransScopeSwitch *switch_scope; |
| 2293 | | 2302 | |
| ... | @@ -2305,6 +2314,10 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw | ... | @@ -2305,6 +2314,10 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw |
| 2305 | } | 2314 | } |
| 2306 | block_scope->node->data.block.statements.append(switch_scope->switch_node); | 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 | const Expr *cond_expr = stmt->getCond(); | 2321 | const Expr *cond_expr = stmt->getCond(); |
| 2309 | assert(cond_expr != nullptr); | 2322 | assert(cond_expr != nullptr); |
| 2310 | | 2323 | |
| ... | @@ -2336,9 +2349,11 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw | ... | @@ -2336,9 +2349,11 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw |
| 2336 | } | 2349 | } |
| 2337 | | 2350 | |
| 2338 | // This is necessary if the last switch case "falls through" the end of the switch block | 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 | static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStmt *stmt, AstNode **out_node, | 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,18 +2380,13 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStm |
| 2365 | return ErrorUnexpected; | 2380 | return ErrorUnexpected; |
| 2366 | prong_node->data.switch_prong.items.append(item_node); | 2381 | prong_node->data.switch_prong.items.append(item_node); |
| 2367 | | 2382 | |
| 2368 | AstNode *goto_node = trans_create_node(c, NodeTypeGoto); | 2383 | prong_node->data.switch_prong.expr = trans_create_node_goto(c, label_name); |
| 2369 | goto_node->data.goto_expr.name = label_name; | | |
| 2370 | prong_node->data.switch_prong.expr = goto_node; | | |
| 2371 | | 2384 | |
| 2372 | switch_scope->switch_node->data.switch_expr.prongs.append(prong_node); | 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 | TransScopeBlock *scope_block = trans_scope_block_find(parent_scope); | 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 | AstNode *sub_stmt_node; | 2391 | AstNode *sub_stmt_node; |
| 2382 | TransScope *new_scope = trans_stmt(c, parent_scope, stmt->getSubStmt(), &sub_stmt_node); | 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,23 +2409,19 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const Defa |
| 2399 | | 2409 | |
| 2400 | Buf *label_name = buf_sprintf("default"); | 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 | // Add the prong | 2413 | // Add the prong |
| 2407 | AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng); | 2414 | AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng); |
| 2408 | | 2415 | |
| 2409 | AstNode *goto_node = trans_create_node(c, NodeTypeGoto); | 2416 | prong_node->data.switch_prong.expr = trans_create_node_goto(c, label_name); |
| 2410 | goto_node->data.goto_expr.name = label_name; | | |
| 2411 | prong_node->data.switch_prong.expr = goto_node; | | |
| 2412 | | 2417 | |
| 2413 | switch_scope->switch_node->data.switch_expr.prongs.append(prong_node); | 2418 | switch_scope->switch_node->data.switch_expr.prongs.append(prong_node); |
| 2414 | switch_scope->found_default = true; | 2419 | switch_scope->found_default = true; |
| 2415 | } | 2420 | } |
| 2416 | | 2421 | |
| 2417 | TransScopeBlock *scope_block = trans_scope_block_find(parent_scope); | 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 | AstNode *sub_stmt_node; | 2426 | AstNode *sub_stmt_node; |
| 2421 | TransScope *new_scope = trans_stmt(c, parent_scope, stmt->getSubStmt(), &sub_stmt_node); | 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,7 +2506,17 @@ static AstNode *trans_string_literal(Context *c, TransScope *scope, const String |
| 2500 | } | 2506 | } |
| 2501 | | 2507 | |
| 2502 | static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt *stmt) { | 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 | static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const ContinueStmt *stmt) { | 2522 | static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const ContinueStmt *stmt) { |