Break the monolithic examples/50-smoke.sx into 30 focused per-section examples,
filed into their category blocks (basic/types/comptime/memory/protocols/ffi),
each carrying only the top-level decls its section references (the protocols
section keeps the full preamble — its deps flow through UFCS method calls that
name-based extraction can't see). Outputs verified identical to the original
section blocks.
Add examples/1036-errors-failable-smoke.sx — an end-to-end error-handling example
(the E5.4 work): named + inferred error sets consumed via destructure, try (in
helpers), catch (bare-expr / match-body / diverging / no-binding), or
value-terminator, onfail+defer interleave, and error.X value + {} tag
interpolation.
Remove examples/50-smoke.sx. Suite: 324 passed, 0 failed.
343 lines
8.2 KiB
Plaintext
343 lines
8.2 KiB
Plaintext
#import "modules/std.sx";
|
|
#import "modules/math/math.sx";
|
|
#import "modules/compiler.sx";
|
|
#import "modules/test.sx";
|
|
pkg :: #import "modules/testpkg";
|
|
|
|
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 = ---;
|
|
}
|
|
|
|
MyFloat :: f64;
|
|
|
|
Status :: enum u8 { ok; err; timeout; }
|
|
|
|
add :: (a: s32, b: s32) -> s32 { a + b; }
|
|
|
|
mul :: (a: s32, b: s32) -> s32 { a * b; }
|
|
|
|
vec3 :: (x: f32, y: f32, z: f32) -> Vector(3, f32) {
|
|
.[x, y, z];
|
|
}
|
|
|
|
// Global variable for address-of test
|
|
g_smoke_val : s32 = 42;
|
|
|
|
write_to_ptr :: (p: *s32) {
|
|
p.* = 99;
|
|
}
|
|
|
|
main :: () {
|
|
|
|
// ========================================================
|
|
// 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]);
|
|
}
|