ffi 2D: migrate android.sx safe-insets to declarative #jni_class blocks
The four foreign-class declarations move into a new sub-module
`library/modules/platform/android_jni.sx`, imported under a named
namespace from `android.sx`:
Jni :: #import "modules/platform/android_jni.sx";
This keeps the bare class names (`Activity`, `Window`, `View`,
`WindowInsets`) out of the top level — consumers that flat-import
`modules/platform/android.sx` no longer see `View` collide with
`modules/ui/view.sx`'s protocol of the same name (chess hit this
on the first build attempt).
Compiler-side change: `scanDecls`/`lowerDecls` now also iterate any
`namespace_decl` they encounter and register the contained
`foreign_class_decl`s under their qualified name (`Jni.Activity`).
The recursive scan continues to register the bare names too, so
cross-class refs inside method signatures (e.g. `getWindow ::
(self: *Self) -> *Window`) still resolve through the bare key.
Receiver types like `*Jni.Activity` now route through
`getStructTypeName` → "Jni.Activity" → `foreign_class_map` lookup.
`sx_query_safe_insets_jni`'s param signature changes from
`activity: *Activity` to `activity: *Jni.Activity`; the caller in
`AndroidPlatform.safe_insets` casts via `xx`.
Verified on-device — chess APK built with the new sx, installed via
`adb install -r`, launched on the Pixel. Screencap shows the board
rendering with correct status-bar clearance (time + battery icons
visible above the board, board sized below them) — safe insets are
being queried via the new declarative dispatch and produce the same
values as the pre-migration hand-rolled #jni_call chain.
129/129 examples + cross_compile 3/3 + on-device chess all green.
This commit is contained in:
@@ -367,6 +367,7 @@ pub const Lowering = struct {
|
||||
self.registerForeignClassDecl(&decl.data.foreign_class_decl);
|
||||
},
|
||||
.namespace_decl => |ns| {
|
||||
self.registerNamespacedForeignClasses(ns);
|
||||
if (self.main_file != null) {
|
||||
self.lowerDecls(ns.decls);
|
||||
}
|
||||
@@ -507,6 +508,7 @@ pub const Lowering = struct {
|
||||
self.registerForeignClassDecl(&decl.data.foreign_class_decl);
|
||||
},
|
||||
.namespace_decl => |ns| {
|
||||
self.registerNamespacedForeignClasses(ns);
|
||||
if (self.main_file != null) {
|
||||
self.scanDecls(ns.decls);
|
||||
}
|
||||
@@ -8121,6 +8123,25 @@ pub const Lowering = struct {
|
||||
self.foreign_class_map.put(fcd.name, fcd) catch {};
|
||||
}
|
||||
|
||||
/// When a namespaced import (`Ns :: #import "..."`) contains foreign-class
|
||||
/// declarations, ALSO register them under their qualified name `Ns.Class`
|
||||
/// so receiver types like `*Ns.Class` can find the fcd. The recursive
|
||||
/// scan/lower already handles bare-name registration; this only adds the
|
||||
/// qualified-name entry, so cross-class refs in method signatures
|
||||
/// (`*View` → bare lookup) still work.
|
||||
fn registerNamespacedForeignClasses(self: *Lowering, ns: ast.NamespaceDecl) void {
|
||||
for (ns.decls) |inner| {
|
||||
if (inner.data == .foreign_class_decl) {
|
||||
const fcd = &inner.data.foreign_class_decl;
|
||||
const qualified = std.fmt.allocPrint(self.alloc, "{s}.{s}", .{ ns.name, fcd.name }) catch fcd.name;
|
||||
self.foreign_class_map.put(qualified, fcd) catch {};
|
||||
} else if (inner.data == .namespace_decl) {
|
||||
// Nested namespaces — qualify with both prefixes.
|
||||
self.registerNamespacedForeignClasses(inner.data.namespace_decl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Register an impl block: register its methods as TypeName.method in fn_ast_map.
|
||||
fn registerImplBlock(self: *Lowering, ib: *const ast.ImplBlock, is_imported: bool, decl: *const Node) void {
|
||||
// Parameterised-protocol impl (e.g. `impl Into(Block) for Closure() -> void`):
|
||||
|
||||
Reference in New Issue
Block a user