authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-23 20:19:05+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-24 15:36:42-07:00
log1520e084cb5fee08ddaf670046c38fd34d3d2cff
treea87a0d1f866186495f9347c0b1a201310da175c9
parente9b15ac9a099fd17e6b68d0f04ec42a2dbfda0ca

stage2: implement accessing error values


4 files changed, 96 insertions(+), 33 deletions(-)

src-self-hosted/Module.zig+7-4
...@@ -2081,12 +2081,15 @@ fn createNewDecl(...@@ -2081,12 +2081,15 @@ fn createNewDecl(
2081}2081}
20822082
2083/// Get error value for error tag `name`.2083/// Get error value for error tag `name`.
2084pub fn getErrorValue(self: *Module, name: []const u8) !u16 {2084pub fn getErrorValue(self: *Module, name: []const u8) !std.StringHashMapUnmanaged(u16).Entry {
2085 const new_val = @intCast(u16, self.global_error_set.items().len);2085 const new_val = @intCast(u16, self.global_error_set.items().len);
2086 if (self.global_error_set.get(name)) |some| return some;2086 if (self.global_error_set.getEntry(name)) |some| return some.*;
20872087
2088 try self.global_error_set.put(self.gpa, try self.gpa.dupe(u8, name), new_val);2088 const duped = try self.gpa.dupe(u8, name);
2089 return new_val;2089 errdefer self.gpa.free(duped);
2090
2091 try self.global_error_set.put(self.gpa, duped, new_val);
2092 return self.global_error_set.getEntry(duped).?.*;
2090}2093}
20912094
2092/// TODO split this into `requireRuntimeBlock` and `requireFunctionBlock` and audit callsites.2095/// TODO split this into `requireRuntimeBlock` and `requireFunctionBlock` and audit callsites.
src-self-hosted/astgen.zig+28-23
...@@ -247,7 +247,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -247,7 +247,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
247 .Return => return ret(mod, scope, node.castTag(.Return).?),247 .Return => return ret(mod, scope, node.castTag(.Return).?),
248 .If => return ifExpr(mod, scope, rl, node.castTag(.If).?),248 .If => return ifExpr(mod, scope, rl, node.castTag(.If).?),
249 .While => return whileExpr(mod, scope, rl, node.castTag(.While).?),249 .While => return whileExpr(mod, scope, rl, node.castTag(.While).?),
250 .Period => return rlWrap(mod, scope, rl, try field(mod, scope, node.castTag(.Period).?)),250 .Period => return field(mod, scope, rl, node.castTag(.Period).?),
251 .Deref => return rlWrap(mod, scope, rl, try deref(mod, scope, node.castTag(.Deref).?)),251 .Deref => return rlWrap(mod, scope, rl, try deref(mod, scope, node.castTag(.Deref).?)),
252 .AddressOf => return rlWrap(mod, scope, rl, try addressOf(mod, scope, node.castTag(.AddressOf).?)),252 .AddressOf => return rlWrap(mod, scope, rl, try addressOf(mod, scope, node.castTag(.AddressOf).?)),
253 .FloatLiteral => return rlWrap(mod, scope, rl, try floatLiteral(mod, scope, node.castTag(.FloatLiteral).?)),253 .FloatLiteral => return rlWrap(mod, scope, rl, try floatLiteral(mod, scope, node.castTag(.FloatLiteral).?)),
...@@ -270,7 +270,8 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -270,7 +270,8 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
270 .ErrorUnion => return rlWrap(mod, scope, rl, try typeInixOp(mod, scope, node.castTag(.ErrorUnion).?, .error_union_type)),270 .ErrorUnion => return rlWrap(mod, scope, rl, try typeInixOp(mod, scope, node.castTag(.ErrorUnion).?, .error_union_type)),
271 .MergeErrorSets => return rlWrap(mod, scope, rl, try typeInixOp(mod, scope, node.castTag(.MergeErrorSets).?, .merge_error_sets)),271 .MergeErrorSets => return rlWrap(mod, scope, rl, try typeInixOp(mod, scope, node.castTag(.MergeErrorSets).?, .merge_error_sets)),
272 .AnyFrameType => return rlWrap(mod, scope, rl, try anyFrameType(mod, scope, node.castTag(.AnyFrameType).?)),272 .AnyFrameType => return rlWrap(mod, scope, rl, try anyFrameType(mod, scope, node.castTag(.AnyFrameType).?)),
273 .ErrorSetDecl => return rlWrap(mod, scope, rl, try errorSetDecl(mod, scope, node.castTag(.ErrorSetDecl).?)),273 .ErrorSetDecl => return errorSetDecl(mod, scope, rl, node.castTag(.ErrorSetDecl).?),
274 .ErrorType => return rlWrap(mod, scope, rl, try errorType(mod, scope, node.castTag(.ErrorType).?)),
274275
275 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),276 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),
276 .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}),277 .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}),
...@@ -290,7 +291,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -290,7 +291,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
290 .Suspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Suspend", .{}),291 .Suspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Suspend", .{}),
291 .Continue => return mod.failNode(scope, node, "TODO implement astgen.expr for .Continue", .{}),292 .Continue => return mod.failNode(scope, node, "TODO implement astgen.expr for .Continue", .{}),
292 .AnyType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyType", .{}),293 .AnyType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyType", .{}),
293 .ErrorType => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorType", .{}),
294 .FnProto => return mod.failNode(scope, node, "TODO implement astgen.expr for .FnProto", .{}),294 .FnProto => return mod.failNode(scope, node, "TODO implement astgen.expr for .FnProto", .{}),
295 .ContainerDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerDecl", .{}),295 .ContainerDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerDecl", .{}),
296 .Comptime => return mod.failNode(scope, node, "TODO implement astgen.expr for .Comptime", .{}),296 .Comptime => return mod.failNode(scope, node, "TODO implement astgen.expr for .Comptime", .{}),
...@@ -722,13 +722,10 @@ fn unwrapOptional(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Si...@@ -722,13 +722,10 @@ fn unwrapOptional(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Si
722 const src = tree.token_locs[node.rtoken].start;722 const src = tree.token_locs[node.rtoken].start;
723723
724 const operand = try expr(mod, scope, .ref, node.lhs);724 const operand = try expr(mod, scope, .ref, node.lhs);
725 const unwrapped_ptr = try addZIRUnOp(mod, scope, src, .unwrap_optional_safe, operand);725 return rlWrapPtr(mod, scope, rl, try addZIRUnOp(mod, scope, src, .unwrap_optional_safe, operand));
726 if (rl == .lvalue or rl == .ref) return unwrapped_ptr;
727
728 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, unwrapped_ptr));
729}726}
730727
731fn errorSetDecl(mod: *Module, scope: *Scope, node: *ast.Node.ErrorSetDecl) InnerError!*zir.Inst {728fn errorSetDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.ErrorSetDecl) InnerError!*zir.Inst {
732 const tree = scope.tree();729 const tree = scope.tree();
733 const src = tree.token_locs[node.error_token].start;730 const src = tree.token_locs[node.error_token].start;
734 const decls = node.decls();731 const decls = node.decls();
...@@ -739,7 +736,17 @@ fn errorSetDecl(mod: *Module, scope: *Scope, node: *ast.Node.ErrorSetDecl) Inner...@@ -739,7 +736,17 @@ fn errorSetDecl(mod: *Module, scope: *Scope, node: *ast.Node.ErrorSetDecl) Inner
739 fields[i] = try identifierTokenString(mod, scope, tag.name_token);736 fields[i] = try identifierTokenString(mod, scope, tag.name_token);
740 }737 }
741738
742 return addZIRInst(mod, scope, src, zir.Inst.ErrorSet, .{ .fields = fields }, .{});739 // analyzing the error set results in a decl ref, so we might need to dereference it
740 return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.ErrorSet, .{ .fields = fields }, .{}));
741}
742
743fn errorType(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerError!*zir.Inst {
744 const tree = scope.tree();
745 const src = tree.token_locs[node.token].start;
746 return addZIRInstConst(mod, scope, src, .{
747 .ty = Type.initTag(.type),
748 .val = Value.initTag(.anyerror_type),
749 });
743}750}
744751
745/// Return whether the identifier names of two tokens are equal. Resolves @"" tokens without allocating.752/// Return whether the identifier names of two tokens are equal. Resolves @"" tokens without allocating.
...@@ -779,16 +786,16 @@ pub fn identifierStringInst(mod: *Module, scope: *Scope, node: *ast.Node.OneToke...@@ -779,16 +786,16 @@ pub fn identifierStringInst(mod: *Module, scope: *Scope, node: *ast.Node.OneToke
779 return addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = ident_name }, .{});786 return addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = ident_name }, .{});
780}787}
781788
782fn field(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst {789fn field(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst {
783 // TODO introduce lvalues
784 const tree = scope.tree();790 const tree = scope.tree();
785 const src = tree.token_locs[node.op_token].start;791 const src = tree.token_locs[node.op_token].start;
786792
787 const lhs = try expr(mod, scope, .none, node.lhs);793 const lhs = try expr(mod, scope, .ref, node.lhs);
788 const field_name = try identifierStringInst(mod, scope, node.rhs.castTag(.Identifier).?);794 const field_name = try identifierStringInst(mod, scope, node.rhs.castTag(.Identifier).?);
789795
790 const pointer = try addZIRInst(mod, scope, src, zir.Inst.FieldPtr, .{ .object_ptr = lhs, .field_name = field_name }, .{});796 const pointer = try addZIRInst(mod, scope, src, zir.Inst.FieldPtr, .{ .object_ptr = lhs, .field_name = field_name }, .{});
791 return addZIRUnOp(mod, scope, src, .deref, pointer);797 if (rl == .ref or rl == .lvalue) return pointer;
798 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, pointer));
792}799}
793800
794fn deref(mod: *Module, scope: *Scope, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst {801fn deref(mod: *Module, scope: *Scope, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst {
...@@ -1274,12 +1281,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo...@@ -1274,12 +1281,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
1274 .local_ptr => {1281 .local_ptr => {
1275 const local_ptr = s.cast(Scope.LocalPtr).?;1282 const local_ptr = s.cast(Scope.LocalPtr).?;
1276 if (mem.eql(u8, local_ptr.name, ident_name)) {1283 if (mem.eql(u8, local_ptr.name, ident_name)) {
1277 if (rl == .lvalue or rl == .ref) {1284 return rlWrapPtr(mod, scope, rl, local_ptr.ptr);
1278 return local_ptr.ptr;
1279 } else {
1280 const result = try addZIRUnOp(mod, scope, src, .deref, local_ptr.ptr);
1281 return rlWrap(mod, scope, rl, result);
1282 }
1283 }1285 }
1284 s = local_ptr.parent;1286 s = local_ptr.parent;
1285 },1287 },
...@@ -1289,10 +1291,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo...@@ -1289,10 +1291,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
1289 }1291 }
12901292
1291 if (mod.lookupDeclName(scope, ident_name)) |decl| {1293 if (mod.lookupDeclName(scope, ident_name)) |decl| {
1292 const result = try addZIRInst(mod, scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{});1294 return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{}));
1293 if (rl == .lvalue or rl == .ref)
1294 return result;
1295 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, result));
1296 }1295 }
12971296
1298 return mod.failNode(scope, &ident.base, "use of undeclared identifier '{}'", .{ident_name});1297 return mod.failNode(scope, &ident.base, "use of undeclared identifier '{}'", .{ident_name});
...@@ -1886,6 +1885,12 @@ fn rlWrapVoid(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node, resul...@@ -1886,6 +1885,12 @@ fn rlWrapVoid(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node, resul
1886 return rlWrap(mod, scope, rl, void_inst);1885 return rlWrap(mod, scope, rl, void_inst);
1887}1886}
18881887
1888fn rlWrapPtr(mod: *Module, scope: *Scope, rl: ResultLoc, ptr: *zir.Inst) InnerError!*zir.Inst {
1889 if (rl == .lvalue or rl == .ref) return ptr;
1890
1891 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, ptr.src, .deref, ptr));
1892}
1893
1889pub fn addZIRInstSpecial(1894pub fn addZIRInstSpecial(
1890 mod: *Module,1895 mod: *Module,
1891 scope: *Scope,1896 scope: *Scope,
src-self-hosted/value.zig+26-2
...@@ -92,6 +92,7 @@ pub const Value = extern union {...@@ -92,6 +92,7 @@ pub const Value = extern union {
92 float_128,92 float_128,
93 enum_literal,93 enum_literal,
94 error_set,94 error_set,
95 @"error",
9596
96 pub const last_no_payload_tag = Tag.bool_false;97 pub const last_no_payload_tag = Tag.bool_false;
97 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;98 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
...@@ -244,9 +245,10 @@ pub const Value = extern union {...@@ -244,9 +245,10 @@ pub const Value = extern union {
244 };245 };
245 return Value{ .ptr_otherwise = &new_payload.base };246 return Value{ .ptr_otherwise = &new_payload.base };
246 },247 },
248 .@"error" => return self.copyPayloadShallow(allocator, Payload.Error),
247249
248 // memory is managed by the declaration250 // memory is managed by the declaration
249 .error_set => return self,251 .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
250 }252 }
251 }253 }
252254
...@@ -358,6 +360,7 @@ pub const Value = extern union {...@@ -358,6 +360,7 @@ pub const Value = extern union {
358 }360 }
359 return out_stream.writeAll("}");361 return out_stream.writeAll("}");
360 },362 },
363 .@"error" => return out_stream.print("error.{}", .{val.cast(Payload.Error).?.name}),
361 };364 };
362 }365 }
363366
...@@ -424,6 +427,7 @@ pub const Value = extern union {...@@ -424,6 +427,7 @@ pub const Value = extern union {
424 .const_slice_u8_type => Type.initTag(.const_slice_u8),427 .const_slice_u8_type => Type.initTag(.const_slice_u8),
425 .enum_literal_type => Type.initTag(.enum_literal),428 .enum_literal_type => Type.initTag(.enum_literal),
426 .anyframe_type => Type.initTag(.@"anyframe"),429 .anyframe_type => Type.initTag(.@"anyframe"),
430 .error_set => @panic("TODO error set to type"),
427431
428 .undef,432 .undef,
429 .zero,433 .zero,
...@@ -449,7 +453,7 @@ pub const Value = extern union {...@@ -449,7 +453,7 @@ pub const Value = extern union {
449 .float_64,453 .float_64,
450 .float_128,454 .float_128,
451 .enum_literal,455 .enum_literal,
452 .error_set,456 .@"error",
453 => unreachable,457 => unreachable,
454 };458 };
455 }459 }
...@@ -517,6 +521,7 @@ pub const Value = extern union {...@@ -517,6 +521,7 @@ pub const Value = extern union {
517 .empty_array,521 .empty_array,
518 .enum_literal,522 .enum_literal,
519 .error_set,523 .error_set,
524 .@"error",
520 => unreachable,525 => unreachable,
521526
522 .undef => unreachable,527 .undef => unreachable,
...@@ -597,6 +602,7 @@ pub const Value = extern union {...@@ -597,6 +602,7 @@ pub const Value = extern union {
597 .empty_array,602 .empty_array,
598 .enum_literal,603 .enum_literal,
599 .error_set,604 .error_set,
605 .@"error",
600 => unreachable,606 => unreachable,
601607
602 .undef => unreachable,608 .undef => unreachable,
...@@ -677,6 +683,7 @@ pub const Value = extern union {...@@ -677,6 +683,7 @@ pub const Value = extern union {
677 .empty_array,683 .empty_array,
678 .enum_literal,684 .enum_literal,
679 .error_set,685 .error_set,
686 .@"error",
680 => unreachable,687 => unreachable,
681688
682 .undef => unreachable,689 .undef => unreachable,
...@@ -784,6 +791,7 @@ pub const Value = extern union {...@@ -784,6 +791,7 @@ pub const Value = extern union {
784 .empty_array,791 .empty_array,
785 .enum_literal,792 .enum_literal,
786 .error_set,793 .error_set,
794 .@"error",
787 => unreachable,795 => unreachable,
788796
789 .zero,797 .zero,
...@@ -868,6 +876,7 @@ pub const Value = extern union {...@@ -868,6 +876,7 @@ pub const Value = extern union {
868 .empty_array,876 .empty_array,
869 .enum_literal,877 .enum_literal,
870 .error_set,878 .error_set,
879 .@"error",
871 => unreachable,880 => unreachable,
872881
873 .zero,882 .zero,
...@@ -1036,6 +1045,7 @@ pub const Value = extern union {...@@ -1036,6 +1045,7 @@ pub const Value = extern union {
1036 .unreachable_value,1045 .unreachable_value,
1037 .enum_literal,1046 .enum_literal,
1038 .error_set,1047 .error_set,
1048 .@"error",
1039 => unreachable,1049 => unreachable,
10401050
1041 .zero => false,1051 .zero => false,
...@@ -1107,6 +1117,7 @@ pub const Value = extern union {...@@ -1107,6 +1117,7 @@ pub const Value = extern union {
1107 .empty_array,1117 .empty_array,
1108 .enum_literal,1118 .enum_literal,
1109 .error_set,1119 .error_set,
1120 .@"error",
1110 => unreachable,1121 => unreachable,
11111122
1112 .zero,1123 .zero,
...@@ -1251,6 +1262,7 @@ pub const Value = extern union {...@@ -1251,6 +1262,7 @@ pub const Value = extern union {
1251 .empty_array,1262 .empty_array,
1252 .enum_literal,1263 .enum_literal,
1253 .error_set,1264 .error_set,
1265 .@"error",
1254 => unreachable,1266 => unreachable,
12551267
1256 .ref_val => self.cast(Payload.RefVal).?.val,1268 .ref_val => self.cast(Payload.RefVal).?.val,
...@@ -1332,6 +1344,7 @@ pub const Value = extern union {...@@ -1332,6 +1344,7 @@ pub const Value = extern union {
1332 .unreachable_value,1344 .unreachable_value,
1333 .enum_literal,1345 .enum_literal,
1334 .error_set,1346 .error_set,
1347 .@"error",
1335 => unreachable,1348 => unreachable,
13361349
1337 .empty_array => unreachable, // out of bounds array index1350 .empty_array => unreachable, // out of bounds array index
...@@ -1430,6 +1443,7 @@ pub const Value = extern union {...@@ -1430,6 +1443,7 @@ pub const Value = extern union {
1430 .void_value,1443 .void_value,
1431 .enum_literal,1444 .enum_literal,
1432 .error_set,1445 .error_set,
1446 .@"error",
1433 => false,1447 => false,
14341448
1435 .undef => unreachable,1449 .undef => unreachable,
...@@ -1566,6 +1580,16 @@ pub const Value = extern union {...@@ -1566,6 +1580,16 @@ pub const Value = extern union {
1566 // TODO revisit this when we have the concept of the error tag type1580 // TODO revisit this when we have the concept of the error tag type
1567 fields: std.StringHashMapUnmanaged(u16),1581 fields: std.StringHashMapUnmanaged(u16),
1568 };1582 };
1583
1584 pub const Error = struct {
1585 base: Payload = .{ .tag = .@"error" },
1586
1587 // TODO revisit this when we have the concept of the error tag type
1588 /// `name` is owned by `Module` and will be valid for the entire
1589 /// duration of the compilation.
1590 name: []const u8,
1591 value: u16,
1592 };
1569 };1593 };
15701594
1571 /// Big enough to fit any non-BigInt value1595 /// Big enough to fit any non-BigInt value
src-self-hosted/zir_sema.zig+35-4
...@@ -740,8 +740,7 @@ fn analyzeInstAnyframeType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) In...@@ -740,8 +740,7 @@ fn analyzeInstAnyframeType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) In
740}740}
741741
742fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) InnerError!*Inst {742fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) InnerError!*Inst {
743 // The bytes references memory inside the ZIR module, which can get deallocated743 // The declarations arena will store the hashmap.
744 // after semantic analysis is complete. We need the memory to be in the new anonymous Decl's arena.
745 var new_decl_arena = std.heap.ArenaAllocator.init(mod.gpa);744 var new_decl_arena = std.heap.ArenaAllocator.init(mod.gpa);
746 errdefer new_decl_arena.deinit();745 errdefer new_decl_arena.deinit();
747746
...@@ -750,8 +749,8 @@ fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) In...@@ -750,8 +749,8 @@ fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) In
750 try payload.fields.ensureCapacity(&new_decl_arena.allocator, inst.positionals.fields.len);749 try payload.fields.ensureCapacity(&new_decl_arena.allocator, inst.positionals.fields.len);
751750
752 for (inst.positionals.fields) |field_name| {751 for (inst.positionals.fields) |field_name| {
753 const value = try mod.getErrorValue(field_name);752 const entry = try mod.getErrorValue(field_name);
754 if (payload.fields.fetchPutAssumeCapacity(field_name, value)) |prev| {753 if (payload.fields.fetchPutAssumeCapacity(entry.key, entry.value)) |prev| {
755 return mod.fail(scope, inst.base.src, "duplicate error: '{}'", .{field_name});754 return mod.fail(scope, inst.base.src, "duplicate error: '{}'", .{field_name});
756 }755 }
757 }756 }
...@@ -909,6 +908,38 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr...@@ -909,6 +908,38 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr
909 );908 );
910 }909 }
911 },910 },
911 .Type => {
912 _ = try mod.resolveConstValue(scope, object_ptr);
913 const result = try mod.analyzeDeref(scope, fieldptr.base.src, object_ptr, object_ptr.src);
914 const val = result.value().?;
915 const child_type = val.toType();
916 switch (child_type.zigTypeTag()) {
917 .ErrorSet => {
918 // TODO resolve inferred error sets
919 const entry = if (val.cast(Value.Payload.ErrorSet)) |payload|
920 (payload.fields.getEntry(field_name) orelse
921 return mod.fail(scope, fieldptr.base.src, "no error named '{}' in '{}'", .{ field_name, child_type })).*
922 else
923 try mod.getErrorValue(field_name);
924
925 const error_payload = try scope.arena().create(Value.Payload.Error);
926 error_payload.* = .{
927 .name = entry.key,
928 .value = entry.value,
929 };
930
931 const ref_payload = try scope.arena().create(Value.Payload.RefVal);
932 ref_payload.* = .{ .val = Value.initPayload(&error_payload.base) };
933
934 // TODO if this is accessing the global error set create a `error{field_name}` type
935 return mod.constInst(scope, fieldptr.base.src, .{
936 .ty = try mod.simplePtrType(scope, fieldptr.base.src, child_type, false, .One),
937 .val = Value.initPayload(&ref_payload.base),
938 });
939 },
940 else => return mod.fail(scope, fieldptr.base.src, "type '{}' does not support field access", .{child_type}),
941 }
942 },
912 else => return mod.fail(scope, fieldptr.base.src, "type '{}' does not support field access", .{elem_ty}),943 else => return mod.fail(scope, fieldptr.base.src, "type '{}' does not support field access", .{elem_ty}),
913 }944 }
914}945}