Surface rename of the signed integer family: s1..s64 become i1..i64
(u1..u64, usize, isize unchanged). 'string' keeps the s-prefix arm in
name classification; width parsing moves to the i-prefix arm next to
isize.
Internal TypeId tags follow the surface (.s8/.s16/.s32/.s64 ->
.i8/.i16/.i32/.i64), as do mono-key mangle fragments (ptr_i64,
tu_i64_bool) and all display/diagnostic formatting (i{d}).
Migrated in the same sweep: stdlib + examples + issue repros + FFI C
companions (shared symbol names like ffi_id_i64), expected
stdout/stderr/ir snapshots, specs.md, readme.md, CLAUDE.md/AGENTS.md,
implementation_plan.md, docs/, issue writeups. Vendored stb_image and
historical flow state left untouched.
zig build test: 426/426; examples suite: 595/595.
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: i32; }
|
|
|
|
add :: (a: i32, b: i32) -> i32 { a + b }
|
|
|
|
Counter :: protocol {
|
|
inc :: ();
|
|
get :: () -> i32;
|
|
}
|
|
|
|
Summable :: protocol {
|
|
sum :: () -> i32;
|
|
}
|
|
|
|
SimpleCounter :: struct { val: i32; }
|
|
|
|
impl Counter for SimpleCounter {
|
|
inc :: (self: *SimpleCounter) { self.val += 1; }
|
|
get :: (self: *SimpleCounter) -> i32 { self.val }
|
|
}
|
|
|
|
impl Summable for Point {
|
|
sum :: (self: *Point) -> i32 { 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)) -> i32 {
|
|
xx self.a + xx self.b
|
|
}
|
|
}
|
|
|
|
// P6.5: Struct type param constraints
|
|
|
|
// Init block test struct
|
|
Builder :: struct {
|
|
total: i32;
|
|
count: i32;
|
|
|
|
add :: (self: *Builder, val: i32) {
|
|
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) -> i32 { 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: i64;
|
|
b: i64;
|
|
|
|
make :: (a: i64, b: i64) -> 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 i32
|
|
x : i32 = 10;
|
|
y : usize = xx x;
|
|
print("i32->usize: {}\n", y);
|
|
|
|
// coercion to i64
|
|
z : i64 = xx a;
|
|
print("usize->i64: {}\n", z);
|
|
}
|
|
}
|