mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
stage2: astgen orelse
This commit is contained in:
parent
9a59cdcd41
commit
ff7c6e1e3c
@ -277,10 +277,10 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
|
||||
.ArrayAccess => return arrayAccess(mod, scope, rl, node.castTag(.ArrayAccess).?),
|
||||
.Catch => return catchExpr(mod, scope, rl, node.castTag(.Catch).?),
|
||||
.Comptime => return comptimeKeyword(mod, scope, rl, node.castTag(.Comptime).?),
|
||||
.OrElse => return orelseExpr(mod, scope, rl, node.castTag(.OrElse).?),
|
||||
|
||||
.Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),
|
||||
.Range => return mod.failNode(scope, node, "TODO implement astgen.expr for .Range", .{}),
|
||||
.OrElse => return mod.failNode(scope, node, "TODO implement astgen.expr for .OrElse", .{}),
|
||||
.Await => return mod.failNode(scope, node, "TODO implement astgen.expr for .Await", .{}),
|
||||
.Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}),
|
||||
.Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),
|
||||
@ -790,13 +790,31 @@ fn errorType(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerError!*
|
||||
}
|
||||
|
||||
fn catchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Catch) InnerError!*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const src = tree.token_locs[node.op_token].start;
|
||||
return orelseCatchExpr(mod, scope, rl, node.lhs, node.op_token, .iserr, .unwrap_err_unsafe, node.rhs, node.payload);
|
||||
}
|
||||
|
||||
const err_union_ptr = try expr(mod, scope, .ref, node.lhs);
|
||||
// TODO we could avoid an unnecessary copy if .iserr took a pointer
|
||||
const err_union = try addZIRUnOp(mod, scope, src, .deref, err_union_ptr);
|
||||
const cond = try addZIRUnOp(mod, scope, src, .iserr, err_union);
|
||||
fn orelseExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst {
|
||||
return orelseCatchExpr(mod, scope, rl, node.lhs, node.op_token, .isnull, .unwrap_optional_unsafe, node.rhs, null);
|
||||
}
|
||||
|
||||
fn orelseCatchExpr(
|
||||
mod: *Module,
|
||||
scope: *Scope,
|
||||
rl: ResultLoc,
|
||||
lhs: *ast.Node,
|
||||
op_token: ast.TokenIndex,
|
||||
cond_op: zir.Inst.Tag,
|
||||
unwrap_op: zir.Inst.Tag,
|
||||
rhs: *ast.Node,
|
||||
payload_node: ?*ast.Node,
|
||||
) InnerError!*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const src = tree.token_locs[op_token].start;
|
||||
|
||||
const operand_ptr = try expr(mod, scope, .ref, lhs);
|
||||
// TODO we could avoid an unnecessary copy if .iserr, .isnull took a pointer
|
||||
const err_union = try addZIRUnOp(mod, scope, src, .deref, operand_ptr);
|
||||
const cond = try addZIRUnOp(mod, scope, src, cond_op, err_union);
|
||||
|
||||
var block_scope: Scope.GenZIR = .{
|
||||
.parent = scope,
|
||||
@ -825,55 +843,55 @@ fn catchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Catch)
|
||||
.inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block },
|
||||
};
|
||||
|
||||
var err_scope: Scope.GenZIR = .{
|
||||
var then_scope: Scope.GenZIR = .{
|
||||
.parent = scope,
|
||||
.decl = block_scope.decl,
|
||||
.arena = block_scope.arena,
|
||||
.instructions = .{},
|
||||
};
|
||||
defer err_scope.instructions.deinit(mod.gpa);
|
||||
defer then_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
var err_val_scope: Scope.LocalVal = undefined;
|
||||
const err_sub_scope = blk: {
|
||||
const payload = node.payload orelse
|
||||
break :blk &err_scope.base;
|
||||
const then_sub_scope = blk: {
|
||||
const payload = payload_node orelse
|
||||
break :blk &then_scope.base;
|
||||
|
||||
const err_name = tree.tokenSlice(payload.castTag(.Payload).?.error_symbol.firstToken());
|
||||
if (mem.eql(u8, err_name, "_"))
|
||||
break :blk &err_scope.base;
|
||||
break :blk &then_scope.base;
|
||||
|
||||
const unwrapped_err_ptr = try addZIRUnOp(mod, &err_scope.base, src, .unwrap_err_code, err_union_ptr);
|
||||
const unwrapped_err_ptr = try addZIRUnOp(mod, &then_scope.base, src, .unwrap_err_code, operand_ptr);
|
||||
err_val_scope = .{
|
||||
.parent = &err_scope.base,
|
||||
.gen_zir = &err_scope,
|
||||
.parent = &then_scope.base,
|
||||
.gen_zir = &then_scope,
|
||||
.name = err_name,
|
||||
.inst = try addZIRUnOp(mod, &err_scope.base, src, .deref, unwrapped_err_ptr),
|
||||
.inst = try addZIRUnOp(mod, &then_scope.base, src, .deref, unwrapped_err_ptr),
|
||||
};
|
||||
break :blk &err_val_scope.base;
|
||||
};
|
||||
|
||||
_ = try addZIRInst(mod, &err_scope.base, src, zir.Inst.Break, .{
|
||||
_ = try addZIRInst(mod, &then_scope.base, src, zir.Inst.Break, .{
|
||||
.block = block,
|
||||
.operand = try expr(mod, err_sub_scope, branch_rl, node.rhs),
|
||||
.operand = try expr(mod, then_sub_scope, branch_rl, rhs),
|
||||
}, .{});
|
||||
|
||||
var not_err_scope: Scope.GenZIR = .{
|
||||
var else_scope: Scope.GenZIR = .{
|
||||
.parent = scope,
|
||||
.decl = block_scope.decl,
|
||||
.arena = block_scope.arena,
|
||||
.instructions = .{},
|
||||
};
|
||||
defer not_err_scope.instructions.deinit(mod.gpa);
|
||||
defer else_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
const unwrapped_payload = try addZIRUnOp(mod, ¬_err_scope.base, src, .unwrap_err_unsafe, err_union_ptr);
|
||||
_ = try addZIRInst(mod, ¬_err_scope.base, src, zir.Inst.Break, .{
|
||||
const unwrapped_payload = try addZIRUnOp(mod, &else_scope.base, src, unwrap_op, operand_ptr);
|
||||
_ = try addZIRInst(mod, &else_scope.base, src, zir.Inst.Break, .{
|
||||
.block = block,
|
||||
.operand = unwrapped_payload,
|
||||
}, .{});
|
||||
|
||||
condbr.positionals.then_body = .{ .instructions = try err_scope.arena.dupe(*zir.Inst, err_scope.instructions.items) };
|
||||
condbr.positionals.else_body = .{ .instructions = try not_err_scope.arena.dupe(*zir.Inst, not_err_scope.instructions.items) };
|
||||
return rlWrap(mod, scope, rl, &block.base);
|
||||
condbr.positionals.then_body = .{ .instructions = try then_scope.arena.dupe(*zir.Inst, then_scope.instructions.items) };
|
||||
condbr.positionals.else_body = .{ .instructions = try else_scope.arena.dupe(*zir.Inst, else_scope.instructions.items) };
|
||||
return rlWrapPtr(mod, scope, rl, &block.base);
|
||||
}
|
||||
|
||||
/// Return whether the identifier names of two tokens are equal. Resolves @"" tokens without allocating.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user