Commit fd208d9d59

Andrew Kelley <andrew@ziglang.org>
2021-02-26 02:21:22
stage2: implement the error_value AST tag
1 parent 4360f45
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", .{}),
     }
 }
 
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,
             },
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,
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();