authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-19 12:25:16-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-19 12:25:16-07:00
log27d4bea9a478e9c544329869d076b0e505d0e382
tree98ade88dbf91dcbaea5d06d4f175a081c140aeb5
parent3dadccec45832f31810d01b5599f984db5935e8c

AstGen: implement if optional, if error union


1 files changed, 90 insertions(+), 9 deletions(-)

src/AstGen.zig+90-9
......@@ -3264,6 +3264,9 @@ fn ifExpr(
32643264 if_full: ast.full.If,
32653265) InnerError!Zir.Inst.Ref {
32663266 const astgen = parent_gz.astgen;
3267 const tree = &astgen.file.tree;
3268 const token_tags = tree.tokens.items(.tag);
3269
32673270 var block_scope: GenZir = .{
32683271 .parent = scope,
32693272 .decl_node_index = parent_gz.decl_node_index,
......@@ -3274,14 +3277,37 @@ fn ifExpr(
32743277 block_scope.setBreakResultLoc(rl);
32753278 defer block_scope.instructions.deinit(astgen.gpa);
32763279
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: {
32793289 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 };
32813297 } 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 };
32833305 } 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 };
32853311 }
32863312 };
32873313
......@@ -3300,8 +3326,44 @@ fn ifExpr(
33003326 };
33013327 defer then_scope.instructions.deinit(astgen.gpa);
33023328
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 };
33053367
33063368 block_scope.break_count += 1;
33073369 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(
33243386 result: Zir.Inst.Ref,
33253387 } = if (else_node != 0) blk: {
33263388 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 };
33283409 break :blk .{
33293410 .src = else_node,
33303411 .result = try expr(&else_scope, sub_scope, block_scope.break_result_loc, else_node),
......@@ -3343,7 +3424,7 @@ fn ifExpr(
33433424 &then_scope,
33443425 &else_scope,
33453426 condbr,
3346 cond,
3427 cond.bool_bit,
33473428 if_full.ast.then_expr,
33483429 else_info.src,
33493430 then_result,