authorchloe caruso <git@paperclover.net> 2024-09-21 01:25:24-07:00
committerchloe caruso <git@paperclover.net> 2024-09-21 01:25:24-07:00
log1eedbe39492f981ee0cfaf692af0707cf3d99383
tree926982dd66bf3df168d658c2ee0f1bfb403e78b4
parentf3f70b7d818c9ee8330dd21a3b263478f560cee9

chore: rename Teg -> Hir


22 files changed, 1761 insertions(+), 1753 deletions(-)

README.md+3-2
......@@ -1,7 +1,8 @@
11# Ix
22
3Ix (**I**nferable E**x**pression) is a high-level, general purpose programming
4language. It features a mix of Rust, Zig, and JavaScript's great points.
3Ix (***I***nferable E***x***pression) is a high-level, general purpose
4programming language. It features a mix of Rust, Zig, and JavaScript's great
5points.
56
67For a guide on how to use Ix, see the manual included in the binary
78distribution. Additionally, the latest commit of the manual is hosted online at
doc/architecture.md+7-7
......@@ -34,13 +34,13 @@ compiler tests into these categories:
3434 runtime, testing both the semantic analysis pass as well as the code
3535 generation backend.
3636- **Transform Error Tests** (`test/transform_error`) confirm that the transform
37 pass errors are correct. A passing `Teg` fails the test.
37 pass errors are correct. A passing `Hir` fails the test.
3838
39All compiler tests can be run with `zig build test`, or the test suite can be
40filtered using flags, see `zig build test --help`
39All compiler tests can be run with `./build test`, or the test suite can be
40filtered using flags, see `./build test -- --help`
4141
42To run Zig tests for an associated module, use `zig build test-{name}`, or run
43`zig build test-all` to run all tests in the codebase.
42To run Zig tests for an associated module, use `./build test-{name}`, or run
43`./build test-all` to run all tests in the codebase.
4444
4545## Core
4646
......@@ -48,7 +48,7 @@ The `core` module contains most of the compiler:
4848
4949- Tokenizing and Parsing files. (`Tokenizer.zig`, `Parse.zig`, `Ast.zig`)
5050- Transform Pass, moving from Ast to an untyped intermediate representation
51 (`Transform.zig`)
51 (`Transform.zig`, `Hir.zig`)
5252- Semantic Analysis, resolving all types and comptime values. (`Sema.zig`)
5353- Intern Pool, storing and de-duplicating objects in a compilation.
5454 (`InternPool.zig`)
......@@ -56,7 +56,7 @@ The `core` module contains most of the compiler:
5656
5757Note that components like the formatter and module fetching code are not here.
5858Keeping this module as small as possible is important for keeping compile times
59low. Using `zig build compiler -- --help` instead of the fully featured binary
59low. Using `./build compiler -- --help` instead of the fully featured binary
6060will allow for faster and more focused iteration.
6161
6262## Manual
doc/language-manual.md+1-1
......@@ -1,6 +1,6 @@
11# Ix Programming Language
22
3Ix (**I**nferable E**x**pression) is a high-level programming language for
3Ix (***I***nferable E***x***pression) is a high-level programming language for
44developing web applications and games.
55
66Key goals of this project are:
src/cli_compiler.zig+2-2
......@@ -81,7 +81,7 @@ pub fn main() !u8 {
8181 const main_file = try comp.getFile(file_path);
8282
8383 var fail_report: Report = undefined;
84 const teg = main_file.getTeg(&comp, &fail_report) catch |err| switch (err) {
84 const hir = main_file.getHir(&comp, &fail_report) catch |err| switch (err) {
8585 error.TransformFail => {
8686 std.debug.print("Transform failed:\n", .{});
8787 try fail_report.dump(.initComp(&comp, main_file), comp.out);
......@@ -97,7 +97,7 @@ pub fn main() !u8 {
9797
9898 if (comp.options.dump_ir) {
9999 const stderr = std.io.getStdErr().writer();
100 try teg.dumpToWriter(stderr, null);
100 try hir.dumpToWriter(stderr, null);
101101 }
102102
103103 const entry_point = try comp.enqueueEntryModule(main_file);
src/cli_transform.zig+5-5
......@@ -66,7 +66,7 @@ pub fn main() !u8 {
6666 }
6767
6868 var teg_report: core.Report = undefined;
69 var teg = core.Transform.transform(ast, alloc, &teg_report) catch |err| switch (err) {
69 var hir = core.Transform.transform(ast, alloc, &teg_report) catch |err| switch (err) {
7070 error.OutOfMemory => return err,
7171 error.TransformFail => {
7272 defer teg_report.deinit(alloc);
......@@ -81,13 +81,13 @@ pub fn main() !u8 {
8181 return 1;
8282 },
8383 };
84 defer teg.deinit(alloc);
84 defer hir.deinit(alloc);
8585
86 // const file = try std.fs.cwd().createFile("serialized.teg", .{});
86 // const file = try std.fs.cwd().createFile("serialized.hir", .{});
8787 // defer file.close();
88 // try teg.serialize(.{ .file = file });
88 // try hir.serialize(.{ .file = file });
8989
90 try teg.dumpToWriter(out.writer, out.tty);
90 try hir.dumpToWriter(out.writer, out.tty);
9191
9292 return 0;
9393}
src/core/Air.Dump.zig+1-1
......@@ -1,4 +1,4 @@
1//! This implements a debug formatter for Teg
1//! This implements a debug formatter for Air
22air: Air,
33ip: *const InternPool,
44tty: std.io.tty.Config,
src/core/Ast.zig+1-1
......@@ -1,6 +1,6 @@
11//! The Abstract Syntax Tree preserves most details of the source code,
22//! as it is used for formatting. Before semantic analysis, this
3//! structure is normalized into `Teg`, which removes constructs like
3//! structure is normalized into `Hir`, which removes constructs like
44//! whitespace, unneeded let bindings, and other transforms.
55//!
66//! `ast.nodes` contains nodes stored as three parts:
src/core/Comp.zig+30-30
......@@ -110,14 +110,14 @@ const Job = union(enum) {
110110
111111pub fn enqueueEntryModule(comp: *Comp, file: *File) !Decl.Index {
112112 var report: Report = undefined;
113 const teg = try file.getTeg(comp, &report);
113 const hir = try file.getHir(comp, &report);
114114
115115 // TODO, move this elsewhere. we should print all errors and warnings at once
116 if (teg.report.warnings.len > 0) {
117 try teg.report.dump(.initComp(comp, file), comp.out);
116 if (hir.report.warnings.len > 0) {
117 try hir.report.dump(.initComp(comp, file), comp.out);
118118 }
119119
120 const ns = try comp.indexTegModule(file, .main_module_inst);
120 const ns = try comp.indexHirModule(file, .main_module_inst);
121121 const main_str = try comp.intern_pool.getOrPutString(comp.gpa, "main", .no_embedded_nulls);
122122 const decl_index = comp.intern_pool.namespacePtr(ns).lookupDirect(comp, main_str) orelse {
123123 // TODO: add a helper function into Report to render a single error
......@@ -168,12 +168,12 @@ fn runAnalysisJob(comp: *Comp, unit: InternPool.AnalysisUnit, first_blocked_sema
168168 };
169169 const decl = comp.intern_pool.declPtr(decl_index);
170170 const file = comp.intern_pool.namespacePtr(decl.src_namespace).file_scope;
171 const teg = file.teg orelse @panic("TODO: make sure teg is loaded to avoid annoying error set?");
171 const hir = file.hir orelse @panic("TODO: make sure hir is loaded to avoid annoying error set?");
172172
173173 try sema.init(
174174 comp,
175175 file,
176 teg,
176 hir,
177177 unit,
178178 decl.src_namespace,
179179 std.heap.ArenaAllocator.init(comp.gpa),
......@@ -266,7 +266,7 @@ pub fn getFile(comp: *Comp, absolute_file_path: []const u8) !*File {
266266 .root_namespace = .none,
267267 .source = null,
268268 .ast = null,
269 .teg = null,
269 .hir = null,
270270 };
271271 gop.value_ptr.* = file;
272272 return file;
......@@ -277,7 +277,7 @@ pub const Source = struct {
277277 stat: Stat,
278278};
279279
280/// A file in the compilation and it's associated data structures. Ast and Teg
280/// A file in the compilation and it's associated data structures. Ast and Hir
281281/// are not guaranteed to be loaded, even if it's `status` says `success`.
282282pub const File = struct {
283283 /// TODO: change this to a URL
......@@ -287,7 +287,7 @@ pub const File = struct {
287287
288288 source: ?Source,
289289 ast: ?Ast,
290 teg: ?Teg,
290 hir: ?Hir,
291291
292292 path_digest: ?Cache.BinDigest,
293293
......@@ -323,7 +323,7 @@ pub const File = struct {
323323
324324 // Here we do not modify stat fields because this function is the one
325325 // used for error reporting. We need to keep the stat fields stale so that
326 // transformFile can know to regenerate Teg.
326 // transformFile can know to regenerate Hir.
327327
328328 const loaded_source: Source = .{
329329 .code = source,
......@@ -370,11 +370,11 @@ pub const File = struct {
370370 return &(file.ast.?);
371371 }
372372
373 pub const GetTegError = GetAstError || Transform.Error;
373 pub const GetHirError = GetAstError || Transform.Error;
374374
375 pub fn getTeg(file: *File, comp: *Comp, fail_report: *Report) GetTegError!Teg {
376 if (file.teg) |teg| {
377 return teg;
375 pub fn getHir(file: *File, comp: *Comp, fail_report: *Report) GetHirError!Hir {
376 if (file.hir) |hir| {
377 return hir;
378378 }
379379
380380 const bin_digest = hash: {
......@@ -387,10 +387,10 @@ pub const File = struct {
387387 };
388388 file.path_digest = bin_digest;
389389
390 const teg = try Transform.transform((try file.getAst(comp)).*, comp.gpa, fail_report);
390 const hir = try Transform.transform((try file.getAst(comp)).*, comp.gpa, fail_report);
391391
392 file.teg = teg;
393 return teg;
392 file.hir = hir;
393 return hir;
394394 }
395395
396396 pub fn unloadSource(file: *File, gpa: Allocator) void {
......@@ -407,15 +407,15 @@ pub const File = struct {
407407 }
408408 }
409409
410 pub fn unloadTeg(file: *File, gpa: Allocator) void {
411 if (file.teg) |*teg| {
412 teg.deinit(gpa);
413 file.teg = null;
410 pub fn unloadHir(file: *File, gpa: Allocator) void {
411 if (file.hir) |*hir| {
412 hir.deinit(gpa);
413 file.hir = null;
414414 }
415415 }
416416
417417 pub fn deinit(file: *File, gpa: Allocator) void {
418 file.unloadTeg(gpa);
418 file.unloadHir(gpa);
419419 file.unloadAst(gpa);
420420 file.unloadSource(gpa);
421421 gpa.destroy(file);
......@@ -476,7 +476,7 @@ pub const Decl = struct {
476476 // /// This value is absolute.
477477 // src_line: u32,
478478
479 /// Index of the Teg `declaration` instruction from which this `Decl` was created.
479 /// Index of the Hir `declaration` instruction from which this `Decl` was created.
480480 teg_decl_index: InternPool.TrackedInst.Index,
481481
482482 /// Represents the "shallow" analysis status. For example, for decls that are functions,
......@@ -620,10 +620,10 @@ pub const Namespace = struct {
620620 pub const Index = InternPool.NamespaceIndex;
621621};
622622
623/// Index a Teg's module scope as a namespace. This prepares `Decl` objects for
623/// Index a Hir's module scope as a namespace. This prepares `Decl` objects for
624624/// every declaration, but does not begin analysis of them.
625pub fn indexTegModule(comp: *Comp, file: *File, module_index: Teg.Inst.Index) !Namespace.Index {
626 const teg = file.teg.?;
625pub fn indexHirModule(comp: *Comp, file: *File, module_index: Hir.Inst.Index) !Namespace.Index {
626 const hir = file.hir.?;
627627
628628 assert(file.root_namespace == .none);
629629
......@@ -635,12 +635,12 @@ pub fn indexTegModule(comp: *Comp, file: *File, module_index: Teg.Inst.Index) !N
635635 const ns_ptr = comp.intern_pool.namespacePtr(ns);
636636 errdefer comp.intern_pool.destroyNamespace(comp.gpa, ns);
637637
638 for (teg.moduleDeclarations(module_index)) |decl_index| {
639 switch (teg.instTag(decl_index)) {
638 for (hir.moduleDeclarations(module_index)) |decl_index| {
639 switch (hir.instTag(decl_index)) {
640640 .declaration => {
641641 const name = try comp.intern_pool.getOrPutString(
642642 comp.gpa,
643 teg.declName(decl_index),
643 hir.declName(decl_index),
644644 .no_embedded_nulls,
645645 );
646646 const tracked_inst = try comp.intern_pool.trackInst(comp.gpa, file, decl_index);
......@@ -736,7 +736,7 @@ const InternPool = core.InternPool;
736736
737737const Ast = core.Ast;
738738const Air = core.Air;
739const Teg = core.Teg;
739const Hir = core.Hir;
740740const Cache = core.Cache;
741741const Sema = core.Sema;
742742const Transform = core.Transform;
src/core/Hir.Dump.zig created+522
......@@ -0,0 +1,522 @@
1//! This implements a debug formatter for Hir
2hir: Hir,
3tty: ?std.io.tty.Config = null,
4
5const State = struct {
6 arena: std.mem.Allocator,
7 hir: *const Hir,
8 indent: usize = 0,
9 tty: std.io.tty.Config,
10 visited: std.AutoHashMapUnmanaged(Hir.Inst.Index, void) = .{},
11
12 fn newline(state: State, writer: anytype) !void {
13 try writer.writeByte('\n');
14 if (state.indent > 0)
15 try writer.writeByteNTimes(' ', state.indent * 2);
16 }
17
18 fn dumpInst(s: *State, writer: anytype, inst: Hir.Inst.Index) @TypeOf(writer).Error!void {
19 const hir = s.hir;
20 const tty = s.tty;
21
22 try writer.print("%{} = ", .{@intFromEnum(inst)});
23
24 const tag = s.hir.instTag(inst);
25
26 try tty.setColor(writer, .bright_black);
27 const node_offset = hir.instNodeOffset(inst);
28 try writer.print("{c}{d} ", .{
29 @as(u8, if (node_offset >= 0) '+' else '-'),
30 @abs(node_offset),
31 });
32 try tty.setColor(writer, .reset);
33
34 try tty.setColor(writer, .cyan);
35 try writer.print("{s}", .{@tagName(tag)});
36 try tty.setColor(writer, .reset);
37
38 if ((try s.visited.fetchPut(s.arena, inst, {})) != null) {
39 try tty.setColor(writer, .red);
40 try writer.writeAll(" [error: recursive tree]");
41 try tty.setColor(writer, .reset);
42 return;
43 }
44
45 switch (tag) {
46 .module => {
47 try s.dumpInstList(writer, hir.moduleDeclarations(inst), '{', '}');
48 },
49 .declaration, .variable_declaration, .test_declaration => {
50 const decl = hir.fullDecl(inst);
51
52 try writer.writeAll(" ");
53 const name = decl.name.slice(hir.string_bytes);
54 if (name.len == 0) {
55 try tty.setColor(writer, .bold);
56 try writer.writeAll("[no name]");
57 } else {
58 try tty.setColor(writer, .magenta);
59 try writer.writeAll(name);
60 }
61 try tty.setColor(writer, .reset);
62 try writer.writeAll(" (");
63 try writer.print("{d}", .{decl.instruction_count});
64 try writer.writeAll(")");
65 try tty.setColor(writer, .bright_black);
66 try writer.writeAll(" [");
67 try writer.writeAll(&std.fmt.bytesToHex(decl.hash, .lower));
68 try writer.writeAll("]");
69 try tty.setColor(writer, .reset);
70 try writer.writeAll(" (");
71 s.indent += 1;
72 try s.newline(writer);
73 try s.dumpRef(writer, decl.body);
74 s.indent -= 1;
75 try s.newline(writer);
76 try writer.writeAll(")");
77 },
78 .func => {
79 const func: Hir.Func = hir.instPayload(.func, inst);
80 try writer.writeAll(" {");
81 s.indent += 1;
82 try s.newline(writer);
83 try writer.writeAll("params: ");
84 try s.dumpOptionalRefList(writer, func.params.slice(hir), '[', ']');
85 try s.newline(writer);
86 try writer.writeAll("return_type: ");
87 if (func.return_type.unwrap()) |ret|
88 try s.dumpRef(writer, ret)
89 else {
90 try tty.setColor(writer, .bright_black);
91 try writer.writeAll("<inferred>");
92 try tty.setColor(writer, .reset);
93 }
94 try s.newline(writer);
95 try writer.writeAll("captures: ");
96 try s.dumpInstList2(writer, func.captures.slice(hir), '[', ']');
97 try s.newline(writer);
98 try writer.writeAll("body: ");
99 try s.dumpInst(writer, func.body);
100 s.indent -= 1;
101 try s.newline(writer);
102 try writer.writeAll("}");
103 },
104 .param => {
105 const data = hir.instData(.param, inst);
106 try writer.writeAll("(");
107 if (data.data == std.math.maxInt(u32)) {
108 try tty.setColor(writer, .bright_black);
109 try writer.writeAll("<return type>");
110 } else {
111 try tty.setColor(writer, .yellow);
112 try writer.print("{d}", .{data.data});
113 }
114 try tty.setColor(writer, .reset);
115 try writer.writeAll(")");
116 },
117 inline .block, .@"comptime" => |t| {
118 const block = hir.instData(t, inst);
119 const index_list = block.extra_index.get(hir);
120 try s.dumpInstList(writer, index_list.slice(hir), '[', ']');
121 },
122 .number => {
123 const number = hir.instData(.number, inst);
124 const float = number.extra_index.get(hir).decode();
125 try tty.setColor(writer, .yellow);
126 try writer.print(" {d}", .{float});
127 try tty.setColor(writer, .reset);
128 },
129 inline .field,
130 .index,
131 .add,
132 .sub,
133 .mul,
134 .div,
135 .rem,
136 .pow,
137 .@"and",
138 .@"or",
139 .bit_and,
140 .bit_or,
141 .bit_xor,
142 .shl,
143 .shr,
144 .eq,
145 .ne,
146 .lt,
147 .le,
148 .gt,
149 .ge,
150 => |comptime_tag| {
151 const data = hir.instData(comptime_tag, inst).extra_index.get(hir);
152 try writer.writeAll("(");
153 try s.dumpRefMarker(writer, data.lhs);
154 try writer.writeAll(", ");
155 try s.dumpRefMarker(writer, data.rhs);
156 try writer.writeAll(")");
157 },
158 .coercion => {
159 const data = hir.instData(.coercion, inst).extra_index.get(hir);
160 try writer.writeAll("(");
161 try s.dumpRefMarker(writer, data.type);
162 try writer.writeAll(", ");
163 try s.dumpRefMarker(writer, data.operand);
164 try writer.writeAll(")");
165 },
166 .@"break" => {
167 const data: Hir.Break = hir.instData(.@"break", inst).extra_index.get(hir);
168 try writer.writeAll("(");
169 try s.dumpRefMarker(writer, data.block.toRef());
170 try writer.writeAll(", ");
171 try s.dumpRefMarker(writer, data.operand);
172 try writer.writeAll(")");
173 },
174 .store => {
175 const data: Hir.Store = hir.instData(.store, inst).extra_index.get(hir);
176 try writer.writeAll("(");
177 try s.dumpRefMarker(writer, data.memory.toRef());
178 try writer.writeAll(", ");
179 try s.dumpRefMarker(writer, data.operand);
180 try writer.writeAll(")");
181 },
182 .store_field => {
183 const data: Hir.StoreField = hir.instData(.store_field, inst).extra_index.get(hir);
184 try writer.writeAll("(");
185 try s.dumpRefMarker(writer, data.base);
186 try writer.writeAll(", ");
187 try s.dumpRefMarker(writer, data.field);
188 try writer.writeAll(", ");
189 try s.dumpRefMarker(writer, data.operand);
190 try writer.writeAll(")");
191 },
192 .store_decl => {
193 const data: Hir.StoreVarDecl = hir.instData(.store_decl, inst).extra_index.get(hir);
194 try writer.writeAll("(");
195 try tty.setColor(writer, .magenta);
196 try writer.writeAll(data.var_decl.slice(hir.string_bytes));
197 try tty.setColor(writer, .reset);
198 try writer.writeAll(", ");
199 try s.dumpRefMarker(writer, data.operand);
200 try writer.writeAll(")");
201 },
202 .string => {
203 const data: Hir.SlicedString = hir.instData(.string, inst).extra_index.get(hir);
204 try tty.setColor(writer, .green);
205 try writer.writeAll(" \"");
206 try writer.writeAll(data.slice(hir.string_bytes));
207 try writer.writeAll("\"");
208 try tty.setColor(writer, .reset);
209 },
210 inline .memory,
211 .discard,
212 .ensure_void,
213 .negate,
214 .bool_not,
215 .bit_not,
216 .@"extern",
217 .import,
218 .fetch,
219 .compile_error,
220 .type_of,
221 .array_type,
222 .assert,
223 => |comptime_tag| {
224 const data = hir.instData(comptime_tag, inst);
225 try writer.writeAll("(");
226 try s.dumpRefMarker(writer, data.operand);
227 try writer.writeAll(")");
228 },
229 .call => {
230 const call: Hir.Call = hir.instData(.call, inst).extra_index.get(hir);
231 try writer.writeAll("(");
232 try s.dumpRefMarker(writer, call.base);
233 try writer.writeAll(", ");
234 try s.dumpRefMarkerList(writer, call.args.slice(hir), '[', ']');
235 try writer.writeAll(")");
236 },
237 .js_new => {
238 const call: Hir.JsNew = hir.instData(.js_new, inst).extra_index.get(hir);
239 try writer.writeAll("(");
240 try s.dumpRefMarker(writer, call.base);
241 try writer.writeAll(", ");
242 try s.dumpRefMarkerList(writer, call.args.slice(hir), '[', ']');
243 try writer.writeAll(")");
244 },
245 .load_decl => {
246 const call: Hir.StrNode = hir.instData(.load_decl, inst);
247
248 try tty.setColor(writer, .red);
249 try writer.print(" {s}", .{call.string.slice(hir.string_bytes)});
250 try tty.setColor(writer, .reset);
251 },
252 .@"if" => {
253 const data: Hir.If = hir.instPayload(.@"if", inst);
254 try writer.writeAll("(");
255 try s.dumpRefMarker(writer, data.cond);
256 try writer.writeAll(") {");
257 s.indent += 1;
258 try s.newline(writer);
259 try writer.writeAll("yes: ");
260 try s.dumpRef(writer, data.yes);
261 try s.newline(writer);
262 try writer.writeAll("no: ");
263 try s.dumpRef(writer, data.no);
264 s.indent -= 1;
265 try s.newline(writer);
266 try writer.writeAll("}");
267 },
268 .struct_decl => {
269 const data: Hir.StructDecl = hir.instPayload(.struct_decl, inst);
270 try writer.writeAll(" {");
271 s.indent += 1;
272 try s.newline(writer);
273 for (data.keys(hir), data.types(hir), 0..) |key, value, i| {
274 if (i != 0)
275 try s.newline(writer);
276 try writer.print("{s}: ", .{key.slice(hir.string_bytes)});
277 try s.dumpRefMarker(writer, value);
278 }
279 s.indent -= 1;
280 try s.newline(writer);
281 try writer.writeAll("}");
282 },
283 .struct_init => {
284 const data: Hir.StructInit = hir.instPayload(.struct_init, inst);
285 try writer.writeAll("(");
286 try s.dumpRefMarker(writer, data.base_type);
287 try writer.writeAll(") {");
288 s.indent += 1;
289 try s.newline(writer);
290 for (data.keys(hir), data.inits(hir), 0..) |key, value, i| {
291 if (i != 0)
292 try s.newline(writer);
293 try writer.print("{s}: ", .{key.slice(hir.string_bytes)});
294 try s.dumpRefMarker(writer, value);
295 }
296 s.indent -= 1;
297 try s.newline(writer);
298 try writer.writeAll("}");
299 },
300 .array_init => {
301 const data: Hir.ArrayInit = hir.instPayload(.array_init, inst);
302
303 if (data.type_hint.unwrap()) |type_hint| {
304 try writer.writeAll("(");
305 try s.dumpRef(writer, type_hint);
306 try writer.writeAll(", ");
307 }
308
309 try writer.writeAll("[");
310
311 s.indent += 1;
312
313 for (data.list.slice(hir)) |item| {
314 try s.newline(writer);
315 try s.dumpRefMarker(writer, item);
316 try writer.writeAll(",");
317 }
318
319 s.indent -= 1;
320 try s.newline(writer);
321
322 try writer.writeAll("]");
323
324 if (data.type_hint != .none)
325 try writer.writeAll(")");
326 },
327 .tuple_type => {
328 const data: Hir.TupleType = hir.instPayload(.tuple_type, inst);
329
330 try writer.writeAll("(");
331 try s.dumpRefMarkerList(writer, data.items.slice(hir), '[', ']');
332 try writer.writeAll(")");
333 },
334 .tuple_init => {
335 const data: Hir.TupleInit = hir.instPayload(.tuple_init, inst);
336
337 try writer.writeAll("(");
338 if (data.type_hint.unwrap()) |type_hint| {
339 try s.dumpRef(writer, type_hint);
340 try writer.writeAll(", ");
341 }
342 try s.dumpRefMarkerList(writer, data.items.slice(hir), '[', ']');
343 try writer.writeAll(")");
344 },
345 .result_type_argument => {
346 const data: Hir.ResultTypeArgument = hir.instData(.result_type_argument, inst);
347
348 try writer.writeAll("(");
349 try s.dumpRefMarker(writer, data.call_base);
350 try writer.print(", {d}", .{data.argument});
351 try writer.writeAll(")");
352 },
353 .result_type_struct_field => {
354 const data: Hir.ResultTypeStructField = hir.instData(.result_type_struct_field, inst);
355
356 try writer.writeAll("(");
357 try s.dumpRefMarker(writer, data.type);
358 try writer.print(", {s}", .{data.field.slice(s.hir.string_bytes)});
359 try writer.writeAll(")");
360 },
361 .result_type_tuple_field => {
362 const data: Hir.ResultTypeTupleField = hir.instData(.result_type_tuple_field, inst);
363
364 try writer.writeAll("(");
365 try s.dumpRefMarker(writer, data.type);
366 try writer.print(", {d}", .{data.item});
367 try writer.writeAll(")");
368 },
369 .result_type_array_value => {
370 const data: Hir.ResultTypeArrayValue = hir.instData(.result_type_array_value, inst);
371
372 try writer.writeAll("(");
373 try s.dumpRefMarker(writer, data.type);
374 try writer.writeAll(")");
375 },
376 }
377 }
378
379 fn dumpRef(s: *State, writer: anytype, ref: Hir.Inst.Ref) !void {
380 switch (ref.decode()) {
381 .index => |index| try s.dumpInst(writer, index),
382 .value => {
383 try s.tty.setColor(writer, .blue);
384 try writer.print("%{s}", .{@tagName(ref)});
385 try s.tty.setColor(writer, .reset);
386 },
387 }
388 }
389
390 fn dumpRefMarker(s: *State, writer: anytype, ref: Hir.Inst.Ref) !void {
391 switch (ref.decode()) {
392 .index => |index| {
393 try s.tty.setColor(writer, .blue);
394 try writer.print("%{d}", .{@intFromEnum(index)});
395 try s.tty.setColor(writer, .reset);
396 },
397 .value => {
398 try s.tty.setColor(writer, .blue);
399 try writer.print("%{s}", .{@tagName(ref)});
400 try s.tty.setColor(writer, .reset);
401 },
402 }
403 }
404
405 fn dumpInstList(state: *State, writer: anytype, list: []const Hir.Inst.Index, l: u8, r: u8) !void {
406 try writer.print(" {c}", .{l});
407 if (list.len > 0) {
408 state.indent += 1;
409
410 for (list) |inst| {
411 try state.newline(writer);
412 try state.dumpInst(writer, inst);
413 }
414
415 state.indent -= 1;
416 try state.newline(writer);
417 }
418 try writer.print("{c}", .{r});
419 }
420
421 fn dumpInstList2(state: *State, writer: anytype, list: []const Hir.Inst.Index, l: u8, r: u8) !void {
422 try writer.print(" {c}", .{l});
423 if (list.len > 0) {
424 state.indent += 1;
425
426 for (list) |inst| {
427 try state.newline(writer);
428 try state.dumpRefMarker(writer, inst.toRef());
429 }
430
431 state.indent -= 1;
432 try state.newline(writer);
433 }
434 try writer.print("{c}", .{r});
435 }
436
437 fn dumpRefList(state: *State, writer: anytype, list: []const Hir.Inst.Ref, l: u8, r: u8) !void {
438 try writer.print(" {c}", .{l});
439 if (list.len > 0) {
440 state.indent += 1;
441
442 for (list) |ref| {
443 try state.newline(writer);
444 try state.dumpRef(writer, ref);
445 }
446
447 state.indent -= 1;
448
449 try state.newline(writer);
450 }
451 try writer.print("{c}", .{r});
452 }
453
454 fn dumpOptionalRefList(state: *State, writer: anytype, list: []const Hir.Inst.Ref.Optional, l: u8, r: u8) !void {
455 try writer.print(" {c}", .{l});
456 if (list.len > 0) {
457 state.indent += 1;
458
459 for (list) |optional_ref| {
460 try state.newline(writer);
461 if (optional_ref.unwrap()) |ref|
462 try state.dumpRef(writer, ref)
463 else {
464 try state.tty.setColor(writer, .bright_black);
465 try writer.writeAll("<inferred>");
466 try state.tty.setColor(writer, .reset);
467 }
468 }
469
470 state.indent -= 1;
471
472 try state.newline(writer);
473 }
474 try writer.print("{c}", .{r});
475 }
476
477 fn dumpRefMarkerList(state: *State, writer: anytype, list: []const Hir.Inst.Ref, l: u8, r: u8) !void {
478 try writer.print("{c}", .{l});
479 if (list.len > 0) {
480 state.indent += 1;
481
482 for (list) |ref| {
483 try state.newline(writer);
484 try state.dumpRefMarker(writer, ref);
485 }
486
487 state.indent -= 1;
488
489 try state.newline(writer);
490 }
491 try writer.print("{c}", .{r});
492 }
493};
494
495pub fn format(
496 dump: @This(),
497 comptime unused_fmt: []const u8,
498 _: std.fmt.FormatOptions,
499 writer: anytype,
500) !void {
501 comptime assert(unused_fmt.len == 0);
502
503 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
504 defer arena.deinit();
505
506 const hir = dump.hir;
507 var state = State{
508 .hir = &hir,
509 .tty = dump.tty orelse detectTTYFromWriter(writer),
510 .arena = arena.allocator(),
511 };
512 try state.dumpInst(writer, .main_module_inst);
513 try writer.writeAll("\n");
514 assert(state.indent == 0);
515}
516
517const std = @import("std");
518const assert = std.debug.assert;
519
520const core = @import("mod.zig");
521const Hir = core.Hir;
522const detectTTYFromWriter = core.detectTTYFromWriter;
src/core/Hir.zig created+1017
......@@ -0,0 +1,1017 @@
1//! High-level Intermediate Representation is an instruction list format that
2//! describes a source file in a manner effective for Semantic Analysis to
3//! process. The root instruction of every Hir is a `.module` that contains the
4//! root declarations. Each declaration's value contains a list of instructions.
5//! In contrast to the nested nature of syntax trees, Hir represents nested
6//! expressions as flat instruction sequences.
7//!
8//! Hir for a given file has no dependencies on it's imports, meaning it can be
9//! computed in parallel and cached when not changed.
10//!
11//! A helper program exists to visualize Hir: './build transform -- ./file.ix'
12//! Alternatively, `ix build` has the `--dump-ir` option.
13
14insts: Inst.List.Slice,
15string_bytes: []const u8,
16extra: ExtraStore = .{},
17report: Report,
18
19pub const ExtraStore = dod.ExtraStore(.hir, .@"const");
20pub const EncodedData = dod.EncodedData(Tag, u64);
21pub const ExtraIndex = ExtraStore.Index;
22pub const Dump = @import("Hir.Dump.zig");
23
24pub const Tag = enum(u8) {
25 /// Either the top level module or a `module` keyword. Contains a list of `.declarations`
26 /// Every analyzed module gets a `Comp.Namespace`
27 module,
28 /// Smallest unit of re-compilation. Every analyzed declaration gets a `Comp.Decl`
29 declaration,
30 /// Top-level memory location
31 variable_declaration,
32 /// Test declaration
33 test_declaration,
34 /// Retrieves a declaration value via it's name. Since declarations are
35 /// analyzed in isolation of each other, all references to instructions
36 /// outside of the current declaration must be in the form of this.
37 load_decl,
38 /// Blocks are a list of instructions. The block will end with a `.break`,
39 /// which will assign the block a return value.
40 block,
41 /// Ends a block (current or any parent) with a value.
42 /// `return` expressions are lowered to this.
43 @"break",
44 /// Creates a memory cell in the current scope with a starting value.
45 memory,
46 /// Re-assign a memory cell with a new ref.
47 store,
48 /// Re-assign a global variable decl with a new ref.
49 store_decl,
50 /// Re-assign a field with a new ref
51 store_field,
52 /// Performs a type coercion, such as in variable declarations.
53 /// The resulting Air Ref will be guaranteed to be the coerced type.
54 coercion,
55 /// Load a parameter
56 /// if data value is maxInt(u32), the function return type is used
57 param,
58 /// Asserts the operand is not void. Used for discard statements.
59 discard,
60 /// Asserts the operand is `void`. Used for undiscarded expressions.
61 ensure_void,
62
63 /// Branch takes a boolean condition and takes either a yes or no path.
64 @"if",
65 /// Given a block instruction
66 @"comptime",
67
68 /// A function expression, with or without captures
69 func,
70
71 // The following instructions are used to implement `Transform.ResultType`
72 result_type_argument,
73 result_type_struct_field,
74 result_type_tuple_field,
75 result_type_array_value,
76
77 /// Numeric constant.
78 number,
79 /// String literal constant.
80 string,
81
82 /// Constructs a unique struct type.
83 struct_decl,
84 /// Constructs an array type
85 array_type,
86
87 struct_init,
88 array_init,
89
90 tuple_init,
91 tuple_type,
92
93 add,
94 sub,
95 mul,
96 div,
97 rem,
98 pow,
99 @"and",
100 @"or",
101 bit_and,
102 bit_or,
103 bit_xor,
104 shl,
105 shr,
106 eq,
107 ne,
108 lt,
109 le,
110 gt,
111 ge,
112
113 negate,
114 bool_not,
115 bit_not,
116 assert,
117 field,
118 index,
119 call,
120 type_of,
121 /// Implements the `@extern` builtin
122 @"extern",
123
124 /// Implements the `@jsNew` builtin
125 js_new,
126 /// Implements the `@import` builtin
127 import,
128 /// Implements the `@fetch` builtin
129 fetch,
130 /// Implements the `@compileError` builtin
131 compile_error,
132
133 pub fn Data(comptime tag: Tag) type {
134 return switch (tag) {
135 .module, .block, .@"comptime" => PlNode(IndexList),
136
137 .declaration,
138 .variable_declaration,
139 .test_declaration,
140 => PlNode(Decl),
141
142 .coercion => PlNode(Coercion),
143 .@"break" => PlNode(Break),
144 .number => PlNode(Float),
145 .string => PlNode(SlicedString),
146 .call => PlNode(Call),
147 .@"if" => PlNode(If),
148 .store => PlNode(Store),
149 .store_decl => PlNode(StoreVarDecl),
150 .store_field => PlNode(StoreField),
151 .js_new => PlNode(JsNew),
152 .struct_decl => PlNode(StructDecl),
153 .struct_init => PlNode(StructInit),
154 .array_init => PlNode(ArrayInit),
155 .tuple_type => PlNode(TupleType),
156 .tuple_init => PlNode(TupleInit),
157 .func => PlNode(Func),
158
159 .load_decl => StrNode,
160 .param => DataNode,
161
162 .result_type_argument => ResultTypeArgument,
163 .result_type_struct_field => ResultTypeStructField,
164 .result_type_tuple_field => ResultTypeTupleField,
165 .result_type_array_value => ResultTypeArrayValue,
166
167 // One operand instructions
168 .memory,
169 .discard,
170 .ensure_void,
171 .negate,
172 .bool_not,
173 .bit_not,
174 .@"extern",
175 .import,
176 .fetch,
177 .compile_error,
178 .type_of,
179 .array_type,
180 .assert,
181 => RefNode,
182
183 // Two operand instructions
184 .field,
185 .index,
186 .add,
187 .sub,
188 .mul,
189 .div,
190 .rem,
191 .pow,
192 .@"and",
193 .@"or",
194 .bit_and,
195 .bit_or,
196 .bit_xor,
197 .shl,
198 .shr,
199 .eq,
200 .ne,
201 .lt,
202 .le,
203 .gt,
204 .ge,
205 => PlNode(Bin),
206 };
207 }
208
209 pub fn airTag(comptime tag: Tag) Air.Inst.Tag {
210 return @field(Air.Inst.Tag, @tagName(tag));
211 }
212};
213
214pub fn PlNode(comptime Payload: type) type {
215 return struct {
216 pub const T = Payload;
217
218 src_node: NodeOffset,
219 extra_index: ExtraIndex(Payload),
220 };
221}
222
223pub const RefNode = struct {
224 src_node: NodeOffset,
225 operand: Inst.Ref,
226};
227
228pub const StrNode = struct {
229 src_node: NodeOffset,
230 string: NullTerminatedString,
231};
232
233pub const DataNode = struct {
234 src_node: NodeOffset,
235 data: u32,
236};
237
238pub const Inst = struct {
239 pub const List = std.MultiArrayList(Inst);
240
241 tag: Tag,
242 data: EncodedData,
243
244 /// The position of a Hir instruction within the `Hir` instructions array.
245 pub const Index = enum(u32) {
246 /// Hir is structured so that the outermost "main" struct of any file
247 /// is always at index 0.
248 main_module_inst = 0,
249 _,
250
251 pub const static_len = @intFromEnum(Ref.empty_tuple) + 1;
252
253 pub fn toRef(i: Index) Inst.Ref {
254 return @enumFromInt(static_len + @intFromEnum(i));
255 }
256
257 pub fn toOptional(i: Index) Optional {
258 return @enumFromInt(@intFromEnum(i));
259 }
260
261 pub fn op(i: Index, operand: Report.Operand) InstOp {
262 return .{ .index = i, .op = operand };
263 }
264
265 pub const Optional = enum(u32) {
266 none = std.math.maxInt(u32),
267 _,
268
269 pub fn unwrap(oi: Optional) ?Index {
270 return if (oi == .none) null else @enumFromInt(@intFromEnum(oi));
271 }
272 };
273 };
274
275 /// A reference to an instruction, or to a static InternPool value.
276 ///
277 /// If the integer tag value is < InternPool.static_len, then it
278 /// corresponds to a Value. Otherwise, it is an instruction index.
279 pub const Ref = enum(u32) {
280 opaque_type,
281 bool_type,
282 int32_type,
283 float_type,
284 string_type,
285 never_type,
286 type_type,
287 numeric_literal_type,
288 numeric_literal_array_type,
289 never_array_type,
290 empty_tuple_type,
291
292 void,
293 bool_true,
294 bool_false,
295 int32_zero,
296 float_zero,
297 nan,
298 empty_string,
299 empty_array,
300 empty_tuple,
301 _,
302
303 pub const Decoded = union(enum) {
304 value: InternPool.Value,
305 index: Hir.Inst.Index,
306 };
307
308 pub fn decode(ref: Ref) Decoded {
309 const ref_int = @intFromEnum(ref);
310 return if (ref_int >= Index.static_len)
311 .{ .index = @enumFromInt(ref_int - Index.static_len) }
312 else
313 .{ .value = @enumFromInt(ref_int) };
314 }
315
316 pub fn index(ref: Ref) ?Index {
317 const ref_int = @intFromEnum(ref);
318 if (ref_int >= Index.static_len) {
319 return @enumFromInt(ref_int - Index.static_len);
320 } else {
321 return null;
322 }
323 }
324
325 pub fn value(inst: Ref) ?InternPool.Value {
326 const ref_int = @intFromEnum(inst);
327
328 // TODO: is this > or >=
329 if (ref_int > Index.static_len)
330 return null;
331
332 return @enumFromInt(ref_int);
333 }
334
335 pub fn toOptional(ref: Ref) Optional {
336 return @enumFromInt(@intFromEnum(ref));
337 }
338
339 pub const Optional = enum(u32) {
340 none = std.math.maxInt(u32),
341 _,
342
343 pub fn unwrap(opt: Optional) ?Ref {
344 return if (opt != .none) @enumFromInt(@intFromEnum(opt)) else null;
345 }
346 };
347 };
348};
349
350pub const Bin = struct {
351 lhs: Inst.Ref,
352 rhs: Inst.Ref,
353};
354
355pub const Store = struct {
356 memory: Inst.Index,
357 operand: Inst.Ref,
358};
359
360pub const StoreVarDecl = struct {
361 var_decl: NullTerminatedString,
362 operand: Inst.Ref,
363};
364
365pub const StoreField = struct {
366 base: Inst.Ref,
367 field: Inst.Ref,
368 operand: Inst.Ref,
369};
370
371pub const Coercion = struct {
372 type: Inst.Ref,
373 operand: Inst.Ref,
374};
375
376pub const Break = struct {
377 block: Inst.Index,
378 operand: Inst.Ref,
379};
380
381pub const Call = struct {
382 base: Inst.Ref,
383 args: RefList,
384};
385
386pub const If = struct {
387 cond: Inst.Ref,
388 yes: Inst.Ref,
389 no: Inst.Ref,
390};
391
392pub const JsNew = struct {
393 base: Inst.Ref,
394 args: RefList,
395};
396
397/// Index into extra which contains `field_len * 2` u32s. The first half
398/// are the keys (NullTerminatedString) and the second half are field types
399/// (Ref). This basically is like a specialized MultiArrayList.
400pub const StructDecl = struct {
401 payload_index: u32,
402 field_len: u32,
403
404 pub fn keys(decl: StructDecl, hir: *const Hir) []const NullTerminatedString {
405 return @ptrCast(
406 hir.extra.list.items[decl.payload_index..][0..decl.field_len],
407 );
408 }
409
410 pub fn types(decl: StructDecl, hir: *const Hir) []const Inst.Ref {
411 return @ptrCast(
412 hir.extra.list.items[decl.payload_index + decl.field_len ..][0..decl.field_len],
413 );
414 }
415};
416
417/// This memory is laid out with the same strategy described in StructDecl
418pub const StructInit = struct {
419 base_type: Inst.Ref,
420 payload_index: u32,
421 field_len: u32,
422
423 pub fn keys(decl: StructInit, hir: *const Hir) []const NullTerminatedString {
424 return @ptrCast(
425 hir.extra.list.items[decl.payload_index..][0..decl.field_len],
426 );
427 }
428
429 pub fn inits(decl: StructInit, hir: *const Hir) []const Inst.Ref {
430 return @ptrCast(
431 hir.extra.list.items[decl.payload_index + decl.field_len ..][0..decl.field_len],
432 );
433 }
434};
435
436pub const ArrayInit = struct {
437 /// Optionally provide a result type for more reliable type coercion.
438 /// If specified, this must be an array type. Otherwise, the first
439 /// element's type is used.
440 type_hint: Inst.Ref.Optional,
441 /// The items in the array
442 list: RefList,
443};
444
445pub const TupleType = struct {
446 /// The items in the tuple
447 items: RefList,
448};
449
450pub const TupleInit = struct {
451 /// Optionally provide a result type for more reliable type coercion.
452 /// If specified, this must be an array type. Otherwise, the first
453 /// element's type is used.
454 type_hint: Inst.Ref.Optional,
455 /// The items in the tuple
456 items: RefList,
457};
458
459pub const Decl = struct {
460 name: NullTerminatedString,
461 hash: Cache.BinDigest,
462 instruction_count: u32,
463 body: Inst.Ref,
464};
465
466pub const Func = struct {
467 params: OptionalRefList,
468 return_type: Inst.Ref.Optional,
469 body: Inst.Index,
470 captures: IndexList,
471 instruction_count: u32,
472};
473
474pub const ResultTypeArgument = struct {
475 /// The VALUE that is going to be called.
476 call_base: Inst.Ref,
477 /// Which argument
478 argument: u32,
479};
480
481pub const ResultTypeStructField = struct {
482 /// The type of the struct itself,
483 type: Inst.Ref,
484 /// Which field
485 field: NullTerminatedString,
486};
487
488pub const ResultTypeTupleField = struct {
489 /// The type of the tuple itself,
490 type: Inst.Ref,
491 /// Which item
492 item: u32,
493};
494
495pub const ResultTypeArrayValue = struct {
496 /// The type of the array itself,
497 type: Inst.Ref,
498 unused: u32 = 0,
499};
500
501// TODO: make this an enum
502const NodeOffset = i32;
503
504// TODO: remove InstOp. LazyNode should not have a decl
505pub const InstOp = struct {
506 index: Inst.Index,
507 op: Report.Operand,
508
509 pub fn lazyNode(inst: InstOp, decl: Comp.Decl.Index) LazyNode {
510 return .{
511 .inst = inst.index,
512 .operand = inst.op,
513 .decl = decl,
514 };
515 }
516};
517
518pub const NullTerminatedString = enum(u32) {
519 empty = 0,
520 _,
521
522 pub fn slice(str: NullTerminatedString, string_bytes: []const u8) [:0]const u8 {
523 if (str == .empty) return "";
524 const sub = string_bytes[@intFromEnum(str)..];
525 const i = mem.indexOfScalar(u8, sub, 0) orelse unreachable;
526
527 return sub[0..i :0];
528 }
529};
530
531pub const SlicedString = struct {
532 start: u32,
533 len: u32,
534
535 pub fn slice(str: SlicedString, string_bytes: []const u8) []const u8 {
536 return string_bytes[str.start..][0..str.len];
537 }
538};
539
540// TODO: Make the next three structs using a generic comptime thing
541
542pub const RefList = struct {
543 start: u32,
544 len: u32,
545
546 pub fn slice(self: RefList, hir: *const Hir) []const Inst.Ref {
547 return @ptrCast(hir.extra.list.items[self.start..][0..self.len]);
548 }
549};
550
551pub const OptionalRefList = struct {
552 start: u32,
553 len: u32,
554
555 pub fn slice(self: OptionalRefList, hir: *const Hir) []const Inst.Ref.Optional {
556 return @ptrCast(hir.extra.list.items[self.start..][0..self.len]);
557 }
558};
559
560pub const IndexList = struct {
561 start: u32,
562 len: u32,
563
564 pub fn slice(self: IndexList, hir: *const Hir) []const Inst.Index {
565 return @ptrCast(hir.extra.list.items[self.start..][0..self.len]);
566 }
567};
568
569pub const NullTermStringList = struct {
570 start: u32,
571 len: u32,
572
573 pub fn slice(self: IndexList, hir: *const Hir) []const NullTerminatedString {
574 return @ptrCast(hir.extra.list.items[self.start..][0..self.len]);
575 }
576};
577
578pub fn deinit(hir: *Hir, gpa: std.mem.Allocator) void {
579 gpa.free(hir.string_bytes);
580 hir.extra.deinit(gpa);
581 hir.insts.deinit(gpa);
582 hir.report.deinit(gpa);
583 hir.* = undefined;
584}
585
586pub fn instTag(hir: *const Hir, index: Inst.Index) Hir.Tag {
587 return hir.insts.items(.tag)[@intFromEnum(index)];
588}
589
590pub fn instEncodedData(hir: *const Hir, index: Inst.Index) EncodedData {
591 return hir.insts.items(.data)[@intFromEnum(index)];
592}
593
594pub fn instData(hir: *const Hir, comptime tag: Hir.Tag, index: Inst.Index) tag.Data() {
595 return hir.instEncodedData(index).decode(tag, hir.instTag(index));
596}
597
598pub fn instDataUnsafe(hir: *const Hir, comptime T: type, index: Inst.Index) T {
599 return hir.instEncodedData(index).decodeUnsafe(T, hir.instTag(index));
600}
601
602pub fn instPayload(hir: *const Hir, comptime tag: Hir.Tag, index: Inst.Index) tag.Data().T {
603 return hir.instData(tag, index).extra_index.get(hir);
604}
605
606pub fn instNodeOffset(hir: *const Hir, index: Inst.Index) i32 {
607 return switch (hir.instTag(index)) {
608 // these nodes never get errors, but Hir.Dump will print these regardless
609 // TODO:
610 .declaration,
611 .result_type_argument,
612 .result_type_struct_field,
613 .result_type_tuple_field,
614 .result_type_array_value,
615 => 0,
616
617 inline else => |tag| hir.instData(tag, index).src_node,
618 };
619}
620
621pub fn blockInstructions(hir: *const Hir, index: Inst.Index) []const Inst.Index {
622 return hir.instData(.block, index).extra_index.get(hir).slice(hir);
623}
624
625pub fn fullFuncDecl(hir: *const Hir, index: Inst.Index) struct { Hir.Decl, Hir.DeclFn } {
626 const decl, var trail = hir.instData(.declaration, index).extra_index.getTrail(hir);
627 assert(decl.kind == .function);
628 const decl_fn = trail.read(&hir.extra, Hir.DeclFn);
629 return .{ decl, decl_fn };
630}
631
632pub fn fullDecl(hir: *const Hir, index: Inst.Index) Decl {
633 const decl = hir.instEncodedData(index).decodeUnsafe(PlNode(Decl), hir.instTag(index)).extra_index.get(hir);
634 return .{
635 .name = decl.name,
636 .hash = decl.hash,
637 .instruction_count = decl.instruction_count,
638 .body = decl.body,
639 };
640}
641
642pub fn declData(hir: *const Hir, index: Inst.Index) Hir.Decl {
643 return hir.instDataUnsafe(PlNode(Decl), index).extra_index.get(hir);
644}
645
646pub fn moduleDeclarations(hir: *const Hir, module_index: Inst.Index) []const Inst.Index {
647 const module = hir.instData(.module, module_index);
648 const module_data: IndexList = module.extra_index.get(hir);
649 const slice = module_data.slice(hir);
650 if (core.runtime_safety) {
651 for (slice) |item| {
652 switch (hir.instTag(item)) {
653 .declaration, .variable_declaration, .test_declaration => {},
654 else => {
655 std.debug.panic("\ngot unknown tag {s}\n", .{@tagName(hir.instTag(item))});
656 },
657 }
658 }
659 }
660 return slice;
661}
662
663pub fn rootFunction(hir: *const Hir) Inst.Index {
664 const decls = hir.moduleDeclarations(.main_module_inst);
665 const root_fn = decls[decls.len - 1];
666 assert(hir.declName(root_fn).len == 0);
667 return root_fn;
668}
669
670pub fn declName(hir: *const Hir, decl_index: Inst.Index) []const u8 {
671 const decl = hir.instDataUnsafe(PlNode(Decl), decl_index);
672 const decl_data: Decl = decl.extra_index.get(hir);
673 return decl_data.name.slice(hir.string_bytes);
674}
675
676pub fn dumpToWriter(hir: Hir, writer: anytype, tty: ?std.io.tty.Config) !void {
677 try writer.print("{}", .{Dump{ .hir = hir, .tty = tty }});
678}
679
680/// Used for generating decl hashes
681fn isolatedRefValue(decl_index: Inst.Index, ref_to_hash: Inst.Ref) i32 {
682 return switch (ref_to_hash.decode()) {
683 .value => |value| -@as(i32, @intCast(@intFromEnum(value))),
684 .index => |index| @intCast(@intFromEnum(index) - @intFromEnum(decl_index)),
685 };
686}
687
688/// Used for generating decl hashes
689fn isolatedIndexValue(decl_index: Inst.Index, index_to_hash: Inst.Index) u32 {
690 return @intFromEnum(index_to_hash) - @intFromEnum(decl_index);
691}
692
693pub fn writeToHasher(
694 hir: *const Hir,
695 hasher: *HashHelper,
696 tag_list: []Tag,
697 data_list: []EncodedData,
698 decl_index: Inst.Index,
699) void {
700 // Add all of the tags
701 hasher.addBytes(std.mem.sliceAsBytes(tag_list));
702
703 // Add all of the data
704 for (tag_list, data_list) |tag, data| {
705
706 // This should roughly line up with Hir.Tag.Data
707 switch (tag) {
708 // PlNode(IndexList),
709 .module,
710 .block,
711 .@"comptime",
712 => {
713 const pl_node = data.decodeUnsafe(PlNode(IndexList), tag);
714 hasher.add(pl_node.src_node);
715 writeIndexListToHasher(hasher, pl_node.extra_index.get(hir).slice(hir), decl_index);
716 },
717
718 // PlNode
719 inline .declaration,
720 .variable_declaration,
721 .test_declaration,
722 .coercion,
723 .@"break",
724 .number,
725 .string,
726 .call,
727 .@"if",
728 .store,
729 .js_new,
730 .struct_decl,
731 .struct_init,
732 .array_init,
733 .tuple_init,
734 .tuple_type,
735 .func,
736 .store_decl,
737 .store_field,
738 => |pl_node_tag| {
739 const pl_node = data.decode(pl_node_tag, tag);
740 hasher.add(pl_node.src_node);
741 hir.writePlNodeInnerToHasher(hasher, pl_node_tag.Data().T, pl_node.extra_index.get(hir), decl_index);
742 },
743 // StrNode
744 .load_decl => {
745 const str_node = data.decodeUnsafe(StrNode, tag);
746 hasher.add(str_node.src_node);
747 hasher.addBytes(str_node.string.slice(hir.string_bytes));
748 },
749 // DataNode
750 .param => {
751 const data_node = data.decodeUnsafe(DataNode, tag);
752 hasher.add(data_node.src_node);
753 hasher.add(data_node.data);
754 },
755 // RefNode
756 .memory,
757 .discard,
758 .ensure_void,
759 .negate,
760 .bool_not,
761 .bit_not,
762 .@"extern",
763 .import,
764 .fetch,
765 .compile_error,
766 .type_of,
767 .array_type,
768 .assert,
769 => {
770 const ref_node = data.decodeUnsafe(RefNode, tag);
771 hasher.add(ref_node.src_node);
772 hasher.add(isolatedRefValue(decl_index, ref_node.operand));
773 },
774 // PlNode(Bin)
775 .field,
776 .index,
777 .add,
778 .sub,
779 .mul,
780 .div,
781 .rem,
782 .pow,
783 .@"and",
784 .@"or",
785 .bit_and,
786 .bit_or,
787 .bit_xor,
788 .shl,
789 .shr,
790 .eq,
791 .ne,
792 .lt,
793 .le,
794 .gt,
795 .ge,
796 => {
797 const pl_node = data.decodeUnsafe(PlNode(Bin), tag);
798 const bin = pl_node.extra_index.get(hir);
799 hasher.add(isolatedRefValue(decl_index, bin.lhs));
800 hasher.add(isolatedRefValue(decl_index, bin.rhs));
801 },
802 // Result Types
803 .result_type_argument => {
804 const arg = data.decodeUnsafe(ResultTypeArgument, tag);
805 hasher.add(isolatedRefValue(decl_index, arg.call_base));
806 hasher.add(arg.argument);
807 },
808 .result_type_struct_field => {
809 const struct_field = data.decodeUnsafe(ResultTypeStructField, tag);
810 hasher.add(isolatedRefValue(decl_index, struct_field.type));
811 hasher.addBytes(struct_field.field.slice(hir.string_bytes));
812 },
813 .result_type_tuple_field => {
814 const tuple_field = data.decodeUnsafe(ResultTypeTupleField, tag);
815 hasher.add(isolatedRefValue(decl_index, tuple_field.type));
816 hasher.add(tuple_field.item);
817 },
818 .result_type_array_value => {
819 const array_value = data.decodeUnsafe(ResultTypeArrayValue, tag);
820 hasher.add(isolatedRefValue(decl_index, array_value.type));
821 },
822 }
823 }
824}
825
826fn writeIndexListToHasher(
827 hasher: *HashHelper,
828 index_list: []const Inst.Index,
829 decl_index: Inst.Index,
830) void {
831 hasher.add(index_list.len);
832 for (index_list) |idx| {
833 hasher.add(isolatedIndexValue(decl_index, idx));
834 }
835}
836
837fn writeRefListToHasher(
838 hasher: *HashHelper,
839 decl_index: Inst.Index,
840 index_list: []const Inst.Ref,
841) void {
842 hasher.add(index_list.len);
843 for (index_list) |idx| {
844 hasher.add(isolatedRefValue(decl_index, idx));
845 }
846}
847
848fn writePlNodeInnerToHasher(
849 hir: *const Hir,
850 hasher: *HashHelper,
851 comptime T: type,
852 data: T,
853 decl_index: Inst.Index,
854) void {
855 switch (T) {
856 Decl => {
857 hasher.addBytes(&data.hash);
858 hasher.addBytes(data.name.slice(hir.string_bytes));
859 },
860 Float => {
861 const as_bytes: [2]u32 = .{
862 data.low,
863 data.high,
864 };
865 hasher.add(@as(u64, @bitCast(as_bytes)));
866 },
867 SlicedString => {
868 hasher.addBytes(data.slice(hir.string_bytes));
869 },
870 Coercion => {
871 hasher.add(isolatedRefValue(decl_index, data.type));
872 hasher.add(isolatedRefValue(decl_index, data.operand));
873 },
874 Break => {
875 hasher.add(isolatedIndexValue(decl_index, data.block));
876 hasher.add(isolatedRefValue(decl_index, data.operand));
877 },
878 Call => {
879 hasher.add(isolatedRefValue(decl_index, data.base));
880 writeRefListToHasher(hasher, decl_index, data.args.slice(hir));
881 },
882 If => {
883 hasher.add(isolatedRefValue(decl_index, data.cond));
884 hasher.add(isolatedRefValue(decl_index, data.yes));
885 hasher.add(isolatedRefValue(decl_index, data.no));
886 },
887 Store => {
888 hasher.add(isolatedIndexValue(decl_index, data.memory));
889 hasher.add(isolatedRefValue(decl_index, data.operand));
890 },
891 StoreField => {
892 hasher.add(isolatedRefValue(decl_index, data.base));
893 hasher.add(isolatedRefValue(decl_index, data.field));
894 hasher.add(isolatedRefValue(decl_index, data.operand));
895 },
896 StoreVarDecl => {
897 hasher.addBytes(data.var_decl.slice(hir.string_bytes));
898 hasher.add(isolatedRefValue(decl_index, data.operand));
899 },
900 JsNew => {
901 hasher.add(isolatedRefValue(decl_index, data.base));
902 writeRefListToHasher(hasher, decl_index, data.args.slice(hir));
903 },
904 StructDecl => {
905 hasher.add(data.field_len);
906 for (data.keys(hir), data.types(hir)) |key, ty| {
907 hasher.addBytes(key.slice(hir.string_bytes));
908 hasher.add(isolatedRefValue(decl_index, ty));
909 }
910 },
911 StructInit => {
912 hasher.add(isolatedRefValue(decl_index, data.base_type));
913 hasher.add(data.field_len);
914 for (data.keys(hir), data.inits(hir)) |key, init| {
915 hasher.addBytes(key.slice(hir.string_bytes));
916 hasher.add(isolatedRefValue(decl_index, init));
917 }
918 },
919 ArrayInit => {
920 if (data.type_hint.unwrap()) |type_hint|
921 hasher.add(isolatedRefValue(decl_index, type_hint))
922 else
923 hasher.add(@as(i32, std.math.maxInt(i32)));
924 writeRefListToHasher(hasher, decl_index, data.list.slice(hir));
925 },
926 Func => {
927 for (data.params.slice(hir)) |optional| {
928 if (optional.unwrap()) |item|
929 hasher.add(isolatedRefValue(decl_index, item));
930 }
931
932 if (data.return_type.unwrap()) |type_hint|
933 hasher.add(isolatedRefValue(decl_index, type_hint))
934 else
935 hasher.add(@as(i32, std.math.maxInt(i32)));
936
937 hasher.add(isolatedIndexValue(decl_index, data.body));
938 hasher.add(data.instruction_count);
939 },
940 TupleType => {
941 hasher.add(data.items.len);
942 for (data.items.slice(hir)) |item| {
943 hasher.add(isolatedRefValue(decl_index, item));
944 }
945 },
946 TupleInit => {
947 if (data.type_hint.unwrap()) |type_hint|
948 hasher.add(isolatedRefValue(decl_index, type_hint))
949 else
950 hasher.add(@as(i32, std.math.maxInt(i32)));
951 writeRefListToHasher(hasher, decl_index, data.items.slice(hir));
952 },
953 else => @compileError("hash not implemented for " ++ @typeName(T)),
954 }
955}
956
957pub const SerializedHeader = extern struct {
958 const version = @import("config").version_string ++ "\x00";
959
960 instruction_len: u32,
961 string_bytes: u32,
962 extra_len: u32,
963 report_err_len: u32,
964 report_warn_len: u32,
965};
966
967pub fn serialize(hir: Hir, target: core.SerializeTarget) !void {
968 const header: SerializedHeader = .{
969 .instruction_len = @intCast(hir.insts.len),
970 .string_bytes = @intCast(hir.string_bytes.len),
971 .extra_len = @intCast(hir.extra.list.items.len),
972 .report_err_len = @intCast(hir.report.errors.len),
973 .report_warn_len = @intCast(hir.report.warnings.len),
974 };
975
976 var iovecs = [_]std.posix.iovec_const{
977 core.iovecConst(SerializedHeader.version),
978 core.iovecConst(std.mem.asBytes(&header)),
979 core.iovecConst(std.mem.sliceAsBytes(hir.insts.items(.tag))),
980 core.iovecConst(std.mem.sliceAsBytes(hir.insts.items(.data))),
981 core.iovecConst(hir.string_bytes),
982 core.iovecConst(std.mem.sliceAsBytes(hir.extra.list.items)),
983 core.iovecConst(std.mem.sliceAsBytes(hir.report.errors)),
984 core.iovecConst(std.mem.sliceAsBytes(hir.report.warnings)),
985 };
986 try target.writev(&iovecs);
987}
988
989const Hir = @This();
990
991const std = @import("std");
992const mem = std.mem;
993const assert = std.debug.assert;
994const HashHelper = std.Build.Cache.HashHelper;
995
996const core = @import("mod.zig");
997const Cache = core.Cache;
998
999const Ast = core.Ast;
1000const Unused = Ast.Unused;
1001const NodeIndex = Ast.NodeIndex;
1002const TokenIndex = Ast.TokenIndex;
1003const OptionalNodeIndex = Ast.OptionalNodeIndex;
1004const OptionalTokenIndex = Ast.OptionalTokenIndex;
1005const OptionalExtraIndex = Ast.OptionalExtraIndex;
1006
1007const dod = core.array;
1008const Float = dod.Float;
1009
1010const InternPool = core.InternPool;
1011
1012const Air = core.Air;
1013
1014const Comp = core.Comp;
1015
1016const Report = core.Report;
1017const LazyNode = Report.LazyNode;
src/core/InternPool.zig+6-6
......@@ -638,7 +638,7 @@ pub const ExtraIndex = ExtraStore.Index;
638638/// This is specified with an integer literal and a corresponding comptime
639639/// assert below to break an unfortunate and arguably incorrect dependency loop
640640/// when compiling.
641pub const static_len = Teg.Inst.Index.static_len;
641pub const static_len = Hir.Inst.Index.static_len;
642642comptime {
643643 // @compileLog(static_len, static_keys.len);
644644 assert(static_len == static_keys.len);
......@@ -805,16 +805,16 @@ pub const NullTerminatedString = enum(u32) {
805805
806806pub const TrackedInst = extern struct {
807807 path_digest: Cache.BinDigest,
808 inst: Teg.Inst.Index,
808 inst: Hir.Inst.Index,
809809
810810 comptime {
811811 // The fields should be tightly packed. See also serialization logic in `Compilation.saveState`.
812 assert(@sizeOf(@This()) == Cache.bin_digest_len + @sizeOf(Teg.Inst.Index));
812 assert(@sizeOf(@This()) == Cache.bin_digest_len + @sizeOf(Hir.Inst.Index));
813813 }
814814
815815 pub const Index = enum(u32) {
816816 _,
817 pub fn resolve(i: TrackedInst.Index, ip: *const InternPool) Teg.Inst.Index {
817 pub fn resolve(i: TrackedInst.Index, ip: *const InternPool) Hir.Inst.Index {
818818 return i.get(ip).inst;
819819 }
820820
......@@ -1659,7 +1659,7 @@ fn getOrPutTrailingString(
16591659 }
16601660}
16611661
1662pub fn trackInst(ip: *InternPool, gpa: Allocator, file: *Comp.File, inst: Teg.Inst.Index) Allocator.Error!TrackedInst.Index {
1662pub fn trackInst(ip: *InternPool, gpa: Allocator, file: *Comp.File, inst: Hir.Inst.Index) Allocator.Error!TrackedInst.Index {
16631663 const t = tracer.trace(@src());
16641664 defer t.end();
16651665
......@@ -1869,7 +1869,7 @@ const assert = std.debug.assert;
18691869const core = @import("mod.zig");
18701870const Comp = core.Comp;
18711871const Cache = core.Cache;
1872const Teg = core.Teg;
1872const Hir = core.Hir;
18731873const Air = core.Air;
18741874const dod = core.array;
18751875const Float = dod.Float;
src/core/Report.zig+8-8
......@@ -1093,7 +1093,7 @@ pub const MsgContext = struct {
10931093pub const LazyNode = struct {
10941094 // TODO: remove this, it should be inferable off of the analysis unit that belongs to the report
10951095 decl: Comp.Decl.Index,
1096 inst: Teg.Inst.Index,
1096 inst: Hir.Inst.Index,
10971097 operand: Operand,
10981098
10991099 pub fn get(lazy: LazyNode, ctx: *MsgContext) !NodeIndex {
......@@ -1111,15 +1111,15 @@ pub const LazyNode = struct {
11111111 @panic("TODO: LazyNode.get when the decl is in a nested namespace");
11121112 }
11131113
1114 const teg = &(ctx.file.?.teg orelse
1114 const hir = &(ctx.file.?.hir orelse
11151115 // this will be required once incremental compilation hits
1116 @panic("TODO: teg was unloaded"));
1116 @panic("TODO: hir was unloaded"));
11171117
11181118 const decl_inst = decl.teg_decl_index;
11191119
1120 const teg_decl = teg.instData(.declaration, decl_inst.resolve(ctx.ip()));
1120 const teg_decl = hir.instData(.declaration, decl_inst.resolve(ctx.ip()));
11211121
1122 const node_offset = teg.instNodeOffset(lazy.inst);
1122 const node_offset = hir.instNodeOffset(lazy.inst);
11231123
11241124 const base_node: NodeIndex = @intCast(teg_decl.src_node + node_offset);
11251125 if (lazy.operand == .main_node)
......@@ -1129,7 +1129,7 @@ pub const LazyNode = struct {
11291129
11301130 const node_tag = ctx.ast.nodeTag(base_node);
11311131
1132 switch (teg.instTag(lazy.inst)) {
1132 switch (hir.instTag(lazy.inst)) {
11331133 .coercion => switch (node_tag) {
11341134 .var_decl => switch (lazy.operand) {
11351135 .lhs => return data.var_decl.type.unwrap().?,
......@@ -1213,7 +1213,7 @@ pub const LazyNode = struct {
12131213 }
12141214
12151215 std.debug.print("TODO: operand lookup: .{s} + .{s} + {}\n", .{
1216 @tagName(teg.instTag(lazy.inst)),
1216 @tagName(hir.instTag(lazy.inst)),
12171217 @tagName(ctx.ast.nodeTag(base_node)),
12181218 lazy.operand,
12191219 });
......@@ -1467,7 +1467,7 @@ const TokenIndex = Ast.TokenIndex;
14671467const NodeIndex = Ast.NodeIndex;
14681468const Location = Ast.Location;
14691469
1470const Teg = core.Teg;
1470const Hir = core.Hir;
14711471
14721472const Comp = core.Comp;
14731473const File = Comp.File;
src/core/Sema.zig+91-95
......@@ -1,13 +1,9 @@
1//! Semantic Analysis converts `Teg`
1//! Semantic Analysis converts `Hir` to `Air` by stepping over every instruction
2//! and evaluating comptime values or emitting runtime instructions.
23//!
3//! Designed as a nonrecursive state machine which can be paused when an
4//! unfinished dependency is encountered, allowing the thread to work
5//! on other analysis jobs.
6//!
7//! Sema's responsibilities include
8//! - Operation validation and reporting of most compile errors.
9//! - Evaluation of `comptime` code.
10//! - Declaring dependencies on other analysis units.
4//! Designed as a nonrecursive state machine, `Sema` can be paused when an
5//! unfinished dependency is encountered, allowing the thread to work on other
6//! analysis jobs.
117
128comp: *Comp,
139ip: *InternPool,
......@@ -20,13 +16,13 @@ owner: AnalysisUnit,
2016/// The namespace index that is used for declaration lookups
2117ns_index: Namespace.Index,
2218/// Non-owning copy
23teg: Teg,
24/// The file that .teg is from
19hir: Hir,
20/// The file that .hir is from
2521file: *File,
2622
2723/// All errors and warnings from this decl
2824report: Report.Builder,
29/// Map of `Teg` instructions to their resulting `Air` Ref
25/// Map of `Hir` instructions to their resulting `Air` Ref
3026inst_map: InstMap,
3127
3228/// `null` when not analyzing function bodies
......@@ -63,7 +59,7 @@ pub fn init(
6359 s: *Sema,
6460 comp: *Comp,
6561 file: *File,
66 teg: Teg,
62 hir: Hir,
6763 owner: AnalysisUnit,
6864 ns_index: Namespace.Index,
6965 arena_state: std.heap.ArenaAllocator,
......@@ -82,7 +78,7 @@ pub fn init(
8278 .arena_state = arena_state,
8379 .owner = owner,
8480 .ns_index = ns_index,
85 .teg = teg,
81 .hir = hir,
8682 .file = file,
8783
8884 .report = .init(comp.gpa),
......@@ -102,12 +98,12 @@ pub fn init(
10298 const first_instruction, const count = switch (owner.unwrap()) {
10399 .decl => |decl| data: {
104100 const decl_inst = s.ip.declPtr(decl).teg_decl_index.resolve(s.ip);
105 const teg_decl: Teg.Decl = teg.instPayload(.declaration, decl_inst);
101 const teg_decl: Hir.Decl = hir.instPayload(.declaration, decl_inst);
106102 break :data .{ decl_inst, teg_decl.instruction_count };
107103 },
108104 .func => |value| data: {
109105 const func_inst = value.toKey(s.ip).func.teg_body_inst.get(s.ip);
110 const func: Teg.Func = teg.instPayload(.func, func_inst.inst);
106 const func: Hir.Func = hir.instPayload(.func, func_inst.inst);
111107 break :data .{ func.body, func.instruction_count };
112108 },
113109 };
......@@ -115,7 +111,7 @@ pub fn init(
115111 s.inst_map = try .init(s.arena(), first_instruction, count);
116112
117113 const block_index = switch (owner.unwrap()) {
118 .decl => switch (s.teg.declData(first_instruction).body.decode()) {
114 .decl => switch (s.hir.declData(first_instruction).body.decode()) {
119115 .index => |index| index,
120116 .value => unreachable, // Sema must not be created for a static value
121117 },
......@@ -165,11 +161,11 @@ const AnalysisMode = enum {
165161};
166162
167163const Frame = struct {
168 ip: [*]const Teg.Inst.Index,
164 ip: [*]const Hir.Inst.Index,
169165 instructions_left: if (runtime_safety) usize else void,
170166
171167 mode: AnalysisMode,
172 block_index: Teg.Inst.Index,
168 block_index: Hir.Inst.Index,
173169 mark_index: u32,
174170 data: Data,
175171
......@@ -192,15 +188,15 @@ const Frame = struct {
192188 argument: u16,
193189 };
194190
195 fn initFromBlock(s: *Sema, block_index: Teg.Inst.Index, mode: AnalysisMode, data: Data) Frame {
196 switch (s.teg.instTag(block_index)) {
191 fn initFromBlock(s: *Sema, block_index: Hir.Inst.Index, mode: AnalysisMode, data: Data) Frame {
192 switch (s.hir.instTag(block_index)) {
197193 else => unreachable, // not a block
198194 .block, .@"comptime" => {},
199195 }
200 const list = s.teg.instEncodedData(block_index)
201 .decodeUnsafe(Teg.PlNode(Teg.IndexList), s.teg.instTag(block_index))
202 .extra_index.get(&s.teg)
203 .slice(&s.teg);
196 const list = s.hir.instEncodedData(block_index)
197 .decodeUnsafe(Hir.PlNode(Hir.IndexList), s.hir.instTag(block_index))
198 .extra_index.get(&s.hir)
199 .slice(&s.hir);
204200 return .{
205201 .ip = list[0..].ptr,
206202 .instructions_left = if (runtime_safety) list.len,
......@@ -211,12 +207,12 @@ const Frame = struct {
211207 };
212208 }
213209
214 fn currentIndex(frame: *const Frame) Teg.Inst.Index {
210 fn currentIndex(frame: *const Frame) Hir.Inst.Index {
215211 // validate the pointer is correct
216212 if (runtime_safety) {
217213 const s: *const Sema = @fieldParentPtr("frame", frame);
218214 assert(s.magic == .valid);
219 const extra = s.teg.extra.list.items;
215 const extra = s.hir.extra.list.items;
220216 assert(@intFromPtr(frame.ip) > @intFromPtr(extra.ptr) and
221217 @intFromPtr(frame.ip) <= @intFromPtr(&extra.ptr[extra.len - 1]));
222218 }
......@@ -224,22 +220,22 @@ const Frame = struct {
224220 return frame.ip[0];
225221 }
226222
227 fn currentTag(frame: *const Frame) Teg.Tag {
223 fn currentTag(frame: *const Frame) Hir.Tag {
228224 const s: *const Sema = @fieldParentPtr("frame", frame);
229225 assert(s.magic == .valid);
230 return s.teg.instTag(frame.currentIndex());
226 return s.hir.instTag(frame.currentIndex());
231227 }
232228
233 fn currentData(frame: *const Frame, comptime tag: Teg.Tag) tag.Data() {
229 fn currentData(frame: *const Frame, comptime tag: Hir.Tag) tag.Data() {
234230 const s: *const Sema = @fieldParentPtr("frame", frame);
235231 assert(s.magic == .valid);
236 return s.teg.instData(tag, frame.currentIndex());
232 return s.hir.instData(tag, frame.currentIndex());
237233 }
238234
239 fn currentPayload(frame: *const Frame, comptime tag: Teg.Tag) tag.Data().T {
235 fn currentPayload(frame: *const Frame, comptime tag: Hir.Tag) tag.Data().T {
240236 const s: *const Sema = @fieldParentPtr("frame", frame);
241237 assert(s.magic == .valid);
242 return s.teg.instPayload(tag, frame.currentIndex());
238 return s.hir.instPayload(tag, frame.currentIndex());
243239 }
244240
245241 fn advance(frame: *Frame) void {
......@@ -282,10 +278,10 @@ const Function = struct {
282278/// instructions it has.
283279const InstMap = struct {
284280 items: []Air.Inst.Ref.Optional,
285 start: Teg.Inst.Index,
281 start: Hir.Inst.Index,
286282 debug_traces: if (runtime_safety) []StoredTrace else void,
287283
288 pub fn init(allocator: Allocator, inst_start: Teg.Inst.Index, inst_len: u32) !InstMap {
284 pub fn init(allocator: Allocator, inst_start: Hir.Inst.Index, inst_len: u32) !InstMap {
289285 const insts = try allocator.alloc(Air.Inst.Ref.Optional, inst_len);
290286 errdefer allocator.free(insts);
291287
......@@ -309,7 +305,7 @@ const InstMap = struct {
309305 map.* = undefined;
310306 }
311307
312 pub fn getOrNull(map: *const InstMap, teg_code: Teg.Inst.Index) ?Air.Inst.Ref {
308 pub fn getOrNull(map: *const InstMap, teg_code: Hir.Inst.Index) ?Air.Inst.Ref {
313309 const source_i = @intFromEnum(teg_code);
314310 const start_i = @intFromEnum(map.start);
315311 if (assertFailed(source_i >= start_i and source_i <= start_i + map.items.len)) {
......@@ -322,7 +318,7 @@ const InstMap = struct {
322318 return map.items[source_i - start_i].unwrap();
323319 }
324320
325 pub fn get(map: *const InstMap, teg_code: Teg.Inst.Index) Air.Inst.Ref {
321 pub fn get(map: *const InstMap, teg_code: Hir.Inst.Index) Air.Inst.Ref {
326322 return map.getOrNull(teg_code) orelse {
327323 if (runtime_safety) {
328324 std.debug.panic("did not analyze %{d}", .{@intFromEnum(teg_code)});
......@@ -331,7 +327,7 @@ const InstMap = struct {
331327 };
332328 }
333329
334 pub fn add(map: *InstMap, from: Teg.Inst.Index, to: Air.Inst.Ref) void {
330 pub fn add(map: *InstMap, from: Hir.Inst.Index, to: Air.Inst.Ref) void {
335331 const source_i = @intFromEnum(from);
336332 const start_i = @intFromEnum(map.start);
337333 if (assertFailed(source_i >= start_i and source_i <= start_i + map.items.len)) {
......@@ -371,7 +367,7 @@ const DoMark = enum {
371367 marked,
372368};
373369
374fn getRef(s: *Sema, teg_ref: Teg.Inst.Ref, mark: DoMark) Air.Inst.Ref {
370fn getRef(s: *Sema, teg_ref: Hir.Inst.Ref, mark: DoMark) Air.Inst.Ref {
375371 switch (teg_ref.decode()) {
376372 .value => |value| return value.toAir(),
377373 .index => |index| {
......@@ -389,7 +385,7 @@ fn getRef(s: *Sema, teg_ref: Teg.Inst.Ref, mark: DoMark) Air.Inst.Ref {
389385 }
390386}
391387
392fn getValue(s: *Sema, src: LazyNode, teg_ref: Teg.Inst.Ref) !Value {
388fn getValue(s: *Sema, src: LazyNode, teg_ref: Hir.Inst.Ref) !Value {
393389 switch (teg_ref.decode()) {
394390 .value => |value| return value,
395391 .index => |index| {
......@@ -399,17 +395,17 @@ fn getValue(s: *Sema, src: LazyNode, teg_ref: Teg.Inst.Ref) !Value {
399395 }
400396}
401397
402fn getCoercedValue(s: *Sema, src: LazyNode, teg_ref: Teg.Inst.Ref, ty: Type) !Value {
398fn getCoercedValue(s: *Sema, src: LazyNode, teg_ref: Hir.Inst.Ref, ty: Type) !Value {
403399 const any = try s.getValue(src, teg_ref);
404400 return try s.coerceValue(src, any, ty);
405401}
406402
407fn getCoercedRef(s: *Sema, src: LazyNode, teg_ref: Teg.Inst.Ref, ty: Type, mark: DoMark) !Air.Inst.Ref {
403fn getCoercedRef(s: *Sema, src: LazyNode, teg_ref: Hir.Inst.Ref, ty: Type, mark: DoMark) !Air.Inst.Ref {
408404 const any = s.getRef(teg_ref, mark);
409405 return try s.coerceRef(src, any, ty);
410406}
411407
412fn getType(s: *Sema, src: LazyNode, teg_ref: Teg.Inst.Ref) !Type {
408fn getType(s: *Sema, src: LazyNode, teg_ref: Hir.Inst.Ref) !Type {
413409 return (try s.getCoercedValue(src, teg_ref, .type)).toTypeUnsafe(s.ip);
414410}
415411
......@@ -491,7 +487,7 @@ const InstructionKind = enum {
491487 control_flow,
492488 pop_control_flow,
493489
494 pub inline fn fromTag(tag: Teg.Tag) InstructionKind {
490 pub inline fn fromTag(tag: Hir.Tag) InstructionKind {
495491 return switch (tag) {
496492 // these push new frames, and frame end will assign its value
497493 .func,
......@@ -523,7 +519,7 @@ const InstructionKind = enum {
523519
524520const PopControlFlowState = enum { stop, @"continue" };
525521
526fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag).Result() {
522fn stepInner(s: *Sema, comptime tag: Hir.Tag) Error!InstructionKind.fromTag(tag).Result() {
527523 switch (tag) {
528524 .block => unreachable, // frame must already be pushed
529525 .declaration,
......@@ -534,7 +530,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
534530 // TODO: pre-evaluate `.param` nodes, since they are always at the start of a function.
535531 // this way we can avoid repeating the non-trivial call into InternPool
536532 .param => {
537 const param: Teg.DataNode = s.frame.currentData(.param);
533 const param: Hir.DataNode = s.frame.currentData(.param);
538534 assert(s.frame.mode == .run_time); // never emitted in a comptime block
539535 assert(s.owner.kind == .func); // only emitted in function body
540536 const proto = s.owner.unwrap().func.toKey(s.ip).func.ty.toUnresolvedFunctionPrototype(s.ip).?;
......@@ -550,8 +546,8 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
550546 }
551547 },
552548 .string => {
553 const string: Teg.SlicedString = s.frame.currentPayload(.string);
554 return s.makeValueAir(.{ .string = string.slice(s.teg.string_bytes) });
549 const string: Hir.SlicedString = s.frame.currentPayload(.string);
550 return s.makeValueAir(.{ .string = string.slice(s.hir.string_bytes) });
555551 },
556552 .number => {
557553 const number: store.Float = s.frame.currentPayload(.number);
......@@ -565,7 +561,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
565561 .gt,
566562 .eq,
567563 => {
568 const bin: Teg.Bin = s.frame.currentPayload(tag);
564 const bin: Hir.Bin = s.frame.currentPayload(tag);
569565 const op = @field(BinaryOp, @tagName(tag));
570566
571567 const lhs = s.getRef(bin.lhs, .marked);
......@@ -600,7 +596,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
600596 });
601597 },
602598 .negate => {
603 const un: Teg.RefNode = s.frame.currentData(.negate);
599 const un: Hir.RefNode = s.frame.currentData(.negate);
604600
605601 const operand = s.getRef(un.operand, .marked);
606602
......@@ -622,7 +618,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
622618 return s.addRef(.negate, .{ .operand = operand });
623619 },
624620 .bool_not => {
625 const un: Teg.RefNode = s.frame.currentData(.bool_not);
621 const un: Hir.RefNode = s.frame.currentData(.bool_not);
626622
627623 const operand = try s.getCoercedRef(s.lazyNode(.operand), un.operand, .bool, .marked);
628624
......@@ -639,7 +635,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
639635 return s.addRef(.bool_not, .{ .operand = operand });
640636 },
641637 .struct_decl => {
642 const node: Teg.StructDecl = s.frame.currentPayload(.struct_decl);
638 const node: Hir.StructDecl = s.frame.currentPayload(.struct_decl);
643639
644640 const scratch = try s.scratch.reserveMulti(
645641 s.arena(),
......@@ -649,12 +645,12 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
649645 defer scratch.deinit();
650646
651647 // Fill the first half with keys
652 for (scratch.items(.keys), node.keys(&s.teg)) |*dest, src| {
653 dest.* = try s.ip.getOrPutString(s.gpa, src.slice(s.teg.string_bytes), .no_embedded_nulls);
648 for (scratch.items(.keys), node.keys(&s.hir)) |*dest, src| {
649 dest.* = try s.ip.getOrPutString(s.gpa, src.slice(s.hir.string_bytes), .no_embedded_nulls);
654650 }
655651
656652 // Fill the second half with coerced values.
657 for (node.types(&s.teg), 0..) |ty, i| {
653 for (node.types(&s.hir), 0..) |ty, i| {
658654 scratch.at(.types, i).* = try s.getType(s.lazyNode(.argument(@intCast(i))), ty);
659655 }
660656
......@@ -688,7 +684,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
688684 } });
689685 },
690686 .field => {
691 const field: Teg.Bin = s.frame.currentPayload(.field);
687 const field: Hir.Bin = s.frame.currentPayload(.field);
692688 const lhs = s.getRef(field.lhs, .marked);
693689 const lhs_type = s.typeOfRef(lhs);
694690
......@@ -733,7 +729,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
733729 });
734730 },
735731 .call => {
736 const call: Teg.Call = s.frame.currentPayload(.call);
732 const call: Hir.Call = s.frame.currentPayload(.call);
737733 const base = s.getRef(call.base, .marked);
738734 const base_type = s.typeOfRef(base);
739735
......@@ -759,7 +755,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
759755 }
760756
761757 // validate function args
762 for (proto.param_types, call.args.slice(&s.teg), 0..) |param, arg, i| {
758 for (proto.param_types, call.args.slice(&s.hir), 0..) |param, arg, i| {
763759 const ref = s.getRef(arg, .marked);
764760 const coerced = try s.coerceRef(
765761 s.lazyNode(.argument(@intCast(i))),
......@@ -769,7 +765,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
769765 scratch[i] = coerced;
770766 }
771767 } else {
772 for (call.args.slice(&s.teg), 0..) |arg, i| {
768 for (call.args.slice(&s.hir), 0..) |arg, i| {
773769 const ref = try s.ensureValueDefinedRepresentation(
774770 s.lazyNode(.argument(@intCast(i))),
775771 s.getRef(arg, .marked),
......@@ -792,7 +788,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
792788 });
793789 },
794790 .array_init => {
795 const node: Teg.ArrayInit = s.frame.currentPayload(.array_init);
791 const node: Hir.ArrayInit = s.frame.currentPayload(.array_init);
796792
797793 assert(node.list.len > 0 or node.type_hint.unwrap() != null);
798794
......@@ -806,7 +802,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
806802
807803 var is_constant = true;
808804
809 for (node.list.slice(&s.teg), 0..) |item_teg_ref, i| {
805 for (node.list.slice(&s.hir), 0..) |item_teg_ref, i| {
810806 const item = s.getRef(item_teg_ref, .marked);
811807 const coerced = if (item_type) |ty|
812808 try s.coerceRef(s.lazyNode(.argument(@intCast(i))), item, ty)
......@@ -862,8 +858,8 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
862858 });
863859 },
864860 .store => {
865 const data: Teg.Store = s.frame.currentPayload(.store);
866 assert(s.teg.instTag(data.memory) == .memory); // corrupt store instruction
861 const data: Hir.Store = s.frame.currentPayload(.store);
862 assert(s.hir.instTag(data.memory) == .memory); // corrupt store instruction
867863
868864 try s.ensureAtRuntime(s.lazyNode(.main_node)); // TODO
869865
......@@ -885,7 +881,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
885881 },
886882
887883 .js_new => {
888 const call: Teg.JsNew = s.frame.currentPayload(.js_new);
884 const call: Hir.JsNew = s.frame.currentPayload(.js_new);
889885
890886 try s.ensureAtRuntime(s.lazyNode(.main_node));
891887
......@@ -893,7 +889,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
893889
894890 const scratch = try s.arena().alloc(Air.Inst.Ref, call.args.len);
895891 defer s.arena().free(scratch);
896 for (call.args.slice(&s.teg), 0..) |arg, i| {
892 for (call.args.slice(&s.hir), 0..) |arg, i| {
897893 const ref = try s.ensureValueDefinedRepresentation(
898894 s.lazyNode(.argument(@intCast(i))),
899895 s.getRef(arg, .marked),
......@@ -924,7 +920,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
924920 },
925921
926922 .func => {
927 const data: Teg.Func = s.frame.currentPayload(.func);
923 const data: Hir.Func = s.frame.currentPayload(.func);
928924 const reserve = try s.scratch.reserveMulti(
929925 s.arena(),
930926 .{ .params = Type, .captures = Air.Inst.Ref },
......@@ -937,7 +933,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
937933 defer handled_reserve.assertUnlocked();
938934 errdefer handled_reserve.unlock();
939935
940 for (data.params.slice(&s.teg), 0..) |param, i| {
936 for (data.params.slice(&s.hir), 0..) |param, i| {
941937 const src = s.lazyNode(.argument(@intCast(i)));
942938
943939 const known = param.unwrap() orelse @panic("TODO: inferred param sets");
......@@ -991,7 +987,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
991987 },
992988
993989 .@"break" => {
994 const brk: Teg.Break = s.frame.currentPayload(.@"break");
990 const brk: Hir.Break = s.frame.currentPayload(.@"break");
995991 const operand = s.getRef(brk.operand, .marked);
996992
997993 assert(s.frame.block_index == brk.block);
......@@ -1036,7 +1032,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
10361032 s.frame.advance();
10371033 },
10381034 .@"if" => {
1039 const if_data: Teg.If = s.frame.currentPayload(.@"if");
1035 const if_data: Hir.If = s.frame.currentPayload(.@"if");
10401036
10411037 switch (data.conditional) {
10421038 .comptime_condition => {
......@@ -1093,7 +1089,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
10931089 s.frame.advance();
10941090 },
10951091 .func => {
1096 const func_data: Teg.Func = s.frame.currentPayload(.func);
1092 const func_data: Hir.Func = s.frame.currentPayload(.func);
10971093
10981094 const reserve: FunctionReserve = .fromIndex(
10991095 &s.scratch,
......@@ -1104,7 +1100,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
11041100 const return_type = switch (data.func) {
11051101 .argument => |arg_num| ret: {
11061102 for (
1107 func_data.params.slice(&s.teg)[arg_num + 1 ..],
1103 func_data.params.slice(&s.hir)[arg_num + 1 ..],
11081104 reserve.items(.params)[arg_num + 1 ..],
11091105 arg_num + 1..,
11101106 ) |param, *dst, i| {
......@@ -1172,10 +1168,10 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
11721168 },
11731169
11741170 .load_decl => {
1175 const request: Teg.StrNode = s.frame.currentData(.load_decl);
1171 const request: Hir.StrNode = s.frame.currentData(.load_decl);
11761172 const decl_name = try s.ip.getOrPutString(
11771173 s.gpa,
1178 request.string.slice(s.teg.string_bytes),
1174 request.string.slice(s.hir.string_bytes),
11791175 .no_embedded_nulls,
11801176 );
11811177 const decl_index = s.lookupDecl(decl_name);
......@@ -1183,13 +1179,13 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
11831179 },
11841180
11851181 .coercion => {
1186 const as: Teg.Coercion = s.frame.currentPayload(.coercion);
1182 const as: Hir.Coercion = s.frame.currentPayload(.coercion);
11871183 const coerce_to = try s.getType(s.lazyNode(.operand), as.type);
11881184 return try s.getCoercedRef(s.lazyNode(.operand), as.operand, coerce_to, .marked);
11891185 },
11901186
11911187 .compile_error => {
1192 const node: Teg.RefNode = s.frame.currentData(.compile_error);
1188 const node: Hir.RefNode = s.frame.currentData(.compile_error);
11931189 const value = try s.getCoercedValue(s.lazyNode(.operand), node.operand, .string);
11941190 const str = value.asString(s.ip).toSlice(s.ip);
11951191 return s.fail(.user_compile_error, .{
......@@ -1199,7 +1195,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
11991195 },
12001196
12011197 .@"if" => {
1202 const data: Teg.If = s.frame.currentPayload(.@"if");
1198 const data: Hir.If = s.frame.currentPayload(.@"if");
12031199
12041200 const condition = try s.getCoercedRef(s.lazyNode(.operand), data.cond, .bool, .marked);
12051201 switch (condition.decode()) {
......@@ -1270,7 +1266,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
12701266 },
12711267
12721268 .struct_init => {
1273 const node: Teg.StructInit = s.frame.currentPayload(.struct_init);
1269 const node: Hir.StructInit = s.frame.currentPayload(.struct_init);
12741270
12751271 // Ensure we have a valid struct to operate on
12761272 const ty = try s.getType(s.lazyNode(.operand), node.base_type);
......@@ -1295,9 +1291,9 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
12951291 // The ordering of `storage` is defined by the struct's type, which
12961292 // may be different than the instantiation. The fields are visited in
12971293 // order of the instantiation.
1298 for (node.keys(&s.teg), node.inits(&s.teg), 0..) |init_key, init_value, i| {
1294 for (node.keys(&s.hir), node.inits(&s.hir), 0..) |init_key, init_value, i| {
12991295 const found_index = index: for (struct_type.field_keys, 0..) |decl_key, j| {
1300 if (decl_key.eqlSlice(init_key.slice(s.teg.string_bytes), s.ip))
1296 if (decl_key.eqlSlice(init_key.slice(s.hir.string_bytes), s.ip))
13011297 break :index j;
13021298 } else {
13031299 has_errors = true;
......@@ -1374,18 +1370,18 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
13741370 },
13751371
13761372 .array_type => {
1377 const un: Teg.RefNode = s.frame.currentData(.array_type);
1373 const un: Hir.RefNode = s.frame.currentData(.array_type);
13781374 const operand = try s.getType(s.lazyNode(.operand), un.operand);
13791375 return s.makeValueAir(.{ .array_type = .{ .item_type = operand } });
13801376 },
13811377
13821378 .tuple_type => {
1383 const data: Teg.TupleType = s.frame.currentPayload(.tuple_type);
1379 const data: Hir.TupleType = s.frame.currentPayload(.tuple_type);
13841380
13851381 const scratch = try s.scratch.reserve(s.arena(), Type, data.items.len);
13861382 defer scratch.deinit();
13871383
1388 for (data.items.slice(&s.teg), scratch.slice(), 0..) |src, *dst, i| {
1384 for (data.items.slice(&s.hir), scratch.slice(), 0..) |src, *dst, i| {
13891385 dst.* = try s.getType(s.lazyNode(.argument(@intCast(i))), src);
13901386 }
13911387
......@@ -1393,7 +1389,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
13931389 },
13941390
13951391 .tuple_init => {
1396 const data: Teg.TupleInit = s.frame.currentPayload(.tuple_init);
1392 const data: Hir.TupleInit = s.frame.currentPayload(.tuple_init);
13971393
13981394 _ = data.type_hint; // TODO: use type hint
13991395
......@@ -1401,7 +1397,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
14011397 defer scratch.deinit();
14021398
14031399 var is_const = true;
1404 for (data.items.slice(&s.teg), scratch.slice()) |src, *dst| {
1400 for (data.items.slice(&s.hir), scratch.slice()) |src, *dst| {
14051401 const result = s.getRef(src, .marked);
14061402 dst.* = result;
14071403 if (result.kind == .index) is_const = false;
......@@ -1447,7 +1443,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
14471443 },
14481444
14491445 .result_type_argument => {
1450 const result: Teg.ResultTypeArgument = s.frame.currentData(.result_type_argument);
1446 const result: Hir.ResultTypeArgument = s.frame.currentData(.result_type_argument);
14511447
14521448 const operand = s.getRef(result.call_base, .no_mark);
14531449 const ty = s.typeOfRef(operand);
......@@ -1462,7 +1458,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
14621458 },
14631459
14641460 .result_type_array_value => {
1465 const result: Teg.ResultTypeArrayValue = s.frame.currentData(.result_type_array_value);
1461 const result: Hir.ResultTypeArrayValue = s.frame.currentData(.result_type_array_value);
14661462
14671463 const operand = try s.getValue(s.lazyNode(.main_node), result.type);
14681464 const ty = operand.toType(s.ip) orelse
......@@ -1475,7 +1471,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
14751471 },
14761472
14771473 .result_type_tuple_field => {
1478 const result: Teg.ResultTypeTupleField = s.frame.currentData(.result_type_tuple_field);
1474 const result: Hir.ResultTypeTupleField = s.frame.currentData(.result_type_tuple_field);
14791475
14801476 const operand = try s.getValue(s.lazyNode(.main_node), result.type);
14811477 const ty = operand.toType(s.ip) orelse
......@@ -1487,7 +1483,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
14871483 },
14881484
14891485 .result_type_struct_field => {
1490 const result: Teg.ResultTypeStructField = s.frame.currentData(.result_type_struct_field);
1486 const result: Hir.ResultTypeStructField = s.frame.currentData(.result_type_struct_field);
14911487
14921488 const operand = try s.getValue(s.lazyNode(.main_node), result.type);
14931489 const ty = operand.toType(s.ip) orelse
......@@ -1496,7 +1492,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
14961492 const struct_type = ty.toStructType(s.ip) orelse
14971493 return Value.opaque_type.toAir();
14981494
1499 const to_match = result.field.slice(s.teg.string_bytes);
1495 const to_match = result.field.slice(s.hir.string_bytes);
15001496 for (struct_type.field_keys, struct_type.field_types) |k, v| {
15011497 if (k.eqlSlice(to_match, s.ip)) {
15021498 return v.value().toAir();
......@@ -1512,7 +1508,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
15121508
15131509fn emitRuntimeBlock(
15141510 s: *Sema,
1515 from: Teg.Inst.Index,
1511 from: Hir.Inst.Index,
15161512 break_operand: Air.Inst.Ref,
15171513 mark: core.U32Stack.Mark,
15181514) !void {
......@@ -1553,7 +1549,7 @@ const BinaryOp = enum {
15531549 eq,
15541550};
15551551
1556fn binTypeResolution(s: *Sema, src: Teg.Inst.Index, op: BinaryOp, lhs: Type, rhs: Type) !Type {
1552fn binTypeResolution(s: *Sema, src: Hir.Inst.Index, op: BinaryOp, lhs: Type, rhs: Type) !Type {
15571553 if (lhs == .@"opaque") {
15581554 return if (rhs == .numeric_literal) .float else rhs;
15591555 }
......@@ -2084,7 +2080,7 @@ fn fieldAccessStruct(
20842080 lhs: Air.Inst.Ref,
20852081 lhs_type: Type,
20862082 struct_type: InternPool.Key.StructType,
2087 field: Teg.Inst.Ref,
2083 field: Hir.Inst.Ref,
20882084) !Air.Inst.Ref {
20892085 const rhs = try s.getCoercedValue(s.lazyNode(.rhs), field, .string);
20902086 const string = rhs.asString(s.ip);
......@@ -2125,7 +2121,7 @@ fn fieldAccessStruct(
21252121 }
21262122}
21272123
2128fn fieldAccessArray(s: *Sema, lhs: Air.Inst.Ref, lhs_type: Type, rhs_teg: Teg.Inst.Ref) !Air.Inst.Ref {
2124fn fieldAccessArray(s: *Sema, lhs: Air.Inst.Ref, lhs_type: Type, rhs_teg: Hir.Inst.Ref) !Air.Inst.Ref {
21292125 const rhs = s.getRef(rhs_teg, .marked);
21302126
21312127 switch (s.typeOfRef(rhs)) {
......@@ -2176,7 +2172,7 @@ fn fieldAccessTuple(
21762172 lhs: Air.Inst.Ref,
21772173 lhs_type: Type,
21782174 tuple_type: InternPool.Key.TupleType,
2179 field: Teg.Inst.Ref,
2175 field: Hir.Inst.Ref,
21802176) !Air.Inst.Ref {
21812177 const index_value = try s.getCoercedValue(s.lazyNode(.rhs), field, .int32);
21822178 const index_signed = index_value.toInt32(s.ip) orelse unreachable;
......@@ -2387,7 +2383,7 @@ const File = Comp.File;
23872383const Decl = Comp.Decl;
23882384const Namespace = Comp.Namespace;
23892385
2390const Teg = core.Teg;
2386const Hir = core.Hir;
23912387
23922388const Air = core.Air;
23932389const Ast = core.Ast;
src/core/StoredTrace.zig+3-3
......@@ -1,6 +1,6 @@
1//! A variant of std.builtin.StackTrace that stores its data within itself
2//! instead of being a pointer. This allows capturing the stack trace and
3//! saving it for later printing.
1//! A variant of `std.builtin.StackTrace` that stores its data within itself
2//! instead of being a pointer. This allows storing captured stack traces
3//! for later printing.
44
55data: [31]usize,
66index: usize,
src/core/Teg.Dump.zig deleted-522
......@@ -1,522 +0,0 @@
1//! This implements a debug formatter for Teg
2teg: Teg,
3tty: ?std.io.tty.Config = null,
4
5const State = struct {
6 arena: std.mem.Allocator,
7 teg: *const Teg,
8 indent: usize = 0,
9 tty: std.io.tty.Config,
10 visited: std.AutoHashMapUnmanaged(Teg.Inst.Index, void) = .{},
11
12 fn newline(state: State, writer: anytype) !void {
13 try writer.writeByte('\n');
14 if (state.indent > 0)
15 try writer.writeByteNTimes(' ', state.indent * 2);
16 }
17
18 fn dumpInst(s: *State, writer: anytype, inst: Teg.Inst.Index) @TypeOf(writer).Error!void {
19 const teg = s.teg;
20 const tty = s.tty;
21
22 try writer.print("%{} = ", .{@intFromEnum(inst)});
23
24 const tag = s.teg.instTag(inst);
25
26 try tty.setColor(writer, .bright_black);
27 const node_offset = teg.instNodeOffset(inst);
28 try writer.print("{c}{d} ", .{
29 @as(u8, if (node_offset >= 0) '+' else '-'),
30 @abs(node_offset),
31 });
32 try tty.setColor(writer, .reset);
33
34 try tty.setColor(writer, .cyan);
35 try writer.print("{s}", .{@tagName(tag)});
36 try tty.setColor(writer, .reset);
37
38 if ((try s.visited.fetchPut(s.arena, inst, {})) != null) {
39 try tty.setColor(writer, .red);
40 try writer.writeAll(" [error: recursive tree]");
41 try tty.setColor(writer, .reset);
42 return;
43 }
44
45 switch (tag) {
46 .module => {
47 try s.dumpInstList(writer, teg.moduleDeclarations(inst), '{', '}');
48 },
49 .declaration, .variable_declaration, .test_declaration => {
50 const decl = teg.fullDecl(inst);
51
52 try writer.writeAll(" ");
53 const name = decl.name.slice(teg.string_bytes);
54 if (name.len == 0) {
55 try tty.setColor(writer, .bold);
56 try writer.writeAll("[no name]");
57 } else {
58 try tty.setColor(writer, .magenta);
59 try writer.writeAll(name);
60 }
61 try tty.setColor(writer, .reset);
62 try writer.writeAll(" (");
63 try writer.print("{d}", .{decl.instruction_count});
64 try writer.writeAll(")");
65 try tty.setColor(writer, .bright_black);
66 try writer.writeAll(" [");
67 try writer.writeAll(&std.fmt.bytesToHex(decl.hash, .lower));
68 try writer.writeAll("]");
69 try tty.setColor(writer, .reset);
70 try writer.writeAll(" (");
71 s.indent += 1;
72 try s.newline(writer);
73 try s.dumpRef(writer, decl.body);
74 s.indent -= 1;
75 try s.newline(writer);
76 try writer.writeAll(")");
77 },
78 .func => {
79 const func: Teg.Func = teg.instPayload(.func, inst);
80 try writer.writeAll(" {");
81 s.indent += 1;
82 try s.newline(writer);
83 try writer.writeAll("params: ");
84 try s.dumpOptionalRefList(writer, func.params.slice(teg), '[', ']');
85 try s.newline(writer);
86 try writer.writeAll("return_type: ");
87 if (func.return_type.unwrap()) |ret|
88 try s.dumpRef(writer, ret)
89 else {
90 try tty.setColor(writer, .bright_black);
91 try writer.writeAll("<inferred>");
92 try tty.setColor(writer, .reset);
93 }
94 try s.newline(writer);
95 try writer.writeAll("captures: ");
96 try s.dumpInstList2(writer, func.captures.slice(teg), '[', ']');
97 try s.newline(writer);
98 try writer.writeAll("body: ");
99 try s.dumpInst(writer, func.body);
100 s.indent -= 1;
101 try s.newline(writer);
102 try writer.writeAll("}");
103 },
104 .param => {
105 const data = teg.instData(.param, inst);
106 try writer.writeAll("(");
107 if (data.data == std.math.maxInt(u32)) {
108 try tty.setColor(writer, .bright_black);
109 try writer.writeAll("<return type>");
110 } else {
111 try tty.setColor(writer, .yellow);
112 try writer.print("{d}", .{data.data});
113 }
114 try tty.setColor(writer, .reset);
115 try writer.writeAll(")");
116 },
117 inline .block, .@"comptime" => |t| {
118 const block = teg.instData(t, inst);
119 const index_list = block.extra_index.get(teg);
120 try s.dumpInstList(writer, index_list.slice(teg), '[', ']');
121 },
122 .number => {
123 const number = teg.instData(.number, inst);
124 const float = number.extra_index.get(teg).decode();
125 try tty.setColor(writer, .yellow);
126 try writer.print(" {d}", .{float});
127 try tty.setColor(writer, .reset);
128 },
129 inline .field,
130 .index,
131 .add,
132 .sub,
133 .mul,
134 .div,
135 .rem,
136 .pow,
137 .@"and",
138 .@"or",
139 .bit_and,
140 .bit_or,
141 .bit_xor,
142 .shl,
143 .shr,
144 .eq,
145 .ne,
146 .lt,
147 .le,
148 .gt,
149 .ge,
150 => |comptime_tag| {
151 const data = teg.instData(comptime_tag, inst).extra_index.get(teg);
152 try writer.writeAll("(");
153 try s.dumpRefMarker(writer, data.lhs);
154 try writer.writeAll(", ");
155 try s.dumpRefMarker(writer, data.rhs);
156 try writer.writeAll(")");
157 },
158 .coercion => {
159 const data = teg.instData(.coercion, inst).extra_index.get(teg);
160 try writer.writeAll("(");
161 try s.dumpRefMarker(writer, data.type);
162 try writer.writeAll(", ");
163 try s.dumpRefMarker(writer, data.operand);
164 try writer.writeAll(")");
165 },
166 .@"break" => {
167 const data: Teg.Break = teg.instData(.@"break", inst).extra_index.get(teg);
168 try writer.writeAll("(");
169 try s.dumpRefMarker(writer, data.block.toRef());
170 try writer.writeAll(", ");
171 try s.dumpRefMarker(writer, data.operand);
172 try writer.writeAll(")");
173 },
174 .store => {
175 const data: Teg.Store = teg.instData(.store, inst).extra_index.get(teg);
176 try writer.writeAll("(");
177 try s.dumpRefMarker(writer, data.memory.toRef());
178 try writer.writeAll(", ");
179 try s.dumpRefMarker(writer, data.operand);
180 try writer.writeAll(")");
181 },
182 .store_field => {
183 const data: Teg.StoreField = teg.instData(.store_field, inst).extra_index.get(teg);
184 try writer.writeAll("(");
185 try s.dumpRefMarker(writer, data.base);
186 try writer.writeAll(", ");
187 try s.dumpRefMarker(writer, data.field);
188 try writer.writeAll(", ");
189 try s.dumpRefMarker(writer, data.operand);
190 try writer.writeAll(")");
191 },
192 .store_decl => {
193 const data: Teg.StoreVarDecl = teg.instData(.store_decl, inst).extra_index.get(teg);
194 try writer.writeAll("(");
195 try tty.setColor(writer, .magenta);
196 try writer.writeAll(data.var_decl.slice(teg.string_bytes));
197 try tty.setColor(writer, .reset);
198 try writer.writeAll(", ");
199 try s.dumpRefMarker(writer, data.operand);
200 try writer.writeAll(")");
201 },
202 .string => {
203 const data: Teg.SlicedString = teg.instData(.string, inst).extra_index.get(teg);
204 try tty.setColor(writer, .green);
205 try writer.writeAll(" \"");
206 try writer.writeAll(data.slice(teg.string_bytes));
207 try writer.writeAll("\"");
208 try tty.setColor(writer, .reset);
209 },
210 inline .memory,
211 .discard,
212 .ensure_void,
213 .negate,
214 .bool_not,
215 .bit_not,
216 .@"extern",
217 .import,
218 .fetch,
219 .compile_error,
220 .type_of,
221 .array_type,
222 .assert,
223 => |comptime_tag| {
224 const data = teg.instData(comptime_tag, inst);
225 try writer.writeAll("(");
226 try s.dumpRefMarker(writer, data.operand);
227 try writer.writeAll(")");
228 },
229 .call => {
230 const call: Teg.Call = teg.instData(.call, inst).extra_index.get(teg);
231 try writer.writeAll("(");
232 try s.dumpRefMarker(writer, call.base);
233 try writer.writeAll(", ");
234 try s.dumpRefMarkerList(writer, call.args.slice(teg), '[', ']');
235 try writer.writeAll(")");
236 },
237 .js_new => {
238 const call: Teg.JsNew = teg.instData(.js_new, inst).extra_index.get(teg);
239 try writer.writeAll("(");
240 try s.dumpRefMarker(writer, call.base);
241 try writer.writeAll(", ");
242 try s.dumpRefMarkerList(writer, call.args.slice(teg), '[', ']');
243 try writer.writeAll(")");
244 },
245 .load_decl => {
246 const call: Teg.StrNode = teg.instData(.load_decl, inst);
247
248 try tty.setColor(writer, .red);
249 try writer.print(" {s}", .{call.string.slice(teg.string_bytes)});
250 try tty.setColor(writer, .reset);
251 },
252 .@"if" => {
253 const data: Teg.If = teg.instPayload(.@"if", inst);
254 try writer.writeAll("(");
255 try s.dumpRefMarker(writer, data.cond);
256 try writer.writeAll(") {");
257 s.indent += 1;
258 try s.newline(writer);
259 try writer.writeAll("yes: ");
260 try s.dumpRef(writer, data.yes);
261 try s.newline(writer);
262 try writer.writeAll("no: ");
263 try s.dumpRef(writer, data.no);
264 s.indent -= 1;
265 try s.newline(writer);
266 try writer.writeAll("}");
267 },
268 .struct_decl => {
269 const data: Teg.StructDecl = teg.instPayload(.struct_decl, inst);
270 try writer.writeAll(" {");
271 s.indent += 1;
272 try s.newline(writer);
273 for (data.keys(teg), data.types(teg), 0..) |key, value, i| {
274 if (i != 0)
275 try s.newline(writer);
276 try writer.print("{s}: ", .{key.slice(teg.string_bytes)});
277 try s.dumpRefMarker(writer, value);
278 }
279 s.indent -= 1;
280 try s.newline(writer);
281 try writer.writeAll("}");
282 },
283 .struct_init => {
284 const data: Teg.StructInit = teg.instPayload(.struct_init, inst);
285 try writer.writeAll("(");
286 try s.dumpRefMarker(writer, data.base_type);
287 try writer.writeAll(") {");
288 s.indent += 1;
289 try s.newline(writer);
290 for (data.keys(teg), data.inits(teg), 0..) |key, value, i| {
291 if (i != 0)
292 try s.newline(writer);
293 try writer.print("{s}: ", .{key.slice(teg.string_bytes)});
294 try s.dumpRefMarker(writer, value);
295 }
296 s.indent -= 1;
297 try s.newline(writer);
298 try writer.writeAll("}");
299 },
300 .array_init => {
301 const data: Teg.ArrayInit = teg.instPayload(.array_init, inst);
302
303 if (data.type_hint.unwrap()) |type_hint| {
304 try writer.writeAll("(");
305 try s.dumpRef(writer, type_hint);
306 try writer.writeAll(", ");
307 }
308
309 try writer.writeAll("[");
310
311 s.indent += 1;
312
313 for (data.list.slice(teg)) |item| {
314 try s.newline(writer);
315 try s.dumpRefMarker(writer, item);
316 try writer.writeAll(",");
317 }
318
319 s.indent -= 1;
320 try s.newline(writer);
321
322 try writer.writeAll("]");
323
324 if (data.type_hint != .none)
325 try writer.writeAll(")");
326 },
327 .tuple_type => {
328 const data: Teg.TupleType = teg.instPayload(.tuple_type, inst);
329
330 try writer.writeAll("(");
331 try s.dumpRefMarkerList(writer, data.items.slice(teg), '[', ']');
332 try writer.writeAll(")");
333 },
334 .tuple_init => {
335 const data: Teg.TupleInit = teg.instPayload(.tuple_init, inst);
336
337 try writer.writeAll("(");
338 if (data.type_hint.unwrap()) |type_hint| {
339 try s.dumpRef(writer, type_hint);
340 try writer.writeAll(", ");
341 }
342 try s.dumpRefMarkerList(writer, data.items.slice(teg), '[', ']');
343 try writer.writeAll(")");
344 },
345 .result_type_argument => {
346 const data: Teg.ResultTypeArgument = teg.instData(.result_type_argument, inst);
347
348 try writer.writeAll("(");
349 try s.dumpRefMarker(writer, data.call_base);
350 try writer.print(", {d}", .{data.argument});
351 try writer.writeAll(")");
352 },
353 .result_type_struct_field => {
354 const data: Teg.ResultTypeStructField = teg.instData(.result_type_struct_field, inst);
355
356 try writer.writeAll("(");
357 try s.dumpRefMarker(writer, data.type);
358 try writer.print(", {s}", .{data.field.slice(s.teg.string_bytes)});
359 try writer.writeAll(")");
360 },
361 .result_type_tuple_field => {
362 const data: Teg.ResultTypeTupleField = teg.instData(.result_type_tuple_field, inst);
363
364 try writer.writeAll("(");
365 try s.dumpRefMarker(writer, data.type);
366 try writer.print(", {d}", .{data.item});
367 try writer.writeAll(")");
368 },
369 .result_type_array_value => {
370 const data: Teg.ResultTypeArrayValue = teg.instData(.result_type_array_value, inst);
371
372 try writer.writeAll("(");
373 try s.dumpRefMarker(writer, data.type);
374 try writer.writeAll(")");
375 },
376 }
377 }
378
379 fn dumpRef(s: *State, writer: anytype, ref: Teg.Inst.Ref) !void {
380 switch (ref.decode()) {
381 .index => |index| try s.dumpInst(writer, index),
382 .value => {
383 try s.tty.setColor(writer, .blue);
384 try writer.print("%{s}", .{@tagName(ref)});
385 try s.tty.setColor(writer, .reset);
386 },
387 }
388 }
389
390 fn dumpRefMarker(s: *State, writer: anytype, ref: Teg.Inst.Ref) !void {
391 switch (ref.decode()) {
392 .index => |index| {
393 try s.tty.setColor(writer, .blue);
394 try writer.print("%{d}", .{@intFromEnum(index)});
395 try s.tty.setColor(writer, .reset);
396 },
397 .value => {
398 try s.tty.setColor(writer, .blue);
399 try writer.print("%{s}", .{@tagName(ref)});
400 try s.tty.setColor(writer, .reset);
401 },
402 }
403 }
404
405 fn dumpInstList(state: *State, writer: anytype, list: []const Teg.Inst.Index, l: u8, r: u8) !void {
406 try writer.print(" {c}", .{l});
407 if (list.len > 0) {
408 state.indent += 1;
409
410 for (list) |inst| {
411 try state.newline(writer);
412 try state.dumpInst(writer, inst);
413 }
414
415 state.indent -= 1;
416 try state.newline(writer);
417 }
418 try writer.print("{c}", .{r});
419 }
420
421 fn dumpInstList2(state: *State, writer: anytype, list: []const Teg.Inst.Index, l: u8, r: u8) !void {
422 try writer.print(" {c}", .{l});
423 if (list.len > 0) {
424 state.indent += 1;
425
426 for (list) |inst| {
427 try state.newline(writer);
428 try state.dumpRefMarker(writer, inst.toRef());
429 }
430
431 state.indent -= 1;
432 try state.newline(writer);
433 }
434 try writer.print("{c}", .{r});
435 }
436
437 fn dumpRefList(state: *State, writer: anytype, list: []const Teg.Inst.Ref, l: u8, r: u8) !void {
438 try writer.print(" {c}", .{l});
439 if (list.len > 0) {
440 state.indent += 1;
441
442 for (list) |ref| {
443 try state.newline(writer);
444 try state.dumpRef(writer, ref);
445 }
446
447 state.indent -= 1;
448
449 try state.newline(writer);
450 }
451 try writer.print("{c}", .{r});
452 }
453
454 fn dumpOptionalRefList(state: *State, writer: anytype, list: []const Teg.Inst.Ref.Optional, l: u8, r: u8) !void {
455 try writer.print(" {c}", .{l});
456 if (list.len > 0) {
457 state.indent += 1;
458
459 for (list) |optional_ref| {
460 try state.newline(writer);
461 if (optional_ref.unwrap()) |ref|
462 try state.dumpRef(writer, ref)
463 else {
464 try state.tty.setColor(writer, .bright_black);
465 try writer.writeAll("<inferred>");
466 try state.tty.setColor(writer, .reset);
467 }
468 }
469
470 state.indent -= 1;
471
472 try state.newline(writer);
473 }
474 try writer.print("{c}", .{r});
475 }
476
477 fn dumpRefMarkerList(state: *State, writer: anytype, list: []const Teg.Inst.Ref, l: u8, r: u8) !void {
478 try writer.print("{c}", .{l});
479 if (list.len > 0) {
480 state.indent += 1;
481
482 for (list) |ref| {
483 try state.newline(writer);
484 try state.dumpRefMarker(writer, ref);
485 }
486
487 state.indent -= 1;
488
489 try state.newline(writer);
490 }
491 try writer.print("{c}", .{r});
492 }
493};
494
495pub fn format(
496 dump: @This(),
497 comptime unused_fmt: []const u8,
498 _: std.fmt.FormatOptions,
499 writer: anytype,
500) !void {
501 comptime assert(unused_fmt.len == 0);
502
503 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
504 defer arena.deinit();
505
506 const teg = dump.teg;
507 var state = State{
508 .teg = &teg,
509 .tty = dump.tty orelse detectTTYFromWriter(writer),
510 .arena = arena.allocator(),
511 };
512 try state.dumpInst(writer, .main_module_inst);
513 try writer.writeAll("\n");
514 assert(state.indent == 0);
515}
516
517const std = @import("std");
518const assert = std.debug.assert;
519
520const core = @import("mod.zig");
521const Teg = core.Teg;
522const detectTTYFromWriter = core.detectTTYFromWriter;
src/core/Teg.zig deleted-1006
......@@ -1,1006 +0,0 @@
1//! TODO: rename this to EIR (expression intermediate representation)
2
3insts: Inst.List.Slice,
4string_bytes: []const u8,
5extra: ExtraStore = .{},
6report: Report,
7
8pub const ExtraStore = dod.ExtraStore(.teg, .@"const");
9pub const EncodedData = dod.EncodedData(Tag, u64);
10pub const ExtraIndex = ExtraStore.Index;
11pub const Dump = @import("Teg.Dump.zig");
12
13pub const Tag = enum(u8) {
14 /// Either the top level module or a `module` keyword. Contains a list of `.declarations`
15 /// Every analyzed module gets a `Comp.Namespace`
16 module,
17 /// Smallest unit of re-compilation. Every analyzed declaration gets a `Comp.Decl`
18 declaration,
19 /// Top-level memory location
20 variable_declaration,
21 /// Test declaration
22 test_declaration,
23 /// Retrieves a declaration value via it's name. Since declarations are
24 /// analyzed in isolation of each other, all references to instructions
25 /// outside of the current declaration must be in the form of this.
26 load_decl,
27 /// Blocks are a list of instructions. The block will end with a `.break`,
28 /// which will assign the block a return value.
29 block,
30 /// Ends a block (current or any parent) with a value.
31 /// `return` expressions are lowered to this.
32 @"break",
33 /// Creates a memory cell in the current scope with a starting value.
34 memory,
35 /// Re-assign a memory cell with a new ref.
36 store,
37 /// Re-assign a global variable decl with a new ref.
38 store_decl,
39 /// Re-assign a field with a new ref
40 store_field,
41 /// Performs a type coercion, such as in variable declarations.
42 /// The resulting Air Ref will be guaranteed to be the coerced type.
43 coercion,
44 /// Load a parameter
45 /// if data value is maxInt(u32), the function return type is used
46 param,
47 /// Asserts the operand is not void. Used for discard statements.
48 discard,
49 /// Asserts the operand is `void`. Used for undiscarded expressions.
50 ensure_void,
51
52 /// Branch takes a boolean condition and takes either a yes or no path.
53 @"if",
54 /// Given a block instruction
55 @"comptime",
56
57 /// A function expression, with or without captures
58 func,
59
60 // The following instructions are used to implement `Transform.ResultType`
61 result_type_argument,
62 result_type_struct_field,
63 result_type_tuple_field,
64 result_type_array_value,
65
66 /// Numeric constant.
67 number,
68 /// String literal constant.
69 string,
70
71 /// Constructs a unique struct type.
72 struct_decl,
73 /// Constructs an array type
74 array_type,
75
76 struct_init,
77 array_init,
78
79 tuple_init,
80 tuple_type,
81
82 add,
83 sub,
84 mul,
85 div,
86 rem,
87 pow,
88 @"and",
89 @"or",
90 bit_and,
91 bit_or,
92 bit_xor,
93 shl,
94 shr,
95 eq,
96 ne,
97 lt,
98 le,
99 gt,
100 ge,
101
102 negate,
103 bool_not,
104 bit_not,
105 assert,
106 field,
107 index,
108 call,
109 type_of,
110 /// Implements the `@extern` builtin
111 @"extern",
112
113 /// Implements the `@jsNew` builtin
114 js_new,
115 /// Implements the `@import` builtin
116 import,
117 /// Implements the `@fetch` builtin
118 fetch,
119 /// Implements the `@compileError` builtin
120 compile_error,
121
122 pub fn Data(comptime tag: Tag) type {
123 return switch (tag) {
124 .module, .block, .@"comptime" => PlNode(IndexList),
125
126 .declaration,
127 .variable_declaration,
128 .test_declaration,
129 => PlNode(Decl),
130
131 .coercion => PlNode(Coercion),
132 .@"break" => PlNode(Break),
133 .number => PlNode(Float),
134 .string => PlNode(SlicedString),
135 .call => PlNode(Call),
136 .@"if" => PlNode(If),
137 .store => PlNode(Store),
138 .store_decl => PlNode(StoreVarDecl),
139 .store_field => PlNode(StoreField),
140 .js_new => PlNode(JsNew),
141 .struct_decl => PlNode(StructDecl),
142 .struct_init => PlNode(StructInit),
143 .array_init => PlNode(ArrayInit),
144 .tuple_type => PlNode(TupleType),
145 .tuple_init => PlNode(TupleInit),
146 .func => PlNode(Func),
147
148 .load_decl => StrNode,
149 .param => DataNode,
150
151 .result_type_argument => ResultTypeArgument,
152 .result_type_struct_field => ResultTypeStructField,
153 .result_type_tuple_field => ResultTypeTupleField,
154 .result_type_array_value => ResultTypeArrayValue,
155
156 // One operand instructions
157 .memory,
158 .discard,
159 .ensure_void,
160 .negate,
161 .bool_not,
162 .bit_not,
163 .@"extern",
164 .import,
165 .fetch,
166 .compile_error,
167 .type_of,
168 .array_type,
169 .assert,
170 => RefNode,
171
172 // Two operand instructions
173 .field,
174 .index,
175 .add,
176 .sub,
177 .mul,
178 .div,
179 .rem,
180 .pow,
181 .@"and",
182 .@"or",
183 .bit_and,
184 .bit_or,
185 .bit_xor,
186 .shl,
187 .shr,
188 .eq,
189 .ne,
190 .lt,
191 .le,
192 .gt,
193 .ge,
194 => PlNode(Bin),
195 };
196 }
197
198 pub fn airTag(comptime tag: Tag) Air.Inst.Tag {
199 return @field(Air.Inst.Tag, @tagName(tag));
200 }
201};
202
203pub fn PlNode(comptime Payload: type) type {
204 return struct {
205 pub const T = Payload;
206
207 src_node: NodeOffset,
208 extra_index: ExtraIndex(Payload),
209 };
210}
211
212pub const RefNode = struct {
213 src_node: NodeOffset,
214 operand: Inst.Ref,
215};
216
217pub const StrNode = struct {
218 src_node: NodeOffset,
219 string: NullTerminatedString,
220};
221
222pub const DataNode = struct {
223 src_node: NodeOffset,
224 data: u32,
225};
226
227pub const Inst = struct {
228 pub const List = std.MultiArrayList(Inst);
229
230 tag: Tag,
231 data: EncodedData,
232
233 /// The position of a Teg instruction within the `Teg` instructions array.
234 pub const Index = enum(u32) {
235 /// Teg is structured so that the outermost "main" struct of any file
236 /// is always at index 0.
237 main_module_inst = 0,
238 _,
239
240 pub const static_len = @intFromEnum(Ref.empty_tuple) + 1;
241
242 pub fn toRef(i: Index) Inst.Ref {
243 return @enumFromInt(static_len + @intFromEnum(i));
244 }
245
246 pub fn toOptional(i: Index) Optional {
247 return @enumFromInt(@intFromEnum(i));
248 }
249
250 pub fn op(i: Index, operand: Report.Operand) InstOp {
251 return .{ .index = i, .op = operand };
252 }
253
254 pub const Optional = enum(u32) {
255 none = std.math.maxInt(u32),
256 _,
257
258 pub fn unwrap(oi: Optional) ?Index {
259 return if (oi == .none) null else @enumFromInt(@intFromEnum(oi));
260 }
261 };
262 };
263
264 /// A reference to an instruction, or to a static InternPool value.
265 ///
266 /// If the integer tag value is < InternPool.static_len, then it
267 /// corresponds to a Value. Otherwise, it is an instruction index.
268 pub const Ref = enum(u32) {
269 opaque_type,
270 bool_type,
271 int32_type,
272 float_type,
273 string_type,
274 never_type,
275 type_type,
276 numeric_literal_type,
277 numeric_literal_array_type,
278 never_array_type,
279 empty_tuple_type,
280
281 void,
282 bool_true,
283 bool_false,
284 int32_zero,
285 float_zero,
286 nan,
287 empty_string,
288 empty_array,
289 empty_tuple,
290 _,
291
292 pub const Decoded = union(enum) {
293 value: InternPool.Value,
294 index: Teg.Inst.Index,
295 };
296
297 pub fn decode(ref: Ref) Decoded {
298 const ref_int = @intFromEnum(ref);
299 return if (ref_int >= Index.static_len)
300 .{ .index = @enumFromInt(ref_int - Index.static_len) }
301 else
302 .{ .value = @enumFromInt(ref_int) };
303 }
304
305 pub fn index(ref: Ref) ?Index {
306 const ref_int = @intFromEnum(ref);
307 if (ref_int >= Index.static_len) {
308 return @enumFromInt(ref_int - Index.static_len);
309 } else {
310 return null;
311 }
312 }
313
314 pub fn value(inst: Ref) ?InternPool.Value {
315 const ref_int = @intFromEnum(inst);
316
317 // TODO: is this > or >=
318 if (ref_int > Index.static_len)
319 return null;
320
321 return @enumFromInt(ref_int);
322 }
323
324 pub fn toOptional(ref: Ref) Optional {
325 return @enumFromInt(@intFromEnum(ref));
326 }
327
328 pub const Optional = enum(u32) {
329 none = std.math.maxInt(u32),
330 _,
331
332 pub fn unwrap(opt: Optional) ?Ref {
333 return if (opt != .none) @enumFromInt(@intFromEnum(opt)) else null;
334 }
335 };
336 };
337};
338
339pub const Bin = struct {
340 lhs: Inst.Ref,
341 rhs: Inst.Ref,
342};
343
344pub const Store = struct {
345 memory: Inst.Index,
346 operand: Inst.Ref,
347};
348
349pub const StoreVarDecl = struct {
350 var_decl: NullTerminatedString,
351 operand: Inst.Ref,
352};
353
354pub const StoreField = struct {
355 base: Inst.Ref,
356 field: Inst.Ref,
357 operand: Inst.Ref,
358};
359
360pub const Coercion = struct {
361 type: Inst.Ref,
362 operand: Inst.Ref,
363};
364
365pub const Break = struct {
366 block: Inst.Index,
367 operand: Inst.Ref,
368};
369
370pub const Call = struct {
371 base: Inst.Ref,
372 args: RefList,
373};
374
375pub const If = struct {
376 cond: Inst.Ref,
377 yes: Inst.Ref,
378 no: Inst.Ref,
379};
380
381pub const JsNew = struct {
382 base: Inst.Ref,
383 args: RefList,
384};
385
386/// Index into extra which contains `field_len * 2` u32s. The first half
387/// are the keys (NullTerminatedString) and the second half are field types
388/// (Ref). This basically is like a specialized MultiArrayList.
389pub const StructDecl = struct {
390 payload_index: u32,
391 field_len: u32,
392
393 pub fn keys(decl: StructDecl, teg: *const Teg) []const NullTerminatedString {
394 return @ptrCast(
395 teg.extra.list.items[decl.payload_index..][0..decl.field_len],
396 );
397 }
398
399 pub fn types(decl: StructDecl, teg: *const Teg) []const Inst.Ref {
400 return @ptrCast(
401 teg.extra.list.items[decl.payload_index + decl.field_len ..][0..decl.field_len],
402 );
403 }
404};
405
406/// This memory is laid out with the same strategy described in StructDecl
407pub const StructInit = struct {
408 base_type: Inst.Ref,
409 payload_index: u32,
410 field_len: u32,
411
412 pub fn keys(decl: StructInit, teg: *const Teg) []const NullTerminatedString {
413 return @ptrCast(
414 teg.extra.list.items[decl.payload_index..][0..decl.field_len],
415 );
416 }
417
418 pub fn inits(decl: StructInit, teg: *const Teg) []const Inst.Ref {
419 return @ptrCast(
420 teg.extra.list.items[decl.payload_index + decl.field_len ..][0..decl.field_len],
421 );
422 }
423};
424
425pub const ArrayInit = struct {
426 /// Optionally provide a result type for more reliable type coercion.
427 /// If specified, this must be an array type. Otherwise, the first
428 /// element's type is used.
429 type_hint: Inst.Ref.Optional,
430 /// The items in the array
431 list: RefList,
432};
433
434pub const TupleType = struct {
435 /// The items in the tuple
436 items: RefList,
437};
438
439pub const TupleInit = struct {
440 /// Optionally provide a result type for more reliable type coercion.
441 /// If specified, this must be an array type. Otherwise, the first
442 /// element's type is used.
443 type_hint: Inst.Ref.Optional,
444 /// The items in the tuple
445 items: RefList,
446};
447
448pub const Decl = struct {
449 name: NullTerminatedString,
450 hash: Cache.BinDigest,
451 instruction_count: u32,
452 body: Inst.Ref,
453};
454
455pub const Func = struct {
456 params: OptionalRefList,
457 return_type: Inst.Ref.Optional,
458 body: Inst.Index,
459 captures: IndexList,
460 instruction_count: u32,
461};
462
463pub const ResultTypeArgument = struct {
464 /// The VALUE that is going to be called.
465 call_base: Inst.Ref,
466 /// Which argument
467 argument: u32,
468};
469
470pub const ResultTypeStructField = struct {
471 /// The type of the struct itself,
472 type: Inst.Ref,
473 /// Which field
474 field: NullTerminatedString,
475};
476
477pub const ResultTypeTupleField = struct {
478 /// The type of the tuple itself,
479 type: Inst.Ref,
480 /// Which item
481 item: u32,
482};
483
484pub const ResultTypeArrayValue = struct {
485 /// The type of the array itself,
486 type: Inst.Ref,
487 unused: u32 = 0,
488};
489
490// TODO: make this an enum
491const NodeOffset = i32;
492
493// TODO: remove InstOp. LazyNode should not have a decl
494pub const InstOp = struct {
495 index: Inst.Index,
496 op: Report.Operand,
497
498 pub fn lazyNode(inst: InstOp, decl: Comp.Decl.Index) LazyNode {
499 return .{
500 .inst = inst.index,
501 .operand = inst.op,
502 .decl = decl,
503 };
504 }
505};
506
507pub const NullTerminatedString = enum(u32) {
508 empty = 0,
509 _,
510
511 pub fn slice(str: NullTerminatedString, string_bytes: []const u8) [:0]const u8 {
512 if (str == .empty) return "";
513 const sub = string_bytes[@intFromEnum(str)..];
514 const i = mem.indexOfScalar(u8, sub, 0) orelse unreachable;
515
516 return sub[0..i :0];
517 }
518};
519
520pub const SlicedString = struct {
521 start: u32,
522 len: u32,
523
524 pub fn slice(str: SlicedString, string_bytes: []const u8) []const u8 {
525 return string_bytes[str.start..][0..str.len];
526 }
527};
528
529// TODO: Make the next three structs using a generic comptime thing
530
531pub const RefList = struct {
532 start: u32,
533 len: u32,
534
535 pub fn slice(self: RefList, teg: *const Teg) []const Inst.Ref {
536 return @ptrCast(teg.extra.list.items[self.start..][0..self.len]);
537 }
538};
539
540pub const OptionalRefList = struct {
541 start: u32,
542 len: u32,
543
544 pub fn slice(self: OptionalRefList, teg: *const Teg) []const Inst.Ref.Optional {
545 return @ptrCast(teg.extra.list.items[self.start..][0..self.len]);
546 }
547};
548
549pub const IndexList = struct {
550 start: u32,
551 len: u32,
552
553 pub fn slice(self: IndexList, teg: *const Teg) []const Inst.Index {
554 return @ptrCast(teg.extra.list.items[self.start..][0..self.len]);
555 }
556};
557
558pub const NullTermStringList = struct {
559 start: u32,
560 len: u32,
561
562 pub fn slice(self: IndexList, teg: *const Teg) []const NullTerminatedString {
563 return @ptrCast(teg.extra.list.items[self.start..][0..self.len]);
564 }
565};
566
567pub fn deinit(teg: *Teg, gpa: std.mem.Allocator) void {
568 gpa.free(teg.string_bytes);
569 teg.extra.deinit(gpa);
570 teg.insts.deinit(gpa);
571 teg.report.deinit(gpa);
572 teg.* = undefined;
573}
574
575pub fn instTag(teg: *const Teg, index: Inst.Index) Teg.Tag {
576 return teg.insts.items(.tag)[@intFromEnum(index)];
577}
578
579pub fn instEncodedData(teg: *const Teg, index: Inst.Index) EncodedData {
580 return teg.insts.items(.data)[@intFromEnum(index)];
581}
582
583pub fn instData(teg: *const Teg, comptime tag: Teg.Tag, index: Inst.Index) tag.Data() {
584 return teg.instEncodedData(index).decode(tag, teg.instTag(index));
585}
586
587pub fn instDataUnsafe(teg: *const Teg, comptime T: type, index: Inst.Index) T {
588 return teg.instEncodedData(index).decodeUnsafe(T, teg.instTag(index));
589}
590
591pub fn instPayload(teg: *const Teg, comptime tag: Teg.Tag, index: Inst.Index) tag.Data().T {
592 return teg.instData(tag, index).extra_index.get(teg);
593}
594
595pub fn instNodeOffset(teg: *const Teg, index: Inst.Index) i32 {
596 return switch (teg.instTag(index)) {
597 // these nodes never get errors, but Teg.Dump will print these regardless
598 // TODO:
599 .declaration,
600 .result_type_argument,
601 .result_type_struct_field,
602 .result_type_tuple_field,
603 .result_type_array_value,
604 => 0,
605
606 inline else => |tag| teg.instData(tag, index).src_node,
607 };
608}
609
610pub fn blockInstructions(teg: *const Teg, index: Inst.Index) []const Inst.Index {
611 return teg.instData(.block, index).extra_index.get(teg).slice(teg);
612}
613
614pub fn fullFuncDecl(teg: *const Teg, index: Inst.Index) struct { Teg.Decl, Teg.DeclFn } {
615 const decl, var trail = teg.instData(.declaration, index).extra_index.getTrail(teg);
616 assert(decl.kind == .function);
617 const decl_fn = trail.read(&teg.extra, Teg.DeclFn);
618 return .{ decl, decl_fn };
619}
620
621pub fn fullDecl(teg: *const Teg, index: Inst.Index) Decl {
622 const decl = teg.instEncodedData(index).decodeUnsafe(PlNode(Decl), teg.instTag(index)).extra_index.get(teg);
623 return .{
624 .name = decl.name,
625 .hash = decl.hash,
626 .instruction_count = decl.instruction_count,
627 .body = decl.body,
628 };
629}
630
631pub fn declData(teg: *const Teg, index: Inst.Index) Teg.Decl {
632 return teg.instDataUnsafe(PlNode(Decl), index).extra_index.get(teg);
633}
634
635pub fn moduleDeclarations(teg: *const Teg, module_index: Inst.Index) []const Inst.Index {
636 const module = teg.instData(.module, module_index);
637 const module_data: IndexList = module.extra_index.get(teg);
638 const slice = module_data.slice(teg);
639 if (core.runtime_safety) {
640 for (slice) |item| {
641 switch (teg.instTag(item)) {
642 .declaration, .variable_declaration, .test_declaration => {},
643 else => {
644 std.debug.panic("\ngot unknown tag {s}\n", .{@tagName(teg.instTag(item))});
645 },
646 }
647 }
648 }
649 return slice;
650}
651
652pub fn rootFunction(teg: *const Teg) Inst.Index {
653 const decls = teg.moduleDeclarations(.main_module_inst);
654 const root_fn = decls[decls.len - 1];
655 assert(teg.declName(root_fn).len == 0);
656 return root_fn;
657}
658
659pub fn declName(teg: *const Teg, decl_index: Inst.Index) []const u8 {
660 const decl = teg.instDataUnsafe(PlNode(Decl), decl_index);
661 const decl_data: Decl = decl.extra_index.get(teg);
662 return decl_data.name.slice(teg.string_bytes);
663}
664
665pub fn dumpToWriter(teg: Teg, writer: anytype, tty: ?std.io.tty.Config) !void {
666 try writer.print("{}", .{Dump{ .teg = teg, .tty = tty }});
667}
668
669/// Used for generating decl hashes
670fn isolatedRefValue(decl_index: Inst.Index, ref_to_hash: Inst.Ref) i32 {
671 return switch (ref_to_hash.decode()) {
672 .value => |value| -@as(i32, @intCast(@intFromEnum(value))),
673 .index => |index| @intCast(@intFromEnum(index) - @intFromEnum(decl_index)),
674 };
675}
676
677/// Used for generating decl hashes
678fn isolatedIndexValue(decl_index: Inst.Index, index_to_hash: Inst.Index) u32 {
679 return @intFromEnum(index_to_hash) - @intFromEnum(decl_index);
680}
681
682pub fn writeToHasher(
683 teg: *const Teg,
684 hasher: *HashHelper,
685 tag_list: []Tag,
686 data_list: []EncodedData,
687 decl_index: Inst.Index,
688) void {
689 // Add all of the tags
690 hasher.addBytes(std.mem.sliceAsBytes(tag_list));
691
692 // Add all of the data
693 for (tag_list, data_list) |tag, data| {
694
695 // This should roughly line up with Teg.Tag.Data
696 switch (tag) {
697 // PlNode(IndexList),
698 .module,
699 .block,
700 .@"comptime",
701 => {
702 const pl_node = data.decodeUnsafe(PlNode(IndexList), tag);
703 hasher.add(pl_node.src_node);
704 writeIndexListToHasher(hasher, pl_node.extra_index.get(teg).slice(teg), decl_index);
705 },
706
707 // PlNode
708 inline .declaration,
709 .variable_declaration,
710 .test_declaration,
711 .coercion,
712 .@"break",
713 .number,
714 .string,
715 .call,
716 .@"if",
717 .store,
718 .js_new,
719 .struct_decl,
720 .struct_init,
721 .array_init,
722 .tuple_init,
723 .tuple_type,
724 .func,
725 .store_decl,
726 .store_field,
727 => |pl_node_tag| {
728 const pl_node = data.decode(pl_node_tag, tag);
729 hasher.add(pl_node.src_node);
730 teg.writePlNodeInnerToHasher(hasher, pl_node_tag.Data().T, pl_node.extra_index.get(teg), decl_index);
731 },
732 // StrNode
733 .load_decl => {
734 const str_node = data.decodeUnsafe(StrNode, tag);
735 hasher.add(str_node.src_node);
736 hasher.addBytes(str_node.string.slice(teg.string_bytes));
737 },
738 // DataNode
739 .param => {
740 const data_node = data.decodeUnsafe(DataNode, tag);
741 hasher.add(data_node.src_node);
742 hasher.add(data_node.data);
743 },
744 // RefNode
745 .memory,
746 .discard,
747 .ensure_void,
748 .negate,
749 .bool_not,
750 .bit_not,
751 .@"extern",
752 .import,
753 .fetch,
754 .compile_error,
755 .type_of,
756 .array_type,
757 .assert,
758 => {
759 const ref_node = data.decodeUnsafe(RefNode, tag);
760 hasher.add(ref_node.src_node);
761 hasher.add(isolatedRefValue(decl_index, ref_node.operand));
762 },
763 // PlNode(Bin)
764 .field,
765 .index,
766 .add,
767 .sub,
768 .mul,
769 .div,
770 .rem,
771 .pow,
772 .@"and",
773 .@"or",
774 .bit_and,
775 .bit_or,
776 .bit_xor,
777 .shl,
778 .shr,
779 .eq,
780 .ne,
781 .lt,
782 .le,
783 .gt,
784 .ge,
785 => {
786 const pl_node = data.decodeUnsafe(PlNode(Bin), tag);
787 const bin = pl_node.extra_index.get(teg);
788 hasher.add(isolatedRefValue(decl_index, bin.lhs));
789 hasher.add(isolatedRefValue(decl_index, bin.rhs));
790 },
791 // Result Types
792 .result_type_argument => {
793 const arg = data.decodeUnsafe(ResultTypeArgument, tag);
794 hasher.add(isolatedRefValue(decl_index, arg.call_base));
795 hasher.add(arg.argument);
796 },
797 .result_type_struct_field => {
798 const struct_field = data.decodeUnsafe(ResultTypeStructField, tag);
799 hasher.add(isolatedRefValue(decl_index, struct_field.type));
800 hasher.addBytes(struct_field.field.slice(teg.string_bytes));
801 },
802 .result_type_tuple_field => {
803 const tuple_field = data.decodeUnsafe(ResultTypeTupleField, tag);
804 hasher.add(isolatedRefValue(decl_index, tuple_field.type));
805 hasher.add(tuple_field.item);
806 },
807 .result_type_array_value => {
808 const array_value = data.decodeUnsafe(ResultTypeArrayValue, tag);
809 hasher.add(isolatedRefValue(decl_index, array_value.type));
810 },
811 }
812 }
813}
814
815fn writeIndexListToHasher(
816 hasher: *HashHelper,
817 index_list: []const Inst.Index,
818 decl_index: Inst.Index,
819) void {
820 hasher.add(index_list.len);
821 for (index_list) |idx| {
822 hasher.add(isolatedIndexValue(decl_index, idx));
823 }
824}
825
826fn writeRefListToHasher(
827 hasher: *HashHelper,
828 decl_index: Inst.Index,
829 index_list: []const Inst.Ref,
830) void {
831 hasher.add(index_list.len);
832 for (index_list) |idx| {
833 hasher.add(isolatedRefValue(decl_index, idx));
834 }
835}
836
837fn writePlNodeInnerToHasher(
838 teg: *const Teg,
839 hasher: *HashHelper,
840 comptime T: type,
841 data: T,
842 decl_index: Inst.Index,
843) void {
844 switch (T) {
845 Decl => {
846 hasher.addBytes(&data.hash);
847 hasher.addBytes(data.name.slice(teg.string_bytes));
848 },
849 Float => {
850 const as_bytes: [2]u32 = .{
851 data.low,
852 data.high,
853 };
854 hasher.add(@as(u64, @bitCast(as_bytes)));
855 },
856 SlicedString => {
857 hasher.addBytes(data.slice(teg.string_bytes));
858 },
859 Coercion => {
860 hasher.add(isolatedRefValue(decl_index, data.type));
861 hasher.add(isolatedRefValue(decl_index, data.operand));
862 },
863 Break => {
864 hasher.add(isolatedIndexValue(decl_index, data.block));
865 hasher.add(isolatedRefValue(decl_index, data.operand));
866 },
867 Call => {
868 hasher.add(isolatedRefValue(decl_index, data.base));
869 writeRefListToHasher(hasher, decl_index, data.args.slice(teg));
870 },
871 If => {
872 hasher.add(isolatedRefValue(decl_index, data.cond));
873 hasher.add(isolatedRefValue(decl_index, data.yes));
874 hasher.add(isolatedRefValue(decl_index, data.no));
875 },
876 Store => {
877 hasher.add(isolatedIndexValue(decl_index, data.memory));
878 hasher.add(isolatedRefValue(decl_index, data.operand));
879 },
880 StoreField => {
881 hasher.add(isolatedRefValue(decl_index, data.base));
882 hasher.add(isolatedRefValue(decl_index, data.field));
883 hasher.add(isolatedRefValue(decl_index, data.operand));
884 },
885 StoreVarDecl => {
886 hasher.addBytes(data.var_decl.slice(teg.string_bytes));
887 hasher.add(isolatedRefValue(decl_index, data.operand));
888 },
889 JsNew => {
890 hasher.add(isolatedRefValue(decl_index, data.base));
891 writeRefListToHasher(hasher, decl_index, data.args.slice(teg));
892 },
893 StructDecl => {
894 hasher.add(data.field_len);
895 for (data.keys(teg), data.types(teg)) |key, ty| {
896 hasher.addBytes(key.slice(teg.string_bytes));
897 hasher.add(isolatedRefValue(decl_index, ty));
898 }
899 },
900 StructInit => {
901 hasher.add(isolatedRefValue(decl_index, data.base_type));
902 hasher.add(data.field_len);
903 for (data.keys(teg), data.inits(teg)) |key, init| {
904 hasher.addBytes(key.slice(teg.string_bytes));
905 hasher.add(isolatedRefValue(decl_index, init));
906 }
907 },
908 ArrayInit => {
909 if (data.type_hint.unwrap()) |type_hint|
910 hasher.add(isolatedRefValue(decl_index, type_hint))
911 else
912 hasher.add(@as(i32, std.math.maxInt(i32)));
913 writeRefListToHasher(hasher, decl_index, data.list.slice(teg));
914 },
915 Func => {
916 for (data.params.slice(teg)) |optional| {
917 if (optional.unwrap()) |item|
918 hasher.add(isolatedRefValue(decl_index, item));
919 }
920
921 if (data.return_type.unwrap()) |type_hint|
922 hasher.add(isolatedRefValue(decl_index, type_hint))
923 else
924 hasher.add(@as(i32, std.math.maxInt(i32)));
925
926 hasher.add(isolatedIndexValue(decl_index, data.body));
927 hasher.add(data.instruction_count);
928 },
929 TupleType => {
930 hasher.add(data.items.len);
931 for (data.items.slice(teg)) |item| {
932 hasher.add(isolatedRefValue(decl_index, item));
933 }
934 },
935 TupleInit => {
936 if (data.type_hint.unwrap()) |type_hint|
937 hasher.add(isolatedRefValue(decl_index, type_hint))
938 else
939 hasher.add(@as(i32, std.math.maxInt(i32)));
940 writeRefListToHasher(hasher, decl_index, data.items.slice(teg));
941 },
942 else => @compileError("hash not implemented for " ++ @typeName(T)),
943 }
944}
945
946pub const SerializedHeader = extern struct {
947 const version = @import("config").version_string ++ "\x00";
948
949 instruction_len: u32,
950 string_bytes: u32,
951 extra_len: u32,
952 report_err_len: u32,
953 report_warn_len: u32,
954};
955
956pub fn serialize(teg: Teg, target: core.SerializeTarget) !void {
957 const header: SerializedHeader = .{
958 .instruction_len = @intCast(teg.insts.len),
959 .string_bytes = @intCast(teg.string_bytes.len),
960 .extra_len = @intCast(teg.extra.list.items.len),
961 .report_err_len = @intCast(teg.report.errors.len),
962 .report_warn_len = @intCast(teg.report.warnings.len),
963 };
964
965 var iovecs = [_]std.posix.iovec_const{
966 core.iovecConst(SerializedHeader.version),
967 core.iovecConst(std.mem.asBytes(&header)),
968 core.iovecConst(std.mem.sliceAsBytes(teg.insts.items(.tag))),
969 core.iovecConst(std.mem.sliceAsBytes(teg.insts.items(.data))),
970 core.iovecConst(teg.string_bytes),
971 core.iovecConst(std.mem.sliceAsBytes(teg.extra.list.items)),
972 core.iovecConst(std.mem.sliceAsBytes(teg.report.errors)),
973 core.iovecConst(std.mem.sliceAsBytes(teg.report.warnings)),
974 };
975 try target.writev(&iovecs);
976}
977
978const Teg = @This();
979
980const std = @import("std");
981const mem = std.mem;
982const assert = std.debug.assert;
983const HashHelper = std.Build.Cache.HashHelper;
984
985const core = @import("mod.zig");
986const Cache = core.Cache;
987
988const Ast = core.Ast;
989const Unused = Ast.Unused;
990const NodeIndex = Ast.NodeIndex;
991const TokenIndex = Ast.TokenIndex;
992const OptionalNodeIndex = Ast.OptionalNodeIndex;
993const OptionalTokenIndex = Ast.OptionalTokenIndex;
994const OptionalExtraIndex = Ast.OptionalExtraIndex;
995
996const dod = core.array;
997const Float = dod.Float;
998
999const InternPool = core.InternPool;
1000
1001const Air = core.Air;
1002
1003const Comp = core.Comp;
1004
1005const Report = core.Report;
1006const LazyNode = Report.LazyNode;
src/core/Transform.zig+52-52
......@@ -1,5 +1,5 @@
1//! Transform pass converts an Ast into a high-level/untyped instruction format.
2//! See Teg.zig for more details about the IR. Transforming handles:
1//! Transform pass converts an Ast into a Hir. See Hir.zig for more details
2//! about the resulting data structure. Transforming handles:
33//!
44//! - Flattening nested expressions into instruction sequences.
55//! - Resolving all local variables into reference or declaration names.
......@@ -38,7 +38,7 @@ pub const Error = error{
3838 TransformFail,
3939} || Allocator.Error;
4040
41pub fn transform(ast: Ast, gpa: Allocator, fail_report: *Report) Error!Teg {
41pub fn transform(ast: Ast, gpa: Allocator, fail_report: *Report) Error!Hir {
4242 const trace = tracer.trace(@src());
4343 defer trace.end();
4444
......@@ -117,16 +117,16 @@ const ResultType = union(enum) {
117117 /// The expression will be cast to the type of this ref
118118 type_of: Inst.Ref,
119119 /// The expression is an argument to a function.
120 argument: Teg.ResultTypeArgument,
120 argument: Hir.ResultTypeArgument,
121121 /// The expression is a field in a struct initialization
122 struct_field: Teg.ResultTypeStructField,
122 struct_field: Hir.ResultTypeStructField,
123123 /// The expression is a field in a tuple initialization
124 tuple_field: Teg.ResultTypeTupleField,
124 tuple_field: Hir.ResultTypeTupleField,
125125 /// The expression is a field in an array initialization
126126 array_value: Inst.Ref,
127127
128128 // /// The expression is unknown field
129 // field: Teg.ResultTypeField,
129 // field: Hir.ResultTypeField,
130130
131131 /// This will return an instruction pointing to the the type
132132 pub fn consume(result: *ResultType, t: *Transform) !?Inst.Ref {
......@@ -259,8 +259,8 @@ const Scope = struct {
259259/// Sema requires that function expressions must know their up-front captures,
260260/// so it can classify a function as comptime or runtime.
261261const CaptureScope = struct {
262 start_index: Teg.Inst.Index,
263 symbol_uses: std.AutoArrayHashMapUnmanaged(Teg.Inst.Index, void) = .{},
262 start_index: Hir.Inst.Index,
263 symbol_uses: std.AutoArrayHashMapUnmanaged(Hir.Inst.Index, void) = .{},
264264
265265 fn deinit(s: *CaptureScope, t: *Transform) void {
266266 s.symbol_uses.deinit(t.gpa);
......@@ -535,7 +535,7 @@ fn transformDecl(t: *Transform, outer_decl: BlockContext, node: NodeIndex) Alloc
535535 var hasher: std.Build.Cache.HashHelper = .{ .hasher = core.Cache.hasher_init };
536536 hasher.addBytes(id);
537537
538 const temp_teg: Teg = .{
538 const temp_teg: Hir = .{
539539 .insts = t.insts.slice(),
540540 .extra = t.extra.constant(),
541541 .string_bytes = t.string_bytes.items,
......@@ -547,7 +547,7 @@ fn transformDecl(t: *Transform, outer_decl: BlockContext, node: NodeIndex) Alloc
547547
548548 temp_teg.writeToHasher(&hasher, tag_list, data_list, decl_index);
549549
550 const decl_extra = try t.extra.append(t.gpa, Teg.Decl, .{
550 const decl_extra = try t.extra.append(t.gpa, Hir.Decl, .{
551551 .name = name,
552552 .hash = hasher.hasher.finalResult(),
553553 .instruction_count = inst_count,
......@@ -579,7 +579,7 @@ fn transformTestDecl(t: *Transform, outer_decl: BlockContext, node: NodeIndex) A
579579
580580 var hasher: std.Build.Cache.HashHelper = .{ .hasher = core.Cache.hasher_init };
581581
582 const temp_teg: Teg = .{
582 const temp_teg: Hir = .{
583583 .insts = t.insts.slice(),
584584 .extra = t.extra.constant(),
585585 .string_bytes = t.string_bytes.items,
......@@ -591,7 +591,7 @@ fn transformTestDecl(t: *Transform, outer_decl: BlockContext, node: NodeIndex) A
591591
592592 temp_teg.writeToHasher(&hasher, tag_list, data_list, decl_index);
593593
594 const decl_extra = try t.extra.append(t.gpa, Teg.Decl, .{
594 const decl_extra = try t.extra.append(t.gpa, Hir.Decl, .{
595595 .name = .empty,
596596 .hash = hasher.hasher.finalResult(),
597597 .instruction_count = inst_count,
......@@ -738,7 +738,7 @@ fn transformToBlock(
738738 .none, .used => result,
739739 else => try t.addRef(.coercion, .{
740740 .src_node = ctx.nodeOffset(node),
741 .extra_index = try t.extra.append(t.gpa, Teg.Coercion, .{
741 .extra_index = try t.extra.append(t.gpa, Hir.Coercion, .{
742742 .type = try result_type_ptr.consume(t) orelse
743743 unreachable, // `.none` already handled
744744 .operand = result,
......@@ -748,7 +748,7 @@ fn transformToBlock(
748748
749749 _ = try t.addIndex(.@"break", .{
750750 .src_node = ctx.nodeOffset(node),
751 .extra_index = try t.extra.append(t.gpa, Teg.Break, .{
751 .extra_index = try t.extra.append(t.gpa, Hir.Break, .{
752752 .block = ret_block,
753753 .operand = coerced_result,
754754 }),
......@@ -864,7 +864,7 @@ pub const Builtin = enum {
864864
865865 return try t.addRef(.js_new, .{
866866 .src_node = decl.nodeOffset(args[0]),
867 .extra_index = try t.extra.append(t.gpa, Teg.JsNew, .{
867 .extra_index = try t.extra.append(t.gpa, Hir.JsNew, .{
868868 .base = base,
869869 .args = args_list,
870870 }),
......@@ -987,7 +987,7 @@ fn transformExpression(
987987
988988 return try t.addRef(.coercion, .{
989989 .src_node = ctx.nodeOffset(node),
990 .extra_index = try t.extra.append(t.gpa, Teg.Coercion, .{
990 .extra_index = try t.extra.append(t.gpa, Hir.Coercion, .{
991991 .type = type_ref.?,
992992 .operand = data_ref,
993993 }),
......@@ -1075,7 +1075,7 @@ fn transformExpression(
10751075 // compound compute + assign operation.
10761076 const is_assign = comptime tag.isAssignBin();
10771077 const teg_tag = @field(
1078 Teg.Tag,
1078 Hir.Tag,
10791079 if (is_assign)
10801080 @tagName(tag)[0 .. @tagName(tag).len - "_assign".len]
10811081 else
......@@ -1096,7 +1096,7 @@ fn transformExpression(
10961096
10971097 const compute_inst = try t.addRef(teg_tag, .{
10981098 .src_node = ctx.nodeOffset(node),
1099 .extra_index = try t.extra.append(t.gpa, Teg.Bin, .{
1099 .extra_index = try t.extra.append(t.gpa, Hir.Bin, .{
11001100 .lhs = if (is_assign) try lhs.toRef(t) else lhs,
11011101 .rhs = rhs,
11021102 }),
......@@ -1116,7 +1116,7 @@ fn transformExpression(
11161116 .assert,
11171117 => |tag| {
11181118 const ast_un = t.ast.nodeData(node).un;
1119 const teg_tag = @field(Teg.Tag, @tagName(tag));
1119 const teg_tag = @field(Hir.Tag, @tagName(tag));
11201120
11211121 var operand_type: ResultType = switch (tag) {
11221122 .negate => .none, // any numeric type allowed
......@@ -1178,7 +1178,7 @@ fn transformExpression(
11781178 if (inner_expr) |out| {
11791179 _ = try t.addRef(.@"break", .{
11801180 .src_node = ctx.nodeOffset(node),
1181 .extra_index = try t.extra.append(t.gpa, Teg.Break, .{
1181 .extra_index = try t.extra.append(t.gpa, Hir.Break, .{
11821182 .block = block,
11831183 .operand = out,
11841184 }),
......@@ -1276,7 +1276,7 @@ fn transformExpression(
12761276
12771277 const call_inst = try t.addRef(.call, .{
12781278 .src_node = ctx.nodeOffset(node),
1279 .extra_index = try t.extra.append(t.gpa, Teg.Call, .{
1279 .extra_index = try t.extra.append(t.gpa, Hir.Call, .{
12801280 .base = base,
12811281 .args = args_list,
12821282 }),
......@@ -1319,7 +1319,7 @@ fn transformExpression(
13191319
13201320 return try t.addRef(.field, .{
13211321 .src_node = ctx.nodeOffset(node),
1322 .extra_index = try t.extra.append(t.gpa, Teg.Bin, .{
1322 .extra_index = try t.extra.append(t.gpa, Hir.Bin, .{
13231323 .lhs = base,
13241324 .rhs = rhs,
13251325 }),
......@@ -1339,7 +1339,7 @@ fn transformExpression(
13391339
13401340 return try t.addRef(.field, .{
13411341 .src_node = ctx.nodeOffset(node),
1342 .extra_index = try t.extra.append(t.gpa, Teg.Bin, .{
1342 .extra_index = try t.extra.append(t.gpa, Hir.Bin, .{
13431343 .lhs = lhs,
13441344 .rhs = rhs,
13451345 }),
......@@ -1370,7 +1370,7 @@ fn transformExpression(
13701370
13711371 return try t.addRef(.@"if", .{
13721372 .src_node = ctx.nodeOffset(node),
1373 .extra_index = try t.extra.append(t.gpa, Teg.If, .{
1373 .extra_index = try t.extra.append(t.gpa, Hir.If, .{
13741374 .cond = cond,
13751375 .yes = yes,
13761376 .no = no,
......@@ -1399,7 +1399,7 @@ fn transformExpression(
13991399
14001400 _ = try t.addIndex(.@"break", .{
14011401 .src_node = ctx.nodeOffset(node),
1402 .extra_index = try t.extra.append(t.gpa, Teg.Break, .{
1402 .extra_index = try t.extra.append(t.gpa, Hir.Break, .{
14031403 .block = target.block_index,
14041404 .operand = operand,
14051405 }),
......@@ -1431,7 +1431,7 @@ fn transformExpression(
14311431 .none, .used => operand,
14321432 else => try t.addRef(.coercion, .{
14331433 .src_node = ctx.nodeOffset(node),
1434 .extra_index = try t.extra.append(t.gpa, Teg.Coercion, .{
1434 .extra_index = try t.extra.append(t.gpa, Hir.Coercion, .{
14351435 .type = try break_result.consume(t) orelse
14361436 unreachable, // `.none` already handled
14371437 .operand = operand,
......@@ -1441,7 +1441,7 @@ fn transformExpression(
14411441
14421442 _ = try t.addIndex(.@"break", .{
14431443 .src_node = ctx.nodeOffset(node),
1444 .extra_index = try t.extra.append(t.gpa, Teg.Break, .{
1444 .extra_index = try t.extra.append(t.gpa, Hir.Break, .{
14451445 .block = try block.getInst(t),
14461446 .operand = coerced_operand,
14471447 }),
......@@ -1474,7 +1474,7 @@ fn transformExpression(
14741474
14751475 return try t.addRef(.struct_decl, .{
14761476 .src_node = ctx.nodeOffset(node),
1477 .extra_index = try t.extra.append(t.gpa, Teg.StructDecl, .{
1477 .extra_index = try t.extra.append(t.gpa, Hir.StructDecl, .{
14781478 .payload_index = payload_index,
14791479 .field_len = @intCast(struct_node.fields.len),
14801480 }),
......@@ -1524,7 +1524,7 @@ fn transformExpression(
15241524
15251525 return try t.addRef(.struct_init, .{
15261526 .src_node = ctx.nodeOffset(node),
1527 .extra_index = try t.extra.append(t.gpa, Teg.StructInit, .{
1527 .extra_index = try t.extra.append(t.gpa, Hir.StructInit, .{
15281528 .base_type = base_type,
15291529 .payload_index = payload_index,
15301530 .field_len = @intCast(struct_node.fields.len),
......@@ -1549,7 +1549,7 @@ fn transformExpression(
15491549
15501550 return try t.addRef(.array_init, .{
15511551 .src_node = ctx.nodeOffset(node),
1552 .extra_index = try t.extra.append(t.gpa, Teg.ArrayInit, .{
1552 .extra_index = try t.extra.append(t.gpa, Hir.ArrayInit, .{
15531553 .type_hint = if (array_type) |ty| ty.toOptional() else .none,
15541554 .list = items,
15551555 }),
......@@ -1567,7 +1567,7 @@ fn transformExpression(
15671567
15681568 return try t.addRef(.tuple_init, .{
15691569 .src_node = ctx.nodeOffset(node),
1570 .extra_index = try t.extra.append(t.gpa, Teg.TupleInit, .{
1570 .extra_index = try t.extra.append(t.gpa, Hir.TupleInit, .{
15711571 .type_hint = .none,
15721572 .items = items,
15731573 }),
......@@ -1581,7 +1581,7 @@ fn transformExpression(
15811581
15821582 return try t.addRef(.tuple_type, .{
15831583 .src_node = ctx.nodeOffset(node),
1584 .extra_index = try t.extra.append(t.gpa, Teg.TupleType, .{
1584 .extra_index = try t.extra.append(t.gpa, Hir.TupleType, .{
15851585 .items = items,
15861586 }),
15871587 });
......@@ -1645,7 +1645,7 @@ fn transformExpression(
16451645
16461646 return try t.addRef(.func, .{
16471647 .src_node = ctx.nodeOffset(node),
1648 .extra_index = try t.extra.append(t.gpa, Teg.Func, .{
1648 .extra_index = try t.extra.append(t.gpa, Hir.Func, .{
16491649 .params = param_list,
16501650 .return_type = if (return_type) |ref| ref.toOptional() else .none,
16511651 .body = body,
......@@ -1862,7 +1862,7 @@ const AssignmentTarget = union(enum) {
18621862 }),
18631863 .field => |field| try t.addRef(.field, .{
18641864 .src_node = field.src_node,
1865 .extra_index = try t.extra.append(t.gpa, Teg.Bin, .{
1865 .extra_index = try t.extra.append(t.gpa, Hir.Bin, .{
18661866 .lhs = field.base,
18671867 .rhs = field.field,
18681868 }),
......@@ -1874,21 +1874,21 @@ const AssignmentTarget = union(enum) {
18741874 return switch (target) {
18751875 .memory => |memory| try t.addRef(.store, .{
18761876 .src_node = ctx.nodeOffset(node),
1877 .extra_index = try t.extra.append(t.gpa, Teg.Store, .{
1877 .extra_index = try t.extra.append(t.gpa, Hir.Store, .{
18781878 .memory = memory,
18791879 .operand = rhs,
18801880 }),
18811881 }),
18821882 .variable_declaration => |var_decl| try t.addRef(.store_decl, .{
18831883 .src_node = ctx.nodeOffset(node),
1884 .extra_index = try t.extra.append(t.gpa, Teg.StoreVarDecl, .{
1884 .extra_index = try t.extra.append(t.gpa, Hir.StoreVarDecl, .{
18851885 .var_decl = var_decl.string,
18861886 .operand = rhs,
18871887 }),
18881888 }),
18891889 .field => |field| try t.addRef(.store_field, .{
18901890 .src_node = ctx.nodeOffset(node),
1891 .extra_index = try t.extra.append(t.gpa, Teg.StoreField, .{
1891 .extra_index = try t.extra.append(t.gpa, Hir.StoreField, .{
18921892 .base = field.base,
18931893 .field = field.field,
18941894 .operand = rhs,
......@@ -1998,7 +1998,7 @@ fn transformBlockStatement(
19981998 if (value_result != .used) {
19991999 break :coerced try t.addRef(.coercion, .{
20002000 .src_node = ctx.nodeOffset(node),
2001 .extra_index = try t.extra.append(t.gpa, Teg.Coercion, .{
2001 .extra_index = try t.extra.append(t.gpa, Hir.Coercion, .{
20022002 .type = ref,
20032003 .operand = data_ref,
20042004 }),
......@@ -2110,7 +2110,7 @@ fn transformBlockStatement(
21102110 }
21112111}
21122112
2113fn addUntracked(t: *Transform, comptime tag: Teg.Tag, data: tag.Data()) !Inst.Index {
2113fn addUntracked(t: *Transform, comptime tag: Hir.Tag, data: tag.Data()) !Inst.Index {
21142114 try t.insts.append(t.gpa, .{
21152115 .tag = tag,
21162116 .data = .encode(tag, data),
......@@ -2118,13 +2118,13 @@ fn addUntracked(t: *Transform, comptime tag: Teg.Tag, data: tag.Data()) !Inst.In
21182118 return @enumFromInt(t.insts.len - 1);
21192119}
21202120
2121fn addIndex(t: *Transform, comptime tag: Teg.Tag, data: tag.Data()) !Inst.Index {
2121fn addIndex(t: *Transform, comptime tag: Hir.Tag, data: tag.Data()) !Inst.Index {
21222122 const index = try t.addUntracked(tag, data);
21232123 try t.scratch.add(t.arena, Inst.Index, index);
21242124 return index;
21252125}
21262126
2127fn addRef(t: *Transform, comptime tag: Teg.Tag, data: tag.Data()) !Inst.Ref {
2127fn addRef(t: *Transform, comptime tag: Hir.Tag, data: tag.Data()) !Inst.Ref {
21282128 return (try t.addIndex(tag, data)).toRef();
21292129}
21302130
......@@ -2333,18 +2333,18 @@ const Allocator = mem.Allocator;
23332333const assert = std.debug.assert;
23342334
23352335const core = @import("mod.zig");
2336const Teg = core.Teg;
2337const Inst = Teg.Inst;
2338const NullTerminatedString = Teg.NullTerminatedString;
2339const SlicedString = Teg.SlicedString;
2340const RefList = Teg.RefList;
2341const IndexList = Teg.IndexList;
2342const OptionalRefList = Teg.OptionalRefList;
2343const EncodedData = Teg.EncodedData;
2344const ExtraIndex = Teg.ExtraIndex;
2336const Hir = core.Hir;
2337const Inst = Hir.Inst;
2338const NullTerminatedString = Hir.NullTerminatedString;
2339const SlicedString = Hir.SlicedString;
2340const RefList = Hir.RefList;
2341const IndexList = Hir.IndexList;
2342const OptionalRefList = Hir.OptionalRefList;
2343const EncodedData = Hir.EncodedData;
2344const ExtraIndex = Hir.ExtraIndex;
23452345
23462346const array = core.array;
2347const ExtraStore = array.ExtraStore(.teg, .@"var");
2347const ExtraStore = array.ExtraStore(.hir, .@"var");
23482348const Float = array.Float;
23492349
23502350const Tokenizer = core.Tokenizer;
src/core/array.zig+1-1
......@@ -77,7 +77,7 @@ fn getAsU32(items: []const u32, comptime T: type, index: usize) T {
7777
7878pub const StoreKind = enum {
7979 intern_pool,
80 teg,
80 hir,
8181 air,
8282 js_tree,
8383
src/core/mod.zig+1-1
......@@ -17,7 +17,7 @@ pub const U32Stack = Stack(u32);
1717pub const StoredTrace = @import("StoredTrace.zig");
1818pub const DebugStoredTrace = StoredTrace.DebugStoredTrace;
1919pub const Queue = @import("queue.zig").Queue;
20pub const Teg = @import("Teg.zig");
20pub const Hir = @import("Hir.zig");
2121pub const Tokenizer = @import("Tokenizer.zig");
2222pub const Transform = @import("Transform.zig");
2323pub const unicode_props = @import("unicode_props.zig");
src/main.zig+2-2
......@@ -299,7 +299,7 @@ fn cmdBuildOrRun(ctx: Context, comptime mode: enum { build, run }) !void {
299299 const main_file = try comp.getFile(file_path);
300300
301301 var fail_report: Report = undefined;
302 const teg = main_file.getTeg(&comp, &fail_report) catch |err| switch (err) {
302 const hir = main_file.getHir(&comp, &fail_report) catch |err| switch (err) {
303303 error.TransformFail => {
304304 std.debug.print("Transform failed:\n", .{});
305305 try fail_report.dump(.initComp(&comp, main_file), comp.out);
......@@ -321,7 +321,7 @@ fn cmdBuildOrRun(ctx: Context, comptime mode: enum { build, run }) !void {
321321
322322 if (comp.options.dump_ir) {
323323 const stderr = std.io.getStdErr().writer();
324 try teg.dumpToWriter(stderr, null);
324 try hir.dumpToWriter(stderr, null);
325325 }
326326
327327 const entry_point = comp.enqueueEntryModule(main_file) catch |err| switch (err) {
src/wasm/enum_codegen.zig+3-3
......@@ -6,8 +6,8 @@ pub fn main() !void {
66 inline for (.{
77 .{ "TokenTag", Tokenizer.Token.Tag },
88 .{ "NodeTag", Ast.Node.Tag },
9 .{ "TegInstTag", Teg.Tag },
10 .{ "TegInstRef", Teg.Inst.Ref },
9 .{ "HirInstTag", Hir.Tag },
10 .{ "HirInstRef", Hir.Inst.Ref },
1111 }) |decl| {
1212 const name, const enum_type = decl;
1313
......@@ -24,4 +24,4 @@ const std = @import("std");
2424const core = @import("core");
2525const Tokenizer = core.Tokenizer;
2626const Ast = core.Ast;
27const Teg = core.Teg;
27const Hir = core.Hir;
test/compiler_tests.zig+5-5
......@@ -98,7 +98,7 @@ fn runTestCase(
9898 const main_file = try comp.getFile(file_path);
9999
100100 var fail_report: core.Report = undefined;
101 const teg = main_file.getTeg(&comp, &fail_report) catch |err| switch (err) {
101 const hir = main_file.getHir(&comp, &fail_report) catch |err| switch (err) {
102102 error.TransformFail => {
103103 try out.print("Transform failed:\n", .{});
104104 try fail_report.dump(.{ .comp = .{ .comp = &comp, .file = main_file } }, comp.out);
......@@ -112,7 +112,7 @@ fn runTestCase(
112112 };
113113
114114 if (case_options.dump_ir) {
115 try teg.dumpToWriter(out, .escape_codes);
115 try hir.dumpToWriter(out, .escape_codes);
116116 }
117117
118118 const entry_point = try comp.enqueueEntryModule(main_file);
......@@ -121,8 +121,8 @@ fn runTestCase(
121121 if (comp.temp_flag_had_errors)
122122 return error.SemaErrors;
123123
124 if (teg.report.warnings.len > 0)
125 return error.TegWarnings;
124 if (hir.report.warnings.len > 0)
125 return error.HirWarnings;
126126
127127 var js_out: std.ArrayListUnmanaged(u8) = .{};
128128 defer js_out.deinit(alloc);
......@@ -227,7 +227,7 @@ pub fn runTestCaseWrap(
227227 const stack = switch (err) {
228228 error.TransformFail,
229229 error.ParseFail,
230 error.TegWarnings,
230 error.HirWarnings,
231231 error.SemaErrors,
232232 error.AnalysisFail,
233233 => core.StoredTrace.empty,