diff --git a/src/astgen.zig b/src/astgen.zig index 1a533a6e96..63184e641b 100644 --- a/src/astgen.zig +++ b/src/astgen.zig @@ -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", .{}), } } diff --git a/src/value.zig b/src/value.zig index a602d08c06..0a6a48dbf7 100644 --- a/src/value.zig +++ b/src/value.zig @@ -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, }, diff --git a/src/zir.zig b/src/zir.zig index 42c972e29d..d013f25ee5 100644 --- a/src/zir.zig +++ b/src/zir.zig @@ -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, diff --git a/src/zir_sema.zig b/src/zir_sema.zig index f9ff256a35..8da4fd9eff 100644 --- a/src/zir_sema.zig +++ b/src/zir_sema.zig @@ -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();