P5.7 Step B1: remove the compiler_call IR op + the hook Registry
The compiler_call op + #compiler hook mechanism was fully superseded by abi(.compiler) VM-native dispatch (P5.5) — no sx code emits it anymore. Remove: the compiler_call op variant + CompilerCall struct (inst.zig); the Builder.compilerCall emitter (module.zig); the two dead producer blocks in lower/call.zig (compiler_expr-bodied free fns + methods); every consumer switch arm (emit_llvm, ops.emitCompilerCall, print, interp dispatch); the interp.hooks field + init/deinit. Strip compiler_hooks.zig down to the still- live BuildConfig / BuildHooks / AssetDir (delete HookError/HookFn/Registry/ registerDefaults + all hookXxx, and the now-unused interp/Value imports). Test refs that used compiler_call as a sample unported op now use vec_splat. 501/501 unit + 706/0 corpus.
This commit is contained in:
@@ -1,13 +1,12 @@
|
||||
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;
|
||||
const inst = @import("inst.zig");
|
||||
const FuncId = inst.FuncId;
|
||||
|
||||
// ── BuildConfig ─────────────────────────────────────────────────────────
|
||||
// Mutable build configuration accumulated by #run blocks via #compiler methods.
|
||||
// Mutable build configuration accumulated by the sx-driven build pipeline
|
||||
// (`default_pipeline` / an `on_build` callback) running on the comptime VM,
|
||||
// which reads/writes these fields via the `abi(.compiler)` primitives.
|
||||
|
||||
/// `(src_dir, dest_in_bundle)` pair recorded by
|
||||
/// `BuildOptions.add_asset_dir(src, dest)`. The sx bundler walks the
|
||||
@@ -144,440 +143,3 @@ pub const BuildHooks = struct {
|
||||
) anyerror!void,
|
||||
};
|
||||
|
||||
// ── 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.add_asset_dir", &hookAddAssetDir) catch {};
|
||||
self.hooks.put("BuildOptions.asset_dir_count", &hookAssetDirCount) catch {};
|
||||
self.hooks.put("BuildOptions.asset_dir_src_at", &hookAssetDirSrcAt) catch {};
|
||||
self.hooks.put("BuildOptions.asset_dir_dest_at", &hookAssetDirDestAt) catch {};
|
||||
self.hooks.put("BuildOptions.set_output_path", &hookSetOutputPath) catch {};
|
||||
self.hooks.put("BuildOptions.set_wasm_shell", &hookSetWasmShell) catch {};
|
||||
self.hooks.put("BuildOptions.set_post_link_callback", &hookSetPostLinkCallback) catch {};
|
||||
self.hooks.put("BuildOptions.set_post_link_module", &hookSetPostLinkModule) catch {};
|
||||
self.hooks.put("BuildOptions.binary_path", &hookGetBinaryPath) catch {};
|
||||
// Bundling setters
|
||||
self.hooks.put("BuildOptions.set_bundle_path", &hookSetBundlePath) catch {};
|
||||
self.hooks.put("BuildOptions.set_bundle_id", &hookSetBundleId) catch {};
|
||||
self.hooks.put("BuildOptions.set_codesign_identity", &hookSetCodesignIdentity) catch {};
|
||||
self.hooks.put("BuildOptions.set_provisioning_profile", &hookSetProvisioningProfile) catch {};
|
||||
// Bundling accessors
|
||||
self.hooks.put("BuildOptions.bundle_path", &hookGetBundlePath) catch {};
|
||||
self.hooks.put("BuildOptions.bundle_id", &hookGetBundleId) catch {};
|
||||
self.hooks.put("BuildOptions.codesign_identity", &hookGetCodesignIdentity) catch {};
|
||||
self.hooks.put("BuildOptions.provisioning_profile", &hookGetProvisioningProfile) catch {};
|
||||
// Target accessors — mirror TargetConfig.is{MacOS,IOS,IOSDevice,IOSSimulator,Android}()
|
||||
self.hooks.put("BuildOptions.target_triple", &hookGetTargetTriple) catch {};
|
||||
self.hooks.put("BuildOptions.is_macos", &hookIsMacOS) catch {};
|
||||
self.hooks.put("BuildOptions.is_ios", &hookIsIOS) catch {};
|
||||
self.hooks.put("BuildOptions.is_ios_device", &hookIsIOSDevice) catch {};
|
||||
self.hooks.put("BuildOptions.is_ios_simulator", &hookIsIOSSimulator) catch {};
|
||||
self.hooks.put("BuildOptions.is_android", &hookIsAndroid) catch {};
|
||||
// Android-specific setters + accessors
|
||||
self.hooks.put("BuildOptions.set_manifest_path", &hookSetManifestPath) catch {};
|
||||
self.hooks.put("BuildOptions.manifest_path", &hookGetManifestPath) catch {};
|
||||
self.hooks.put("BuildOptions.set_keystore_path", &hookSetKeystorePath) catch {};
|
||||
self.hooks.put("BuildOptions.keystore_path", &hookGetKeystorePath) catch {};
|
||||
// #jni_main class emissions, exposed by index so bundle.sx can iterate.
|
||||
self.hooks.put("BuildOptions.jni_main_count", &hookJniMainCount) catch {};
|
||||
self.hooks.put("BuildOptions.jni_main_runtime_path_at", &hookJniMainRuntimePathAt) catch {};
|
||||
self.hooks.put("BuildOptions.jni_main_java_source_at", &hookJniMainJavaSourceAt) catch {};
|
||||
// Framework list accessors (for `.app/Frameworks/` embedding)
|
||||
self.hooks.put("BuildOptions.framework_count", &hookFrameworkCount) catch {};
|
||||
self.hooks.put("BuildOptions.framework_at", &hookFrameworkAt) catch {};
|
||||
self.hooks.put("BuildOptions.framework_path_count", &hookFrameworkPathCount) catch {};
|
||||
self.hooks.put("BuildOptions.framework_path_at", &hookFrameworkPathAt) 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 hookAddAssetDir(
|
||||
interp: *const Interpreter,
|
||||
args: []const Value,
|
||||
bc: *BuildConfig,
|
||||
alloc: Allocator,
|
||||
) HookError!Value {
|
||||
// args: [self (BuildOptions value), src_path, dest_path_in_bundle]
|
||||
if (args.len < 3) return .void_val;
|
||||
const src = args[1].asString(interp) orelse return error.TypeError;
|
||||
const dest = args[2].asString(interp) orelse return error.TypeError;
|
||||
const src_dup = alloc.dupe(u8, src) catch return error.CannotEvalComptime;
|
||||
const dest_dup = alloc.dupe(u8, dest) catch return error.CannotEvalComptime;
|
||||
bc.asset_dirs.append(alloc, .{ .src = src_dup, .dest = dest_dup }) catch return error.CannotEvalComptime;
|
||||
return .void_val;
|
||||
}
|
||||
|
||||
fn hookAssetDirCount(_: *const Interpreter, _: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
return Value{ .int = @intCast(bc.asset_dirs.items.len) };
|
||||
}
|
||||
|
||||
fn hookAssetDirSrcAt(_: *const Interpreter, args: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
if (args.len < 2) return Value{ .string = "" };
|
||||
const idx = args[1].asInt() orelse return error.TypeError;
|
||||
if (idx < 0 or @as(usize, @intCast(idx)) >= bc.asset_dirs.items.len) return Value{ .string = "" };
|
||||
return Value{ .string = bc.asset_dirs.items[@intCast(idx)].src };
|
||||
}
|
||||
|
||||
fn hookAssetDirDestAt(_: *const Interpreter, args: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
if (args.len < 2) return Value{ .string = "" };
|
||||
const idx = args[1].asInt() orelse return error.TypeError;
|
||||
if (idx < 0 or @as(usize, @intCast(idx)) >= bc.asset_dirs.items.len) return Value{ .string = "" };
|
||||
return Value{ .string = bc.asset_dirs.items[@intCast(idx)].dest };
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
fn hookSetPostLinkCallback(
|
||||
_: *const Interpreter,
|
||||
args: []const Value,
|
||||
bc: *BuildConfig,
|
||||
_: Allocator,
|
||||
) HookError!Value {
|
||||
// args: [self (BuildOptions value), fn_value]. We accept a function
|
||||
// value (.func_ref) and stash the FuncId so `main.zig` can re-enter
|
||||
// the interpreter after linking.
|
||||
if (args.len < 2) return .void_val;
|
||||
switch (args[1]) {
|
||||
.func_ref => |id| bc.post_link_callback_fn = id,
|
||||
else => return error.TypeError,
|
||||
}
|
||||
return .void_val;
|
||||
}
|
||||
|
||||
fn hookSetPostLinkModule(
|
||||
interp: *const Interpreter,
|
||||
args: []const Value,
|
||||
bc: *BuildConfig,
|
||||
alloc: Allocator,
|
||||
) HookError!Value {
|
||||
if (args.len < 2) return .void_val;
|
||||
if (args[1].asString(interp)) |s| {
|
||||
bc.post_link_module = alloc.dupe(u8, s) catch return error.CannotEvalComptime;
|
||||
}
|
||||
return .void_val;
|
||||
}
|
||||
|
||||
/// Read the linked-binary path that main.zig populated right before
|
||||
/// invoking the post-link callback. Returns the fat-string aggregate
|
||||
/// the interpreter normally hands out for sx `string` values.
|
||||
fn hookGetBinaryPath(
|
||||
interp: *const Interpreter,
|
||||
_: []const Value,
|
||||
bc: *BuildConfig,
|
||||
_: Allocator,
|
||||
) HookError!Value {
|
||||
_ = interp;
|
||||
const path = bc.binary_path orelse "";
|
||||
return Value{ .string = path };
|
||||
}
|
||||
|
||||
// ── Bundling setters & accessors ─────────────────────────────────────
|
||||
// Same pattern as set_output_path: take a string arg, dupe into the
|
||||
// long-lived allocator, store on BuildConfig. The companion accessor
|
||||
// reads back the same field; empty string when unset.
|
||||
|
||||
fn hookSetBundlePath(
|
||||
interp: *const Interpreter,
|
||||
args: []const Value,
|
||||
bc: *BuildConfig,
|
||||
alloc: Allocator,
|
||||
) HookError!Value {
|
||||
if (args.len < 2) return .void_val;
|
||||
if (args[1].asString(interp)) |s| {
|
||||
bc.bundle_path = alloc.dupe(u8, s) catch return error.CannotEvalComptime;
|
||||
}
|
||||
return .void_val;
|
||||
}
|
||||
|
||||
fn hookSetBundleId(
|
||||
interp: *const Interpreter,
|
||||
args: []const Value,
|
||||
bc: *BuildConfig,
|
||||
alloc: Allocator,
|
||||
) HookError!Value {
|
||||
if (args.len < 2) return .void_val;
|
||||
if (args[1].asString(interp)) |s| {
|
||||
bc.bundle_id = alloc.dupe(u8, s) catch return error.CannotEvalComptime;
|
||||
}
|
||||
return .void_val;
|
||||
}
|
||||
|
||||
fn hookSetCodesignIdentity(
|
||||
interp: *const Interpreter,
|
||||
args: []const Value,
|
||||
bc: *BuildConfig,
|
||||
alloc: Allocator,
|
||||
) HookError!Value {
|
||||
if (args.len < 2) return .void_val;
|
||||
if (args[1].asString(interp)) |s| {
|
||||
bc.codesign_identity = alloc.dupe(u8, s) catch return error.CannotEvalComptime;
|
||||
}
|
||||
return .void_val;
|
||||
}
|
||||
|
||||
fn hookSetProvisioningProfile(
|
||||
interp: *const Interpreter,
|
||||
args: []const Value,
|
||||
bc: *BuildConfig,
|
||||
alloc: Allocator,
|
||||
) HookError!Value {
|
||||
if (args.len < 2) return .void_val;
|
||||
if (args[1].asString(interp)) |s| {
|
||||
bc.provisioning_profile = alloc.dupe(u8, s) catch return error.CannotEvalComptime;
|
||||
}
|
||||
return .void_val;
|
||||
}
|
||||
|
||||
fn hookGetBundlePath(_: *const Interpreter, _: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
return Value{ .string = bc.bundle_path orelse "" };
|
||||
}
|
||||
|
||||
fn hookGetBundleId(_: *const Interpreter, _: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
return Value{ .string = bc.bundle_id orelse "" };
|
||||
}
|
||||
|
||||
fn hookGetCodesignIdentity(_: *const Interpreter, _: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
return Value{ .string = bc.codesign_identity orelse "" };
|
||||
}
|
||||
|
||||
fn hookGetProvisioningProfile(_: *const Interpreter, _: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
return Value{ .string = bc.provisioning_profile orelse "" };
|
||||
}
|
||||
|
||||
// ── Target accessors ──────────────────────────────────────────────────
|
||||
// These look at the target_triple that main.zig populates and answer
|
||||
// the same questions TargetConfig's helpers do for Zig callers.
|
||||
|
||||
fn tripleContains(triple: ?[]const u8, needle: []const u8) bool {
|
||||
const t = triple orelse return false;
|
||||
return std.mem.indexOf(u8, t, needle) != null;
|
||||
}
|
||||
|
||||
fn isIOSTriple(triple: ?[]const u8) bool {
|
||||
return tripleContains(triple, "apple-ios");
|
||||
}
|
||||
|
||||
fn hookGetTargetTriple(_: *const Interpreter, _: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
return Value{ .string = bc.target_triple orelse "" };
|
||||
}
|
||||
|
||||
fn hookIsMacOS(_: *const Interpreter, _: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
if (isIOSTriple(bc.target_triple)) return Value{ .boolean = false };
|
||||
const t = bc.target_triple orelse "";
|
||||
const is_mac = std.mem.indexOf(u8, t, "apple-macosx") != null or
|
||||
std.mem.indexOf(u8, t, "apple-macos") != null or
|
||||
std.mem.indexOf(u8, t, "apple-darwin") != null;
|
||||
return Value{ .boolean = is_mac };
|
||||
}
|
||||
|
||||
fn hookIsIOS(_: *const Interpreter, _: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
return Value{ .boolean = isIOSTriple(bc.target_triple) };
|
||||
}
|
||||
|
||||
fn hookIsIOSDevice(_: *const Interpreter, _: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
const ios = isIOSTriple(bc.target_triple);
|
||||
const sim = tripleContains(bc.target_triple, "simulator");
|
||||
return Value{ .boolean = ios and !sim };
|
||||
}
|
||||
|
||||
fn hookIsIOSSimulator(_: *const Interpreter, _: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
const ios = isIOSTriple(bc.target_triple);
|
||||
const sim = tripleContains(bc.target_triple, "simulator");
|
||||
return Value{ .boolean = ios and sim };
|
||||
}
|
||||
|
||||
fn hookIsAndroid(_: *const Interpreter, _: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
return Value{ .boolean = tripleContains(bc.target_triple, "android") };
|
||||
}
|
||||
|
||||
// ── Android-specific bundling setters + accessors ─────────────────────
|
||||
|
||||
fn hookSetManifestPath(interp: *const Interpreter, args: []const Value, bc: *BuildConfig, alloc: Allocator) HookError!Value {
|
||||
if (args.len < 2) return .void_val;
|
||||
if (args[1].asString(interp)) |s| {
|
||||
bc.manifest_path = alloc.dupe(u8, s) catch return error.CannotEvalComptime;
|
||||
}
|
||||
return .void_val;
|
||||
}
|
||||
|
||||
fn hookGetManifestPath(_: *const Interpreter, _: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
return Value{ .string = bc.manifest_path orelse "" };
|
||||
}
|
||||
|
||||
fn hookSetKeystorePath(interp: *const Interpreter, args: []const Value, bc: *BuildConfig, alloc: Allocator) HookError!Value {
|
||||
if (args.len < 2) return .void_val;
|
||||
if (args[1].asString(interp)) |s| {
|
||||
bc.keystore_path = alloc.dupe(u8, s) catch return error.CannotEvalComptime;
|
||||
}
|
||||
return .void_val;
|
||||
}
|
||||
|
||||
fn hookGetKeystorePath(_: *const Interpreter, _: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
return Value{ .string = bc.keystore_path orelse "" };
|
||||
}
|
||||
|
||||
// ── #jni_main emission accessors ──────────────────────────────────────
|
||||
// The Android bundler walks these as `0..jni_main_count()` and reads
|
||||
// each entry's `(runtime_path, java_source)` pair so it can write a
|
||||
// `.java` file per decl, compile via javac, and produce classes.dex
|
||||
// via d8 before zipping into the APK.
|
||||
|
||||
fn hookJniMainCount(_: *const Interpreter, _: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
return Value{ .int = @intCast(bc.jni_main_runtime_paths.len) };
|
||||
}
|
||||
|
||||
fn hookJniMainRuntimePathAt(_: *const Interpreter, args: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
if (args.len < 2) return Value{ .string = "" };
|
||||
const idx = args[1].asInt() orelse return error.TypeError;
|
||||
if (idx < 0 or @as(usize, @intCast(idx)) >= bc.jni_main_runtime_paths.len) return Value{ .string = "" };
|
||||
return Value{ .string = bc.jni_main_runtime_paths[@intCast(idx)] };
|
||||
}
|
||||
|
||||
fn hookJniMainJavaSourceAt(_: *const Interpreter, args: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
if (args.len < 2) return Value{ .string = "" };
|
||||
const idx = args[1].asInt() orelse return error.TypeError;
|
||||
if (idx < 0 or @as(usize, @intCast(idx)) >= bc.jni_main_java_sources.len) return Value{ .string = "" };
|
||||
return Value{ .string = bc.jni_main_java_sources[@intCast(idx)] };
|
||||
}
|
||||
|
||||
// ── Framework list accessors ──────────────────────────────────────────
|
||||
// The Apple .app bundler in `library/modules/platform/bundle.sx` walks
|
||||
// the framework list to recursively copy each `<Name>.framework`
|
||||
// directory from the user's -F search paths into `<bundle>/Frameworks/`.
|
||||
// Slice-of-string returns aren't natively expressible as a Value, so we
|
||||
// expose count + indexed lookups instead.
|
||||
|
||||
fn intValue(n: i64) Value {
|
||||
return Value{ .int = n };
|
||||
}
|
||||
|
||||
fn hookFrameworkCount(_: *const Interpreter, _: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
return intValue(@intCast(bc.target_frameworks.len));
|
||||
}
|
||||
|
||||
fn hookFrameworkAt(_: *const Interpreter, args: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
if (args.len < 2) return Value{ .string = "" };
|
||||
const idx_i64 = args[1].asInt() orelse return error.TypeError;
|
||||
if (idx_i64 < 0 or @as(usize, @intCast(idx_i64)) >= bc.target_frameworks.len) {
|
||||
return Value{ .string = "" };
|
||||
}
|
||||
return Value{ .string = bc.target_frameworks[@intCast(idx_i64)] };
|
||||
}
|
||||
|
||||
fn hookFrameworkPathCount(_: *const Interpreter, _: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
return intValue(@intCast(bc.target_framework_paths.len));
|
||||
}
|
||||
|
||||
fn hookFrameworkPathAt(_: *const Interpreter, args: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
|
||||
if (args.len < 2) return Value{ .string = "" };
|
||||
const idx_i64 = args[1].asInt() orelse return error.TypeError;
|
||||
if (idx_i64 < 0 or @as(usize, @intCast(idx_i64)) >= bc.target_framework_paths.len) {
|
||||
return Value{ .string = "" };
|
||||
}
|
||||
return Value{ .string = bc.target_framework_paths[@intCast(idx_i64)] };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user