| ... | @@ -3264,6 +3264,9 @@ fn ifExpr( | ... | @@ -3264,6 +3264,9 @@ fn ifExpr( |
| 3264 | if_full: ast.full.If, | 3264 | if_full: ast.full.If, |
| 3265 | ) InnerError!Zir.Inst.Ref { | 3265 | ) InnerError!Zir.Inst.Ref { |
| 3266 | const astgen = parent_gz.astgen; | 3266 | const astgen = parent_gz.astgen; |
| | 3267 | const tree = &astgen.file.tree; |
| | 3268 | const token_tags = tree.tokens.items(.tag); |
| | 3269 | |
| 3267 | var block_scope: GenZir = .{ | 3270 | var block_scope: GenZir = .{ |
| 3268 | .parent = scope, | 3271 | .parent = scope, |
| 3269 | .decl_node_index = parent_gz.decl_node_index, | 3272 | .decl_node_index = parent_gz.decl_node_index, |
| ... | @@ -3274,14 +3277,37 @@ fn ifExpr( | ... | @@ -3274,14 +3277,37 @@ fn ifExpr( |
| 3274 | block_scope.setBreakResultLoc(rl); | 3277 | block_scope.setBreakResultLoc(rl); |
| 3275 | defer block_scope.instructions.deinit(astgen.gpa); | 3278 | defer block_scope.instructions.deinit(astgen.gpa); |
| 3276 | | 3279 | |
| 3277 | const cond = c: { | 3280 | const payload_is_ref = if (if_full.payload_token) |payload_token| |
| 3278 | // TODO https://github.com/ziglang/zig/issues/7929 | 3281 | token_tags[payload_token] == .asterisk |
| | 3282 | else |
| | 3283 | false; |
| | 3284 | |
| | 3285 | const cond: struct { |
| | 3286 | inst: Zir.Inst.Ref, |
| | 3287 | bool_bit: Zir.Inst.Ref, |
| | 3288 | } = c: { |
| 3279 | if (if_full.error_token) |error_token| { | 3289 | if (if_full.error_token) |error_token| { |
| 3280 | return astgen.failTok(error_token, "TODO implement if error union", .{}); | 3290 | const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none; |
| | 3291 | const err_union = try expr(&block_scope, &block_scope.base, cond_rl, if_full.ast.cond_expr); |
| | 3292 | const tag: Zir.Inst.Tag = if (payload_is_ref) .is_err_ptr else .is_err; |
| | 3293 | break :c .{ |
| | 3294 | .inst = err_union, |
| | 3295 | .bool_bit = try block_scope.addUnNode(tag, err_union, node), |
| | 3296 | }; |
| 3281 | } else if (if_full.payload_token) |payload_token| { | 3297 | } else if (if_full.payload_token) |payload_token| { |
| 3282 | return astgen.failTok(payload_token, "TODO implement if optional", .{}); | 3298 | const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none; |
| | 3299 | const optional = try expr(&block_scope, &block_scope.base, cond_rl, if_full.ast.cond_expr); |
| | 3300 | const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null; |
| | 3301 | break :c .{ |
| | 3302 | .inst = optional, |
| | 3303 | .bool_bit = try block_scope.addUnNode(tag, optional, node), |
| | 3304 | }; |
| 3283 | } else { | 3305 | } else { |
| 3284 | break :c try expr(&block_scope, &block_scope.base, bool_rl, if_full.ast.cond_expr); | 3306 | const cond = try expr(&block_scope, &block_scope.base, bool_rl, if_full.ast.cond_expr); |
| | 3307 | break :c .{ |
| | 3308 | .inst = cond, |
| | 3309 | .bool_bit = cond, |
| | 3310 | }; |
| 3285 | } | 3311 | } |
| 3286 | }; | 3312 | }; |
| 3287 | | 3313 | |
| ... | @@ -3300,8 +3326,44 @@ fn ifExpr( | ... | @@ -3300,8 +3326,44 @@ fn ifExpr( |
| 3300 | }; | 3326 | }; |
| 3301 | defer then_scope.instructions.deinit(astgen.gpa); | 3327 | defer then_scope.instructions.deinit(astgen.gpa); |
| 3302 | | 3328 | |
| 3303 | // declare payload to the then_scope | 3329 | var payload_val_scope: Scope.LocalVal = undefined; |
| 3304 | const then_sub_scope = &then_scope.base; | 3330 | |
| | 3331 | const then_sub_scope = s: { |
| | 3332 | if (if_full.error_token) |error_token| { |
| | 3333 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| | 3334 | .err_union_payload_unsafe_ptr |
| | 3335 | else |
| | 3336 | .err_union_payload_unsafe; |
| | 3337 | const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); |
| | 3338 | const ident_name = try astgen.identifierTokenString(error_token); |
| | 3339 | payload_val_scope = .{ |
| | 3340 | .parent = &then_scope.base, |
| | 3341 | .gen_zir = &then_scope, |
| | 3342 | .name = ident_name, |
| | 3343 | .inst = payload_inst, |
| | 3344 | .token_src = error_token, |
| | 3345 | }; |
| | 3346 | break :s &payload_val_scope.base; |
| | 3347 | } else if (if_full.payload_token) |payload_token| { |
| | 3348 | const ident_token = if (payload_is_ref) payload_token + 1 else payload_token; |
| | 3349 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| | 3350 | .optional_payload_unsafe_ptr |
| | 3351 | else |
| | 3352 | .optional_payload_unsafe; |
| | 3353 | const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); |
| | 3354 | const ident_name = try astgen.identifierTokenString(ident_token); |
| | 3355 | payload_val_scope = .{ |
| | 3356 | .parent = &then_scope.base, |
| | 3357 | .gen_zir = &then_scope, |
| | 3358 | .name = ident_name, |
| | 3359 | .inst = payload_inst, |
| | 3360 | .token_src = ident_token, |
| | 3361 | }; |
| | 3362 | break :s &payload_val_scope.base; |
| | 3363 | } else { |
| | 3364 | break :s &then_scope.base; |
| | 3365 | } |
| | 3366 | }; |
| 3305 | | 3367 | |
| 3306 | block_scope.break_count += 1; | 3368 | block_scope.break_count += 1; |
| 3307 | const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_loc, if_full.ast.then_expr); | 3369 | const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_loc, if_full.ast.then_expr); |
| ... | @@ -3324,7 +3386,26 @@ fn ifExpr( | ... | @@ -3324,7 +3386,26 @@ fn ifExpr( |
| 3324 | result: Zir.Inst.Ref, | 3386 | result: Zir.Inst.Ref, |
| 3325 | } = if (else_node != 0) blk: { | 3387 | } = if (else_node != 0) blk: { |
| 3326 | block_scope.break_count += 1; | 3388 | block_scope.break_count += 1; |
| 3327 | const sub_scope = &else_scope.base; | 3389 | const sub_scope = s: { |
| | 3390 | if (if_full.error_token) |error_token| { |
| | 3391 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| | 3392 | .err_union_code_ptr |
| | 3393 | else |
| | 3394 | .err_union_code; |
| | 3395 | const payload_inst = try else_scope.addUnNode(tag, cond.inst, node); |
| | 3396 | const ident_name = try astgen.identifierTokenString(error_token); |
| | 3397 | payload_val_scope = .{ |
| | 3398 | .parent = &else_scope.base, |
| | 3399 | .gen_zir = &else_scope, |
| | 3400 | .name = ident_name, |
| | 3401 | .inst = payload_inst, |
| | 3402 | .token_src = error_token, |
| | 3403 | }; |
| | 3404 | break :s &payload_val_scope.base; |
| | 3405 | } else { |
| | 3406 | break :s &else_scope.base; |
| | 3407 | } |
| | 3408 | }; |
| 3328 | break :blk .{ | 3409 | break :blk .{ |
| 3329 | .src = else_node, | 3410 | .src = else_node, |
| 3330 | .result = try expr(&else_scope, sub_scope, block_scope.break_result_loc, else_node), | 3411 | .result = try expr(&else_scope, sub_scope, block_scope.break_result_loc, else_node), |
| ... | @@ -3343,7 +3424,7 @@ fn ifExpr( | ... | @@ -3343,7 +3424,7 @@ fn ifExpr( |
| 3343 | &then_scope, | 3424 | &then_scope, |
| 3344 | &else_scope, | 3425 | &else_scope, |
| 3345 | condbr, | 3426 | condbr, |
| 3346 | cond, | 3427 | cond.bool_bit, |
| 3347 | if_full.ast.then_expr, | 3428 | if_full.ast.then_expr, |
| 3348 | else_info.src, | 3429 | else_info.src, |
| 3349 | then_result, | 3430 | then_result, |