| ... | ... | @@ -3264,6 +3264,9 @@ fn ifExpr( |
| 3264 | 3264 | if_full: ast.full.If, |
| 3265 | 3265 | ) InnerError!Zir.Inst.Ref { |
| 3266 | 3266 | const astgen = parent_gz.astgen; |
| 3267 | const tree = &astgen.file.tree; |
| 3268 | const token_tags = tree.tokens.items(.tag); |
| 3269 | |
| 3267 | 3270 | var block_scope: GenZir = .{ |
| 3268 | 3271 | .parent = scope, |
| 3269 | 3272 | .decl_node_index = parent_gz.decl_node_index, |
| ... | ... | @@ -3274,14 +3277,37 @@ fn ifExpr( |
| 3274 | 3277 | block_scope.setBreakResultLoc(rl); |
| 3275 | 3278 | defer block_scope.instructions.deinit(astgen.gpa); |
| 3276 | 3279 | |
| 3277 | | const cond = c: { |
| 3278 | | // TODO https://github.com/ziglang/zig/issues/7929 |
| 3280 | const payload_is_ref = if (if_full.payload_token) |payload_token| |
| 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 | 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 | 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 | 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 | 3326 | }; |
| 3301 | 3327 | defer then_scope.instructions.deinit(astgen.gpa); |
| 3302 | 3328 | |
| 3303 | | // declare payload to the then_scope |
| 3304 | | const then_sub_scope = &then_scope.base; |
| 3329 | var payload_val_scope: Scope.LocalVal = undefined; |
| 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 | 3368 | block_scope.break_count += 1; |
| 3307 | 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 | 3386 | result: Zir.Inst.Ref, |
| 3325 | 3387 | } = if (else_node != 0) blk: { |
| 3326 | 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 | 3409 | break :blk .{ |
| 3329 | 3410 | .src = else_node, |
| 3330 | 3411 | .result = try expr(&else_scope, sub_scope, block_scope.break_result_loc, else_node), |
| ... | ... | @@ -3343,7 +3424,7 @@ fn ifExpr( |
| 3343 | 3424 | &then_scope, |
| 3344 | 3425 | &else_scope, |
| 3345 | 3426 | condbr, |
| 3346 | | cond, |
| 3427 | cond.bool_bit, |
| 3347 | 3428 | if_full.ast.then_expr, |
| 3348 | 3429 | else_info.src, |
| 3349 | 3430 | then_result, |