build options #compiler

This commit is contained in:
agra
2026-03-03 09:35:50 +02:00
parent aa1235c621
commit 03074472e5
16 changed files with 191 additions and 64 deletions

View File

@@ -106,17 +106,8 @@ pub const InterpError = error{
Unreachable,
};
// ── BuildConfig ─────────────────────────────────────────────────────────
// Mutable build configuration accumulated by #run blocks via BuildOptions methods.
pub const BuildConfig = struct {
link_flags: std.ArrayList([]const u8) = .empty,
output_path: ?[]const u8 = null,
pub fn deinit(self: *BuildConfig, alloc: Allocator) void {
self.link_flags.deinit(alloc);
}
};
const compiler_hooks = @import("compiler_hooks.zig");
pub const BuildConfig = compiler_hooks.BuildConfig;
// ── Interpreter ─────────────────────────────────────────────────────────
@@ -136,13 +127,19 @@ pub const Interpreter = struct {
// Mutable build configuration — set by LLVMEmitter, written by #run blocks
build_config: ?*BuildConfig = null,
// Compiler hook registry for #compiler methods
hooks: compiler_hooks.Registry,
pub fn init(module: *const Module, alloc: Allocator) Interpreter {
var hooks = compiler_hooks.Registry.init(alloc);
hooks.registerDefaults();
return .{
.module = module,
.alloc = alloc,
.output = std.ArrayList(u8).empty,
.heap = std.ArrayList([]u8).empty,
.global_values = std.AutoHashMap(u32, Value).init(alloc),
.hooks = hooks,
};
}
@@ -154,6 +151,7 @@ pub const Interpreter = struct {
self.heap.deinit(self.alloc);
self.output.deinit(self.alloc);
self.global_values.deinit();
self.hooks.deinit();
}
// ── Heap operations ────────────────────────────────────────────
@@ -618,6 +616,25 @@ pub const Interpreter = struct {
return self.execBuiltin(bi, frame, instruction.ty);
},
// ── Compiler hook calls (#compiler methods) ────────
.compiler_call => |cc| {
const name = self.module.types.getString(@enumFromInt(cc.name));
if (self.hooks.get(name)) |hook| {
// Resolve args from Ref to Value
var resolved_args = std.ArrayList(Value).empty;
defer resolved_args.deinit(self.alloc);
for (cc.args) |arg| {
resolved_args.append(self.alloc, frame.getRef(arg)) catch return error.CannotEvalComptime;
}
if (self.build_config) |bc| {
const result = hook(self, resolved_args.items, bc, self.alloc) catch return error.CannotEvalComptime;
return .{ .value = result };
}
return .{ .value = .void_val };
}
return error.CannotEvalComptime;
},
// ── Struct GEP (field pointer) ─────────────────────
.struct_gep => |fa| {
const base = frame.getRef(fa.base);
@@ -1257,30 +1274,6 @@ pub const Interpreter = struct {
const f = val.asFloat() orelse return error.TypeError;
return .{ .value = .{ .float = @floor(f) } };
},
.build_options => {
// Returns a void sentinel — the "handle" to BuildConfig
return .{ .value = .void_val };
},
.build_options_add_link_flag => {
// args: [opts_handle, flag_string]
const str_val = frame.getRef(bi.args[1]);
if (str_val.asString(self)) |s| {
if (self.build_config) |bc| {
bc.link_flags.append(self.alloc, self.alloc.dupe(u8, s) catch return error.CannotEvalComptime) catch return error.CannotEvalComptime;
}
}
return .{ .value = .void_val };
},
.build_options_set_output_path => {
// args: [opts_handle, path_string]
const str_val = frame.getRef(bi.args[1]);
if (str_val.asString(self)) |s| {
if (self.build_config) |bc| {
bc.output_path = self.alloc.dupe(u8, s) catch return error.CannotEvalComptime;
}
}
return .{ .value = .void_val };
},
.cast, .type_of, .alloc, .dealloc => {
return error.CannotEvalComptime;
},