2343 lines
52 KiB
Plaintext
2343 lines
52 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, 5lf.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: {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: {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
|
|
}\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
|
|
}\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 = .[1 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 = .[1 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, 20, 30, 40, 50, 20, 30, 40, 5 |