authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-23 15:50:36+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-24 15:36:42-07:00
loge9b15ac9a099fd17e6b68d0f04ec42a2dbfda0ca
treee87ce5b3ddb43d4add33b720412b1a354d718d95
parent16d7db59ed9b0b1be6790bdb80777fbe5f80c7ed

stage2: error set declarations


5 files changed, 142 insertions(+), 47 deletions(-)

src-self-hosted/Module.zig+17
...@@ -80,6 +80,9 @@ deletion_set: std.ArrayListUnmanaged(*Decl) = .{},...@@ -80,6 +80,9 @@ deletion_set: std.ArrayListUnmanaged(*Decl) = .{},
80root_name: []u8,80root_name: []u8,
81keep_source_files_loaded: bool,81keep_source_files_loaded: bool,
8282
83/// Error tags and their values, tag names are duped with mod.gpa.
84global_error_set: std.StringHashMapUnmanaged(u16) = .{},
85
83pub const InnerError = error{ OutOfMemory, AnalysisFail };86pub const InnerError = error{ OutOfMemory, AnalysisFail };
8487
85const WorkItem = union(enum) {88const WorkItem = union(enum) {
...@@ -928,6 +931,11 @@ pub fn deinit(self: *Module) void {...@@ -928,6 +931,11 @@ pub fn deinit(self: *Module) void {
928931
929 self.symbol_exports.deinit(gpa);932 self.symbol_exports.deinit(gpa);
930 self.root_scope.destroy(gpa);933 self.root_scope.destroy(gpa);
934
935 for (self.global_error_set.items()) |entry| {
936 gpa.free(entry.key);
937 }
938 self.global_error_set.deinit(gpa);
931 self.* = undefined;939 self.* = undefined;
932}940}
933941
...@@ -2072,6 +2080,15 @@ fn createNewDecl(...@@ -2072,6 +2080,15 @@ fn createNewDecl(
2072 return new_decl;2080 return new_decl;
2073}2081}
20742082
2083/// Get error value for error tag `name`.
2084pub fn getErrorValue(self: *Module, name: []const u8) !u16 {
2085 const new_val = @intCast(u16, self.global_error_set.items().len);
2086 if (self.global_error_set.get(name)) |some| return some;
2087
2088 try self.global_error_set.put(self.gpa, try self.gpa.dupe(u8, name), new_val);
2089 return new_val;
2090}
2091
2075/// TODO split this into `requireRuntimeBlock` and `requireFunctionBlock` and audit callsites.2092/// TODO split this into `requireRuntimeBlock` and `requireFunctionBlock` and audit callsites.
2076pub fn requireRuntimeBlock(self: *Module, scope: *Scope, src: usize) !*Scope.Block {2093pub fn requireRuntimeBlock(self: *Module, scope: *Scope, src: usize) !*Scope.Block {
2077 return scope.cast(Scope.Block) orelse2094 return scope.cast(Scope.Block) orelse
src-self-hosted/astgen.zig+29-46
...@@ -270,6 +270,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -270,6 +270,7 @@ 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).?)),
273274
274 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),275 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),
275 .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}),276 .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}),
...@@ -291,7 +292,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -291,7 +292,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
291 .AnyType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyType", .{}),292 .AnyType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyType", .{}),
292 .ErrorType => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorType", .{}),293 .ErrorType => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorType", .{}),
293 .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", .{}),
294 .ErrorSetDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorSetDecl", .{}),
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", .{}),
297 .Nosuspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Nosuspend", .{}),297 .Nosuspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Nosuspend", .{}),
...@@ -459,7 +459,9 @@ fn varDecl(...@@ -459,7 +459,9 @@ fn varDecl(
459 const tree = scope.tree();459 const tree = scope.tree();
460 const name_src = tree.token_locs[node.name_token].start;460 const name_src = tree.token_locs[node.name_token].start;
461 const ident_name = try identifierTokenString(mod, scope, node.name_token);461 const ident_name = try identifierTokenString(mod, scope, node.name_token);
462 const init_node = node.getTrailer("init_node").?;462 const init_node = node.getTrailer("init_node") orelse
463 return mod.fail(scope, name_src, "variables must be initialized", .{});
464
463 switch (tree.token_ids[node.mut_token]) {465 switch (tree.token_ids[node.mut_token]) {
464 .Keyword_const => {466 .Keyword_const => {
465 // Depending on the type of AST the initialization expression is, we may need an lvalue467 // Depending on the type of AST the initialization expression is, we may need an lvalue
...@@ -582,11 +584,7 @@ fn addressOf(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerE...@@ -582,11 +584,7 @@ fn addressOf(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerE
582fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {584fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
583 const tree = scope.tree();585 const tree = scope.tree();
584 const src = tree.token_locs[node.op_token].start;586 const src = tree.token_locs[node.op_token].start;
585 const meta_type = try addZIRInstConst(mod, scope, src, .{587 const operand = try typeExpr(mod, scope, node.rhs);
586 .ty = Type.initTag(.type),
587 .val = Value.initTag(.type_type),
588 });
589 const operand = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);
590 return addZIRUnOp(mod, scope, src, .optional_type, operand);588 return addZIRUnOp(mod, scope, src, .optional_type, operand);
591}589}
592590
...@@ -611,18 +609,13 @@ fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir...@@ -611,18 +609,13 @@ fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir
611}609}
612610
613fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo, rhs: *ast.Node, size: std.builtin.TypeInfo.Pointer.Size) InnerError!*zir.Inst {611fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo, rhs: *ast.Node, size: std.builtin.TypeInfo.Pointer.Size) InnerError!*zir.Inst {
614 const meta_type = try addZIRInstConst(mod, scope, src, .{
615 .ty = Type.initTag(.type),
616 .val = Value.initTag(.type_type),
617 });
618
619 const simple = ptr_info.allowzero_token == null and612 const simple = ptr_info.allowzero_token == null and
620 ptr_info.align_info == null and613 ptr_info.align_info == null and
621 ptr_info.volatile_token == null and614 ptr_info.volatile_token == null and
622 ptr_info.sentinel == null;615 ptr_info.sentinel == null;
623616
624 if (simple) {617 if (simple) {
625 const child_type = try expr(mod, scope, .{ .ty = meta_type }, rhs);618 const child_type = try typeExpr(mod, scope, rhs);
626 const mutable = ptr_info.const_token == null;619 const mutable = ptr_info.const_token == null;
627 // TODO stage1 type inference bug620 // TODO stage1 type inference bug
628 const T = zir.Inst.Tag;621 const T = zir.Inst.Tag;
...@@ -650,7 +643,7 @@ fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo,...@@ -650,7 +643,7 @@ fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo,
650 kw_args.sentinel = try expr(mod, scope, .none, some);643 kw_args.sentinel = try expr(mod, scope, .none, some);
651 }644 }
652645
653 const child_type = try expr(mod, scope, .{ .ty = meta_type }, rhs);646 const child_type = try typeExpr(mod, scope, rhs);
654 if (kw_args.sentinel) |some| {647 if (kw_args.sentinel) |some| {
655 kw_args.sentinel = try addZIRBinOp(mod, scope, some.src, .as, child_type, some);648 kw_args.sentinel = try addZIRBinOp(mod, scope, some.src, .as, child_type, some);
656 }649 }
...@@ -661,10 +654,6 @@ fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo,...@@ -661,10 +654,6 @@ fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo,
661fn arrayType(mod: *Module, scope: *Scope, node: *ast.Node.ArrayType) !*zir.Inst {654fn arrayType(mod: *Module, scope: *Scope, node: *ast.Node.ArrayType) !*zir.Inst {
662 const tree = scope.tree();655 const tree = scope.tree();
663 const src = tree.token_locs[node.op_token].start;656 const src = tree.token_locs[node.op_token].start;
664 const meta_type = try addZIRInstConst(mod, scope, src, .{
665 .ty = Type.initTag(.type),
666 .val = Value.initTag(.type_type),
667 });
668 const usize_type = try addZIRInstConst(mod, scope, src, .{657 const usize_type = try addZIRInstConst(mod, scope, src, .{
669 .ty = Type.initTag(.type),658 .ty = Type.initTag(.type),
670 .val = Value.initTag(.usize_type),659 .val = Value.initTag(.usize_type),
...@@ -672,18 +661,14 @@ fn arrayType(mod: *Module, scope: *Scope, node: *ast.Node.ArrayType) !*zir.Inst...@@ -672,18 +661,14 @@ fn arrayType(mod: *Module, scope: *Scope, node: *ast.Node.ArrayType) !*zir.Inst
672661
673 // TODO check for [_]T662 // TODO check for [_]T
674 const len = try expr(mod, scope, .{ .ty = usize_type }, node.len_expr);663 const len = try expr(mod, scope, .{ .ty = usize_type }, node.len_expr);
675 const child_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);664 const elem_type = try typeExpr(mod, scope, node.rhs);
676665
677 return addZIRBinOp(mod, scope, src, .array_type, len, child_type);666 return addZIRBinOp(mod, scope, src, .array_type, len, elem_type);
678}667}
679668
680fn arrayTypeSentinel(mod: *Module, scope: *Scope, node: *ast.Node.ArrayTypeSentinel) !*zir.Inst {669fn arrayTypeSentinel(mod: *Module, scope: *Scope, node: *ast.Node.ArrayTypeSentinel) !*zir.Inst {
681 const tree = scope.tree();670 const tree = scope.tree();
682 const src = tree.token_locs[node.op_token].start;671 const src = tree.token_locs[node.op_token].start;
683 const meta_type = try addZIRInstConst(mod, scope, src, .{
684 .ty = Type.initTag(.type),
685 .val = Value.initTag(.type_type),
686 });
687 const usize_type = try addZIRInstConst(mod, scope, src, .{672 const usize_type = try addZIRInstConst(mod, scope, src, .{
688 .ty = Type.initTag(.type),673 .ty = Type.initTag(.type),
689 .val = Value.initTag(.usize_type),674 .val = Value.initTag(.usize_type),
...@@ -692,7 +677,7 @@ fn arrayTypeSentinel(mod: *Module, scope: *Scope, node: *ast.Node.ArrayTypeSenti...@@ -692,7 +677,7 @@ fn arrayTypeSentinel(mod: *Module, scope: *Scope, node: *ast.Node.ArrayTypeSenti
692 // TODO check for [_]T677 // TODO check for [_]T
693 const len = try expr(mod, scope, .{ .ty = usize_type }, node.len_expr);678 const len = try expr(mod, scope, .{ .ty = usize_type }, node.len_expr);
694 const sentinel_uncasted = try expr(mod, scope, .none, node.sentinel);679 const sentinel_uncasted = try expr(mod, scope, .none, node.sentinel);
695 const elem_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);680 const elem_type = try typeExpr(mod, scope, node.rhs);
696 const sentinel = try addZIRBinOp(mod, scope, src, .as, elem_type, sentinel_uncasted);681 const sentinel = try addZIRBinOp(mod, scope, src, .as, elem_type, sentinel_uncasted);
697682
698 return addZIRInst(mod, scope, src, zir.Inst.ArrayTypeSentinel, .{683 return addZIRInst(mod, scope, src, zir.Inst.ArrayTypeSentinel, .{
...@@ -706,11 +691,7 @@ fn anyFrameType(mod: *Module, scope: *Scope, node: *ast.Node.AnyFrameType) Inner...@@ -706,11 +691,7 @@ fn anyFrameType(mod: *Module, scope: *Scope, node: *ast.Node.AnyFrameType) Inner
706 const tree = scope.tree();691 const tree = scope.tree();
707 const src = tree.token_locs[node.anyframe_token].start;692 const src = tree.token_locs[node.anyframe_token].start;
708 if (node.result) |some| {693 if (node.result) |some| {
709 const meta_type = try addZIRInstConst(mod, scope, src, .{694 const return_type = try typeExpr(mod, scope, some.return_type);
710 .ty = Type.initTag(.type),
711 .val = Value.initTag(.type_type),
712 });
713 const return_type = try expr(mod, scope, .{ .ty = meta_type}, some.return_type);
714 return addZIRUnOp(mod, scope, src, .anyframe_type, return_type);695 return addZIRUnOp(mod, scope, src, .anyframe_type, return_type);
715 } else {696 } else {
716 return addZIRInstConst(mod, scope, src, .{697 return addZIRInstConst(mod, scope, src, .{
...@@ -723,12 +704,8 @@ fn anyFrameType(mod: *Module, scope: *Scope, node: *ast.Node.AnyFrameType) Inner...@@ -723,12 +704,8 @@ fn anyFrameType(mod: *Module, scope: *Scope, node: *ast.Node.AnyFrameType) Inner
723fn typeInixOp(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp, op_inst_tag: zir.Inst.Tag) InnerError!*zir.Inst {704fn typeInixOp(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp, op_inst_tag: zir.Inst.Tag) InnerError!*zir.Inst {
724 const tree = scope.tree();705 const tree = scope.tree();
725 const src = tree.token_locs[node.op_token].start;706 const src = tree.token_locs[node.op_token].start;
726 const meta_type = try addZIRInstConst(mod, scope, src, .{707 const error_set = try typeExpr(mod, scope, node.lhs);
727 .ty = Type.initTag(.type),708 const payload = try typeExpr(mod, scope, node.rhs);
728 .val = Value.initTag(.type_type),
729 });
730 const error_set = try expr(mod, scope, .{ .ty = meta_type }, node.lhs);
731 const payload = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);
732 return addZIRBinOp(mod, scope, src, op_inst_tag, error_set, payload);709 return addZIRBinOp(mod, scope, src, op_inst_tag, error_set, payload);
733}710}
734711
...@@ -751,6 +728,20 @@ fn unwrapOptional(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Si...@@ -751,6 +728,20 @@ fn unwrapOptional(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Si
751 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, unwrapped_ptr));728 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, unwrapped_ptr));
752}729}
753730
731fn errorSetDecl(mod: *Module, scope: *Scope, node: *ast.Node.ErrorSetDecl) InnerError!*zir.Inst {
732 const tree = scope.tree();
733 const src = tree.token_locs[node.error_token].start;
734 const decls = node.decls();
735 const fields = try scope.arena().alloc([]const u8, decls.len);
736
737 for (decls) |decl, i| {
738 const tag = decl.castTag(.ErrorTag).?;
739 fields[i] = try identifierTokenString(mod, scope, tag.name_token);
740 }
741
742 return addZIRInst(mod, scope, src, zir.Inst.ErrorSet, .{ .fields = fields }, .{});
743}
744
754/// Return whether the identifier names of two tokens are equal. Resolves @"" tokens without allocating.745/// Return whether the identifier names of two tokens are equal. Resolves @"" tokens without allocating.
755/// OK in theory it could do it without allocating. This implementation allocates when the @"" form is used.746/// OK in theory it could do it without allocating. This implementation allocates when the @"" form is used.
756fn tokenIdentEql(mod: *Module, scope: *Scope, token1: ast.TokenIndex, token2: ast.TokenIndex) !bool {747fn tokenIdentEql(mod: *Module, scope: *Scope, token1: ast.TokenIndex, token2: ast.TokenIndex) !bool {
...@@ -1517,12 +1508,8 @@ fn simpleCast(...@@ -1517,12 +1508,8 @@ fn simpleCast(
1517 try ensureBuiltinParamCount(mod, scope, call, 2);1508 try ensureBuiltinParamCount(mod, scope, call, 2);
1518 const tree = scope.tree();1509 const tree = scope.tree();
1519 const src = tree.token_locs[call.builtin_token].start;1510 const src = tree.token_locs[call.builtin_token].start;
1520 const type_type = try addZIRInstConst(mod, scope, src, .{
1521 .ty = Type.initTag(.type),
1522 .val = Value.initTag(.type_type),
1523 });
1524 const params = call.params();1511 const params = call.params();
1525 const dest_type = try expr(mod, scope, .{ .ty = type_type }, params[0]);1512 const dest_type = try typeExpr(mod, scope, params[0]);
1526 const rhs = try expr(mod, scope, .none, params[1]);1513 const rhs = try expr(mod, scope, .none, params[1]);
1527 const result = try addZIRBinOp(mod, scope, src, inst_tag, dest_type, rhs);1514 const result = try addZIRBinOp(mod, scope, src, inst_tag, dest_type, rhs);
1528 return rlWrap(mod, scope, rl, result);1515 return rlWrap(mod, scope, rl, result);
...@@ -1584,12 +1571,8 @@ fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCa...@@ -1584,12 +1571,8 @@ fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCa
1584 try ensureBuiltinParamCount(mod, scope, call, 2);1571 try ensureBuiltinParamCount(mod, scope, call, 2);
1585 const tree = scope.tree();1572 const tree = scope.tree();
1586 const src = tree.token_locs[call.builtin_token].start;1573 const src = tree.token_locs[call.builtin_token].start;
1587 const type_type = try addZIRInstConst(mod, scope, src, .{
1588 .ty = Type.initTag(.type),
1589 .val = Value.initTag(.type_type),
1590 });
1591 const params = call.params();1574 const params = call.params();
1592 const dest_type = try expr(mod, scope, .{ .ty = type_type }, params[0]);1575 const dest_type = try typeExpr(mod, scope, params[0]);
1593 switch (rl) {1576 switch (rl) {
1594 .none => {1577 .none => {
1595 const operand = try expr(mod, scope, .none, params[1]);1578 const operand = try expr(mod, scope, .none, params[1]);
src-self-hosted/value.zig+30
...@@ -91,6 +91,7 @@ pub const Value = extern union {...@@ -91,6 +91,7 @@ pub const Value = extern union {
91 float_64,91 float_64,
92 float_128,92 float_128,
93 enum_literal,93 enum_literal,
94 error_set,
9495
95 pub const last_no_payload_tag = Tag.bool_false;96 pub const last_no_payload_tag = Tag.bool_false;
96 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;97 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
...@@ -243,6 +244,9 @@ pub const Value = extern union {...@@ -243,6 +244,9 @@ pub const Value = extern union {
243 };244 };
244 return Value{ .ptr_otherwise = &new_payload.base };245 return Value{ .ptr_otherwise = &new_payload.base };
245 },246 },
247
248 // memory is managed by the declaration
249 .error_set => return self,
246 }250 }
247 }251 }
248252
...@@ -346,6 +350,14 @@ pub const Value = extern union {...@@ -346,6 +350,14 @@ pub const Value = extern union {
346 .float_32 => return out_stream.print("{}", .{val.cast(Payload.Float_32).?.val}),350 .float_32 => return out_stream.print("{}", .{val.cast(Payload.Float_32).?.val}),
347 .float_64 => return out_stream.print("{}", .{val.cast(Payload.Float_64).?.val}),351 .float_64 => return out_stream.print("{}", .{val.cast(Payload.Float_64).?.val}),
348 .float_128 => return out_stream.print("{}", .{val.cast(Payload.Float_128).?.val}),352 .float_128 => return out_stream.print("{}", .{val.cast(Payload.Float_128).?.val}),
353 .error_set => {
354 const error_set = val.cast(Payload.ErrorSet).?;
355 try out_stream.writeAll("error{");
356 for (error_set.fields.items()) |entry| {
357 try out_stream.print("{},", .{entry.value});
358 }
359 return out_stream.writeAll("}");
360 },
349 };361 };
350 }362 }
351363
...@@ -437,6 +449,7 @@ pub const Value = extern union {...@@ -437,6 +449,7 @@ pub const Value = extern union {
437 .float_64,449 .float_64,
438 .float_128,450 .float_128,
439 .enum_literal,451 .enum_literal,
452 .error_set,
440 => unreachable,453 => unreachable,
441 };454 };
442 }455 }
...@@ -503,6 +516,7 @@ pub const Value = extern union {...@@ -503,6 +516,7 @@ pub const Value = extern union {
503 .unreachable_value,516 .unreachable_value,
504 .empty_array,517 .empty_array,
505 .enum_literal,518 .enum_literal,
519 .error_set,
506 => unreachable,520 => unreachable,
507521
508 .undef => unreachable,522 .undef => unreachable,
...@@ -582,6 +596,7 @@ pub const Value = extern union {...@@ -582,6 +596,7 @@ pub const Value = extern union {
582 .unreachable_value,596 .unreachable_value,
583 .empty_array,597 .empty_array,
584 .enum_literal,598 .enum_literal,
599 .error_set,
585 => unreachable,600 => unreachable,
586601
587 .undef => unreachable,602 .undef => unreachable,
...@@ -661,6 +676,7 @@ pub const Value = extern union {...@@ -661,6 +676,7 @@ pub const Value = extern union {
661 .unreachable_value,676 .unreachable_value,
662 .empty_array,677 .empty_array,
663 .enum_literal,678 .enum_literal,
679 .error_set,
664 => unreachable,680 => unreachable,
665681
666 .undef => unreachable,682 .undef => unreachable,
...@@ -767,6 +783,7 @@ pub const Value = extern union {...@@ -767,6 +783,7 @@ pub const Value = extern union {
767 .unreachable_value,783 .unreachable_value,
768 .empty_array,784 .empty_array,
769 .enum_literal,785 .enum_literal,
786 .error_set,
770 => unreachable,787 => unreachable,
771788
772 .zero,789 .zero,
...@@ -850,6 +867,7 @@ pub const Value = extern union {...@@ -850,6 +867,7 @@ pub const Value = extern union {
850 .unreachable_value,867 .unreachable_value,
851 .empty_array,868 .empty_array,
852 .enum_literal,869 .enum_literal,
870 .error_set,
853 => unreachable,871 => unreachable,
854872
855 .zero,873 .zero,
...@@ -1017,6 +1035,7 @@ pub const Value = extern union {...@@ -1017,6 +1035,7 @@ pub const Value = extern union {
1017 .void_value,1035 .void_value,
1018 .unreachable_value,1036 .unreachable_value,
1019 .enum_literal,1037 .enum_literal,
1038 .error_set,
1020 => unreachable,1039 => unreachable,
10211040
1022 .zero => false,1041 .zero => false,
...@@ -1087,6 +1106,7 @@ pub const Value = extern union {...@@ -1087,6 +1106,7 @@ pub const Value = extern union {
1087 .unreachable_value,1106 .unreachable_value,
1088 .empty_array,1107 .empty_array,
1089 .enum_literal,1108 .enum_literal,
1109 .error_set,
1090 => unreachable,1110 => unreachable,
10911111
1092 .zero,1112 .zero,
...@@ -1230,6 +1250,7 @@ pub const Value = extern union {...@@ -1230,6 +1250,7 @@ pub const Value = extern union {
1230 .unreachable_value,1250 .unreachable_value,
1231 .empty_array,1251 .empty_array,
1232 .enum_literal,1252 .enum_literal,
1253 .error_set,
1233 => unreachable,1254 => unreachable,
12341255
1235 .ref_val => self.cast(Payload.RefVal).?.val,1256 .ref_val => self.cast(Payload.RefVal).?.val,
...@@ -1310,6 +1331,7 @@ pub const Value = extern union {...@@ -1310,6 +1331,7 @@ pub const Value = extern union {
1310 .void_value,1331 .void_value,
1311 .unreachable_value,1332 .unreachable_value,
1312 .enum_literal,1333 .enum_literal,
1334 .error_set,
1313 => unreachable,1335 => unreachable,
13141336
1315 .empty_array => unreachable, // out of bounds array index1337 .empty_array => unreachable, // out of bounds array index
...@@ -1407,6 +1429,7 @@ pub const Value = extern union {...@@ -1407,6 +1429,7 @@ pub const Value = extern union {
1407 .float_128,1429 .float_128,
1408 .void_value,1430 .void_value,
1409 .enum_literal,1431 .enum_literal,
1432 .error_set,
1410 => false,1433 => false,
14111434
1412 .undef => unreachable,1435 .undef => unreachable,
...@@ -1536,6 +1559,13 @@ pub const Value = extern union {...@@ -1536,6 +1559,13 @@ pub const Value = extern union {
1536 base: Payload = .{ .tag = .float_128 },1559 base: Payload = .{ .tag = .float_128 },
1537 val: f128,1560 val: f128,
1538 };1561 };
1562
1563 pub const ErrorSet = struct {
1564 base: Payload = .{ .tag = .error_set },
1565
1566 // TODO revisit this when we have the concept of the error tag type
1567 fields: std.StringHashMapUnmanaged(u16),
1568 };
1539 };1569 };
15401570
1541 /// Big enough to fit any non-BigInt value1571 /// Big enough to fit any non-BigInt value
src-self-hosted/zir.zig+39
...@@ -139,6 +139,8 @@ pub const Inst = struct {...@@ -139,6 +139,8 @@ pub const Inst = struct {
139 ensure_result_non_error,139 ensure_result_non_error,
140 /// Create a `E!T` type.140 /// Create a `E!T` type.
141 error_union_type,141 error_union_type,
142 /// Create an error set.
143 error_set,
142 /// Export the provided Decl as the provided name in the compilation's output object file.144 /// Export the provided Decl as the provided name in the compilation's output object file.
143 @"export",145 @"export",
144 /// Given a pointer to a struct or object that contains virtual fields, returns a pointer146 /// Given a pointer to a struct or object that contains virtual fields, returns a pointer
...@@ -359,6 +361,7 @@ pub const Inst = struct {...@@ -359,6 +361,7 @@ pub const Inst = struct {
359 .condbr => CondBr,361 .condbr => CondBr,
360 .ptr_type => PtrType,362 .ptr_type => PtrType,
361 .enum_literal => EnumLiteral,363 .enum_literal => EnumLiteral,
364 .error_set => ErrorSet,
362 };365 };
363 }366 }
364367
...@@ -454,6 +457,7 @@ pub const Inst = struct {...@@ -454,6 +457,7 @@ pub const Inst = struct {
454 .anyframe_type,457 .anyframe_type,
455 .error_union_type,458 .error_union_type,
456 .bitnot,459 .bitnot,
460 .error_set,
457 => false,461 => false,
458462
459 .@"break",463 .@"break",
...@@ -924,6 +928,16 @@ pub const Inst = struct {...@@ -924,6 +928,16 @@ pub const Inst = struct {
924 },928 },
925 kw_args: struct {},929 kw_args: struct {},
926 };930 };
931
932 pub const ErrorSet = struct {
933 pub const base_tag = Tag.error_set;
934 base: Inst,
935
936 positionals: struct {
937 fields: [][]const u8,
938 },
939 kw_args: struct {},
940 };
927};941};
928942
929pub const ErrorMsg = struct {943pub const ErrorMsg = struct {
...@@ -1158,6 +1172,16 @@ const Writer = struct {...@@ -1158,6 +1172,16 @@ const Writer = struct {
1158 const name = self.loop_table.get(param).?;1172 const name = self.loop_table.get(param).?;
1159 return std.zig.renderStringLiteral(name, stream);1173 return std.zig.renderStringLiteral(name, stream);
1160 },1174 },
1175 [][]const u8 => {
1176 try stream.writeByte('[');
1177 for (param) |str, i| {
1178 if (i != 0) {
1179 try stream.writeAll(", ");
1180 }
1181 try std.zig.renderStringLiteral(str, stream);
1182 }
1183 try stream.writeByte(']');
1184 },
1161 else => |T| @compileError("unimplemented: rendering parameter of type " ++ @typeName(T)),1185 else => |T| @compileError("unimplemented: rendering parameter of type " ++ @typeName(T)),
1162 }1186 }
1163 }1187 }
...@@ -1555,6 +1579,21 @@ const Parser = struct {...@@ -1555,6 +1579,21 @@ const Parser = struct {
1555 const name = try self.parseStringLiteral();1579 const name = try self.parseStringLiteral();
1556 return self.loop_table.get(name).?;1580 return self.loop_table.get(name).?;
1557 },1581 },
1582 [][]const u8 => {
1583 try requireEatBytes(self, "[");
1584 skipSpace(self);
1585 if (eatByte(self, ']')) return &[0][]const u8{};
1586
1587 var strings = std.ArrayList([]const u8).init(&self.arena.allocator);
1588 while (true) {
1589 skipSpace(self);
1590 try strings.append(try self.parseStringLiteral());
1591 skipSpace(self);
1592 if (!eatByte(self, ',')) break;
1593 }
1594 try requireEatBytes(self, "]");
1595 return strings.toOwnedSlice();
1596 },
1558 else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)),1597 else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)),
1559 }1598 }
1560 return self.fail("TODO parse parameter {}", .{@typeName(T)});1599 return self.fail("TODO parse parameter {}", .{@typeName(T)});
src-self-hosted/zir_sema.zig+27-1
...@@ -126,6 +126,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!...@@ -126,6 +126,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
126 .merge_error_sets => return analyzeInstMergeErrorSets(mod, scope, old_inst.castTag(.merge_error_sets).?),126 .merge_error_sets => return analyzeInstMergeErrorSets(mod, scope, old_inst.castTag(.merge_error_sets).?),
127 .error_union_type => return analyzeInstErrorUnionType(mod, scope, old_inst.castTag(.error_union_type).?),127 .error_union_type => return analyzeInstErrorUnionType(mod, scope, old_inst.castTag(.error_union_type).?),
128 .anyframe_type => return analyzeInstAnyframeType(mod, scope, old_inst.castTag(.anyframe_type).?),128 .anyframe_type => return analyzeInstAnyframeType(mod, scope, old_inst.castTag(.anyframe_type).?),
129 .error_set => return analyzeInstErrorSet(mod, scope, old_inst.castTag(.error_set).?),
129 }130 }
130}131}
131132
...@@ -435,6 +436,7 @@ fn analyzeInstStr(mod: *Module, scope: *Scope, str_inst: *zir.Inst.Str) InnerErr...@@ -435,6 +436,7 @@ fn analyzeInstStr(mod: *Module, scope: *Scope, str_inst: *zir.Inst.Str) InnerErr
435 // The bytes references memory inside the ZIR module, which can get deallocated436 // The bytes references memory inside the ZIR module, which can get deallocated
436 // after semantic analysis is complete. We need the memory to be in the new anonymous Decl's arena.437 // after semantic analysis is complete. We need the memory to be in the new anonymous Decl's arena.
437 var new_decl_arena = std.heap.ArenaAllocator.init(mod.gpa);438 var new_decl_arena = std.heap.ArenaAllocator.init(mod.gpa);
439 errdefer new_decl_arena.deinit();
438 const arena_bytes = try new_decl_arena.allocator.dupe(u8, str_inst.positionals.bytes);440 const arena_bytes = try new_decl_arena.allocator.dupe(u8, str_inst.positionals.bytes);
439441
440 const ty_payload = try scope.arena().create(Type.Payload.Array_u8_Sentinel0);442 const ty_payload = try scope.arena().create(Type.Payload.Array_u8_Sentinel0);
...@@ -737,6 +739,30 @@ fn analyzeInstAnyframeType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) In...@@ -737,6 +739,30 @@ fn analyzeInstAnyframeType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) In
737 return mod.constType(scope, inst.base.src, try mod.anyframeType(scope, return_type));739 return mod.constType(scope, inst.base.src, try mod.anyframeType(scope, return_type));
738}740}
739741
742fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) InnerError!*Inst {
743 // The bytes references memory inside the ZIR module, which can get deallocated
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);
746 errdefer new_decl_arena.deinit();
747
748 const payload = try scope.arena().create(Value.Payload.ErrorSet);
749 payload.* = .{ .fields = .{} };
750 try payload.fields.ensureCapacity(&new_decl_arena.allocator, inst.positionals.fields.len);
751
752 for (inst.positionals.fields) |field_name| {
753 const value = try mod.getErrorValue(field_name);
754 if (payload.fields.fetchPutAssumeCapacity(field_name, value)) |prev| {
755 return mod.fail(scope, inst.base.src, "duplicate error: '{}'", .{field_name});
756 }
757 }
758 // TODO create name in format "error:line:column"
759 const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{
760 .ty = Type.initTag(.type),
761 .val = Value.initPayload(&payload.base),
762 });
763 return mod.analyzeDeclRef(scope, inst.base.src, new_decl);
764}
765
740fn analyzeInstMergeErrorSets(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {766fn analyzeInstMergeErrorSets(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
741 return mod.fail(scope, inst.base.src, "TODO implement merge_error_sets", .{});767 return mod.fail(scope, inst.base.src, "TODO implement merge_error_sets", .{});
742}768}
...@@ -1377,7 +1403,7 @@ fn analyzeInstPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.PtrType) Inne...@@ -1377,7 +1403,7 @@ fn analyzeInstPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.PtrType) Inne
13771403
1378 if (host_size != 0 and bit_offset >= host_size * 8)1404 if (host_size != 0 and bit_offset >= host_size * 8)
1379 return mod.fail(scope, inst.base.src, "bit offset starts after end of host integer", .{});1405 return mod.fail(scope, inst.base.src, "bit offset starts after end of host integer", .{});
1380 1406
1381 const sentinel = if (inst.kw_args.sentinel) |some|1407 const sentinel = if (inst.kw_args.sentinel) |some|
1382 (try resolveInstConst(mod, scope, some)).val1408 (try resolveInstConst(mod, scope, some)).val
1383 else1409 else