Files
sx/examples/smoke_a.sx
agra 6a920dbd2c ir
2026-02-28 18:03:38 +02:00

1612 lines
40 KiB
Plaintext

#import "modules/std.sx";
#import "modules/math/math.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;
}
}
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 ---
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);
// --- 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);
}
// ========================================================
// 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
}
print("=== DONE ===
");
}