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.
201 lines
4.9 KiB
Plaintext
201 lines
4.9 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; }
|
|
|
|
add :: (a: s32, b: s32) -> s32 { a + b; }
|
|
|
|
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
|
|
|
|
// 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
|
|
|
|
// Init block test struct
|
|
Builder :: struct {
|
|
total: s32;
|
|
count: s32;
|
|
|
|
add :: (self: *Builder, val: s32) {
|
|
self.total += val;
|
|
self.count += 1;
|
|
}
|
|
}
|
|
|
|
// Global variable for address-of test
|
|
|
|
main :: () {
|
|
|
|
// --- Init Blocks (IB) ---
|
|
print("=== Init Blocks ===\n");
|
|
|
|
// IB1: basic init block with struct methods
|
|
{
|
|
b := Builder.{ total = 0, count = 0 } {
|
|
self.add(10);
|
|
self.add(20);
|
|
self.add(30);
|
|
};
|
|
print("IB1: {} {}\n", b.total, b.count);
|
|
}
|
|
|
|
// IB2: nested init blocks (self shadows correctly)
|
|
{
|
|
b1 := Builder.{ total = 0, count = 0 } {
|
|
self.add(100);
|
|
b2 := Builder.{ total = 0, count = 0 } {
|
|
self.add(42);
|
|
};
|
|
self.add(b2.total);
|
|
};
|
|
print("IB2: {} {}\n", b1.total, b1.count);
|
|
}
|
|
|
|
// IB3: empty init block
|
|
{
|
|
b := Builder.{ total = 5, count = 1 } {};
|
|
print("IB3: {} {}\n", b.total, b.count);
|
|
}
|
|
|
|
// IB4: conditional inside init block
|
|
{
|
|
add_extra := true;
|
|
b := Builder.{ total = 0, count = 0 } {
|
|
self.add(10);
|
|
if add_extra {
|
|
self.add(90);
|
|
}
|
|
};
|
|
print("IB4: {}\n", b.total);
|
|
}
|
|
|
|
// IB5: init block + auto type erasure combined
|
|
{
|
|
use_counter :: (c: Counter) -> s32 { c.inc(); c.inc(); c.get(); }
|
|
result := use_counter(SimpleCounter.{ val = 0 } {
|
|
self.val = 50;
|
|
});
|
|
print("IB5: {}\n", result);
|
|
}
|
|
|
|
// ============================================================
|
|
// SECTION: Struct static method shorthand (.method(args) syntax)
|
|
// ============================================================
|
|
print("--- struct static method shorthand ---\n");
|
|
|
|
// SM1: Basic shorthand — .create(args) resolves to Dims.create(args)
|
|
{
|
|
Dims :: struct {
|
|
w: f32;
|
|
h: f32;
|
|
|
|
create :: (w: f32, h: f32) -> Dims {
|
|
Dims.{ w = w, h = h };
|
|
}
|
|
|
|
square :: (size: f32) -> Dims {
|
|
Dims.{ w = size, h = size };
|
|
}
|
|
}
|
|
use_dims :: (d: Dims) { print("SM1: {} {}\n", d.w, d.h); }
|
|
use_dims(.create(16.0, 8.0));
|
|
use_dims(.square(5.0));
|
|
}
|
|
|
|
// SM2: Shorthand in variable declaration with explicit type
|
|
{
|
|
Pair :: struct {
|
|
a: s64;
|
|
b: s64;
|
|
|
|
make :: (a: s64, b: s64) -> Pair {
|
|
Pair.{ a = a, b = b };
|
|
}
|
|
}
|
|
p : Pair = .make(10, 20);
|
|
print("SM2: {} {}\n", p.a, p.b);
|
|
}
|
|
|
|
// ============================================================
|
|
// OPTIONAL IF-ELSE COERCION
|
|
// ============================================================
|
|
{
|
|
print("--- optional if-else coercion ---\n");
|
|
OptF :: struct { width: ?f32; }
|
|
x :f32: 10.0;
|
|
|
|
// null in then branch
|
|
f1 := OptF.{ width = if true then null else x };
|
|
print("opt-if1: {}\n", f1.width ?? 99.0);
|
|
|
|
// value in then branch, null in else
|
|
f2 := OptF.{ width = if true then x else null };
|
|
print("opt-if2: {}\n", f2.width ?? 99.0);
|
|
|
|
// both branches are values
|
|
f3 := OptF.{ width = if false then 5.0 else x };
|
|
print("opt-if3: {}\n", f3.width ?? 99.0);
|
|
|
|
// standalone optional variable
|
|
val: ?f32 = if true then null else 42.0;
|
|
print("opt-if4: {}\n", val ?? 0.0);
|
|
|
|
val2: ?f32 = if false then null else 42.0;
|
|
print("opt-if5: {}\n", val2 ?? 0.0);
|
|
}
|
|
|
|
// --- usize / isize ---
|
|
{
|
|
a : usize = 42;
|
|
b : isize = 0 - 7;
|
|
print("usize: {}\n", a);
|
|
print("isize: {}\n", b);
|
|
|
|
// arithmetic
|
|
c : usize = a + 8;
|
|
print("usize+8: {}\n", c);
|
|
|
|
// coercion from s32
|
|
x : s32 = 10;
|
|
y : usize = xx x;
|
|
print("s32->usize: {}\n", y);
|
|
|
|
// coercion to s64
|
|
z : s64 = xx a;
|
|
print("usize->s64: {}\n", z);
|
|
}
|
|
}
|