stage2: implement the error_value AST tag

This commit is contained in:
Andrew Kelley 2021-02-25 18:21:22 -07:00
parent 4360f45d7f
commit fd208d9d59
4 changed files with 41 additions and 4 deletions

View File

@ -482,6 +482,13 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
const result = try addZIRInst(mod, scope, src, zir.Inst.EnumLiteral, .{ .name = name }, .{});
return rvalue(mod, scope, rl, result);
},
.error_value => {
const ident_token = node_datas[node].rhs;
const name = try mod.identifierTokenString(scope, ident_token);
const src = token_starts[ident_token];
const result = try addZirInstTag(mod, scope, src, .error_value, .{ .name = name });
return rvalue(mod, scope, rl, result);
},
.error_union => {
const error_set = try typeExpr(mod, scope, node_datas[node].lhs);
const payload = try typeExpr(mod, scope, node_datas[node].rhs);
@ -644,7 +651,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
=> return mod.failNode(scope, node, "TODO implement astgen.expr for function prototypes", .{}),
.@"nosuspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .nosuspend", .{}),
.error_value => return mod.failNode(scope, node, "TODO implement astgen.expr for .error_value", .{}),
}
}

View File

@ -2138,13 +2138,13 @@ pub const Value = extern union {
data: f128,
};
// TODO move to type.zig
/// TODO move to type.zig
pub const ErrorSet = struct {
pub const base_tag = Tag.error_set;
base: Payload = .{ .tag = base_tag },
data: struct {
// TODO revisit this when we have the concept of the error tag type
/// TODO revisit this when we have the concept of the error tag type
fields: std.StringHashMapUnmanaged(u16),
decl: *Module.Decl,
},
@ -2153,9 +2153,9 @@ pub const Value = extern union {
pub const Error = struct {
base: Payload = .{ .tag = .@"error" },
data: struct {
// TODO revisit this when we have the concept of the error tag type
/// `name` is owned by `Module` and will be valid for the entire
/// duration of the compilation.
/// TODO revisit this when we have the concept of the error tag type
name: []const u8,
value: u16,
},

View File

@ -154,6 +154,8 @@ pub const Inst = struct {
error_union_type,
/// Create an error set.
error_set,
/// `error.Foo` syntax.
error_value,
/// Export the provided Decl as the provided name in the compilation's output object file.
@"export",
/// Given a pointer to a struct or object that contains virtual fields, returns a pointer
@ -487,6 +489,7 @@ pub const Inst = struct {
.ptr_type => PtrType,
.enum_literal => EnumLiteral,
.error_set => ErrorSet,
.error_value => ErrorValue,
.slice => Slice,
.typeof_peer => TypeOfPeer,
.container_field_named => ContainerFieldNamed,
@ -612,6 +615,7 @@ pub const Inst = struct {
.error_union_type,
.bit_not,
.error_set,
.error_value,
.slice,
.slice_start,
.import,
@ -1099,6 +1103,16 @@ pub const Inst = struct {
kw_args: struct {},
};
pub const ErrorValue = struct {
pub const base_tag = Tag.error_value;
base: Inst,
positionals: struct {
name: []const u8,
},
kw_args: struct {},
};
pub const Slice = struct {
pub const base_tag = Tag.slice;
base: Inst,

View File

@ -149,6 +149,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
.error_union_type => return zirErrorUnionType(mod, scope, old_inst.castTag(.error_union_type).?),
.anyframe_type => return zirAnyframeType(mod, scope, old_inst.castTag(.anyframe_type).?),
.error_set => return zirErrorSet(mod, scope, old_inst.castTag(.error_set).?),
.error_value => return zirErrorValue(mod, scope, old_inst.castTag(.error_value).?),
.slice => return zirSlice(mod, scope, old_inst.castTag(.slice).?),
.slice_start => return zirSliceStart(mod, scope, old_inst.castTag(.slice_start).?),
.import => return zirImport(mod, scope, old_inst.castTag(.import).?),
@ -1166,6 +1167,22 @@ fn zirErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) InnerError
return mod.analyzeDeclVal(scope, inst.base.src, new_decl);
}
fn zirErrorValue(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorValue) InnerError!*Inst {
const tracy = trace(@src());
defer tracy.end();
// Create an anonymous error set type with only this error value, and return the value.
const entry = try mod.getErrorValue(inst.positionals.name);
const result_type = try Type.Tag.error_set_single.create(scope.arena(), entry.key);
return mod.constInst(scope, inst.base.src, .{
.ty = result_type,
.val = try Value.Tag.@"error".create(scope.arena(), .{
.name = entry.key,
.value = entry.value,
}),
});
}
fn zirMergeErrorSets(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
const tracy = trace(@src());
defer tracy.end();