- objc.sx, objc_block.sx (from std/) + sdl3/opengl/raylib/stb/stb_truetype/ wasm vendor bindings (from modules/ root) -> modules/ffi/ - std/uikit.sx deleted: platform/uikit.sx already declares UIApplicationMain and imports objc; '#framework "UIKit"' cannot live in a file imported on macOS targets (unconditional link directive, UIKit is iOS-only), so the three iOS-only examples carry the 3-line glue inline. 1607/1608/1616 also un-rotted (dead ns_string -> 'xx "..."' Into conversions, callconv(.c) msgSend fn-ptrs) — all three build for ios-sim/ios again. - math/math.sx -> math/scalar.sx; one spelling '#import "modules/math"' everywhere (4 pinned IR snapshots regenerated: dir import adds Vec2/Mat4 to the type tables). - compiler.sx -> build.sx (imports, CLAUDE.md bundling table, specs.md). - testpkg/ + test_c.sx -> tests/fixtures/ (resolve CWD-relative from repo root, same as vendors/). - library-internal imports use full modules/... paths (std.sx tail, platform/bundle.sx, fixtures).
201 lines
4.9 KiB
Plaintext
201 lines
4.9 KiB
Plaintext
#import "modules/std.sx";
|
|
#import "modules/math";
|
|
#import "modules/build.sx";
|
|
#import "modules/std/test.sx";
|
|
pkg :: #import "tests/fixtures/testpkg";
|
|
|
|
Point :: struct { x, y: s32; }
|
|
|
|
add :: (a: s32, b: s32) -> s32 { a + b }
|
|
|
|
Counter :: protocol {
|
|
inc :: ();
|
|
get :: () -> s32;
|
|
}
|
|
|
|
Summable :: protocol {
|
|
sum :: () -> s32;
|
|
}
|
|
|
|
SimpleCounter :: struct { val: s32; }
|
|
|
|
impl Counter for SimpleCounter {
|
|
inc :: (self: *SimpleCounter) { self.val += 1; }
|
|
get :: (self: *SimpleCounter) -> s32 { self.val }
|
|
}
|
|
|
|
impl Summable for Point {
|
|
sum :: (self: *Point) -> s32 { self.x + self.y }
|
|
}
|
|
|
|
// Phase 2: #inline protocol for dynamic dispatch
|
|
|
|
// Phase 7: Generic struct impls
|
|
Pair :: struct ($T: Type) {
|
|
a: T;
|
|
b: T;
|
|
}
|
|
|
|
impl Summable for Pair($T) {
|
|
sum :: (self: *Pair(T)) -> s32 {
|
|
xx self.a + xx self.b
|
|
}
|
|
}
|
|
|
|
// P6.5: Struct type param constraints
|
|
|
|
// Init block test struct
|
|
Builder :: struct {
|
|
total: s32;
|
|
count: s32;
|
|
|
|
add :: (self: *Builder, val: s32) {
|
|
self.total += val;
|
|
self.count += 1;
|
|
}
|
|
}
|
|
|
|
// Global variable for address-of test
|
|
|
|
main :: () {
|
|
|
|
// --- Init Blocks (IB) ---
|
|
print("=== Init Blocks ===\n");
|
|
|
|
// IB1: basic init block with struct methods
|
|
{
|
|
b := Builder.{ total = 0, count = 0 } {
|
|
self.add(10);
|
|
self.add(20);
|
|
self.add(30);
|
|
};
|
|
print("IB1: {} {}\n", b.total, b.count);
|
|
}
|
|
|
|
// IB2: nested init blocks (self shadows correctly)
|
|
{
|
|
b1 := Builder.{ total = 0, count = 0 } {
|
|
self.add(100);
|
|
b2 := Builder.{ total = 0, count = 0 } {
|
|
self.add(42);
|
|
};
|
|
self.add(b2.total);
|
|
};
|
|
print("IB2: {} {}\n", b1.total, b1.count);
|
|
}
|
|
|
|
// IB3: empty init block
|
|
{
|
|
b := Builder.{ total = 5, count = 1 } {};
|
|
print("IB3: {} {}\n", b.total, b.count);
|
|
}
|
|
|
|
// IB4: conditional inside init block
|
|
{
|
|
add_extra := true;
|
|
b := Builder.{ total = 0, count = 0 } {
|
|
self.add(10);
|
|
if add_extra {
|
|
self.add(90);
|
|
}
|
|
};
|
|
print("IB4: {}\n", b.total);
|
|
}
|
|
|
|
// IB5: init block + auto type erasure combined
|
|
{
|
|
use_counter :: (c: Counter) -> s32 { c.inc(); c.inc(); c.get() }
|
|
result := use_counter(SimpleCounter.{ val = 0 } {
|
|
self.val = 50;
|
|
});
|
|
print("IB5: {}\n", result);
|
|
}
|
|
|
|
// ============================================================
|
|
// SECTION: Struct static method shorthand (.method(args) syntax)
|
|
// ============================================================
|
|
print("--- struct static method shorthand ---\n");
|
|
|
|
// SM1: Basic shorthand — .create(args) resolves to Dims.create(args)
|
|
{
|
|
Dims :: struct {
|
|
w: f32;
|
|
h: f32;
|
|
|
|
create :: (w: f32, h: f32) -> Dims {
|
|
Dims.{ w = w, h = h }
|
|
}
|
|
|
|
square :: (size: f32) -> Dims {
|
|
Dims.{ w = size, h = size }
|
|
}
|
|
}
|
|
use_dims :: (d: Dims) { print("SM1: {} {}\n", d.w, d.h); }
|
|
use_dims(.create(16.0, 8.0));
|
|
use_dims(.square(5.0));
|
|
}
|
|
|
|
// SM2: Shorthand in variable declaration with explicit type
|
|
{
|
|
Pair :: struct {
|
|
a: s64;
|
|
b: s64;
|
|
|
|
make :: (a: s64, b: s64) -> Pair {
|
|
Pair.{ a = a, b = b }
|
|
}
|
|
}
|
|
p : Pair = .make(10, 20);
|
|
print("SM2: {} {}\n", p.a, p.b);
|
|
}
|
|
|
|
// ============================================================
|
|
// OPTIONAL IF-ELSE COERCION
|
|
// ============================================================
|
|
{
|
|
print("--- optional if-else coercion ---\n");
|
|
OptF :: struct { width: ?f32; }
|
|
x :f32: 10.0;
|
|
|
|
// null in then branch
|
|
f1 := OptF.{ width = if true then null else x };
|
|
print("opt-if1: {}\n", f1.width ?? 99.0);
|
|
|
|
// value in then branch, null in else
|
|
f2 := OptF.{ width = if true then x else null };
|
|
print("opt-if2: {}\n", f2.width ?? 99.0);
|
|
|
|
// both branches are values
|
|
f3 := OptF.{ width = if false then 5.0 else x };
|
|
print("opt-if3: {}\n", f3.width ?? 99.0);
|
|
|
|
// standalone optional variable
|
|
val: ?f32 = if true then null else 42.0;
|
|
print("opt-if4: {}\n", val ?? 0.0);
|
|
|
|
val2: ?f32 = if false then null else 42.0;
|
|
print("opt-if5: {}\n", val2 ?? 0.0);
|
|
}
|
|
|
|
// --- usize / isize ---
|
|
{
|
|
a : usize = 42;
|
|
b : isize = 0 - 7;
|
|
print("usize: {}\n", a);
|
|
print("isize: {}\n", b);
|
|
|
|
// arithmetic
|
|
c : usize = a + 8;
|
|
print("usize+8: {}\n", c);
|
|
|
|
// coercion from s32
|
|
x : s32 = 10;
|
|
y : usize = xx x;
|
|
print("s32->usize: {}\n", y);
|
|
|
|
// coercion to s64
|
|
z : s64 = xx a;
|
|
print("usize->s64: {}\n", z);
|
|
}
|
|
}
|