#import "modules/std.sx"; #import "modules/math/math.sx"; #import "modules/compiler.sx"; #import "modules/test.sx"; pkg :: #import "modules/testpkg"; // ============================================================ // Comprehensive Smoke Test — exercises every spec feature // ============================================================ // --- Top-level type declarations --- Point :: struct { x, y: s32; } Color :: enum { red; green; blue; } Shape :: enum { circle: f32; rect: struct { w, h: f32; }; none; } Overlay :: union { f: f32; i: s32; } Vec2 :: union { data: [2]f32; struct { x, y: f32; }; } Defaults :: struct { a: s32; b: s32 = 99; c: s32 = ---; } OptNode :: struct { value: s32; next: ?s32; } OptInner :: struct { val: s32; } OptOuter :: struct { inner: ?OptInner; } MyFloat :: f64; Perms :: enum flags { read; write; execute; } Status :: enum u8 { ok; err; timeout; } WindowFlags :: enum flags u32 { vsync :: 64; resizable :: 4; hidden :: 128; } // --- Top-level functions --- add :: (a: s32, b: s32) -> s32 { a + b; } mul :: (a: s32, b: s32) -> s32 { a * b; } identity :: (x: $T) -> T { x; } pair_add :: (a: $T, b: $U) -> s64 { cast(s64) a + cast(s64) b; } typed_sum :: (args: ..s32) -> s32 { result := 0; for args: (it) { result = result + it; } result; } apply :: (f: (s32, s32) -> s32, x: s32, y: s32) -> s32 { f(x, y); } void_return :: () { return; } implicit_return :: (x: s32) -> s32 { x * 2; } early_return :: (x: s32) -> s32 { if x > 10 { return 99; } x; } vec3 :: (x: f32, y: f32, z: f32) -> Vector(3, f32) { .[x, y, z]; } point_sum :: (p: Point) -> s32 { p.x + p.y; } // #run compile-time constants CT_VAL :: #run add(10, 15); CT_MUL :: #run mul(6, 7); CT_CHAIN :: #run add(CT_VAL, 5); // #run compile-time optional tests ct_opt_coalesce :: () -> s32 { x: ?s32 = 42; y: ?s32 = null; return (x ?? 0) + (y ?? 99); } ct_opt_unwrap :: () -> s32 { x: ?s32 = 77; return x!; } ct_opt_guard :: () -> s32 { x: ?s32 = 10; if x == null { return -1; } return x; } CT_OPT_COALESCE :: #run ct_opt_coalesce(); CT_OPT_UNWRAP :: #run ct_opt_unwrap(); CT_OPT_GUARD :: #run ct_opt_guard(); // #insert helpers gen_code :: () -> string { return "print(\"insert-ok\\n\");"; } gen_val :: () -> string { return "print(\"insert-gen: {}\\n\", 42);"; } // --- Foreign function binding --- libc :: #library "c"; c_abs :: (n: s32) -> s32 #foreign libc "abs"; // --- Protocol declarations (Phase 1: static dispatch only) --- 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 Adder :: protocol #inline { add :: (n: s32); value :: () -> s32; } Accumulator :: struct { total: s32; } impl Adder for Accumulator { add :: (self: *Accumulator, n: s32) { self.total += n; } value :: (self: *Accumulator) -> s32 { self.total; } } Doubler :: struct { val: s32; } impl Adder for Doubler { add :: (self: *Doubler, n: s32) { self.val = self.val + n + n; } value :: (self: *Doubler) -> s32 { self.val; } } // Phase 4: default methods Repeater :: protocol { say :: (msg: string); say_twice :: (msg: string) { self.say(msg); self.say(msg); } } Printer :: struct { count: s32; } impl Repeater for Printer { say :: (self: *Printer, msg: string) { self.count += 1; out(msg); } } // P4 edge: Chained default→default calls Chained :: protocol { base :: (msg: string) -> s32; wrap :: (msg: string) -> s32 { self.base(msg) + 1; } double_wrap :: (msg: string) -> s32 { self.wrap(msg) + self.wrap(msg); } } ChainImpl :: struct { val: s32; } impl Chained for ChainImpl { base :: (self: *ChainImpl, msg: string) -> s32 { self.val += 1; msg.len; } } // Phase 5: Self type Eq :: protocol { eq :: (other: Self) -> bool; } impl Eq for Point { eq :: (self: *Point, other: Point) -> bool { self.x == other.x and self.y == other.y; } } Cloneable :: protocol { clone :: () -> Self; } impl Cloneable for Point { clone :: (self: *Point) -> Point { Point.{ x = self.x, y = self.y }; } } impl Eq for s64 { eq :: (self: *s64, other: s64) -> bool { self.* == other; } } // Phase 6: Generic constraints are_equal :: ($T: Type/Eq, a: T, b: T) -> bool { a.eq(b); } Hashable :: protocol { hash :: () -> s64; } impl Hashable for Point { hash :: (self: *Point) -> s64 { xx self.x * 31 + xx self.y; } } eq_and_hash :: ($T: Type/Eq/Hashable, a: T, b: T) -> bool { if a.hash() != b.hash() { return false; } a.eq(b); } // P6.4: inline constraint syntax ($T/Protocol) sum_of_inline :: (a: $T/Summable, b: T) -> s32 { a.sum() + b.sum(); } // 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 SumBox :: struct ($T: Type/Summable) { val: T; } // ============================================================ // Struct constants test Phys :: struct { x, y: f32; GRAVITY :f32: 9.81; MAX_SPEED :: 100; } // 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 g_smoke_val : s32 = 42; write_to_ptr :: (p: *s32) { p.* = 99; } main :: () { // ======================================================== // 1. LITERALS // ======================================================== print("=== 1. Literals ===\n"); // Integer literals print("decimal: {}\n", 42); print("hex: {}\n", 0xFF); print("binary: {}\n", 0b1010); // Float literal pi := 3.14; print("float: {}\n", pi); // Explicit f64 big : f64 = 2.718281828; print("f64: {}\n", big); // Boolean literals print("true: {}\n", true); print("false: {}\n", false); // String with escapes print("escapes: hello\tworld\n"); // Multi-line string ml := "line1 line2"; print("multiline: {}\n", ml); // Heredoc string hd := #string END raw heredoc END; print("heredoc: {}\n", hd); // Undefined with type undef_val : s32 = ---; undef_val = 77; print("undef-then-set: {}\n", undef_val); // Enum literal (context-inferred) c : Color = .green; print("enum-lit: {}\n", c); // Null pointer np : *s32 = null; print("null-ptr: {}\n", np); // String .len slen := "hello"; print("string-len: {}\n", slen.len); // Empty string .len es := ""; print("empty-string: {}\n", es.len); // ======================================================== // 2. OPERATORS & PRECEDENCE // ======================================================== print("=== 2. Operators ===\n"); // Arithmetic print("add: {}\n", 3 + 4); print("sub: {}\n", 10 - 3); print("mul: {}\n", 6 * 7); print("div: {}\n", 20 / 4); print("mod: {}\n", 17 % 5); print("neg: {}\n", -(5)); // Comparisons print("eq: {}\n", 5 == 5); print("neq: {}\n", 5 != 3); print("lt: {}\n", 3 < 5); print("gt: {}\n", 5 > 3); print("le: {}\n", 5 <= 5); print("ge: {}\n", 5 >= 3); // Chained comparisons v := 50; print("chain: {}\n", 0 <= v <= 100); print("chain-gt: {}\n", 100 > v > 0); print("chain-mixed: {}\n", 100 > v >= 0); // Equality chains print("eq-chain: {}\n", 5 == 5 == 5); print("eq-chain-f: {}\n", 5 == 5 == 6); // Bitwise print("band: {}\n", 0xFF & 0x0F); print("bor: {}\n", 1 | 2 | 4); // Bitwise XOR print("bxor: {}\n", 0xFF ^ 0x0F); print("bxor2: {}\n", 6 ^ 3); // Bitwise NOT print("bnot: {}\n", ~0); print("bnot2: {}\n", ~1); // Shifts print("shl: {}\n", 1 << 4); print("shr: {}\n", 256 >> 4); print("shl2: {}\n", 3 << 3); print("shr2: {}\n", 255 >> 1); // Bitwise on variables bv1 := 0xFF; bv2 := 0x0F; print("band-var: {}\n", bv1 & bv2); bv3 := 1; bv4 := 6; print("bor-var: {}\n", bv3 | bv4); print("bxor-var: {}\n", bv1 ^ bv2); print("shl-var: {}\n", bv3 << 4); print("shr-var: {}\n", bv1 >> 4); print("bnot-var: {}\n", ~bv2); // Bitwise compound assignment bca := 0xFF; bca &= 0x0F; print("and-assign: {}\n", bca); bco := 0x0F; bco |= 0xF0; print("or-assign: {}\n", bco); bcx := 0xFF; bcx ^= 0x0F; print("xor-assign: {}\n", bcx); bcs := 1; bcs <<= 8; print("shl-assign: {}\n", bcs); bcr := 256; bcr >>= 4; print("shr-assign: {}\n", bcr); // Modulo on variables mv1 := 17; mv2 := 5; print("mod-var: {}\n", mv1 % mv2); // Logical (short-circuit) print("and: {}\n", true and true); print("and-false: {}\n", true and false); print("or: {}\n", false or true); print("or-false: {}\n", false or false); // Short-circuit verification print("short-and: {}\n", false and true); print("short-or: {}\n", true or false); // Compound assignment ca := 10; ca += 5; print("ca+=: {}\n", ca); ca -= 3; print("ca-=: {}\n", ca); ca *= 2; print("ca*=: {}\n", ca); ca /= 6; print("ca/=: {}\n", ca); // Precedence print("prec1: {}\n", 2 + 3 * 4); print("prec2: {}\n", (2 + 3) * 4); // xx explicit cast big2 : f64 = 200.7; small : u8 = xx big2; print("xx-cast: {}\n", small); // Implicit widening conversions wu : u8 = 200; ws : s64 = wu; print("widen-u8-s64: {}\n", ws); wi3 : s32 = 42; wf : f64 = wi3; print("widen-s32-f64: {}\n", wf); wf32 : f32 = 1.5; wf64 : f64 = wf32; print("widen-f32-f64: {}\n", wf64); wu2 : u8 = 100; ws2 : s16 = wu2; print("widen-u8-s16: {}\n", ws2); // More xx narrowing xl : s64 = 12345; xs : s32 = xx xl; print("xx-s64-s32: {}\n", xs); xd : f64 = 1.5; xf : f32 = xx xd; print("xx-f64-f32: {}\n", xf); xdf : f64 = 7.9; xdi : s32 = xx xdf; print("xx-f64-s32: {}\n", xdi); // ======================================================== // 3. TYPE SYSTEM // ======================================================== print("=== 3. Types ===\n"); // Primitive types v_s8 : s8 = 127; v_s16 : s16 = 32000; v_s32 : s32 = 100000; v_u8 : u8 = 255; v_u16 : u16 = 65000; v_u32 : u32 = 4000000; print("s8: {}\n", v_s8); print("s16: {}\n", v_s16); print("s32: {}\n", v_s32); print("u8: {}\n", v_u8); print("u16: {}\n", v_u16); print("u32: {}\n", v_u32); // Type alias mf : MyFloat = 1.5; print("alias: {}\n", mf); // --- Structs --- // Positional literal p1 : Point = .{ 1, 2 }; print("struct-pos: {}\n", p1); // Type-prefix literal p2 := Point.{ 3, 4 }; print("struct-prefix: {}\n", p2); // Named fields p3 := Point.{ y=10, x=20 }; print("struct-named: {}\n", p3); // Shorthand (variable name = field name) x : s32 = 5; y : s32 = 6; p4 := Point.{ x, y }; print("struct-shorthand: {}\n", p4); // Field defaults d1 : Defaults; print("defaults: a={} b={}\n", d1.a, d1.b); // Field access and assignment p5 := Point.{ 0, 0 }; p5.x = 42; p5.y = 99; print("field-assign: {}\n", p5); // --- Enum (payload-less) --- ec : Color = .red; print("enum: {}\n", ec); // Enum comparison ce1 : Color = .red; ce2 : Color = .red; ce3 : Color = .blue; print("enum-eq: {}\n", ce1 == ce2); print("enum-neq: {}\n", ce1 != ce3); // Backing type st : Status = .err; print("backing: {}\n", st); // --- Enum (tagged union) --- sh : Shape = .circle(3.14); print("tagged: {}\n", sh); // Payload access radius := sh.circle; print("payload: {}\n", radius); // Void variant sh = .none; print("void-variant: {}\n", sh); // Variant reassignment sh = .circle(1.0); print("reassign: {}\n", sh); sh = .rect(.{ 5, 3 }); print("reassign2: {}\n", sh); // Type-prefix construction tp := Shape.circle(2.5); print("enum-prefix: {}\n", tp); // Pattern matching sh2 : Shape = .rect(.{ 5, 3 }); if sh2 == { case .circle: print("match: circle\n"); case .rect: print("match: rect\n"); case .none: print("match: none\n"); } // Match as expression sh3 : Shape = .circle(1.0); ms := if sh3 == { case .circle: 10; case .rect: 20; case .none: 30; } print("match-expr: {}\n", ms); // Match expression with else me_val := 42; me_res := if me_val == { case 1: 10; case 2: 20; else: 99; } print("match-expr-else: {}\n", me_res); // Payload capture (block form) sh4 : Shape = .circle(9.5); if sh4 == { case .circle: (r) { print("capture: {}\n", r); } case .rect: (sz) { print("capture: {}\n", sz); } case .none: print("capture: none\n"); } // Payload capture (arrow form) sh_ca : Shape = .circle(7.5); if sh_ca == { case .circle: (r) => print("capture-arrow: {}\n", r); case .rect: (sz) => print("capture-arrow: rect\n"); case .none: print("capture-arrow: none\n"); } // else arm in match num := 42; if num == { case 1: print("else-match: one\n"); case 2: print("else-match: two\n"); else: print("else-match: other\n"); } // Integer pattern matching code := 2; if code == { case 1: print("int-match: one\n"); case 2: print("int-match: two\n"); case 3: print("int-match: three\n"); } // Integer match with else im_code := 99; if im_code == { case 1: print("int-match-else: one\n"); case 2: print("int-match-else: two\n"); else: print("int-match-else: unknown\n"); } // Bool pattern matching bm := true; if bm == { case true: print("bool-match-t: yes\n"); case false: print("bool-match-t: no\n"); } bm2 := false; if bm2 == { case true: print("bool-match-f: yes\n"); case false: print("bool-match-f: no\n"); } // Bool conditional flag := true; if flag { print("bool: true\n"); } // --- Union (untagged) --- o : Overlay = ---; o.f = 3.14; print("union-f: {}\n", o.f); // Type punning — read same bits as s32 print("union-i: {}\n", o.i); // Union member promotion uv : Vec2 = ---; uv.x = 1.0; uv.y = 2.0; print("promoted-x: {}\n", uv.x); print("promoted-data0: {}\n", uv.data[0]); // --- Arrays --- arr : [5]s32 = .[10, 20, 30, 40, 50]; print("arr[2]: {}\n", arr[2]); print("arr.len: {}\n", arr.len); // Array element assignment aa : [3]s32 = .[1, 2, 3]; aa[1] = 99; print("arr-assign: {}\n", aa); // --- Slices --- sl : []s32 = .[1, 2, 3, 4, 5]; print("sl[0]: {}\n", sl[0]); print("sl.len: {}\n", sl.len); // Slice element write sla : []s32 = .[10, 20, 30]; sla[1] = 55; print("sl-assign: {}\n", sla); // Subslicing sub := arr[1..4]; print("sub: {}\n", sub); head := arr[..3]; print("head: {}\n", head); tail := arr[2..]; print("tail: {}\n", tail); // Slice of slice sos : []s32 = .[10, 20, 30, 40, 50]; mid := sos[1..4]; inner := mid[0..2]; print("slice-of-slice: {}\n", inner); // String subslicing msg := "hello world"; print("strsub: {}\n", msg[6..11]); print("str-prefix: {}\n", msg[..5]); print("str-suffix: {}\n", msg[6..]); // --- Pointers --- // Address-of global variable write_to_ptr(@g_smoke_val); print("global-addr-of: {}\n", g_smoke_val); pv := Point.{ 10, 20 }; ptr := @pv; print("deref: {}\n", ptr.*); // Auto-deref print("auto-deref: {}\n", ptr.x); // Many-pointer mp : [*]s32 = @arr[0]; print("mp[0]: {}\n", mp[0]); print("mp[3]: {}\n", mp[3]); // Many-pointer write mpw : [5]s32 = .[10, 20, 30, 40, 50]; mpw_ptr : [*]s32 = @mpw[0]; mpw_ptr[2] = 99; print("mp-write: {}\n", mpw[2]); // Pointer-null comparison np : *s32 = null; print("ptr==null: {}\n", np == null); print("ptr!=null: {}\n", np != null); np2 := @pv.x; print("ptr2==null: {}\n", np2 == null); print("ptr2!=null: {}\n", np2 != null); // Pointer to nested struct field Inner3 :: struct { a: f32; b: f32; c: f32; } Outer3 :: struct { key: s32; inner: Inner3; } out3 := Outer3.{ key = 42, inner = Inner3.{ a = 1.0, b = 2.0, c = 3.0 } }; ip3 := @out3.inner; print("ptr-nested-field: {} {} {}\n", ip3.a, ip3.b, ip3.c); // Store to many-pointer field must not corrupt adjacent memory MpHolder :: struct { items: [*]s64; sentinel: s64; } mph := MpHolder.{ items = xx 0, sentinel = 42 }; mph.items = xx 0; print("mp-store-sentinel: {}\n", mph.sentinel); // --- Vectors --- vc := vec3(1, 3, 2); print("vec-construct: {}\n", vc); va := vec3(1, 2, 3); vb := vec3(4, 5, 6); print("vec-add: {}\n", va + vb); print("vec-sub: {}\n", vec3(5, 5, 5) - vec3(1, 2, 3)); print("vec-mul: {}\n", vec3(2, 3, 4) * vec3(1, 2, 3)); print("vec-div: {}\n", vec3(10, 9, 8) / vec3(2, 3, 4)); print("vec-scalar: {}\n", vec3(1, 3, 2) * 2.0); print("vec-neg: {}\n", -vec3(1, 3, 2)); ve := vec3(10, 20, 30); print("vec-x: {}\n", ve.x); print("vec-y: {}\n", ve.y); print("vec-z: {}\n", ve.z); print("vec-idx: {}\n", ve[1]); // ======================================================== // 4. CONTROL FLOW // ======================================================== print("=== 4. Control Flow ===\n"); // If-then-else (inline, as expression) ite := if true then 1 else 2; print("ite: {}\n", ite); // If-then-else both branches ie_a := if true then 10 else 20; ie_b := if false then 10 else 20; print("ite-both: {} {}\n", ie_a, ie_b); // If block if 1 < 2 { print("if-block: yes\n"); } // If without else (statement) if false { print("should-not-print\n"); } print("if-no-else: after\n"); // Nested if nx := 10; if nx > 5 { if nx > 8 { print("nested-if: deep\n"); } } // If-else-if chain eiv := 2; if eiv == 1 { print("if-else-if: first\n"); } else if eiv == 2 { print("if-else-if: second\n"); } else { print("if-else-if: other\n"); } // If block as expression ibe := 10 + if true { 5; } else { 0; }; print("if-block-expr: {}\n", ibe); // While basic wi := 0; while wi < 5 { wi += 1; } print("while: {}\n", wi); // While with false condition (never executes) while false { print("should-not-print\n"); } print("while-false: skipped\n"); // While with break wb := 0; while wb < 100 { if wb == 7 { break; } wb += 1; } print("while-break: {}\n", wb); // While with continue wsum := 0; wc := 0; while wc < 10 { wc += 1; if wc % 2 == 0 { continue; } wsum += wc; } print("while-continue: {}\n", wsum); // While sum 1..10 wsum2 := 0; wi2 := 1; while wi2 <= 10 { wsum2 += wi2; wi2 += 1; } print("while-sum: {}\n", wsum2); // Nested while nw_outer := 0; nw_count := 0; while nw_outer < 3 { nw_inner := 0; while nw_inner < 3 { nw_count += 1; nw_inner += 1; } nw_outer += 1; } print("nested-while: {}\n", nw_count); // Nested while with break in inner nb_outer := 0; nb_icount := 0; while nb_outer < 5 { nb_i := 0; while nb_i < 5 { if nb_i == 1 { break; } nb_i += 1; } nb_icount += nb_i; nb_outer += 1; if nb_outer == 2 { break; } } print("nested-break: {} {}\n", nb_outer, nb_icount); // For loop basic farr : [4]s32 = .[10, 20, 30, 40]; out("for:"); for farr: (it) { out(" "); out(int_to_string(it)); } out("\n"); // For with print out("for-print:"); for farr: (it) { print(" {}", it); } out("\n"); // For with index out("for-idx:"); for farr: (_, ix) { out(" "); out(int_to_string(ix)); } out("\n"); // For with print two args out("for-2arg:"); for farr: (it, ix) { print(" {}@{}", it, ix); } out("\n"); // For with break out("for-break:"); for farr: (it) { if it == 30 { break; } print(" {}", it); } out("\n"); // For with continue out("for-continue:"); for farr: (it) { if it == 20 { continue; } print(" {}", it); } out("\n"); // For on slice fsl : []s32 = .[10, 20, 30]; out("for-slice:"); for fsl: (it) { print(" {}", it); } out("\n"); // For on slice with index out("for-slice-idx:"); for fsl: (it, ix) { print(" {}:{}", ix, it); } out("\n"); // Nested for nf_a : [2]s32 = .[0, 1]; nf_b : [2]s32 = .[0, 1]; out("for-nested:"); for nf_a: (oa) { for nf_b: (ob) { print(" ({},{})", oa, ob); } } out("\n"); // For with break preserving index fbi : [5]s32 = .[10, 20, 30, 40, 50]; fbi_idx := 0; for fbi: (it, ix) { if it == 30 { fbi_idx = ix; break; } } print("for-break-idx: {}\n", fbi_idx); // Multiple print placeholders print("multi: {} {} {}\n", 1, 2, 3); // ======================================================== // 5. FUNCTIONS & DECLARATIONS // ======================================================== print("=== 5. Functions ===\n"); // Constant binding FORTY_TWO :: 42; print("const: {}\n", FORTY_TWO); // Typed constant TYPED_PI : f64 : 3.14; print("typed-const: {}\n", TYPED_PI); // Variable with default init di : s32; print("default-init: {}\n", di); // Implicit return print("implicit-ret: {}\n", implicit_return(21)); // Explicit return print("early-ret: {}\n", early_return(5)); print("early-ret2: {}\n", early_return(20)); // Void return void_return(); print("void-return: ok\n"); // Generic — single param print("generic-s32: {}\n", identity(42)); print("generic-f32: {}\n", identity(1.5)); print("generic-bool: {}\n", identity(true)); // Generic — multiple params print("generic-multi: {}\n", pair_add(10, 20)); // Lambda double :: (x: s32) => x * 2; print("lambda: {}\n", double(7)); // Lambda with return type halve :: (x: f32) -> f32 => x / 2.0; print("lambda-ret: {}\n", halve(10.0)); // Local function (non-lambda) local_add :: (a: s32, b: s32) -> s32 { a + b; } print("local-fn: {}\n", local_add(3, 4)); // Nested function calls print("fn-nested: {}\n", add(mul(2, 3), mul(4, 5))); // Variadic (typed) print("varargs: {}\n", typed_sum(1, 2, 3, 4, 5)); // Spread spread_arr : [3]s32 = .[10, 20, 30]; print("spread: {}\n", typed_sum(..spread_arr)); // Function pointers fp : (s32, s32) -> s32 = add; print("fp: {}\n", fp(3, 4)); fp = mul; print("fp-reassign: {}\n", fp(3, 4)); print("fp-apply: {}\n", apply(add, 10, 20)); // ======================================================== // 6. SCOPING & DEFER // ======================================================== print("=== 6. Scoping ===\n"); // Scope block with shadowing sv := 100; { sv := 200; print("inner: {}\n", sv); } print("outer: {}\n", sv); // Shadow with different type st_v := 42; print("shadow-type: {}\n", st_v); { st_v := 3.14; print("shadow-type: {}\n", st_v); } // Nested scopes (3 levels) nv := 1; { nv := 2; { nv := 3; print("nest3: {}\n", nv); } print("nest2: {}\n", nv); } print("nest1: {}\n", nv); // Scope isolation { iso := 100; print("scope-isolate: {}\n", iso); } // Reuse name after scope exit sr := 1; print("scope-reuse: {}\n", sr); { sr := 2; print("scope-reuse: {}\n", sr); } print("scope-reuse: {}\n", sr); // Multiple defers (LIFO order) { defer print("defer-c\n"); defer print("defer-b\n"); defer print("defer-a\n"); } // Four defers { defer print("d1\n"); defer print("d2\n"); defer print("d3\n"); defer print("d4\n"); } // Defer in nested scopes { defer print("outer-defer\n"); { defer print("inner-defer\n"); } } // Defer in if block if true { defer print("defer-in-if: deferred\n"); print("defer-in-if: body\n"); } // ======================================================== // 7. BUILT-IN FUNCTIONS // ======================================================== print("=== 7. Builtins ===\n"); // out out("out-ok\n"); // sqrt print("sqrt: {}\n", sqrt(9.0)); print("sqrt-f64: {}\n", sqrt(16.0)); // size_of print("sizeof-s32: {}\n", size_of(s32)); print("sizeof-f64: {}\n", size_of(f64)); print("sizeof-struct: {}\n", size_of(Point)); // type_of + category matching tv := 42; ttype := type_of(tv); if ttype == { case int: print("typeof: int\n"); case float: print("typeof: float\n"); else: print("typeof: other\n"); } // type_of — float tf := 3.14; if type_of(tf) == { case float: print("typeof-float: float\n"); else: print("typeof-float: other\n"); } // type_of — string ts := "hello"; if type_of(ts) == { case string: print("typeof-string: string\n"); else: print("typeof-string: other\n"); } // type_of — bool tb := true; if type_of(tb) == { case bool: print("typeof-bool: bool\n"); else: print("typeof-bool: other\n"); } // type_of — struct tst := Point.{ 1, 2 }; if type_of(tst) == { case struct: print("typeof-struct: struct\n"); else: print("typeof-struct: other\n"); } // type_of — enum ten : Color = .red; if type_of(ten) == { case enum: print("typeof-enum: enum\n"); else: print("typeof-enum: other\n"); } // type_name print("typename: {}\n", type_name(Point)); // field_count on struct print("fieldcount: {}\n", field_count(Point)); // field_count on enum print("fieldcount-enum: {}\n", field_count(Color)); // field_name on struct print("fieldname0: {}\n", field_name(Point, 0)); print("fieldname1: {}\n", field_name(Point, 1)); // field_name on enum print("fieldname-enum0: {}\n", field_name(Color, 0)); print("fieldname-enum2: {}\n", field_name(Color, 2)); // field_value (use any_to_string to avoid sext-on-Any bug) fv_pt := Point.{ 11, 22 }; out("fieldval0: "); out(any_to_string(field_value(fv_pt, 0))); out("\n"); out("fieldval1: "); out(any_to_string(field_value(fv_pt, 1))); out("\n"); // field_index on plain enum fi_c : Color = .green; print("fieldidx: {}\n", field_index(Color, fi_c)); // field_index on tagged enum fi_sh : Shape = .circle(1.0); print("fieldidx-tagged: {}\n", field_index(Shape, fi_sh)); fi_sh2 : Shape = .none; print("fieldidx-tagged2: {}\n", field_index(Shape, fi_sh2)); // cast cval : f64 = 3.7; print("cast: {}\n", cast(s32) cval); cv2 : s32 = 42; print("cast-int-f64: {}\n", cast(f64) cv2); // ======================================================== // 8. COMPILE-TIME // ======================================================== print("=== 8. Comptime ===\n"); // #run constant print("run-const: {}\n", CT_VAL); // #run with expression print("run-expr: {}\n", CT_MUL); // #run chained dependency print("run-chain: {}\n", CT_CHAIN); // #run comptime optionals print("ct-opt-coalesce: {}\n", CT_OPT_COALESCE); // ct-opt-coalesce: 141 print("ct-opt-unwrap: {}\n", CT_OPT_UNWRAP); // ct-opt-unwrap: 77 print("ct-opt-guard: {}\n", CT_OPT_GUARD); // ct-opt-guard: 10 // #insert with function #insert gen_code(); // #insert additional #insert gen_val(); // ======================================================== // 9. FLAGS // ======================================================== print("=== 9. Flags ===\n"); // Combine flags perm : Perms = .read | .write; print("flags: {}\n", perm); // Test flag if perm & .read { print("has-read: yes\n"); } if perm & .execute { print("has-exec: yes\n"); } // Test flag negative pt : Perms = .write; if pt & .read { print("flags-neg: has-read\n"); } else { print("flags-neg: no-read\n"); } // Single flag ps : Perms = .execute; print("flags-single: {}\n", ps); // All flags pall : Perms = .read | .write | .execute; print("flags-all: {}\n", pall); // Cast to int print("flags-raw: {}\n", cast(s64) perm); // Flags with explicit values wf : WindowFlags = .vsync | .resizable; print("flags-explicit: {}\n", wf); print("flags-explicit-raw: {}\n", cast(s64) wf); // --- Multi-target assignment (swap) --- print("--- swap ---\n"); // Variable swap { sa := 10; sb := 20; sa, sb = sb, sa; print("var swap: {} {}\n", sa, sb); } // Array element swap { sarr : [3]s64 = .[1, 2, 3]; sarr[0], sarr[2] = sarr[2], sarr[0]; print("arr swap: {} {}\n", sarr[0], sarr[2]); } // 3-way rotation { ra := 1; rb := 2; rc := 3; ra, rb, rc = rc, ra, rb; print("3-way: {} {} {}\n", ra, rb, rc); } // --- Tuple destructuring --- print("--- destructure ---\n"); // Basic tuple destructuring { da, db := (10, 20); print("basic: {} {}\n", da, db); } // Destructure from function return { dswap :: (a: s64, b: s64) -> (s64, s64) { (b, a); } dx, dy := dswap(1, 2); print("fn: {} {}\n", dx, dy); } // Discard with _ { _, dsecond := (100, 200); print("discard: {}\n", dsecond); } // Three elements { da3, db3, dc3 := (1, 2, 3); print("triple: {} {} {}\n", da3, db3, dc3); } // ======================================================== // 15. FOREIGN FUNCTION BINDING // ======================================================== print("=== 15. Foreign ===\n"); // Symbol rename: c_abs maps to C's abs() print("foreign-rename: {}\n", c_abs(xx -42)); // ======================================================== // 16. COMPOUND ASSIGNMENT TYPE CONVERSION // ======================================================== print("=== 16. Compound Assign ===\n"); { ca_a : f64 = 10.0; ca_b : f32 = 3.0; ca_a += ca_b; print("f64+=f32: {}\n", ca_a); ca_c : s64 = 100; ca_d : s32 = 7; ca_c -= ca_d; print("s64-=s32: {}\n", ca_c); } // ======================================================== // 17. SLICE/ARRAY .ptr ACCESS // ======================================================== print("=== 17. Slice Ptr ===\n"); { sarr : [5]s32 = .[10, 20, 30, 40, 50]; ssl := sarr[1..4]; sp := ssl.ptr; print("sl-ptr[0]: {}\n", sp[0]); print("sl-ptr[1]: {}\n", sp[1]); } // ======================================================== // 18. ARRAYS OF USER-DEFINED TYPES // ======================================================== print("=== 18. Array of Structs ===\n"); { spts : [2]Point = .[Point.{1, 2}, Point.{3, 4}]; spt2 := spts[1]; print("arr-struct-x: {}\n", spt2.x); for spts: (it) { print("for-struct: {}\n", it); } } // ======================================================== // 19. LOCAL FUNCTION RETURNING STRUCT/ENUM // ======================================================== print("=== 19. Local Fn Return ===\n"); { local_pt :: () -> Point { Point.{42, 99}; } lp := local_pt(); print("local-struct: {} {}\n", lp.x, lp.y); local_sh :: () -> Shape { .circle(2.5); } ls := local_sh(); print("local-enum: {}\n", ls); } // ======================================================== // 20. PIPE UFCS RETURN TYPE INFERENCE // ======================================================== print("=== 20. UFCS Return Type ===\n"); { p := Point.{3, 4}; print("direct: {}\n", point_sum(p)); print("ufcs: {}\n", p |> point_sum()); } // ======================================================== // 21. TYPE-NAMED VARIABLES (s2, u8, etc.) // ======================================================== print("=== 21. Type-Named Vars ===\n"); { s2 := 42; print("s2: {}\n", s2); s2 = s2 + 1; print("s2+1: {}\n", s2); } // ======================================================== // 22. IF-EXPRESSION RETURNING STRUCT // ======================================================== print("=== 22. If-Struct ===\n"); { flag := true; p := if flag { Point.{10, 20}; } else { Point.{30, 40}; }; print("if-struct: {} {}\n", p.x, p.y); q := if !flag { Point.{10, 20}; } else { Point.{30, 40}; }; print("else-struct: {} {}\n", q.x, q.y); } // ======================================================== // 23. NESTED ARRAYS (2D) // ======================================================== print("=== 23. Nested Arrays ===\n"); { matrix : [2][3]s32 = .[ .[1, 2, 3], .[4, 5, 6] ]; print("m[0][0]: {}\n", matrix[0][0]); print("m[0][2]: {}\n", matrix[0][2]); print("m[1][0]: {}\n", matrix[1][0]); print("m[1][2]: {}\n", matrix[1][2]); } // ======================================================== // 24. STRING COMPARISON // ======================================================== print("=== 24. String Comparison ===\n"); { a := "hello"; b := "hello"; c := "world"; print("str-eq: {}\n", a == b); print("str-neq: {}\n", a != c); print("str-diff: {}\n", a == c); empty := ""; print("empty-eq: {}\n", empty == ""); } // ======================================================== // 25. ARRAY LOOP MUTATION // ======================================================== print("=== 25. Array Loop Mutation ===\n"); { arr : [4]s32 = .[0, 0, 0, 0]; i := 0; while i < 4 { arr[i] = xx (i + 1); i += 1; } print("loop-fill: {} {} {} {}\n", arr[0], arr[1], arr[2], arr[3]); arr[2] += 10; print("compound: {}\n", arr[2]); } // === 26. #using struct composition === print("=== 26. #using ===\n"); { UBase :: struct { x: s32; y: s32; } UExt :: struct { #using UBase; z: s32; } e := UExt.{ x = 1, y = 2, z = 3 }; print("using-x: {}\n", e.x); print("using-y: {}\n", e.y); print("using-z: {}\n", e.z); // #using in middle position UHeader :: struct { version: s32; } UPacket :: struct { id: s32; #using UHeader; payload: s32; } p := UPacket.{ id = 10, version = 42, payload = 99 }; print("pkt-id: {}\n", p.id); print("pkt-ver: {}\n", p.version); print("pkt-pay: {}\n", p.payload); // Multiple #using UPos :: struct { px: s32; py: s32; } UCol :: struct { r: s32; g: s32; } USprite :: struct { #using UPos; #using UCol; scale: s32; } s := USprite.{ px = 10, py = 20, r = 255, g = 128, scale = 1 }; print("sprite-px: {}\n", s.px); print("sprite-r: {}\n", s.r); print("sprite-scale: {}\n", s.scale); } // --- Comptime format --- { ct_body :: "hello"; ct_msg :: format("say: {} (len={})", ct_body, ct_body.len); print("{}\n", ct_msg); ct_num :: 42; ct_num_msg :: format("n={}", ct_num); print("{}\n", ct_num_msg); } // --- Tuples --- { print("=== Tuples ===\n"); pair := (40, 2); print("{}\n", pair.0); print("{}\n", pair.1); named := (x: 10, y: 20); print("{}\n", named.x); print("{}\n", named.0); single := (42,); print("{}\n", single.0); zeroed : (s32, s32) = ---; print("{}\n", zeroed.0); print("{}\n", zeroed.1); } // --- UFCS Aliases & Pipe --- { print("=== UFCS Aliases ===\n"); num_sum :: (a: s64, b: s64) -> s64 { a + b; } sum :: ufcs num_sum; print("{}\n", num_sum(40, 2)); // 42 — direct call print("{}\n", sum(40, 2)); // 42 — alias direct call print("{}\n", 40 |> sum(2)); // 42 — pipe UFCS via alias print("{}\n", num_sum(40, 2)); // 42 — direct (was tuple full-splat) print("{}\n", 40 |> sum(2)); // 42 — pipe (was tuple partial-splat) compute :: (a: s64, b: s64, c: s64, d: s64) -> s64 { a + b * c - d; } calc :: ufcs compute; print("{}\n", compute(1, 2, 3, 4)); // 1+2*3-4 = 3 (was tuple full-splat) print("{}\n", compute(1, 2, 3, 4)); // same = 3 (was tuple partial-splat) print("{}\n", 1 |> calc(2, 3, 4)); // same = 3 — pipe UFCS // Tuple return type swap :: (a: s64, b: s64) -> (s64, s64) { (b, a); } s := swap(1, 2); a := s.0; b := s.1; print("{}\n", a); // 2 print("{}\n", b); // 1 wrap :: (x: s64) -> (s64) { (x,); } t := wrap(99); print("{}\n", t.0); // 99 } // --- Tuple Operators --- { print("=== Tuple Operators ===\n"); // Equality print("{}\n", (1, 2) == (1, 2)); // true print("{}\n", (1, 2) == (1, 3)); // false print("{}\n", (1, 2) != (1, 3)); // true print("{}\n", (1, 2) != (1, 2)); // false // Concatenation c := (1, 2) + (3, 4); print("{}\n", c.0); // 1 print("{}\n", c.1); // 2 print("{}\n", c.2); // 3 print("{}\n", c.3); // 4 // Repetition r := (1, 2) * 3; print("{}\n", r.0); // 1 print("{}\n", r.1); // 2 print("{}\n", r.2); // 1 print("{}\n", r.3); // 2 print("{}\n", r.4); // 1 print("{}\n", r.5); // 2 // Lexicographic comparison print("{}\n", (1, 2) < (1, 3)); // true print("{}\n", (1, 3) < (1, 2)); // false print("{}\n", (1, 2) < (1, 2)); // false print("{}\n", (1, 2) <= (1, 2)); // true print("{}\n", (2, 0) > (1, 9)); // true print("{}\n", (1, 2) >= (1, 2)); // true // Membership print("{}\n", 2 in (1, 2, 3)); // true print("{}\n", 5 in (1, 2, 3)); // false } // --- Directory imports --- { print("--- directory imports ---\n"); print("{}\n", pkg.add(3, 4)); // 7 print("{}\n", pkg.mul(5, 6)); // 30 print("{}\n", pkg.hello()); // hello from testpkg print("{}\n", pkg.cwd_greet()); // cwd-import-ok } // --- Pipe operator --- { print("--- pipe operator ---\n"); // Basic: a |> f(b) → f(a, b) print("{}\n", 3 |> pkg.add(4)); // 7 print("{}\n", 5 |> pkg.mul(6)); // 30 // Chaining: a |> f(b) |> g(c) → g(f(a, b), c) print("{}\n", 3 |> pkg.add(4) |> pkg.mul(2)); // 14 // With non-namespaced functions print("{}\n", "hello" |> concat(" world")); // hello world // Chained string ops print("{}\n", "piped" |> concat(" ok") |> concat("!")); // piped ok! } // ── alloc_slice ────────────────────────────────────────── { items := alloc_slice(s64, 5); items[0] = 10; items[1] = 20; items[2] = 30; items[3] = 40; items[4] = 50; print("alloc len: {}\n", items.len); // alloc len: 5 print("alloc[0]: {}\n", items[0]); // alloc[0]: 10 print("alloc[4]: {}\n", items[4]); // alloc[4]: 50 // alloc_slice with u8 bytes := alloc_slice(u8, 3); bytes[0] = 65; bytes[1] = 66; bytes[2] = 67; print("bytes len: {}\n", bytes.len); // bytes len: 3 } // ======================================================== // ALLOCATORS // ======================================================== print("--- allocators ---\n"); // ── GPA ───────────────────────────────────────────────── { gpa_state : GPA = .{ alloc_count = 0 }; gpa := gpa_state.create(); p1 := gpa.alloc(64); p2 := gpa.alloc(128); print("gpa allocs: {}\n", gpa_state.alloc_count); // gpa allocs: 2 gpa.dealloc(p1); gpa.dealloc(p2); print("gpa final: {}\n", gpa_state.alloc_count); // gpa final: 0 } // ── Arena backed by GPA (multi-chunk) ─────────────────── { gpa_state3 : GPA = .{ alloc_count = 0 }; gpa3 := gpa_state3.create(); arena_state : Arena = ---; arena := arena_state.create(gpa3, 32); // First chunk fits 80 usable bytes a1 := arena.alloc(40); a2 := arena.alloc(40); print("arena chunks: {}\n", gpa_state3.alloc_count); // arena chunks: 1 // Overflow → new chunk a3 := arena.alloc(16); print("arena overflow: {}\n", gpa_state3.alloc_count); // arena overflow: 2 // Verify memory works across chunks p1 : [*]u8 = xx a1; p3 : [*]u8 = xx a3; p1[0] = 42; p3[0] = 99; print("arena a1: {}\n", p1[0]); // arena a1: 42 print("arena a3: {}\n", p3[0]); // arena a3: 99 // Reset retains newest chunk arena_state.reset(); print("arena reset idx: {}\n", arena_state.end_index); // arena reset idx: 0 print("arena reset gpa: {}\n", gpa_state3.alloc_count);// arena reset gpa: 1 // Deinit frees all arena_state.deinit(); print("arena deinit: {}\n", gpa_state3.alloc_count); // arena deinit: 0 } // ── BufAlloc from stack array ─────────────────────────── { stack_buf : [128]u8 = ---; buf_state : BufAlloc = ---; bufalloc := buf_state.create(@stack_buf[0], 128); b1 := bufalloc.alloc(24); b2 := bufalloc.alloc(24); print("buf pos: {}\n", buf_state.pos); // buf pos: 48 b3 := bufalloc.alloc(200); b3_i : s64 = xx b3; print("buf overflow: {}\n", b3_i); // buf overflow: 0 buf_state.reset(); print("buf reset: {}\n", buf_state.pos); // buf reset: 0 } { if 1 == (1,) { print("1 == (1)\n"); } if (1,) == (1) { print("(1) == 1\n"); } if (1,) == 1 { print("1 == 1\n"); } } // ======================================================== // OPTIONALS // ======================================================== print("--- optionals ---\n"); // Basic optional creation and null { x: ?s32 = 42; y: ?s32 = null; print("opt x: {}\n", x); // opt x: 42 print("opt y: {}\n", y); // opt y: null } // Force unwrap { x: ?s32 = 10; val := x!; print("unwrap: {}\n", val); // unwrap: 10 } // Null coalescing { x: ?s32 = 42; y: ?s32 = null; a := x ?? 0; b := y ?? 99; print("coalesce a: {}\n", a); // coalesce a: 42 print("coalesce b: {}\n", b); // coalesce b: 99 // Chained ?? (right-associative): a ?? b ?? c z: ?s32 = null; c := x ?? y ?? 0; d := z ?? y ?? 99; e := z ?? z ?? 0; print("chained ?? c: {}\n", c); // chained ?? c: 42 print("chained ?? d: {}\n", d); // chained ?? d: 99 print("chained ?? e: {}\n", e); // chained ?? e: 0 } // If-binding (safe unwrap) { x: ?s32 = 7; y: ?s32 = null; if val := x { print("if-bind x: {}\n", val); // if-bind x: 7 } if val := y { print("if-bind y: should not print\n"); } else { print("if-bind y: none\n"); // if-bind y: none } } // Pattern matching on optionals { check :: (v: ?s32) -> s32 { return if v == { case .some: (val) { val; } case .none: { 0; } }; } a: ?s32 = 55; b: ?s32 = null; print("match some: {}\n", check(a)); // match some: 55 print("match none: {}\n", check(b)); // match none: 0 } // Optional with implicit wrapping { opt_wrap :: (n: s32) -> ?s32 { if n > 0 { return n; } return null; } r1 := opt_wrap(5); r2 := opt_wrap(0); print("wrap pos: {}\n", r1); // wrap pos: 5 print("wrap neg: {}\n", r2); // wrap neg: null } // Struct field defaults for ?T { n := OptNode.{ value = 10 }; print("opt field default: {}\n", n.next); // opt field default: null m := OptNode.{ value = 20, next = 42 }; print("opt field set: {}\n", m.next); // opt field set: 42 } // ?T as function parameter { opt_process :: (val: ?s32) -> s32 { return val ?? 0; } a: ?s32 = 42; b: ?s32 = null; print("opt param a: {}\n", opt_process(a)); // opt param a: 42 print("opt param b: {}\n", opt_process(b)); // opt param b: 0 print("opt param 7: {}\n", opt_process(7)); // opt param 7: 7 } // Assignment to optional variable (f32 → ?f32) { iw: ?f32 = null; w: f32 = 42.5; iw = w; print("opt reassign: {}\n", iw ?? 0.0); // opt reassign: 42.5 // Assignment of computed value to optional iw2: ?f32 = null; a: ?f32 = 10.0; if v := a { iw2 = v + 5.0; } print("opt compute assign: {}\n", iw2 ?? 0.0); // opt compute assign: 15.0 // Re-assign optional back to null iw2 = null; print("opt re-null: {}\n", iw2 ?? 99.0); // opt re-null: 99.0 } // Generic function with ?T return { first_pos :: ($T: Type, a: T, b: T) -> ?T { if a > 0 { return a; } if b > 0 { return b; } return null; } print("generic opt 1: {}\n", first_pos(s32, 5, 10)); // generic opt 1: 5 print("generic opt 2: {}\n", first_pos(s32, 0, 7)); // generic opt 2: 7 print("generic opt 3: {}\n", first_pos(s32, 0, 0)); // generic opt 3: null } // Optional chaining (?.) { p: ?OptNode = OptNode.{ value = 10, next = 20 }; q: ?OptNode = null; print("chain some: {}\n", p?.value ?? 0); // chain some: 10 print("chain none: {}\n", q?.value ?? 0); // chain none: 0 print("chain print: {}\n", p?.next); // chain print: 20 print("chain null: {}\n", q?.next); // chain null: null // Chained: obj.field?.field o1 := OptOuter.{ inner = OptInner.{ val = 99 } }; o2 := OptOuter.{ inner = null }; print("deep chain 1: {}\n", o1.inner?.val ?? 0); // deep chain 1: 99 print("deep chain 2: {}\n", o2.inner?.val ?? 0); // deep chain 2: 0 } // Flow-sensitive narrowing { x: ?s32 = 42; y: ?s32 = null; // if x != null → x is narrowed to s32 if x != null { print("narrow x: {}\n", x); // narrow x: 42 } // if y != null → not entered if y != null { print("should not print\n"); } else { print("narrow y else: null\n"); // narrow y else: null } // if x == null ... else → else-branch narrowed if x == null { print("should not print\n"); } else { print("narrow else x: {}\n", x); // narrow else x: 42 } } // Guard narrowing { guard_fn :: (v: ?s32) -> s32 { if v == null { return 0; } return v; } print("guard some: {}\n", guard_fn(42)); // guard some: 42 print("guard none: {}\n", guard_fn(null)); // guard none: 0 } // Compound narrowing: && chains { a: ?s32 = 10; b: ?s32 = 20; c: ?s32 = null; if a != null and b != null { print("and both: {} {}\n", a, b); // and both: 10 20 } if a != null and c != null { print("should not print\n"); } else { print("and one null\n"); // and one null } } // Compound guard narrowing: || chains { guard2 :: (a: ?s32, b: ?s32) -> s32 { if a == null or b == null { return 0; } return a + b; } print("or guard: {}\n", guard2(3, 4)); // or guard: 7 print("or guard null: {}\n", guard2(3, null)); // or guard null: 0 } // Nested if narrowing { a: ?s32 = 10; b: ?s32 = 20; if a != null { if b != null { print("nested narrow: {} {}\n", a, b); // nested narrow: 10 20 } } } // Guard narrowing used in loop { guard_loop :: (v: ?s32) -> s32 { if v == null { return 0; } sum := 0; i := 0; while i < v { sum = sum + 1; i = i + 1; } return sum; } print("guard loop: {}\n", guard_loop(3)); // guard loop: 3 } // --- block-body lambdas --- { // block-body lambda with return type clamp := (x: s64, lo: s64, hi: s64) -> s64 { if x < lo { return lo; } if x > hi { return hi; } return x; }; print("block-lambda: {}\n", clamp(50, 0, 100)); // block-lambda: 50 print("block-lambda: {}\n", clamp(-10, 0, 100)); // block-lambda: 0 print("block-lambda: {}\n", clamp(999, 0, 100)); // block-lambda: 100 // block-body lambda without return type annotation greet := (name: string) { print("hello {}\n", name); }; greet("block"); // hello block } // --- named params in function types --- { // Named params are documentation only — ignored for type identity apply_named :: (f: (x: s32, y: s32) -> s32, a: s32, b: s32) -> s32 { return f(a, b); } add :: (a: s32, b: s32) -> s32 { return a + b; } print("named-fn-type: {}\n", apply_named(add, 3, 4)); // named-fn-type: 7 } // --- xx on function pointers --- { MyEnv :: struct { n: s32; } typed_fn :: (e: *MyEnv, x: s32) -> s32 { return x + e.n; } // xx cast: (*MyEnv, s32) -> s32 → (*void, s32) -> s32 f : (*void, s32) -> s32 = xx typed_fn; env := MyEnv.{ n = 100 }; print("xx-fnptr: {}\n", f(xx @env, 42)); // xx-fnptr: 142 } // --- closure type: construct and access fields --- { dummy_fn :: (env: *void, x: s32) -> s32 { return x * 2; } fn_ptr : *void = xx dummy_fn; null_env : *void = xx 0; c : Closure(s32) -> s32 = .{ fn_ptr = fn_ptr, env = null_env }; print("closure-type: fn_ptr-nonnull={}\n", c.fn_ptr != null_env); print("closure-type: env-null={}\n", c.env == null_env); } // --- closure calling convention --- { Env :: struct { n: s32; } impl_fn :: (env: *void, x: s32) -> s32 { e : *Env = xx env; return x + e.n; } env := Env.{ n = 5 }; fn_ptr : *void = xx impl_fn; env_ptr : *void = xx @env; c : Closure(s32) -> s32 = .{ fn_ptr = fn_ptr, env = env_ptr }; print("closure-call: {}\n", c(10)); } // --- auto-promotion: bare fn → Closure --- { double :: (x: s32) -> s32 { return x * 2; } apply :: (f: Closure(s32) -> s32, x: s32) -> s32 { return f(x); } print("auto-promote: {}\n", apply(double, 10)); // Named function to Closure variable f : Closure(s32) -> s32 = double; print("auto-promote-var: {}\n", f(5)); } // --- closure() intrinsic --- { // capture scalar n := 42; f := closure((x: s32) => x + n); print("closure-capture: {}\n", f(10)); // capture by value is a snapshot m := 5; g := closure((x: s32) => x + m); m = 100; print("closure-snapshot: {}\n", g(10)); // no captures (null env) h := closure((x: s32) => x * 2); print("closure-nocap: {}\n", h(7)); // multiple captures a := 10; b := 20; multi := closure((x: s32) => x + a + b); print("closure-multi: {}\n", multi(3)); // block-body closure with return offset := 50; clamp := closure((x: s64) -> s64 { if x < 0 { return 0; } if x > 100 { return 100; } return x + offset; }); r1 : s64 = clamp(10); r2 : s64 = clamp(0 - 5); r3 : s64 = clamp(999); print("closure-block: {}\n", r1); print("closure-block: {}\n", r2); print("closure-block: {}\n", r3); // void closure tag := "LOG"; logger := closure((msg: string) { print("[{}] {}\n", tag, msg); }); logger("hello"); // pass closure to higher-order function dbl :: (x: s32) -> s32 { return x * 2; } apply_cl :: (f2: Closure(s32) -> s32, x: s32) -> s32 { return f2(x); } factor : s32 = 3; print("closure-hof: {}\n", apply_cl(closure((x: s32) -> s32 => x * factor), 10)); // auto-promoted bare fn passed alongside closures print("closure-hof-bare: {}\n", apply_cl(dbl, 10)); // C5.A2: capture f32 scale := 2.5; f_f32 := closure((x: f32) -> f32 => x * scale); print("closure-f32: {}\n", f_f32(4.0)); // C5.A3: capture bool verbose := true; f_bool := closure((msg: string) { if verbose { print("closure-bool: {}\n", msg); } }); f_bool("hello"); // C5.B3: two params base : s32 = 100; f_2p := closure((x: s32, y: s32) -> s32 => x + y + base); print("closure-2p: {}\n", f_2p(3, 4)); // C5.B4: three params bias : s32 = 1; f_3p := closure((a: s32, b: s32, c2: s32) -> s32 => a + b + c2 + bias); print("closure-3p: {}\n", f_3p(10, 20, 30)); // C5.B5: mixed param types (string + s32) extra : s32 = 5; f_mix := closure((name: string, age: s32) { print("closure-mix: {} is {}\n", name, age + extra); }); f_mix("Alice", 30); // C5.C3: return bool threshold : s32 = 100; f_rbool := closure((x: s32) -> bool { return x > threshold; }); print("closure-rbool: {} {}\n", f_rbool(50), f_rbool(200)); // C5.D3: reduce / fold reduce :: (arr: []s32, f3: Closure(s32, s32) -> s32, init: s32) -> s32 { acc := init; i : s64 = 0; while i < arr.len { acc = f3(acc, arr[i]); i += 1; } return acc; } r_nums : []s32 = .[1, 2, 3, 4, 5]; r_bonus : s32 = 100; r_total := reduce(r_nums, closure((acc: s32, x: s32) -> s32 => acc + x), r_bonus); print("closure-reduce: {}\n", r_total); // C5.G1: factory function make_adder :: (n: s32) -> Closure(s32) -> s32 { return closure((x: s32) -> s32 => x + n); } add5 := make_adder(5); add10 := make_adder(10); print("closure-factory: {} {}\n", add5(100), add10(100)); // C5.A5: capture struct origin := Point.{ x = 10, y = 20 }; f_st := closure(() { print("closure-struct: {} {}\n", origin.x, origin.y); }); f_st(); // C5.H1: closure captures another closure inner_n := 10; inner_cl := closure((x: s64) -> s64 => x + inner_n); outer_cl := closure((x: s64) -> s64 => inner_cl(x) * 2); print("closure-compose: {}\n", outer_cl(5)); // C5.M7: multiple closures from same scope capture independently shared : s32 = 10; cl_a := closure((x: s32) -> s32 => x + shared); cl_b := closure((x: s32) -> s32 => x * shared); print("closure-indep: {} {}\n", cl_a(5), cl_b(5)); // C6: optional closures f_none : ?Closure(s64) -> s64 = null; if h := f_none { print("should not print: {}\n", h(1)); } else { print("opt-closure: none\n"); } opt_n := 10; f_some : ?Closure(s64) -> s64 = closure((x: s64) -> s64 => x + opt_n); if h := f_some { print("opt-closure: {}\n", h(5)); } else { print("should not print\n"); } // Struct with optional closure callback Btn :: struct { label: string; on_click: ?Closure(s64) -> void; } btn_x := 99; btn_cl := closure((id: s64) { print("opt-closure-btn: {} {}\n", id, btn_x); }); btn1 := Btn.{ label = "OK", on_click = btn_cl }; btn2 := Btn.{ label = "Cancel", on_click = null }; if h := btn1.on_click { h(1); } if h := btn2.on_click { h(2); } else { print("opt-closure-btn: null\n"); } // C5.A6: capture pointer (shared mutable state) count_a6 : s32 = 0; p_a6 := @count_a6; inc_fn := closure(() { p_a6.* += 1; }); inc_fn(); inc_fn(); inc_fn(); print("closure-ptr: {}\n", count_a6); // C5.A9: capture enum value (as s32 tag) c_a9 : s32 = 2; // simulate enum tag f_a9 := closure(() -> s32 => c_a9); print("closure-enum: {}\n", f_a9()); // C5.C4: return string tag_c4 := "INFO"; f_c4 := closure((msg: string) -> string => format("[{}] {}", tag_c4, msg)); print("closure-rstr: {}\n", f_c4("ok")); // C5.C5: return struct off_c5 := Point.{ x = 10, y = 20 }; f_c5 := closure((p: Point) -> Point => Point.{ x = p.x + off_c5.x, y = p.y + off_c5.y }); res_c5 := f_c5(Point.{ x = 1, y = 2 }); print("closure-rstruct: {} {}\n", res_c5.x, res_c5.y); // C5.G2: factory with multiple captures make_linear :: (m: s32, b: s32) -> Closure(s32) -> s32 { return closure((x: s32) -> s32 => m * x + b); } lin := make_linear(3, 7); print("closure-linear: {}\n", lin(10)); // C5.G3: factory returning clamper make_clamper :: (lo: s32, hi: s32) -> Closure(s32) -> s32 { return closure((x: s32) -> s32 { if x < lo { return lo; } if x > hi { return hi; } return x; }); } clamp_fn := make_clamper(0, 255); cv1 : s32 = xx -10; cv2 : s32 = 100; cv3 : s32 = 999; print("closure-clamp: {} {} {}\n", clamp_fn(cv1), clamp_fn(cv2), clamp_fn(cv3)); // C5.H2: compose compose :: (f_h2: Closure(s32) -> s32, g_h2: Closure(s32) -> s32) -> Closure(s32) -> s32 { return closure((x: s32) -> s32 => f_h2(g_h2(x))); } one_h2 : s32 = 1; two_h2 : s32 = 2; add1_h2 := closure((x: s32) -> s32 => x + one_h2); mul2_h2 := closure((x: s32) -> s32 => x * two_h2); composed := compose(mul2_h2, add1_h2); print("closure-compose2: {}\n", composed(5)); // C5.H3: chain of closures ch_k1 : s32 = 1; ch_k2 : s32 = 2; ch_k10 : s32 = 10; ch_a := closure((x: s32) -> s32 => x + ch_k1); ch_b := closure((x: s32) -> s32 => ch_a(x) * ch_k2); ch_c := closure((x: s32) -> s32 => ch_b(x) + ch_k10); print("closure-chain: {}\n", ch_c(5)); // C5.D1: map map_cl :: (arr: [*]s32, cnt: s64, f_map: Closure(s32) -> s32, result: [*]s32) { i := 0; while i < cnt { result[i] = f_map(arr[i]); i += 1; } } map_src : [5]s32 = .[1, 2, 3, 4, 5]; map_dst : [5]s32 = .[0, 0, 0, 0, 0]; factor_d1 : s32 = 3; map_cl(xx @map_src, 5, closure((x: s32) -> s32 => x * factor_d1), xx @map_dst); print("closure-map: {} {} {} {} {}\n", map_dst[0], map_dst[1], map_dst[2], map_dst[3], map_dst[4]); // C5.D2: filter filter_cl :: (arr: [*]s32, cnt: s64, pred: Closure(s32) -> bool, result: [*]s32) -> s64 { j := 0; i := 0; while i < cnt { if pred(arr[i]) { result[j] = arr[i]; j += 1; } i += 1; } return j; } min_val : s32 = 3; filt_dst : [5]s32 = .[0, 0, 0, 0, 0]; kept := filter_cl(xx @map_src, 5, closure((x: s32) -> bool => x >= min_val), xx @filt_dst); print("closure-filter: {} [{} {} {}]\n", kept, filt_dst[0], filt_dst[1], filt_dst[2]); // C5.D4: sort comparator (bubble sort) sort_cl :: (arr: [*]s32, cnt: s64, less: Closure(s32, s32) -> bool) { i := 0; while i < cnt { j := 0; while j < cnt - 1 - i { if less(arr[j + 1], arr[j]) { tmp := arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } j += 1; } i += 1; } } sort_arr : [5]s32 = .[5, 3, 1, 4, 2]; descending := true; sort_cl(xx @sort_arr, 5, closure((a: s32, b: s32) -> bool { if descending { return a > b; } return a < b; })); print("closure-sort: {} {} {} {} {}\n", sort_arr[0], sort_arr[1], sort_arr[2], sort_arr[3], sort_arr[4]); // C5.D5: for_each with index for_each_cl :: (arr: [*]s32, cnt: s64, f_fe: Closure(s32, s64) -> void) { i : s64 = 0; while i < cnt { f_fe(arr[i], i); i += 1; } } fe_label := "item"; fe_arr : [3]s32 = .[10, 20, 30]; for_each_cl(xx @fe_arr, 3, closure((val: s32, idx: s64) { print("closure-fe: {} {}={}\n", fe_label, idx, val); })); // C5.D6: find find_cl :: (arr: [*]s32, cnt: s64, pred_f: Closure(s32) -> bool) -> s64 { i : s64 = 0; while i < cnt { if pred_f(arr[i]) { return i; } i += 1; } return -1; } target : s32 = 30; found_idx := find_cl(xx @fe_arr, 3, closure((x: s32) -> bool => x == target)); print("closure-find: {}\n", found_idx); // C5.D7: any any_cl :: (arr: [*]s32, cnt: s64, pred_a: Closure(s32) -> bool) -> bool { i : s64 = 0; while i < cnt { if pred_a(arr[i]) { return true; } i += 1; } return false; } has_big := any_cl(xx @fe_arr, 3, closure((x: s32) -> bool => x > 100)); has_20 := any_cl(xx @fe_arr, 3, closure((x: s32) -> bool => x == 20)); print("closure-any: {} {}\n", has_big, has_20); // C5.E4: auto-promotion in struct field assignment Widget :: struct { transform: Closure(s32) -> s32; } negate_fn :: (x: s32) -> s32 { return 0 - x; } w_e4 := Widget.{ transform = negate_fn }; print("closure-struct-field: {}\n", w_e4.transform(5)); // C5.F1: single closure callback in struct Button :: struct { label: string; on_press: Closure(s32) -> void; } btn_x2 := 99; btn_cb := closure((id: s32) { print("closure-btn: {} {}\n", id, btn_x2); }); btn3 := Button.{ label = "OK", on_press = btn_cb }; btn3.on_press(1); // C5.J1: stateful counter via pointer capture state_j1 : s32 = 0; p_j1 := @state_j1; inc_j1 := closure(() -> s32 { p_j1.* += 1; return p_j1.*; }); print("closure-counter: {} {} {}\n", inc_j1(), inc_j1(), inc_j1()); // C5.J2: stateful accumulator state_j2 : s32 = 100; p_j2 := @state_j2; acc_j2 := closure((x: s32) -> s32 { p_j2.* += x; return p_j2.*; }); print("closure-acc: {} {}\n", acc_j2(5), acc_j2(10)); // C5.K2: block-body with local variables and loops base_k2 : s32 = 100; sum_fn := closure((items: [*]s32, cnt: s64) -> s32 { total : s32 = 0; i : s64 = 0; while i < cnt { total += items[i]; i += 1; } return total + base_k2; }); k2_arr : [5]s32 = .[1, 2, 3, 4, 5]; print("closure-loop: {}\n", sum_fn(xx @k2_arr, 5)); // C5.M3: reassigning a closure variable n_m3 : s32 = 1; f_m3 := closure((x: s32) -> s32 => x + n_m3); print("closure-reassign: {}\n", f_m3(10)); m_m3 : s32 = 2; f_m3 = closure((x: s32) -> s32 => x * m_m3); print("closure-reassign: {}\n", f_m3(10)); // C5.M6b: snapshot verified with struct capture pt_m6 := Point.{ x = 5, y = 10 }; f_m6 := closure(() -> s32 => pt_m6.x + pt_m6.y); pt_m6 = Point.{ x = 99, y = 99 }; print("closure-snapstruct: {}\n", f_m6()); // C5.M2: closure capturing auto-promoted closure double_m2 :: (x: s32) -> s32 { return x * 2; } base_m2 : Closure(s32) -> s32 = double_m2; n_m2 : s32 = 1; f_m2 := closure((x: s32) -> s32 => base_m2(x) + n_m2); print("closure-cap-promoted: {}\n", f_m2(5)); // C5.M5: immediately invoked closure (via temp var) n_m5 : s32 = 5; iife := closure((x: s32) -> s32 => x + n_m5); result_m5 := iife(10); print("closure-iife: {}\n", result_m5); // C5.F2: optional callback (none) Toggle :: struct { on_change: ?Closure(bool) -> void; } t_f2 := Toggle.{ on_change = null }; if h := t_f2.on_change { h(true); } else { print("closure-toggle: none\n"); } // C5.F3: optional callback (some) t_f3_cb := closure((enabled: bool) { print("closure-toggle: {}\n", enabled); }); t_f3 := Toggle.{ on_change = t_f3_cb }; if h := t_f3.on_change { h(true); } // C5.F5: callback receiving caller context Panel :: struct { title: string; on_resize: Closure(string, s32, s32) -> void; } p_f5_cb := closure((title: string, w: s32, h: s32) { print("closure-panel: {} {}x{}\n", title, w, h); }); p_f5 := Panel.{ title = "main", on_resize = p_f5_cb }; p_f5.on_resize(p_f5.title, 800, 600); // C5.E6: protocol value passed through multiple function calls step3 :: (a: Allocator) -> *void { a.alloc(8); } step2 :: (a: Allocator) -> *void { step3(a); } step1 :: (a: Allocator) -> *void { step2(a); } gpa_e6 : GPA = .{ alloc_count = 0 }; a_e6 : Allocator = xx @gpa_e6; ptr_e6 := step1(a_e6); print("closure-chain-call: {}\n", ptr_e6 != null); a_e6.dealloc(ptr_e6); // C5.I1: creating closures in a loop (each captures different value) // TEMPORARILY DISABLED — closure-in-loop causes infinite loop (index_gep element size issue?) // cl_arr : [5]Closure(s32) -> s32 = ---; // i_loop := 0; // while i_loop < 5 { // val_loop : s32 = xx (i_loop * 10); // cl_arr[i_loop] = closure((x: s32) -> s32 => x + val_loop); // i_loop += 1; // } // I2: calling closures from array // tmp_cl := cl_arr[0]; print("closure-loop-0: {}\n", tmp_cl(1)); // tmp_cl = cl_arr[1]; print("closure-loop-1: {}\n", tmp_cl(1)); // tmp_cl = cl_arr[4]; print("closure-loop-4: {}\n", tmp_cl(1)); // C5.M4: closure in conditional expression (via temp var) use_fast := true; k_fast : s32 = 2; k_slow : s32 = 10; f_fast := closure((x: s32) -> s32 => x * k_fast); f_slow := closure((x: s32) -> s32 => x + k_slow); f_cond : Closure(s32) -> s32 = if use_fast then f_fast else f_slow; print("closure-cond: {}\n", f_cond(5)); // C5.F4: multiple callbacks on one struct Form :: struct { on_submit: ?Closure() -> void; on_cancel: ?Closure() -> void; } msg_f4 := "submitted"; sub_cb := closure(() { print("closure-form: {}\n", msg_f4); }); form_f4 := Form.{ on_submit = sub_cb, on_cancel = null }; if h := form_f4.on_submit { h(); } if h := form_f4.on_cancel { h(); } else { print("closure-form: no cancel\n"); } // C5.L3: auto-promoted closure env is null (no free needed) double_l3 :: (x: s32) -> s32 { return x * 2; } f_l3 : Closure(s32) -> s32 = double_l3; print("closure-null-env: {}\n", f_l3.env == null); // C5.A7: capture slice (fat pointer like string) sl_a7 : [3]s32 = .[10, 20, 30]; ptr_a7 : [*]s32 = xx @sl_a7; f_a7 := closure((i: s64) -> s32 => ptr_a7[i]); print("closure-slice: {} {} {}\n", f_a7(0), f_a7(1), f_a7(2)); // C5.L1: arena bulk free (closures allocated on arena, freed in bulk) gpa_l1 : GPA = .{ alloc_count = 0 }; a_l1 : Allocator = xx @gpa_l1; arena_l1 : Arena = ---; arena_alloc := arena_l1.create(a_l1, 4096); push Context.{ allocator = arena_alloc } { n_l1 : s32 = 5; f_l1 := closure((x: s32) -> s32 => x + n_l1); print("closure-arena: {}\n", f_l1(10)); } arena_l1.deinit(); // C5.L2: GPA manual free (verify env alloc/dealloc) gpa_l2 : GPA = .{ alloc_count = 0 }; a_l2 : Allocator = xx @gpa_l2; n_l2 : s32 = 7; result_l2 : s32 = 0; push Context.{ allocator = a_l2 } { f_l2 := closure((x: s32) -> s32 => x + n_l2); result_l2 = f_l2(10); a_l2.dealloc(f_l2.env); } print("closure-gpa: {} allocs={}\n", result_l2, gpa_l2.alloc_count); // C5.A10: capture optional val_a10 : ?s32 = 42; f_a10 := closure(() -> s32 { if v := val_a10 { return v; } return 0; }); print("closure-opt: {}\n", f_a10()); // C5.C6: return optional limit_c6 : s32 = 100; f_c6 := closure((x: s32) -> ?s32 { if x > limit_c6 { return null; } return x; }); r1_c6 := f_c6(50); r2_c6 := f_c6(200); if v := r1_c6 { print("closure-ropt: {}\n", v); } if v := r2_c6 { print("should-not-print\n"); } else { print("closure-ropt: none\n"); } // C5.M8: array of closures with mixed origins double_m8 :: (x: s32) -> s32 { return x * 2; } n_m8 : s32 = 10; fns_m8 : [3]Closure(s32) -> s32 = ---; fns_m8[0] = double_m8; // auto-promoted fns_m8[1] = closure((x: s32) -> s32 => x + n_m8); // captured fns_m8[2] = closure((x: s32) -> s32 => x * x); // no capture tmp_m8 := fns_m8[0]; print("closure-mixed: {}\n", tmp_m8(5)); tmp_m8 = fns_m8[1]; print("closure-mixed: {}\n", tmp_m8(5)); tmp_m8 = fns_m8[2]; print("closure-mixed: {}\n", tmp_m8(5)); // C5.E1: independent closures from same factory (each has own env) mk_e1 :: (n: s32) -> Closure(s32) -> s32 { return closure((x: s32) -> s32 => x * n); } f1_e1 := mk_e1(2); f2_e1 := mk_e1(3); f3_e1 := mk_e1(4); print("closure-factory-indep: {} {} {}\n", f1_e1(10), f2_e1(10), f3_e1(10)); // C5.E2: deep chain — closure capturing closure capturing closure v_e2 : s32 = 1; k2_e2 : s32 = 2; k100_e2 : s32 = 100; f0_e2 := closure((x: s32) -> s32 => x + v_e2); f1_e2 := closure((x: s32) -> s32 => f0_e2(x) * k2_e2); f2_e2 := closure((x: s32) -> s32 => f1_e2(x) + k100_e2); print("closure-deep-chain: {}\n", f2_e2(10)); // C5.E3: many captures (stress env struct) c1_e3 : s32 = 1; c2_e3 : s32 = 2; c3_e3 : s32 = 3; c4_e3 : s32 = 4; c5_e3 : s32 = 5; c6_e3 : s32 = 6; c7_e3 : s32 = 7; c8_e3 : s32 = 8; big_env := closure(() -> s32 => c1_e3 + c2_e3 + c3_e3 + c4_e3 + c5_e3 + c6_e3 + c7_e3 + c8_e3); print("closure-8cap: {}\n", big_env()); // C5.E5: closure with many parameters (4 params) multi_param := closure((a: s32, b: s32, c: s32, d: s32) -> s32 => a + b + c + d); a_e5 : s32 = 1; b_e5 : s32 = 2; c_e5 : s32 = 3; d_e5 : s32 = 4; print("closure-4param: {}\n", multi_param(a_e5, b_e5, c_e5, d_e5)); // C5.E7: two closures sharing the same captured pointer shared : s32 = 0; shared_p := @shared; inc_shared := closure(() { shared_p.* += 1; }); add5_shared := closure(() { shared_p.* += 5; }); inc_shared(); add5_shared(); inc_shared(); print("closure-shared-ptr: {}\n", shared); // C5.E8: closure with f64 arithmetic pi_e8 : f64 = 3.14159; area_fn := closure((r: f64) -> f64 => pi_e8 * r * r); a_e8 := area_fn(10.0); print("closure-f64: {}\n", a_e8 > 314.0); // C5.E9: zero-capture closure (env should be null, like auto-promoted) no_cap := closure((x: s32) -> s32 => x * x); print("closure-zerocap: {} {}\n", no_cap(7), no_cap.env == null); // C5.E10: closure capturing and calling struct method pt_e10 := Point.{ x = 3, y = 4 }; p_e10 := @pt_e10; get_xy := closure(() -> s32 => p_e10.x + p_e10.y); print("closure-struct-method: {}\n", get_xy()); // C5.E11: multiple closures from same factory with different captures fns_e11 : [3]Closure(s32) -> s32 = ---; i_e11 := 0; while i_e11 < 3 { multiplier : s32 = xx (i_e11 + 1); fns_e11[i_e11] = closure((x: s32) -> s32 => x * multiplier); i_e11 += 1; } t_e11 := fns_e11[0]; print("closure-multi-factory: {}\n", t_e11(10)); t_e11 = fns_e11[1]; print("closure-multi-factory: {}\n", t_e11(10)); t_e11 = fns_e11[2]; print("closure-multi-factory: {}\n", t_e11(10)); // C5.E12: closure capturing bool flag_e12 := true; check_fn := closure((x: s32) -> bool { if flag_e12 { return x > 0; } return x < 0; }); pos_e12 : s32 = 5; neg_e12 : s32 = xx -3; print("closure-bool-cap: {} {}\n", check_fn(pos_e12), check_fn(neg_e12)); // C5.E13: closure as argument to another closure apply_fn := closure((f_app: Closure(s32) -> s32, val: s32) -> s32 => f_app(val)); k_e13 : s32 = 100; inner_fn := closure((x: s32) -> s32 => x + k_e13); print("closure-as-arg: {}\n", apply_fn(inner_fn, 42)); // C5.E14: closure capturing string and formatting prefix_e14 := "hello"; greet_fn := closure((name: string) -> string => format("{} {}", prefix_e14, name)); print("closure-strfmt: {}\n", greet_fn("world")); // C5.E15: reassigning shared pointer target between closure calls val_e15 : s32 = 10; p_e15 := @val_e15; read_fn := closure(() -> s32 => p_e15.*); print("closure-ptr-before: {}\n", read_fn()); val_e15 = 42; print("closure-ptr-after: {}\n", read_fn()); // C5.E16: closure returning negative value off_e16 : s32 = 100; neg_fn := closure((x: s32) -> s32 => x - off_e16); val_e16 : s32 = 30; print("closure-neg: {}\n", neg_fn(val_e16)); // C5.E17: closure with protocol value capture (#inline protocol) gpa_e17 : GPA = .{ alloc_count = 0 }; a_e17 : Allocator = xx @gpa_e17; alloc_fn := closure((size: s64) -> *void => a_e17.alloc(size)); ptr_e17 := alloc_fn(32); print("closure-proto-cap: {}\n", ptr_e17 != null); a_e17.dealloc(ptr_e17); // C5.E18: chained factory — compose two factories make_scaler :: (factor: s32) -> Closure(s32) -> s32 { return closure((x: s32) -> s32 => x * factor); } make_offset :: (off: s32) -> Closure(s32) -> s32 { return closure((x: s32) -> s32 => x + off); } s_fn := make_scaler(3); o_fn := make_offset(7); // manually compose: scale then offset print("closure-chain-factory: {}\n", o_fn(s_fn(10))); // C5.E19: closure in while loop condition helper threshold : s32 = 50; above_fn := closure((x: s32) -> bool => x >= threshold); vals_e19 : [5]s32 = .[10, 30, 50, 70, 90]; count_above : s32 = 0; idx_e19 : s64 = 0; while idx_e19 < 5 { if above_fn(vals_e19[idx_e19]) { count_above += 1; } idx_e19 += 1; } print("closure-while-cond: {}\n", count_above); // ---- Inferred closure parameter types ---- // CI.1: inferred params from typed variable f_ci1 : Closure(s32, s32) -> s32 = closure((a, b) => a + b); a_ci1 : s32 = 3; b_ci1 : s32 = 4; print("closure-infer: {}\n", f_ci1(a_ci1, b_ci1)); // CI.2: inferred params from function argument apply_ci :: (f: Closure(s32) -> s32, x: s32) -> s32 { return f(x); } k_ci : s32 = 10; v_ci : s32 = 5; print("closure-infer-arg: {}\n", apply_ci(closure((x) => x + k_ci), v_ci)); // CI.3: inferred with block body h_ci : Closure(s32, s32) -> s32 = closure((a, b) { return a * b; }); print("closure-infer-block: {}\n", h_ci(a_ci1, b_ci1)); // CI.4: inferred with captures cap_ci : s32 = 100; f_ci4 : Closure(s32) -> s32 = closure((x) => x + cap_ci); print("closure-infer-cap: {}\n", f_ci4(v_ci)); // CI.5: inferred in factory return mk_ci :: (n: s32) -> Closure(s32) -> s32 { return closure((x) => x * n); } f_ci5 := mk_ci(7); print("closure-infer-factory: {}\n", f_ci5(v_ci)); // CI.6: inferred with higher-order (closure taking closure) compose_ci :: (f: Closure(s32) -> s32, g: Closure(s32) -> s32) -> Closure(s32) -> s32 { return closure((x: s32) -> s32 => f(g(x))); } one_ci : s32 = 1; two_ci : s32 = 2; c_ci := compose_ci(closure((x) => x + one_ci), closure((x) => x * two_ci)); print("closure-infer-compose: {}\n", c_ci(v_ci)); // CI.7: inferred void return msg_ci := "infer-void"; cb_ci : Closure(s32) -> void = closure((x) { print("closure-{}: {}\n", msg_ci, x); }); cb_ci(42); } // ======================================================== // PROTOCOLS (Phase 1: static dispatch) // ======================================================== print("=== Protocols ===\n"); // P1.1: Basic protocol + impl, direct call on concrete type { sc := SimpleCounter.{ val = 0 }; sc.inc(); sc.inc(); sc.inc(); print("P1.1: {}\n", sc.get()); } // P1.2: impl in separate scope (retroactive conformance) { p := Point.{ x = 10, y = 20 }; print("P1.2: {}\n", p.sum()); } // P2.1: #inline protocol — xx conversion + dynamic dispatch { acc := Accumulator.{ total = 0 }; a : Adder = xx @acc; a.add(10); a.add(20); a.add(12); print("P2.1: {}\n", a.value()); } // P2.2: pass protocol value to function { use_adder :: (a: Adder, n: s32) -> s32 { a.add(n); a.value(); } acc := Accumulator.{ total = 100 }; result := use_adder(xx @acc, 50); print("P2.2: {}\n", result); } // P2.3: different impls through same protocol type { acc := Accumulator.{ total = 0 }; dbl := Doubler.{ val = 0 }; a1 : Adder = xx @acc; a2 : Adder = xx @dbl; a1.add(5); a2.add(5); print("P2.3: {} {}\n", a1.value(), a2.value()); } // P3.1: vtable-pointer protocol (default, no #inline) { sc := SimpleCounter.{ val = 0 }; c : Counter = xx @sc; c.inc(); c.inc(); c.inc(); c.inc(); c.inc(); print("P3.1: {}\n", c.get()); } // P3.2: vtable protocol passed to function { use_counter :: (c: Counter) -> s32 { c.inc(); c.inc(); c.get(); } sc := SimpleCounter.{ val = 10 }; result := use_counter(xx @sc); print("P3.2: {}\n", result); } // P4.1: default method calls required method (static dispatch) { pr := Printer.{ count = 0 }; pr.say_twice("hi "); print("\nP4.1: {}\n", pr.count); } // P4.2: default method via dynamic dispatch (vtable) { pr := Printer.{ count = 0 }; r : Repeater = xx @pr; r.say_twice("yo "); print("\nP4.2: {}\n", pr.count); } // P4.3: chained default→default calls via vtable { ci := ChainImpl.{ val = 0 }; ch : Chained = xx @ci; // double_wrap calls wrap twice, wrap calls base once each // base("hi") returns 2 (len), wrap adds 1 → 3, double_wrap = 3 + 3 = 6 result := ch.double_wrap("hi"); // base was called 2 times (once per wrap call) print("P4.3: {} {}\n", result, ci.val); } // P5.1: Self type in protocol — static dispatch { p1 := Point.{ x = 1, y = 2 }; p2 := Point.{ x = 1, y = 2 }; p3 := Point.{ x = 3, y = 4 }; print("P5.1: {} {}\n", p1.eq(p2), p1.eq(p3)); } // P5.2: Self in return position { p := Point.{ x = 10, y = 20 }; p2 := p.clone(); print("P5.2: {} {}\n", p2.x, p2.y); } // P5.5: impl for primitive type { x := 42; y := 42; z := 99; r1 := x.eq(y); r2 := x.eq(z); print("P5.5: {} {}\n", r1, r2); } // P5.3: Self with dynamic dispatch (erased to *void) { p1 := Point.{ x = 1, y = 2 }; p2 := Point.{ x = 1, y = 2 }; p3 := Point.{ x = 3, y = 4 }; e : Eq = xx p1; print("P5.3: {} {}\n", e.eq(p2), e.eq(p3)); } // P6.1: Single constraint — constrained generic function { p1 := Point.{ x = 1, y = 2 }; p2 := Point.{ x = 1, y = 2 }; p3 := Point.{ x = 3, y = 4 }; print("P6.1: {} {}\n", are_equal(p1, p2), are_equal(p1, p3)); } // P6.2: Constraint with primitive type { print("P6.2: {} {}\n", are_equal(42, 42), are_equal(42, 99)); } // P6.3: Multiple constraints { p1 := Point.{ x = 1, y = 2 }; p2 := Point.{ x = 1, y = 2 }; p3 := Point.{ x = 3, y = 4 }; print("P6.3: {} {}\n", eq_and_hash(p1, p2), eq_and_hash(p1, p3)); } // P6.4: inline constraint syntax ($T/Protocol) { // sum_of_inline uses $T/Summable inline (not $T: Type/Summable) p1 := Point.{ x = 10, y = 20 }; p2 := Point.{ x = 3, y = 7 }; print("P6.4: {}\n", sum_of_inline(p1, p2)); } // P6.5: Struct type param constraints ($T: Type/Summable) { box := SumBox(Point).{ val = Point.{ x = 5, y = 15 } }; print("P6.5: {}\n", box.val.sum()); } // P7.1: impl for generic struct { p := Pair(s32).{ a = 10, b = 20 }; print("P7.1: {}\n", p.sum()); } // P7.2: generic struct impl with different type arg { p1 := Pair(s32).{ a = 3, b = 7 }; p2 := Pair(s64).{ a = 100, b = 200 }; print("P7.2: {} {}\n", p1.sum(), p2.sum()); } // P2.4: xx in function return position (tested in standalone test_return.sx) // Covered by: make_adder :: (acc: *Accumulator) -> Adder { xx acc; } // P2.6: protocol values in arrays { acc := Accumulator.{ total = 0 }; dbl := Doubler.{ val = 0 }; adders : [2]Adder = .[xx @acc, xx @dbl]; i := 0; while i < 2 { adders[i].add(5); i += 1; } print("P2.6: {} {}\n", acc.total, dbl.val); } // P2.7: xx on inline struct literal (no intermediate variable) { use_adder :: (a: Adder) -> s32 { a.add(10); a.value(); } result := use_adder(xx Accumulator.{ total = 5 }); print("P2.7: {}\n", result); } // P3.3: xx on inline struct literal with vtable protocol { use_counter :: (c: Counter) -> s32 { c.inc(); c.inc(); c.get(); } result := use_counter(xx SimpleCounter.{ val = 100 }); print("P3.3: {}\n", result); } // --- Auto type erasure (AE) --- print("=== Auto Type Erasure ===\n"); // AE1: function argument — concrete passed where protocol expected (no xx) { use_counter :: (c: Counter) -> s32 { c.inc(); c.inc(); c.get(); } sc := SimpleCounter.{ val = 10 }; result := use_counter(sc); print("AE1: {}\n", result); } // AE2: variable assignment — concrete to protocol variable (no xx) { acc := Accumulator.{ total = 0 }; a: Adder = acc; a.add(5); a.add(3); print("AE2: {}\n", a.value()); } // AE3: struct literal passed directly (no xx) { use_counter :: (c: Counter) -> s32 { c.inc(); c.inc(); c.get(); } result := use_counter(SimpleCounter.{ val = 100 }); print("AE3: {}\n", result); } // AE4: explicit xx still works (not broken) { use_counter :: (c: Counter) -> s32 { c.inc(); c.get(); } result := use_counter(xx SimpleCounter.{ val = 50 }); print("AE4: {}\n", result); } // AE5: pointer auto-erasure — *ConcreteType to protocol { use_adder :: (a: Adder) { a.add(10); } acc := Accumulator.{ total = 5 }; p := @acc; use_adder(p); print("AE5: {}\n", acc.total); } // --- Struct Constants --- print("=== Struct Constants ===\n"); { print("gravity: {}\n", Phys.GRAVITY); // gravity: 9.810000 print("max speed: {}\n", Phys.MAX_SPEED); // max speed: 100 p := Phys.{ x = 0.0, y = Phys.GRAVITY }; print("p.y: {}\n", p.y); // p.y: 9.810000 } // --- 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); } // --- inline if (compile-time conditionals) --- print("=== inline if ===\n"); { // POINTER_SIZE is 8 on desktop (64-bit) inline if POINTER_SIZE == 8 { print("64-bit\n"); } else { print("32-bit\n"); } // OS enum comparison inline if OS == .wasm { print("wasm\n"); } else { print("not wasm\n"); } // != comparison inline if OS != .unknown { print("known os\n"); } else { print("unknown os\n"); } // nested inline if inline if POINTER_SIZE != 4 { inline if OS != .wasm { print("desktop 64-bit\n"); } else { print("wasm 64-bit??\n"); } } // POINTER_SIZE in regular (non-inline) if expression ps := if POINTER_SIZE == 8 then "8" else "4"; print("pointer size via if: {}\n", ps); } // ── Trailing commas ────────────────────────────────────────── print("=== Trailing Commas ===\n"); { // Struct literal with trailing comma Vec4 :: struct { x: f64; y: f64; z: f64; w: f64; } v := Vec4.{ x = 1.0, y = 2.0, z = 3.0, w = 4.0, }; assert(v.x == 1.0); assert(v.w == 4.0); // Function call with trailing comma add :: (a: s64, b: s64) -> s64 { return a + b; } r := add(10, 20,); assert(r == 30); // Array literal with trailing comma arr := s64.[1, 2, 3,]; assert(arr[2] == 3); print("trailing commas ok\n"); } print("=== DONE ===\n"); }