| author | |
| committer | |
| log | daf7e3a223445a0020d0ffa52a54f26bf4374126 |
| tree | 926982dd66bf3df168d658c2ee0f1bfb403e78b4 |
| parent | 5f480e3bc33c572ac26aefc905d9426cad259954 |
| signature | Commit is signed but in an unrecognized format. |
22 files changed, 1761 insertions(+), 1753 deletions(-)
README.md+3-2| ... | @@ -1,7 +1,8 @@ | ... | @@ -1,7 +1,8 @@ |
| 1 | # Ix | 1 | # Ix |
| 2 | 2 | ||
| 3 | Ix (**I**nferable E**x**pression) is a high-level, general purpose programming | 3 | Ix (***I***nferable E***x***pression) is a high-level, general purpose |
| 4 | language. It features a mix of Rust, Zig, and JavaScript's great points. | 4 | programming language. It features a mix of Rust, Zig, and JavaScript's great |
| 5 | points. | ||
| 5 | 6 | ||
| 6 | For a guide on how to use Ix, see the manual included in the binary | 7 | For a guide on how to use Ix, see the manual included in the binary |
| 7 | distribution. Additionally, the latest commit of the manual is hosted online at | 8 | distribution. 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 code | 34 | 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 transform | 36 | - **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. |
| 38 | 38 | ||
| 39 | All compiler tests can be run with `zig build test`, or the test suite can be | 39 | All compiler tests can be run with `./build test`, or the test suite can be |
| 40 | filtered using flags, see `zig build test --help` | 40 | filtered using flags, see `./build test -- --help` |
| 41 | 41 | ||
| 42 | To run Zig tests for an associated module, use `zig build test-{name}`, or run | 42 | To 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. |
| 44 | 44 | ||
| 45 | ## Core | 45 | ## Core |
| 46 | 46 | ||
| ... | @@ -48,7 +48,7 @@ The `core` module contains most of the compiler: | ... | @@ -48,7 +48,7 @@ The `core` module contains most of the compiler: |
| 48 | 48 | ||
| 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 representation | 50 | - 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: |
| 56 | 56 | ||
| 57 | Note that components like the formatter and module fetching code are not here. | 57 | Note that components like the formatter and module fetching code are not here. |
| 58 | Keeping this module as small as possible is important for keeping compile times | 58 | Keeping this module as small as possible is important for keeping compile times |
| 59 | low. Using `zig build compiler -- --help` instead of the fully featured binary | 59 | low. Using `./build compiler -- --help` instead of the fully featured binary |
| 60 | will allow for faster and more focused iteration. | 60 | will allow for faster and more focused iteration. |
| 61 | 61 | ||
| 62 | ## Manual | 62 | ## Manual |
doc/language-manual.md+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | # Ix Programming Language | 1 | # Ix Programming Language |
| 2 | 2 | ||
| 3 | Ix (**I**nferable E**x**pression) is a high-level programming language for | 3 | Ix (***I***nferable E***x***pression) is a high-level programming language for |
| 4 | developing web applications and games. | 4 | developing web applications and games. |
| 5 | 5 | ||
| 6 | Key goals of this project are: | 6 | Key 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); |
| 82 | 82 | ||
| 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 { |
| 97 | 97 | ||
| 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 | } |
| 102 | 102 | ||
| 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 | } |
| 67 | 67 | ||
| 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); |
| 85 | 85 | ||
| 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 }); |
| 89 | 89 | ||
| 90 | try teg.dumpToWriter(out.writer, out.tty); | 90 | try hir.dumpToWriter(out.writer, out.tty); |
| 91 | 91 | ||
| 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 Teg | 1 | //! This implements a debug formatter for Air |
| 2 | air: Air, | 2 | air: Air, |
| 3 | ip: *const InternPool, | 3 | ip: *const InternPool, |
| 4 | tty: std.io.tty.Config, | 4 | tty: 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, this | 2 | //! as it is used for formatting. Before semantic analysis, this |
| 3 | //! structure is normalized into `Teg`, which removes constructs like | 3 | //! structure is normalized into `Hir`, which removes constructs like |
| 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) { |
| 110 | 110 | ||
| 111 | pub fn enqueueEntryModule(comp: *Comp, file: *File) !Decl.Index { | 111 | pub 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); |
| 114 | 114 | ||
| 115 | // TODO, move this elsewhere. we should print all errors and warnings at once | 115 | // 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 | } |
| 119 | 119 | ||
| 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 error | 123 | // 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?"); |
| 172 | 172 | ||
| 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 | }; |
| 279 | 279 | ||
| 280 | /// A file in the compilation and it's associated data structures. Ast and Teg | 280 | /// A file in the compilation and it's associated data structures. Ast and Hir |
| 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`. |
| 282 | pub const File = struct { | 282 | pub const File = struct { |
| 283 | /// TODO: change this to a URL | 283 | /// TODO: change this to a URL |
| ... | @@ -287,7 +287,7 @@ pub const File = struct { | ... | @@ -287,7 +287,7 @@ pub const File = struct { |
| 287 | 287 | ||
| 288 | source: ?Source, | 288 | source: ?Source, |
| 289 | ast: ?Ast, | 289 | ast: ?Ast, |
| 290 | teg: ?Teg, | 290 | hir: ?Hir, |
| 291 | 291 | ||
| 292 | path_digest: ?Cache.BinDigest, | 292 | path_digest: ?Cache.BinDigest, |
| 293 | 293 | ||
| ... | @@ -323,7 +323,7 @@ pub const File = struct { | ... | @@ -323,7 +323,7 @@ pub const File = struct { |
| 323 | 323 | ||
| 324 | // Here we do not modify stat fields because this function is the one | 324 | // 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 that | 325 | // 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. |
| 327 | 327 | ||
| 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 | } |
| 372 | 372 | ||
| 373 | pub const GetTegError = GetAstError || Transform.Error; | 373 | pub const GetHirError = GetAstError || Transform.Error; |
| 374 | 374 | ||
| 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 | } |
| 379 | 379 | ||
| 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; |
| 389 | 389 | ||
| 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); |
| 391 | 391 | ||
| 392 | file.teg = teg; | 392 | file.hir = hir; |
| 393 | return teg; | 393 | return hir; |
| 394 | } | 394 | } |
| 395 | 395 | ||
| 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 | } |
| 409 | 409 | ||
| 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 | } |
| 416 | 416 | ||
| 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, |
| 478 | 478 | ||
| 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, |
| 481 | 481 | ||
| 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 | }; |
| 622 | 622 | ||
| 623 | /// Index a Teg's module scope as a namespace. This prepares `Decl` objects for | 623 | /// Index a Hir's module scope as a namespace. This prepares `Decl` objects for |
| 624 | /// every declaration, but does not begin analysis of them. | 624 | /// every declaration, but does not begin analysis of them. |
| 625 | pub fn indexTegModule(comp: *Comp, file: *File, module_index: Teg.Inst.Index) !Namespace.Index { | 625 | pub fn indexHirModule(comp: *Comp, file: *File, module_index: Hir.Inst.Index) !Namespace.Index { |
| 626 | const teg = file.teg.?; | 626 | const hir = file.hir.?; |
| 627 | 627 | ||
| 628 | assert(file.root_namespace == .none); | 628 | assert(file.root_namespace == .none); |
| 629 | 629 | ||
| ... | @@ -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); |
| 637 | 637 | ||
| 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; |
| 736 | 736 | ||
| 737 | const Ast = core.Ast; | 737 | const Ast = core.Ast; |
| 738 | const Air = core.Air; | 738 | const Air = core.Air; |
| 739 | const Teg = core.Teg; | 739 | const Hir = core.Hir; |
| 740 | const Cache = core.Cache; | 740 | const Cache = core.Cache; |
| 741 | const Sema = core.Sema; | 741 | const Sema = core.Sema; |
| 742 | const Transform = core.Transform; | 742 | const Transform = core.Transform; |
src/core/Hir.Dump.zig created+522| ... | @@ -0,0 +1,522 @@ | ||
| 1 | //! This implements a debug formatter for Hir | ||
| 2 | hir: Hir, | ||
| 3 | tty: ?std.io.tty.Config = null, | ||
| 4 | |||
| 5 | const 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 | |||
| 495 | pub 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 | |||
| 517 | const std = @import("std"); | ||
| 518 | const assert = std.debug.assert; | ||
| 519 | |||
| 520 | const core = @import("mod.zig"); | ||
| 521 | const Hir = core.Hir; | ||
| 522 | const 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 | |||
| 14 | insts: Inst.List.Slice, | ||
| 15 | string_bytes: []const u8, | ||
| 16 | extra: ExtraStore = .{}, | ||
| 17 | report: Report, | ||
| 18 | |||
| 19 | pub const ExtraStore = dod.ExtraStore(.hir, .@"const"); | ||
| 20 | pub const EncodedData = dod.EncodedData(Tag, u64); | ||
| 21 | pub const ExtraIndex = ExtraStore.Index; | ||
| 22 | pub const Dump = @import("Hir.Dump.zig"); | ||
| 23 | |||
| 24 | pub 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 | |||
| 214 | pub 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 | |||
| 223 | pub const RefNode = struct { | ||
| 224 | src_node: NodeOffset, | ||
| 225 | operand: Inst.Ref, | ||
| 226 | }; | ||
| 227 | |||
| 228 | pub const StrNode = struct { | ||
| 229 | src_node: NodeOffset, | ||
| 230 | string: NullTerminatedString, | ||
| 231 | }; | ||
| 232 | |||
| 233 | pub const DataNode = struct { | ||
| 234 | src_node: NodeOffset, | ||
| 235 | data: u32, | ||
| 236 | }; | ||
| 237 | |||
| 238 | pub 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 | |||
| 350 | pub const Bin = struct { | ||
| 351 | lhs: Inst.Ref, | ||
| 352 | rhs: Inst.Ref, | ||
| 353 | }; | ||
| 354 | |||
| 355 | pub const Store = struct { | ||
| 356 | memory: Inst.Index, | ||
| 357 | operand: Inst.Ref, | ||
| 358 | }; | ||
| 359 | |||
| 360 | pub const StoreVarDecl = struct { | ||
| 361 | var_decl: NullTerminatedString, | ||
| 362 | operand: Inst.Ref, | ||
| 363 | }; | ||
| 364 | |||
| 365 | pub const StoreField = struct { | ||
| 366 | base: Inst.Ref, | ||
| 367 | field: Inst.Ref, | ||
| 368 | operand: Inst.Ref, | ||
| 369 | }; | ||
| 370 | |||
| 371 | pub const Coercion = struct { | ||
| 372 | type: Inst.Ref, | ||
| 373 | operand: Inst.Ref, | ||
| 374 | }; | ||
| 375 | |||
| 376 | pub const Break = struct { | ||
| 377 | block: Inst.Index, | ||
| 378 | operand: Inst.Ref, | ||
| 379 | }; | ||
| 380 | |||
| 381 | pub const Call = struct { | ||
| 382 | base: Inst.Ref, | ||
| 383 | args: RefList, | ||
| 384 | }; | ||
| 385 | |||
| 386 | pub const If = struct { | ||
| 387 | cond: Inst.Ref, | ||
| 388 | yes: Inst.Ref, | ||
| 389 | no: Inst.Ref, | ||
| 390 | }; | ||
| 391 | |||
| 392 | pub 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. | ||
| 400 | pub 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 | ||
| 418 | pub 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 | |||
| 436 | pub 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 | |||
| 445 | pub const TupleType = struct { | ||
| 446 | /// The items in the tuple | ||
| 447 | items: RefList, | ||
| 448 | }; | ||
| 449 | |||
| 450 | pub 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 | |||
| 459 | pub const Decl = struct { | ||
| 460 | name: NullTerminatedString, | ||
| 461 | hash: Cache.BinDigest, | ||
| 462 | instruction_count: u32, | ||
| 463 | body: Inst.Ref, | ||
| 464 | }; | ||
| 465 | |||
| 466 | pub 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 | |||
| 474 | pub 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 | |||
| 481 | pub const ResultTypeStructField = struct { | ||
| 482 | /// The type of the struct itself, | ||
| 483 | type: Inst.Ref, | ||
| 484 | /// Which field | ||
| 485 | field: NullTerminatedString, | ||
| 486 | }; | ||
| 487 | |||
| 488 | pub const ResultTypeTupleField = struct { | ||
| 489 | /// The type of the tuple itself, | ||
| 490 | type: Inst.Ref, | ||
| 491 | /// Which item | ||
| 492 | item: u32, | ||
| 493 | }; | ||
| 494 | |||
| 495 | pub 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 | ||
| 502 | const NodeOffset = i32; | ||
| 503 | |||
| 504 | // TODO: remove InstOp. LazyNode should not have a decl | ||
| 505 | pub 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 | |||
| 518 | pub 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 | |||
| 531 | pub 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 | |||
| 542 | pub 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 | |||
| 551 | pub 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 | |||
| 560 | pub 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 | |||
| 569 | pub 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 | |||
| 578 | pub 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 | |||
| 586 | pub fn instTag(hir: *const Hir, index: Inst.Index) Hir.Tag { | ||
| 587 | return hir.insts.items(.tag)[@intFromEnum(index)]; | ||
| 588 | } | ||
| 589 | |||
| 590 | pub fn instEncodedData(hir: *const Hir, index: Inst.Index) EncodedData { | ||
| 591 | return hir.insts.items(.data)[@intFromEnum(index)]; | ||
| 592 | } | ||
| 593 | |||
| 594 | pub 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 | |||
| 598 | pub fn instDataUnsafe(hir: *const Hir, comptime T: type, index: Inst.Index) T { | ||
| 599 | return hir.instEncodedData(index).decodeUnsafe(T, hir.instTag(index)); | ||
| 600 | } | ||
| 601 | |||
| 602 | pub 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 | |||
| 606 | pub 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 | |||
| 621 | pub 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 | |||
| 625 | pub 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 | |||
| 632 | pub 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 | |||
| 642 | pub fn declData(hir: *const Hir, index: Inst.Index) Hir.Decl { | ||
| 643 | return hir.instDataUnsafe(PlNode(Decl), index).extra_index.get(hir); | ||
| 644 | } | ||
| 645 | |||
| 646 | pub 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 | |||
| 663 | pub 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 | |||
| 670 | pub 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 | |||
| 676 | pub 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 | ||
| 681 | fn 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 | ||
| 689 | fn isolatedIndexValue(decl_index: Inst.Index, index_to_hash: Inst.Index) u32 { | ||
| 690 | return @intFromEnum(index_to_hash) - @intFromEnum(decl_index); | ||
| 691 | } | ||
| 692 | |||
| 693 | pub 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 | |||
| 826 | fn 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 | |||
| 837 | fn 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 | |||
| 848 | fn 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 | |||
| 957 | pub 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 | |||
| 967 | pub 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 | |||
| 989 | const Hir = @This(); | ||
| 990 | |||
| 991 | const std = @import("std"); | ||
| 992 | const mem = std.mem; | ||
| 993 | const assert = std.debug.assert; | ||
| 994 | const HashHelper = std.Build.Cache.HashHelper; | ||
| 995 | |||
| 996 | const core = @import("mod.zig"); | ||
| 997 | const Cache = core.Cache; | ||
| 998 | |||
| 999 | const Ast = core.Ast; | ||
| 1000 | const Unused = Ast.Unused; | ||
| 1001 | const NodeIndex = Ast.NodeIndex; | ||
| 1002 | const TokenIndex = Ast.TokenIndex; | ||
| 1003 | const OptionalNodeIndex = Ast.OptionalNodeIndex; | ||
| 1004 | const OptionalTokenIndex = Ast.OptionalTokenIndex; | ||
| 1005 | const OptionalExtraIndex = Ast.OptionalExtraIndex; | ||
| 1006 | |||
| 1007 | const dod = core.array; | ||
| 1008 | const Float = dod.Float; | ||
| 1009 | |||
| 1010 | const InternPool = core.InternPool; | ||
| 1011 | |||
| 1012 | const Air = core.Air; | ||
| 1013 | |||
| 1014 | const Comp = core.Comp; | ||
| 1015 | |||
| 1016 | const Report = core.Report; | ||
| 1017 | const 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 comptime | 638 | /// This is specified with an integer literal and a corresponding comptime |
| 639 | /// assert below to break an unfortunate and arguably incorrect dependency loop | 639 | /// assert below to break an unfortunate and arguably incorrect dependency loop |
| 640 | /// when compiling. | 640 | /// when compiling. |
| 641 | pub const static_len = Teg.Inst.Index.static_len; | 641 | pub const static_len = Hir.Inst.Index.static_len; |
| 642 | comptime { | 642 | comptime { |
| 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) { |
| 805 | 805 | ||
| 806 | pub const TrackedInst = extern struct { | 806 | pub const TrackedInst = extern struct { |
| 807 | path_digest: Cache.BinDigest, | 807 | path_digest: Cache.BinDigest, |
| 808 | inst: Teg.Inst.Index, | 808 | inst: Hir.Inst.Index, |
| 809 | 809 | ||
| 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 | } |
| 814 | 814 | ||
| 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 | } |
| 820 | 820 | ||
| ... | @@ -1659,7 +1659,7 @@ fn getOrPutTrailingString( | ... | @@ -1659,7 +1659,7 @@ fn getOrPutTrailingString( |
| 1659 | } | 1659 | } |
| 1660 | } | 1660 | } |
| 1661 | 1661 | ||
| 1662 | pub fn trackInst(ip: *InternPool, gpa: Allocator, file: *Comp.File, inst: Teg.Inst.Index) Allocator.Error!TrackedInst.Index { | 1662 | pub 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(); |
| 1665 | 1665 | ||
| ... | @@ -1869,7 +1869,7 @@ const assert = std.debug.assert; | ... | @@ -1869,7 +1869,7 @@ const assert = std.debug.assert; |
| 1869 | const core = @import("mod.zig"); | 1869 | const core = @import("mod.zig"); |
| 1870 | const Comp = core.Comp; | 1870 | const Comp = core.Comp; |
| 1871 | const Cache = core.Cache; | 1871 | const Cache = core.Cache; |
| 1872 | const Teg = core.Teg; | 1872 | const Hir = core.Hir; |
| 1873 | const Air = core.Air; | 1873 | const Air = core.Air; |
| 1874 | const dod = core.array; | 1874 | const dod = core.array; |
| 1875 | const Float = dod.Float; | 1875 | const 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 { |
| 1093 | pub const LazyNode = struct { | 1093 | pub const LazyNode = struct { |
| 1094 | // TODO: remove this, it should be inferable off of the analysis unit that belongs to the report | 1094 | // 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, |
| 1098 | 1098 | ||
| 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 | } |
| 1113 | 1113 | ||
| 1114 | const teg = &(ctx.file.?.teg orelse | 1114 | const hir = &(ctx.file.?.hir orelse |
| 1115 | // this will be required once incremental compilation hits | 1115 | // this will be required once incremental compilation hits |
| 1116 | @panic("TODO: teg was unloaded")); | 1116 | @panic("TODO: hir was unloaded")); |
| 1117 | 1117 | ||
| 1118 | const decl_inst = decl.teg_decl_index; | 1118 | const decl_inst = decl.teg_decl_index; |
| 1119 | 1119 | ||
| 1120 | const teg_decl = teg.instData(.declaration, decl_inst.resolve(ctx.ip())); | 1120 | const teg_decl = hir.instData(.declaration, decl_inst.resolve(ctx.ip())); |
| 1121 | 1121 | ||
| 1122 | const node_offset = teg.instNodeOffset(lazy.inst); | 1122 | const node_offset = hir.instNodeOffset(lazy.inst); |
| 1123 | 1123 | ||
| 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 { |
| 1129 | 1129 | ||
| 1130 | const node_tag = ctx.ast.nodeTag(base_node); | 1130 | const node_tag = ctx.ast.nodeTag(base_node); |
| 1131 | 1131 | ||
| 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 | } |
| 1214 | 1214 | ||
| 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; |
| 1467 | const NodeIndex = Ast.NodeIndex; | 1467 | const NodeIndex = Ast.NodeIndex; |
| 1468 | const Location = Ast.Location; | 1468 | const Location = Ast.Location; |
| 1469 | 1469 | ||
| 1470 | const Teg = core.Teg; | 1470 | const Hir = core.Hir; |
| 1471 | 1471 | ||
| 1472 | const Comp = core.Comp; | 1472 | const Comp = core.Comp; |
| 1473 | const File = Comp.File; | 1473 | const 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 an | 4 | //! Designed as a nonrecursive state machine, `Sema` can be paused when an |
| 4 | //! unfinished dependency is encountered, allowing the thread to work | 5 | //! 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. | ||
| 11 | 7 | ||
| 12 | comp: *Comp, | 8 | comp: *Comp, |
| 13 | ip: *InternPool, | 9 | ip: *InternPool, |
| ... | @@ -20,13 +16,13 @@ owner: AnalysisUnit, | ... | @@ -20,13 +16,13 @@ owner: AnalysisUnit, |
| 20 | /// The namespace index that is used for declaration lookups | 16 | /// The namespace index that is used for declaration lookups |
| 21 | ns_index: Namespace.Index, | 17 | ns_index: Namespace.Index, |
| 22 | /// Non-owning copy | 18 | /// Non-owning copy |
| 23 | teg: Teg, | 19 | hir: Hir, |
| 24 | /// The file that .teg is from | 20 | /// The file that .hir is from |
| 25 | file: *File, | 21 | file: *File, |
| 26 | 22 | ||
| 27 | /// All errors and warnings from this decl | 23 | /// All errors and warnings from this decl |
| 28 | report: Report.Builder, | 24 | report: Report.Builder, |
| 29 | /// Map of `Teg` instructions to their resulting `Air` Ref | 25 | /// Map of `Hir` instructions to their resulting `Air` Ref |
| 30 | inst_map: InstMap, | 26 | inst_map: InstMap, |
| 31 | 27 | ||
| 32 | /// `null` when not analyzing function bodies | 28 | /// `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, |
| 87 | 83 | ||
| 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); |
| 116 | 112 | ||
| 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 value | 116 | .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 | }; |
| 166 | 162 | ||
| 167 | const Frame = struct { | 163 | const 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, |
| 170 | 166 | ||
| 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, |
| 175 | 171 | ||
| ... | @@ -192,15 +188,15 @@ const Frame = struct { | ... | @@ -192,15 +188,15 @@ const Frame = struct { |
| 192 | argument: u16, | 188 | argument: u16, |
| 193 | }; | 189 | }; |
| 194 | 190 | ||
| 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 block | 193 | 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 | } |
| 213 | 209 | ||
| 214 | fn currentIndex(frame: *const Frame) Teg.Inst.Index { | 210 | fn currentIndex(frame: *const Frame) Hir.Inst.Index { |
| 215 | // validate the pointer is correct | 211 | // 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) and | 216 | 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 | } |
| 226 | 222 | ||
| 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 | } |
| 232 | 228 | ||
| 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 | } |
| 238 | 234 | ||
| 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 | } |
| 244 | 240 | ||
| 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. |
| 283 | const InstMap = struct { | 279 | const 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, |
| 287 | 283 | ||
| 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); |
| 291 | 287 | ||
| ... | @@ -309,7 +305,7 @@ const InstMap = struct { | ... | @@ -309,7 +305,7 @@ const InstMap = struct { |
| 309 | map.* = undefined; | 305 | map.* = undefined; |
| 310 | } | 306 | } |
| 311 | 307 | ||
| 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 | } |
| 324 | 320 | ||
| 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 | } |
| 333 | 329 | ||
| 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 | }; |
| 373 | 369 | ||
| 374 | fn getRef(s: *Sema, teg_ref: Teg.Inst.Ref, mark: DoMark) Air.Inst.Ref { | 370 | fn 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 | } |
| 391 | 387 | ||
| 392 | fn getValue(s: *Sema, src: LazyNode, teg_ref: Teg.Inst.Ref) !Value { | 388 | fn 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 | } |
| 401 | 397 | ||
| 402 | fn getCoercedValue(s: *Sema, src: LazyNode, teg_ref: Teg.Inst.Ref, ty: Type) !Value { | 398 | fn 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 | } |
| 406 | 402 | ||
| 407 | fn getCoercedRef(s: *Sema, src: LazyNode, teg_ref: Teg.Inst.Ref, ty: Type, mark: DoMark) !Air.Inst.Ref { | 403 | fn 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 | } |
| 411 | 407 | ||
| 412 | fn getType(s: *Sema, src: LazyNode, teg_ref: Teg.Inst.Ref) !Type { | 408 | fn 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 | } |
| 415 | 411 | ||
| ... | @@ -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, |
| 493 | 489 | ||
| 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 value | 492 | // 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 { |
| 523 | 519 | ||
| 524 | const PopControlFlowState = enum { stop, @"continue" }; | 520 | const PopControlFlowState = enum { stop, @"continue" }; |
| 525 | 521 | ||
| 526 | fn stepInner(s: *Sema, comptime tag: Teg.Tag) Error!InstructionKind.fromTag(tag).Result() { | 522 | fn 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 pushed | 524 | .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 InternPool | 531 | // 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 block | 534 | assert(s.frame.mode == .run_time); // never emitted in a comptime block |
| 539 | assert(s.owner.kind == .func); // only emitted in function body | 535 | 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)); |
| 570 | 566 | ||
| 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); |
| 604 | 600 | ||
| 605 | const operand = s.getRef(un.operand, .marked); | 601 | const operand = s.getRef(un.operand, .marked); |
| 606 | 602 | ||
| ... | @@ -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); |
| 626 | 622 | ||
| 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); |
| 628 | 624 | ||
| ... | @@ -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); |
| 643 | 639 | ||
| 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(); |
| 650 | 646 | ||
| 651 | // Fill the first half with keys | 647 | // 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 | } |
| 655 | 651 | ||
| 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 | } |
| 660 | 656 | ||
| ... | @@ -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); |
| 694 | 690 | ||
| ... | @@ -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); |
| 739 | 735 | ||
| ... | @@ -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 | } |
| 760 | 756 | ||
| 761 | // validate function args | 757 | // 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); |
| 796 | 792 | ||
| 797 | assert(node.list.len > 0 or node.type_hint.unwrap() != null); | 793 | assert(node.list.len > 0 or node.type_hint.unwrap() != null); |
| 798 | 794 | ||
| ... | @@ -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) |
| 806 | 802 | ||
| 807 | var is_constant = true; | 803 | var is_constant = true; |
| 808 | 804 | ||
| 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 instruction | 862 | assert(s.hir.instTag(data.memory) == .memory); // corrupt store instruction |
| 867 | 863 | ||
| 868 | try s.ensureAtRuntime(s.lazyNode(.main_node)); // TODO | 864 | try s.ensureAtRuntime(s.lazyNode(.main_node)); // TODO |
| 869 | 865 | ||
| ... | @@ -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 | }, |
| 886 | 882 | ||
| 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); |
| 889 | 885 | ||
| 890 | try s.ensureAtRuntime(s.lazyNode(.main_node)); | 886 | try s.ensureAtRuntime(s.lazyNode(.main_node)); |
| 891 | 887 | ||
| ... | @@ -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) |
| 893 | 889 | ||
| 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 | }, |
| 925 | 921 | ||
| 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(); |
| 939 | 935 | ||
| 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))); |
| 942 | 938 | ||
| 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 | }, |
| 992 | 988 | ||
| 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); |
| 996 | 992 | ||
| 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"); |
| 1040 | 1036 | ||
| 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); |
| 1097 | 1093 | ||
| 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 | }, |
| 1173 | 1169 | ||
| 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 | }, |
| 1184 | 1180 | ||
| 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 | }, |
| 1190 | 1186 | ||
| 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 | }, |
| 1200 | 1196 | ||
| 1201 | .@"if" => { | 1197 | .@"if" => { |
| 1202 | const data: Teg.If = s.frame.currentPayload(.@"if"); | 1198 | const data: Hir.If = s.frame.currentPayload(.@"if"); |
| 1203 | 1199 | ||
| 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 | }, |
| 1271 | 1267 | ||
| 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); |
| 1274 | 1270 | ||
| 1275 | // Ensure we have a valid struct to operate on | 1271 | // 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, which | 1291 | // The ordering of `storage` is defined by the struct's type, which |
| 1296 | // may be different than the instantiation. The fields are visited in | 1292 | // 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 | }, |
| 1375 | 1371 | ||
| 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 | }, |
| 1381 | 1377 | ||
| 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); |
| 1384 | 1380 | ||
| 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(); |
| 1387 | 1383 | ||
| 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 | } |
| 1391 | 1387 | ||
| ... | @@ -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 | }, |
| 1394 | 1390 | ||
| 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); |
| 1397 | 1393 | ||
| 1398 | _ = data.type_hint; // TODO: use type hint | 1394 | _ = data.type_hint; // TODO: use type hint |
| 1399 | 1395 | ||
| ... | @@ -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(); |
| 1402 | 1398 | ||
| 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 | }, |
| 1448 | 1444 | ||
| 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); |
| 1451 | 1447 | ||
| 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 | }, |
| 1463 | 1459 | ||
| 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); |
| 1466 | 1462 | ||
| 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) orelse | 1464 | 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 | }, |
| 1476 | 1472 | ||
| 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); |
| 1479 | 1475 | ||
| 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) orelse | 1477 | 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 | }, |
| 1488 | 1484 | ||
| 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); |
| 1491 | 1487 | ||
| 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) orelse | 1489 | 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) orelse | 1492 | const struct_type = ty.toStructType(s.ip) orelse |
| 1497 | return Value.opaque_type.toAir(); | 1493 | return Value.opaque_type.toAir(); |
| 1498 | 1494 | ||
| 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) |
| 1512 | 1508 | ||
| 1513 | fn emitRuntimeBlock( | 1509 | fn 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 | }; |
| 1555 | 1551 | ||
| 1556 | fn binTypeResolution(s: *Sema, src: Teg.Inst.Index, op: BinaryOp, lhs: Type, rhs: Type) !Type { | 1552 | fn 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 | } |
| 2127 | 2123 | ||
| 2128 | fn fieldAccessArray(s: *Sema, lhs: Air.Inst.Ref, lhs_type: Type, rhs_teg: Teg.Inst.Ref) !Air.Inst.Ref { | 2124 | fn 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); |
| 2130 | 2126 | ||
| 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; |
| 2387 | const Decl = Comp.Decl; | 2383 | const Decl = Comp.Decl; |
| 2388 | const Namespace = Comp.Namespace; | 2384 | const Namespace = Comp.Namespace; |
| 2389 | 2385 | ||
| 2390 | const Teg = core.Teg; | 2386 | const Hir = core.Hir; |
| 2391 | 2387 | ||
| 2392 | const Air = core.Air; | 2388 | const Air = core.Air; |
| 2393 | const Ast = core.Ast; | 2389 | const 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 itself | 1 | //! A variant of `std.builtin.StackTrace` that stores its data within itself |
| 2 | //! instead of being a pointer. This allows capturing the stack trace and | 2 | //! instead of being a pointer. This allows storing captured stack traces |
| 3 | //! saving it for later printing. | 3 | //! for later printing. |
| 4 | 4 | ||
| 5 | data: [31]usize, | 5 | data: [31]usize, |
| 6 | index: usize, | 6 | index: usize, |
src/core/Teg.Dump.zig deleted-522| ... | @@ -1,522 +0,0 @@ | ||
| 1 | //! This implements a debug formatter for Teg | ||
| 2 | teg: Teg, | ||
| 3 | tty: ?std.io.tty.Config = null, | ||
| 4 | |||
| 5 | const 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 | |||
| 495 | pub 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 | |||
| 517 | const std = @import("std"); | ||
| 518 | const assert = std.debug.assert; | ||
| 519 | |||
| 520 | const core = @import("mod.zig"); | ||
| 521 | const Teg = core.Teg; | ||
| 522 | const detectTTYFromWriter = core.detectTTYFromWriter; | ||
src/core/Teg.zig deleted-1006| ... | @@ -1,1006 +0,0 @@ | ||
| 1 | //! TODO: rename this to EIR (expression intermediate representation) | ||
| 2 | |||
| 3 | insts: Inst.List.Slice, | ||
| 4 | string_bytes: []const u8, | ||
| 5 | extra: ExtraStore = .{}, | ||
| 6 | report: Report, | ||
| 7 | |||
| 8 | pub const ExtraStore = dod.ExtraStore(.teg, .@"const"); | ||
| 9 | pub const EncodedData = dod.EncodedData(Tag, u64); | ||
| 10 | pub const ExtraIndex = ExtraStore.Index; | ||
| 11 | pub const Dump = @import("Teg.Dump.zig"); | ||
| 12 | |||
| 13 | pub 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 | |||
| 203 | pub 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 | |||
| 212 | pub const RefNode = struct { | ||
| 213 | src_node: NodeOffset, | ||
| 214 | operand: Inst.Ref, | ||
| 215 | }; | ||
| 216 | |||
| 217 | pub const StrNode = struct { | ||
| 218 | src_node: NodeOffset, | ||
| 219 | string: NullTerminatedString, | ||
| 220 | }; | ||
| 221 | |||
| 222 | pub const DataNode = struct { | ||
| 223 | src_node: NodeOffset, | ||
| 224 | data: u32, | ||
| 225 | }; | ||
| 226 | |||
| 227 | pub 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 | |||
| 339 | pub const Bin = struct { | ||
| 340 | lhs: Inst.Ref, | ||
| 341 | rhs: Inst.Ref, | ||
| 342 | }; | ||
| 343 | |||
| 344 | pub const Store = struct { | ||
| 345 | memory: Inst.Index, | ||
| 346 | operand: Inst.Ref, | ||
| 347 | }; | ||
| 348 | |||
| 349 | pub const StoreVarDecl = struct { | ||
| 350 | var_decl: NullTerminatedString, | ||
| 351 | operand: Inst.Ref, | ||
| 352 | }; | ||
| 353 | |||
| 354 | pub const StoreField = struct { | ||
| 355 | base: Inst.Ref, | ||
| 356 | field: Inst.Ref, | ||
| 357 | operand: Inst.Ref, | ||
| 358 | }; | ||
| 359 | |||
| 360 | pub const Coercion = struct { | ||
| 361 | type: Inst.Ref, | ||
| 362 | operand: Inst.Ref, | ||
| 363 | }; | ||
| 364 | |||
| 365 | pub const Break = struct { | ||
| 366 | block: Inst.Index, | ||
| 367 | operand: Inst.Ref, | ||
| 368 | }; | ||
| 369 | |||
| 370 | pub const Call = struct { | ||
| 371 | base: Inst.Ref, | ||
| 372 | args: RefList, | ||
| 373 | }; | ||
| 374 | |||
| 375 | pub const If = struct { | ||
| 376 | cond: Inst.Ref, | ||
| 377 | yes: Inst.Ref, | ||
| 378 | no: Inst.Ref, | ||
| 379 | }; | ||
| 380 | |||
| 381 | pub 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. | ||
| 389 | pub 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 | ||
| 407 | pub 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 | |||
| 425 | pub 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 | |||
| 434 | pub const TupleType = struct { | ||
| 435 | /// The items in the tuple | ||
| 436 | items: RefList, | ||
| 437 | }; | ||
| 438 | |||
| 439 | pub 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 | |||
| 448 | pub const Decl = struct { | ||
| 449 | name: NullTerminatedString, | ||
| 450 | hash: Cache.BinDigest, | ||
| 451 | instruction_count: u32, | ||
| 452 | body: Inst.Ref, | ||
| 453 | }; | ||
| 454 | |||
| 455 | pub 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 | |||
| 463 | pub 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 | |||
| 470 | pub const ResultTypeStructField = struct { | ||
| 471 | /// The type of the struct itself, | ||
| 472 | type: Inst.Ref, | ||
| 473 | /// Which field | ||
| 474 | field: NullTerminatedString, | ||
| 475 | }; | ||
| 476 | |||
| 477 | pub const ResultTypeTupleField = struct { | ||
| 478 | /// The type of the tuple itself, | ||
| 479 | type: Inst.Ref, | ||
| 480 | /// Which item | ||
| 481 | item: u32, | ||
| 482 | }; | ||
| 483 | |||
| 484 | pub 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 | ||
| 491 | const NodeOffset = i32; | ||
| 492 | |||
| 493 | // TODO: remove InstOp. LazyNode should not have a decl | ||
| 494 | pub 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 | |||
| 507 | pub 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 | |||
| 520 | pub 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 | |||
| 531 | pub 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 | |||
| 540 | pub 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 | |||
| 549 | pub 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 | |||
| 558 | pub 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 | |||
| 567 | pub 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 | |||
| 575 | pub fn instTag(teg: *const Teg, index: Inst.Index) Teg.Tag { | ||
| 576 | return teg.insts.items(.tag)[@intFromEnum(index)]; | ||
| 577 | } | ||
| 578 | |||
| 579 | pub fn instEncodedData(teg: *const Teg, index: Inst.Index) EncodedData { | ||
| 580 | return teg.insts.items(.data)[@intFromEnum(index)]; | ||
| 581 | } | ||
| 582 | |||
| 583 | pub 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 | |||
| 587 | pub fn instDataUnsafe(teg: *const Teg, comptime T: type, index: Inst.Index) T { | ||
| 588 | return teg.instEncodedData(index).decodeUnsafe(T, teg.instTag(index)); | ||
| 589 | } | ||
| 590 | |||
| 591 | pub 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 | |||
| 595 | pub 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 | |||
| 610 | pub 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 | |||
| 614 | pub 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 | |||
| 621 | pub 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 | |||
| 631 | pub fn declData(teg: *const Teg, index: Inst.Index) Teg.Decl { | ||
| 632 | return teg.instDataUnsafe(PlNode(Decl), index).extra_index.get(teg); | ||
| 633 | } | ||
| 634 | |||
| 635 | pub 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 | |||
| 652 | pub 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 | |||
| 659 | pub 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 | |||
| 665 | pub 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 | ||
| 670 | fn 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 | ||
| 678 | fn isolatedIndexValue(decl_index: Inst.Index, index_to_hash: Inst.Index) u32 { | ||
| 679 | return @intFromEnum(index_to_hash) - @intFromEnum(decl_index); | ||
| 680 | } | ||
| 681 | |||
| 682 | pub 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 | |||
| 815 | fn 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 | |||
| 826 | fn 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 | |||
| 837 | fn 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 | |||
| 946 | pub 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 | |||
| 956 | pub 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 | |||
| 978 | const Teg = @This(); | ||
| 979 | |||
| 980 | const std = @import("std"); | ||
| 981 | const mem = std.mem; | ||
| 982 | const assert = std.debug.assert; | ||
| 983 | const HashHelper = std.Build.Cache.HashHelper; | ||
| 984 | |||
| 985 | const core = @import("mod.zig"); | ||
| 986 | const Cache = core.Cache; | ||
| 987 | |||
| 988 | const Ast = core.Ast; | ||
| 989 | const Unused = Ast.Unused; | ||
| 990 | const NodeIndex = Ast.NodeIndex; | ||
| 991 | const TokenIndex = Ast.TokenIndex; | ||
| 992 | const OptionalNodeIndex = Ast.OptionalNodeIndex; | ||
| 993 | const OptionalTokenIndex = Ast.OptionalTokenIndex; | ||
| 994 | const OptionalExtraIndex = Ast.OptionalExtraIndex; | ||
| 995 | |||
| 996 | const dod = core.array; | ||
| 997 | const Float = dod.Float; | ||
| 998 | |||
| 999 | const InternPool = core.InternPool; | ||
| 1000 | |||
| 1001 | const Air = core.Air; | ||
| 1002 | |||
| 1003 | const Comp = core.Comp; | ||
| 1004 | |||
| 1005 | const Report = core.Report; | ||
| 1006 | const 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; |
| 40 | 40 | ||
| 41 | pub fn transform(ast: Ast, gpa: Allocator, fail_report: *Report) Error!Teg { | 41 | pub 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(); |
| 44 | 44 | ||
| ... | @@ -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 ref | 117 | /// 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 initialization | 121 | /// 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 initialization | 123 | /// 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 initialization | 125 | /// The expression is a field in an array initialization |
| 126 | array_value: Inst.Ref, | 126 | array_value: Inst.Ref, |
| 127 | 127 | ||
| 128 | // /// The expression is unknown field | 128 | // /// The expression is unknown field |
| 129 | // field: Teg.ResultTypeField, | 129 | // field: Hir.ResultTypeField, |
| 130 | 130 | ||
| 131 | /// This will return an instruction pointing to the the type | 131 | /// 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. |
| 261 | const CaptureScope = struct { | 261 | const 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) = .{}, |
| 264 | 264 | ||
| 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); |
| 537 | 537 | ||
| 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 |
| 547 | 547 | ||
| 548 | temp_teg.writeToHasher(&hasher, tag_list, data_list, decl_index); | 548 | temp_teg.writeToHasher(&hasher, tag_list, data_list, decl_index); |
| 549 | 549 | ||
| 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 |
| 579 | 579 | ||
| 580 | var hasher: std.Build.Cache.HashHelper = .{ .hasher = core.Cache.hasher_init }; | 580 | var hasher: std.Build.Cache.HashHelper = .{ .hasher = core.Cache.hasher_init }; |
| 581 | 581 | ||
| 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 |
| 591 | 591 | ||
| 592 | temp_teg.writeToHasher(&hasher, tag_list, data_list, decl_index); | 592 | temp_teg.writeToHasher(&hasher, tag_list, data_list, decl_index); |
| 593 | 593 | ||
| 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) orelse | 742 | .type = try result_type_ptr.consume(t) orelse |
| 743 | unreachable, // `.none` already handled | 743 | unreachable, // `.none` already handled |
| 744 | .operand = result, | 744 | .operand = result, |
| ... | @@ -748,7 +748,7 @@ fn transformToBlock( | ... | @@ -748,7 +748,7 @@ fn transformToBlock( |
| 748 | 748 | ||
| 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 { |
| 864 | 864 | ||
| 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( |
| 987 | 987 | ||
| 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 | else | 1081 | else |
| ... | @@ -1096,7 +1096,7 @@ fn transformExpression( | ... | @@ -1096,7 +1096,7 @@ fn transformExpression( |
| 1096 | 1096 | ||
| 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)); |
| 1120 | 1120 | ||
| 1121 | var operand_type: ResultType = switch (tag) { | 1121 | var operand_type: ResultType = switch (tag) { |
| 1122 | .negate => .none, // any numeric type allowed | 1122 | .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( |
| 1276 | 1276 | ||
| 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( |
| 1319 | 1319 | ||
| 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( |
| 1339 | 1339 | ||
| 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( |
| 1370 | 1370 | ||
| 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( |
| 1399 | 1399 | ||
| 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) orelse | 1435 | .type = try break_result.consume(t) orelse |
| 1436 | unreachable, // `.none` already handled | 1436 | unreachable, // `.none` already handled |
| 1437 | .operand = operand, | 1437 | .operand = operand, |
| ... | @@ -1441,7 +1441,7 @@ fn transformExpression( | ... | @@ -1441,7 +1441,7 @@ fn transformExpression( |
| 1441 | 1441 | ||
| 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( |
| 1474 | 1474 | ||
| 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( |
| 1524 | 1524 | ||
| 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( |
| 1549 | 1549 | ||
| 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( |
| 1567 | 1567 | ||
| 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( |
| 1581 | 1581 | ||
| 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( |
| 1645 | 1645 | ||
| 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 | } |
| 2112 | 2112 | ||
| 2113 | fn addUntracked(t: *Transform, comptime tag: Teg.Tag, data: tag.Data()) !Inst.Index { | 2113 | fn 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 | } |
| 2120 | 2120 | ||
| 2121 | fn addIndex(t: *Transform, comptime tag: Teg.Tag, data: tag.Data()) !Inst.Index { | 2121 | fn 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 | } |
| 2126 | 2126 | ||
| 2127 | fn addRef(t: *Transform, comptime tag: Teg.Tag, data: tag.Data()) !Inst.Ref { | 2127 | fn 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 | } |
| 2130 | 2130 | ||
| ... | @@ -2333,18 +2333,18 @@ const Allocator = mem.Allocator; | ... | @@ -2333,18 +2333,18 @@ const Allocator = mem.Allocator; |
| 2333 | const assert = std.debug.assert; | 2333 | const assert = std.debug.assert; |
| 2334 | 2334 | ||
| 2335 | const core = @import("mod.zig"); | 2335 | const core = @import("mod.zig"); |
| 2336 | const Teg = core.Teg; | 2336 | const Hir = core.Hir; |
| 2337 | const Inst = Teg.Inst; | 2337 | const Inst = Hir.Inst; |
| 2338 | const NullTerminatedString = Teg.NullTerminatedString; | 2338 | const NullTerminatedString = Hir.NullTerminatedString; |
| 2339 | const SlicedString = Teg.SlicedString; | 2339 | const SlicedString = Hir.SlicedString; |
| 2340 | const RefList = Teg.RefList; | 2340 | const RefList = Hir.RefList; |
| 2341 | const IndexList = Teg.IndexList; | 2341 | const IndexList = Hir.IndexList; |
| 2342 | const OptionalRefList = Teg.OptionalRefList; | 2342 | const OptionalRefList = Hir.OptionalRefList; |
| 2343 | const EncodedData = Teg.EncodedData; | 2343 | const EncodedData = Hir.EncodedData; |
| 2344 | const ExtraIndex = Teg.ExtraIndex; | 2344 | const ExtraIndex = Hir.ExtraIndex; |
| 2345 | 2345 | ||
| 2346 | const array = core.array; | 2346 | const array = core.array; |
| 2347 | const ExtraStore = array.ExtraStore(.teg, .@"var"); | 2347 | const ExtraStore = array.ExtraStore(.hir, .@"var"); |
| 2348 | const Float = array.Float; | 2348 | const Float = array.Float; |
| 2349 | 2349 | ||
| 2350 | const Tokenizer = core.Tokenizer; | 2350 | const 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 { |
| 77 | 77 | ||
| 78 | pub const StoreKind = enum { | 78 | pub const StoreKind = enum { |
| 79 | intern_pool, | 79 | intern_pool, |
| 80 | teg, | 80 | hir, |
| 81 | air, | 81 | air, |
| 82 | js_tree, | 82 | js_tree, |
| 83 | 83 |
src/core/mod.zig+1-1| ... | @@ -17,7 +17,7 @@ pub const U32Stack = Stack(u32); | ... | @@ -17,7 +17,7 @@ pub const U32Stack = Stack(u32); |
| 17 | pub const StoredTrace = @import("StoredTrace.zig"); | 17 | pub const StoredTrace = @import("StoredTrace.zig"); |
| 18 | pub const DebugStoredTrace = StoredTrace.DebugStoredTrace; | 18 | pub const DebugStoredTrace = StoredTrace.DebugStoredTrace; |
| 19 | pub const Queue = @import("queue.zig").Queue; | 19 | pub const Queue = @import("queue.zig").Queue; |
| 20 | pub const Teg = @import("Teg.zig"); | 20 | pub const Hir = @import("Hir.zig"); |
| 21 | pub const Tokenizer = @import("Tokenizer.zig"); | 21 | pub const Tokenizer = @import("Tokenizer.zig"); |
| 22 | pub const Transform = @import("Transform.zig"); | 22 | pub const Transform = @import("Transform.zig"); |
| 23 | pub const unicode_props = @import("unicode_props.zig"); | 23 | pub 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); |
| 300 | 300 | ||
| 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 { |
| 321 | 321 | ||
| 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 | } |
| 326 | 326 | ||
| 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; |
| 13 | 13 | ||
| ... | @@ -24,4 +24,4 @@ const std = @import("std"); | ... | @@ -24,4 +24,4 @@ const std = @import("std"); |
| 24 | const core = @import("core"); | 24 | const core = @import("core"); |
| 25 | const Tokenizer = core.Tokenizer; | 25 | const Tokenizer = core.Tokenizer; |
| 26 | const Ast = core.Ast; | 26 | const Ast = core.Ast; |
| 27 | const Teg = core.Teg; | 27 | const 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); |
| 99 | 99 | ||
| 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 | }; |
| 113 | 113 | ||
| 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 | } |
| 117 | 117 | ||
| 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; |
| 123 | 123 | ||
| 124 | if (teg.report.warnings.len > 0) | 124 | if (hir.report.warnings.len > 0) |
| 125 | return error.TegWarnings; | 125 | return error.HirWarnings; |
| 126 | 126 | ||
| 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, |