authorchloe caruso <git@paperclover.net> 2024-05-25 17:53:36-07:00
committerchloe caruso <git@paperclover.net> 2024-05-25 17:53:36-07:00
log91ee439c7b9f751d6bceaa26282cfdd0b3cdc6ca
treecb69168284b422a4d88568479c0b8898b5e096b3
parent974964a59da977061f958f51c142256ece5f30ea

introduce InstOp, making it possible to point report items at Teg.Inst


10 files changed, 342 insertions(+), 106 deletions(-)

demo.ix created+1
......@@ -0,0 +1 @@
1let x: int = 1.5;
demo.wl deleted-1
......@@ -1 +0,0 @@
1let x: int = 1.5;
src/compiler/Air.Dump.zig+2-2
......@@ -157,14 +157,14 @@ pub const State = struct {
157157
158158 fn dumpRef(s: *State, w: anytype, ref: Inst.Ref) !void {
159159 switch (ref.decode()) {
160 .inst => |i| try s.dumpInstRef(w, i),
160 .index => |i| try s.dumpInstRef(w, i),
161161 .value => |v| try s.dumpValue(w, v),
162162 }
163163 }
164164
165165 fn dumpRefRecurse(s: *State, w: anytype, ref: Inst.Ref) !void {
166166 switch (ref.decode()) {
167 .inst => |i| try s.dumpInst(w, i),
167 .index => |i| try s.dumpInst(w, i),
168168 .value => |v| try s.dumpValue(w, v),
169169 }
170170 }
src/compiler/Air.zig+5-5
......@@ -68,17 +68,17 @@ pub const Inst = struct {
6868 kind: Kind,
6969 data: u31,
7070
71 pub const Kind = enum(u1) { value, inst };
71 pub const Kind = enum(u1) { value, index };
7272
7373 pub const Decoded = union(enum) {
7474 value: Value,
75 inst: Index,
75 index: Index,
7676 };
7777
7878 pub fn decode(ref: Ref) Decoded {
7979 return switch (ref.kind) {
8080 .value => .{ .value = @enumFromInt(ref.data) },
81 .inst => .{ .inst = @enumFromInt(ref.data) },
81 .index => .{ .index = @enumFromInt(ref.data) },
8282 };
8383 }
8484
......@@ -113,7 +113,7 @@ pub const Inst = struct {
113113
114114 pub fn toRef(index: Index) Ref {
115115 return .{
116 .kind = .inst,
116 .kind = .index,
117117 .data = @intCast(@intFromEnum(index)),
118118 };
119119 }
......@@ -252,7 +252,7 @@ pub fn instPayload(air: *const Air, comptime tag: Inst.Tag, index: Inst.Index) t
252252pub fn typeOf(air: *const Air, ref: Inst.Ref, ip: *InternPool) InternPool.Type {
253253 return switch (ref.decode()) {
254254 .value => |v| v.typeOf(ip),
255 .inst => |i| air.typeOfIndex(i, ip),
255 .index => |i| air.typeOfIndex(i, ip),
256256 };
257257}
258258
src/compiler/Ast.zig+85
......@@ -520,6 +520,91 @@ pub fn nodeToken(ast: Ast, node: NodeIndex) TokenIndex {
520520 return ast.nodes.items(.main_token)[node];
521521}
522522
523// pub fn operandNode(ast: Ast, node: NodeIndex, operand: OperandId) NodeIndex {
524// if (operand == .main_node) return node;
525
526// switch (ast.nodeTag(node)) {
527// .root => unreachable,
528// .block_void => unreachable,
529// .block_implicit_return => unreachable,
530// .var_decl,
531// => return switch (operand) {
532// .type => ast.nodeData(node).var_decl.type.unwrap().?,
533// .initializer => ast.nodeData(node).var_decl.init,
534// else => unreachable,
535// },
536
537// .label,
538// .group,
539// .negate,
540// .bit_not,
541// .bool_not,
542// .@"comptime",
543// => return switch (operand) {
544// .base => ast.nodeData(node).un.expr,
545// else => unreachable, // Invalid unary operand
546// },
547
548// .add,
549// .sub,
550// .mul,
551// .div,
552// .rem,
553// .pow,
554// .@"and",
555// .@"or",
556// .bit_and,
557// .bit_or,
558// .bit_xor,
559// .shl,
560// .shr,
561// .eq,
562// .ne,
563// .lt,
564// .le,
565// .gt,
566// .ge,
567// .assign,
568// .add_assign,
569// .sub_assign,
570// .mul_assign,
571// .div_assign,
572// .rem_assign,
573// .pow_assign,
574// .and_assign,
575// .or_assign,
576// .bit_and_assign,
577// .bit_or_assign,
578// .bit_xor_assign,
579// .shl_assign,
580// .shr_assign,
581// => {
582// const bin = ast.nodeData(node).bin;
583// return switch (operand) {
584// .lhs => bin.lhs,
585// .rhs => bin.rhs,
586// else => unreachable, // Not a valid operand for binary node
587// };
588// },
589
590// .fn_decl,
591// .param_decl,
592// .id,
593// .number_int,
594// .number_float,
595// .string,
596// .multiline_string,
597// .call,
598// .builtin_call,
599// .@"if",
600// .field,
601// .index,
602// .@"return",
603// .@"break",
604// => |tag| std.debug.panic("TODO: operandNode .{s}", .{@tagName(tag)}),
605// }
606// }
607
523608pub fn fullFnDecl(ast: Ast, node: NodeIndex) full.FnDecl {
524609 const tok_tags = ast.tokens.items(.tag);
525610
src/compiler/JsNodeGen.zig+6-6
......@@ -185,8 +185,8 @@ fn codeGenInst(c: *JsNodeGen, inst: Air.Inst.Index) Error!void {
185185
186186 const target = try c.fetchInstExpression(data.memory);
187187
188 if (data.operand.kind == .inst) {
189 const index = data.operand.decode().inst;
188 if (data.operand.kind == .index) {
189 const index = data.operand.decode().index;
190190 switch (c.air.instTag(index)) {
191191 inline .add,
192192 .sub,
......@@ -418,7 +418,7 @@ fn fetchExpression(c: *JsNodeGen, ref: Air.Inst.Ref) !Node.Index {
418418
419419 return switch (ref.decode()) {
420420 .value => |v| c.valueToExpression(v),
421 .inst => |index| fetchInstExpression(c, index),
421 .index => |index| fetchInstExpression(c, index),
422422 };
423423}
424424
......@@ -509,7 +509,7 @@ fn codeGenBranch(c: *JsNodeGen, inst: Air.Inst.Ref, temporary: ?Node.Index) !?Br
509509 }
510510 break :items c.scratch.items[scratch_top..];
511511 },
512 .inst => |i| items: {
512 .index => |i| items: {
513513 assert(c.air.instTag(i) == .block);
514514 c.air_node_map[@intFromEnum(i)] = .{
515515 .block = .{ .index = @intCast(scratch_top) },
......@@ -600,7 +600,7 @@ fn canLowerToExpression(c: *const JsNodeGen, inst: Air.Inst.Ref) bool {
600600
601601 return switch (inst.decode()) {
602602 .value => true,
603 .inst => |index| switch (c.air.instTag(index)) {
603 .index => |index| switch (c.air.instTag(index)) {
604604 .js_global_ref,
605605 .call,
606606 .arg,
......@@ -651,7 +651,7 @@ fn lowerToExpression(c: *JsNodeGen, ref: Air.Inst.Ref) !Node.Index {
651651 assert(c.canLowerToExpression(ref));
652652 return switch (ref.decode()) {
653653 .value => |v| try c.valueToExpression(v),
654 .inst => |index| {
654 .index => |index| {
655655 try c.codeGenInst(index);
656656 return c.fetchExpression(ref);
657657 },
src/compiler/Report.zig+62-2
......@@ -142,6 +142,16 @@ pub const Err = union(enum) {
142142 try ctx.msgNode(node, "numeric literal \"{d}\" cannot be coerced to \"int\"", .{data.val});
143143 }
144144 },
145 coersion: struct {
146 from: Type,
147 to: Type,
148 src: LazyNode,
149
150 fn build(data: @This(), ctx: *MsgContext) !void {
151 const node = try data.src.get(ctx);
152 try ctx.msgNode(node, "stinky", .{});
153 }
154 },
145155};
146156
147157pub const Warn = union(enum) {
......@@ -614,7 +624,8 @@ pub const MsgContext = struct {
614624
615625pub const LazyNode = struct {
616626 decl: Comp.Decl.Index,
617 node_offset: i32,
627 inst: Teg.Inst.Index,
628 operand: Operand,
618629
619630 pub fn get(lazy: LazyNode, ctx: *MsgContext) !NodeIndex {
620631 const decl = ctx.comp.intern_pool.declPtrConst(lazy.decl);
......@@ -640,7 +651,50 @@ pub const LazyNode = struct {
640651
641652 const teg_decl = teg.instData(.declaration, decl_inst.resolve(&ctx.comp.intern_pool));
642653
643 return @intCast(teg_decl.src_node - lazy.node_offset);
654 const node_offset = teg.instNodeOffset(lazy.inst);
655
656 const base_node: NodeIndex = @intCast(node_offset - teg_decl.src_node);
657 if (lazy.operand == .main_node)
658 return base_node;
659
660 const data = ctx.ast.nodeData(base_node);
661
662 switch (teg.instTag(lazy.inst)) {
663 .as => switch (ctx.ast.nodeTag(base_node)) {
664 .var_decl => {
665 switch (lazy.operand) {
666 .rhs => return data.var_decl.init,
667 else => {},
668 }
669 },
670 else => {},
671 },
672 else => {},
673 }
674
675 if (!std.debug.runtime_safety) unreachable;
676
677 std.debug.panic("TODO: operand lookup: .{s} + .{s} + {}", .{
678 @tagName(teg.instTag(lazy.inst)),
679 @tagName(ctx.ast.nodeTag(base_node)),
680 lazy.operand,
681 });
682 }
683};
684
685pub const Operand = enum(u32) {
686 /// Point to the main node of an instruction
687 main_node = 0,
688 /// Base of a call, field, or operand to a unary instruction
689 operand = 1,
690 /// Left hand side of a binary instruction
691 lhs,
692 /// Right hand side of a binary instruction
693 rhs,
694
695 /// An argument of a call node
696 pub fn argument(id: u32) Operand {
697 return @enumFromInt(id + 2);
644698 }
645699};
646700
......@@ -660,7 +714,13 @@ const TokenIndex = Ast.TokenIndex;
660714const NodeIndex = Ast.NodeIndex;
661715const Location = Ast.Location;
662716
717const Teg = @import("Teg.zig");
718
663719const Comp = @import("Comp.zig");
664720const File = Comp.File;
665721
722const InternPool = @import("InternPool.zig");
723const Value = InternPool.Value;
724const Type = InternPool.Type;
725
666726const util = @import("util.zig");
src/compiler/Sema.zig+155-77
......@@ -64,7 +64,7 @@ const InstMap = struct {
6464 if (assertWithMessage(map.get(from) == null)) {
6565 std.debug.panic("%{d} is already mapped (to #{d})", .{
6666 @intFromEnum(from),
67 @intFromEnum(map.get(from).?.decode().inst),
67 @intFromEnum(map.get(from).?.decode().index),
6868 });
6969 }
7070 const source_i = @intFromEnum(from);
......@@ -330,7 +330,7 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref {
330330 .@"break" => {
331331 const brk: Teg.Inst.Break = s.code.instPayload(.@"break", in);
332332 const operand = try s.resolveRefRuntime(brk.operand);
333 const block_ref = s.inst_map.get(brk.block).?.decode().inst; // block ref is resolved by teg
333 const block_ref = s.inst_map.get(brk.block).?.decode().index; // block ref is resolved by teg
334334 return s.addInstRef(.@"break", .{
335335 .block_ref = block_ref,
336336 .value = operand,
......@@ -439,7 +439,7 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref {
439439 .block => {
440440 const block = try s.analyzeBlock(in);
441441 switch (block.decode()) {
442 .inst => |t| if (s.tempAir().instTag(t) == .block) {
442 .index => |t| if (s.tempAir().instTag(t) == .block) {
443443 try s.scratch.append(s.gpa, @intFromEnum(t));
444444 },
445445 else => {},
......@@ -455,7 +455,7 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref {
455455 .value => |v| switch (v.toKey(s.ip)) {
456456 .comptime_float => |val| {
457457 try s.report.warn(.numeric_int_var_ambiguity, .{
458 .node = s.nodeLoc(in),
458 .node = s.nodeLoc(in, .operand),
459459 });
460460 initial_value = (try s.makeValue(.{ .float = val })).toAir();
461461 },
......@@ -473,7 +473,7 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref {
473473 const data: Teg.Inst.Store = s.code.instPayload(.store, in);
474474 assert(s.code.instTag(data.memory) == .memory); // corrupt store instruction
475475
476 const location = s.mapTeg(data.memory.toRef()).decode().inst;
476 const location = s.mapTeg(data.memory.toRef()).decode().index;
477477 const operand = try s.resolveRefRuntime(data.operand);
478478
479479 // try s.validateType(
......@@ -488,9 +488,9 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref {
488488 },
489489 .as => {
490490 const as: Teg.Inst.As = s.code.instPayload(.as, in);
491 const coerce_to = try s.resolveRefComptime(as.type);
491 const coerce_to = try s.resolveRefComptimeType(in.op(.lhs) ,as.type, .type);
492492 const operand = try s.resolveRefRuntime(as.operand);
493 return try s.coerceRef(in, operand, coerce_to.toType(s.ip).?);
493 return try s.coerceRef(in.op(.rhs), operand, coerce_to.toType(s.ip).?);
494494 },
495495 else => |tag| std.debug.panic("TODO: analyze of .{s}", .{@tagName(tag)}),
496496 }
......@@ -516,8 +516,8 @@ fn analyzeRefToBlock(s: *Sema, in: Teg.Inst.Ref) anyerror!Air.Inst.Ref {
516516 return visited;
517517 }
518518
519 if (visited.kind == .inst and
520 s.air_instructions.items(.tag)[@intFromEnum(visited.decode().inst)] == .block)
519 if (visited.kind == .index and
520 s.air_instructions.items(.tag)[@intFromEnum(visited.decode().index)] == .block)
521521 {
522522 return visited;
523523 }
......@@ -538,7 +538,7 @@ fn resolveRefRuntimeExtra(s: *Sema, ref: Teg.Inst.Ref, mark: bool) anyerror!Air.
538538 if (s.inst_map.get(index)) |air| {
539539 if (mark) {
540540 switch (air.decode()) {
541 .inst => |i| s.markInst(i),
541 .index => |i| s.markInst(i),
542542 else => {},
543543 }
544544 }
......@@ -576,67 +576,130 @@ fn resolveRefComptime(s: *Sema, ref: Teg.Inst.Ref) !Value {
576576}
577577
578578/// Coerce `value` runtime ref to `coerce_type`, and emit an error at `teg_ref`'s location
579fn coerceRef(
580 s: *Sema,
581 teg_ref: Teg.Inst.Index,
582 value: Air.Inst.Ref,
583 coerce_to: Type,
584) !Air.Inst.Ref {
585 _ = teg_ref;
586 _ = s;
587 _ = value;
588 _ = coerce_to;
589 // const value_type = s.typeOfRef(value);
590 // switch (coerce_type.toKey(s.ip)) {
591 // .simple_type => |simple_type| switch (simple_type) {
592 // // .@"opaque",
593 // .int32 => {
594 // switch (value_type.toKey(s.ip)) {
595 // .simple_type => switch (simple_type) {
596 // // .int32 => return value,
597 // // .numeric_literal => {
598 // // const val = value.decode().value.toKey(s.ip).comptime_float;
599 // // std.debug.print("buh {d}\n", .{val});
600 // // if (!math.isFinite(val) or
601 // // val < math.minInt(i32) or
602 // // val > math.maxInt(i32))
603 // // {
604 // // try s.fail(.comptime_float_to_int, .{
605 // // .val = val,
606 // // .src = s.nodeLoc(teg_ref),
607 // // });
608 // // }
609 // // return (try s.makeValue(.{ .int32 = @intFromFloat(val) })).toAir();
610 // // },
611 // else => |tag| std.debug.panic("TODO: coerceTo value_type simple_type .{s}", .{@tagName(tag)}),
612 // },
613 // else => |tag| std.debug.panic("TODO: coerceTo value_type .{s}", .{@tagName(tag)}),
614 // }
615 // },
616 // // .float,
617 // // .string,
618 // // .bool,
619 // // .noreturn,
620 // // .type,
621 // // .numeric_literal,
622 // else => |tag| std.debug.panic("TODO: coerceTo coerce_type .simple_type = .{s}", .{@tagName(tag)}),
623 // },
624 // else => |tag| std.debug.panic("TODO: coerceTo coerce_type .{s}", .{@tagName(tag)}),
625 // }
626 @panic("TODO");
627}
628
629fn coerceValue(
630 s: *Sema,
631 teg_ref: Teg.Inst.Index,
632 value: Value,
633 coerce_to: Type,
634) !Value {
635 _ = s;
636 _ = teg_ref;
637 _ = value;
638 _ = coerce_to;
639 @panic("TODO");
579fn coerceRef(s: *Sema, src: InstOp, value: Air.Inst.Ref, to: Type) !Air.Inst.Ref {
580 const from = s.typeOfRef(value);
581 if (from == to) {
582 return value;
583 }
584 const index = switch (value.decode()) {
585 .value => |v| return (try s.coerceValue(src, v, to)).toAir(),
586 .index => |index| index,
587 };
588 switch (to) {
589 .@"opaque" => {
590 //
591 },
592 .bool => {
593 //
594 },
595 .int32 => switch (from) {
596 .int32 => unreachable, // same type handled
597 .numeric_literal => unreachable, // must should comptime known
598 else => {},
599 },
600 .float => switch (from) {
601 .float => unreachable, // same type handled
602 .int32 => return index.toRef(),
603 else => {},
604 },
605 .string => {
606 //
607 },
608 .noreturn => {
609 //
610 },
611 .type => {
612 //
613 },
614 .numeric_literal => {
615 @panic("TODO: error message for not known at compile time");
616 },
617 .void => {
618 //
619 },
620 else => {},
621 }
622 return s.coersionError(src, from, to);
623}
624
625fn coerceValue(s: *Sema, src: InstOp, value: Value, to: Type) !Value {
626 const from = value.typeOf(s.ip);
627 if (from == to) {
628 return value;
629 }
630 switch (to) {
631 // .simple_type => |simple_type| switch (simple_type) {
632 // // .@"opaque",
633 // .int32 => {
634 // switch (value_type.toKey(s.ip)) {
635 // .simple_type => switch (simple_type) {
636 // // .int32 => return value,
637 // // .numeric_literal => {
638 // // const val = value.decode().value.toKey(s.ip).comptime_float;
639 // // },
640 // else => |tag| std.debug.panic("TODO: coerceTo value_type simple_type .{s}", .{@tagName(tag)}),
641 // },
642 // else => |tag| std.debug.panic("TODO: coerceTo value_type .{s}", .{@tagName(tag)}),
643 // }
644 // },
645 // // .float,
646 // // .string,
647 // // .bool,
648 // // .noreturn,
649 // // .type,
650 // // .numeric_literal,
651 // else => |tag| std.debug.panic("TODO: coerceTo coerce_type .simple_type = .{s}", .{@tagName(tag)}),
652 // },
653 // else => |tag| std.debug.panic("TODO: coerceTo coerce_type .{s}", .{@tagName(tag)}),
654 // }
655 .@"opaque" => {
656 //
657 },
658 .bool => {
659 //
660 },
661 .int32 => switch (from) {
662 .int32 => unreachable, // same type handled
663 .numeric_literal, .float => switch (value.toKey(s.ip)) {
664 .comptime_float, .float => |val| {
665 if (!math.isFinite(val) or
666 val < math.minInt(i32) or
667 val > math.maxInt(i32) or
668 (@rem(val, 1) != 0))
669 {
670 return s.fail(.comptime_float_to_int, .{
671 .val = val,
672 .src = s.lazyNode(src),
673 });
674 }
675
676 return try s.makeValue(.{
677 .int32 = @intFromFloat(val),
678 });
679 },
680 else => unreachable, // not a numeric literal
681 },
682 else => return s.coersionError(src, from, to),
683 },
684 .float => {
685 //
686 },
687 .string => {
688 //
689 },
690 .noreturn => {
691 //
692 },
693 .type => {
694 //
695 },
696 .numeric_literal => {},
697 .void => {
698 //
699 },
700 else => {},
701 }
702 return s.coersionError(src, from, to);
640703}
641704
642705fn resolveDecl(s: *Sema, decl_index: Decl.Index) !Value {
......@@ -856,23 +919,35 @@ fn lookupDecl(s: *Sema, name: NullTerminatedString) ?InternPool.DeclIndex {
856919 }
857920}
858921
859fn nodeLoc(s: *const Sema, in: Teg.Inst.Index) Report.LazyNode {
860 return s.code.instSrcLoc(in, s.decl_index);
922fn nodeLoc(s: *const Sema, in: Teg.Inst.Index, op: Report.Operand) Report.LazyNode {
923 return s.lazyNode(in.op(op));
861924}
862925
863pub fn addWarn(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) !void {
926fn addWarn(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) !void {
864927 try s.report.warn(kind, data);
865928}
866929
867pub fn addError(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) !void {
930fn addError(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) !void {
868931 try s.report.err(kind, data);
869932}
870933
871pub fn fail(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) Error!void {
934fn fail(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) Error {
872935 try s.report.err(kind, data);
873936 return Error.AnalysisFail;
874937}
875938
939fn coersionError(s: *Sema, src: InstOp, from: Type, to: Type) Error {
940 return s.fail(.coersion, .{
941 .from = from,
942 .to = to,
943 .src = s.lazyNode(src),
944 });
945}
946
947fn lazyNode(s: *const Sema, src: InstOp) Report.LazyNode {
948 return src.lazyNode( s.decl_index);
949}
950
876951const Sema = @This();
877952
878953const std = @import("std");
......@@ -895,9 +970,12 @@ const File = Comp.File;
895970const Decl = Comp.Decl;
896971const Namespace = Comp.Namespace;
897972
898const Air = @import("Air.zig");
899973const Teg = @import("Teg.zig");
974const InstOp = Teg.InstOp;
975
976const Air = @import("Air.zig");
900977const Report = @import("Report.zig");
978const Ast = @import("Ast.zig");
901979const dod = @import("dod.zig");
902980const tracer = @import("tracer");
903981
src/compiler/Teg.Dump.zig+1-1
......@@ -23,7 +23,7 @@ const State = struct {
2323 const tag = s.teg.instTag(inst);
2424
2525 try tty.setColor(writer, .bright_black);
26 const node_offset = teg.instSrcLoc(inst, @enumFromInt(0)).node_offset;
26 const node_offset = teg.instNodeOffset(inst);
2727 try writer.print("{c}{d} ", .{
2828 @as(u8, if (node_offset >= 0) '+' else '-'),
2929 @abs(node_offset),
src/compiler/Teg.zig+25-12
......@@ -180,6 +180,10 @@ pub const Inst = struct {
180180 pub fn toOptional(i: Index) OptionalIndex {
181181 return @enumFromInt(@intFromEnum(i));
182182 }
183
184 pub fn op(i: Index, operand: Report.Operand) InstOp {
185 return .{ .index = i, .op = operand };
186 }
183187 };
184188
185189 pub const OptionalIndex = enum(u32) {
......@@ -318,6 +322,19 @@ pub const Inst = struct {
318322 };
319323};
320324
325pub const InstOp = struct {
326 index: Inst.Index,
327 op: Report.Operand,
328
329 pub fn lazyNode(inst: InstOp, decl: Comp.Decl.Index) LazyNode {
330 return .{
331 .inst = inst.index,
332 .operand = inst.op,
333 .decl = decl,
334 };
335 }
336};
337
321338pub const NullTerminatedString = enum(u32) {
322339 empty = 0,
323340 _,
......@@ -382,6 +399,14 @@ pub fn instPayload(teg: *const Teg, comptime tag: Inst.Tag, index: Inst.Index) t
382399 return teg.instData(tag, index).extra_index.get(teg);
383400}
384401
402pub fn instNodeOffset(teg: *const Teg, index: Inst.Index) i32 {
403 switch (teg.instTag(index)) {
404 inline else => |tag| {
405 return teg.instData(tag, index).src_node;
406 },
407 }
408}
409
385410pub fn blockInstructions(teg: *const Teg, index: Inst.Index) []const Inst.Index {
386411 return teg.instData(.block, index).extra_index.get(teg).slice(teg);
387412}
......@@ -396,18 +421,6 @@ pub fn declData(teg: *const Teg, index: Inst.Index) Inst.Decl {
396421 return teg.instData(.declaration, index).extra_index.get(teg);
397422}
398423
399pub fn instSrcLoc(teg: *const Teg, inst: Inst.Index, decl: Comp.Decl.Index) LazyNode {
400 switch (teg.instTag(inst)) {
401 inline else => |tag| {
402 const data = teg.instData(tag, inst);
403 return .{
404 .node_offset = data.src_node,
405 .decl = decl,
406 };
407 },
408 }
409}
410
411424pub fn moduleDeclarations(teg: *const Teg, module_index: Inst.Index) []const Inst.Index {
412425 const module = teg.instData(.module, module_index);
413426 const module_data: IndexList = module.extra_index.get(teg);