refactor(ffi-linkage): Phase 9.2d — rename foreign_path → runtime_path (coupled .sx↔.zig↔hook)

The JNI/runtime-class path (Decision 5, Runtime* family). Coordinated across the
hook boundary so the BuildOptions accessor + its registered hook string stay in sync:
- src/: RuntimeClassDecl.foreign_path→runtime_path, splitForeignPath→splitRuntimePath,
  foreignPathToJavaName→runtimePathToJavaName, jni_main_foreign_paths→
  jni_main_runtime_paths, hookJniMainForeignPathAt→hookJniMainRuntimePathAt, and the
  hook string 'BuildOptions.jni_main_foreign_path_at'→'…runtime_path_at'.
- library/: build.sx accessor jni_main_foreign_path_at→jni_main_runtime_path_at +
  bundle.sx call sites + the  local var → runtime_path + a comment.
- specs.md: the accessor name + <foreign_path_with_dots> doc refs.
- Regenerated 37 .ir snapshots: every program importing build declares the renamed
  @BuildOptions.jni_main_runtime_path_at hook stub — symbol-name change only (verified
  the .ir diff is ONLY this rename; reverted orthogonal empty-file normalization).
Suite green (646 corpus / 444 unit, 0 failed).
This commit is contained in:
agra
2026-06-15 09:20:30 +03:00
parent a15a868391
commit 8cca3b9dde
53 changed files with 130 additions and 130 deletions

View File

@@ -81,7 +81,7 @@ pub const BuildConfig = struct {
/// and bundles the resulting `classes.dex` into the APK. Slices
/// reference compiler-owned memory that outlives the post-link
/// callback.
jni_main_foreign_paths: []const []const u8 = &.{},
jni_main_runtime_paths: []const []const u8 = &.{},
jni_main_java_sources: []const []const u8 = &.{},
pub fn deinit(self: *BuildConfig, alloc: Allocator) void {
@@ -160,7 +160,7 @@ pub const Registry = struct {
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_foreign_path_at", &hookJniMainForeignPathAt) 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 {};
@@ -470,19 +470,19 @@ fn hookGetKeystorePath(_: *const Interpreter, _: []const Value, bc: *BuildConfig
// ── #jni_main emission accessors ──────────────────────────────────────
// The Android bundler walks these as `0..jni_main_count()` and reads
// each entry's `(foreign_path, java_source)` pair so it can write a
// 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_foreign_paths.len) };
return Value{ .int = @intCast(bc.jni_main_runtime_paths.len) };
}
fn hookJniMainForeignPathAt(_: *const Interpreter, args: []const Value, bc: *BuildConfig, _: Allocator) HookError!Value {
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_foreign_paths.len) return Value{ .string = "" };
return Value{ .string = bc.jni_main_foreign_paths[@intCast(idx)] };
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 {