feat: ink variable semantics, global ref table for astgen

This commit is contained in:
Brett Broadhurst 2026-03-09 09:21:42 -06:00
parent 197a37ebe7
commit 9658c8a308
Failed to generate hash of commit
7 changed files with 298 additions and 141 deletions

View file

@ -4,6 +4,7 @@ const Ir = @This();
string_bytes: []u8,
instructions: []Inst,
globals: []Global,
extra: []u32,
errors: []Ast.Error,
@ -23,6 +24,9 @@ pub const Inst = struct {
decl_var,
decl_ref,
block,
alloc_local,
load_local,
store_local,
add,
sub,
mul,
@ -78,6 +82,17 @@ pub const Inst = struct {
};
};
pub const Global = struct {
tag: Tag,
name: Ir.NullTerminatedString,
is_constant: bool,
pub const Tag = enum {
knot,
variable,
};
};
pub const NullTerminatedString = enum(u32) {
empty,
_,
@ -91,6 +106,7 @@ pub const IndexSlice = struct {
pub fn deinit(ir: *Ir, gpa: std.mem.Allocator) void {
gpa.free(ir.string_bytes);
gpa.free(ir.instructions);
gpa.free(ir.globals);
gpa.free(ir.extra);
gpa.free(ir.errors);
ir.* = undefined;
@ -129,12 +145,17 @@ const Render = struct {
WriteFailed,
};
fn renderUnaryInst(r: *Render, inst: Inst) Error!void {
fn renderSimple(r: *Render, inst: Inst) Error!void {
const io_w = r.writer;
return io_w.print("{s}(?)", .{@tagName(inst.tag)});
}
fn renderUnary(r: *Render, inst: Inst) Error!void {
const io_w = r.writer;
return io_w.print("{s}(%{d})", .{ @tagName(inst.tag), inst.data.un.lhs });
}
fn renderBinaryInst(r: *Render, inst: Inst) Error!void {
fn renderBinary(r: *Render, inst: Inst) Error!void {
const io_w = r.writer;
return io_w.print("{s}(%{d}, %{d})", .{ @tagName(inst.tag), inst.data.bin.lhs, inst.data.bin.rhs });
}
@ -152,7 +173,7 @@ const Render = struct {
try io_w.writeAll("}");
}
fn renderBlockInst(r: *Render, ir: Ir, inst: Inst) Error!void {
fn renderBlock(r: *Render, ir: Ir, inst: Inst) Error!void {
const io_w = r.writer;
const extra = ir.extraData(Inst.Block, inst.data.payload.payload_index);
const body_slice = ir.bodySlice(extra.end, extra.data.body_len);
@ -182,16 +203,6 @@ const Render = struct {
try io_w.writeAll(")");
}
fn renderFileInst(r: *Render, ir: Ir, inst: Inst) Error!void {
const io_w = r.writer;
const extra = ir.extraData(Inst.Block, inst.data.payload.payload_index);
const body_slice = ir.bodySlice(extra.end, extra.data.body_len);
try io_w.print("{s}(", .{@tagName(inst.tag)});
try renderBodyInner(r, ir, body_slice);
return io_w.writeAll(")");
}
fn renderDeclaration(r: *Render, ir: Ir, inst: Inst) Error!void {
const io_w = r.writer;
const extra = ir.extraData(Inst.Declaration, inst.data.payload.payload_index);
@ -207,6 +218,16 @@ const Render = struct {
return io_w.writeAll(")");
}
fn renderFile(r: *Render, ir: Ir, inst: Inst) Error!void {
const io_w = r.writer;
const extra = ir.extraData(Inst.Block, inst.data.payload.payload_index);
const body_slice = ir.bodySlice(extra.end, extra.data.body_len);
try io_w.print("{s}(", .{@tagName(inst.tag)});
try renderBodyInner(r, ir, body_slice);
return io_w.writeAll(")");
}
fn renderInst(r: *Render, ir: Ir, index: Inst.Index) Error!void {
const io_w = r.writer;
const inst_index: u32 = @intFromEnum(index);
@ -215,7 +236,7 @@ const Render = struct {
try r.prefix.writeIndent(io_w);
try io_w.print("%{d} = ", .{inst_index});
switch (inst.tag) {
.file => try r.renderFileInst(ir, inst),
.file => try r.renderFile(ir, inst),
.declaration => try r.renderDeclaration(ir, inst),
.decl_knot => try r.renderKnotDecl(ir, inst),
.decl_var => try r.renderVarDecl(ir, inst),
@ -223,13 +244,16 @@ const Render = struct {
const str_bytes = inst.data.string.get(ir);
try io_w.print("{s}(\"{s}\")", .{ @tagName(inst.tag), str_bytes });
},
.block => try r.renderBlockInst(ir, inst),
.add => try r.renderBinaryInst(inst),
.sub => try r.renderBinaryInst(inst),
.mul => try r.renderBinaryInst(inst),
.div => try r.renderBinaryInst(inst),
.mod => try r.renderBinaryInst(inst),
.neg => try r.renderUnaryInst(inst),
.alloc_local => try r.renderSimple(inst),
.load_local => try r.renderUnary(inst),
.store_local => try r.renderBinary(inst),
.block => try r.renderBlock(ir, inst),
.add => try r.renderBinary(inst),
.sub => try r.renderBinary(inst),
.mul => try r.renderBinary(inst),
.div => try r.renderBinary(inst),
.mod => try r.renderBinary(inst),
.neg => try r.renderUnary(inst),
.true_literal => {
try io_w.print("{s}", .{@tagName(inst.tag)});
},
@ -244,7 +268,7 @@ const Render = struct {
const str_bytes = inst.data.string.get(ir);
try io_w.print("{s}(\"{s}\")", .{ @tagName(inst.tag), str_bytes });
},
.content => try r.renderUnaryInst(inst),
.content => try r.renderUnary(inst),
}
try io_w.writeAll("\n");
}
@ -259,18 +283,23 @@ pub fn render(ir: Ir, gpa: std.mem.Allocator, writer: *std.Io.Writer) !void {
return writer.flush();
}
pub fn dumpStringsWithHex(cu: *const Ir) void {
const bytes = cu.string_bytes;
pub fn dumpInfo(ir: Ir, writer: *std.Io.Writer) !void {
const bytes = ir.string_bytes;
var start: usize = 0;
while (start < bytes.len) {
const end = std.mem.indexOfScalarPos(u8, bytes, start, 0) orelse break;
const s = bytes[start..end];
const str = bytes[start..end];
std.debug.print("[{d:04}] ", .{start});
for (s) |b| std.debug.print("{x:02} ", .{b});
std.debug.print("00: {s}\n", .{s});
try writer.print("[{d:04}] ", .{start});
for (str) |b| try writer.print("{x:02} ", .{b});
try writer.print("00: {s}\n", .{str});
start = end + 1;
}
for (ir.globals) |global| {
try writer.print("{any}\n", .{global});
}
return writer.flush();
}
fn ExtraData(comptime T: type) type {