| author | |
| committer | |
| log | 1520e084cb5fee08ddaf670046c38fd34d3d2cff |
| tree | a87a0d1f866186495f9347c0b1a201310da175c9 |
| parent | e9b15ac9a099fd17e6b68d0f04ec42a2dbfda0ca |
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 | } |
| 2082 | 2082 | ||
| 2083 | /// Get error value for error tag `name`. | 2083 | /// Get error value for error tag `name`. |
| 2084 | pub fn getErrorValue(self: *Module, name: []const u8) !u16 { | 2084 | pub 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.*; |
| 2087 | 2087 | ||
| 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 | } |
| 2091 | 2094 | ||
| 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).?)), | ||
| 274 | 275 | ||
| 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; |
| 723 | 723 | ||
| 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 | } |
| 730 | 727 | ||
| 731 | fn errorSetDecl(mod: *Module, scope: *Scope, node: *ast.Node.ErrorSetDecl) InnerError!*zir.Inst { | 728 | fn 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 | } |
| 741 | 738 | ||
| 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 | |||
| 743 | fn 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 | } |
| 744 | 751 | ||
| 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 | } |
| 781 | 788 | ||
| 782 | fn field(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst { | 789 | fn 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; |
| 786 | 792 | ||
| 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).?); |
| 789 | 795 | ||
| 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 | } |
| 793 | 800 | ||
| 794 | fn deref(mod: *Module, scope: *Scope, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst { | 801 | fn 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 | } |
| 1290 | 1292 | ||
| 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 | } |
| 1297 | 1296 | ||
| 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 | } |
| 1888 | 1887 | ||
| 1888 | fn 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 | |||
| 1889 | pub fn addZIRInstSpecial( | 1894 | pub 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", | ||
| 95 | 96 | ||
| 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), | ||
| 247 | 249 | ||
| 248 | // memory is managed by the declaration | 250 | // memory is managed by the declaration |
| 249 | .error_set => return self, | 251 | .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), |
| 250 | } | 252 | } |
| 251 | } | 253 | } |
| 252 | 254 | ||
| ... | @@ -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 | } |
| 363 | 366 | ||
| ... | @@ -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"), | ||
| 427 | 431 | ||
| 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, |
| 521 | 526 | ||
| 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, |
| 601 | 607 | ||
| 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, |
| 681 | 688 | ||
| 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, |
| 788 | 796 | ||
| 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, |
| 872 | 881 | ||
| 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, |
| 1040 | 1050 | ||
| 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, |
| 1111 | 1122 | ||
| 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, |
| 1255 | 1267 | ||
| 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, |
| 1336 | 1349 | ||
| 1337 | .empty_array => unreachable, // out of bounds array index | 1350 | .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, |
| 1434 | 1448 | ||
| 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 type | 1580 | // 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 | }; |
| 1570 | 1594 | ||
| 1571 | /// Big enough to fit any non-BigInt value | 1595 | /// 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 | } |
| 741 | 741 | ||
| 742 | fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) InnerError!*Inst { | 742 | fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) InnerError!*Inst { |
| 743 | // The bytes references memory inside the ZIR module, which can get deallocated | 743 | // 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(); |
| 747 | 746 | ||
| ... | @@ -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); |
| 751 | 750 | ||
| 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 | } |