- ios: --target ios/ios-sim shorthands, iOS SDK auto-discovery,
#framework directive + BuildOptions.add_framework hook,
.app bundle + Info.plist + codesign (ad-hoc and real),
--codesign-identity/--provisioning-profile/--entitlements flags,
modules/std/{objc,uikit}.sx, dynamic class registration,
typed objc_msgSend cast pattern, UIApplicationMain handoff,
UIWindow scene attach. Runs on iPhone hardware.
- ir: silent .s64 defaults → loud diagnostics,
resolveReturnType infers from body, sub-byte int sizes match LLVM,
tuple type interning includes names, compile errors exit 1
- issue-NNNN convention: resolved bugs rename to focused features
- 50 regression tests passing
137 lines
4.6 KiB
Zig
137 lines
4.6 KiB
Zig
const std = @import("std");
|
|
const Allocator = std.mem.Allocator;
|
|
const interp_mod = @import("interp.zig");
|
|
const Value = interp_mod.Value;
|
|
const Interpreter = interp_mod.Interpreter;
|
|
|
|
// ── BuildConfig ─────────────────────────────────────────────────────────
|
|
// Mutable build configuration accumulated by #run blocks via #compiler methods.
|
|
|
|
pub const BuildConfig = struct {
|
|
link_flags: std.ArrayList([]const u8) = .empty,
|
|
frameworks: std.ArrayList([]const u8) = .empty,
|
|
output_path: ?[]const u8 = null,
|
|
wasm_shell_path: ?[]const u8 = null,
|
|
|
|
pub fn deinit(self: *BuildConfig, alloc: Allocator) void {
|
|
self.link_flags.deinit(alloc);
|
|
self.frameworks.deinit(alloc);
|
|
}
|
|
};
|
|
|
|
// ── Hook system ─────────────────────────────────────────────────────────
|
|
|
|
pub const HookError = error{
|
|
CannotEvalComptime,
|
|
TypeError,
|
|
};
|
|
|
|
/// Hook function signature. Receives the interpreter (for heap/string access),
|
|
/// resolved argument values, and the mutable build config.
|
|
pub const HookFn = *const fn (
|
|
interp: *const Interpreter,
|
|
args: []const Value,
|
|
bc: *BuildConfig,
|
|
alloc: Allocator,
|
|
) HookError!Value;
|
|
|
|
pub const Registry = struct {
|
|
hooks: std.StringHashMap(HookFn),
|
|
|
|
pub fn init(alloc: Allocator) Registry {
|
|
return .{ .hooks = std.StringHashMap(HookFn).init(alloc) };
|
|
}
|
|
|
|
pub fn deinit(self: *Registry) void {
|
|
self.hooks.deinit();
|
|
}
|
|
|
|
pub fn get(self: *const Registry, name: []const u8) ?HookFn {
|
|
return self.hooks.get(name);
|
|
}
|
|
|
|
/// Register all built-in compiler hooks.
|
|
pub fn registerDefaults(self: *Registry) void {
|
|
self.hooks.put("build_options", &hookBuildOptions) catch {};
|
|
self.hooks.put("BuildOptions.add_link_flag", &hookAddLinkFlag) catch {};
|
|
self.hooks.put("BuildOptions.add_framework", &hookAddFramework) catch {};
|
|
self.hooks.put("BuildOptions.set_output_path", &hookSetOutputPath) catch {};
|
|
self.hooks.put("BuildOptions.set_wasm_shell", &hookSetWasmShell) catch {};
|
|
}
|
|
};
|
|
|
|
// ── build_options() hook ────────────────────────────────────────────────
|
|
|
|
fn hookBuildOptions(
|
|
_: *const Interpreter,
|
|
_: []const Value,
|
|
_: *BuildConfig,
|
|
_: Allocator,
|
|
) HookError!Value {
|
|
// build_options() returns a sentinel value; the real work happens
|
|
// when methods like add_link_flag/set_output_path are called on it.
|
|
return .void_val;
|
|
}
|
|
|
|
// ── BuildOptions hooks ──────────────────────────────────────────────────
|
|
|
|
fn hookAddLinkFlag(
|
|
interp: *const Interpreter,
|
|
args: []const Value,
|
|
bc: *BuildConfig,
|
|
alloc: Allocator,
|
|
) HookError!Value {
|
|
// args: [self (BuildOptions value), flag_string]
|
|
if (args.len < 2) return .void_val;
|
|
const str_val = args[1];
|
|
if (str_val.asString(interp)) |s| {
|
|
bc.link_flags.append(alloc, alloc.dupe(u8, s) catch return error.CannotEvalComptime) catch return error.CannotEvalComptime;
|
|
}
|
|
return .void_val;
|
|
}
|
|
|
|
fn hookAddFramework(
|
|
interp: *const Interpreter,
|
|
args: []const Value,
|
|
bc: *BuildConfig,
|
|
alloc: Allocator,
|
|
) HookError!Value {
|
|
// args: [self (BuildOptions value), framework_name]
|
|
if (args.len < 2) return .void_val;
|
|
const str_val = args[1];
|
|
if (str_val.asString(interp)) |s| {
|
|
bc.frameworks.append(alloc, alloc.dupe(u8, s) catch return error.CannotEvalComptime) catch return error.CannotEvalComptime;
|
|
}
|
|
return .void_val;
|
|
}
|
|
|
|
fn hookSetOutputPath(
|
|
interp: *const Interpreter,
|
|
args: []const Value,
|
|
bc: *BuildConfig,
|
|
alloc: Allocator,
|
|
) HookError!Value {
|
|
// args: [self (BuildOptions value), path_string]
|
|
if (args.len < 2) return .void_val;
|
|
const str_val = args[1];
|
|
if (str_val.asString(interp)) |s| {
|
|
bc.output_path = alloc.dupe(u8, s) catch return error.CannotEvalComptime;
|
|
}
|
|
return .void_val;
|
|
}
|
|
|
|
fn hookSetWasmShell(
|
|
interp: *const Interpreter,
|
|
args: []const Value,
|
|
bc: *BuildConfig,
|
|
alloc: Allocator,
|
|
) HookError!Value {
|
|
// args: [self (BuildOptions value), path_string]
|
|
if (args.len < 2) return .void_val;
|
|
const str_val = args[1];
|
|
if (str_val.asString(interp)) |s| {
|
|
bc.wasm_shell_path = alloc.dupe(u8, s) catch return error.CannotEvalComptime;
|
|
}
|
|
return .void_val;
|
|
}
|