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 @@...@@ -1,7 +1,8 @@
1# Ix1# Ix
22
3Ix (**I**nferable E**x**pression) is a high-level, general purpose programming3Ix (***I***nferable E***x***pression) is a high-level, general purpose
4language. It features a mix of Rust, Zig, and JavaScript's great points.4programming language. It features a mix of Rust, Zig, and JavaScript's great
5points.
56
6For a guide on how to use Ix, see the manual included in the binary7For a guide on how to use Ix, see the manual included in the binary
7distribution. Additionally, the latest commit of the manual is hosted online at8distribution. 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:...@@ -34,13 +34,13 @@ compiler tests into these categories:
34 runtime, testing both the semantic analysis pass as well as the code34 runtime, testing both the semantic analysis pass as well as the code
35 generation backend.35 generation backend.
36- **Transform Error Tests** (`test/transform_error`) confirm that the transform36- **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 be39All compiler tests can be run with `./build test`, or the test suite can be
40filtered using flags, see `zig build test --help`40filtered using flags, see `./build test -- --help`
4141
42To run Zig tests for an associated module, use `zig build test-{name}`, or run42To run Zig tests for an associated module, use `./build test-{name}`, or run
43`zig build test-all` to run all tests in the codebase.43`./build test-all` to run all tests in the codebase.
4444
45## Core45## Core
4646
...@@ -48,7 +48,7 @@ The `core` module contains most of the compiler:...@@ -48,7 +48,7 @@ The `core` module contains most of the compiler:
4848
49- Tokenizing and Parsing files. (`Tokenizer.zig`, `Parse.zig`, `Ast.zig`)49- Tokenizing and Parsing files. (`Tokenizer.zig`, `Parse.zig`, `Ast.zig`)
50- Transform Pass, moving from Ast to an untyped intermediate representation50- Transform Pass, moving from Ast to an untyped intermediate representation
51 (`Transform.zig`)51 (`Transform.zig`, `Hir.zig`)
52- Semantic Analysis, resolving all types and comptime values. (`Sema.zig`)52- Semantic Analysis, resolving all types and comptime values. (`Sema.zig`)
53- Intern Pool, storing and de-duplicating objects in a compilation.53- Intern Pool, storing and de-duplicating objects in a compilation.
54 (`InternPool.zig`)54 (`InternPool.zig`)
...@@ -56,7 +56,7 @@ The `core` module contains most of the compiler:...@@ -56,7 +56,7 @@ The `core` module contains most of the compiler:
5656
57Note that components like the formatter and module fetching code are not here.57Note that components like the formatter and module fetching code are not here.
58Keeping this module as small as possible is important for keeping compile times58Keeping this module as small as possible is important for keeping compile times
59low. Using `zig build compiler -- --help` instead of the fully featured binary59low. Using `./build compiler -- --help` instead of the fully featured binary
60will allow for faster and more focused iteration.60will allow for faster and more focused iteration.
6161
62## Manual62## Manual
doc/language-manual.md+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# Ix Programming Language1# Ix Programming Language
22
3Ix (**I**nferable E**x**pression) is a high-level programming language for3Ix (***I***nferable E***x***pression) is a high-level programming language for
4developing web applications and games.4developing web applications and games.
55
6Key goals of this project are:6Key goals of this project are:
src/cli_compiler.zig+2-2
...@@ -81,7 +81,7 @@ pub fn main() !u8 {...@@ -81,7 +81,7 @@ pub fn main() !u8 {
81 const main_file = try comp.getFile(file_path);81 const main_file = try comp.getFile(file_path);
8282
83 var fail_report: Report = undefined;83 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) {
85 error.TransformFail => {85 error.TransformFail => {
86 std.debug.print("Transform failed:\n", .{});86 std.debug.print("Transform failed:\n", .{});
87 try fail_report.dump(.initComp(&comp, main_file), comp.out);87 try fail_report.dump(.initComp(&comp, main_file), comp.out);
...@@ -97,7 +97,7 @@ pub fn main() !u8 {...@@ -97,7 +97,7 @@ pub fn main() !u8 {
9797
98 if (comp.options.dump_ir) {98 if (comp.options.dump_ir) {
99 const stderr = std.io.getStdErr().writer();99 const stderr = std.io.getStdErr().writer();
100 try teg.dumpToWriter(stderr, null);100 try hir.dumpToWriter(stderr, null);
101 }101 }
102102
103 const entry_point = try comp.enqueueEntryModule(main_file);103 const entry_point = try comp.enqueueEntryModule(main_file);
src/cli_transform.zig+5-5
...@@ -66,7 +66,7 @@ pub fn main() !u8 {...@@ -66,7 +66,7 @@ pub fn main() !u8 {
66 }66 }
6767
68 var teg_report: core.Report = undefined;68 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) {
70 error.OutOfMemory => return err,70 error.OutOfMemory => return err,
71 error.TransformFail => {71 error.TransformFail => {
72 defer teg_report.deinit(alloc);72 defer teg_report.deinit(alloc);
...@@ -81,13 +81,13 @@ pub fn main() !u8 {...@@ -81,13 +81,13 @@ pub fn main() !u8 {
81 return 1;81 return 1;
82 },82 },
83 };83 };
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", .{});
87 // defer file.close();87 // 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
92 return 0;92 return 0;
93}93}
src/core/Air.Dump.zig+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//! This implements a debug formatter for Teg1//! This implements a debug formatter for Air
2air: Air,2air: Air,
3ip: *const InternPool,3ip: *const InternPool,
4tty: std.io.tty.Config,4tty: std.io.tty.Config,
src/core/Ast.zig+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1//! The Abstract Syntax Tree preserves most details of the source code,1//! The Abstract Syntax Tree preserves most details of the source code,
2//! as it is used for formatting. Before semantic analysis, this2//! as it is used for formatting. Before semantic analysis, this
3//! structure is normalized into `Teg`, which removes constructs like3//! structure is normalized into `Hir`, which removes constructs like
4//! whitespace, unneeded let bindings, and other transforms.4//! whitespace, unneeded let bindings, and other transforms.
5//!5//!
6//! `ast.nodes` contains nodes stored as three parts:6//! `ast.nodes` contains nodes stored as three parts:
src/core/Comp.zig+30-30
...@@ -110,14 +110,14 @@ const Job = union(enum) {...@@ -110,14 +110,14 @@ const Job = union(enum) {
110110
111pub fn enqueueEntryModule(comp: *Comp, file: *File) !Decl.Index {111pub fn enqueueEntryModule(comp: *Comp, file: *File) !Decl.Index {
112 var report: Report = undefined;112 var report: Report = undefined;
113 const teg = try file.getTeg(comp, &report);113 const hir = try file.getHir(comp, &report);
114114
115 // TODO, move this elsewhere. we should print all errors and warnings at once115 // TODO, move this elsewhere. we should print all errors and warnings at once
116 if (teg.report.warnings.len > 0) {116 if (hir.report.warnings.len > 0) {
117 try teg.report.dump(.initComp(comp, file), comp.out);117 try hir.report.dump(.initComp(comp, file), comp.out);
118 }118 }
119119
120 const ns = try comp.indexTegModule(file, .main_module_inst);120 const ns = try comp.indexHirModule(file, .main_module_inst);
121 const main_str = try comp.intern_pool.getOrPutString(comp.gpa, "main", .no_embedded_nulls);121 const main_str = try comp.intern_pool.getOrPutString(comp.gpa, "main", .no_embedded_nulls);
122 const decl_index = comp.intern_pool.namespacePtr(ns).lookupDirect(comp, main_str) orelse {122 const decl_index = comp.intern_pool.namespacePtr(ns).lookupDirect(comp, main_str) orelse {
123 // TODO: add a helper function into Report to render a single error123 // 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...@@ -168,12 +168,12 @@ fn runAnalysisJob(comp: *Comp, unit: InternPool.AnalysisUnit, first_blocked_sema
168 };168 };
169 const decl = comp.intern_pool.declPtr(decl_index);169 const decl = comp.intern_pool.declPtr(decl_index);
170 const file = comp.intern_pool.namespacePtr(decl.src_namespace).file_scope;170 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
173 try sema.init(173 try sema.init(
174 comp,174 comp,
175 file,175 file,
176 teg,176 hir,
177 unit,177 unit,
178 decl.src_namespace,178 decl.src_namespace,
179 std.heap.ArenaAllocator.init(comp.gpa),179 std.heap.ArenaAllocator.init(comp.gpa),
...@@ -266,7 +266,7 @@ pub fn getFile(comp: *Comp, absolute_file_path: []const u8) !*File {...@@ -266,7 +266,7 @@ pub fn getFile(comp: *Comp, absolute_file_path: []const u8) !*File {
266 .root_namespace = .none,266 .root_namespace = .none,
267 .source = null,267 .source = null,
268 .ast = null,268 .ast = null,
269 .teg = null,269 .hir = null,
270 };270 };
271 gop.value_ptr.* = file;271 gop.value_ptr.* = file;
272 return file;272 return file;
...@@ -277,7 +277,7 @@ pub const Source = struct {...@@ -277,7 +277,7 @@ pub const Source = struct {
277 stat: Stat,277 stat: Stat,
278};278};
279279
280/// A file in the compilation and it's associated data structures. Ast and Teg280/// A file in the compilation and it's associated data structures. Ast and Hir
281/// are not guaranteed to be loaded, even if it's `status` says `success`.281/// are not guaranteed to be loaded, even if it's `status` says `success`.
282pub const File = struct {282pub const File = struct {
283 /// TODO: change this to a URL283 /// TODO: change this to a URL
...@@ -287,7 +287,7 @@ pub const File = struct {...@@ -287,7 +287,7 @@ pub const File = struct {
287287
288 source: ?Source,288 source: ?Source,
289 ast: ?Ast,289 ast: ?Ast,
290 teg: ?Teg,290 hir: ?Hir,
291291
292 path_digest: ?Cache.BinDigest,292 path_digest: ?Cache.BinDigest,
293293
...@@ -323,7 +323,7 @@ pub const File = struct {...@@ -323,7 +323,7 @@ pub const File = struct {
323323
324 // Here we do not modify stat fields because this function is the one324 // Here we do not modify stat fields because this function is the one
325 // used for error reporting. We need to keep the stat fields stale so that325 // 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
328 const loaded_source: Source = .{328 const loaded_source: Source = .{
329 .code = source,329 .code = source,
...@@ -370,11 +370,11 @@ pub const File = struct {...@@ -370,11 +370,11 @@ pub const File = struct {
370 return &(file.ast.?);370 return &(file.ast.?);
371 }371 }
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 {375 pub fn getHir(file: *File, comp: *Comp, fail_report: *Report) GetHirError!Hir {
376 if (file.teg) |teg| {376 if (file.hir) |hir| {
377 return teg;377 return hir;
378 }378 }
379379
380 const bin_digest = hash: {380 const bin_digest = hash: {
...@@ -387,10 +387,10 @@ pub const File = struct {...@@ -387,10 +387,10 @@ pub const File = struct {
387 };387 };
388 file.path_digest = bin_digest;388 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;392 file.hir = hir;
393 return teg;393 return hir;
394 }394 }
395395
396 pub fn unloadSource(file: *File, gpa: Allocator) void {396 pub fn unloadSource(file: *File, gpa: Allocator) void {
...@@ -407,15 +407,15 @@ pub const File = struct {...@@ -407,15 +407,15 @@ pub const File = struct {
407 }407 }
408 }408 }
409409
410 pub fn unloadTeg(file: *File, gpa: Allocator) void {410 pub fn unloadHir(file: *File, gpa: Allocator) void {
411 if (file.teg) |*teg| {411 if (file.hir) |*hir| {
412 teg.deinit(gpa);412 hir.deinit(gpa);
413 file.teg = null;413 file.hir = null;
414 }414 }
415 }415 }
416416
417 pub fn deinit(file: *File, gpa: Allocator) void {417 pub fn deinit(file: *File, gpa: Allocator) void {
418 file.unloadTeg(gpa);418 file.unloadHir(gpa);
419 file.unloadAst(gpa);419 file.unloadAst(gpa);
420 file.unloadSource(gpa);420 file.unloadSource(gpa);
421 gpa.destroy(file);421 gpa.destroy(file);
...@@ -476,7 +476,7 @@ pub const Decl = struct {...@@ -476,7 +476,7 @@ pub const Decl = struct {
476 // /// This value is absolute.476 // /// This value is absolute.
477 // src_line: u32,477 // 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.
480 teg_decl_index: InternPool.TrackedInst.Index,480 teg_decl_index: InternPool.TrackedInst.Index,
481481
482 /// Represents the "shallow" analysis status. For example, for decls that are functions,482 /// Represents the "shallow" analysis status. For example, for decls that are functions,
...@@ -620,10 +620,10 @@ pub const Namespace = struct {...@@ -620,10 +620,10 @@ pub const Namespace = struct {
620 pub const Index = InternPool.NamespaceIndex;620 pub const Index = InternPool.NamespaceIndex;
621};621};
622622
623/// Index a Teg's module scope as a namespace. This prepares `Decl` objects for623/// Index a Hir's module scope as a namespace. This prepares `Decl` objects for
624/// every declaration, but does not begin analysis of them.624/// every declaration, but does not begin analysis of them.
625pub fn indexTegModule(comp: *Comp, file: *File, module_index: Teg.Inst.Index) !Namespace.Index {625pub fn indexHirModule(comp: *Comp, file: *File, module_index: Hir.Inst.Index) !Namespace.Index {
626 const teg = file.teg.?;626 const hir = file.hir.?;
627627
628 assert(file.root_namespace == .none);628 assert(file.root_namespace == .none);
629629
...@@ -635,12 +635,12 @@ pub fn indexTegModule(comp: *Comp, file: *File, module_index: Teg.Inst.Index) !N...@@ -635,12 +635,12 @@ pub fn indexTegModule(comp: *Comp, file: *File, module_index: Teg.Inst.Index) !N
635 const ns_ptr = comp.intern_pool.namespacePtr(ns);635 const ns_ptr = comp.intern_pool.namespacePtr(ns);
636 errdefer comp.intern_pool.destroyNamespace(comp.gpa, ns);636 errdefer comp.intern_pool.destroyNamespace(comp.gpa, ns);
637637
638 for (teg.moduleDeclarations(module_index)) |decl_index| {638 for (hir.moduleDeclarations(module_index)) |decl_index| {
639 switch (teg.instTag(decl_index)) {639 switch (hir.instTag(decl_index)) {
640 .declaration => {640 .declaration => {
641 const name = try comp.intern_pool.getOrPutString(641 const name = try comp.intern_pool.getOrPutString(
642 comp.gpa,642 comp.gpa,
643 teg.declName(decl_index),643 hir.declName(decl_index),
644 .no_embedded_nulls,644 .no_embedded_nulls,
645 );645 );
646 const tracked_inst = try comp.intern_pool.trackInst(comp.gpa, file, decl_index);646 const tracked_inst = try comp.intern_pool.trackInst(comp.gpa, file, decl_index);
...@@ -736,7 +736,7 @@ const InternPool = core.InternPool;...@@ -736,7 +736,7 @@ const InternPool = core.InternPool;
736736
737const Ast = core.Ast;737const Ast = core.Ast;
738const Air = core.Air;738const Air = core.Air;
739const Teg = core.Teg;739const Hir = core.Hir;
740const Cache = core.Cache;740const Cache = core.Cache;
741const Sema = core.Sema;741const Sema = core.Sema;
742const Transform = core.Transform;742const 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;...@@ -638,7 +638,7 @@ pub const ExtraIndex = ExtraStore.Index;
638/// This is specified with an integer literal and a corresponding comptime638/// This is specified with an integer literal and a corresponding comptime
639/// assert below to break an unfortunate and arguably incorrect dependency loop639/// assert below to break an unfortunate and arguably incorrect dependency loop
640/// when compiling.640/// when compiling.
641pub const static_len = Teg.Inst.Index.static_len;641pub const static_len = Hir.Inst.Index.static_len;
642comptime {642comptime {
643 // @compileLog(static_len, static_keys.len);643 // @compileLog(static_len, static_keys.len);
644 assert(static_len == static_keys.len);644 assert(static_len == static_keys.len);
...@@ -805,16 +805,16 @@ pub const NullTerminatedString = enum(u32) {...@@ -805,16 +805,16 @@ pub const NullTerminatedString = enum(u32) {
805805
806pub const TrackedInst = extern struct {806pub const TrackedInst = extern struct {
807 path_digest: Cache.BinDigest,807 path_digest: Cache.BinDigest,
808 inst: Teg.Inst.Index,808 inst: Hir.Inst.Index,
809809
810 comptime {810 comptime {
811 // The fields should be tightly packed. See also serialization logic in `Compilation.saveState`.811 // 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));
813 }813 }
814814
815 pub const Index = enum(u32) {815 pub const Index = enum(u32) {
816 _,816 _,
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 {
818 return i.get(ip).inst;818 return i.get(ip).inst;
819 }819 }
820820
...@@ -1659,7 +1659,7 @@ fn getOrPutTrailingString(...@@ -1659,7 +1659,7 @@ fn getOrPutTrailingString(
1659 }1659 }
1660}1660}
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 {
1663 const t = tracer.trace(@src());1663 const t = tracer.trace(@src());
1664 defer t.end();1664 defer t.end();
16651665
...@@ -1869,7 +1869,7 @@ const assert = std.debug.assert;...@@ -1869,7 +1869,7 @@ const assert = std.debug.assert;
1869const core = @import("mod.zig");1869const core = @import("mod.zig");
1870const Comp = core.Comp;1870const Comp = core.Comp;
1871const Cache = core.Cache;1871const Cache = core.Cache;
1872const Teg = core.Teg;1872const Hir = core.Hir;
1873const Air = core.Air;1873const Air = core.Air;
1874const dod = core.array;1874const dod = core.array;
1875const Float = dod.Float;1875const Float = dod.Float;
src/core/Report.zig+8-8
...@@ -1093,7 +1093,7 @@ pub const MsgContext = struct {...@@ -1093,7 +1093,7 @@ pub const MsgContext = struct {
1093pub const LazyNode = struct {1093pub const LazyNode = struct {
1094 // TODO: remove this, it should be inferable off of the analysis unit that belongs to the report1094 // TODO: remove this, it should be inferable off of the analysis unit that belongs to the report
1095 decl: Comp.Decl.Index,1095 decl: Comp.Decl.Index,
1096 inst: Teg.Inst.Index,1096 inst: Hir.Inst.Index,
1097 operand: Operand,1097 operand: Operand,
10981098
1099 pub fn get(lazy: LazyNode, ctx: *MsgContext) !NodeIndex {1099 pub fn get(lazy: LazyNode, ctx: *MsgContext) !NodeIndex {
...@@ -1111,15 +1111,15 @@ pub const LazyNode = struct {...@@ -1111,15 +1111,15 @@ pub const LazyNode = struct {
1111 @panic("TODO: LazyNode.get when the decl is in a nested namespace");1111 @panic("TODO: LazyNode.get when the decl is in a nested namespace");
1112 }1112 }
11131113
1114 const teg = &(ctx.file.?.teg orelse1114 const hir = &(ctx.file.?.hir orelse
1115 // this will be required once incremental compilation hits1115 // this will be required once incremental compilation hits
1116 @panic("TODO: teg was unloaded"));1116 @panic("TODO: hir was unloaded"));
11171117
1118 const decl_inst = decl.teg_decl_index;1118 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
1124 const base_node: NodeIndex = @intCast(teg_decl.src_node + node_offset);1124 const base_node: NodeIndex = @intCast(teg_decl.src_node + node_offset);
1125 if (lazy.operand == .main_node)1125 if (lazy.operand == .main_node)
...@@ -1129,7 +1129,7 @@ pub const LazyNode = struct {...@@ -1129,7 +1129,7 @@ pub const LazyNode = struct {
11291129
1130 const node_tag = ctx.ast.nodeTag(base_node);1130 const node_tag = ctx.ast.nodeTag(base_node);
11311131
1132 switch (teg.instTag(lazy.inst)) {1132 switch (hir.instTag(lazy.inst)) {
1133 .coercion => switch (node_tag) {1133 .coercion => switch (node_tag) {
1134 .var_decl => switch (lazy.operand) {1134 .var_decl => switch (lazy.operand) {
1135 .lhs => return data.var_decl.type.unwrap().?,1135 .lhs => return data.var_decl.type.unwrap().?,
...@@ -1213,7 +1213,7 @@ pub const LazyNode = struct {...@@ -1213,7 +1213,7 @@ pub const LazyNode = struct {
1213 }1213 }
12141214
1215 std.debug.print("TODO: operand lookup: .{s} + .{s} + {}\n", .{1215 std.debug.print("TODO: operand lookup: .{s} + .{s} + {}\n", .{
1216 @tagName(teg.instTag(lazy.inst)),1216 @tagName(hir.instTag(lazy.inst)),
1217 @tagName(ctx.ast.nodeTag(base_node)),1217 @tagName(ctx.ast.nodeTag(base_node)),
1218 lazy.operand,1218 lazy.operand,
1219 });1219 });
...@@ -1467,7 +1467,7 @@ const TokenIndex = Ast.TokenIndex;...@@ -1467,7 +1467,7 @@ const TokenIndex = Ast.TokenIndex;
1467const NodeIndex = Ast.NodeIndex;1467const NodeIndex = Ast.NodeIndex;
1468const Location = Ast.Location;1468const Location = Ast.Location;
14691469
1470const Teg = core.Teg;1470const Hir = core.Hir;
14711471
1472const Comp = core.Comp;1472const Comp = core.Comp;
1473const File = Comp.File;1473const File = Comp.File;
src/core/Sema.zig+91-95
...@@ -1,13 +1,9 @@...@@ -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.
2//!3//!
3//! Designed as a nonrecursive state machine which can be paused when an4//! Designed as a nonrecursive state machine, `Sema` can be paused when an
4//! unfinished dependency is encountered, allowing the thread to work5//! unfinished dependency is encountered, allowing the thread to work on other
5//! on other analysis jobs.6//! 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.
117
12comp: *Comp,8comp: *Comp,
13ip: *InternPool,9ip: *InternPool,
...@@ -20,13 +16,13 @@ owner: AnalysisUnit,...@@ -20,13 +16,13 @@ owner: AnalysisUnit,
20/// The namespace index that is used for declaration lookups16/// The namespace index that is used for declaration lookups
21ns_index: Namespace.Index,17ns_index: Namespace.Index,
22/// Non-owning copy18/// Non-owning copy
23teg: Teg,19hir: Hir,
24/// The file that .teg is from20/// The file that .hir is from
25file: *File,21file: *File,
2622
27/// All errors and warnings from this decl23/// All errors and warnings from this decl
28report: Report.Builder,24report: Report.Builder,
29/// Map of `Teg` instructions to their resulting `Air` Ref25/// Map of `Hir` instructions to their resulting `Air` Ref
30inst_map: InstMap,26inst_map: InstMap,
3127
32/// `null` when not analyzing function bodies28/// `null` when not analyzing function bodies
...@@ -63,7 +59,7 @@ pub fn init(...@@ -63,7 +59,7 @@ pub fn init(
63 s: *Sema,59 s: *Sema,
64 comp: *Comp,60 comp: *Comp,
65 file: *File,61 file: *File,
66 teg: Teg,62 hir: Hir,
67 owner: AnalysisUnit,63 owner: AnalysisUnit,
68 ns_index: Namespace.Index,64 ns_index: Namespace.Index,
69 arena_state: std.heap.ArenaAllocator,65 arena_state: std.heap.ArenaAllocator,
...@@ -82,7 +78,7 @@ pub fn init(...@@ -82,7 +78,7 @@ pub fn init(
82 .arena_state = arena_state,78 .arena_state = arena_state,
83 .owner = owner,79 .owner = owner,
84 .ns_index = ns_index,80 .ns_index = ns_index,
85 .teg = teg,81 .hir = hir,
86 .file = file,82 .file = file,
8783
88 .report = .init(comp.gpa),84 .report = .init(comp.gpa),
...@@ -102,12 +98,12 @@ pub fn init(...@@ -102,12 +98,12 @@ pub fn init(
102 const first_instruction, const count = switch (owner.unwrap()) {98 const first_instruction, const count = switch (owner.unwrap()) {
103 .decl => |decl| data: {99 .decl => |decl| data: {
104 const decl_inst = s.ip.declPtr(decl).teg_decl_index.resolve(s.ip);100 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);
106 break :data .{ decl_inst, teg_decl.instruction_count };102 break :data .{ decl_inst, teg_decl.instruction_count };
107 },103 },
108 .func => |value| data: {104 .func => |value| data: {
109 const func_inst = value.toKey(s.ip).func.teg_body_inst.get(s.ip);105 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);
111 break :data .{ func.body, func.instruction_count };107 break :data .{ func.body, func.instruction_count };
112 },108 },
113 };109 };
...@@ -115,7 +111,7 @@ pub fn init(...@@ -115,7 +111,7 @@ pub fn init(
115 s.inst_map = try .init(s.arena(), first_instruction, count);111 s.inst_map = try .init(s.arena(), first_instruction, count);
116112
117 const block_index = switch (owner.unwrap()) {113 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()) {
119 .index => |index| index,115 .index => |index| index,
120 .value => unreachable, // Sema must not be created for a static value116 .value => unreachable, // Sema must not be created for a static value
121 },117 },
...@@ -165,11 +161,11 @@ const AnalysisMode = enum {...@@ -165,11 +161,11 @@ const AnalysisMode = enum {
165};161};
166162
167const Frame = struct {163const Frame = struct {
168 ip: [*]const Teg.Inst.Index,164 ip: [*]const Hir.Inst.Index,
169 instructions_left: if (runtime_safety) usize else void,165 instructions_left: if (runtime_safety) usize else void,
170166
171 mode: AnalysisMode,167 mode: AnalysisMode,
172 block_index: Teg.Inst.Index,168 block_index: Hir.Inst.Index,
173 mark_index: u32,169 mark_index: u32,
174 data: Data,170 data: Data,
175171
...@@ -192,15 +188,15 @@ const Frame = struct {...@@ -192,15 +188,15 @@ const Frame = struct {
192 argument: u16,188 argument: u16,
193 };189 };
194190
195 fn initFromBlock(s: *Sema, block_index: Teg.Inst.Index, mode: AnalysisMode, data: Data) Frame {191 fn initFromBlock(s: *Sema, block_index: Hir.Inst.Index, mode: AnalysisMode, data: Data) Frame {
196 switch (s.teg.instTag(block_index)) {192 switch (s.hir.instTag(block_index)) {
197 else => unreachable, // not a block193 else => unreachable, // not a block
198 .block, .@"comptime" => {},194 .block, .@"comptime" => {},
199 }195 }
200 const list = s.teg.instEncodedData(block_index)196 const list = s.hir.instEncodedData(block_index)
201 .decodeUnsafe(Teg.PlNode(Teg.IndexList), s.teg.instTag(block_index))197 .decodeUnsafe(Hir.PlNode(Hir.IndexList), s.hir.instTag(block_index))
202 .extra_index.get(&s.teg)198 .extra_index.get(&s.hir)
203 .slice(&s.teg);199 .slice(&s.hir);
204 return .{200 return .{
205 .ip = list[0..].ptr,201 .ip = list[0..].ptr,
206 .instructions_left = if (runtime_safety) list.len,202 .instructions_left = if (runtime_safety) list.len,
...@@ -211,12 +207,12 @@ const Frame = struct {...@@ -211,12 +207,12 @@ const Frame = struct {
211 };207 };
212 }208 }
213209
214 fn currentIndex(frame: *const Frame) Teg.Inst.Index {210 fn currentIndex(frame: *const Frame) Hir.Inst.Index {
215 // validate the pointer is correct211 // validate the pointer is correct
216 if (runtime_safety) {212 if (runtime_safety) {
217 const s: *const Sema = @fieldParentPtr("frame", frame);213 const s: *const Sema = @fieldParentPtr("frame", frame);
218 assert(s.magic == .valid);214 assert(s.magic == .valid);
219 const extra = s.teg.extra.list.items;215 const extra = s.hir.extra.list.items;
220 assert(@intFromPtr(frame.ip) > @intFromPtr(extra.ptr) and216 assert(@intFromPtr(frame.ip) > @intFromPtr(extra.ptr) and
221 @intFromPtr(frame.ip) <= @intFromPtr(&extra.ptr[extra.len - 1]));217 @intFromPtr(frame.ip) <= @intFromPtr(&extra.ptr[extra.len - 1]));
222 }218 }
...@@ -224,22 +220,22 @@ const Frame = struct {...@@ -224,22 +220,22 @@ const Frame = struct {
224 return frame.ip[0];220 return frame.ip[0];
225 }221 }
226222
227 fn currentTag(frame: *const Frame) Teg.Tag {223 fn currentTag(frame: *const Frame) Hir.Tag {
228 const s: *const Sema = @fieldParentPtr("frame", frame);224 const s: *const Sema = @fieldParentPtr("frame", frame);
229 assert(s.magic == .valid);225 assert(s.magic == .valid);
230 return s.teg.instTag(frame.currentIndex());226 return s.hir.instTag(frame.currentIndex());
231 }227 }
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() {
234 const s: *const Sema = @fieldParentPtr("frame", frame);230 const s: *const Sema = @fieldParentPtr("frame", frame);
235 assert(s.magic == .valid);231 assert(s.magic == .valid);
236 return s.teg.instData(tag, frame.currentIndex());232 return s.hir.instData(tag, frame.currentIndex());
237 }233 }
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 {
240 const s: *const Sema = @fieldParentPtr("frame", frame);236 const s: *const Sema = @fieldParentPtr("frame", frame);
241 assert(s.magic == .valid);237 assert(s.magic == .valid);
242 return s.teg.instPayload(tag, frame.currentIndex());238 return s.hir.instPayload(tag, frame.currentIndex());
243 }239 }
244240
245 fn advance(frame: *Frame) void {241 fn advance(frame: *Frame) void {
...@@ -282,10 +278,10 @@ const Function = struct {...@@ -282,10 +278,10 @@ const Function = struct {
282/// instructions it has.278/// instructions it has.
283const InstMap = struct {279const InstMap = struct {
284 items: []Air.Inst.Ref.Optional,280 items: []Air.Inst.Ref.Optional,
285 start: Teg.Inst.Index,281 start: Hir.Inst.Index,
286 debug_traces: if (runtime_safety) []StoredTrace else void,282 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 {
289 const insts = try allocator.alloc(Air.Inst.Ref.Optional, inst_len);285 const insts = try allocator.alloc(Air.Inst.Ref.Optional, inst_len);
290 errdefer allocator.free(insts);286 errdefer allocator.free(insts);
291287
...@@ -309,7 +305,7 @@ const InstMap = struct {...@@ -309,7 +305,7 @@ const InstMap = struct {
309 map.* = undefined;305 map.* = undefined;
310 }306 }
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 {
313 const source_i = @intFromEnum(teg_code);309 const source_i = @intFromEnum(teg_code);
314 const start_i = @intFromEnum(map.start);310 const start_i = @intFromEnum(map.start);
315 if (assertFailed(source_i >= start_i and source_i <= start_i + map.items.len)) {311 if (assertFailed(source_i >= start_i and source_i <= start_i + map.items.len)) {
...@@ -322,7 +318,7 @@ const InstMap = struct {...@@ -322,7 +318,7 @@ const InstMap = struct {
322 return map.items[source_i - start_i].unwrap();318 return map.items[source_i - start_i].unwrap();
323 }319 }
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 {
326 return map.getOrNull(teg_code) orelse {322 return map.getOrNull(teg_code) orelse {
327 if (runtime_safety) {323 if (runtime_safety) {
328 std.debug.panic("did not analyze %{d}", .{@intFromEnum(teg_code)});324 std.debug.panic("did not analyze %{d}", .{@intFromEnum(teg_code)});
...@@ -331,7 +327,7 @@ const InstMap = struct {...@@ -331,7 +327,7 @@ const InstMap = struct {
331 };327 };
332 }328 }
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 {
335 const source_i = @intFromEnum(from);331 const source_i = @intFromEnum(from);
336 const start_i = @intFromEnum(map.start);332 const start_i = @intFromEnum(map.start);
337 if (assertFailed(source_i >= start_i and source_i <= start_i + map.items.len)) {333 if (assertFailed(source_i >= start_i and source_i <= start_i + map.items.len)) {
...@@ -371,7 +367,7 @@ const DoMark = enum {...@@ -371,7 +367,7 @@ const DoMark = enum {
371 marked,367 marked,
372};368};
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 {
375 switch (teg_ref.decode()) {371 switch (teg_ref.decode()) {
376 .value => |value| return value.toAir(),372 .value => |value| return value.toAir(),
377 .index => |index| {373 .index => |index| {
...@@ -389,7 +385,7 @@ fn getRef(s: *Sema, teg_ref: Teg.Inst.Ref, mark: DoMark) Air.Inst.Ref {...@@ -389,7 +385,7 @@ fn getRef(s: *Sema, teg_ref: Teg.Inst.Ref, mark: DoMark) Air.Inst.Ref {
389 }385 }
390}386}
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 {
393 switch (teg_ref.decode()) {389 switch (teg_ref.decode()) {
394 .value => |value| return value,390 .value => |value| return value,
395 .index => |index| {391 .index => |index| {
...@@ -399,17 +395,17 @@ fn getValue(s: *Sema, src: LazyNode, teg_ref: Teg.Inst.Ref) !Value {...@@ -399,17 +395,17 @@ fn getValue(s: *Sema, src: LazyNode, teg_ref: Teg.Inst.Ref) !Value {
399 }395 }
400}396}
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 {
403 const any = try s.getValue(src, teg_ref);399 const any = try s.getValue(src, teg_ref);
404 return try s.coerceValue(src, any, ty);400 return try s.coerceValue(src, any, ty);
405}401}
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 {
408 const any = s.getRef(teg_ref, mark);404 const any = s.getRef(teg_ref, mark);
409 return try s.coerceRef(src, any, ty);405 return try s.coerceRef(src, any, ty);
410}406}
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 {
413 return (try s.getCoercedValue(src, teg_ref, .type)).toTypeUnsafe(s.ip);409 return (try s.getCoercedValue(src, teg_ref, .type)).toTypeUnsafe(s.ip);
414}410}
415411
...@@ -491,7 +487,7 @@ const InstructionKind = enum {...@@ -491,7 +487,7 @@ const InstructionKind = enum {
491 control_flow,487 control_flow,
492 pop_control_flow,488 pop_control_flow,
493489
494 pub inline fn fromTag(tag: Teg.Tag) InstructionKind {490 pub inline fn fromTag(tag: Hir.Tag) InstructionKind {
495 return switch (tag) {491 return switch (tag) {
496 // these push new frames, and frame end will assign its value492 // these push new frames, and frame end will assign its value
497 .func,493 .func,
...@@ -523,7 +519,7 @@ const InstructionKind = enum {...@@ -523,7 +519,7 @@ const InstructionKind = enum {
523519
524const PopControlFlowState = enum { stop, @"continue" };520const 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() {
527 switch (tag) {523 switch (tag) {
528 .block => unreachable, // frame must already be pushed524 .block => unreachable, // frame must already be pushed
529 .declaration,525 .declaration,
...@@ -534,7 +530,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -534,7 +530,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
534 // TODO: pre-evaluate `.param` nodes, since they are always at the start of a function.530 // TODO: pre-evaluate `.param` nodes, since they are always at the start of a function.
535 // this way we can avoid repeating the non-trivial call into InternPool531 // this way we can avoid repeating the non-trivial call into InternPool
536 .param => {532 .param => {
537 const param: Teg.DataNode = s.frame.currentData(.param);533 const param: Hir.DataNode = s.frame.currentData(.param);
538 assert(s.frame.mode == .run_time); // never emitted in a comptime block534 assert(s.frame.mode == .run_time); // never emitted in a comptime block
539 assert(s.owner.kind == .func); // only emitted in function body535 assert(s.owner.kind == .func); // only emitted in function body
540 const proto = s.owner.unwrap().func.toKey(s.ip).func.ty.toUnresolvedFunctionPrototype(s.ip).?;536 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)...@@ -550,8 +546,8 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
550 }546 }
551 },547 },
552 .string => {548 .string => {
553 const string: Teg.SlicedString = s.frame.currentPayload(.string);549 const string: Hir.SlicedString = s.frame.currentPayload(.string);
554 return s.makeValueAir(.{ .string = string.slice(s.teg.string_bytes) });550 return s.makeValueAir(.{ .string = string.slice(s.hir.string_bytes) });
555 },551 },
556 .number => {552 .number => {
557 const number: store.Float = s.frame.currentPayload(.number);553 const number: store.Float = s.frame.currentPayload(.number);
...@@ -565,7 +561,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -565,7 +561,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
565 .gt,561 .gt,
566 .eq,562 .eq,
567 => {563 => {
568 const bin: Teg.Bin = s.frame.currentPayload(tag);564 const bin: Hir.Bin = s.frame.currentPayload(tag);
569 const op = @field(BinaryOp, @tagName(tag));565 const op = @field(BinaryOp, @tagName(tag));
570566
571 const lhs = s.getRef(bin.lhs, .marked);567 const lhs = s.getRef(bin.lhs, .marked);
...@@ -600,7 +596,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -600,7 +596,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
600 });596 });
601 },597 },
602 .negate => {598 .negate => {
603 const un: Teg.RefNode = s.frame.currentData(.negate);599 const un: Hir.RefNode = s.frame.currentData(.negate);
604600
605 const operand = s.getRef(un.operand, .marked);601 const operand = s.getRef(un.operand, .marked);
606602
...@@ -622,7 +618,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -622,7 +618,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
622 return s.addRef(.negate, .{ .operand = operand });618 return s.addRef(.negate, .{ .operand = operand });
623 },619 },
624 .bool_not => {620 .bool_not => {
625 const un: Teg.RefNode = s.frame.currentData(.bool_not);621 const un: Hir.RefNode = s.frame.currentData(.bool_not);
626622
627 const operand = try s.getCoercedRef(s.lazyNode(.operand), un.operand, .bool, .marked);623 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)...@@ -639,7 +635,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
639 return s.addRef(.bool_not, .{ .operand = operand });635 return s.addRef(.bool_not, .{ .operand = operand });
640 },636 },
641 .struct_decl => {637 .struct_decl => {
642 const node: Teg.StructDecl = s.frame.currentPayload(.struct_decl);638 const node: Hir.StructDecl = s.frame.currentPayload(.struct_decl);
643639
644 const scratch = try s.scratch.reserveMulti(640 const scratch = try s.scratch.reserveMulti(
645 s.arena(),641 s.arena(),
...@@ -649,12 +645,12 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -649,12 +645,12 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
649 defer scratch.deinit();645 defer scratch.deinit();
650646
651 // Fill the first half with keys647 // Fill the first half with keys
652 for (scratch.items(.keys), node.keys(&s.teg)) |*dest, src| {648 for (scratch.items(.keys), node.keys(&s.hir)) |*dest, src| {
653 dest.* = try s.ip.getOrPutString(s.gpa, src.slice(s.teg.string_bytes), .no_embedded_nulls);649 dest.* = try s.ip.getOrPutString(s.gpa, src.slice(s.hir.string_bytes), .no_embedded_nulls);
654 }650 }
655651
656 // Fill the second half with coerced values.652 // 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| {
658 scratch.at(.types, i).* = try s.getType(s.lazyNode(.argument(@intCast(i))), ty);654 scratch.at(.types, i).* = try s.getType(s.lazyNode(.argument(@intCast(i))), ty);
659 }655 }
660656
...@@ -688,7 +684,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -688,7 +684,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
688 } });684 } });
689 },685 },
690 .field => {686 .field => {
691 const field: Teg.Bin = s.frame.currentPayload(.field);687 const field: Hir.Bin = s.frame.currentPayload(.field);
692 const lhs = s.getRef(field.lhs, .marked);688 const lhs = s.getRef(field.lhs, .marked);
693 const lhs_type = s.typeOfRef(lhs);689 const lhs_type = s.typeOfRef(lhs);
694690
...@@ -733,7 +729,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -733,7 +729,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
733 });729 });
734 },730 },
735 .call => {731 .call => {
736 const call: Teg.Call = s.frame.currentPayload(.call);732 const call: Hir.Call = s.frame.currentPayload(.call);
737 const base = s.getRef(call.base, .marked);733 const base = s.getRef(call.base, .marked);
738 const base_type = s.typeOfRef(base);734 const base_type = s.typeOfRef(base);
739735
...@@ -759,7 +755,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -759,7 +755,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
759 }755 }
760756
761 // validate function args757 // 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| {
763 const ref = s.getRef(arg, .marked);759 const ref = s.getRef(arg, .marked);
764 const coerced = try s.coerceRef(760 const coerced = try s.coerceRef(
765 s.lazyNode(.argument(@intCast(i))),761 s.lazyNode(.argument(@intCast(i))),
...@@ -769,7 +765,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -769,7 +765,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
769 scratch[i] = coerced;765 scratch[i] = coerced;
770 }766 }
771 } else {767 } else {
772 for (call.args.slice(&s.teg), 0..) |arg, i| {768 for (call.args.slice(&s.hir), 0..) |arg, i| {
773 const ref = try s.ensureValueDefinedRepresentation(769 const ref = try s.ensureValueDefinedRepresentation(
774 s.lazyNode(.argument(@intCast(i))),770 s.lazyNode(.argument(@intCast(i))),
775 s.getRef(arg, .marked),771 s.getRef(arg, .marked),
...@@ -792,7 +788,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -792,7 +788,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
792 });788 });
793 },789 },
794 .array_init => {790 .array_init => {
795 const node: Teg.ArrayInit = s.frame.currentPayload(.array_init);791 const node: Hir.ArrayInit = s.frame.currentPayload(.array_init);
796792
797 assert(node.list.len > 0 or node.type_hint.unwrap() != null);793 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)...@@ -806,7 +802,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
806802
807 var is_constant = true;803 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| {
810 const item = s.getRef(item_teg_ref, .marked);806 const item = s.getRef(item_teg_ref, .marked);
811 const coerced = if (item_type) |ty|807 const coerced = if (item_type) |ty|
812 try s.coerceRef(s.lazyNode(.argument(@intCast(i))), item, ty)808 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)...@@ -862,8 +858,8 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
862 });858 });
863 },859 },
864 .store => {860 .store => {
865 const data: Teg.Store = s.frame.currentPayload(.store);861 const data: Hir.Store = s.frame.currentPayload(.store);
866 assert(s.teg.instTag(data.memory) == .memory); // corrupt store instruction862 assert(s.hir.instTag(data.memory) == .memory); // corrupt store instruction
867863
868 try s.ensureAtRuntime(s.lazyNode(.main_node)); // TODO864 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)...@@ -885,7 +881,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
885 },881 },
886882
887 .js_new => {883 .js_new => {
888 const call: Teg.JsNew = s.frame.currentPayload(.js_new);884 const call: Hir.JsNew = s.frame.currentPayload(.js_new);
889885
890 try s.ensureAtRuntime(s.lazyNode(.main_node));886 try s.ensureAtRuntime(s.lazyNode(.main_node));
891887
...@@ -893,7 +889,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -893,7 +889,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
893889
894 const scratch = try s.arena().alloc(Air.Inst.Ref, call.args.len);890 const scratch = try s.arena().alloc(Air.Inst.Ref, call.args.len);
895 defer s.arena().free(scratch);891 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| {
897 const ref = try s.ensureValueDefinedRepresentation(893 const ref = try s.ensureValueDefinedRepresentation(
898 s.lazyNode(.argument(@intCast(i))),894 s.lazyNode(.argument(@intCast(i))),
899 s.getRef(arg, .marked),895 s.getRef(arg, .marked),
...@@ -924,7 +920,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -924,7 +920,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
924 },920 },
925921
926 .func => {922 .func => {
927 const data: Teg.Func = s.frame.currentPayload(.func);923 const data: Hir.Func = s.frame.currentPayload(.func);
928 const reserve = try s.scratch.reserveMulti(924 const reserve = try s.scratch.reserveMulti(
929 s.arena(),925 s.arena(),
930 .{ .params = Type, .captures = Air.Inst.Ref },926 .{ .params = Type, .captures = Air.Inst.Ref },
...@@ -937,7 +933,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -937,7 +933,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
937 defer handled_reserve.assertUnlocked();933 defer handled_reserve.assertUnlocked();
938 errdefer handled_reserve.unlock();934 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| {
941 const src = s.lazyNode(.argument(@intCast(i)));937 const src = s.lazyNode(.argument(@intCast(i)));
942938
943 const known = param.unwrap() orelse @panic("TODO: inferred param sets");939 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)...@@ -991,7 +987,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
991 },987 },
992988
993 .@"break" => {989 .@"break" => {
994 const brk: Teg.Break = s.frame.currentPayload(.@"break");990 const brk: Hir.Break = s.frame.currentPayload(.@"break");
995 const operand = s.getRef(brk.operand, .marked);991 const operand = s.getRef(brk.operand, .marked);
996992
997 assert(s.frame.block_index == brk.block);993 assert(s.frame.block_index == brk.block);
...@@ -1036,7 +1032,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -1036,7 +1032,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
1036 s.frame.advance();1032 s.frame.advance();
1037 },1033 },
1038 .@"if" => {1034 .@"if" => {
1039 const if_data: Teg.If = s.frame.currentPayload(.@"if");1035 const if_data: Hir.If = s.frame.currentPayload(.@"if");
10401036
1041 switch (data.conditional) {1037 switch (data.conditional) {
1042 .comptime_condition => {1038 .comptime_condition => {
...@@ -1093,7 +1089,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -1093,7 +1089,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
1093 s.frame.advance();1089 s.frame.advance();
1094 },1090 },
1095 .func => {1091 .func => {
1096 const func_data: Teg.Func = s.frame.currentPayload(.func);1092 const func_data: Hir.Func = s.frame.currentPayload(.func);
10971093
1098 const reserve: FunctionReserve = .fromIndex(1094 const reserve: FunctionReserve = .fromIndex(
1099 &s.scratch,1095 &s.scratch,
...@@ -1104,7 +1100,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -1104,7 +1100,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
1104 const return_type = switch (data.func) {1100 const return_type = switch (data.func) {
1105 .argument => |arg_num| ret: {1101 .argument => |arg_num| ret: {
1106 for (1102 for (
1107 func_data.params.slice(&s.teg)[arg_num + 1 ..],1103 func_data.params.slice(&s.hir)[arg_num + 1 ..],
1108 reserve.items(.params)[arg_num + 1 ..],1104 reserve.items(.params)[arg_num + 1 ..],
1109 arg_num + 1..,1105 arg_num + 1..,
1110 ) |param, *dst, i| {1106 ) |param, *dst, i| {
...@@ -1172,10 +1168,10 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -1172,10 +1168,10 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
1172 },1168 },
11731169
1174 .load_decl => {1170 .load_decl => {
1175 const request: Teg.StrNode = s.frame.currentData(.load_decl);1171 const request: Hir.StrNode = s.frame.currentData(.load_decl);
1176 const decl_name = try s.ip.getOrPutString(1172 const decl_name = try s.ip.getOrPutString(
1177 s.gpa,1173 s.gpa,
1178 request.string.slice(s.teg.string_bytes),1174 request.string.slice(s.hir.string_bytes),
1179 .no_embedded_nulls,1175 .no_embedded_nulls,
1180 );1176 );
1181 const decl_index = s.lookupDecl(decl_name);1177 const decl_index = s.lookupDecl(decl_name);
...@@ -1183,13 +1179,13 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -1183,13 +1179,13 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
1183 },1179 },
11841180
1185 .coercion => {1181 .coercion => {
1186 const as: Teg.Coercion = s.frame.currentPayload(.coercion);1182 const as: Hir.Coercion = s.frame.currentPayload(.coercion);
1187 const coerce_to = try s.getType(s.lazyNode(.operand), as.type);1183 const coerce_to = try s.getType(s.lazyNode(.operand), as.type);
1188 return try s.getCoercedRef(s.lazyNode(.operand), as.operand, coerce_to, .marked);1184 return try s.getCoercedRef(s.lazyNode(.operand), as.operand, coerce_to, .marked);
1189 },1185 },
11901186
1191 .compile_error => {1187 .compile_error => {
1192 const node: Teg.RefNode = s.frame.currentData(.compile_error);1188 const node: Hir.RefNode = s.frame.currentData(.compile_error);
1193 const value = try s.getCoercedValue(s.lazyNode(.operand), node.operand, .string);1189 const value = try s.getCoercedValue(s.lazyNode(.operand), node.operand, .string);
1194 const str = value.asString(s.ip).toSlice(s.ip);1190 const str = value.asString(s.ip).toSlice(s.ip);
1195 return s.fail(.user_compile_error, .{1191 return s.fail(.user_compile_error, .{
...@@ -1199,7 +1195,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -1199,7 +1195,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
1199 },1195 },
12001196
1201 .@"if" => {1197 .@"if" => {
1202 const data: Teg.If = s.frame.currentPayload(.@"if");1198 const data: Hir.If = s.frame.currentPayload(.@"if");
12031199
1204 const condition = try s.getCoercedRef(s.lazyNode(.operand), data.cond, .bool, .marked);1200 const condition = try s.getCoercedRef(s.lazyNode(.operand), data.cond, .bool, .marked);
1205 switch (condition.decode()) {1201 switch (condition.decode()) {
...@@ -1270,7 +1266,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -1270,7 +1266,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
1270 },1266 },
12711267
1272 .struct_init => {1268 .struct_init => {
1273 const node: Teg.StructInit = s.frame.currentPayload(.struct_init);1269 const node: Hir.StructInit = s.frame.currentPayload(.struct_init);
12741270
1275 // Ensure we have a valid struct to operate on1271 // Ensure we have a valid struct to operate on
1276 const ty = try s.getType(s.lazyNode(.operand), node.base_type);1272 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)...@@ -1295,9 +1291,9 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
1295 // The ordering of `storage` is defined by the struct's type, which1291 // The ordering of `storage` is defined by the struct's type, which
1296 // may be different than the instantiation. The fields are visited in1292 // may be different than the instantiation. The fields are visited in
1297 // order of the instantiation.1293 // 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| {
1299 const found_index = index: for (struct_type.field_keys, 0..) |decl_key, j| {1295 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))
1301 break :index j;1297 break :index j;
1302 } else {1298 } else {
1303 has_errors = true;1299 has_errors = true;
...@@ -1374,18 +1370,18 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -1374,18 +1370,18 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
1374 },1370 },
13751371
1376 .array_type => {1372 .array_type => {
1377 const un: Teg.RefNode = s.frame.currentData(.array_type);1373 const un: Hir.RefNode = s.frame.currentData(.array_type);
1378 const operand = try s.getType(s.lazyNode(.operand), un.operand);1374 const operand = try s.getType(s.lazyNode(.operand), un.operand);
1379 return s.makeValueAir(.{ .array_type = .{ .item_type = operand } });1375 return s.makeValueAir(.{ .array_type = .{ .item_type = operand } });
1380 },1376 },
13811377
1382 .tuple_type => {1378 .tuple_type => {
1383 const data: Teg.TupleType = s.frame.currentPayload(.tuple_type);1379 const data: Hir.TupleType = s.frame.currentPayload(.tuple_type);
13841380
1385 const scratch = try s.scratch.reserve(s.arena(), Type, data.items.len);1381 const scratch = try s.scratch.reserve(s.arena(), Type, data.items.len);
1386 defer scratch.deinit();1382 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| {
1389 dst.* = try s.getType(s.lazyNode(.argument(@intCast(i))), src);1385 dst.* = try s.getType(s.lazyNode(.argument(@intCast(i))), src);
1390 }1386 }
13911387
...@@ -1393,7 +1389,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -1393,7 +1389,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
1393 },1389 },
13941390
1395 .tuple_init => {1391 .tuple_init => {
1396 const data: Teg.TupleInit = s.frame.currentPayload(.tuple_init);1392 const data: Hir.TupleInit = s.frame.currentPayload(.tuple_init);
13971393
1398 _ = data.type_hint; // TODO: use type hint1394 _ = data.type_hint; // TODO: use type hint
13991395
...@@ -1401,7 +1397,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -1401,7 +1397,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
1401 defer scratch.deinit();1397 defer scratch.deinit();
14021398
1403 var is_const = true;1399 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| {
1405 const result = s.getRef(src, .marked);1401 const result = s.getRef(src, .marked);
1406 dst.* = result;1402 dst.* = result;
1407 if (result.kind == .index) is_const = false;1403 if (result.kind == .index) is_const = false;
...@@ -1447,7 +1443,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -1447,7 +1443,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
1447 },1443 },
14481444
1449 .result_type_argument => {1445 .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
1452 const operand = s.getRef(result.call_base, .no_mark);1448 const operand = s.getRef(result.call_base, .no_mark);
1453 const ty = s.typeOfRef(operand);1449 const ty = s.typeOfRef(operand);
...@@ -1462,7 +1458,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -1462,7 +1458,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
1462 },1458 },
14631459
1464 .result_type_array_value => {1460 .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
1467 const operand = try s.getValue(s.lazyNode(.main_node), result.type);1463 const operand = try s.getValue(s.lazyNode(.main_node), result.type);
1468 const ty = operand.toType(s.ip) orelse1464 const ty = operand.toType(s.ip) orelse
...@@ -1475,7 +1471,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -1475,7 +1471,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
1475 },1471 },
14761472
1477 .result_type_tuple_field => {1473 .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
1480 const operand = try s.getValue(s.lazyNode(.main_node), result.type);1476 const operand = try s.getValue(s.lazyNode(.main_node), result.type);
1481 const ty = operand.toType(s.ip) orelse1477 const ty = operand.toType(s.ip) orelse
...@@ -1487,7 +1483,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -1487,7 +1483,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
1487 },1483 },
14881484
1489 .result_type_struct_field => {1485 .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
1492 const operand = try s.getValue(s.lazyNode(.main_node), result.type);1488 const operand = try s.getValue(s.lazyNode(.main_node), result.type);
1493 const ty = operand.toType(s.ip) orelse1489 const ty = operand.toType(s.ip) orelse
...@@ -1496,7 +1492,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -1496,7 +1492,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
1496 const struct_type = ty.toStructType(s.ip) orelse1492 const struct_type = ty.toStructType(s.ip) orelse
1497 return Value.opaque_type.toAir();1493 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);
1500 for (struct_type.field_keys, struct_type.field_types) |k, v| {1496 for (struct_type.field_keys, struct_type.field_types) |k, v| {
1501 if (k.eqlSlice(to_match, s.ip)) {1497 if (k.eqlSlice(to_match, s.ip)) {
1502 return v.value().toAir();1498 return v.value().toAir();
...@@ -1512,7 +1508,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)...@@ -1512,7 +1508,7 @@ fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag)
15121508
1513fn emitRuntimeBlock(1509fn emitRuntimeBlock(
1514 s: *Sema,1510 s: *Sema,
1515 from: Teg.Inst.Index,1511 from: Hir.Inst.Index,
1516 break_operand: Air.Inst.Ref,1512 break_operand: Air.Inst.Ref,
1517 mark: core.U32Stack.Mark,1513 mark: core.U32Stack.Mark,
1518) !void {1514) !void {
...@@ -1553,7 +1549,7 @@ const BinaryOp = enum {...@@ -1553,7 +1549,7 @@ const BinaryOp = enum {
1553 eq,1549 eq,
1554};1550};
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 {
1557 if (lhs == .@"opaque") {1553 if (lhs == .@"opaque") {
1558 return if (rhs == .numeric_literal) .float else rhs;1554 return if (rhs == .numeric_literal) .float else rhs;
1559 }1555 }
...@@ -2084,7 +2080,7 @@ fn fieldAccessStruct(...@@ -2084,7 +2080,7 @@ fn fieldAccessStruct(
2084 lhs: Air.Inst.Ref,2080 lhs: Air.Inst.Ref,
2085 lhs_type: Type,2081 lhs_type: Type,
2086 struct_type: InternPool.Key.StructType,2082 struct_type: InternPool.Key.StructType,
2087 field: Teg.Inst.Ref,2083 field: Hir.Inst.Ref,
2088) !Air.Inst.Ref {2084) !Air.Inst.Ref {
2089 const rhs = try s.getCoercedValue(s.lazyNode(.rhs), field, .string);2085 const rhs = try s.getCoercedValue(s.lazyNode(.rhs), field, .string);
2090 const string = rhs.asString(s.ip);2086 const string = rhs.asString(s.ip);
...@@ -2125,7 +2121,7 @@ fn fieldAccessStruct(...@@ -2125,7 +2121,7 @@ fn fieldAccessStruct(
2125 }2121 }
2126}2122}
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 {
2129 const rhs = s.getRef(rhs_teg, .marked);2125 const rhs = s.getRef(rhs_teg, .marked);
21302126
2131 switch (s.typeOfRef(rhs)) {2127 switch (s.typeOfRef(rhs)) {
...@@ -2176,7 +2172,7 @@ fn fieldAccessTuple(...@@ -2176,7 +2172,7 @@ fn fieldAccessTuple(
2176 lhs: Air.Inst.Ref,2172 lhs: Air.Inst.Ref,
2177 lhs_type: Type,2173 lhs_type: Type,
2178 tuple_type: InternPool.Key.TupleType,2174 tuple_type: InternPool.Key.TupleType,
2179 field: Teg.Inst.Ref,2175 field: Hir.Inst.Ref,
2180) !Air.Inst.Ref {2176) !Air.Inst.Ref {
2181 const index_value = try s.getCoercedValue(s.lazyNode(.rhs), field, .int32);2177 const index_value = try s.getCoercedValue(s.lazyNode(.rhs), field, .int32);
2182 const index_signed = index_value.toInt32(s.ip) orelse unreachable;2178 const index_signed = index_value.toInt32(s.ip) orelse unreachable;
...@@ -2387,7 +2383,7 @@ const File = Comp.File;...@@ -2387,7 +2383,7 @@ const File = Comp.File;
2387const Decl = Comp.Decl;2383const Decl = Comp.Decl;
2388const Namespace = Comp.Namespace;2384const Namespace = Comp.Namespace;
23892385
2390const Teg = core.Teg;2386const Hir = core.Hir;
23912387
2392const Air = core.Air;2388const Air = core.Air;
2393const Ast = core.Ast;2389const Ast = core.Ast;
src/core/StoredTrace.zig+3-3
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1//! A variant of std.builtin.StackTrace that stores its data within itself1//! A variant of `std.builtin.StackTrace` that stores its data within itself
2//! instead of being a pointer. This allows capturing the stack trace and2//! instead of being a pointer. This allows storing captured stack traces
3//! saving it for later printing.3//! for later printing.
44
5data: [31]usize,5data: [31]usize,
6index: usize,6index: 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,5 +1,5 @@
1//! Transform pass converts an Ast into a high-level/untyped instruction format.1//! Transform pass converts an Ast into a Hir. See Hir.zig for more details
2//! See Teg.zig for more details about the IR. Transforming handles:2//! about the resulting data structure. Transforming handles:
3//!3//!
4//! - Flattening nested expressions into instruction sequences.4//! - Flattening nested expressions into instruction sequences.
5//! - Resolving all local variables into reference or declaration names.5//! - Resolving all local variables into reference or declaration names.
...@@ -38,7 +38,7 @@ pub const Error = error{...@@ -38,7 +38,7 @@ pub const Error = error{
38 TransformFail,38 TransformFail,
39} || Allocator.Error;39} || 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 {
42 const trace = tracer.trace(@src());42 const trace = tracer.trace(@src());
43 defer trace.end();43 defer trace.end();
4444
...@@ -117,16 +117,16 @@ const ResultType = union(enum) {...@@ -117,16 +117,16 @@ const ResultType = union(enum) {
117 /// The expression will be cast to the type of this ref117 /// The expression will be cast to the type of this ref
118 type_of: Inst.Ref,118 type_of: Inst.Ref,
119 /// The expression is an argument to a function.119 /// The expression is an argument to a function.
120 argument: Teg.ResultTypeArgument,120 argument: Hir.ResultTypeArgument,
121 /// The expression is a field in a struct initialization121 /// The expression is a field in a struct initialization
122 struct_field: Teg.ResultTypeStructField,122 struct_field: Hir.ResultTypeStructField,
123 /// The expression is a field in a tuple initialization123 /// The expression is a field in a tuple initialization
124 tuple_field: Teg.ResultTypeTupleField,124 tuple_field: Hir.ResultTypeTupleField,
125 /// The expression is a field in an array initialization125 /// The expression is a field in an array initialization
126 array_value: Inst.Ref,126 array_value: Inst.Ref,
127127
128 // /// The expression is unknown field128 // /// The expression is unknown field
129 // field: Teg.ResultTypeField,129 // field: Hir.ResultTypeField,
130130
131 /// This will return an instruction pointing to the the type131 /// This will return an instruction pointing to the the type
132 pub fn consume(result: *ResultType, t: *Transform) !?Inst.Ref {132 pub fn consume(result: *ResultType, t: *Transform) !?Inst.Ref {
...@@ -259,8 +259,8 @@ const Scope = struct {...@@ -259,8 +259,8 @@ const Scope = struct {
259/// Sema requires that function expressions must know their up-front captures,259/// Sema requires that function expressions must know their up-front captures,
260/// so it can classify a function as comptime or runtime.260/// so it can classify a function as comptime or runtime.
261const CaptureScope = struct {261const CaptureScope = struct {
262 start_index: Teg.Inst.Index,262 start_index: Hir.Inst.Index,
263 symbol_uses: std.AutoArrayHashMapUnmanaged(Teg.Inst.Index, void) = .{},263 symbol_uses: std.AutoArrayHashMapUnmanaged(Hir.Inst.Index, void) = .{},
264264
265 fn deinit(s: *CaptureScope, t: *Transform) void {265 fn deinit(s: *CaptureScope, t: *Transform) void {
266 s.symbol_uses.deinit(t.gpa);266 s.symbol_uses.deinit(t.gpa);
...@@ -535,7 +535,7 @@ fn transformDecl(t: *Transform, outer_decl: BlockContext, node: NodeIndex) Alloc...@@ -535,7 +535,7 @@ fn transformDecl(t: *Transform, outer_decl: BlockContext, node: NodeIndex) Alloc
535 var hasher: std.Build.Cache.HashHelper = .{ .hasher = core.Cache.hasher_init };535 var hasher: std.Build.Cache.HashHelper = .{ .hasher = core.Cache.hasher_init };
536 hasher.addBytes(id);536 hasher.addBytes(id);
537537
538 const temp_teg: Teg = .{538 const temp_teg: Hir = .{
539 .insts = t.insts.slice(),539 .insts = t.insts.slice(),
540 .extra = t.extra.constant(),540 .extra = t.extra.constant(),
541 .string_bytes = t.string_bytes.items,541 .string_bytes = t.string_bytes.items,
...@@ -547,7 +547,7 @@ fn transformDecl(t: *Transform, outer_decl: BlockContext, node: NodeIndex) Alloc...@@ -547,7 +547,7 @@ fn transformDecl(t: *Transform, outer_decl: BlockContext, node: NodeIndex) Alloc
547547
548 temp_teg.writeToHasher(&hasher, tag_list, data_list, decl_index);548 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, .{
551 .name = name,551 .name = name,
552 .hash = hasher.hasher.finalResult(),552 .hash = hasher.hasher.finalResult(),
553 .instruction_count = inst_count,553 .instruction_count = inst_count,
...@@ -579,7 +579,7 @@ fn transformTestDecl(t: *Transform, outer_decl: BlockContext, node: NodeIndex) A...@@ -579,7 +579,7 @@ fn transformTestDecl(t: *Transform, outer_decl: BlockContext, node: NodeIndex) A
579579
580 var hasher: std.Build.Cache.HashHelper = .{ .hasher = core.Cache.hasher_init };580 var hasher: std.Build.Cache.HashHelper = .{ .hasher = core.Cache.hasher_init };
581581
582 const temp_teg: Teg = .{582 const temp_teg: Hir = .{
583 .insts = t.insts.slice(),583 .insts = t.insts.slice(),
584 .extra = t.extra.constant(),584 .extra = t.extra.constant(),
585 .string_bytes = t.string_bytes.items,585 .string_bytes = t.string_bytes.items,
...@@ -591,7 +591,7 @@ fn transformTestDecl(t: *Transform, outer_decl: BlockContext, node: NodeIndex) A...@@ -591,7 +591,7 @@ fn transformTestDecl(t: *Transform, outer_decl: BlockContext, node: NodeIndex) A
591591
592 temp_teg.writeToHasher(&hasher, tag_list, data_list, decl_index);592 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, .{
595 .name = .empty,595 .name = .empty,
596 .hash = hasher.hasher.finalResult(),596 .hash = hasher.hasher.finalResult(),
597 .instruction_count = inst_count,597 .instruction_count = inst_count,
...@@ -738,7 +738,7 @@ fn transformToBlock(...@@ -738,7 +738,7 @@ fn transformToBlock(
738 .none, .used => result,738 .none, .used => result,
739 else => try t.addRef(.coercion, .{739 else => try t.addRef(.coercion, .{
740 .src_node = ctx.nodeOffset(node),740 .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, .{
742 .type = try result_type_ptr.consume(t) orelse742 .type = try result_type_ptr.consume(t) orelse
743 unreachable, // `.none` already handled743 unreachable, // `.none` already handled
744 .operand = result,744 .operand = result,
...@@ -748,7 +748,7 @@ fn transformToBlock(...@@ -748,7 +748,7 @@ fn transformToBlock(
748748
749 _ = try t.addIndex(.@"break", .{749 _ = try t.addIndex(.@"break", .{
750 .src_node = ctx.nodeOffset(node),750 .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, .{
752 .block = ret_block,752 .block = ret_block,
753 .operand = coerced_result,753 .operand = coerced_result,
754 }),754 }),
...@@ -864,7 +864,7 @@ pub const Builtin = enum {...@@ -864,7 +864,7 @@ pub const Builtin = enum {
864864
865 return try t.addRef(.js_new, .{865 return try t.addRef(.js_new, .{
866 .src_node = decl.nodeOffset(args[0]),866 .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, .{
868 .base = base,868 .base = base,
869 .args = args_list,869 .args = args_list,
870 }),870 }),
...@@ -987,7 +987,7 @@ fn transformExpression(...@@ -987,7 +987,7 @@ fn transformExpression(
987987
988 return try t.addRef(.coercion, .{988 return try t.addRef(.coercion, .{
989 .src_node = ctx.nodeOffset(node),989 .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, .{
991 .type = type_ref.?,991 .type = type_ref.?,
992 .operand = data_ref,992 .operand = data_ref,
993 }),993 }),
...@@ -1075,7 +1075,7 @@ fn transformExpression(...@@ -1075,7 +1075,7 @@ fn transformExpression(
1075 // compound compute + assign operation.1075 // compound compute + assign operation.
1076 const is_assign = comptime tag.isAssignBin();1076 const is_assign = comptime tag.isAssignBin();
1077 const teg_tag = @field(1077 const teg_tag = @field(
1078 Teg.Tag,1078 Hir.Tag,
1079 if (is_assign)1079 if (is_assign)
1080 @tagName(tag)[0 .. @tagName(tag).len - "_assign".len]1080 @tagName(tag)[0 .. @tagName(tag).len - "_assign".len]
1081 else1081 else
...@@ -1096,7 +1096,7 @@ fn transformExpression(...@@ -1096,7 +1096,7 @@ fn transformExpression(
10961096
1097 const compute_inst = try t.addRef(teg_tag, .{1097 const compute_inst = try t.addRef(teg_tag, .{
1098 .src_node = ctx.nodeOffset(node),1098 .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, .{
1100 .lhs = if (is_assign) try lhs.toRef(t) else lhs,1100 .lhs = if (is_assign) try lhs.toRef(t) else lhs,
1101 .rhs = rhs,1101 .rhs = rhs,
1102 }),1102 }),
...@@ -1116,7 +1116,7 @@ fn transformExpression(...@@ -1116,7 +1116,7 @@ fn transformExpression(
1116 .assert,1116 .assert,
1117 => |tag| {1117 => |tag| {
1118 const ast_un = t.ast.nodeData(node).un;1118 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
1121 var operand_type: ResultType = switch (tag) {1121 var operand_type: ResultType = switch (tag) {
1122 .negate => .none, // any numeric type allowed1122 .negate => .none, // any numeric type allowed
...@@ -1178,7 +1178,7 @@ fn transformExpression(...@@ -1178,7 +1178,7 @@ fn transformExpression(
1178 if (inner_expr) |out| {1178 if (inner_expr) |out| {
1179 _ = try t.addRef(.@"break", .{1179 _ = try t.addRef(.@"break", .{
1180 .src_node = ctx.nodeOffset(node),1180 .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, .{
1182 .block = block,1182 .block = block,
1183 .operand = out,1183 .operand = out,
1184 }),1184 }),
...@@ -1276,7 +1276,7 @@ fn transformExpression(...@@ -1276,7 +1276,7 @@ fn transformExpression(
12761276
1277 const call_inst = try t.addRef(.call, .{1277 const call_inst = try t.addRef(.call, .{
1278 .src_node = ctx.nodeOffset(node),1278 .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, .{
1280 .base = base,1280 .base = base,
1281 .args = args_list,1281 .args = args_list,
1282 }),1282 }),
...@@ -1319,7 +1319,7 @@ fn transformExpression(...@@ -1319,7 +1319,7 @@ fn transformExpression(
13191319
1320 return try t.addRef(.field, .{1320 return try t.addRef(.field, .{
1321 .src_node = ctx.nodeOffset(node),1321 .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, .{
1323 .lhs = base,1323 .lhs = base,
1324 .rhs = rhs,1324 .rhs = rhs,
1325 }),1325 }),
...@@ -1339,7 +1339,7 @@ fn transformExpression(...@@ -1339,7 +1339,7 @@ fn transformExpression(
13391339
1340 return try t.addRef(.field, .{1340 return try t.addRef(.field, .{
1341 .src_node = ctx.nodeOffset(node),1341 .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, .{
1343 .lhs = lhs,1343 .lhs = lhs,
1344 .rhs = rhs,1344 .rhs = rhs,
1345 }),1345 }),
...@@ -1370,7 +1370,7 @@ fn transformExpression(...@@ -1370,7 +1370,7 @@ fn transformExpression(
13701370
1371 return try t.addRef(.@"if", .{1371 return try t.addRef(.@"if", .{
1372 .src_node = ctx.nodeOffset(node),1372 .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, .{
1374 .cond = cond,1374 .cond = cond,
1375 .yes = yes,1375 .yes = yes,
1376 .no = no,1376 .no = no,
...@@ -1399,7 +1399,7 @@ fn transformExpression(...@@ -1399,7 +1399,7 @@ fn transformExpression(
13991399
1400 _ = try t.addIndex(.@"break", .{1400 _ = try t.addIndex(.@"break", .{
1401 .src_node = ctx.nodeOffset(node),1401 .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, .{
1403 .block = target.block_index,1403 .block = target.block_index,
1404 .operand = operand,1404 .operand = operand,
1405 }),1405 }),
...@@ -1431,7 +1431,7 @@ fn transformExpression(...@@ -1431,7 +1431,7 @@ fn transformExpression(
1431 .none, .used => operand,1431 .none, .used => operand,
1432 else => try t.addRef(.coercion, .{1432 else => try t.addRef(.coercion, .{
1433 .src_node = ctx.nodeOffset(node),1433 .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, .{
1435 .type = try break_result.consume(t) orelse1435 .type = try break_result.consume(t) orelse
1436 unreachable, // `.none` already handled1436 unreachable, // `.none` already handled
1437 .operand = operand,1437 .operand = operand,
...@@ -1441,7 +1441,7 @@ fn transformExpression(...@@ -1441,7 +1441,7 @@ fn transformExpression(
14411441
1442 _ = try t.addIndex(.@"break", .{1442 _ = try t.addIndex(.@"break", .{
1443 .src_node = ctx.nodeOffset(node),1443 .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, .{
1445 .block = try block.getInst(t),1445 .block = try block.getInst(t),
1446 .operand = coerced_operand,1446 .operand = coerced_operand,
1447 }),1447 }),
...@@ -1474,7 +1474,7 @@ fn transformExpression(...@@ -1474,7 +1474,7 @@ fn transformExpression(
14741474
1475 return try t.addRef(.struct_decl, .{1475 return try t.addRef(.struct_decl, .{
1476 .src_node = ctx.nodeOffset(node),1476 .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, .{
1478 .payload_index = payload_index,1478 .payload_index = payload_index,
1479 .field_len = @intCast(struct_node.fields.len),1479 .field_len = @intCast(struct_node.fields.len),
1480 }),1480 }),
...@@ -1524,7 +1524,7 @@ fn transformExpression(...@@ -1524,7 +1524,7 @@ fn transformExpression(
15241524
1525 return try t.addRef(.struct_init, .{1525 return try t.addRef(.struct_init, .{
1526 .src_node = ctx.nodeOffset(node),1526 .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, .{
1528 .base_type = base_type,1528 .base_type = base_type,
1529 .payload_index = payload_index,1529 .payload_index = payload_index,
1530 .field_len = @intCast(struct_node.fields.len),1530 .field_len = @intCast(struct_node.fields.len),
...@@ -1549,7 +1549,7 @@ fn transformExpression(...@@ -1549,7 +1549,7 @@ fn transformExpression(
15491549
1550 return try t.addRef(.array_init, .{1550 return try t.addRef(.array_init, .{
1551 .src_node = ctx.nodeOffset(node),1551 .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, .{
1553 .type_hint = if (array_type) |ty| ty.toOptional() else .none,1553 .type_hint = if (array_type) |ty| ty.toOptional() else .none,
1554 .list = items,1554 .list = items,
1555 }),1555 }),
...@@ -1567,7 +1567,7 @@ fn transformExpression(...@@ -1567,7 +1567,7 @@ fn transformExpression(
15671567
1568 return try t.addRef(.tuple_init, .{1568 return try t.addRef(.tuple_init, .{
1569 .src_node = ctx.nodeOffset(node),1569 .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, .{
1571 .type_hint = .none,1571 .type_hint = .none,
1572 .items = items,1572 .items = items,
1573 }),1573 }),
...@@ -1581,7 +1581,7 @@ fn transformExpression(...@@ -1581,7 +1581,7 @@ fn transformExpression(
15811581
1582 return try t.addRef(.tuple_type, .{1582 return try t.addRef(.tuple_type, .{
1583 .src_node = ctx.nodeOffset(node),1583 .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, .{
1585 .items = items,1585 .items = items,
1586 }),1586 }),
1587 });1587 });
...@@ -1645,7 +1645,7 @@ fn transformExpression(...@@ -1645,7 +1645,7 @@ fn transformExpression(
16451645
1646 return try t.addRef(.func, .{1646 return try t.addRef(.func, .{
1647 .src_node = ctx.nodeOffset(node),1647 .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, .{
1649 .params = param_list,1649 .params = param_list,
1650 .return_type = if (return_type) |ref| ref.toOptional() else .none,1650 .return_type = if (return_type) |ref| ref.toOptional() else .none,
1651 .body = body,1651 .body = body,
...@@ -1862,7 +1862,7 @@ const AssignmentTarget = union(enum) {...@@ -1862,7 +1862,7 @@ const AssignmentTarget = union(enum) {
1862 }),1862 }),
1863 .field => |field| try t.addRef(.field, .{1863 .field => |field| try t.addRef(.field, .{
1864 .src_node = field.src_node,1864 .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, .{
1866 .lhs = field.base,1866 .lhs = field.base,
1867 .rhs = field.field,1867 .rhs = field.field,
1868 }),1868 }),
...@@ -1874,21 +1874,21 @@ const AssignmentTarget = union(enum) {...@@ -1874,21 +1874,21 @@ const AssignmentTarget = union(enum) {
1874 return switch (target) {1874 return switch (target) {
1875 .memory => |memory| try t.addRef(.store, .{1875 .memory => |memory| try t.addRef(.store, .{
1876 .src_node = ctx.nodeOffset(node),1876 .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, .{
1878 .memory = memory,1878 .memory = memory,
1879 .operand = rhs,1879 .operand = rhs,
1880 }),1880 }),
1881 }),1881 }),
1882 .variable_declaration => |var_decl| try t.addRef(.store_decl, .{1882 .variable_declaration => |var_decl| try t.addRef(.store_decl, .{
1883 .src_node = ctx.nodeOffset(node),1883 .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, .{
1885 .var_decl = var_decl.string,1885 .var_decl = var_decl.string,
1886 .operand = rhs,1886 .operand = rhs,
1887 }),1887 }),
1888 }),1888 }),
1889 .field => |field| try t.addRef(.store_field, .{1889 .field => |field| try t.addRef(.store_field, .{
1890 .src_node = ctx.nodeOffset(node),1890 .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, .{
1892 .base = field.base,1892 .base = field.base,
1893 .field = field.field,1893 .field = field.field,
1894 .operand = rhs,1894 .operand = rhs,
...@@ -1998,7 +1998,7 @@ fn transformBlockStatement(...@@ -1998,7 +1998,7 @@ fn transformBlockStatement(
1998 if (value_result != .used) {1998 if (value_result != .used) {
1999 break :coerced try t.addRef(.coercion, .{1999 break :coerced try t.addRef(.coercion, .{
2000 .src_node = ctx.nodeOffset(node),2000 .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, .{
2002 .type = ref,2002 .type = ref,
2003 .operand = data_ref,2003 .operand = data_ref,
2004 }),2004 }),
...@@ -2110,7 +2110,7 @@ fn transformBlockStatement(...@@ -2110,7 +2110,7 @@ fn transformBlockStatement(
2110 }2110 }
2111}2111}
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 {
2114 try t.insts.append(t.gpa, .{2114 try t.insts.append(t.gpa, .{
2115 .tag = tag,2115 .tag = tag,
2116 .data = .encode(tag, data),2116 .data = .encode(tag, data),
...@@ -2118,13 +2118,13 @@ fn addUntracked(t: *Transform, comptime tag: Teg.Tag, data: tag.Data()) !Inst.In...@@ -2118,13 +2118,13 @@ fn addUntracked(t: *Transform, comptime tag: Teg.Tag, data: tag.Data()) !Inst.In
2118 return @enumFromInt(t.insts.len - 1);2118 return @enumFromInt(t.insts.len - 1);
2119}2119}
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 {
2122 const index = try t.addUntracked(tag, data);2122 const index = try t.addUntracked(tag, data);
2123 try t.scratch.add(t.arena, Inst.Index, index);2123 try t.scratch.add(t.arena, Inst.Index, index);
2124 return index;2124 return index;
2125}2125}
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 {
2128 return (try t.addIndex(tag, data)).toRef();2128 return (try t.addIndex(tag, data)).toRef();
2129}2129}
21302130
...@@ -2333,18 +2333,18 @@ const Allocator = mem.Allocator;...@@ -2333,18 +2333,18 @@ const Allocator = mem.Allocator;
2333const assert = std.debug.assert;2333const assert = std.debug.assert;
23342334
2335const core = @import("mod.zig");2335const core = @import("mod.zig");
2336const Teg = core.Teg;2336const Hir = core.Hir;
2337const Inst = Teg.Inst;2337const Inst = Hir.Inst;
2338const NullTerminatedString = Teg.NullTerminatedString;2338const NullTerminatedString = Hir.NullTerminatedString;
2339const SlicedString = Teg.SlicedString;2339const SlicedString = Hir.SlicedString;
2340const RefList = Teg.RefList;2340const RefList = Hir.RefList;
2341const IndexList = Teg.IndexList;2341const IndexList = Hir.IndexList;
2342const OptionalRefList = Teg.OptionalRefList;2342const OptionalRefList = Hir.OptionalRefList;
2343const EncodedData = Teg.EncodedData;2343const EncodedData = Hir.EncodedData;
2344const ExtraIndex = Teg.ExtraIndex;2344const ExtraIndex = Hir.ExtraIndex;
23452345
2346const array = core.array;2346const array = core.array;
2347const ExtraStore = array.ExtraStore(.teg, .@"var");2347const ExtraStore = array.ExtraStore(.hir, .@"var");
2348const Float = array.Float;2348const Float = array.Float;
23492349
2350const Tokenizer = core.Tokenizer;2350const Tokenizer = core.Tokenizer;
src/core/array.zig+1-1
...@@ -77,7 +77,7 @@ fn getAsU32(items: []const u32, comptime T: type, index: usize) T {...@@ -77,7 +77,7 @@ fn getAsU32(items: []const u32, comptime T: type, index: usize) T {
7777
78pub const StoreKind = enum {78pub const StoreKind = enum {
79 intern_pool,79 intern_pool,
80 teg,80 hir,
81 air,81 air,
82 js_tree,82 js_tree,
8383
src/core/mod.zig+1-1
...@@ -17,7 +17,7 @@ pub const U32Stack = Stack(u32);...@@ -17,7 +17,7 @@ pub const U32Stack = Stack(u32);
17pub const StoredTrace = @import("StoredTrace.zig");17pub const StoredTrace = @import("StoredTrace.zig");
18pub const DebugStoredTrace = StoredTrace.DebugStoredTrace;18pub const DebugStoredTrace = StoredTrace.DebugStoredTrace;
19pub const Queue = @import("queue.zig").Queue;19pub const Queue = @import("queue.zig").Queue;
20pub const Teg = @import("Teg.zig");20pub const Hir = @import("Hir.zig");
21pub const Tokenizer = @import("Tokenizer.zig");21pub const Tokenizer = @import("Tokenizer.zig");
22pub const Transform = @import("Transform.zig");22pub const Transform = @import("Transform.zig");
23pub const unicode_props = @import("unicode_props.zig");23pub 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 {...@@ -299,7 +299,7 @@ fn cmdBuildOrRun(ctx: Context, comptime mode: enum { build, run }) !void {
299 const main_file = try comp.getFile(file_path);299 const main_file = try comp.getFile(file_path);
300300
301 var fail_report: Report = undefined;301 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) {
303 error.TransformFail => {303 error.TransformFail => {
304 std.debug.print("Transform failed:\n", .{});304 std.debug.print("Transform failed:\n", .{});
305 try fail_report.dump(.initComp(&comp, main_file), comp.out);305 try fail_report.dump(.initComp(&comp, main_file), comp.out);
...@@ -321,7 +321,7 @@ fn cmdBuildOrRun(ctx: Context, comptime mode: enum { build, run }) !void {...@@ -321,7 +321,7 @@ fn cmdBuildOrRun(ctx: Context, comptime mode: enum { build, run }) !void {
321321
322 if (comp.options.dump_ir) {322 if (comp.options.dump_ir) {
323 const stderr = std.io.getStdErr().writer();323 const stderr = std.io.getStdErr().writer();
324 try teg.dumpToWriter(stderr, null);324 try hir.dumpToWriter(stderr, null);
325 }325 }
326326
327 const entry_point = comp.enqueueEntryModule(main_file) catch |err| switch (err) {327 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 {...@@ -6,8 +6,8 @@ pub fn main() !void {
6 inline for (.{6 inline for (.{
7 .{ "TokenTag", Tokenizer.Token.Tag },7 .{ "TokenTag", Tokenizer.Token.Tag },
8 .{ "NodeTag", Ast.Node.Tag },8 .{ "NodeTag", Ast.Node.Tag },
9 .{ "TegInstTag", Teg.Tag },9 .{ "HirInstTag", Hir.Tag },
10 .{ "TegInstRef", Teg.Inst.Ref },10 .{ "HirInstRef", Hir.Inst.Ref },
11 }) |decl| {11 }) |decl| {
12 const name, const enum_type = decl;12 const name, const enum_type = decl;
1313
...@@ -24,4 +24,4 @@ const std = @import("std");...@@ -24,4 +24,4 @@ const std = @import("std");
24const core = @import("core");24const core = @import("core");
25const Tokenizer = core.Tokenizer;25const Tokenizer = core.Tokenizer;
26const Ast = core.Ast;26const Ast = core.Ast;
27const Teg = core.Teg;27const Hir = core.Hir;
test/compiler_tests.zig+5-5
...@@ -98,7 +98,7 @@ fn runTestCase(...@@ -98,7 +98,7 @@ fn runTestCase(
98 const main_file = try comp.getFile(file_path);98 const main_file = try comp.getFile(file_path);
9999
100 var fail_report: core.Report = undefined;100 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) {
102 error.TransformFail => {102 error.TransformFail => {
103 try out.print("Transform failed:\n", .{});103 try out.print("Transform failed:\n", .{});
104 try fail_report.dump(.{ .comp = .{ .comp = &comp, .file = main_file } }, comp.out);104 try fail_report.dump(.{ .comp = .{ .comp = &comp, .file = main_file } }, comp.out);
...@@ -112,7 +112,7 @@ fn runTestCase(...@@ -112,7 +112,7 @@ fn runTestCase(
112 };112 };
113113
114 if (case_options.dump_ir) {114 if (case_options.dump_ir) {
115 try teg.dumpToWriter(out, .escape_codes);115 try hir.dumpToWriter(out, .escape_codes);
116 }116 }
117117
118 const entry_point = try comp.enqueueEntryModule(main_file);118 const entry_point = try comp.enqueueEntryModule(main_file);
...@@ -121,8 +121,8 @@ fn runTestCase(...@@ -121,8 +121,8 @@ fn runTestCase(
121 if (comp.temp_flag_had_errors)121 if (comp.temp_flag_had_errors)
122 return error.SemaErrors;122 return error.SemaErrors;
123123
124 if (teg.report.warnings.len > 0)124 if (hir.report.warnings.len > 0)
125 return error.TegWarnings;125 return error.HirWarnings;
126126
127 var js_out: std.ArrayListUnmanaged(u8) = .{};127 var js_out: std.ArrayListUnmanaged(u8) = .{};
128 defer js_out.deinit(alloc);128 defer js_out.deinit(alloc);
...@@ -227,7 +227,7 @@ pub fn runTestCaseWrap(...@@ -227,7 +227,7 @@ pub fn runTestCaseWrap(
227 const stack = switch (err) {227 const stack = switch (err) {
228 error.TransformFail,228 error.TransformFail,
229 error.ParseFail,229 error.ParseFail,
230 error.TegWarnings,230 error.HirWarnings,
231 error.SemaErrors,231 error.SemaErrors,
232 error.AnalysisFail,232 error.AnalysisFail,
233 => core.StoredTrace.empty,233 => core.StoredTrace.empty,