From 84de5f3373a98b314e681e6e7d5ac259071c50c4 Mon Sep 17 00:00:00 2001 From: dave caruso Date: Sat, 25 May 2024 17:53:36 -0700 Subject: [PATCH] introduce InstOp, making it possible to point report items at Teg.Inst --- demo.wl => demo.ix | 0 src/compiler/Air.Dump.zig | 4 +- src/compiler/Air.zig | 10 +- src/compiler/Ast.zig | 85 ++++++++++++++ src/compiler/JsNodeGen.zig | 12 +- src/compiler/Report.zig | 64 ++++++++++- src/compiler/Sema.zig | 228 +++++++++++++++++++++++++------------ src/compiler/Teg.Dump.zig | 2 +- src/compiler/Teg.zig | 37 ++++-- 9 files changed, 339 insertions(+), 103 deletions(-) rename demo.wl => demo.ix (100%) diff --git a/demo.wl b/demo.ix similarity index 100% rename from demo.wl rename to demo.ix diff --git a/src/compiler/Air.Dump.zig b/src/compiler/Air.Dump.zig index eadc3420da48cf62ce6fa1d7ec52e32a15d512a9..17c3fd4b34be4210cafcd410610599f4a196ec5d 100644 --- a/src/compiler/Air.Dump.zig +++ b/src/compiler/Air.Dump.zig @@ -157,14 +157,14 @@ pub const State = struct { fn dumpRef(s: *State, w: anytype, ref: Inst.Ref) !void { switch (ref.decode()) { - .inst => |i| try s.dumpInstRef(w, i), + .index => |i| try s.dumpInstRef(w, i), .value => |v| try s.dumpValue(w, v), } } fn dumpRefRecurse(s: *State, w: anytype, ref: Inst.Ref) !void { switch (ref.decode()) { - .inst => |i| try s.dumpInst(w, i), + .index => |i| try s.dumpInst(w, i), .value => |v| try s.dumpValue(w, v), } } diff --git a/src/compiler/Air.zig b/src/compiler/Air.zig index f9eaa173a0648da3da0c7f8ace01c0ac44fbe14f..0811efcf84df67ea59921320092586c9ca6eafcb 100644 --- a/src/compiler/Air.zig +++ b/src/compiler/Air.zig @@ -68,17 +68,17 @@ pub const Inst = struct { kind: Kind, data: u31, - pub const Kind = enum(u1) { value, inst }; + pub const Kind = enum(u1) { value, index }; pub const Decoded = union(enum) { value: Value, - inst: Index, + index: Index, }; pub fn decode(ref: Ref) Decoded { return switch (ref.kind) { .value => .{ .value = @enumFromInt(ref.data) }, - .inst => .{ .inst = @enumFromInt(ref.data) }, + .index => .{ .index = @enumFromInt(ref.data) }, }; } @@ -113,7 +113,7 @@ pub const Inst = struct { pub fn toRef(index: Index) Ref { return .{ - .kind = .inst, + .kind = .index, .data = @intCast(@intFromEnum(index)), }; } @@ -252,7 +252,7 @@ pub fn instPayload(air: *const Air, comptime tag: Inst.Tag, index: Inst.Index) t pub fn typeOf(air: *const Air, ref: Inst.Ref, ip: *InternPool) InternPool.Type { return switch (ref.decode()) { .value => |v| v.typeOf(ip), - .inst => |i| air.typeOfIndex(i, ip), + .index => |i| air.typeOfIndex(i, ip), }; } diff --git a/src/compiler/Ast.zig b/src/compiler/Ast.zig index f1eb29fcf62758e5e113d3a4e1573cf1b7d18c57..dc677f430ddfd75fec86f31d6bf0bf5dc953bd49 100644 --- a/src/compiler/Ast.zig +++ b/src/compiler/Ast.zig @@ -520,6 +520,91 @@ pub fn nodeToken(ast: Ast, node: NodeIndex) TokenIndex { return ast.nodes.items(.main_token)[node]; } +// pub fn operandNode(ast: Ast, node: NodeIndex, operand: OperandId) NodeIndex { +// if (operand == .main_node) return node; + +// switch (ast.nodeTag(node)) { +// .root => unreachable, +// .block_void => unreachable, +// .block_implicit_return => unreachable, +// .var_decl, +// => return switch (operand) { +// .type => ast.nodeData(node).var_decl.type.unwrap().?, +// .initializer => ast.nodeData(node).var_decl.init, +// else => unreachable, +// }, + +// .label, +// .group, +// .negate, +// .bit_not, +// .bool_not, +// .@"comptime", +// => return switch (operand) { +// .base => ast.nodeData(node).un.expr, +// else => unreachable, // Invalid unary operand +// }, + +// .add, +// .sub, +// .mul, +// .div, +// .rem, +// .pow, +// .@"and", +// .@"or", +// .bit_and, +// .bit_or, +// .bit_xor, +// .shl, +// .shr, +// .eq, +// .ne, +// .lt, +// .le, +// .gt, +// .ge, +// .assign, +// .add_assign, +// .sub_assign, +// .mul_assign, +// .div_assign, +// .rem_assign, +// .pow_assign, +// .and_assign, +// .or_assign, +// .bit_and_assign, +// .bit_or_assign, +// .bit_xor_assign, +// .shl_assign, +// .shr_assign, +// => { +// const bin = ast.nodeData(node).bin; +// return switch (operand) { +// .lhs => bin.lhs, +// .rhs => bin.rhs, +// else => unreachable, // Not a valid operand for binary node +// }; +// }, + +// .fn_decl, +// .param_decl, +// .id, +// .number_int, +// .number_float, +// .string, +// .multiline_string, +// .call, +// .builtin_call, +// .@"if", +// .field, +// .index, +// .@"return", +// .@"break", +// => |tag| std.debug.panic("TODO: operandNode .{s}", .{@tagName(tag)}), +// } +// } + pub fn fullFnDecl(ast: Ast, node: NodeIndex) full.FnDecl { const tok_tags = ast.tokens.items(.tag); diff --git a/src/compiler/JsNodeGen.zig b/src/compiler/JsNodeGen.zig index 1722043457ba866309ebb576477236029767a9b4..8b61b9ea17ba66eea2e1b1c74b9dadcf564adc2d 100644 --- a/src/compiler/JsNodeGen.zig +++ b/src/compiler/JsNodeGen.zig @@ -185,8 +185,8 @@ fn codeGenInst(c: *JsNodeGen, inst: Air.Inst.Index) Error!void { const target = try c.fetchInstExpression(data.memory); - if (data.operand.kind == .inst) { - const index = data.operand.decode().inst; + if (data.operand.kind == .index) { + const index = data.operand.decode().index; switch (c.air.instTag(index)) { inline .add, .sub, @@ -418,7 +418,7 @@ fn fetchExpression(c: *JsNodeGen, ref: Air.Inst.Ref) !Node.Index { return switch (ref.decode()) { .value => |v| c.valueToExpression(v), - .inst => |index| fetchInstExpression(c, index), + .index => |index| fetchInstExpression(c, index), }; } @@ -509,7 +509,7 @@ fn codeGenBranch(c: *JsNodeGen, inst: Air.Inst.Ref, temporary: ?Node.Index) !?Br } break :items c.scratch.items[scratch_top..]; }, - .inst => |i| items: { + .index => |i| items: { assert(c.air.instTag(i) == .block); c.air_node_map[@intFromEnum(i)] = .{ .block = .{ .index = @intCast(scratch_top) }, @@ -600,7 +600,7 @@ fn canLowerToExpression(c: *const JsNodeGen, inst: Air.Inst.Ref) bool { return switch (inst.decode()) { .value => true, - .inst => |index| switch (c.air.instTag(index)) { + .index => |index| switch (c.air.instTag(index)) { .js_global_ref, .call, .arg, @@ -651,7 +651,7 @@ fn lowerToExpression(c: *JsNodeGen, ref: Air.Inst.Ref) !Node.Index { assert(c.canLowerToExpression(ref)); return switch (ref.decode()) { .value => |v| try c.valueToExpression(v), - .inst => |index| { + .index => |index| { try c.codeGenInst(index); return c.fetchExpression(ref); }, diff --git a/src/compiler/Report.zig b/src/compiler/Report.zig index 5ae1d4c26bc54014154584ed880c9e52daa16fa2..be1fae9f3451aff8e0308420c889bbdd4d63873f 100644 --- a/src/compiler/Report.zig +++ b/src/compiler/Report.zig @@ -142,6 +142,16 @@ pub const Err = union(enum) { try ctx.msgNode(node, "numeric literal \"{d}\" cannot be coerced to \"int\"", .{data.val}); } }, + coersion: struct { + from: Type, + to: Type, + src: LazyNode, + + fn build(data: @This(), ctx: *MsgContext) !void { + const node = try data.src.get(ctx); + try ctx.msgNode(node, "stinky", .{}); + } + }, }; pub const Warn = union(enum) { @@ -614,7 +624,8 @@ pub const MsgContext = struct { pub const LazyNode = struct { decl: Comp.Decl.Index, - node_offset: i32, + inst: Teg.Inst.Index, + operand: Operand, pub fn get(lazy: LazyNode, ctx: *MsgContext) !NodeIndex { const decl = ctx.comp.intern_pool.declPtrConst(lazy.decl); @@ -640,7 +651,50 @@ pub const LazyNode = struct { const teg_decl = teg.instData(.declaration, decl_inst.resolve(&ctx.comp.intern_pool)); - return @intCast(teg_decl.src_node - lazy.node_offset); + const node_offset = teg.instNodeOffset(lazy.inst); + + const base_node: NodeIndex = @intCast(node_offset - teg_decl.src_node); + if (lazy.operand == .main_node) + return base_node; + + const data = ctx.ast.nodeData(base_node); + + switch (teg.instTag(lazy.inst)) { + .as => switch (ctx.ast.nodeTag(base_node)) { + .var_decl => { + switch (lazy.operand) { + .rhs => return data.var_decl.init, + else => {}, + } + }, + else => {}, + }, + else => {}, + } + + if (!std.debug.runtime_safety) unreachable; + + std.debug.panic("TODO: operand lookup: .{s} + .{s} + {}", .{ + @tagName(teg.instTag(lazy.inst)), + @tagName(ctx.ast.nodeTag(base_node)), + lazy.operand, + }); + } +}; + +pub const Operand = enum(u32) { + /// Point to the main node of an instruction + main_node = 0, + /// Base of a call, field, or operand to a unary instruction + operand = 1, + /// Left hand side of a binary instruction + lhs, + /// Right hand side of a binary instruction + rhs, + + /// An argument of a call node + pub fn argument(id: u32) Operand { + return @enumFromInt(id + 2); } }; @@ -660,7 +714,13 @@ const TokenIndex = Ast.TokenIndex; const NodeIndex = Ast.NodeIndex; const Location = Ast.Location; +const Teg = @import("Teg.zig"); + const Comp = @import("Comp.zig"); const File = Comp.File; +const InternPool = @import("InternPool.zig"); +const Value = InternPool.Value; +const Type = InternPool.Type; + const util = @import("util.zig"); diff --git a/src/compiler/Sema.zig b/src/compiler/Sema.zig index ad3e3a04565ff117375eb30230bee567e270d3d6..70922158c23cdde5b9554f5cbe29fa8d709f8128 100644 --- a/src/compiler/Sema.zig +++ b/src/compiler/Sema.zig @@ -64,7 +64,7 @@ const InstMap = struct { if (assertWithMessage(map.get(from) == null)) { std.debug.panic("%{d} is already mapped (to #{d})", .{ @intFromEnum(from), - @intFromEnum(map.get(from).?.decode().inst), + @intFromEnum(map.get(from).?.decode().index), }); } const source_i = @intFromEnum(from); @@ -330,7 +330,7 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref { .@"break" => { const brk: Teg.Inst.Break = s.code.instPayload(.@"break", in); const operand = try s.resolveRefRuntime(brk.operand); - const block_ref = s.inst_map.get(brk.block).?.decode().inst; // block ref is resolved by teg + const block_ref = s.inst_map.get(brk.block).?.decode().index; // block ref is resolved by teg return s.addInstRef(.@"break", .{ .block_ref = block_ref, .value = operand, @@ -439,7 +439,7 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref { .block => { const block = try s.analyzeBlock(in); switch (block.decode()) { - .inst => |t| if (s.tempAir().instTag(t) == .block) { + .index => |t| if (s.tempAir().instTag(t) == .block) { try s.scratch.append(s.gpa, @intFromEnum(t)); }, else => {}, @@ -455,7 +455,7 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref { .value => |v| switch (v.toKey(s.ip)) { .comptime_float => |val| { try s.report.warn(.numeric_int_var_ambiguity, .{ - .node = s.nodeLoc(in), + .node = s.nodeLoc(in, .operand), }); initial_value = (try s.makeValue(.{ .float = val })).toAir(); }, @@ -473,7 +473,7 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref { const data: Teg.Inst.Store = s.code.instPayload(.store, in); assert(s.code.instTag(data.memory) == .memory); // corrupt store instruction - const location = s.mapTeg(data.memory.toRef()).decode().inst; + const location = s.mapTeg(data.memory.toRef()).decode().index; const operand = try s.resolveRefRuntime(data.operand); // try s.validateType( @@ -488,9 +488,9 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref { }, .as => { const as: Teg.Inst.As = s.code.instPayload(.as, in); - const coerce_to = try s.resolveRefComptime(as.type); + const coerce_to = try s.resolveRefComptimeType(in.op(.lhs) ,as.type, .type); const operand = try s.resolveRefRuntime(as.operand); - return try s.coerceRef(in, operand, coerce_to.toType(s.ip).?); + return try s.coerceRef(in.op(.rhs), operand, coerce_to.toType(s.ip).?); }, else => |tag| std.debug.panic("TODO: analyze of .{s}", .{@tagName(tag)}), } @@ -516,8 +516,8 @@ fn analyzeRefToBlock(s: *Sema, in: Teg.Inst.Ref) anyerror!Air.Inst.Ref { return visited; } - if (visited.kind == .inst and - s.air_instructions.items(.tag)[@intFromEnum(visited.decode().inst)] == .block) + if (visited.kind == .index and + s.air_instructions.items(.tag)[@intFromEnum(visited.decode().index)] == .block) { return visited; } @@ -538,7 +538,7 @@ fn resolveRefRuntimeExtra(s: *Sema, ref: Teg.Inst.Ref, mark: bool) anyerror!Air. if (s.inst_map.get(index)) |air| { if (mark) { switch (air.decode()) { - .inst => |i| s.markInst(i), + .index => |i| s.markInst(i), else => {}, } } @@ -576,67 +576,130 @@ fn resolveRefComptime(s: *Sema, ref: Teg.Inst.Ref) !Value { } /// Coerce `value` runtime ref to `coerce_type`, and emit an error at `teg_ref`'s location -fn coerceRef( - s: *Sema, - teg_ref: Teg.Inst.Index, - value: Air.Inst.Ref, - coerce_to: Type, -) !Air.Inst.Ref { - _ = teg_ref; - _ = s; - _ = value; - _ = coerce_to; - // const value_type = s.typeOfRef(value); - // switch (coerce_type.toKey(s.ip)) { - // .simple_type => |simple_type| switch (simple_type) { - // // .@"opaque", - // .int32 => { - // switch (value_type.toKey(s.ip)) { - // .simple_type => switch (simple_type) { - // // .int32 => return value, - // // .numeric_literal => { - // // const val = value.decode().value.toKey(s.ip).comptime_float; - // // std.debug.print("buh {d}\n", .{val}); - // // if (!math.isFinite(val) or - // // val < math.minInt(i32) or - // // val > math.maxInt(i32)) - // // { - // // try s.fail(.comptime_float_to_int, .{ - // // .val = val, - // // .src = s.nodeLoc(teg_ref), - // // }); - // // } - // // return (try s.makeValue(.{ .int32 = @intFromFloat(val) })).toAir(); - // // }, - // else => |tag| std.debug.panic("TODO: coerceTo value_type simple_type .{s}", .{@tagName(tag)}), - // }, - // else => |tag| std.debug.panic("TODO: coerceTo value_type .{s}", .{@tagName(tag)}), - // } - // }, - // // .float, - // // .string, - // // .bool, - // // .noreturn, - // // .type, - // // .numeric_literal, - // else => |tag| std.debug.panic("TODO: coerceTo coerce_type .simple_type = .{s}", .{@tagName(tag)}), - // }, - // else => |tag| std.debug.panic("TODO: coerceTo coerce_type .{s}", .{@tagName(tag)}), - // } - @panic("TODO"); +fn coerceRef(s: *Sema, src: InstOp, value: Air.Inst.Ref, to: Type) !Air.Inst.Ref { + const from = s.typeOfRef(value); + if (from == to) { + return value; + } + const index = switch (value.decode()) { + .value => |v| return (try s.coerceValue(src, v, to)).toAir(), + .index => |index| index, + }; + switch (to) { + .@"opaque" => { + // + }, + .bool => { + // + }, + .int32 => switch (from) { + .int32 => unreachable, // same type handled + .numeric_literal => unreachable, // must should comptime known + else => {}, + }, + .float => switch (from) { + .float => unreachable, // same type handled + .int32 => return index.toRef(), + else => {}, + }, + .string => { + // + }, + .noreturn => { + // + }, + .type => { + // + }, + .numeric_literal => { + @panic("TODO: error message for not known at compile time"); + }, + .void => { + // + }, + else => {}, + } + return s.coersionError(src, from, to); } -fn coerceValue( - s: *Sema, - teg_ref: Teg.Inst.Index, - value: Value, - coerce_to: Type, -) !Value { - _ = s; - _ = teg_ref; - _ = value; - _ = coerce_to; - @panic("TODO"); +fn coerceValue(s: *Sema, src: InstOp, value: Value, to: Type) !Value { + const from = value.typeOf(s.ip); + if (from == to) { + return value; + } + switch (to) { + // .simple_type => |simple_type| switch (simple_type) { + // // .@"opaque", + // .int32 => { + // switch (value_type.toKey(s.ip)) { + // .simple_type => switch (simple_type) { + // // .int32 => return value, + // // .numeric_literal => { + // // const val = value.decode().value.toKey(s.ip).comptime_float; + // // }, + // else => |tag| std.debug.panic("TODO: coerceTo value_type simple_type .{s}", .{@tagName(tag)}), + // }, + // else => |tag| std.debug.panic("TODO: coerceTo value_type .{s}", .{@tagName(tag)}), + // } + // }, + // // .float, + // // .string, + // // .bool, + // // .noreturn, + // // .type, + // // .numeric_literal, + // else => |tag| std.debug.panic("TODO: coerceTo coerce_type .simple_type = .{s}", .{@tagName(tag)}), + // }, + // else => |tag| std.debug.panic("TODO: coerceTo coerce_type .{s}", .{@tagName(tag)}), + // } + .@"opaque" => { + // + }, + .bool => { + // + }, + .int32 => switch (from) { + .int32 => unreachable, // same type handled + .numeric_literal, .float => switch (value.toKey(s.ip)) { + .comptime_float, .float => |val| { + if (!math.isFinite(val) or + val < math.minInt(i32) or + val > math.maxInt(i32) or + (@rem(val, 1) != 0)) + { + return s.fail(.comptime_float_to_int, .{ + .val = val, + .src = s.lazyNode(src), + }); + } + + return try s.makeValue(.{ + .int32 = @intFromFloat(val), + }); + }, + else => unreachable, // not a numeric literal + }, + else => return s.coersionError(src, from, to), + }, + .float => { + // + }, + .string => { + // + }, + .noreturn => { + // + }, + .type => { + // + }, + .numeric_literal => {}, + .void => { + // + }, + else => {}, + } + return s.coersionError(src, from, to); } fn resolveDecl(s: *Sema, decl_index: Decl.Index) !Value { @@ -856,23 +919,35 @@ fn lookupDecl(s: *Sema, name: NullTerminatedString) ?InternPool.DeclIndex { } } -fn nodeLoc(s: *const Sema, in: Teg.Inst.Index) Report.LazyNode { - return s.code.instSrcLoc(in, s.decl_index); +fn nodeLoc(s: *const Sema, in: Teg.Inst.Index, op: Report.Operand) Report.LazyNode { + return s.lazyNode(in.op(op)); } -pub fn addWarn(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) !void { +fn addWarn(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) !void { try s.report.warn(kind, data); } -pub fn addError(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) !void { +fn addError(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) !void { try s.report.err(kind, data); } -pub fn fail(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) Error!void { +fn fail(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) Error { try s.report.err(kind, data); return Error.AnalysisFail; } +fn coersionError(s: *Sema, src: InstOp, from: Type, to: Type) Error { + return s.fail(.coersion, .{ + .from = from, + .to = to, + .src = s.lazyNode(src), + }); +} + +fn lazyNode(s: *const Sema, src: InstOp) Report.LazyNode { + return src.lazyNode( s.decl_index); +} + const Sema = @This(); const std = @import("std"); @@ -895,9 +970,12 @@ const File = Comp.File; const Decl = Comp.Decl; const Namespace = Comp.Namespace; -const Air = @import("Air.zig"); const Teg = @import("Teg.zig"); +const InstOp = Teg.InstOp; + +const Air = @import("Air.zig"); const Report = @import("Report.zig"); +const Ast = @import("Ast.zig"); const dod = @import("dod.zig"); const tracer = @import("tracer"); diff --git a/src/compiler/Teg.Dump.zig b/src/compiler/Teg.Dump.zig index eb4e694385fa1647ab4a5bda31435d38a6801b33..e50cd07496835e9fabe3f26ca134788c4f1918ab 100644 --- a/src/compiler/Teg.Dump.zig +++ b/src/compiler/Teg.Dump.zig @@ -23,7 +23,7 @@ const State = struct { const tag = s.teg.instTag(inst); try tty.setColor(writer, .bright_black); - const node_offset = teg.instSrcLoc(inst, @enumFromInt(0)).node_offset; + const node_offset = teg.instNodeOffset(inst); try writer.print("{c}{d} ", .{ @as(u8, if (node_offset >= 0) '+' else '-'), @abs(node_offset), diff --git a/src/compiler/Teg.zig b/src/compiler/Teg.zig index 2e509cd847b8e9a933bd35a29d7e5ac117ac3ebe..31f2b06ecf5a24eb902fb14b57a4c0024cb96a6e 100644 --- a/src/compiler/Teg.zig +++ b/src/compiler/Teg.zig @@ -180,6 +180,10 @@ pub const Inst = struct { pub fn toOptional(i: Index) OptionalIndex { return @enumFromInt(@intFromEnum(i)); } + + pub fn op(i: Index, operand: Report.Operand) InstOp { + return .{ .index = i, .op = operand }; + } }; pub const OptionalIndex = enum(u32) { @@ -318,6 +322,19 @@ pub const Inst = struct { }; }; +pub const InstOp = struct { + index: Inst.Index, + op: Report.Operand, + + pub fn lazyNode(inst: InstOp, decl: Comp.Decl.Index) LazyNode { + return .{ + .inst = inst.index, + .operand = inst.op, + .decl = decl, + }; + } +}; + pub const NullTerminatedString = enum(u32) { empty = 0, _, @@ -382,6 +399,14 @@ pub fn instPayload(teg: *const Teg, comptime tag: Inst.Tag, index: Inst.Index) t return teg.instData(tag, index).extra_index.get(teg); } +pub fn instNodeOffset(teg: *const Teg, index: Inst.Index) i32 { + switch (teg.instTag(index)) { + inline else => |tag| { + return teg.instData(tag, index).src_node; + }, + } +} + pub fn blockInstructions(teg: *const Teg, index: Inst.Index) []const Inst.Index { return teg.instData(.block, index).extra_index.get(teg).slice(teg); } @@ -396,18 +421,6 @@ pub fn declData(teg: *const Teg, index: Inst.Index) Inst.Decl { return teg.instData(.declaration, index).extra_index.get(teg); } -pub fn instSrcLoc(teg: *const Teg, inst: Inst.Index, decl: Comp.Decl.Index) LazyNode { - switch (teg.instTag(inst)) { - inline else => |tag| { - const data = teg.instData(tag, inst); - return .{ - .node_offset = data.src_node, - .decl = decl, - }; - }, - } -} - pub fn moduleDeclarations(teg: *const Teg, module_index: Inst.Index) []const Inst.Index { const module = teg.instData(.module, module_index); const module_data: IndexList = module.extra_index.get(teg); -- 2.54.0