| ... | @@ -3414,6 +3414,8 @@ fn whileExpr( | ... | @@ -3414,6 +3414,8 @@ fn whileExpr( |
| 3414 | while_full: ast.full.While, | 3414 | while_full: ast.full.While, |
| 3415 | ) InnerError!Zir.Inst.Ref { | 3415 | ) InnerError!Zir.Inst.Ref { |
| 3416 | const astgen = parent_gz.astgen; | 3416 | const astgen = parent_gz.astgen; |
| | 3417 | const tree = &astgen.file.tree; |
| | 3418 | const token_tags = tree.tokens.items(.tag); |
| 3417 | | 3419 | |
| 3418 | if (while_full.label_token) |label_token| { | 3420 | if (while_full.label_token) |label_token| { |
| 3419 | try astgen.checkLabelRedefinition(scope, label_token); | 3421 | try astgen.checkLabelRedefinition(scope, label_token); |
| ... | @@ -3443,14 +3445,37 @@ fn whileExpr( | ... | @@ -3443,14 +3445,37 @@ fn whileExpr( |
| 3443 | }; | 3445 | }; |
| 3444 | defer continue_scope.instructions.deinit(astgen.gpa); | 3446 | defer continue_scope.instructions.deinit(astgen.gpa); |
| 3445 | | 3447 | |
| 3446 | const cond = c: { | 3448 | const payload_is_ref = if (while_full.payload_token) |payload_token| |
| 3447 | // TODO https://github.com/ziglang/zig/issues/7929 | 3449 | token_tags[payload_token] == .asterisk |
| | 3450 | else |
| | 3451 | false; |
| | 3452 | |
| | 3453 | const cond: struct { |
| | 3454 | inst: Zir.Inst.Ref, |
| | 3455 | bool_bit: Zir.Inst.Ref, |
| | 3456 | } = c: { |
| 3448 | if (while_full.error_token) |error_token| { | 3457 | if (while_full.error_token) |error_token| { |
| 3449 | return astgen.failTok(error_token, "TODO implement while error union", .{}); | 3458 | const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none; |
| | 3459 | const err_union = try expr(&continue_scope, &continue_scope.base, cond_rl, while_full.ast.cond_expr); |
| | 3460 | const tag: Zir.Inst.Tag = if (payload_is_ref) .is_err_ptr else .is_err; |
| | 3461 | break :c .{ |
| | 3462 | .inst = err_union, |
| | 3463 | .bool_bit = try continue_scope.addUnNode(tag, err_union, node), |
| | 3464 | }; |
| 3450 | } else if (while_full.payload_token) |payload_token| { | 3465 | } else if (while_full.payload_token) |payload_token| { |
| 3451 | return astgen.failTok(payload_token, "TODO implement while optional", .{}); | 3466 | const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none; |
| | 3467 | const optional = try expr(&continue_scope, &continue_scope.base, cond_rl, while_full.ast.cond_expr); |
| | 3468 | const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null; |
| | 3469 | break :c .{ |
| | 3470 | .inst = optional, |
| | 3471 | .bool_bit = try continue_scope.addUnNode(tag, optional, node), |
| | 3472 | }; |
| 3452 | } else { | 3473 | } else { |
| 3453 | break :c try expr(&continue_scope, &continue_scope.base, bool_rl, while_full.ast.cond_expr); | 3474 | const cond = try expr(&continue_scope, &continue_scope.base, bool_rl, while_full.ast.cond_expr); |
| | 3475 | break :c .{ |
| | 3476 | .inst = cond, |
| | 3477 | .bool_bit = cond, |
| | 3478 | }; |
| 3454 | } | 3479 | } |
| 3455 | }; | 3480 | }; |
| 3456 | | 3481 | |
| ... | @@ -3489,7 +3514,44 @@ fn whileExpr( | ... | @@ -3489,7 +3514,44 @@ fn whileExpr( |
| 3489 | }; | 3514 | }; |
| 3490 | defer then_scope.instructions.deinit(astgen.gpa); | 3515 | defer then_scope.instructions.deinit(astgen.gpa); |
| 3491 | | 3516 | |
| 3492 | const then_sub_scope = &then_scope.base; | 3517 | var payload_val_scope: Scope.LocalVal = undefined; |
| | 3518 | |
| | 3519 | const then_sub_scope = s: { |
| | 3520 | if (while_full.error_token) |error_token| { |
| | 3521 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| | 3522 | .err_union_payload_unsafe_ptr |
| | 3523 | else |
| | 3524 | .err_union_payload_unsafe; |
| | 3525 | const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); |
| | 3526 | const ident_name = try astgen.identifierTokenString(error_token); |
| | 3527 | payload_val_scope = .{ |
| | 3528 | .parent = &then_scope.base, |
| | 3529 | .gen_zir = &then_scope, |
| | 3530 | .name = ident_name, |
| | 3531 | .inst = payload_inst, |
| | 3532 | .token_src = error_token, |
| | 3533 | }; |
| | 3534 | break :s &payload_val_scope.base; |
| | 3535 | } else if (while_full.payload_token) |payload_token| { |
| | 3536 | const ident_token = if (payload_is_ref) payload_token + 1 else payload_token; |
| | 3537 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| | 3538 | .optional_payload_unsafe_ptr |
| | 3539 | else |
| | 3540 | .optional_payload_unsafe; |
| | 3541 | const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); |
| | 3542 | const ident_name = try astgen.identifierTokenString(ident_token); |
| | 3543 | payload_val_scope = .{ |
| | 3544 | .parent = &then_scope.base, |
| | 3545 | .gen_zir = &then_scope, |
| | 3546 | .name = ident_name, |
| | 3547 | .inst = payload_inst, |
| | 3548 | .token_src = ident_token, |
| | 3549 | }; |
| | 3550 | break :s &payload_val_scope.base; |
| | 3551 | } else { |
| | 3552 | break :s &then_scope.base; |
| | 3553 | } |
| | 3554 | }; |
| 3493 | | 3555 | |
| 3494 | loop_scope.break_count += 1; | 3556 | loop_scope.break_count += 1; |
| 3495 | const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr); | 3557 | const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr); |
| ... | @@ -3509,7 +3571,26 @@ fn whileExpr( | ... | @@ -3509,7 +3571,26 @@ fn whileExpr( |
| 3509 | result: Zir.Inst.Ref, | 3571 | result: Zir.Inst.Ref, |
| 3510 | } = if (else_node != 0) blk: { | 3572 | } = if (else_node != 0) blk: { |
| 3511 | loop_scope.break_count += 1; | 3573 | loop_scope.break_count += 1; |
| 3512 | const sub_scope = &else_scope.base; | 3574 | const sub_scope = s: { |
| | 3575 | if (while_full.error_token) |error_token| { |
| | 3576 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| | 3577 | .err_union_code_ptr |
| | 3578 | else |
| | 3579 | .err_union_code; |
| | 3580 | const payload_inst = try else_scope.addUnNode(tag, cond.inst, node); |
| | 3581 | const ident_name = try astgen.identifierTokenString(error_token); |
| | 3582 | payload_val_scope = .{ |
| | 3583 | .parent = &else_scope.base, |
| | 3584 | .gen_zir = &else_scope, |
| | 3585 | .name = ident_name, |
| | 3586 | .inst = payload_inst, |
| | 3587 | .token_src = error_token, |
| | 3588 | }; |
| | 3589 | break :s &payload_val_scope.base; |
| | 3590 | } else { |
| | 3591 | break :s &else_scope.base; |
| | 3592 | } |
| | 3593 | }; |
| 3513 | break :blk .{ | 3594 | break :blk .{ |
| 3514 | .src = else_node, | 3595 | .src = else_node, |
| 3515 | .result = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node), | 3596 | .result = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node), |
| ... | @@ -3534,7 +3615,7 @@ fn whileExpr( | ... | @@ -3534,7 +3615,7 @@ fn whileExpr( |
| 3534 | &then_scope, | 3615 | &then_scope, |
| 3535 | &else_scope, | 3616 | &else_scope, |
| 3536 | condbr, | 3617 | condbr, |
| 3537 | cond, | 3618 | cond.bool_bit, |
| 3538 | while_full.ast.then_expr, | 3619 | while_full.ast.then_expr, |
| 3539 | else_info.src, | 3620 | else_info.src, |
| 3540 | then_result, | 3621 | then_result, |