smoke tests
This commit is contained in:
618
examples/50-smoke.sx
Normal file
618
examples/50-smoke.sx
Normal file
@@ -0,0 +1,618 @@
|
||||
#import "modules/std.sx";
|
||||
|
||||
// ============================================================
|
||||
// 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 = ---;
|
||||
}
|
||||
|
||||
MyFloat :: f64;
|
||||
|
||||
Perms :: enum flags { read; write; execute; }
|
||||
|
||||
Status :: enum u8 { ok; err; timeout; }
|
||||
|
||||
// --- 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 { 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;
|
||||
}
|
||||
|
||||
// #run compile-time constant
|
||||
CT_VAL :: #run add(10, 15);
|
||||
|
||||
// #insert helper
|
||||
gen_code :: () -> string {
|
||||
return "print(\"insert-ok\\n\");";
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
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 (backtick)
|
||||
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);
|
||||
|
||||
// ========================================================
|
||||
// 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);
|
||||
|
||||
// Bitwise
|
||||
print("band: {}\n", 0xFF & 0x0F);
|
||||
print("bor: {}\n", 1 | 2 | 4);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// ========================================================
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// --- Slices ---
|
||||
sl : []s32 = .[1, 2, 3, 4, 5];
|
||||
print("sl[0]: {}\n", sl[0]);
|
||||
print("sl.len: {}\n", sl.len);
|
||||
|
||||
// Subslicing
|
||||
sub := arr[1..4];
|
||||
print("sub: {}\n", sub);
|
||||
head := arr[..3];
|
||||
print("head: {}\n", head);
|
||||
tail := arr[2..];
|
||||
print("tail: {}\n", tail);
|
||||
|
||||
// String subslicing
|
||||
msg := "hello world";
|
||||
print("strsub: {}\n", msg[6..11]);
|
||||
|
||||
// --- 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]);
|
||||
|
||||
// ========================================================
|
||||
// 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 block
|
||||
if 1 < 2 {
|
||||
print("if-block: yes\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 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);
|
||||
|
||||
// For loop basic (using write like example 19)
|
||||
farr : [4]s32 = .[10, 20, 30, 40];
|
||||
write("for:");
|
||||
for farr {
|
||||
write(" ");
|
||||
write(int_to_string(it));
|
||||
}
|
||||
write("\n");
|
||||
|
||||
// For with print
|
||||
write("for-print:");
|
||||
for farr {
|
||||
print(" {}", it);
|
||||
}
|
||||
write("\n");
|
||||
|
||||
// For with it_index
|
||||
write("for-idx:");
|
||||
for farr {
|
||||
write(" ");
|
||||
write(int_to_string(it_index));
|
||||
}
|
||||
write("\n");
|
||||
|
||||
// For with print two args
|
||||
write("for-2arg:");
|
||||
for farr {
|
||||
print(" {}@{}", it, it_index);
|
||||
}
|
||||
write("\n");
|
||||
|
||||
// For with break
|
||||
write("for-break:");
|
||||
for farr {
|
||||
if it == 30 { break; }
|
||||
print(" {}", it);
|
||||
}
|
||||
write("\n");
|
||||
|
||||
// For with continue
|
||||
write("for-continue:");
|
||||
for farr {
|
||||
if it == 20 { continue; }
|
||||
print(" {}", it);
|
||||
}
|
||||
write("\n");
|
||||
|
||||
// ========================================================
|
||||
// 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));
|
||||
|
||||
// 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));
|
||||
|
||||
// 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);
|
||||
|
||||
// Nested scopes (3 levels)
|
||||
nv := 1;
|
||||
{
|
||||
nv := 2;
|
||||
{
|
||||
nv := 3;
|
||||
print("nest3: {}\n", nv);
|
||||
}
|
||||
print("nest2: {}\n", nv);
|
||||
}
|
||||
print("nest1: {}\n", nv);
|
||||
|
||||
// Multiple defers (LIFO order)
|
||||
{
|
||||
defer print("defer-c\n");
|
||||
defer print("defer-b\n");
|
||||
defer print("defer-a\n");
|
||||
}
|
||||
|
||||
// Defer in nested scopes
|
||||
{
|
||||
defer print("outer-defer\n");
|
||||
{
|
||||
defer print("inner-defer\n");
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================================
|
||||
// 7. BUILT-IN FUNCTIONS
|
||||
// ========================================================
|
||||
print("=== 7. Builtins ===\n");
|
||||
|
||||
// write
|
||||
write("write-ok\n");
|
||||
|
||||
// sqrt
|
||||
print("sqrt: {}\n", sqrt(9.0));
|
||||
|
||||
// size_of
|
||||
print("sizeof-s32: {}\n", size_of(s32));
|
||||
print("sizeof-f64: {}\n", size_of(f64));
|
||||
|
||||
// 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_name
|
||||
print("typename: {}\n", type_name(Point));
|
||||
|
||||
// field_count
|
||||
print("fieldcount: {}\n", field_count(Point));
|
||||
|
||||
// field_name
|
||||
print("fieldname0: {}\n", field_name(Point, 0));
|
||||
print("fieldname1: {}\n", field_name(Point, 1));
|
||||
|
||||
// field_value (use any_to_string to avoid sext-on-Any bug)
|
||||
fv_pt := Point.{ 11, 22 };
|
||||
write("fieldval0: ");
|
||||
write(any_to_string(field_value(fv_pt, 0)));
|
||||
write("\n");
|
||||
write("fieldval1: ");
|
||||
write(any_to_string(field_value(fv_pt, 1)));
|
||||
write("\n");
|
||||
|
||||
// field_index on enum
|
||||
fi_c : Color = .green;
|
||||
print("fieldidx: {}\n", field_index(Color, fi_c));
|
||||
|
||||
// cast
|
||||
cval : f64 = 3.7;
|
||||
print("cast: {}\n", cast(s32) cval);
|
||||
|
||||
// ========================================================
|
||||
// 8. COMPILE-TIME
|
||||
// ========================================================
|
||||
print("=== 8. Comptime ===\n");
|
||||
|
||||
// #run constant
|
||||
print("run-const: {}\n", CT_VAL);
|
||||
|
||||
// #insert with function
|
||||
#insert gen_code();
|
||||
|
||||
// ========================================================
|
||||
// 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"); }
|
||||
|
||||
// Cast to int
|
||||
print("flags-raw: {}\n", cast(s64) perm);
|
||||
|
||||
print("=== DONE ===\n");
|
||||
}
|
||||
Reference in New Issue
Block a user