authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-18 22:02:55-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-08-18 22:02:55-04:00
log771f40204e769f92bb28bdb9c44e3ddd9d8c4386
tree9335aaca57403c0b71916b2304af2568cbdaed05
parent626d94c2a11aecebf59348d5031df58e7337cfb1
parente4aefc6d0f9b08a98f566cb8280a6195c08f7a82
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6086 from Vexu/stage2

Stage2: more astgen stuff

8 files changed, 842 insertions(+), 83 deletions(-)

lib/std/zig.zig+101
...@@ -80,6 +80,107 @@ pub fn binNameAlloc(...@@ -80,6 +80,107 @@ pub fn binNameAlloc(
80 }80 }
81}81}
8282
83/// Only validates escape sequence characters.
84/// Slice must be valid utf8 starting and ending with "'" and exactly one codepoint in between.
85pub fn parseCharLiteral(
86 slice: []const u8,
87 bad_index: *usize, // populated if error.InvalidCharacter is returned)
88) error{InvalidCharacter}!u32 {
89 std.debug.assert(slice.len >= 3 and slice[0] == '\'' and slice[slice.len - 1] == '\'');
90
91 if (slice[1] == '\\') {
92 switch (slice[2]) {
93 'n' => return '\n',
94 'r' => return '\r',
95 '\\' => return '\\',
96 't' => return '\t',
97 '\'' => return '\'',
98 '"' => return '"',
99 'x' => {
100 if (slice.len != 6) {
101 bad_index.* = slice.len - 2;
102 return error.InvalidCharacter;
103 }
104
105 var value: u32 = 0;
106 for (slice[3..5]) |c, i| {
107 switch (slice[3]) {
108 '0'...'9' => {
109 value *= 16;
110 value += c - '0';
111 },
112 'a'...'f' => {
113 value *= 16;
114 value += c - 'a';
115 },
116 'A'...'F' => {
117 value *= 16;
118 value += c - 'a';
119 },
120 else => {
121 bad_index.* = i;
122 return error.InvalidCharacter;
123 },
124 }
125 }
126 return value;
127 },
128 'u' => {
129 if (slice.len < 6 or slice[3] != '{') {
130 bad_index.* = 2;
131 return error.InvalidCharacter;
132 }
133 var value: u32 = 0;
134 for (slice[4..]) |c, i| {
135 if (value > 0x10ffff) {
136 bad_index.* = i;
137 return error.InvalidCharacter;
138 }
139 switch (c) {
140 '0'...'9' => {
141 value *= 16;
142 value += c - '0';
143 },
144 'a'...'f' => {
145 value *= 16;
146 value += c - 'a';
147 },
148 'A'...'F' => {
149 value *= 16;
150 value += c - 'A';
151 },
152 '}' => break,
153 else => {
154 bad_index.* = i;
155 return error.InvalidCharacter;
156 },
157 }
158 }
159 return value;
160 },
161 else => {
162 bad_index.* = 2;
163 return error.InvalidCharacter;
164 }
165 }
166 }
167 return std.unicode.utf8Decode(slice[1 .. slice.len - 1]) catch unreachable;
168}
169
170test "parseCharLiteral" {
171 var bad_index: usize = undefined;
172 std.testing.expectEqual(try parseCharLiteral("'a'", &bad_index), 'a');
173 std.testing.expectEqual(try parseCharLiteral("'ä'", &bad_index), 'ä');
174 std.testing.expectEqual(try parseCharLiteral("'\\x00'", &bad_index), 0);
175 std.testing.expectEqual(try parseCharLiteral("'ぁ'", &bad_index), 0x3041);
176 std.testing.expectEqual(try parseCharLiteral("'\\u{3041}'", &bad_index), 0x3041);
177
178 std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\x0'", &bad_index));
179 std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\y'", &bad_index));
180 std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\u'", &bad_index));
181 std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\u{FFFFFF}'", &bad_index));
182}
183
83test "" {184test "" {
84 @import("std").meta.refAllDecls(@This());185 @import("std").meta.refAllDecls(@This());
85}186}
src-self-hosted/Module.zig+66-1
...@@ -2902,7 +2902,7 @@ pub fn floatSub(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs:...@@ -2902,7 +2902,7 @@ pub fn floatSub(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs:
2902 return Value.initPayload(val_payload);2902 return Value.initPayload(val_payload);
2903}2903}
29042904
2905pub fn singlePtrType(self: *Module, scope: *Scope, src: usize, mutable: bool, elem_ty: Type) error{OutOfMemory}!Type {2905pub fn singlePtrType(self: *Module, scope: *Scope, src: usize, mutable: bool, elem_ty: Type) Allocator.Error!Type {
2906 const type_payload = try scope.arena().create(Type.Payload.Pointer);2906 const type_payload = try scope.arena().create(Type.Payload.Pointer);
2907 type_payload.* = .{2907 type_payload.* = .{
2908 .base = .{ .tag = if (mutable) .single_mut_pointer else .single_const_pointer },2908 .base = .{ .tag = if (mutable) .single_mut_pointer else .single_const_pointer },
...@@ -2911,6 +2911,71 @@ pub fn singlePtrType(self: *Module, scope: *Scope, src: usize, mutable: bool, el...@@ -2911,6 +2911,71 @@ pub fn singlePtrType(self: *Module, scope: *Scope, src: usize, mutable: bool, el
2911 return Type.initPayload(&type_payload.base);2911 return Type.initPayload(&type_payload.base);
2912}2912}
29132913
2914pub fn optionalType(self: *Module, scope: *Scope, child_type: Type) Allocator.Error!Type {
2915 return Type.initPayload(switch (child_type.tag()) {
2916 .single_const_pointer => blk: {
2917 const payload = try scope.arena().create(Type.Payload.Pointer);
2918 payload.* = .{
2919 .base = .{ .tag = .optional_single_const_pointer },
2920 .pointee_type = child_type.elemType(),
2921 };
2922 break :blk &payload.base;
2923 },
2924 .single_mut_pointer => blk: {
2925 const payload = try scope.arena().create(Type.Payload.Pointer);
2926 payload.* = .{
2927 .base = .{ .tag = .optional_single_mut_pointer },
2928 .pointee_type = child_type.elemType(),
2929 };
2930 break :blk &payload.base;
2931 },
2932 else => blk: {
2933 const payload = try scope.arena().create(Type.Payload.Optional);
2934 payload.* = .{
2935 .child_type = child_type,
2936 };
2937 break :blk &payload.base;
2938 },
2939 });
2940}
2941
2942pub fn arrayType(self: *Module, scope: *Scope, len: u64, sentinel: ?Value, elem_type: Type) Allocator.Error!Type {
2943 if (elem_type.eql(Type.initTag(.u8))) {
2944 if (sentinel) |some| {
2945 if (some.eql(Value.initTag(.zero))) {
2946 const payload = try scope.arena().create(Type.Payload.Array_u8_Sentinel0);
2947 payload.* = .{
2948 .len = len,
2949 };
2950 return Type.initPayload(&payload.base);
2951 }
2952 } else {
2953 const payload = try scope.arena().create(Type.Payload.Array_u8);
2954 payload.* = .{
2955 .len = len,
2956 };
2957 return Type.initPayload(&payload.base);
2958 }
2959 }
2960
2961 if (sentinel) |some| {
2962 const payload = try scope.arena().create(Type.Payload.ArraySentinel);
2963 payload.* = .{
2964 .len = len,
2965 .sentinel = some,
2966 .elem_type = elem_type,
2967 };
2968 return Type.initPayload(&payload.base);
2969 }
2970
2971 const payload = try scope.arena().create(Type.Payload.Array);
2972 payload.* = .{
2973 .len = len,
2974 .elem_type = elem_type,
2975 };
2976 return Type.initPayload(&payload.base);
2977}
2978
2914pub fn dumpInst(self: *Module, scope: *Scope, inst: *Inst) void {2979pub fn dumpInst(self: *Module, scope: *Scope, inst: *Inst) void {
2915 const zir_module = scope.namespace();2980 const zir_module = scope.namespace();
2916 const source = zir_module.getSource(self) catch @panic("dumpInst failed to get source");2981 const source = zir_module.getSource(self) catch @panic("dumpInst failed to get source");
src-self-hosted/astgen.zig+340-24
...@@ -20,6 +20,8 @@ pub const ResultLoc = union(enum) {...@@ -20,6 +20,8 @@ pub const ResultLoc = union(enum) {
20 /// The expression must generate a pointer rather than a value. For example, the left hand side20 /// The expression must generate a pointer rather than a value. For example, the left hand side
21 /// of an assignment uses an "LValue" result location.21 /// of an assignment uses an "LValue" result location.
22 lvalue,22 lvalue,
23 /// The expression must generate a pointer
24 ref,
23 /// The expression will be type coerced into this type, but it will be evaluated as an rvalue.25 /// The expression will be type coerced into this type, but it will be evaluated as an rvalue.
24 ty: *zir.Inst,26 ty: *zir.Inst,
25 /// The expression must store its result into this typed pointer.27 /// The expression must store its result into this typed pointer.
...@@ -46,6 +48,132 @@ pub fn typeExpr(mod: *Module, scope: *Scope, type_node: *ast.Node) InnerError!*z...@@ -46,6 +48,132 @@ pub fn typeExpr(mod: *Module, scope: *Scope, type_node: *ast.Node) InnerError!*z
4648
47/// Turn Zig AST into untyped ZIR istructions.49/// Turn Zig AST into untyped ZIR istructions.
48pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerError!*zir.Inst {50pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerError!*zir.Inst {
51 if (rl == .lvalue) {
52 switch (node.tag) {
53 .Root => unreachable,
54 .Use => unreachable,
55 .TestDecl => unreachable,
56 .DocComment => unreachable,
57 .VarDecl => unreachable,
58 .SwitchCase => unreachable,
59 .SwitchElse => unreachable,
60 .Else => unreachable,
61 .Payload => unreachable,
62 .PointerPayload => unreachable,
63 .PointerIndexPayload => unreachable,
64 .ErrorTag => unreachable,
65 .FieldInitializer => unreachable,
66 .ContainerField => unreachable,
67
68 .Assign,
69 .AssignBitAnd,
70 .AssignBitOr,
71 .AssignBitShiftLeft,
72 .AssignBitShiftRight,
73 .AssignBitXor,
74 .AssignDiv,
75 .AssignSub,
76 .AssignSubWrap,
77 .AssignMod,
78 .AssignAdd,
79 .AssignAddWrap,
80 .AssignMul,
81 .AssignMulWrap,
82 .Add,
83 .AddWrap,
84 .Sub,
85 .SubWrap,
86 .Mul,
87 .MulWrap,
88 .Div,
89 .Mod,
90 .BitAnd,
91 .BitOr,
92 .BitShiftLeft,
93 .BitShiftRight,
94 .BitXor,
95 .BangEqual,
96 .EqualEqual,
97 .GreaterThan,
98 .GreaterOrEqual,
99 .LessThan,
100 .LessOrEqual,
101 .ArrayCat,
102 .ArrayMult,
103 .BoolAnd,
104 .BoolOr,
105 .Asm,
106 .StringLiteral,
107 .IntegerLiteral,
108 .Call,
109 .Unreachable,
110 .Return,
111 .If,
112 .While,
113 .BoolNot,
114 .AddressOf,
115 .FloatLiteral,
116 .UndefinedLiteral,
117 .BoolLiteral,
118 .NullLiteral,
119 .OptionalType,
120 .Block,
121 .LabeledBlock,
122 .Break,
123 .PtrType,
124 .GroupedExpression,
125 .ArrayType,
126 .ArrayTypeSentinel,
127 .EnumLiteral,
128 .MultilineStringLiteral,
129 .CharLiteral,
130 .Defer,
131 .Catch,
132 .ErrorUnion,
133 .MergeErrorSets,
134 .Range,
135 .OrElse,
136 .Await,
137 .BitNot,
138 .Negation,
139 .NegationWrap,
140 .Resume,
141 .Try,
142 .SliceType,
143 .Slice,
144 .ArrayInitializer,
145 .ArrayInitializerDot,
146 .StructInitializer,
147 .StructInitializerDot,
148 .Switch,
149 .For,
150 .Suspend,
151 .Continue,
152 .AnyType,
153 .ErrorType,
154 .FnProto,
155 .AnyFrameType,
156 .ErrorSetDecl,
157 .ContainerDecl,
158 .Comptime,
159 .Nosuspend,
160 => return mod.failNode(scope, node, "invalid left-hand side to assignment", .{}),
161
162 // @field can be assigned to
163 .BuiltinCall => {
164 const call = node.castTag(.BuiltinCall).?;
165 const tree = scope.tree();
166 const builtin_name = tree.tokenSlice(call.builtin_token);
167
168 if (!mem.eql(u8, builtin_name, "@field")) {
169 return mod.failNode(scope, node, "invalid left-hand side to assignment", .{});
170 }
171 },
172
173 // can be assigned to
174 .UnwrapOptional, .Deref, .Period, .ArrayAccess, .Identifier => {},
175 }
176 }
49 switch (node.tag) {177 switch (node.tag) {
50 .Root => unreachable, // Top-level declaration.178 .Root => unreachable, // Top-level declaration.
51 .Use => unreachable, // Top-level declaration.179 .Use => unreachable, // Top-level declaration.
...@@ -60,6 +188,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -60,6 +188,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
60 .PointerIndexPayload => unreachable, // Handled explicitly.188 .PointerIndexPayload => unreachable, // Handled explicitly.
61 .ErrorTag => unreachable, // Handled explicitly.189 .ErrorTag => unreachable, // Handled explicitly.
62 .FieldInitializer => unreachable, // Handled explicitly.190 .FieldInitializer => unreachable, // Handled explicitly.
191 .ContainerField => unreachable, // Handled explicitly.
63192
64 .Assign => return rlWrapVoid(mod, scope, rl, node, try assign(mod, scope, node.castTag(.Assign).?)),193 .Assign => return rlWrapVoid(mod, scope, rl, node, try assign(mod, scope, node.castTag(.Assign).?)),
65 .AssignBitAnd => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitAnd).?, .bitand)),194 .AssignBitAnd => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitAnd).?, .bitand)),
...@@ -100,6 +229,9 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -100,6 +229,9 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
100 .ArrayCat => return simpleBinOp(mod, scope, rl, node.castTag(.ArrayCat).?, .array_cat),229 .ArrayCat => return simpleBinOp(mod, scope, rl, node.castTag(.ArrayCat).?, .array_cat),
101 .ArrayMult => return simpleBinOp(mod, scope, rl, node.castTag(.ArrayMult).?, .array_mul),230 .ArrayMult => return simpleBinOp(mod, scope, rl, node.castTag(.ArrayMult).?, .array_mul),
102231
232 .BoolAnd => return boolBinOp(mod, scope, rl, node.castTag(.BoolAnd).?),
233 .BoolOr => return boolBinOp(mod, scope, rl, node.castTag(.BoolOr).?),
234
103 .Identifier => return try identifier(mod, scope, rl, node.castTag(.Identifier).?),235 .Identifier => return try identifier(mod, scope, rl, node.castTag(.Identifier).?),
104 .Asm => return rlWrap(mod, scope, rl, try assembly(mod, scope, node.castTag(.Asm).?)),236 .Asm => return rlWrap(mod, scope, rl, try assembly(mod, scope, node.castTag(.Asm).?)),
105 .StringLiteral => return rlWrap(mod, scope, rl, try stringLiteral(mod, scope, node.castTag(.StringLiteral).?)),237 .StringLiteral => return rlWrap(mod, scope, rl, try stringLiteral(mod, scope, node.castTag(.StringLiteral).?)),
...@@ -124,11 +256,15 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -124,11 +256,15 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
124 .LabeledBlock => return labeledBlockExpr(mod, scope, rl, node.castTag(.LabeledBlock).?),256 .LabeledBlock => return labeledBlockExpr(mod, scope, rl, node.castTag(.LabeledBlock).?),
125 .Break => return rlWrap(mod, scope, rl, try breakExpr(mod, scope, node.castTag(.Break).?)),257 .Break => return rlWrap(mod, scope, rl, try breakExpr(mod, scope, node.castTag(.Break).?)),
126 .PtrType => return rlWrap(mod, scope, rl, try ptrType(mod, scope, node.castTag(.PtrType).?)),258 .PtrType => return rlWrap(mod, scope, rl, try ptrType(mod, scope, node.castTag(.PtrType).?)),
259 .GroupedExpression => return expr(mod, scope, rl, node.castTag(.GroupedExpression).?.expr),
260 .ArrayType => return rlWrap(mod, scope, rl, try arrayType(mod, scope, node.castTag(.ArrayType).?)),
261 .ArrayTypeSentinel => return rlWrap(mod, scope, rl, try arrayTypeSentinel(mod, scope, node.castTag(.ArrayTypeSentinel).?)),
262 .EnumLiteral => return rlWrap(mod, scope, rl, try enumLiteral(mod, scope, node.castTag(.EnumLiteral).?)),
263 .MultilineStringLiteral => return rlWrap(mod, scope, rl, try multilineStrLiteral(mod, scope, node.castTag(.MultilineStringLiteral).?)),
264 .CharLiteral => return rlWrap(mod, scope, rl, try charLiteral(mod, scope, node.castTag(.CharLiteral).?)),
127265
128 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),266 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),
129 .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}),267 .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}),
130 .BoolAnd => return mod.failNode(scope, node, "TODO implement astgen.expr for .BoolAnd", .{}),
131 .BoolOr => return mod.failNode(scope, node, "TODO implement astgen.expr for .BoolOr", .{}),
132 .ErrorUnion => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorUnion", .{}),268 .ErrorUnion => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorUnion", .{}),
133 .MergeErrorSets => return mod.failNode(scope, node, "TODO implement astgen.expr for .MergeErrorSets", .{}),269 .MergeErrorSets => return mod.failNode(scope, node, "TODO implement astgen.expr for .MergeErrorSets", .{}),
134 .Range => return mod.failNode(scope, node, "TODO implement astgen.expr for .Range", .{}),270 .Range => return mod.failNode(scope, node, "TODO implement astgen.expr for .Range", .{}),
...@@ -139,8 +275,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -139,8 +275,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
139 .NegationWrap => return mod.failNode(scope, node, "TODO implement astgen.expr for .NegationWrap", .{}),275 .NegationWrap => return mod.failNode(scope, node, "TODO implement astgen.expr for .NegationWrap", .{}),
140 .Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}),276 .Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}),
141 .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),277 .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),
142 .ArrayType => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayType", .{}),
143 .ArrayTypeSentinel => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayTypeSentinel", .{}),
144 .SliceType => return mod.failNode(scope, node, "TODO implement astgen.expr for .SliceType", .{}),278 .SliceType => return mod.failNode(scope, node, "TODO implement astgen.expr for .SliceType", .{}),
145 .Slice => return mod.failNode(scope, node, "TODO implement astgen.expr for .Slice", .{}),279 .Slice => return mod.failNode(scope, node, "TODO implement astgen.expr for .Slice", .{}),
146 .ArrayAccess => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayAccess", .{}),280 .ArrayAccess => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayAccess", .{}),
...@@ -156,15 +290,10 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -156,15 +290,10 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
156 .ErrorType => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorType", .{}),290 .ErrorType => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorType", .{}),
157 .FnProto => return mod.failNode(scope, node, "TODO implement astgen.expr for .FnProto", .{}),291 .FnProto => return mod.failNode(scope, node, "TODO implement astgen.expr for .FnProto", .{}),
158 .AnyFrameType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyFrameType", .{}),292 .AnyFrameType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyFrameType", .{}),
159 .EnumLiteral => return mod.failNode(scope, node, "TODO implement astgen.expr for .EnumLiteral", .{}),
160 .MultilineStringLiteral => return mod.failNode(scope, node, "TODO implement astgen.expr for .MultilineStringLiteral", .{}),
161 .CharLiteral => return mod.failNode(scope, node, "TODO implement astgen.expr for .CharLiteral", .{}),
162 .GroupedExpression => return mod.failNode(scope, node, "TODO implement astgen.expr for .GroupedExpression", .{}),
163 .ErrorSetDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorSetDecl", .{}),293 .ErrorSetDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorSetDecl", .{}),
164 .ContainerDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerDecl", .{}),294 .ContainerDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerDecl", .{}),
165 .Comptime => return mod.failNode(scope, node, "TODO implement astgen.expr for .Comptime", .{}),295 .Comptime => return mod.failNode(scope, node, "TODO implement astgen.expr for .Comptime", .{}),
166 .Nosuspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Nosuspend", .{}),296 .Nosuspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Nosuspend", .{}),
167 .ContainerField => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerField", .{}),
168 }297 }
169}298}
170299
...@@ -187,7 +316,7 @@ fn breakExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowExpr...@@ -187,7 +316,7 @@ fn breakExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowExpr
187 // proper type inference requires peer type resolution on the block's316 // proper type inference requires peer type resolution on the block's
188 // break operand expressions.317 // break operand expressions.
189 const branch_rl: ResultLoc = switch (label.result_loc) {318 const branch_rl: ResultLoc = switch (label.result_loc) {
190 .discard, .none, .ty, .ptr, .lvalue => label.result_loc,319 .discard, .none, .ty, .ptr, .lvalue, .ref => label.result_loc,
191 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = label.block_inst },320 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = label.block_inst },
192 };321 };
193 const operand = try expr(mod, parent_scope, branch_rl, rhs);322 const operand = try expr(mod, parent_scope, branch_rl, rhs);
...@@ -426,7 +555,7 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr...@@ -426,7 +555,7 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr
426}555}
427556
428fn addressOf(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {557fn addressOf(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
429 return expr(mod, scope, .lvalue, node.rhs);558 return expr(mod, scope, .ref, node.rhs);
430}559}
431560
432fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {561fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
...@@ -484,13 +613,65 @@ fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir...@@ -484,13 +613,65 @@ fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir
484 return addZIRInst(mod, scope, src, zir.Inst.PtrType, .{ .child_type = child_type }, kw_args);613 return addZIRInst(mod, scope, src, zir.Inst.PtrType, .{ .child_type = child_type }, kw_args);
485}614}
486615
616fn arrayType(mod: *Module, scope: *Scope, node: *ast.Node.ArrayType) !*zir.Inst {
617 const tree = scope.tree();
618 const src = tree.token_locs[node.op_token].start;
619 const meta_type = try addZIRInstConst(mod, scope, src, .{
620 .ty = Type.initTag(.type),
621 .val = Value.initTag(.type_type),
622 });
623 const usize_type = try addZIRInstConst(mod, scope, src, .{
624 .ty = Type.initTag(.type),
625 .val = Value.initTag(.usize_type),
626 });
627
628 // TODO check for [_]T
629 const len = try expr(mod, scope, .{ .ty = usize_type }, node.len_expr);
630 const child_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);
631
632 return addZIRBinOp(mod, scope, src, .array_type, len, child_type);
633}
634
635fn arrayTypeSentinel(mod: *Module, scope: *Scope, node: *ast.Node.ArrayTypeSentinel) !*zir.Inst {
636 const tree = scope.tree();
637 const src = tree.token_locs[node.op_token].start;
638 const meta_type = try addZIRInstConst(mod, scope, src, .{
639 .ty = Type.initTag(.type),
640 .val = Value.initTag(.type_type),
641 });
642 const usize_type = try addZIRInstConst(mod, scope, src, .{
643 .ty = Type.initTag(.type),
644 .val = Value.initTag(.usize_type),
645 });
646
647 // TODO check for [_]T
648 const len = try expr(mod, scope, .{ .ty = usize_type }, node.len_expr);
649 const sentinel_uncasted = try expr(mod, scope, .none, node.sentinel);
650 const elem_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);
651 const sentinel = try addZIRBinOp(mod, scope, src, .as, elem_type, sentinel_uncasted);
652
653 return addZIRInst(mod, scope, src, zir.Inst.ArrayTypeSentinel, .{
654 .len = len,
655 .sentinel = sentinel,
656 .elem_type = elem_type,
657 }, .{});
658}
659
660fn enumLiteral(mod: *Module, scope: *Scope, node: *ast.Node.EnumLiteral) !*zir.Inst {
661 const tree = scope.tree();
662 const src = tree.token_locs[node.name].start;
663 const name = try identifierTokenString(mod, scope, node.name);
664
665 return addZIRInst(mod, scope, src, zir.Inst.EnumLiteral, .{ .name = name }, .{});
666}
667
487fn unwrapOptional(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst {668fn unwrapOptional(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst {
488 const tree = scope.tree();669 const tree = scope.tree();
489 const src = tree.token_locs[node.rtoken].start;670 const src = tree.token_locs[node.rtoken].start;
490671
491 const operand = try expr(mod, scope, .lvalue, node.lhs);672 const operand = try expr(mod, scope, .ref, node.lhs);
492 const unwrapped_ptr = try addZIRUnOp(mod, scope, src, .unwrap_optional_safe, operand);673 const unwrapped_ptr = try addZIRUnOp(mod, scope, src, .unwrap_optional_safe, operand);
493 if (rl == .lvalue) return unwrapped_ptr;674 if (rl == .lvalue or rl == .ref) return unwrapped_ptr;
494675
495 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, unwrapped_ptr));676 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, unwrapped_ptr));
496}677}
...@@ -568,6 +749,88 @@ fn simpleBinOp(...@@ -568,6 +749,88 @@ fn simpleBinOp(
568 return rlWrap(mod, scope, rl, result);749 return rlWrap(mod, scope, rl, result);
569}750}
570751
752fn boolBinOp(
753 mod: *Module,
754 scope: *Scope,
755 rl: ResultLoc,
756 infix_node: *ast.Node.SimpleInfixOp,
757) InnerError!*zir.Inst {
758 const tree = scope.tree();
759 const src = tree.token_locs[infix_node.op_token].start;
760 const bool_type = try addZIRInstConst(mod, scope, src, .{
761 .ty = Type.initTag(.type),
762 .val = Value.initTag(.bool_type),
763 });
764
765 var block_scope: Scope.GenZIR = .{
766 .parent = scope,
767 .decl = scope.decl().?,
768 .arena = scope.arena(),
769 .instructions = .{},
770 };
771 defer block_scope.instructions.deinit(mod.gpa);
772
773 const lhs = try expr(mod, scope, .{ .ty = bool_type }, infix_node.lhs);
774 const condbr = try addZIRInstSpecial(mod, &block_scope.base, src, zir.Inst.CondBr, .{
775 .condition = lhs,
776 .then_body = undefined, // populated below
777 .else_body = undefined, // populated below
778 }, .{});
779
780 const block = try addZIRInstBlock(mod, scope, src, .{
781 .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items),
782 });
783
784 var rhs_scope: Scope.GenZIR = .{
785 .parent = scope,
786 .decl = block_scope.decl,
787 .arena = block_scope.arena,
788 .instructions = .{},
789 };
790 defer rhs_scope.instructions.deinit(mod.gpa);
791
792 const rhs = try expr(mod, &rhs_scope.base, .{ .ty = bool_type }, infix_node.rhs);
793 _ = try addZIRInst(mod, &rhs_scope.base, src, zir.Inst.Break, .{
794 .block = block,
795 .operand = rhs,
796 }, .{});
797
798 var const_scope: Scope.GenZIR = .{
799 .parent = scope,
800 .decl = block_scope.decl,
801 .arena = block_scope.arena,
802 .instructions = .{},
803 };
804 defer const_scope.instructions.deinit(mod.gpa);
805
806 const is_bool_and = infix_node.base.tag == .BoolAnd;
807 _ = try addZIRInst(mod, &const_scope.base, src, zir.Inst.Break, .{
808 .block = block,
809 .operand = try addZIRInstConst(mod, &const_scope.base, src, .{
810 .ty = Type.initTag(.bool),
811 .val = if (is_bool_and) Value.initTag(.bool_false) else Value.initTag(.bool_true),
812 }),
813 }, .{});
814
815 if (is_bool_and) {
816 // if lhs // AND
817 // break rhs
818 // else
819 // break false
820 condbr.positionals.then_body = .{ .instructions = try rhs_scope.arena.dupe(*zir.Inst, rhs_scope.instructions.items) };
821 condbr.positionals.else_body = .{ .instructions = try const_scope.arena.dupe(*zir.Inst, const_scope.instructions.items) };
822 } else {
823 // if lhs // OR
824 // break true
825 // else
826 // break rhs
827 condbr.positionals.then_body = .{ .instructions = try const_scope.arena.dupe(*zir.Inst, const_scope.instructions.items) };
828 condbr.positionals.else_body = .{ .instructions = try rhs_scope.arena.dupe(*zir.Inst, rhs_scope.instructions.items) };
829 }
830
831 return rlWrap(mod, scope, rl, &block.base);
832}
833
571const CondKind = union(enum) {834const CondKind = union(enum) {
572 bool,835 bool,
573 optional: ?*zir.Inst,836 optional: ?*zir.Inst,
...@@ -583,13 +846,13 @@ const CondKind = union(enum) {...@@ -583,13 +846,13 @@ const CondKind = union(enum) {
583 return try expr(mod, &block_scope.base, .{ .ty = bool_type }, cond_node);846 return try expr(mod, &block_scope.base, .{ .ty = bool_type }, cond_node);
584 },847 },
585 .optional => {848 .optional => {
586 const cond_ptr = try expr(mod, &block_scope.base, .lvalue, cond_node);849 const cond_ptr = try expr(mod, &block_scope.base, .ref, cond_node);
587 self.* = .{ .optional = cond_ptr };850 self.* = .{ .optional = cond_ptr };
588 const result = try addZIRUnOp(mod, &block_scope.base, src, .deref, cond_ptr);851 const result = try addZIRUnOp(mod, &block_scope.base, src, .deref, cond_ptr);
589 return try addZIRUnOp(mod, &block_scope.base, src, .isnonnull, result);852 return try addZIRUnOp(mod, &block_scope.base, src, .isnonnull, result);
590 },853 },
591 .err_union => {854 .err_union => {
592 const err_ptr = try expr(mod, &block_scope.base, .lvalue, cond_node);855 const err_ptr = try expr(mod, &block_scope.base, .ref, cond_node);
593 self.* = .{ .err_union = err_ptr };856 self.* = .{ .err_union = err_ptr };
594 const result = try addZIRUnOp(mod, &block_scope.base, src, .deref, err_ptr);857 const result = try addZIRUnOp(mod, &block_scope.base, src, .deref, err_ptr);
595 return try addZIRUnOp(mod, &block_scope.base, src, .iserr, result);858 return try addZIRUnOp(mod, &block_scope.base, src, .iserr, result);
...@@ -600,7 +863,11 @@ const CondKind = union(enum) {...@@ -600,7 +863,11 @@ const CondKind = union(enum) {
600 fn thenSubScope(self: CondKind, mod: *Module, then_scope: *Scope.GenZIR, src: usize, payload_node: ?*ast.Node) !*Scope {863 fn thenSubScope(self: CondKind, mod: *Module, then_scope: *Scope.GenZIR, src: usize, payload_node: ?*ast.Node) !*Scope {
601 if (self == .bool) return &then_scope.base;864 if (self == .bool) return &then_scope.base;
602865
603 const payload = payload_node.?.castTag(.PointerPayload).?;866 const payload = payload_node.?.castTag(.PointerPayload) orelse {
867 // condition is error union and payload is not explicitly ignored
868 _ = try addZIRUnOp(mod, &then_scope.base, src, .ensure_err_payload_void, self.err_union.?);
869 return &then_scope.base;
870 };
604 const is_ptr = payload.ptr_token != null;871 const is_ptr = payload.ptr_token != null;
605 const ident_node = payload.value_symbol.castTag(.Identifier).?;872 const ident_node = payload.value_symbol.castTag(.Identifier).?;
606873
...@@ -680,7 +947,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn...@@ -680,7 +947,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
680 // proper type inference requires peer type resolution on the if's947 // proper type inference requires peer type resolution on the if's
681 // branches.948 // branches.
682 const branch_rl: ResultLoc = switch (rl) {949 const branch_rl: ResultLoc = switch (rl) {
683 .discard, .none, .ty, .ptr, .lvalue => rl,950 .discard, .none, .ty, .ptr, .lvalue, .ref => rl,
684 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block },951 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block },
685 };952 };
686953
...@@ -810,7 +1077,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W...@@ -810,7 +1077,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
810 // proper type inference requires peer type resolution on the while's1077 // proper type inference requires peer type resolution on the while's
811 // branches.1078 // branches.
812 const branch_rl: ResultLoc = switch (rl) {1079 const branch_rl: ResultLoc = switch (rl) {
813 .discard, .none, .ty, .ptr, .lvalue => rl,1080 .discard, .none, .ty, .ptr, .lvalue, .ref => rl,
814 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = while_block },1081 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = while_block },
815 };1082 };
8161083
...@@ -941,7 +1208,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo...@@ -941,7 +1208,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
941 .local_ptr => {1208 .local_ptr => {
942 const local_ptr = s.cast(Scope.LocalPtr).?;1209 const local_ptr = s.cast(Scope.LocalPtr).?;
943 if (mem.eql(u8, local_ptr.name, ident_name)) {1210 if (mem.eql(u8, local_ptr.name, ident_name)) {
944 if (rl == .lvalue) {1211 if (rl == .lvalue or rl == .ref) {
945 return local_ptr.ptr;1212 return local_ptr.ptr;
946 } else {1213 } else {
947 const result = try addZIRUnOp(mod, scope, src, .deref, local_ptr.ptr);1214 const result = try addZIRUnOp(mod, scope, src, .deref, local_ptr.ptr);
...@@ -983,6 +1250,53 @@ fn stringLiteral(mod: *Module, scope: *Scope, str_lit: *ast.Node.OneToken) Inner...@@ -983,6 +1250,53 @@ fn stringLiteral(mod: *Module, scope: *Scope, str_lit: *ast.Node.OneToken) Inner
983 return addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = bytes }, .{});1250 return addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = bytes }, .{});
984}1251}
9851252
1253fn multilineStrLiteral(mod: *Module, scope: *Scope, node: *ast.Node.MultilineStringLiteral) !*zir.Inst {
1254 const tree = scope.tree();
1255 const lines = node.linesConst();
1256 const src = tree.token_locs[lines[0]].start;
1257
1258 // line lengths and new lines
1259 var len = lines.len - 1;
1260 for (lines) |line| {
1261 len += tree.tokenSlice(line).len - 2;
1262 }
1263
1264 const bytes = try scope.arena().alloc(u8, len);
1265 var i: usize = 0;
1266 for (lines) |line, line_i| {
1267 if (line_i != 0) {
1268 bytes[i] = '\n';
1269 i += 1;
1270 }
1271 const slice = tree.tokenSlice(line)[2..];
1272 mem.copy(u8, bytes[i..], slice);
1273 i += slice.len;
1274 }
1275
1276 return addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = bytes }, .{});
1277}
1278
1279fn charLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) !*zir.Inst {
1280 const tree = scope.tree();
1281 const src = tree.token_locs[node.token].start;
1282 const slice = tree.tokenSlice(node.token);
1283
1284 var bad_index: usize = undefined;
1285 const value = std.zig.parseCharLiteral(slice, &bad_index) catch |err| switch (err) {
1286 error.InvalidCharacter => {
1287 const bad_byte = slice[bad_index];
1288 return mod.fail(scope, src + bad_index, "invalid character: '{c}'\n", .{bad_byte});
1289 },
1290 };
1291
1292 const int_payload = try scope.arena().create(Value.Payload.Int_u64);
1293 int_payload.* = .{ .int = value };
1294 return addZIRInstConst(mod, scope, src, .{
1295 .ty = Type.initTag(.comptime_int),
1296 .val = Value.initPayload(&int_payload.base),
1297 });
1298}
1299
986fn integerLiteral(mod: *Module, scope: *Scope, int_lit: *ast.Node.OneToken) InnerError!*zir.Inst {1300fn integerLiteral(mod: *Module, scope: *Scope, int_lit: *ast.Node.OneToken) InnerError!*zir.Inst {
987 const arena = scope.arena();1301 const arena = scope.arena();
988 const tree = scope.tree();1302 const tree = scope.tree();
...@@ -1158,7 +1472,8 @@ fn as(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) I...@@ -1158,7 +1472,8 @@ fn as(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) I
1158 _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);1472 _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);
1159 return result;1473 return result;
1160 },1474 },
1161 .lvalue => {1475 .lvalue => unreachable,
1476 .ref => {
1162 const result = try expr(mod, scope, .{ .ty = dest_type }, params[1]);1477 const result = try expr(mod, scope, .{ .ty = dest_type }, params[1]);
1163 return addZIRUnOp(mod, scope, result.src, .ref, result);1478 return addZIRUnOp(mod, scope, result.src, .ref, result);
1164 },1479 },
...@@ -1209,9 +1524,10 @@ fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCa...@@ -1209,9 +1524,10 @@ fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCa
1209 _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);1524 _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);
1210 return result;1525 return result;
1211 },1526 },
1212 .lvalue => {1527 .lvalue => unreachable,
1213 const operand = try expr(mod, scope, .lvalue, params[1]);1528 .ref => {
1214 const result = try addZIRBinOp(mod, scope, src, .bitcast_lvalue, dest_type, operand);1529 const operand = try expr(mod, scope, .ref, params[1]);
1530 const result = try addZIRBinOp(mod, scope, src, .bitcast_ref, dest_type, operand);
1215 return result;1531 return result;
1216 },1532 },
1217 .ty => |result_ty| {1533 .ty => |result_ty| {
...@@ -1476,7 +1792,7 @@ fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr...@@ -1476,7 +1792,7 @@ fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr
1476 _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);1792 _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);
1477 return result;1793 return result;
1478 },1794 },
1479 .lvalue => {1795 .lvalue, .ref => {
1480 // We need a pointer but we have a value.1796 // We need a pointer but we have a value.
1481 return addZIRUnOp(mod, scope, result.src, .ref, result);1797 return addZIRUnOp(mod, scope, result.src, .ref, result);
1482 },1798 },
src-self-hosted/type.zig+172-22
...@@ -65,7 +65,7 @@ pub const Type = extern union {...@@ -65,7 +65,7 @@ pub const Type = extern union {
65 .fn_ccc_void_no_args => return .Fn,65 .fn_ccc_void_no_args => return .Fn,
66 .function => return .Fn,66 .function => return .Fn,
6767
68 .array, .array_u8_sentinel_0 => return .Array,68 .array, .array_u8_sentinel_0, .array_u8, .array_sentinel => return .Array,
69 .single_const_pointer => return .Pointer,69 .single_const_pointer => return .Pointer,
70 .single_mut_pointer => return .Pointer,70 .single_mut_pointer => return .Pointer,
71 .single_const_pointer_to_comptime_int => return .Pointer,71 .single_const_pointer_to_comptime_int => return .Pointer,
...@@ -75,6 +75,7 @@ pub const Type = extern union {...@@ -75,6 +75,7 @@ pub const Type = extern union {
75 .optional_single_const_pointer,75 .optional_single_const_pointer,
76 .optional_single_mut_pointer,76 .optional_single_mut_pointer,
77 => return .Optional,77 => return .Optional,
78 .enum_literal => return .EnumLiteral,
78 }79 }
79 }80 }
8081
...@@ -127,6 +128,7 @@ pub const Type = extern union {...@@ -127,6 +128,7 @@ pub const Type = extern union {
127 if (zig_tag_a != zig_tag_b)128 if (zig_tag_a != zig_tag_b)
128 return false;129 return false;
129 switch (zig_tag_a) {130 switch (zig_tag_a) {
131 .EnumLiteral => return true,
130 .Type => return true,132 .Type => return true,
131 .Void => return true,133 .Void => return true,
132 .Bool => return true,134 .Bool => return true,
...@@ -211,7 +213,6 @@ pub const Type = extern union {...@@ -211,7 +213,6 @@ pub const Type = extern union {
211 .Frame,213 .Frame,
212 .AnyFrame,214 .AnyFrame,
213 .Vector,215 .Vector,
214 .EnumLiteral,
215 => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }),216 => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }),
216 }217 }
217 }218 }
...@@ -327,9 +328,11 @@ pub const Type = extern union {...@@ -327,9 +328,11 @@ pub const Type = extern union {
327 .fn_ccc_void_no_args,328 .fn_ccc_void_no_args,
328 .single_const_pointer_to_comptime_int,329 .single_const_pointer_to_comptime_int,
329 .const_slice_u8,330 .const_slice_u8,
331 .enum_literal,
330 => unreachable,332 => unreachable,
331333
332 .array_u8_sentinel_0 => return self.copyPayloadShallow(allocator, Payload.Array_u8_Sentinel0),334 .array_u8_sentinel_0 => return self.copyPayloadShallow(allocator, Payload.Array_u8_Sentinel0),
335 .array_u8 => return self.copyPayloadShallow(allocator, Payload.Array_u8),
333 .array => {336 .array => {
334 const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise);337 const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise);
335 const new_payload = try allocator.create(Payload.Array);338 const new_payload = try allocator.create(Payload.Array);
...@@ -340,6 +343,17 @@ pub const Type = extern union {...@@ -340,6 +343,17 @@ pub const Type = extern union {
340 };343 };
341 return Type{ .ptr_otherwise = &new_payload.base };344 return Type{ .ptr_otherwise = &new_payload.base };
342 },345 },
346 .array_sentinel => {
347 const payload = @fieldParentPtr(Payload.ArraySentinel, "base", self.ptr_otherwise);
348 const new_payload = try allocator.create(Payload.ArraySentinel);
349 new_payload.* = .{
350 .base = payload.base,
351 .len = payload.len,
352 .sentinel = try payload.sentinel.copy(allocator),
353 .elem_type = try payload.elem_type.copy(allocator),
354 };
355 return Type{ .ptr_otherwise = &new_payload.base };
356 },
343 .int_signed => return self.copyPayloadShallow(allocator, Payload.IntSigned),357 .int_signed => return self.copyPayloadShallow(allocator, Payload.IntSigned),
344 .int_unsigned => return self.copyPayloadShallow(allocator, Payload.IntUnsigned),358 .int_unsigned => return self.copyPayloadShallow(allocator, Payload.IntUnsigned),
345 .function => {359 .function => {
...@@ -425,6 +439,7 @@ pub const Type = extern union {...@@ -425,6 +439,7 @@ pub const Type = extern union {
425 .noreturn,439 .noreturn,
426 => return out_stream.writeAll(@tagName(t)),440 => return out_stream.writeAll(@tagName(t)),
427441
442 .enum_literal => return out_stream.writeAll("@TypeOf(.EnumLiteral)"),
428 .@"null" => return out_stream.writeAll("@TypeOf(null)"),443 .@"null" => return out_stream.writeAll("@TypeOf(null)"),
429 .@"undefined" => return out_stream.writeAll("@TypeOf(undefined)"),444 .@"undefined" => return out_stream.writeAll("@TypeOf(undefined)"),
430445
...@@ -445,6 +460,10 @@ pub const Type = extern union {...@@ -445,6 +460,10 @@ pub const Type = extern union {
445 try payload.return_type.format("", .{}, out_stream);460 try payload.return_type.format("", .{}, out_stream);
446 },461 },
447462
463 .array_u8 => {
464 const payload = @fieldParentPtr(Payload.Array_u8, "base", ty.ptr_otherwise);
465 return out_stream.print("[{}]u8", .{payload.len});
466 },
448 .array_u8_sentinel_0 => {467 .array_u8_sentinel_0 => {
449 const payload = @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", ty.ptr_otherwise);468 const payload = @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", ty.ptr_otherwise);
450 return out_stream.print("[{}:0]u8", .{payload.len});469 return out_stream.print("[{}:0]u8", .{payload.len});
...@@ -455,6 +474,12 @@ pub const Type = extern union {...@@ -455,6 +474,12 @@ pub const Type = extern union {
455 ty = payload.elem_type;474 ty = payload.elem_type;
456 continue;475 continue;
457 },476 },
477 .array_sentinel => {
478 const payload = @fieldParentPtr(Payload.ArraySentinel, "base", ty.ptr_otherwise);
479 try out_stream.print("[{}:{}]", .{ payload.len, payload.sentinel });
480 ty = payload.elem_type;
481 continue;
482 },
458 .single_const_pointer => {483 .single_const_pointer => {
459 const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise);484 const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise);
460 try out_stream.writeAll("*const ");485 try out_stream.writeAll("*const ");
...@@ -539,6 +564,7 @@ pub const Type = extern union {...@@ -539,6 +564,7 @@ pub const Type = extern union {
539 .fn_ccc_void_no_args => return Value.initTag(.fn_ccc_void_no_args_type),564 .fn_ccc_void_no_args => return Value.initTag(.fn_ccc_void_no_args_type),
540 .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type),565 .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type),
541 .const_slice_u8 => return Value.initTag(.const_slice_u8_type),566 .const_slice_u8 => return Value.initTag(.const_slice_u8_type),
567 .enum_literal => return Value.initTag(.enum_literal_type),
542 else => {568 else => {
543 const ty_payload = try allocator.create(Value.Payload.Ty);569 const ty_payload = try allocator.create(Value.Payload.Ty);
544 ty_payload.* = .{ .ty = self };570 ty_payload.* = .{ .ty = self };
...@@ -588,6 +614,8 @@ pub const Type = extern union {...@@ -588,6 +614,8 @@ pub const Type = extern union {
588 => true,614 => true,
589 // TODO lazy types615 // TODO lazy types
590 .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,616 .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
617 .array_u8 => self.arrayLen() != 0,
618 .array_sentinel => self.elemType().hasCodeGenBits(),
591 .single_const_pointer => self.elemType().hasCodeGenBits(),619 .single_const_pointer => self.elemType().hasCodeGenBits(),
592 .single_mut_pointer => self.elemType().hasCodeGenBits(),620 .single_mut_pointer => self.elemType().hasCodeGenBits(),
593 .int_signed => self.cast(Payload.IntSigned).?.bits == 0,621 .int_signed => self.cast(Payload.IntSigned).?.bits == 0,
...@@ -601,6 +629,7 @@ pub const Type = extern union {...@@ -601,6 +629,7 @@ pub const Type = extern union {
601 .noreturn,629 .noreturn,
602 .@"null",630 .@"null",
603 .@"undefined",631 .@"undefined",
632 .enum_literal,
604 => false,633 => false,
605 };634 };
606 }635 }
...@@ -616,6 +645,7 @@ pub const Type = extern union {...@@ -616,6 +645,7 @@ pub const Type = extern union {
616 .i8,645 .i8,
617 .bool,646 .bool,
618 .array_u8_sentinel_0,647 .array_u8_sentinel_0,
648 .array_u8,
619 => return 1,649 => return 1,
620650
621 .fn_noreturn_no_args, // represents machine code; not a pointer651 .fn_noreturn_no_args, // represents machine code; not a pointer
...@@ -659,7 +689,7 @@ pub const Type = extern union {...@@ -659,7 +689,7 @@ pub const Type = extern union {
659689
660 .anyerror => return 2, // TODO revisit this when we have the concept of the error tag type690 .anyerror => return 2, // TODO revisit this when we have the concept of the error tag type
661691
662 .array => return self.cast(Payload.Array).?.elem_type.abiAlignment(target),692 .array, .array_sentinel => return self.elemType().abiAlignment(target),
663693
664 .int_signed, .int_unsigned => {694 .int_signed, .int_unsigned => {
665 const bits: u16 = if (self.cast(Payload.IntSigned)) |pl|695 const bits: u16 = if (self.cast(Payload.IntSigned)) |pl|
...@@ -691,6 +721,7 @@ pub const Type = extern union {...@@ -691,6 +721,7 @@ pub const Type = extern union {
691 .noreturn,721 .noreturn,
692 .@"null",722 .@"null",
693 .@"undefined",723 .@"undefined",
724 .enum_literal,
694 => unreachable,725 => unreachable,
695 };726 };
696 }727 }
...@@ -711,18 +742,25 @@ pub const Type = extern union {...@@ -711,18 +742,25 @@ pub const Type = extern union {
711 .noreturn => unreachable,742 .noreturn => unreachable,
712 .@"null" => unreachable,743 .@"null" => unreachable,
713 .@"undefined" => unreachable,744 .@"undefined" => unreachable,
745 .enum_literal => unreachable,
714746
715 .u8,747 .u8,
716 .i8,748 .i8,
717 .bool,749 .bool,
718 => return 1,750 => return 1,
719751
720 .array_u8_sentinel_0 => @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", self.ptr_otherwise).len,752 .array_u8 => @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", self.ptr_otherwise).len,
753 .array_u8_sentinel_0 => @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", self.ptr_otherwise).len + 1,
721 .array => {754 .array => {
722 const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise);755 const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise);
723 const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));756 const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));
724 return payload.len * elem_size;757 return payload.len * elem_size;
725 },758 },
759 .array_sentinel => {
760 const payload = @fieldParentPtr(Payload.ArraySentinel, "base", self.ptr_otherwise);
761 const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));
762 return (payload.len + 1) * elem_size;
763 },
726 .i16, .u16 => return 2,764 .i16, .u16 => return 2,
727 .i32, .u32 => return 4,765 .i32, .u32 => return 4,
728 .i64, .u64 => return 8,766 .i64, .u64 => return 8,
...@@ -818,6 +856,8 @@ pub const Type = extern union {...@@ -818,6 +856,8 @@ pub const Type = extern union {
818 .@"null",856 .@"null",
819 .@"undefined",857 .@"undefined",
820 .array,858 .array,
859 .array_sentinel,
860 .array_u8,
821 .array_u8_sentinel_0,861 .array_u8_sentinel_0,
822 .const_slice_u8,862 .const_slice_u8,
823 .fn_noreturn_no_args,863 .fn_noreturn_no_args,
...@@ -830,6 +870,7 @@ pub const Type = extern union {...@@ -830,6 +870,7 @@ pub const Type = extern union {
830 .optional,870 .optional,
831 .optional_single_mut_pointer,871 .optional_single_mut_pointer,
832 .optional_single_const_pointer,872 .optional_single_const_pointer,
873 .enum_literal,
833 => false,874 => false,
834875
835 .single_const_pointer,876 .single_const_pointer,
...@@ -875,6 +916,8 @@ pub const Type = extern union {...@@ -875,6 +916,8 @@ pub const Type = extern union {
875 .@"null",916 .@"null",
876 .@"undefined",917 .@"undefined",
877 .array,918 .array,
919 .array_sentinel,
920 .array_u8,
878 .array_u8_sentinel_0,921 .array_u8_sentinel_0,
879 .single_const_pointer,922 .single_const_pointer,
880 .single_mut_pointer,923 .single_mut_pointer,
...@@ -889,6 +932,7 @@ pub const Type = extern union {...@@ -889,6 +932,7 @@ pub const Type = extern union {
889 .optional,932 .optional,
890 .optional_single_mut_pointer,933 .optional_single_mut_pointer,
891 .optional_single_const_pointer,934 .optional_single_const_pointer,
935 .enum_literal,
892 => false,936 => false,
893937
894 .const_slice_u8 => true,938 .const_slice_u8 => true,
...@@ -931,6 +975,8 @@ pub const Type = extern union {...@@ -931,6 +975,8 @@ pub const Type = extern union {
931 .@"null",975 .@"null",
932 .@"undefined",976 .@"undefined",
933 .array,977 .array,
978 .array_sentinel,
979 .array_u8,
934 .array_u8_sentinel_0,980 .array_u8_sentinel_0,
935 .fn_noreturn_no_args,981 .fn_noreturn_no_args,
936 .fn_void_no_args,982 .fn_void_no_args,
...@@ -943,6 +989,7 @@ pub const Type = extern union {...@@ -943,6 +989,7 @@ pub const Type = extern union {
943 .optional,989 .optional,
944 .optional_single_mut_pointer,990 .optional_single_mut_pointer,
945 .optional_single_const_pointer,991 .optional_single_const_pointer,
992 .enum_literal,
946 => false,993 => false,
947994
948 .single_const_pointer,995 .single_const_pointer,
...@@ -988,6 +1035,8 @@ pub const Type = extern union {...@@ -988,6 +1035,8 @@ pub const Type = extern union {
988 .@"null",1035 .@"null",
989 .@"undefined",1036 .@"undefined",
990 .array,1037 .array,
1038 .array_sentinel,
1039 .array_u8,
991 .array_u8_sentinel_0,1040 .array_u8_sentinel_0,
992 .fn_noreturn_no_args,1041 .fn_noreturn_no_args,
993 .fn_void_no_args,1042 .fn_void_no_args,
...@@ -1003,6 +1052,7 @@ pub const Type = extern union {...@@ -1003,6 +1052,7 @@ pub const Type = extern union {
1003 .optional,1052 .optional,
1004 .optional_single_mut_pointer,1053 .optional_single_mut_pointer,
1005 .optional_single_const_pointer,1054 .optional_single_const_pointer,
1055 .enum_literal,
1006 => false,1056 => false,
1007 };1057 };
1008 }1058 }
...@@ -1023,6 +1073,45 @@ pub const Type = extern union {...@@ -1023,6 +1073,45 @@ pub const Type = extern union {
1023 }1073 }
1024 }1074 }
10251075
1076 /// Returns if type can be used for a runtime variable
1077 pub fn isValidVarType(self: Type) bool {
1078 var ty = self;
1079 while (true) switch (ty.zigTypeTag()) {
1080 .Bool,
1081 .Int,
1082 .Float,
1083 .ErrorSet,
1084 .Enum,
1085 .Frame,
1086 .AnyFrame,
1087 .Vector,
1088 => return true,
1089
1090 .BoundFn,
1091 .ComptimeFloat,
1092 .ComptimeInt,
1093 .EnumLiteral,
1094 .NoReturn,
1095 .Type,
1096 .Void,
1097 .Undefined,
1098 .Null,
1099 .Opaque,
1100 => return false,
1101
1102 .Optional => {
1103 var buf: Payload.Pointer = undefined;
1104 return ty.optionalChild(&buf).isValidVarType();
1105 },
1106 .Pointer, .Array => ty = ty.elemType(),
1107
1108 .ErrorUnion => @panic("TODO fn isValidVarType"),
1109 .Fn => @panic("TODO fn isValidVarType"),
1110 .Struct => @panic("TODO struct isValidVarType"),
1111 .Union => @panic("TODO union isValidVarType"),
1112 };
1113 }
1114
1026 /// Asserts the type is a pointer or array type.1115 /// Asserts the type is a pointer or array type.
1027 pub fn elemType(self: Type) Type {1116 pub fn elemType(self: Type) Type {
1028 return switch (self.tag()) {1117 return switch (self.tag()) {
...@@ -1069,12 +1158,14 @@ pub const Type = extern union {...@@ -1069,12 +1158,14 @@ pub const Type = extern union {
1069 .optional,1158 .optional,
1070 .optional_single_const_pointer,1159 .optional_single_const_pointer,
1071 .optional_single_mut_pointer,1160 .optional_single_mut_pointer,
1161 .enum_literal,
1072 => unreachable,1162 => unreachable,
10731163
1074 .array => self.cast(Payload.Array).?.elem_type,1164 .array => self.cast(Payload.Array).?.elem_type,
1165 .array_sentinel => self.cast(Payload.ArraySentinel).?.elem_type,
1075 .single_const_pointer => self.castPointer().?.pointee_type,1166 .single_const_pointer => self.castPointer().?.pointee_type,
1076 .single_mut_pointer => self.castPointer().?.pointee_type,1167 .single_mut_pointer => self.castPointer().?.pointee_type,
1077 .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),1168 .array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),
1078 .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),1169 .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),
1079 };1170 };
1080 }1171 }
...@@ -1173,9 +1264,12 @@ pub const Type = extern union {...@@ -1173,9 +1264,12 @@ pub const Type = extern union {
1173 .optional,1264 .optional,
1174 .optional_single_mut_pointer,1265 .optional_single_mut_pointer,
1175 .optional_single_const_pointer,1266 .optional_single_const_pointer,
1267 .enum_literal,
1176 => unreachable,1268 => unreachable,
11771269
1178 .array => self.cast(Payload.Array).?.len,1270 .array => self.cast(Payload.Array).?.len,
1271 .array_sentinel => self.cast(Payload.ArraySentinel).?.len,
1272 .array_u8 => self.cast(Payload.Array_u8).?.len,
1179 .array_u8_sentinel_0 => self.cast(Payload.Array_u8_Sentinel0).?.len,1273 .array_u8_sentinel_0 => self.cast(Payload.Array_u8_Sentinel0).?.len,
1180 };1274 };
1181 }1275 }
...@@ -1230,9 +1324,11 @@ pub const Type = extern union {...@@ -1230,9 +1324,11 @@ pub const Type = extern union {
1230 .optional,1324 .optional,
1231 .optional_single_mut_pointer,1325 .optional_single_mut_pointer,
1232 .optional_single_const_pointer,1326 .optional_single_const_pointer,
1327 .enum_literal,
1233 => unreachable,1328 => unreachable,
12341329
1235 .array => return null,1330 .array, .array_u8 => return null,
1331 .array_sentinel => return self.cast(Payload.ArraySentinel).?.sentinel,
1236 .array_u8_sentinel_0 => return Value.initTag(.zero),1332 .array_u8_sentinel_0 => return Value.initTag(.zero),
1237 };1333 };
1238 }1334 }
...@@ -1266,10 +1362,12 @@ pub const Type = extern union {...@@ -1266,10 +1362,12 @@ pub const Type = extern union {
1266 .fn_ccc_void_no_args,1362 .fn_ccc_void_no_args,
1267 .function,1363 .function,
1268 .array,1364 .array,
1365 .array_sentinel,
1366 .array_u8,
1367 .array_u8_sentinel_0,
1269 .single_const_pointer,1368 .single_const_pointer,
1270 .single_mut_pointer,1369 .single_mut_pointer,
1271 .single_const_pointer_to_comptime_int,1370 .single_const_pointer_to_comptime_int,
1272 .array_u8_sentinel_0,
1273 .const_slice_u8,1371 .const_slice_u8,
1274 .int_unsigned,1372 .int_unsigned,
1275 .u8,1373 .u8,
...@@ -1284,6 +1382,7 @@ pub const Type = extern union {...@@ -1284,6 +1382,7 @@ pub const Type = extern union {
1284 .optional,1382 .optional,
1285 .optional_single_mut_pointer,1383 .optional_single_mut_pointer,
1286 .optional_single_const_pointer,1384 .optional_single_const_pointer,
1385 .enum_literal,
1287 => false,1386 => false,
12881387
1289 .int_signed,1388 .int_signed,
...@@ -1324,10 +1423,12 @@ pub const Type = extern union {...@@ -1324,10 +1423,12 @@ pub const Type = extern union {
1324 .fn_ccc_void_no_args,1423 .fn_ccc_void_no_args,
1325 .function,1424 .function,
1326 .array,1425 .array,
1426 .array_sentinel,
1427 .array_u8,
1428 .array_u8_sentinel_0,
1327 .single_const_pointer,1429 .single_const_pointer,
1328 .single_mut_pointer,1430 .single_mut_pointer,
1329 .single_const_pointer_to_comptime_int,1431 .single_const_pointer_to_comptime_int,
1330 .array_u8_sentinel_0,
1331 .const_slice_u8,1432 .const_slice_u8,
1332 .int_signed,1433 .int_signed,
1333 .i8,1434 .i8,
...@@ -1342,6 +1443,7 @@ pub const Type = extern union {...@@ -1342,6 +1443,7 @@ pub const Type = extern union {
1342 .optional,1443 .optional,
1343 .optional_single_mut_pointer,1444 .optional_single_mut_pointer,
1344 .optional_single_const_pointer,1445 .optional_single_const_pointer,
1446 .enum_literal,
1345 => false,1447 => false,
13461448
1347 .int_unsigned,1449 .int_unsigned,
...@@ -1382,14 +1484,17 @@ pub const Type = extern union {...@@ -1382,14 +1484,17 @@ pub const Type = extern union {
1382 .fn_ccc_void_no_args,1484 .fn_ccc_void_no_args,
1383 .function,1485 .function,
1384 .array,1486 .array,
1487 .array_sentinel,
1488 .array_u8,
1489 .array_u8_sentinel_0,
1385 .single_const_pointer,1490 .single_const_pointer,
1386 .single_mut_pointer,1491 .single_mut_pointer,
1387 .single_const_pointer_to_comptime_int,1492 .single_const_pointer_to_comptime_int,
1388 .array_u8_sentinel_0,
1389 .const_slice_u8,1493 .const_slice_u8,
1390 .optional,1494 .optional,
1391 .optional_single_mut_pointer,1495 .optional_single_mut_pointer,
1392 .optional_single_const_pointer,1496 .optional_single_const_pointer,
1497 .enum_literal,
1393 => unreachable,1498 => unreachable,
13941499
1395 .int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits },1500 .int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits },
...@@ -1438,10 +1543,12 @@ pub const Type = extern union {...@@ -1438,10 +1543,12 @@ pub const Type = extern union {
1438 .fn_ccc_void_no_args,1543 .fn_ccc_void_no_args,
1439 .function,1544 .function,
1440 .array,1545 .array,
1546 .array_sentinel,
1547 .array_u8,
1548 .array_u8_sentinel_0,
1441 .single_const_pointer,1549 .single_const_pointer,
1442 .single_mut_pointer,1550 .single_mut_pointer,
1443 .single_const_pointer_to_comptime_int,1551 .single_const_pointer_to_comptime_int,
1444 .array_u8_sentinel_0,
1445 .const_slice_u8,1552 .const_slice_u8,
1446 .int_unsigned,1553 .int_unsigned,
1447 .int_signed,1554 .int_signed,
...@@ -1456,6 +1563,7 @@ pub const Type = extern union {...@@ -1456,6 +1563,7 @@ pub const Type = extern union {
1456 .optional,1563 .optional,
1457 .optional_single_mut_pointer,1564 .optional_single_mut_pointer,
1458 .optional_single_const_pointer,1565 .optional_single_const_pointer,
1566 .enum_literal,
1459 => false,1567 => false,
14601568
1461 .usize,1569 .usize,
...@@ -1523,10 +1631,12 @@ pub const Type = extern union {...@@ -1523,10 +1631,12 @@ pub const Type = extern union {
1523 .@"null",1631 .@"null",
1524 .@"undefined",1632 .@"undefined",
1525 .array,1633 .array,
1634 .array_sentinel,
1635 .array_u8,
1636 .array_u8_sentinel_0,
1526 .single_const_pointer,1637 .single_const_pointer,
1527 .single_mut_pointer,1638 .single_mut_pointer,
1528 .single_const_pointer_to_comptime_int,1639 .single_const_pointer_to_comptime_int,
1529 .array_u8_sentinel_0,
1530 .const_slice_u8,1640 .const_slice_u8,
1531 .u8,1641 .u8,
1532 .i8,1642 .i8,
...@@ -1551,6 +1661,7 @@ pub const Type = extern union {...@@ -1551,6 +1661,7 @@ pub const Type = extern union {
1551 .optional,1661 .optional,
1552 .optional_single_mut_pointer,1662 .optional_single_mut_pointer,
1553 .optional_single_const_pointer,1663 .optional_single_const_pointer,
1664 .enum_literal,
1554 => unreachable,1665 => unreachable,
1555 };1666 };
1556 }1667 }
...@@ -1584,10 +1695,12 @@ pub const Type = extern union {...@@ -1584,10 +1695,12 @@ pub const Type = extern union {
1584 .@"null",1695 .@"null",
1585 .@"undefined",1696 .@"undefined",
1586 .array,1697 .array,
1698 .array_sentinel,
1699 .array_u8,
1700 .array_u8_sentinel_0,
1587 .single_const_pointer,1701 .single_const_pointer,
1588 .single_mut_pointer,1702 .single_mut_pointer,
1589 .single_const_pointer_to_comptime_int,1703 .single_const_pointer_to_comptime_int,
1590 .array_u8_sentinel_0,
1591 .const_slice_u8,1704 .const_slice_u8,
1592 .u8,1705 .u8,
1593 .i8,1706 .i8,
...@@ -1612,6 +1725,7 @@ pub const Type = extern union {...@@ -1612,6 +1725,7 @@ pub const Type = extern union {
1612 .optional,1725 .optional,
1613 .optional_single_mut_pointer,1726 .optional_single_mut_pointer,
1614 .optional_single_const_pointer,1727 .optional_single_const_pointer,
1728 .enum_literal,
1615 => unreachable,1729 => unreachable,
1616 }1730 }
1617 }1731 }
...@@ -1644,10 +1758,12 @@ pub const Type = extern union {...@@ -1644,10 +1758,12 @@ pub const Type = extern union {
1644 .@"null",1758 .@"null",
1645 .@"undefined",1759 .@"undefined",
1646 .array,1760 .array,
1761 .array_sentinel,
1762 .array_u8,
1763 .array_u8_sentinel_0,
1647 .single_const_pointer,1764 .single_const_pointer,
1648 .single_mut_pointer,1765 .single_mut_pointer,
1649 .single_const_pointer_to_comptime_int,1766 .single_const_pointer_to_comptime_int,
1650 .array_u8_sentinel_0,
1651 .const_slice_u8,1767 .const_slice_u8,
1652 .u8,1768 .u8,
1653 .i8,1769 .i8,
...@@ -1672,6 +1788,7 @@ pub const Type = extern union {...@@ -1672,6 +1788,7 @@ pub const Type = extern union {
1672 .optional,1788 .optional,
1673 .optional_single_mut_pointer,1789 .optional_single_mut_pointer,
1674 .optional_single_const_pointer,1790 .optional_single_const_pointer,
1791 .enum_literal,
1675 => unreachable,1792 => unreachable,
1676 }1793 }
1677 }1794 }
...@@ -1704,10 +1821,12 @@ pub const Type = extern union {...@@ -1704,10 +1821,12 @@ pub const Type = extern union {
1704 .@"null",1821 .@"null",
1705 .@"undefined",1822 .@"undefined",
1706 .array,1823 .array,
1824 .array_sentinel,
1825 .array_u8,
1826 .array_u8_sentinel_0,
1707 .single_const_pointer,1827 .single_const_pointer,
1708 .single_mut_pointer,1828 .single_mut_pointer,
1709 .single_const_pointer_to_comptime_int,1829 .single_const_pointer_to_comptime_int,
1710 .array_u8_sentinel_0,
1711 .const_slice_u8,1830 .const_slice_u8,
1712 .u8,1831 .u8,
1713 .i8,1832 .i8,
...@@ -1732,6 +1851,7 @@ pub const Type = extern union {...@@ -1732,6 +1851,7 @@ pub const Type = extern union {
1732 .optional,1851 .optional,
1733 .optional_single_mut_pointer,1852 .optional_single_mut_pointer,
1734 .optional_single_const_pointer,1853 .optional_single_const_pointer,
1854 .enum_literal,
1735 => unreachable,1855 => unreachable,
1736 };1856 };
1737 }1857 }
...@@ -1761,10 +1881,12 @@ pub const Type = extern union {...@@ -1761,10 +1881,12 @@ pub const Type = extern union {
1761 .@"null",1881 .@"null",
1762 .@"undefined",1882 .@"undefined",
1763 .array,1883 .array,
1884 .array_sentinel,
1885 .array_u8,
1886 .array_u8_sentinel_0,
1764 .single_const_pointer,1887 .single_const_pointer,
1765 .single_mut_pointer,1888 .single_mut_pointer,
1766 .single_const_pointer_to_comptime_int,1889 .single_const_pointer_to_comptime_int,
1767 .array_u8_sentinel_0,
1768 .const_slice_u8,1890 .const_slice_u8,
1769 .u8,1891 .u8,
1770 .i8,1892 .i8,
...@@ -1789,6 +1911,7 @@ pub const Type = extern union {...@@ -1789,6 +1911,7 @@ pub const Type = extern union {
1789 .optional,1911 .optional,
1790 .optional_single_mut_pointer,1912 .optional_single_mut_pointer,
1791 .optional_single_const_pointer,1913 .optional_single_const_pointer,
1914 .enum_literal,
1792 => unreachable,1915 => unreachable,
1793 };1916 };
1794 }1917 }
...@@ -1818,10 +1941,12 @@ pub const Type = extern union {...@@ -1818,10 +1941,12 @@ pub const Type = extern union {
1818 .@"null",1941 .@"null",
1819 .@"undefined",1942 .@"undefined",
1820 .array,1943 .array,
1944 .array_sentinel,
1945 .array_u8,
1946 .array_u8_sentinel_0,
1821 .single_const_pointer,1947 .single_const_pointer,
1822 .single_mut_pointer,1948 .single_mut_pointer,
1823 .single_const_pointer_to_comptime_int,1949 .single_const_pointer_to_comptime_int,
1824 .array_u8_sentinel_0,
1825 .const_slice_u8,1950 .const_slice_u8,
1826 .u8,1951 .u8,
1827 .i8,1952 .i8,
...@@ -1846,6 +1971,7 @@ pub const Type = extern union {...@@ -1846,6 +1971,7 @@ pub const Type = extern union {
1846 .optional,1971 .optional,
1847 .optional_single_mut_pointer,1972 .optional_single_mut_pointer,
1848 .optional_single_const_pointer,1973 .optional_single_const_pointer,
1974 .enum_literal,
1849 => unreachable,1975 => unreachable,
1850 };1976 };
1851 }1977 }
...@@ -1895,14 +2021,17 @@ pub const Type = extern union {...@@ -1895,14 +2021,17 @@ pub const Type = extern union {
1895 .fn_ccc_void_no_args,2021 .fn_ccc_void_no_args,
1896 .function,2022 .function,
1897 .array,2023 .array,
2024 .array_sentinel,
2025 .array_u8,
2026 .array_u8_sentinel_0,
1898 .single_const_pointer,2027 .single_const_pointer,
1899 .single_mut_pointer,2028 .single_mut_pointer,
1900 .single_const_pointer_to_comptime_int,2029 .single_const_pointer_to_comptime_int,
1901 .array_u8_sentinel_0,
1902 .const_slice_u8,2030 .const_slice_u8,
1903 .optional,2031 .optional,
1904 .optional_single_mut_pointer,2032 .optional_single_mut_pointer,
1905 .optional_single_const_pointer,2033 .optional_single_const_pointer,
2034 .enum_literal,
1906 => false,2035 => false,
1907 };2036 };
1908 }2037 }
...@@ -1944,12 +2073,14 @@ pub const Type = extern union {...@@ -1944,12 +2073,14 @@ pub const Type = extern union {
1944 .fn_ccc_void_no_args,2073 .fn_ccc_void_no_args,
1945 .function,2074 .function,
1946 .single_const_pointer_to_comptime_int,2075 .single_const_pointer_to_comptime_int,
2076 .array_sentinel,
1947 .array_u8_sentinel_0,2077 .array_u8_sentinel_0,
1948 .const_slice_u8,2078 .const_slice_u8,
1949 .c_void,2079 .c_void,
1950 .optional,2080 .optional,
1951 .optional_single_mut_pointer,2081 .optional_single_mut_pointer,
1952 .optional_single_const_pointer,2082 .optional_single_const_pointer,
2083 .enum_literal,
1953 => return null,2084 => return null,
19542085
1955 .void => return Value.initTag(.void_value),2086 .void => return Value.initTag(.void_value),
...@@ -1971,11 +2102,10 @@ pub const Type = extern union {...@@ -1971,11 +2102,10 @@ pub const Type = extern union {
1971 return null;2102 return null;
1972 }2103 }
1973 },2104 },
1974 .array => {2105 .array, .array_u8 => {
1975 const array = ty.cast(Payload.Array).?;2106 if (ty.arrayLen() == 0)
1976 if (array.len == 0)
1977 return Value.initTag(.empty_array);2107 return Value.initTag(.empty_array);
1978 ty = array.elem_type;2108 ty = ty.elemType();
1979 continue;2109 continue;
1980 },2110 },
1981 .single_const_pointer, .single_mut_pointer => {2111 .single_const_pointer, .single_mut_pointer => {
...@@ -2022,7 +2152,6 @@ pub const Type = extern union {...@@ -2022,7 +2152,6 @@ pub const Type = extern union {
2022 .fn_ccc_void_no_args,2152 .fn_ccc_void_no_args,
2023 .function,2153 .function,
2024 .single_const_pointer_to_comptime_int,2154 .single_const_pointer_to_comptime_int,
2025 .array_u8_sentinel_0,
2026 .const_slice_u8,2155 .const_slice_u8,
2027 .c_void,2156 .c_void,
2028 .void,2157 .void,
...@@ -2032,11 +2161,15 @@ pub const Type = extern union {...@@ -2032,11 +2161,15 @@ pub const Type = extern union {
2032 .int_unsigned,2161 .int_unsigned,
2033 .int_signed,2162 .int_signed,
2034 .array,2163 .array,
2164 .array_sentinel,
2165 .array_u8,
2166 .array_u8_sentinel_0,
2035 .single_const_pointer,2167 .single_const_pointer,
2036 .single_mut_pointer,2168 .single_mut_pointer,
2037 .optional,2169 .optional,
2038 .optional_single_mut_pointer,2170 .optional_single_mut_pointer,
2039 .optional_single_const_pointer,2171 .optional_single_const_pointer,
2172 .enum_literal,
2040 => return false,2173 => return false,
2041 };2174 };
2042 }2175 }
...@@ -2080,6 +2213,7 @@ pub const Type = extern union {...@@ -2080,6 +2213,7 @@ pub const Type = extern union {
2080 comptime_int,2213 comptime_int,
2081 comptime_float,2214 comptime_float,
2082 noreturn,2215 noreturn,
2216 enum_literal,
2083 @"null",2217 @"null",
2084 @"undefined",2218 @"undefined",
2085 fn_noreturn_no_args,2219 fn_noreturn_no_args,
...@@ -2090,8 +2224,10 @@ pub const Type = extern union {...@@ -2090,8 +2224,10 @@ pub const Type = extern union {
2090 const_slice_u8, // See last_no_payload_tag below.2224 const_slice_u8, // See last_no_payload_tag below.
2091 // After this, the tag requires a payload.2225 // After this, the tag requires a payload.
20922226
2227 array_u8,
2093 array_u8_sentinel_0,2228 array_u8_sentinel_0,
2094 array,2229 array,
2230 array_sentinel,
2095 single_const_pointer,2231 single_const_pointer,
2096 single_mut_pointer,2232 single_mut_pointer,
2097 int_signed,2233 int_signed,
...@@ -2114,11 +2250,25 @@ pub const Type = extern union {...@@ -2114,11 +2250,25 @@ pub const Type = extern union {
2114 len: u64,2250 len: u64,
2115 };2251 };
21162252
2253 pub const Array_u8 = struct {
2254 base: Payload = Payload{ .tag = .array_u8 },
2255
2256 len: u64,
2257 };
2258
2117 pub const Array = struct {2259 pub const Array = struct {
2118 base: Payload = Payload{ .tag = .array },2260 base: Payload = Payload{ .tag = .array },
21192261
2262 len: u64,
2120 elem_type: Type,2263 elem_type: Type,
2264 };
2265
2266 pub const ArraySentinel = struct {
2267 base: Payload = Payload{ .tag = .array_sentinel },
2268
2121 len: u64,2269 len: u64,
2270 sentinel: Value,
2271 elem_type: Type,
2122 };2272 };
21232273
2124 pub const Pointer = struct {2274 pub const Pointer = struct {
src-self-hosted/value.zig+33-2
...@@ -60,6 +60,7 @@ pub const Value = extern union {...@@ -60,6 +60,7 @@ pub const Value = extern union {
60 fn_ccc_void_no_args_type,60 fn_ccc_void_no_args_type,
61 single_const_pointer_to_comptime_int_type,61 single_const_pointer_to_comptime_int_type,
62 const_slice_u8_type,62 const_slice_u8_type,
63 enum_literal_type,
6364
64 undef,65 undef,
65 zero,66 zero,
...@@ -87,6 +88,7 @@ pub const Value = extern union {...@@ -87,6 +88,7 @@ pub const Value = extern union {
87 float_32,88 float_32,
88 float_64,89 float_64,
89 float_128,90 float_128,
91 enum_literal,
9092
91 pub const last_no_payload_tag = Tag.bool_false;93 pub const last_no_payload_tag = Tag.bool_false;
92 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;94 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
...@@ -164,6 +166,7 @@ pub const Value = extern union {...@@ -164,6 +166,7 @@ pub const Value = extern union {
164 .fn_ccc_void_no_args_type,166 .fn_ccc_void_no_args_type,
165 .single_const_pointer_to_comptime_int_type,167 .single_const_pointer_to_comptime_int_type,
166 .const_slice_u8_type,168 .const_slice_u8_type,
169 .enum_literal_type,
167 .undef,170 .undef,
168 .zero,171 .zero,
169 .void_value,172 .void_value,
...@@ -213,7 +216,7 @@ pub const Value = extern union {...@@ -213,7 +216,7 @@ pub const Value = extern union {
213 };216 };
214 return Value{ .ptr_otherwise = &new_payload.base };217 return Value{ .ptr_otherwise = &new_payload.base };
215 },218 },
216 .bytes => return self.copyPayloadShallow(allocator, Payload.Bytes),219 .enum_literal, .bytes => return self.copyPayloadShallow(allocator, Payload.Bytes),
217 .repeated => {220 .repeated => {
218 const payload = @fieldParentPtr(Payload.Repeated, "base", self.ptr_otherwise);221 const payload = @fieldParentPtr(Payload.Repeated, "base", self.ptr_otherwise);
219 const new_payload = try allocator.create(Payload.Repeated);222 const new_payload = try allocator.create(Payload.Repeated);
...@@ -285,6 +288,7 @@ pub const Value = extern union {...@@ -285,6 +288,7 @@ pub const Value = extern union {
285 .fn_ccc_void_no_args_type => return out_stream.writeAll("fn() callconv(.C) void"),288 .fn_ccc_void_no_args_type => return out_stream.writeAll("fn() callconv(.C) void"),
286 .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),289 .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),
287 .const_slice_u8_type => return out_stream.writeAll("[]const u8"),290 .const_slice_u8_type => return out_stream.writeAll("[]const u8"),
291 .enum_literal_type => return out_stream.writeAll("@TypeOf(.EnumLiteral)"),
288292
289 .null_value => return out_stream.writeAll("null"),293 .null_value => return out_stream.writeAll("null"),
290 .undef => return out_stream.writeAll("undefined"),294 .undef => return out_stream.writeAll("undefined"),
...@@ -318,7 +322,7 @@ pub const Value = extern union {...@@ -318,7 +322,7 @@ pub const Value = extern union {
318 val = elem_ptr.array_ptr;322 val = elem_ptr.array_ptr;
319 },323 },
320 .empty_array => return out_stream.writeAll(".{}"),324 .empty_array => return out_stream.writeAll(".{}"),
321 .bytes => return std.zig.renderStringLiteral(self.cast(Payload.Bytes).?.data, out_stream),325 .enum_literal, .bytes => return std.zig.renderStringLiteral(self.cast(Payload.Bytes).?.data, out_stream),
322 .repeated => {326 .repeated => {
323 try out_stream.writeAll("(repeated) ");327 try out_stream.writeAll("(repeated) ");
324 val = val.cast(Payload.Repeated).?.val;328 val = val.cast(Payload.Repeated).?.val;
...@@ -391,6 +395,7 @@ pub const Value = extern union {...@@ -391,6 +395,7 @@ pub const Value = extern union {
391 .fn_ccc_void_no_args_type => Type.initTag(.fn_ccc_void_no_args),395 .fn_ccc_void_no_args_type => Type.initTag(.fn_ccc_void_no_args),
392 .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int),396 .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int),
393 .const_slice_u8_type => Type.initTag(.const_slice_u8),397 .const_slice_u8_type => Type.initTag(.const_slice_u8),
398 .enum_literal_type => Type.initTag(.enum_literal),
394399
395 .undef,400 .undef,
396 .zero,401 .zero,
...@@ -414,6 +419,7 @@ pub const Value = extern union {...@@ -414,6 +419,7 @@ pub const Value = extern union {
414 .float_32,419 .float_32,
415 .float_64,420 .float_64,
416 .float_128,421 .float_128,
422 .enum_literal,
417 => unreachable,423 => unreachable,
418 };424 };
419 }425 }
...@@ -462,6 +468,7 @@ pub const Value = extern union {...@@ -462,6 +468,7 @@ pub const Value = extern union {
462 .fn_ccc_void_no_args_type,468 .fn_ccc_void_no_args_type,
463 .single_const_pointer_to_comptime_int_type,469 .single_const_pointer_to_comptime_int_type,
464 .const_slice_u8_type,470 .const_slice_u8_type,
471 .enum_literal_type,
465 .null_value,472 .null_value,
466 .function,473 .function,
467 .ref_val,474 .ref_val,
...@@ -476,6 +483,7 @@ pub const Value = extern union {...@@ -476,6 +483,7 @@ pub const Value = extern union {
476 .void_value,483 .void_value,
477 .unreachable_value,484 .unreachable_value,
478 .empty_array,485 .empty_array,
486 .enum_literal,
479 => unreachable,487 => unreachable,
480488
481 .undef => unreachable,489 .undef => unreachable,
...@@ -537,6 +545,7 @@ pub const Value = extern union {...@@ -537,6 +545,7 @@ pub const Value = extern union {
537 .fn_ccc_void_no_args_type,545 .fn_ccc_void_no_args_type,
538 .single_const_pointer_to_comptime_int_type,546 .single_const_pointer_to_comptime_int_type,
539 .const_slice_u8_type,547 .const_slice_u8_type,
548 .enum_literal_type,
540 .null_value,549 .null_value,
541 .function,550 .function,
542 .ref_val,551 .ref_val,
...@@ -551,6 +560,7 @@ pub const Value = extern union {...@@ -551,6 +560,7 @@ pub const Value = extern union {
551 .void_value,560 .void_value,
552 .unreachable_value,561 .unreachable_value,
553 .empty_array,562 .empty_array,
563 .enum_literal,
554 => unreachable,564 => unreachable,
555565
556 .undef => unreachable,566 .undef => unreachable,
...@@ -612,6 +622,7 @@ pub const Value = extern union {...@@ -612,6 +622,7 @@ pub const Value = extern union {
612 .fn_ccc_void_no_args_type,622 .fn_ccc_void_no_args_type,
613 .single_const_pointer_to_comptime_int_type,623 .single_const_pointer_to_comptime_int_type,
614 .const_slice_u8_type,624 .const_slice_u8_type,
625 .enum_literal_type,
615 .null_value,626 .null_value,
616 .function,627 .function,
617 .ref_val,628 .ref_val,
...@@ -626,6 +637,7 @@ pub const Value = extern union {...@@ -626,6 +637,7 @@ pub const Value = extern union {
626 .void_value,637 .void_value,
627 .unreachable_value,638 .unreachable_value,
628 .empty_array,639 .empty_array,
640 .enum_literal,
629 => unreachable,641 => unreachable,
630642
631 .undef => unreachable,643 .undef => unreachable,
...@@ -713,6 +725,7 @@ pub const Value = extern union {...@@ -713,6 +725,7 @@ pub const Value = extern union {
713 .fn_ccc_void_no_args_type,725 .fn_ccc_void_no_args_type,
714 .single_const_pointer_to_comptime_int_type,726 .single_const_pointer_to_comptime_int_type,
715 .const_slice_u8_type,727 .const_slice_u8_type,
728 .enum_literal_type,
716 .null_value,729 .null_value,
717 .function,730 .function,
718 .ref_val,731 .ref_val,
...@@ -728,6 +741,7 @@ pub const Value = extern union {...@@ -728,6 +741,7 @@ pub const Value = extern union {
728 .void_value,741 .void_value,
729 .unreachable_value,742 .unreachable_value,
730 .empty_array,743 .empty_array,
744 .enum_literal,
731 => unreachable,745 => unreachable,
732746
733 .zero,747 .zero,
...@@ -793,6 +807,7 @@ pub const Value = extern union {...@@ -793,6 +807,7 @@ pub const Value = extern union {
793 .fn_ccc_void_no_args_type,807 .fn_ccc_void_no_args_type,
794 .single_const_pointer_to_comptime_int_type,808 .single_const_pointer_to_comptime_int_type,
795 .const_slice_u8_type,809 .const_slice_u8_type,
810 .enum_literal_type,
796 .null_value,811 .null_value,
797 .function,812 .function,
798 .ref_val,813 .ref_val,
...@@ -807,6 +822,7 @@ pub const Value = extern union {...@@ -807,6 +822,7 @@ pub const Value = extern union {
807 .void_value,822 .void_value,
808 .unreachable_value,823 .unreachable_value,
809 .empty_array,824 .empty_array,
825 .enum_literal,
810 => unreachable,826 => unreachable,
811827
812 .zero,828 .zero,
...@@ -953,6 +969,7 @@ pub const Value = extern union {...@@ -953,6 +969,7 @@ pub const Value = extern union {
953 .fn_ccc_void_no_args_type,969 .fn_ccc_void_no_args_type,
954 .single_const_pointer_to_comptime_int_type,970 .single_const_pointer_to_comptime_int_type,
955 .const_slice_u8_type,971 .const_slice_u8_type,
972 .enum_literal_type,
956 .bool_true,973 .bool_true,
957 .bool_false,974 .bool_false,
958 .null_value,975 .null_value,
...@@ -970,6 +987,7 @@ pub const Value = extern union {...@@ -970,6 +987,7 @@ pub const Value = extern union {
970 .empty_array,987 .empty_array,
971 .void_value,988 .void_value,
972 .unreachable_value,989 .unreachable_value,
990 .enum_literal,
973 => unreachable,991 => unreachable,
974992
975 .zero => false,993 .zero => false,
...@@ -1025,6 +1043,7 @@ pub const Value = extern union {...@@ -1025,6 +1043,7 @@ pub const Value = extern union {
1025 .fn_ccc_void_no_args_type,1043 .fn_ccc_void_no_args_type,
1026 .single_const_pointer_to_comptime_int_type,1044 .single_const_pointer_to_comptime_int_type,
1027 .const_slice_u8_type,1045 .const_slice_u8_type,
1046 .enum_literal_type,
1028 .null_value,1047 .null_value,
1029 .function,1048 .function,
1030 .ref_val,1049 .ref_val,
...@@ -1036,6 +1055,7 @@ pub const Value = extern union {...@@ -1036,6 +1055,7 @@ pub const Value = extern union {
1036 .void_value,1055 .void_value,
1037 .unreachable_value,1056 .unreachable_value,
1038 .empty_array,1057 .empty_array,
1058 .enum_literal,
1039 => unreachable,1059 => unreachable,
10401060
1041 .zero,1061 .zero,
...@@ -1102,6 +1122,11 @@ pub const Value = extern union {...@@ -1102,6 +1122,11 @@ pub const Value = extern union {
1102 }1122 }
11031123
1104 pub fn eql(a: Value, b: Value) bool {1124 pub fn eql(a: Value, b: Value) bool {
1125 if (a.tag() == b.tag() and a.tag() == .enum_literal) {
1126 const a_name = @fieldParentPtr(Payload.Bytes, "base", a.ptr_otherwise).data;
1127 const b_name = @fieldParentPtr(Payload.Bytes, "base", b.ptr_otherwise).data;
1128 return std.mem.eql(u8, a_name, b_name);
1129 }
1105 // TODO non numerical comparisons1130 // TODO non numerical comparisons
1106 return compare(a, .eq, b);1131 return compare(a, .eq, b);
1107 }1132 }
...@@ -1151,6 +1176,7 @@ pub const Value = extern union {...@@ -1151,6 +1176,7 @@ pub const Value = extern union {
1151 .fn_ccc_void_no_args_type,1176 .fn_ccc_void_no_args_type,
1152 .single_const_pointer_to_comptime_int_type,1177 .single_const_pointer_to_comptime_int_type,
1153 .const_slice_u8_type,1178 .const_slice_u8_type,
1179 .enum_literal_type,
1154 .zero,1180 .zero,
1155 .bool_true,1181 .bool_true,
1156 .bool_false,1182 .bool_false,
...@@ -1170,6 +1196,7 @@ pub const Value = extern union {...@@ -1170,6 +1196,7 @@ pub const Value = extern union {
1170 .void_value,1196 .void_value,
1171 .unreachable_value,1197 .unreachable_value,
1172 .empty_array,1198 .empty_array,
1199 .enum_literal,
1173 => unreachable,1200 => unreachable,
11741201
1175 .ref_val => self.cast(Payload.RefVal).?.val,1202 .ref_val => self.cast(Payload.RefVal).?.val,
...@@ -1227,6 +1254,7 @@ pub const Value = extern union {...@@ -1227,6 +1254,7 @@ pub const Value = extern union {
1227 .fn_ccc_void_no_args_type,1254 .fn_ccc_void_no_args_type,
1228 .single_const_pointer_to_comptime_int_type,1255 .single_const_pointer_to_comptime_int_type,
1229 .const_slice_u8_type,1256 .const_slice_u8_type,
1257 .enum_literal_type,
1230 .zero,1258 .zero,
1231 .bool_true,1259 .bool_true,
1232 .bool_false,1260 .bool_false,
...@@ -1246,6 +1274,7 @@ pub const Value = extern union {...@@ -1246,6 +1274,7 @@ pub const Value = extern union {
1246 .float_128,1274 .float_128,
1247 .void_value,1275 .void_value,
1248 .unreachable_value,1276 .unreachable_value,
1277 .enum_literal,
1249 => unreachable,1278 => unreachable,
12501279
1251 .empty_array => unreachable, // out of bounds array index1280 .empty_array => unreachable, // out of bounds array index
...@@ -1320,6 +1349,7 @@ pub const Value = extern union {...@@ -1320,6 +1349,7 @@ pub const Value = extern union {
1320 .fn_ccc_void_no_args_type,1349 .fn_ccc_void_no_args_type,
1321 .single_const_pointer_to_comptime_int_type,1350 .single_const_pointer_to_comptime_int_type,
1322 .const_slice_u8_type,1351 .const_slice_u8_type,
1352 .enum_literal_type,
1323 .zero,1353 .zero,
1324 .empty_array,1354 .empty_array,
1325 .bool_true,1355 .bool_true,
...@@ -1339,6 +1369,7 @@ pub const Value = extern union {...@@ -1339,6 +1369,7 @@ pub const Value = extern union {
1339 .float_64,1369 .float_64,
1340 .float_128,1370 .float_128,
1341 .void_value,1371 .void_value,
1372 .enum_literal,
1342 => false,1373 => false,
13431374
1344 .undef => unreachable,1375 .undef => unreachable,
src-self-hosted/zir.zig+47-5
...@@ -47,6 +47,10 @@ pub const Inst = struct {...@@ -47,6 +47,10 @@ pub const Inst = struct {
47 array_cat,47 array_cat,
48 /// Array multiplication `a ** b`48 /// Array multiplication `a ** b`
49 array_mul,49 array_mul,
50 /// Create an array type
51 array_type,
52 /// Create an array type with sentinel
53 array_type_sentinel,
50 /// Function parameter value. These must be first in a function's main block,54 /// Function parameter value. These must be first in a function's main block,
51 /// in respective order with the parameters.55 /// in respective order with the parameters.
52 arg,56 arg,
...@@ -58,11 +62,11 @@ pub const Inst = struct {...@@ -58,11 +62,11 @@ pub const Inst = struct {
58 bitand,62 bitand,
59 /// TODO delete this instruction, it has no purpose.63 /// TODO delete this instruction, it has no purpose.
60 bitcast,64 bitcast,
61 /// An arbitrary typed pointer, which is to be used as an L-Value, is pointer-casted65 /// An arbitrary typed pointer is pointer-casted to a new Pointer.
62 /// to a new L-Value. The destination type is given by LHS. The cast is to be evaluated66 /// The destination type is given by LHS. The cast is to be evaluated
63 /// as if it were a bit-cast operation from the operand pointer element type to the67 /// as if it were a bit-cast operation from the operand pointer element type to the
64 /// provided destination type.68 /// provided destination type.
65 bitcast_lvalue,69 bitcast_ref,
66 /// A typed result location pointer is bitcasted to a new result location pointer.70 /// A typed result location pointer is bitcasted to a new result location pointer.
67 /// The new result location pointer has an inferred type.71 /// The new result location pointer has an inferred type.
68 bitcast_result_ptr,72 bitcast_result_ptr,
...@@ -225,6 +229,10 @@ pub const Inst = struct {...@@ -225,6 +229,10 @@ pub const Inst = struct {
225 unwrap_err_safe,229 unwrap_err_safe,
226 /// Same as previous, but without safety checks. Used for orelse, if and while230 /// Same as previous, but without safety checks. Used for orelse, if and while
227 unwrap_err_unsafe,231 unwrap_err_unsafe,
232 /// Takes a *E!T and raises a compiler error if T != void
233 ensure_err_payload_void,
234 /// Enum literal
235 enum_literal,
228236
229 pub fn Type(tag: Tag) type {237 pub fn Type(tag: Tag) type {
230 return switch (tag) {238 return switch (tag) {
...@@ -250,7 +258,7 @@ pub const Inst = struct {...@@ -250,7 +258,7 @@ pub const Inst = struct {
250 .ensure_result_non_error,258 .ensure_result_non_error,
251 .bitcast_result_ptr,259 .bitcast_result_ptr,
252 .ref,260 .ref,
253 .bitcast_lvalue,261 .bitcast_ref,
254 .typeof,262 .typeof,
255 .single_const_ptr_type,263 .single_const_ptr_type,
256 .single_mut_ptr_type,264 .single_mut_ptr_type,
...@@ -259,12 +267,14 @@ pub const Inst = struct {...@@ -259,12 +267,14 @@ pub const Inst = struct {
259 .unwrap_optional_unsafe,267 .unwrap_optional_unsafe,
260 .unwrap_err_safe,268 .unwrap_err_safe,
261 .unwrap_err_unsafe,269 .unwrap_err_unsafe,
270 .ensure_err_payload_void,
262 => UnOp,271 => UnOp,
263272
264 .add,273 .add,
265 .addwrap,274 .addwrap,
266 .array_cat,275 .array_cat,
267 .array_mul,276 .array_mul,
277 .array_type,
268 .bitand,278 .bitand,
269 .bitor,279 .bitor,
270 .div,280 .div,
...@@ -291,6 +301,7 @@ pub const Inst = struct {...@@ -291,6 +301,7 @@ pub const Inst = struct {
291 => BinOp,301 => BinOp,
292302
293 .arg => Arg,303 .arg => Arg,
304 .array_type_sentinel => ArrayTypeSentinel,
294 .block => Block,305 .block => Block,
295 .@"break" => Break,306 .@"break" => Break,
296 .breakvoid => BreakVoid,307 .breakvoid => BreakVoid,
...@@ -317,6 +328,7 @@ pub const Inst = struct {...@@ -317,6 +328,7 @@ pub const Inst = struct {
317 .elemptr => ElemPtr,328 .elemptr => ElemPtr,
318 .condbr => CondBr,329 .condbr => CondBr,
319 .ptr_type => PtrType,330 .ptr_type => PtrType,
331 .enum_literal => EnumLiteral,
320 };332 };
321 }333 }
322334
...@@ -330,12 +342,14 @@ pub const Inst = struct {...@@ -330,12 +342,14 @@ pub const Inst = struct {
330 .alloc_inferred,342 .alloc_inferred,
331 .array_cat,343 .array_cat,
332 .array_mul,344 .array_mul,
345 .array_type,
346 .array_type_sentinel,
333 .arg,347 .arg,
334 .as,348 .as,
335 .@"asm",349 .@"asm",
336 .bitand,350 .bitand,
337 .bitcast,351 .bitcast,
338 .bitcast_lvalue,352 .bitcast_ref,
339 .bitcast_result_ptr,353 .bitcast_result_ptr,
340 .bitor,354 .bitor,
341 .block,355 .block,
...@@ -398,6 +412,8 @@ pub const Inst = struct {...@@ -398,6 +412,8 @@ pub const Inst = struct {
398 .unwrap_err_safe,412 .unwrap_err_safe,
399 .unwrap_err_unsafe,413 .unwrap_err_unsafe,
400 .ptr_type,414 .ptr_type,
415 .ensure_err_payload_void,
416 .enum_literal,
401 => false,417 => false,
402418
403 .@"break",419 .@"break",
...@@ -845,6 +861,28 @@ pub const Inst = struct {...@@ -845,6 +861,28 @@ pub const Inst = struct {
845 sentinel: ?*Inst = null,861 sentinel: ?*Inst = null,
846 },862 },
847 };863 };
864
865 pub const ArrayTypeSentinel = struct {
866 pub const base_tag = Tag.array_type_sentinel;
867 base: Inst,
868
869 positionals: struct {
870 len: *Inst,
871 sentinel: *Inst,
872 elem_type: *Inst,
873 },
874 kw_args: struct {},
875 };
876
877 pub const EnumLiteral = struct {
878 pub const base_tag = Tag.enum_literal;
879 base: Inst,
880
881 positionals: struct {
882 name: []const u8,
883 },
884 kw_args: struct {},
885 };
848};886};
849887
850pub const ErrorMsg = struct {888pub const ErrorMsg = struct {
...@@ -1922,6 +1960,10 @@ const EmitZIR = struct {...@@ -1922,6 +1960,10 @@ const EmitZIR = struct {
1922 return self.emitUnnamedDecl(&str_inst.base);1960 return self.emitUnnamedDecl(&str_inst.base);
1923 },1961 },
1924 .Void => return self.emitPrimitive(src, .void_value),1962 .Void => return self.emitPrimitive(src, .void_value),
1963 .Bool => if (typed_value.val.toBool())
1964 return self.emitPrimitive(src, .@"true")
1965 else
1966 return self.emitPrimitive(src, .@"false"),
1925 else => |t| std.debug.panic("TODO implement emitTypedValue for {}", .{@tagName(t)}),1967 else => |t| std.debug.panic("TODO implement emitTypedValue for {}", .{@tagName(t)}),
1926 }1968 }
1927 }1969 }
src-self-hosted/zir_sema.zig+51-29
...@@ -29,7 +29,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!...@@ -29,7 +29,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
29 .alloc => return analyzeInstAlloc(mod, scope, old_inst.castTag(.alloc).?),29 .alloc => return analyzeInstAlloc(mod, scope, old_inst.castTag(.alloc).?),
30 .alloc_inferred => return analyzeInstAllocInferred(mod, scope, old_inst.castTag(.alloc_inferred).?),30 .alloc_inferred => return analyzeInstAllocInferred(mod, scope, old_inst.castTag(.alloc_inferred).?),
31 .arg => return analyzeInstArg(mod, scope, old_inst.castTag(.arg).?),31 .arg => return analyzeInstArg(mod, scope, old_inst.castTag(.arg).?),
32 .bitcast_lvalue => return analyzeInstBitCastLValue(mod, scope, old_inst.castTag(.bitcast_lvalue).?),32 .bitcast_ref => return analyzeInstBitCastRef(mod, scope, old_inst.castTag(.bitcast_ref).?),
33 .bitcast_result_ptr => return analyzeInstBitCastResultPtr(mod, scope, old_inst.castTag(.bitcast_result_ptr).?),33 .bitcast_result_ptr => return analyzeInstBitCastResultPtr(mod, scope, old_inst.castTag(.bitcast_result_ptr).?),
34 .block => return analyzeInstBlock(mod, scope, old_inst.castTag(.block).?),34 .block => return analyzeInstBlock(mod, scope, old_inst.castTag(.block).?),
35 .@"break" => return analyzeInstBreak(mod, scope, old_inst.castTag(.@"break").?),35 .@"break" => return analyzeInstBreak(mod, scope, old_inst.castTag(.@"break").?),
...@@ -112,6 +112,10 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!...@@ -112,6 +112,10 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
112 .unwrap_optional_unsafe => return analyzeInstUnwrapOptional(mod, scope, old_inst.castTag(.unwrap_optional_unsafe).?, false),112 .unwrap_optional_unsafe => return analyzeInstUnwrapOptional(mod, scope, old_inst.castTag(.unwrap_optional_unsafe).?, false),
113 .unwrap_err_safe => return analyzeInstUnwrapErr(mod, scope, old_inst.castTag(.unwrap_err_safe).?, true),113 .unwrap_err_safe => return analyzeInstUnwrapErr(mod, scope, old_inst.castTag(.unwrap_err_safe).?, true),
114 .unwrap_err_unsafe => return analyzeInstUnwrapErr(mod, scope, old_inst.castTag(.unwrap_err_unsafe).?, false),114 .unwrap_err_unsafe => return analyzeInstUnwrapErr(mod, scope, old_inst.castTag(.unwrap_err_unsafe).?, false),
115 .ensure_err_payload_void => return analyzeInstEnsureErrPayloadVoid(mod, scope, old_inst.castTag(.ensure_err_payload_void).?),
116 .array_type => return analyzeInstArrayType(mod, scope, old_inst.castTag(.array_type).?),
117 .array_type_sentinel => return analyzeInstArrayTypeSentinel(mod, scope, old_inst.castTag(.array_type_sentinel).?),
118 .enum_literal => return analyzeInstEnumLiteral(mod, scope, old_inst.castTag(.enum_literal).?),
115 }119 }
116}120}
117121
...@@ -295,8 +299,8 @@ fn analyzeInstCoerceResultBlockPtr(...@@ -295,8 +299,8 @@ fn analyzeInstCoerceResultBlockPtr(
295 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstCoerceResultBlockPtr", .{});299 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstCoerceResultBlockPtr", .{});
296}300}
297301
298fn analyzeInstBitCastLValue(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {302fn analyzeInstBitCastRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
299 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstBitCastLValue", .{});303 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstBitCastRef", .{});
300}304}
301305
302fn analyzeInstBitCastResultPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {306fn analyzeInstBitCastResultPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
...@@ -361,6 +365,10 @@ fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst....@@ -361,6 +365,10 @@ fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst.
361365
362fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {366fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
363 const var_type = try resolveType(mod, scope, inst.positionals.operand);367 const var_type = try resolveType(mod, scope, inst.positionals.operand);
368 // TODO this should happen only for var allocs
369 if (!var_type.isValidVarType()) {
370 return mod.fail(scope, inst.base.src, "variable of type '{}' must be const or comptime", .{var_type});
371 }
364 const ptr_type = try mod.singlePtrType(scope, inst.base.src, true, var_type);372 const ptr_type = try mod.singlePtrType(scope, inst.base.src, true, var_type);
365 const b = try mod.requireRuntimeBlock(scope, inst.base.src);373 const b = try mod.requireRuntimeBlock(scope, inst.base.src);
366 return mod.addNoOp(b, inst.base.src, ptr_type, .alloc);374 return mod.addNoOp(b, inst.base.src, ptr_type, .alloc);
...@@ -675,31 +683,36 @@ fn analyzeInstIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) I...@@ -675,31 +683,36 @@ fn analyzeInstIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) I
675fn analyzeInstOptionalType(mod: *Module, scope: *Scope, optional: *zir.Inst.UnOp) InnerError!*Inst {683fn analyzeInstOptionalType(mod: *Module, scope: *Scope, optional: *zir.Inst.UnOp) InnerError!*Inst {
676 const child_type = try resolveType(mod, scope, optional.positionals.operand);684 const child_type = try resolveType(mod, scope, optional.positionals.operand);
677685
678 return mod.constType(scope, optional.base.src, Type.initPayload(switch (child_type.tag()) {686 return mod.constType(scope, optional.base.src, try mod.optionalType(scope, child_type));
679 .single_const_pointer => blk: {687}
680 const payload = try scope.arena().create(Type.Payload.Pointer);688
681 payload.* = .{689fn analyzeInstArrayType(mod: *Module, scope: *Scope, array: *zir.Inst.BinOp) InnerError!*Inst {
682 .base = .{ .tag = .optional_single_const_pointer },690 // TODO these should be lazily evaluated
683 .pointee_type = child_type.elemType(),691 const len = try resolveInstConst(mod, scope, array.positionals.lhs);
684 };692 const elem_type = try resolveType(mod, scope, array.positionals.rhs);
685 break :blk &payload.base;693
686 },694 return mod.constType(scope, array.base.src, try mod.arrayType(scope, len.val.toUnsignedInt(), null, elem_type));
687 .single_mut_pointer => blk: {695}
688 const payload = try scope.arena().create(Type.Payload.Pointer);696
689 payload.* = .{697fn analyzeInstArrayTypeSentinel(mod: *Module, scope: *Scope, array: *zir.Inst.ArrayTypeSentinel) InnerError!*Inst {
690 .base = .{ .tag = .optional_single_mut_pointer },698 // TODO these should be lazily evaluated
691 .pointee_type = child_type.elemType(),699 const len = try resolveInstConst(mod, scope, array.positionals.len);
692 };700 const sentinel = try resolveInstConst(mod, scope, array.positionals.sentinel);
693 break :blk &payload.base;701 const elem_type = try resolveType(mod, scope, array.positionals.elem_type);
694 },702
695 else => blk: {703 return mod.constType(scope, array.base.src, try mod.arrayType(scope, len.val.toUnsignedInt(), sentinel.val, elem_type));
696 const payload = try scope.arena().create(Type.Payload.Optional);704}
697 payload.* = .{705
698 .child_type = child_type,706fn analyzeInstEnumLiteral(mod: *Module, scope: *Scope, inst: *zir.Inst.EnumLiteral) InnerError!*Inst {
699 };707 const payload = try scope.arena().create(Value.Payload.Bytes);
700 break :blk &payload.base;708 payload.* = .{
701 },709 .base = .{ .tag = .enum_literal },
702 }));710 .data = try scope.arena().dupe(u8, inst.positionals.name),
711 };
712 return mod.constInst(scope, inst.base.src, .{
713 .ty = Type.initTag(.enum_literal),
714 .val = Value.initPayload(&payload.base),
715 });
703}716}
704717
705fn analyzeInstUnwrapOptional(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp, safety_check: bool) InnerError!*Inst {718fn analyzeInstUnwrapOptional(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp, safety_check: bool) InnerError!*Inst {
...@@ -735,6 +748,10 @@ fn analyzeInstUnwrapErr(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp, saf...@@ -735,6 +748,10 @@ fn analyzeInstUnwrapErr(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp, saf
735 return mod.fail(scope, unwrap.base.src, "TODO implement analyzeInstUnwrapErr", .{});748 return mod.fail(scope, unwrap.base.src, "TODO implement analyzeInstUnwrapErr", .{});
736}749}
737750
751fn analyzeInstEnsureErrPayloadVoid(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp) InnerError!*Inst {
752 return mod.fail(scope, unwrap.base.src, "TODO implement analyzeInstEnsureErrPayloadVoid", .{});
753}
754
738fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst {755fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst {
739 const return_type = try resolveType(mod, scope, fntype.positionals.return_type);756 const return_type = try resolveType(mod, scope, fntype.positionals.return_type);
740757
...@@ -760,7 +777,12 @@ fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) Inne...@@ -760,7 +777,12 @@ fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) Inne
760 const arena = scope.arena();777 const arena = scope.arena();
761 const param_types = try arena.alloc(Type, fntype.positionals.param_types.len);778 const param_types = try arena.alloc(Type, fntype.positionals.param_types.len);
762 for (fntype.positionals.param_types) |param_type, i| {779 for (fntype.positionals.param_types) |param_type, i| {
763 param_types[i] = try resolveType(mod, scope, param_type);780 const resolved = try resolveType(mod, scope, param_type);
781 // TODO skip for comptime params
782 if (!resolved.isValidVarType()) {
783 return mod.fail(scope, param_type.src, "parameter of type '{}' must be declared comptime", .{resolved});
784 }
785 param_types[i] = resolved;
764 }786 }
765787
766 const payload = try arena.create(Type.Payload.Function);788 const payload = try arena.create(Type.Payload.Function);
test/stage2/compare_output.zig+32
...@@ -543,6 +543,38 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -543,6 +543,38 @@ pub fn addCases(ctx: *TestContext) !void {
543 ,543 ,
544 "",544 "",
545 );545 );
546
547 case.addCompareOutput(
548 \\export fn _start() noreturn {
549 \\ const ignore =
550 \\ \\ cool thx
551 \\ \\
552 \\ ;
553 \\ add('ぁ', '\x03');
554 \\
555 \\ exit();
556 \\}
557 \\
558 \\fn add(a: u32, b: u32) void {
559 \\ assert(a + b == 12356);
560 \\}
561 \\
562 \\pub fn assert(ok: bool) void {
563 \\ if (!ok) unreachable; // assertion failure
564 \\}
565 \\
566 \\fn exit() noreturn {
567 \\ asm volatile ("syscall"
568 \\ :
569 \\ : [number] "{rax}" (231),
570 \\ [arg1] "{rdi}" (0)
571 \\ : "rcx", "r11", "memory"
572 \\ );
573 \\ unreachable;
574 \\}
575 ,
576 "",
577 );
546 }578 }
547579
548 {580 {