ffi 3.1 (xfail): add Cls.static_method(args) regression test
xfail half of Phase 3.1: static calls on `#objc_class` aliases lower to `objc_msg_send` against the class object (loaded once per module via `objc_getClass`). Test mirrors the Phase 3.0 pattern (`ffi-objc-dsl-01..04`): synthesize a class at runtime via `objc_allocateClassPair`, add class methods on the metaclass via `object_getClass(cls) + class_addMethod`, declare the sx-side `#objc_class` with `static answer :: ...` / `static add :: ...`, then invoke `SxProbeStatic.answer()` / `.add(7, 35)`. Skips on non-macOS. Surface choice: the call site is `.` (`Cls.method(args)`), matching JNI's existing static dispatch convention (`SurfaceView.new(ctx)`) rather than the plan's notional `::` form. The lowering disambiguates static vs instance by inspecting `method.is_static` on the foreign- class member, same as JNI. Picking `.` avoids extending the parser for a new postfix operator with no other use case. Pre-3.1 snapshot pins the current bail diagnostic at `lowerForeignStaticCall` (lower.zig:4475) — "static calls on 'objc_class' runtime not yet supported (Phase 3/4)" — fires twice because both the niladic and the keyword-arg static call hit it. exit=1. 164/164 tests; next commit implements the dispatch and flips the snapshot to working output.
This commit is contained in:
50
examples/ffi-objc-dsl-05-static.sx
Normal file
50
examples/ffi-objc-dsl-05-static.sx
Normal file
@@ -0,0 +1,50 @@
|
||||
// Phase 3 step 3.1 (PLAN-FFI.md): static call `Cls.class_method(args)`
|
||||
// on an `#objc_class` alias lowers to `objc_msg_send` against the class
|
||||
// object (loaded once per module via `objc_getClass` and cached). The
|
||||
// selector is derived by the same default mangling as Phase 3.0
|
||||
// (`stringWithUTF8String_(s)` → "stringWithUTF8String:").
|
||||
//
|
||||
// Mirrors the JNI surface (`Alias.new(...)` etc.); the lowering
|
||||
// disambiguates static vs instance by looking at `method.is_static` on
|
||||
// the foreign-class member.
|
||||
//
|
||||
// Pre-3.1: `lowerForeignStaticCall` only handles JNI runtime + the
|
||||
// `new` constructor; any other static call bails. Snapshot pins the
|
||||
// bail diagnostic.
|
||||
#import "modules/std.sx";
|
||||
#import "modules/compiler.sx";
|
||||
#import "modules/std/objc.sx";
|
||||
|
||||
SxProbeStatic :: #foreign #objc_class("SxProbeStatic") {
|
||||
static answer :: () -> s32;
|
||||
static add :: (a: s32, b: s32) -> s32;
|
||||
}
|
||||
|
||||
answer_imp :: (self: *void, _cmd: *void) -> s32 callconv(.c) {
|
||||
42;
|
||||
}
|
||||
|
||||
add_imp :: (self: *void, _cmd: *void, a: s32, b: s32) -> s32 callconv(.c) {
|
||||
a + b;
|
||||
}
|
||||
|
||||
main :: () -> s32 {
|
||||
inline if OS == .macos {
|
||||
ns_object := objc_getClass("NSObject".ptr);
|
||||
cls := objc_allocateClassPair(ns_object, "SxProbeStatic".ptr, 0);
|
||||
// class_addMethod on the metaclass — that's where class methods live.
|
||||
metacls := object_getClass(xx cls);
|
||||
class_addMethod(metacls, sel_registerName("answer".ptr), xx answer_imp, "i@:".ptr);
|
||||
class_addMethod(metacls, sel_registerName("add:b:".ptr), xx add_imp, "i@:ii".ptr);
|
||||
objc_registerClassPair(cls);
|
||||
|
||||
n := SxProbeStatic.answer();
|
||||
print("answer() = {}\n", n);
|
||||
s := SxProbeStatic.add(7, 35);
|
||||
print("add(7, 35) = {}\n", s);
|
||||
}
|
||||
inline if OS != .macos {
|
||||
print("skipped (not macos)\n");
|
||||
}
|
||||
0;
|
||||
}
|
||||
Reference in New Issue
Block a user