feat(lang): block value requires no trailing ; (Rust-style)

A block's value is now its last statement ONLY when that statement is a
trailing expression with no `;`. A trailing `;` discards the value,
leaving the block void. This makes value-vs-statement explicit and lets
the compiler reject "this block was supposed to produce a value".

Compiler:
- Parser records `Block.produces_value` (last stmt is a no-`;` trailing
  expression) + `Block.discarded_semi` (the `;` that discarded a value),
  via `expectSemicolonAfter`. A trailing expression before `}` may now
  omit its `;` (previously a parse error). Match-arm and else-arm bodies
  are built value-producing regardless of the arm `;` (arms are exempt —
  the `;` is an arm terminator).
- Lowering: `lowerBlockValue` / the block-expr path / `inferExprType`
  respect `produces_value`. A value-position block that discards its value
  is a hard error (`lowerValueBody` for function bodies; the value-context
  `.block` path for if/else branches, `catch` bodies, value bindings,
  match arms). Pure-failable `-> !` bodies (value rides the error channel)
  and a value-if whose branches are void are handled without false errors.
- `defer`/`onfail` cleanup bodies lower as statements (void), so a
  trailing `;` there is fine.

Migration (behavior-preserving — output unchanged):
- stdlib + ~210 examples: dropped the trailing `;` on value-position last
  expressions. `format` now ends with an explicit `#insert "return
  result;"` (it relied on `#insert`-as-block-value, which `;` discards).
- Two `main :: () -> s32` examples that relied on the old silent
  default-return got an explicit trailing `0`.
- Rejection snapshots 0412 / 1013 regenerated (their quoted source lines
  lost a `;`); the diagnostics themselves are unchanged.

Docs/tests: specs.md "Block values" section; examples 0040 (rules) + 0041
(rejection); 3 parser unit tests. Filed issue 0066 (pre-existing
match-arm negated-literal phi-width quirk, surfaced not caused here).

Gates: zig build, zig build test, run_examples.sh -> 343 passed,
cross_compile.sh -> 7 passed (also refreshed its stale example names).
This commit is contained in:
agra
2026-06-02 09:23:50 +03:00
parent 634cf9bc7f
commit bdd0e96d78
265 changed files with 1070 additions and 761 deletions

View File

@@ -1,5 +1,5 @@
#import "modules/std.sx"; #import "modules/std.sx";
main :: () -> s32 { main :: () -> s32 {
if false then 40 else 42; if false then 40 else 42
} }

View File

@@ -10,6 +10,7 @@ main :: () -> s32 {
print("scoped x: {}\n", x); //expect 6 print("scoped x: {}\n", x); //expect 6
} }
print("main x: {}\n", x); //expect 42 print("main x: {}\n", x); //expect 42
0
} }
// ** stdout ** // ** stdout **

View File

@@ -1,7 +1,7 @@
std :: #import "modules/std.sx"; std :: #import "modules/std.sx";
vec3 :: (x:f32, y:f32, z:f32) -> std.Vector(3, f32) { vec3 :: (x:f32, y:f32, z:f32) -> std.Vector(3, f32) {
.[x,y,z]; .[x,y,z]
} }
main :: () { main :: () {

View File

@@ -7,7 +7,7 @@ sumOf10 :: () -> s32 {
s+=i; s+=i;
i+=1; i+=1;
} }
s; s
} }
someSum :: #run sumOf10(); someSum :: #run sumOf10();

View File

@@ -14,7 +14,7 @@ quick_sort :: (items: []$T) {
} }
i += 1; i += 1;
items[i], items[hi] = items[hi], items[i]; items[i], items[hi] = items[hi], items[i];
i; i
} }
sort :: (items: []T, lo: s64, hi: s64) { sort :: (items: []T, lo: s64, hi: s64) {

View File

@@ -19,12 +19,12 @@ Vec2 :: struct {
x: f32; x: f32;
y: f32; y: f32;
create :: (x: f32, y: f32) -> Vec2 { Vec2.{ x = x, y = y }; } create :: (x: f32, y: f32) -> Vec2 { Vec2.{ x = x, y = y } }
zero :: () -> Vec2 { Vec2.{ x = 0.0, y = 0.0 }; } zero :: () -> Vec2 { Vec2.{ x = 0.0, y = 0.0 } }
unit_x :: () -> Vec2 { Vec2.{ x = 1.0, y = 0.0 }; } unit_x :: () -> Vec2 { Vec2.{ x = 1.0, y = 0.0 } }
add :: (a: Vec2, b: Vec2) -> Vec2 { Vec2.{ x = a.x + b.x, y = a.y + b.y }; } add :: (a: Vec2, b: Vec2) -> Vec2 { Vec2.{ x = a.x + b.x, y = a.y + b.y } }
scale :: (v: Vec2, s: f32) -> Vec2 { Vec2.{ x = v.x * s, y = v.y * s }; } scale :: (v: Vec2, s: f32) -> Vec2 { Vec2.{ x = v.x * s, y = v.y * s } }
len :: (v: Vec2) -> s32 { xx (v.x + v.y); } len :: (v: Vec2) -> s32 { xx (v.x + v.y) }
} }
EdgeInsets :: struct { EdgeInsets :: struct {
@@ -33,9 +33,9 @@ EdgeInsets :: struct {
bottom: f32; bottom: f32;
left: f32; left: f32;
all :: (v: f32) -> EdgeInsets { EdgeInsets.{ top = v, right = v, bottom = v, left = v }; } all :: (v: f32) -> EdgeInsets { EdgeInsets.{ top = v, right = v, bottom = v, left = v } }
symmetric :: (h: f32, v: f32) -> EdgeInsets { EdgeInsets.{ top = v, right = h, bottom = v, left = h }; } symmetric :: (h: f32, v: f32) -> EdgeInsets { EdgeInsets.{ top = v, right = h, bottom = v, left = h } }
horizontal :: (h: f32) -> EdgeInsets { EdgeInsets.{ top = 0.0, right = h, bottom = 0.0, left = h }; } horizontal :: (h: f32) -> EdgeInsets { EdgeInsets.{ top = 0.0, right = h, bottom = 0.0, left = h } }
} }
Trio :: struct { Trio :: struct {
@@ -43,8 +43,8 @@ Trio :: struct {
b: s32; b: s32;
c: s32; c: s32;
make :: (a: s32, b: s32, c: s32) -> Trio { Trio.{ a = a, b = b, c = c }; } make :: (a: s32, b: s32, c: s32) -> Trio { Trio.{ a = a, b = b, c = c } }
sum :: (t: Trio) -> s32 { t.a + t.b + t.c; } sum :: (t: Trio) -> s32 { t.a + t.b + t.c }
} }
Result :: enum { Result :: enum {
@@ -99,7 +99,7 @@ main :: () {
// T6: Return .variant(payload) from function // T6: Return .variant(payload) from function
{ {
make_shape :: (r: f32) -> Shape { .circle(r); } make_shape :: (r: f32) -> Shape { .circle(r) }
sh := make_shape(4.2); sh := make_shape(4.2);
print("T6: {}\n", sh.circle); print("T6: {}\n", sh.circle);
} }
@@ -126,7 +126,7 @@ main :: () {
case .circle: 10; case .circle: 10;
case .rect: 20; case .rect: 20;
case .none: 30; case .none: 30;
}; }
} }
print("T8a: {}\n", describe(.circle(7.0))); print("T8a: {}\n", describe(.circle(7.0)));
print("T8b: {}\n", describe(.rect(.{ 3.0, 4.0 }))); print("T8b: {}\n", describe(.rect(.{ 3.0, 4.0 })));
@@ -137,8 +137,8 @@ main :: () {
{ {
r : Result = .ok(42); r : Result = .ok(42);
ms := if r == { ms := if r == {
case .ok: (v) { v; } case .ok: (v) { v }
case .err: (e) { -1; } case .err: (e) { -1 }
}; };
print("T9: {}\n", ms); print("T9: {}\n", ms);
} }
@@ -150,7 +150,7 @@ main :: () {
case 0: .none; case 0: .none;
case 1: .circle(1.0); case 1: .circle(1.0);
else: .rect(.{ 9.0, 9.0 }); else: .rect(.{ 9.0, 9.0 });
}; }
} }
print("T10a: {}\n", if select(0) == { case .none: 1; else: 0; }); print("T10a: {}\n", if select(0) == { case .none: 1; else: 0; });
print("T10b: {}\n", select(1).circle); print("T10b: {}\n", select(1).circle);
@@ -176,7 +176,7 @@ main :: () {
// S3: Return .method(args) from function with return type // S3: Return .method(args) from function with return type
{ {
make_vec :: () -> Vec2 { .create(7.0, 8.0); } make_vec :: () -> Vec2 { .create(7.0, 8.0) }
v := make_vec(); v := make_vec();
print("S3: {} {}\n", v.x, v.y); print("S3: {} {}\n", v.x, v.y);
} }
@@ -253,7 +253,7 @@ main :: () {
// E3: Bare .variant (no parens) as function arg // E3: Bare .variant (no parens) as function arg
{ {
check_none :: (sh: Shape) -> s32 { check_none :: (sh: Shape) -> s32 {
if sh == { case .none: 1; else: 0; }; if sh == { case .none: 1; else: 0; }
} }
print("E3: {}\n", check_none(.none)); print("E3: {}\n", check_none(.none));
} }

View File

@@ -8,9 +8,9 @@
do_it :: () -> bool { do_it :: () -> bool {
inline if OS != .ios { return false; } inline if OS != .ios { return false; }
true; true
} }
main :: () -> s32 { main :: () -> s32 {
if do_it() then 0 else 1; if do_it() then 0 else 1
} }

View File

@@ -32,5 +32,5 @@ main :: () -> s32 {
print("total: {}\n", p.total()); print("total: {}\n", p.total());
print("scaled: {}\n", p.scaled(3)); print("scaled: {}\n", p.scaled(3));
0; 0
} }

View File

@@ -35,5 +35,5 @@ main :: () -> s32 {
// Inline unroll over a heterogeneous pack. // Inline unroll over a heterogeneous pack.
each(A.{ x = 1 }, B.{ s = "hi" }, A.{ x = 3 }); each(A.{ x = 1 }, B.{ s = "hi" }, A.{ x = 3 });
0; 0
} }

View File

@@ -21,5 +21,5 @@ main :: () -> s32 {
case .none: { print("none\n"); } case .none: { print("none\n"); }
} }
} }
0; 0
} }

View File

@@ -5,13 +5,13 @@
Box :: struct { Box :: struct {
v: s64; v: s64;
boxed :: (self: Box) -> s64 { self.v; } // value receiver boxed :: (self: Box) -> s64 { self.v } // value receiver
} }
sum_ptr :: (xs: *List(s64)) -> s64 { sum_ptr :: (xs: *List(s64)) -> s64 {
total : s64 = 0; total : s64 = 0;
for xs: (n) { total = total + n; } // iterate through a *List for xs: (n) { total = total + n; } // iterate through a *List
total; total
} }
main :: () -> s32 { main :: () -> s32 {
@@ -36,5 +36,5 @@ main :: () -> s32 {
bt : s64 = 0; bt : s64 = 0;
for bs: (*b) { bt = bt + b.boxed(); } // *Box receiver, value-self method for bs: (*b) { bt = bt + b.boxed(); } // *Box receiver, value-self method
print("boxes {}\n", bt); // 7 print("boxes {}\n", bt); // 7
0; 0
} }

View File

@@ -4,18 +4,18 @@
#import "modules/test.sx"; #import "modules/test.sx";
pkg :: #import "modules/testpkg"; pkg :: #import "modules/testpkg";
add :: (a: s32, b: s32) -> s32 { a + b; } add :: (a: s32, b: s32) -> s32 { a + b }
mul :: (a: s32, b: s32) -> s32 { a * b; } mul :: (a: s32, b: s32) -> s32 { a * b }
// P4 edge: Chained default→default calls // P4 edge: Chained default→default calls
Chained :: protocol { Chained :: protocol {
base :: (msg: string) -> s32; base :: (msg: string) -> s32;
wrap :: (msg: string) -> s32 { wrap :: (msg: string) -> s32 {
self.base(msg) + 1; self.base(msg) + 1
} }
double_wrap :: (msg: string) -> s32 { double_wrap :: (msg: string) -> s32 {
self.wrap(msg) + self.wrap(msg); self.wrap(msg) + self.wrap(msg)
} }
} }

View File

@@ -48,7 +48,7 @@ main :: () {
} }
// If block as expression // If block as expression
ibe := 10 + if true { 5; } else { 0; }; ibe := 10 + if true { 5 } else { 0 };
print("if-block-expr: {}\n", ibe); print("if-block-expr: {}\n", ibe);
// While basic // While basic

View File

@@ -4,24 +4,24 @@
#import "modules/test.sx"; #import "modules/test.sx";
pkg :: #import "modules/testpkg"; pkg :: #import "modules/testpkg";
add :: (a: s32, b: s32) -> s32 { a + b; } add :: (a: s32, b: s32) -> s32 { a + b }
mul :: (a: s32, b: s32) -> s32 { a * b; } mul :: (a: s32, b: s32) -> s32 { a * b }
identity :: (x: $T) -> T { x; } identity :: (x: $T) -> T { x }
pair_add :: (a: $T, b: $U) -> s64 { pair_add :: (a: $T, b: $U) -> s64 {
cast(s64) a + cast(s64) b; cast(s64) a + cast(s64) b
} }
typed_sum :: (..args: []s32) -> s32 { typed_sum :: (..args: []s32) -> s32 {
result := 0; result := 0;
for args: (it) { result = result + it; } for args: (it) { result = result + it; }
result; result
} }
apply :: (f: (s32, s32) -> s32, x: s32, y: s32) -> s32 { apply :: (f: (s32, s32) -> s32, x: s32, y: s32) -> s32 {
f(x, y); f(x, y)
} }
void_return :: () { void_return :: () {
@@ -29,12 +29,12 @@ void_return :: () {
} }
implicit_return :: (x: s32) -> s32 { implicit_return :: (x: s32) -> s32 {
x * 2; x * 2
} }
early_return :: (x: s32) -> s32 { early_return :: (x: s32) -> s32 {
if x > 10 { return 99; } if x > 10 { return 99; }
x; x
} }
main :: () { main :: () {
@@ -84,7 +84,7 @@ main :: () {
print("lambda-ret: {}\n", halve(10.0)); print("lambda-ret: {}\n", halve(10.0));
// Local function (non-lambda) // Local function (non-lambda)
local_add :: (a: s32, b: s32) -> s32 { a + b; } local_add :: (a: s32, b: s32) -> s32 { a + b }
print("local-fn: {}\n", local_add(3, 4)); print("local-fn: {}\n", local_add(3, 4));
// Nested function calls // Nested function calls

View File

@@ -19,11 +19,11 @@ main :: () {
// ======================================================== // ========================================================
print("=== 19. Local Fn Return ===\n"); print("=== 19. Local Fn Return ===\n");
{ {
local_pt :: () -> Point { Point.{42, 99}; } local_pt :: () -> Point { Point.{42, 99} }
lp := local_pt(); lp := local_pt();
print("local-struct: {} {}\n", lp.x, lp.y); print("local-struct: {} {}\n", lp.x, lp.y);
local_sh :: () -> Shape { .circle(2.5); } local_sh :: () -> Shape { .circle(2.5) }
ls := local_sh(); ls := local_sh();
print("local-enum: {}\n", ls); print("local-enum: {}\n", ls);
} }

View File

@@ -6,7 +6,7 @@ pkg :: #import "modules/testpkg";
Point :: struct { x, y: s32; } Point :: struct { x, y: s32; }
point_sum :: (p: Point) -> s32 { p.x + p.y; } point_sum :: (p: Point) -> s32 { p.x + p.y }
// #run compile-time constants // #run compile-time constants

View File

@@ -14,9 +14,9 @@ main :: () {
print("=== 22. If-Struct ===\n"); print("=== 22. If-Struct ===\n");
{ {
flag := true; flag := true;
p := if flag { Point.{10, 20}; } else { Point.{30, 40}; }; p := if flag { Point.{10, 20} } else { Point.{30, 40} };
print("if-struct: {} {}\n", p.x, p.y); print("if-struct: {} {}\n", p.x, p.y);
q := if !flag { Point.{10, 20}; } else { Point.{30, 40}; }; q := if !flag { Point.{10, 20} } else { Point.{30, 40} };
print("else-struct: {} {}\n", q.x, q.y); print("else-struct: {} {}\n", q.x, q.y);
} }
} }

View File

@@ -10,7 +10,7 @@ main :: () {
{ {
print("=== UFCS Aliases ===\n"); print("=== UFCS Aliases ===\n");
num_sum :: (a: s64, b: s64) -> s64 { a + b; } num_sum :: (a: s64, b: s64) -> s64 { a + b }
sum :: ufcs num_sum; sum :: ufcs num_sum;
print("{}\n", num_sum(40, 2)); // 42 — direct call print("{}\n", num_sum(40, 2)); // 42 — direct call
@@ -20,7 +20,7 @@ main :: () {
print("{}\n", num_sum(40, 2)); // 42 — direct (was tuple full-splat) print("{}\n", num_sum(40, 2)); // 42 — direct (was tuple full-splat)
print("{}\n", 40 |> sum(2)); // 42 — pipe (was tuple partial-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; } compute :: (a: s64, b: s64, c: s64, d: s64) -> s64 { a + b * c - d }
calc :: ufcs compute; 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)); // 1+2*3-4 = 3 (was tuple full-splat)
@@ -28,14 +28,14 @@ main :: () {
print("{}\n", 1 |> calc(2, 3, 4)); // same = 3 — pipe UFCS print("{}\n", 1 |> calc(2, 3, 4)); // same = 3 — pipe UFCS
// Tuple return type // Tuple return type
swap :: (a: s64, b: s64) -> (s64, s64) { (b, a); } swap :: (a: s64, b: s64) -> (s64, s64) { (b, a) }
s := swap(1, 2); s := swap(1, 2);
a := s.0; a := s.0;
b := s.1; b := s.1;
print("{}\n", a); // 2 print("{}\n", a); // 2
print("{}\n", b); // 1 print("{}\n", b); // 1
wrap :: (x: s64) -> (s64) { (x,); } wrap :: (x: s64) -> (s64) { (x,) }
t := wrap(99); t := wrap(99);
print("{}\n", t.0); // 99 print("{}\n", t.0); // 99
} }

View File

@@ -4,7 +4,7 @@
#import "modules/test.sx"; #import "modules/test.sx";
pkg :: #import "modules/testpkg"; pkg :: #import "modules/testpkg";
add :: (a: s32, b: s32) -> s32 { a + b; } add :: (a: s32, b: s32) -> s32 { a + b }
main :: () { main :: () {

View File

@@ -30,5 +30,5 @@ main :: () -> s32 {
// dead code after a `return` at main's own block level is dropped. // dead code after a `return` at main's own block level is dropped.
return 0; return 0;
print("unreachable\n"); print("unreachable\n")
} }

View File

@@ -0,0 +1,46 @@
// Block value rule: a block's value is its last statement ONLY when that
// statement is a trailing expression with NO `;`. A trailing `;` discards the
// value, leaving the block void. This makes value-vs-statement explicit and lets
// the compiler reject "forgot to produce a value".
//
// { … expr } → value is `expr`
// { … expr; } → void (value discarded)
//
// Match arms are exempt: the arm `;` is an arm terminator, so `case .x: expr;`
// still yields `expr` (only an explicit inner braced block follows the rule).
#import "modules/std.sx";
// Implicit return: trailing expression, no `;`.
double :: (n: s32) -> s32 { n * 2 }
// if/else as a value — each branch's last expression has no `;`.
sign :: (n: s32) -> s32 {
if n < 0 { -1 } else if n > 0 { 1 } else { 0 }
}
// A value-producing block bound to a name.
sum3 :: (a: s32, b: s32, c: s32) -> s32 {
t := { x := a + b; x + c }; // block value is `x + c`
t
}
// Match arms keep their `;` (exempt): the arm `;` is an arm terminator, so each
// arm still yields its expression as the match value.
classify :: (n: s32) -> s32 {
if n == {
case 0: 100;
case 1: 10;
else: 7;
}
}
main :: () -> s32 {
total : s32 = 0;
total = total + double(10); // 20
total = total + sign(-7); // -1
total = total + sum3(1, 2, 3); // 6
total = total + classify(1); // 10
print("block-value total: {}\n", total); // 20 - 1 + 6 + 10 = 35
total
}

View File

@@ -0,0 +1,13 @@
// Rejection counterpart to 0040: a value-position block whose last expression's
// value is discarded by a trailing `;` produces no value. A `-> T` function
// whose body ends that way is a compile error (it used to silently return a
// zero default). Drop the `;` to return the value, or use an explicit `return`.
#import "modules/std.sx";
// `n * 2;` discards the value → the function returns nothing.
double :: (n: s32) -> s32 {
n * 2;
}
main :: () -> s32 { double(5) }

View File

@@ -6,11 +6,11 @@
Handle :: u32; Handle :: u32;
ok :: () -> Handle { 0; } ok :: () -> Handle { 0 }
g : Handle = 0; g : Handle = 0;
main :: () -> s32 { main :: () -> s32 {
g = ok(); g = ok();
if g == 0 then 0 else 1; if g == 0 then 0 else 1
} }

View File

@@ -30,5 +30,5 @@ main :: () -> s32 {
print("size_of(Maybe) = {}\n", size_of(Maybe)); print("size_of(Maybe) = {}\n", size_of(Maybe));
print("size_of(Arr) = {}\n", size_of(Arr)); print("size_of(Arr) = {}\n", size_of(Arr));
print("size_of(Cb) = {}\n", size_of(Cb)); print("size_of(Cb) = {}\n", size_of(Cb));
0; 0
} }

View File

@@ -18,5 +18,5 @@ main :: () -> s32 {
print("align chain: {}\n", align_of(MyChain)); print("align chain: {}\n", align_of(MyChain));
print("size struct-alias: {}\n", size_of(WideAlias)); print("size struct-alias: {}\n", size_of(WideAlias));
print("align struct-alias:{}\n", align_of(WideAlias)); print("align struct-alias:{}\n", align_of(WideAlias));
0; 0
} }

View File

@@ -24,5 +24,5 @@ main :: () -> s32 {
invoke_fn(@b, "hello"); invoke_fn(@b, "hello");
if g_s.len == 0 { print("FAIL: empty\n"); return 1; } if g_s.len == 0 { print("FAIL: empty\n"); return 1; }
print("got: <{}>\n", g_s); print("got: <{}>\n", g_s);
0; 0
} }

View File

@@ -8,8 +8,8 @@
Box :: struct { xs: (s32, s32); } Box :: struct { xs: (s32, s32); }
swap :: (a: s64, b: s64) -> (s64, s64) { (b, a); } swap :: (a: s64, b: s64) -> (s64, s64) { (b, a) }
fst :: (t: (s64, s64)) -> s64 { t.0; } fst :: (t: (s64, s64)) -> s64 { t.0 }
main :: () -> s32 { main :: () -> s32 {
// Inferred positional tuple + numeric field access. // Inferred positional tuple + numeric field access.
@@ -51,5 +51,5 @@ main :: () -> s32 {
// typed correctly (s64 prints as a number, string as text). // typed correctly (s64 prints as a number, string as text).
mixed := (42, "hi"); mixed := (42, "hi");
print("mixed {} {}\n", mixed.0, mixed.1); print("mixed {} {}\n", mixed.0, mixed.1);
0; 0
} }

View File

@@ -21,5 +21,5 @@ main :: () -> s32 {
print("p: x={} y={} .0={}\n", p.x, p.y, p.0); print("p: x={} y={} .0={}\n", p.x, p.y, p.0);
p.0 = 33; // position write reaches the same slot as .x p.0 = 33; // position write reaches the same slot as .x
print("p.x after .0=33: {}\n", p.x); print("p.x after .0=33: {}\n", p.x);
0; 0
} }

View File

@@ -34,12 +34,12 @@ MyFloat :: f64;
Status :: enum u8 { ok; err; timeout; } Status :: enum u8 { ok; err; timeout; }
add :: (a: s32, b: s32) -> s32 { a + b; } add :: (a: s32, b: s32) -> s32 { a + b }
mul :: (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) { vec3 :: (x: f32, y: f32, z: f32) -> Vector(3, f32) {
.[x, y, z]; .[x, y, z]
} }
// Global variable for address-of test // Global variable for address-of test

View File

@@ -87,7 +87,7 @@ main :: () {
// Destructure from function return // Destructure from function return
{ {
dswap :: (a: s64, b: s64) -> (s64, s64) { (b, a); } dswap :: (a: s64, b: s64) -> (s64, s64) { (b, a) }
dx, dy := dswap(1, 2); dx, dy := dswap(1, 2);
print("fn: {} {}\n", dx, dy); print("fn: {} {}\n", dx, dy);
} }

View File

@@ -15,24 +15,24 @@ OptInner :: struct { val: s32; }
OptOuter :: struct { inner: ?OptInner; } OptOuter :: struct { inner: ?OptInner; }
add :: (a: s32, b: s32) -> s32 { a + b; } add :: (a: s32, b: s32) -> s32 { a + b }
mul :: (a: s32, b: s32) -> s32 { a * b; } mul :: (a: s32, b: s32) -> s32 { a * b }
identity :: (x: $T) -> T { x; } identity :: (x: $T) -> T { x }
apply :: (f: (s32, s32) -> s32, x: s32, y: s32) -> s32 { apply :: (f: (s32, s32) -> s32, x: s32, y: s32) -> s32 {
f(x, y); f(x, y)
} }
// P4 edge: Chained default→default calls // P4 edge: Chained default→default calls
Chained :: protocol { Chained :: protocol {
base :: (msg: string) -> s32; base :: (msg: string) -> s32;
wrap :: (msg: string) -> s32 { wrap :: (msg: string) -> s32 {
self.base(msg) + 1; self.base(msg) + 1
} }
double_wrap :: (msg: string) -> s32 { double_wrap :: (msg: string) -> s32 {
self.wrap(msg) + self.wrap(msg); self.wrap(msg) + self.wrap(msg)
} }
} }
@@ -258,8 +258,8 @@ main :: () {
{ {
check :: (v: ?s32) -> s32 { check :: (v: ?s32) -> s32 {
return if v == { return if v == {
case .some: (val) { val; } case .some: (val) { val }
case .none: { 0; } case .none: { 0 }
}; };
} }
a: ?s32 = 55; a: ?s32 = 55;
@@ -909,9 +909,9 @@ main :: () {
p_f5.on_resize(p_f5.title, 800, 600); p_f5.on_resize(p_f5.title, 800, 600);
// C5.E6: protocol value passed through multiple function calls // C5.E6: protocol value passed through multiple function calls
step3 :: (a: Allocator) -> *void { a.alloc(8); } step3 :: (a: Allocator) -> *void { a.alloc(8) }
step2 :: (a: Allocator) -> *void { step3(a); } step2 :: (a: Allocator) -> *void { step3(a) }
step1 :: (a: Allocator) -> *void { step2(a); } step1 :: (a: Allocator) -> *void { step2(a) }
gpa_e6 := GPA.init(); gpa_e6 := GPA.init();
a_e6 : Allocator = xx gpa_e6; a_e6 : Allocator = xx gpa_e6;
ptr_e6 := step1(a_e6); ptr_e6 := step1(a_e6);

View File

@@ -6,7 +6,7 @@ pkg :: #import "modules/testpkg";
Point :: struct { x, y: s32; } Point :: struct { x, y: s32; }
add :: (a: s32, b: s32) -> s32 { a + b; } add :: (a: s32, b: s32) -> s32 { a + b }
Counter :: protocol { Counter :: protocol {
inc :: (); inc :: ();
@@ -21,11 +21,11 @@ SimpleCounter :: struct { val: s32; }
impl Counter for SimpleCounter { impl Counter for SimpleCounter {
inc :: (self: *SimpleCounter) { self.val += 1; } inc :: (self: *SimpleCounter) { self.val += 1; }
get :: (self: *SimpleCounter) -> s32 { self.val; } get :: (self: *SimpleCounter) -> s32 { self.val }
} }
impl Summable for Point { impl Summable for Point {
sum :: (self: *Point) -> s32 { self.x + self.y; } sum :: (self: *Point) -> s32 { self.x + self.y }
} }
// Phase 2: #inline protocol for dynamic dispatch // Phase 2: #inline protocol for dynamic dispatch
@@ -38,7 +38,7 @@ Pair :: struct ($T: Type) {
impl Summable for Pair($T) { impl Summable for Pair($T) {
sum :: (self: *Pair(T)) -> s32 { sum :: (self: *Pair(T)) -> s32 {
xx self.a + xx self.b; xx self.a + xx self.b
} }
} }
@@ -104,7 +104,7 @@ main :: () {
// IB5: init block + auto type erasure combined // IB5: init block + auto type erasure combined
{ {
use_counter :: (c: Counter) -> s32 { c.inc(); c.inc(); c.get(); } use_counter :: (c: Counter) -> s32 { c.inc(); c.inc(); c.get() }
result := use_counter(SimpleCounter.{ val = 0 } { result := use_counter(SimpleCounter.{ val = 0 } {
self.val = 50; self.val = 50;
}); });
@@ -123,11 +123,11 @@ main :: () {
h: f32; h: f32;
create :: (w: f32, h: f32) -> Dims { create :: (w: f32, h: f32) -> Dims {
Dims.{ w = w, h = h }; Dims.{ w = w, h = h }
} }
square :: (size: f32) -> Dims { square :: (size: f32) -> Dims {
Dims.{ w = size, h = size }; Dims.{ w = size, h = size }
} }
} }
use_dims :: (d: Dims) { print("SM1: {} {}\n", d.w, d.h); } use_dims :: (d: Dims) { print("SM1: {} {}\n", d.w, d.h); }
@@ -142,7 +142,7 @@ main :: () {
b: s64; b: s64;
make :: (a: s64, b: s64) -> Pair { make :: (a: s64, b: s64) -> Pair {
Pair.{ a = a, b = b }; Pair.{ a = a, b = b }
} }
} }
p : Pair = .make(10, 20); p : Pair = .make(10, 20);

View File

@@ -18,7 +18,7 @@ Complex :: ($T:Type) -> Type {
Vec3 :: Vec(3, f32); Vec3 :: Vec(3, f32);
vec3 :: (x:f32, y:f32, z:f32) -> Vector(3,f32) { vec3 :: (x:f32, y:f32, z:f32) -> Vector(3,f32) {
.[x, y, z]; .[x, y, z]
} }
Foo :: Complex(u32); Foo :: Complex(u32);

View File

@@ -16,7 +16,7 @@ Size :: struct {
impl Lerpable for Size { impl Lerpable for Size {
lerp :: (self: Size, b: Size, t: f32) -> Size { lerp :: (self: Size, b: Size, t: f32) -> Size {
Size.{ width = self.width + (b.width - self.width) * t, Size.{ width = self.width + (b.width - self.width) * t,
height = self.height + (b.height - self.height) * t }; height = self.height + (b.height - self.height) * t }
} }
} }
@@ -32,7 +32,7 @@ Animated :: struct ($T: Lerpable) {
Animated(T).{ Animated(T).{
current = value, from = value, to = value, current = value, from = value, to = value,
elapsed = 0.0, duration = 0.0, active = false elapsed = 0.0, duration = 0.0, active = false
}; }
} }
set_immediate :: (self: *Animated(T), value: T) { set_immediate :: (self: *Animated(T), value: T) {

View File

@@ -10,9 +10,9 @@
Holder :: struct { Holder :: struct {
n: s64; n: s64;
plain :: (self: *Holder) -> s64 { self.n; } plain :: (self: *Holder) -> s64 { self.n }
sized :: (self: *Holder, $T: Type) -> s64 { size_of(T); } sized :: (self: *Holder, $T: Type) -> s64 { size_of(T) }
taking :: (self: *Holder, $T: Type, v: T) -> T { v; } taking :: (self: *Holder, $T: Type, v: T) -> T { v }
} }
main :: () -> s32 { main :: () -> s32 {
@@ -24,5 +24,5 @@ main :: () -> s32 {
print("sized s64: {}\n", h.sized(s64)); print("sized s64: {}\n", h.sized(s64));
print("taking explicit: {}\n", h.taking(s32, 42)); print("taking explicit: {}\n", h.taking(s32, 42));
print("taking inferred: {}\n", h.taking(99)); print("taking inferred: {}\n", h.taking(99));
0; 0
} }

View File

@@ -33,5 +33,5 @@ main :: () -> s32 {
if g_a != 10 { print("FAIL: g_a={}\n", g_a); return 1; } if g_a != 10 { print("FAIL: g_a={}\n", g_a); return 1; }
if g_b != 20 { print("FAIL: g_b={}\n", g_b); return 1; } if g_b != 20 { print("FAIL: g_b={}\n", g_b); return 1; }
print("generic-into-block ok: a={} b={}\n", g_a, g_b); print("generic-into-block ok: a={} b={}\n", g_a, g_b);
0; 0
} }

View File

@@ -2,7 +2,7 @@
main :: () { main :: () {
fx :: (s:s3) -> s3 { fx :: (s:s3) -> s3 {
s; s
} }
print("{}\n", fx(133)); print("{}\n", fx(133));

View File

@@ -1,10 +1,10 @@
#import "modules/std.sx"; #import "modules/std.sx";
add :: (a: s32, b: s32) -> s32 { a + b; } add :: (a: s32, b: s32) -> s32 { a + b }
mul :: (a: s32, b: s32) -> s32 { a * b; } mul :: (a: s32, b: s32) -> s32 { a * b }
apply :: (f: (s32, s32) -> s32, x: s32, y: s32) -> s32 { apply :: (f: (s32, s32) -> s32, x: s32, y: s32) -> s32 {
f(x, y); f(x, y)
} }
main :: () { main :: () {

View File

@@ -9,11 +9,11 @@ MyProtocol :: protocol {
MyImpl :: struct { value: s64; } MyImpl :: struct { value: s64; }
impl MyProtocol for MyImpl { impl MyProtocol for MyImpl {
get_value :: (self: *MyImpl) -> s64 { self.value; } get_value :: (self: *MyImpl) -> s64 { self.value }
} }
make_thing :: () -> MyProtocol { make_thing :: () -> MyProtocol {
MyImpl.{ value = 42 }; MyImpl.{ value = 42 }
} }
main :: () -> void { main :: () -> void {

View File

@@ -16,5 +16,5 @@ main :: () -> s32 {
}}; }};
c.on(.b); c.on(.b);
c.on(.a); c.on(.a);
0; 0
} }

View File

@@ -17,7 +17,7 @@ Tracer :: struct {
init :: () -> *Tracer { init :: () -> *Tracer {
t : *Tracer = xx libc_malloc(size_of(Tracer)); t : *Tracer = xx libc_malloc(size_of(Tracer));
t.count = 0; t.count = 0;
t; t
} }
} }
@@ -43,5 +43,5 @@ main :: () -> s32 {
_ = add_capture(1); _ = add_capture(1);
} }
print("Tracer.count = {}\n", tracer.count); print("Tracer.count = {}\n", tracer.count);
0; 0
} }

View File

@@ -24,5 +24,5 @@ main :: () -> s32 {
// argument-position, 3 params (s64, s64, string). // argument-position, 3 params (s64, s64, string).
print("q={}\n", apply3((a, b, c) => a + b + c.len, 1, 2, "xyz")); // 1+2+3 = 6 print("q={}\n", apply3((a, b, c) => a + b + c.len, 1, 2, "xyz")); // 1+2+3 = 6
0; 0
} }

View File

@@ -7,11 +7,11 @@ Lerpable :: protocol #inline {
} }
impl Lerpable for f32 { impl Lerpable for f32 {
lerp :: (self: f32, b: f32, t: f32) -> f32 { self + (b - self) * t; } lerp :: (self: f32, b: f32, t: f32) -> f32 { self + (b - self) * t }
} }
do_lerp :: (a: Lerpable, b: f32, t: f32) -> f32 { do_lerp :: (a: Lerpable, b: f32, t: f32) -> f32 {
a.lerp(b, t); a.lerp(b, t)
} }
main :: () -> void { main :: () -> void {

View File

@@ -10,7 +10,7 @@ Sizable :: protocol {
Widget :: struct { value: s64; } Widget :: struct { value: s64; }
impl Sizable for Widget { impl Sizable for Widget {
size :: (self: *Widget) -> s64 { self.value; } size :: (self: *Widget) -> s64 { self.value }
} }
// Wrapper struct with a protocol field (like ViewChild) // Wrapper struct with a protocol field (like ViewChild)

View File

@@ -10,7 +10,7 @@ Sizable :: protocol {
Leaf :: struct { value: s64; } Leaf :: struct { value: s64; }
impl Sizable for Leaf { impl Sizable for Leaf {
size :: (self: *Leaf) -> s64 { self.value; } size :: (self: *Leaf) -> s64 { self.value }
} }
add :: (items: *List(Sizable), w: Leaf) { add :: (items: *List(Sizable), w: Leaf) {

View File

@@ -10,7 +10,7 @@ Sizable :: protocol {
Leaf :: struct { value: s64; } Leaf :: struct { value: s64; }
impl Sizable for Leaf { impl Sizable for Leaf {
size :: (self: *Leaf) -> s64 { self.value; } size :: (self: *Leaf) -> s64 { self.value }
} }
add :: (items: *List(Sizable), w: Leaf) { add :: (items: *List(Sizable), w: Leaf) {

View File

@@ -13,18 +13,18 @@ Drawable :: protocol {
Circle :: struct { radius: s32; } Circle :: struct { radius: s32; }
impl Drawable for Circle { impl Drawable for Circle {
draw :: (self: *Circle) -> s32 { self.radius; } draw :: (self: *Circle) -> s32 { self.radius }
name :: (self: *Circle) -> string { "circle"; } name :: (self: *Circle) -> string { "circle" }
layout :: (self: *Circle, x: s32) -> s32 { x + self.radius; } layout :: (self: *Circle, x: s32) -> s32 { x + self.radius }
handle :: (self: *Circle, event: s32) -> bool { event > 0; } handle :: (self: *Circle, event: s32) -> bool { event > 0 }
} }
Square :: struct { side: s32; } Square :: struct { side: s32; }
impl Drawable for Square { impl Drawable for Square {
draw :: (self: *Square) -> s32 { self.side * self.side; } draw :: (self: *Square) -> s32 { self.side * self.side }
name :: (self: *Square) -> string { "square"; } name :: (self: *Square) -> string { "square" }
layout :: (self: *Square, x: s32) -> s32 { x + self.side; } layout :: (self: *Square, x: s32) -> s32 { x + self.side }
handle :: (self: *Square, event: s32) -> bool { event > 1; } handle :: (self: *Square, event: s32) -> bool { event > 1 }
} }
Rect :: struct { Rect :: struct {
@@ -32,7 +32,7 @@ Rect :: struct {
y: f32; y: f32;
w: f32; w: f32;
h: f32; h: f32;
zero :: () -> Rect { Rect.{ x = 0.0, y = 0.0, w = 0.0, h = 0.0 }; } zero :: () -> Rect { Rect.{ x = 0.0, y = 0.0, w = 0.0, h = 0.0 } }
} }
Container :: struct { Container :: struct {

View File

@@ -19,7 +19,7 @@ impl Proto for Impl {
take :: (f: Fmt) -> s64 { take :: (f: Fmt) -> s64 {
n : s64 = xx f; n : s64 = xx f;
n; n
} }
main :: () -> s32 { main :: () -> s32 {
@@ -28,5 +28,5 @@ main :: () -> s32 {
p : Proto = xx @Impl.{}; p : Proto = xx @Impl.{};
p.take_fmt(.b); p.take_fmt(.b);
p.take_fmt(.a); p.take_fmt(.a);
0; 0
} }

View File

@@ -16,7 +16,7 @@ Impl :: struct {
impl Proto for Impl { impl Proto for Impl {
get :: (self: *Impl) -> *u8 { get :: (self: *Impl) -> *u8 {
@self.val; @self.val
} }
} }
@@ -26,5 +26,5 @@ main :: () -> s32 {
raw : *u8 = p.get(); raw : *u8 = p.get();
addr_word : u64 = xx raw; addr_word : u64 = xx raw;
print("got pointer: {}\n", addr_word != 0); print("got pointer: {}\n", addr_word != 0);
0; 0
} }

View File

@@ -10,11 +10,11 @@ MyTag :: struct { value: s64 = 0; }
impl Into(MyTag) for s64 { impl Into(MyTag) for s64 {
convert :: (self: s64) -> MyTag { convert :: (self: s64) -> MyTag {
.{ value = self }; .{ value = self }
} }
} }
main :: () -> s32 { main :: () -> s32 {
print("ok\n"); print("ok\n");
0; 0
} }

View File

@@ -12,7 +12,7 @@ GPU :: protocol {
Impl :: struct {} Impl :: struct {}
impl GPU for Impl { impl GPU for Impl {
ping :: (self: *Impl) -> s64 { 42; } ping :: (self: *Impl) -> s64 { 42 }
} }
main :: () -> s32 { main :: () -> s32 {
@@ -30,5 +30,5 @@ main :: () -> s32 {
} else { } else {
print("BAD: g still null after assign\n"); print("BAD: g still null after assign\n");
} }
0; 0
} }

View File

@@ -26,5 +26,5 @@ main :: () -> s32 {
print("alloc_count: {}\n", gpa.alloc_count); print("alloc_count: {}\n", gpa.alloc_count);
0; 0
} }

View File

@@ -5,6 +5,6 @@
impl Into(Wrap) for s64 { impl Into(Wrap) for s64 {
convert :: (self: s64) -> Wrap { convert :: (self: s64) -> Wrap {
.{ v = self * 10 }; .{ v = self * 10 }
} }
} }

View File

@@ -6,5 +6,5 @@
run_user :: () -> s32 { run_user :: () -> s32 {
w : Wrap = xx 7; w : Wrap = xx 7;
print("user: w.v = {}\n", w.v); print("user: w.v = {}\n", w.v);
0; 0
} }

View File

@@ -18,4 +18,4 @@
#import "./0410-protocols-impl-visibility-impl.sx"; #import "./0410-protocols-impl-visibility-impl.sx";
#import "./0410-protocols-impl-visibility-user.sx"; #import "./0410-protocols-impl-visibility-user.sx";
main :: () -> s32 { run_user(); } main :: () -> s32 { run_user() }

View File

@@ -4,6 +4,6 @@
impl Into(Wrap) for s64 { impl Into(Wrap) for s64 {
convert :: (self: s64) -> Wrap { convert :: (self: s64) -> Wrap {
.{ v = self * 10 }; .{ v = self * 10 }
} }
} }

View File

@@ -4,6 +4,6 @@
impl Into(Wrap) for s64 { impl Into(Wrap) for s64 {
convert :: (self: s64) -> Wrap { convert :: (self: s64) -> Wrap {
.{ v = self + 100 }; .{ v = self + 100 }
} }
} }

View File

@@ -19,5 +19,5 @@
main :: () -> s32 { main :: () -> s32 {
w : Wrap = xx 7; w : Wrap = xx 7;
print("w.v = {}\n", w.v); print("w.v = {}\n", w.v);
0; 0
} }

View File

@@ -9,11 +9,11 @@
MyA :: struct { v: s64 = 0; } MyA :: struct { v: s64 = 0; }
impl Into(MyA) for s64 { impl Into(MyA) for s64 {
convert :: (self: s64) -> MyA { .{ v = self }; } convert :: (self: s64) -> MyA { .{ v = self } }
} }
impl Into(MyA) for s64 { impl Into(MyA) for s64 {
convert :: (self: s64) -> MyA { .{ v = self * 2 }; } convert :: (self: s64) -> MyA { .{ v = self * 2 } }
} }
main :: () -> s32 { 0; } main :: () -> s32 { 0 }

View File

@@ -18,5 +18,5 @@ main :: () -> s32 {
b : VL(string) = xx StrCell.{ s = "hi" }; b : VL(string) = xx StrCell.{ s = "hi" };
print("b.get={}\n", b.get()); // hi (T = string) print("b.get={}\n", b.get()); // hi (T = string)
0; 0
} }

View File

@@ -29,5 +29,5 @@ make :: (..sources: VL) -> VL(s64) {
main :: () -> s32 { main :: () -> s32 {
r := make(IntCell.{ v = 1 }); r := make(IntCell.{ v = 1 });
print("{}\n", r.get()); // 99 (dispatch through the erased Combined) print("{}\n", r.get()); // 99 (dispatch through the erased Combined)
0; 0
} }

View File

@@ -49,24 +49,24 @@ WindowFlags :: enum flags u32 { vsync :: 64; resizable :: 4; hidden :: 128; }
// --- Top-level functions --- // --- Top-level functions ---
add :: (a: s32, b: s32) -> s32 { a + b; } add :: (a: s32, b: s32) -> s32 { a + b }
mul :: (a: s32, b: s32) -> s32 { a * b; } mul :: (a: s32, b: s32) -> s32 { a * b }
identity :: (x: $T) -> T { x; } identity :: (x: $T) -> T { x }
pair_add :: (a: $T, b: $U) -> s64 { pair_add :: (a: $T, b: $U) -> s64 {
cast(s64) a + cast(s64) b; cast(s64) a + cast(s64) b
} }
typed_sum :: (..args: []s32) -> s32 { typed_sum :: (..args: []s32) -> s32 {
result := 0; result := 0;
for args: (it) { result = result + it; } for args: (it) { result = result + it; }
result; result
} }
apply :: (f: (s32, s32) -> s32, x: s32, y: s32) -> s32 { apply :: (f: (s32, s32) -> s32, x: s32, y: s32) -> s32 {
f(x, y); f(x, y)
} }
void_return :: () { void_return :: () {
@@ -74,19 +74,19 @@ void_return :: () {
} }
implicit_return :: (x: s32) -> s32 { implicit_return :: (x: s32) -> s32 {
x * 2; x * 2
} }
early_return :: (x: s32) -> s32 { early_return :: (x: s32) -> s32 {
if x > 10 { return 99; } if x > 10 { return 99; }
x; x
} }
vec3 :: (x: f32, y: f32, z: f32) -> Vector(3, f32) { vec3 :: (x: f32, y: f32, z: f32) -> Vector(3, f32) {
.[x, y, z]; .[x, y, z]
} }
point_sum :: (p: Point) -> s32 { p.x + p.y; } point_sum :: (p: Point) -> s32 { p.x + p.y }
// #run compile-time constants // #run compile-time constants
@@ -215,11 +215,11 @@ SimpleCounter :: struct { val: s32; }
impl Counter for SimpleCounter { impl Counter for SimpleCounter {
inc :: (self: *SimpleCounter) { self.val += 1; } inc :: (self: *SimpleCounter) { self.val += 1; }
get :: (self: *SimpleCounter) -> s32 { self.val; } get :: (self: *SimpleCounter) -> s32 { self.val }
} }
impl Summable for Point { impl Summable for Point {
sum :: (self: *Point) -> s32 { self.x + self.y; } sum :: (self: *Point) -> s32 { self.x + self.y }
} }
// Phase 2: #inline protocol for dynamic dispatch // Phase 2: #inline protocol for dynamic dispatch
@@ -236,14 +236,14 @@ Accumulator :: struct {
impl Adder for Accumulator { impl Adder for Accumulator {
add :: (self: *Accumulator, n: s32) { self.total += n; } add :: (self: *Accumulator, n: s32) { self.total += n; }
value :: (self: *Accumulator) -> s32 { self.total; } value :: (self: *Accumulator) -> s32 { self.total }
} }
Doubler :: struct { val: s32; } Doubler :: struct { val: s32; }
impl Adder for Doubler { impl Adder for Doubler {
add :: (self: *Doubler, n: s32) { self.val = self.val + n + n; } add :: (self: *Doubler, n: s32) { self.val = self.val + n + n; }
value :: (self: *Doubler) -> s32 { self.val; } value :: (self: *Doubler) -> s32 { self.val }
} }
// Phase 4: default methods // Phase 4: default methods
@@ -272,10 +272,10 @@ impl Repeater for Printer {
Chained :: protocol { Chained :: protocol {
base :: (msg: string) -> s32; base :: (msg: string) -> s32;
wrap :: (msg: string) -> s32 { wrap :: (msg: string) -> s32 {
self.base(msg) + 1; self.base(msg) + 1
} }
double_wrap :: (msg: string) -> s32 { double_wrap :: (msg: string) -> s32 {
self.wrap(msg) + self.wrap(msg); self.wrap(msg) + self.wrap(msg)
} }
} }
@@ -283,7 +283,7 @@ ChainImpl :: struct { val: s32; }
impl Chained for ChainImpl { impl Chained for ChainImpl {
base :: (self: *ChainImpl, msg: string) -> s32 { base :: (self: *ChainImpl, msg: string) -> s32 {
self.val += 1; self.val += 1;
msg.len; msg.len
} }
} }
@@ -296,7 +296,7 @@ Eq :: protocol {
impl Eq for Point { impl Eq for Point {
eq :: (self: *Point, other: Point) -> bool { eq :: (self: *Point, other: Point) -> bool {
self.x == other.x and self.y == other.y; self.x == other.x and self.y == other.y
} }
} }
@@ -306,13 +306,13 @@ Cloneable :: protocol {
impl Cloneable for Point { impl Cloneable for Point {
clone :: (self: *Point) -> Point { clone :: (self: *Point) -> Point {
Point.{ x = self.x, y = self.y }; Point.{ x = self.x, y = self.y }
} }
} }
impl Eq for s64 { impl Eq for s64 {
eq :: (self: *s64, other: s64) -> bool { eq :: (self: *s64, other: s64) -> bool {
self.* == other; self.* == other
} }
} }
@@ -320,7 +320,7 @@ impl Eq for s64 {
// Phase 6: Generic constraints // Phase 6: Generic constraints
are_equal :: ($T: Type/Eq, a: T, b: T) -> bool { are_equal :: ($T: Type/Eq, a: T, b: T) -> bool {
a.eq(b); a.eq(b)
} }
Hashable :: protocol { Hashable :: protocol {
@@ -329,20 +329,20 @@ Hashable :: protocol {
impl Hashable for Point { impl Hashable for Point {
hash :: (self: *Point) -> s64 { hash :: (self: *Point) -> s64 {
xx self.x * 31 + xx self.y; xx self.x * 31 + xx self.y
} }
} }
eq_and_hash :: ($T: Type/Eq/Hashable, a: T, b: T) -> bool { eq_and_hash :: ($T: Type/Eq/Hashable, a: T, b: T) -> bool {
if a.hash() != b.hash() { return false; } if a.hash() != b.hash() { return false; }
a.eq(b); a.eq(b)
} }
// P6.4: inline constraint syntax ($T/Protocol) // P6.4: inline constraint syntax ($T/Protocol)
// P6.4: inline constraint syntax ($T/Protocol) // P6.4: inline constraint syntax ($T/Protocol)
sum_of_inline :: (a: $T/Summable, b: T) -> s32 { sum_of_inline :: (a: $T/Summable, b: T) -> s32 {
a.sum() + b.sum(); a.sum() + b.sum()
} }
// Phase 7: Generic struct impls // Phase 7: Generic struct impls
@@ -355,7 +355,7 @@ Pair :: struct ($T: Type) {
impl Summable for Pair($T) { impl Summable for Pair($T) {
sum :: (self: *Pair(T)) -> s32 { sum :: (self: *Pair(T)) -> s32 {
xx self.a + xx self.b; xx self.a + xx self.b
} }
} }
@@ -435,7 +435,7 @@ main :: () {
{ {
use_adder :: (a: Adder, n: s32) -> s32 { use_adder :: (a: Adder, n: s32) -> s32 {
a.add(n); a.add(n);
a.value(); a.value()
} }
acc := Accumulator.{ total = 100 }; acc := Accumulator.{ total = 100 };
result := use_adder(xx @acc, 50); result := use_adder(xx @acc, 50);
@@ -470,7 +470,7 @@ main :: () {
use_counter :: (c: Counter) -> s32 { use_counter :: (c: Counter) -> s32 {
c.inc(); c.inc();
c.inc(); c.inc();
c.get(); c.get()
} }
sc := SimpleCounter.{ val = 10 }; sc := SimpleCounter.{ val = 10 };
result := use_counter(xx @sc); result := use_counter(xx @sc);
@@ -603,14 +603,14 @@ main :: () {
// P2.7: xx on inline struct literal (no intermediate variable) // P2.7: xx on inline struct literal (no intermediate variable)
{ {
use_adder :: (a: Adder) -> s32 { a.add(10); a.value(); } use_adder :: (a: Adder) -> s32 { a.add(10); a.value() }
result := use_adder(xx Accumulator.{ total = 5 }); result := use_adder(xx Accumulator.{ total = 5 });
print("P2.7: {}\n", result); print("P2.7: {}\n", result);
} }
// P3.3: xx on inline struct literal with vtable protocol // P3.3: xx on inline struct literal with vtable protocol
{ {
use_counter :: (c: Counter) -> s32 { c.inc(); c.inc(); c.get(); } use_counter :: (c: Counter) -> s32 { c.inc(); c.inc(); c.get() }
result := use_counter(xx SimpleCounter.{ val = 100 }); result := use_counter(xx SimpleCounter.{ val = 100 });
print("P3.3: {}\n", result); print("P3.3: {}\n", result);
} }

View File

@@ -6,7 +6,7 @@ pkg :: #import "modules/testpkg";
Point :: struct { x, y: s32; } Point :: struct { x, y: s32; }
add :: (a: s32, b: s32) -> s32 { a + b; } add :: (a: s32, b: s32) -> s32 { a + b }
Counter :: protocol { Counter :: protocol {
inc :: (); inc :: ();
@@ -21,11 +21,11 @@ SimpleCounter :: struct { val: s32; }
impl Counter for SimpleCounter { impl Counter for SimpleCounter {
inc :: (self: *SimpleCounter) { self.val += 1; } inc :: (self: *SimpleCounter) { self.val += 1; }
get :: (self: *SimpleCounter) -> s32 { self.val; } get :: (self: *SimpleCounter) -> s32 { self.val }
} }
impl Summable for Point { impl Summable for Point {
sum :: (self: *Point) -> s32 { self.x + self.y; } sum :: (self: *Point) -> s32 { self.x + self.y }
} }
// Phase 2: #inline protocol for dynamic dispatch // Phase 2: #inline protocol for dynamic dispatch
@@ -42,7 +42,7 @@ Accumulator :: struct {
impl Adder for Accumulator { impl Adder for Accumulator {
add :: (self: *Accumulator, n: s32) { self.total += n; } add :: (self: *Accumulator, n: s32) { self.total += n; }
value :: (self: *Accumulator) -> s32 { self.total; } value :: (self: *Accumulator) -> s32 { self.total }
} }
main :: () { main :: () {
@@ -52,7 +52,7 @@ main :: () {
// AE1: function argument — concrete passed where protocol expected (no xx) // AE1: function argument — concrete passed where protocol expected (no xx)
{ {
use_counter :: (c: Counter) -> s32 { c.inc(); c.inc(); c.get(); } use_counter :: (c: Counter) -> s32 { c.inc(); c.inc(); c.get() }
sc := SimpleCounter.{ val = 10 }; sc := SimpleCounter.{ val = 10 };
result := use_counter(sc); result := use_counter(sc);
print("AE1: {}\n", result); print("AE1: {}\n", result);
@@ -69,14 +69,14 @@ main :: () {
// AE3: struct literal passed directly (no xx) // AE3: struct literal passed directly (no xx)
{ {
use_counter :: (c: Counter) -> s32 { c.inc(); c.inc(); c.get(); } use_counter :: (c: Counter) -> s32 { c.inc(); c.inc(); c.get() }
result := use_counter(SimpleCounter.{ val = 100 }); result := use_counter(SimpleCounter.{ val = 100 });
print("AE3: {}\n", result); print("AE3: {}\n", result);
} }
// AE4: explicit xx still works (not broken) // AE4: explicit xx still works (not broken)
{ {
use_counter :: (c: Counter) -> s32 { c.inc(); c.get(); } use_counter :: (c: Counter) -> s32 { c.inc(); c.get() }
result := use_counter(xx SimpleCounter.{ val = 50 }); result := use_counter(xx SimpleCounter.{ val = 50 });
print("AE4: {}\n", result); print("AE4: {}\n", result);
} }

View File

@@ -5,7 +5,7 @@ sum :: (..args: []s32) -> s32 {
for args: (it) { for args: (it) {
result = result + it; result = result + it;
} }
result; result
} }
print_all :: (..args: []s32) { print_all :: (..args: []s32) {
@@ -31,5 +31,5 @@ main :: () -> s32 {
out(" "); out(" ");
} }
out("\n"); out("\n");
0; 0
} }

View File

@@ -29,7 +29,7 @@ print_any :: (..args: []Any) {
} }
count :: (..args: []Any) -> s32 { count :: (..args: []Any) -> s32 {
args.len; args.len
} }
main :: () -> s32 { main :: () -> s32 {
@@ -43,5 +43,5 @@ main :: () -> s32 {
out(int_to_string(count(1, 2, 3))); out(int_to_string(count(1, 2, 3)));
out("\n"); out("\n");
0; 0
} }

View File

@@ -34,7 +34,7 @@ impl Into(Block) for Closure(..$args) -> $R {
descriptor = xx @__sx_block_descriptor, descriptor = xx @__sx_block_descriptor,
sx_env = self.env, sx_env = self.env,
sx_fn = self.fn_ptr, sx_fn = self.fn_ptr,
}; }
} }
} }

View File

@@ -35,5 +35,5 @@ main :: () -> s32 {
print("n0={}\n", howmany()); // empty pack print("n0={}\n", howmany()); // empty pack
print("n2={}\n", howmany(a, b)); // two elements print("n2={}\n", howmany(a, b)); // two elements
print("n3={}\n", howmany(a, b, c)); // heterogeneous: IntBox, IntBox, StrBox print("n3={}\n", howmany(a, b, c)); // heterogeneous: IntBox, IntBox, StrBox
0; 0
} }

View File

@@ -20,5 +20,5 @@ main :: () -> s32 {
a := IntBox.{ v = 1 }; a := IntBox.{ v = 1 };
n := Naked.{ x = 2 }; n := Naked.{ x = 2 };
print("{}\n", howmany(a, n)); // `n` does not conform to Show print("{}\n", howmany(a, n)); // `n` does not conform to Show
0; 0
} }

View File

@@ -27,5 +27,5 @@ main :: () -> s32 {
print("dog+cat={}\n", pair_sum(d, c)); // 3 + 900 = 903 (heterogeneous) print("dog+cat={}\n", pair_sum(d, c)); // 3 + 900 = 903 (heterogeneous)
print("cat+dog={}\n", pair_sum(c, d)); // 900 + 3 = 903 (order swapped) print("cat+dog={}\n", pair_sum(c, d)); // 900 + 3 = 903 (order swapped)
print("dog+dog={}\n", pair_sum(d, Dog.{ age = 4 })); // 3 + 4 = 7 print("dog+dog={}\n", pair_sum(d, Dog.{ age = 4 })); // 3 + 4 = 7
0; 0
} }

View File

@@ -26,5 +26,5 @@ describe :: (..xs: Box) -> void {
main :: () -> s32 { main :: () -> s32 {
describe(IntCell.{ v = 11 }, StrCell.{ s = "hi" }); describe(IntCell.{ v = 11 }, StrCell.{ s = "hi" });
describe(StrCell.{ s = "x" }, IntCell.{ v = 99 }); describe(StrCell.{ s = "x" }, IntCell.{ v = 99 });
0; 0
} }

View File

@@ -18,5 +18,5 @@ leak :: (..xs: Box) -> s64 {
main :: () -> s32 { main :: () -> s32 {
print("{}\n", leak(IntCell.{ v = 5 })); print("{}\n", leak(IntCell.{ v = 5 }));
0; 0
} }

View File

@@ -24,5 +24,5 @@ show :: (..xs: Box) -> void {
main :: () -> s32 { main :: () -> s32 {
show(IntCell.{ v = 42 }, StrCell.{ s = "hi" }); show(IntCell.{ v = 42 }, StrCell.{ s = "hi" });
show(StrCell.{ s = "x" }, IntCell.{ v = 7 }); // order swapped → (string, s64) show(StrCell.{ s = "x" }, IntCell.{ v = 7 }); // order swapped → (string, s64)
0; 0
} }

View File

@@ -22,5 +22,5 @@ via3 :: (..xs: Box) -> s64 { return add3(..xs.get); }
main :: () -> s32 { main :: () -> s32 {
print("two={}\n", via2(IntCell.{ v = 10 }, Dbl.{ n = 5 })); // 10 + 10 = 20 print("two={}\n", via2(IntCell.{ v = 10 }, Dbl.{ n = 5 })); // 10 + 10 = 20
print("three={}\n", via3(Dbl.{ n = 1 }, IntCell.{ v = 2 }, Dbl.{ n = 3 })); // 2 + 2 + 6 = 10 print("three={}\n", via3(Dbl.{ n = 1 }, IntCell.{ v = 2 }, Dbl.{ n = 3 })); // 2 + 2 + 6 = 10
0; 0
} }

View File

@@ -21,5 +21,5 @@ snapshot :: (..xs: Box) -> void {
main :: () -> s32 { main :: () -> s32 {
snapshot(IntCell.{ v = 42 }, StrCell.{ s = "hi" }); snapshot(IntCell.{ v = 42 }, StrCell.{ s = "hi" });
snapshot(StrCell.{ s = "x" }, IntCell.{ v = 7 }); // order swapped → (string, s64) snapshot(StrCell.{ s = "x" }, IntCell.{ v = 7 }); // order swapped → (string, s64)
0; 0
} }

View File

@@ -34,5 +34,5 @@ fold :: (..xs: Box) -> s64 {
main :: () -> s32 { main :: () -> s32 {
snap(IntCell.{ v = 42 }, StrCell.{ s = "hi" }); // (s64, string) snap(IntCell.{ v = 42 }, StrCell.{ s = "hi" }); // (s64, string)
print("fold={}\n", fold(IntCell.{ v = 10 }, Dbl.{ n = 5 })); // 10 + 10 = 20 print("fold={}\n", fold(IntCell.{ v = 10 }, Dbl.{ n = 5 })); // 10 + 10 = 20
0; 0
} }

View File

@@ -27,5 +27,5 @@ each :: (..xs: []Show) -> void {
main :: () -> s32 { main :: () -> s32 {
each(A.{ x = 1 }, B.{ s = "hi" }, A.{ x = 3 }); // heterogeneous, erased to Show each(A.{ x = 1 }, B.{ s = "hi" }, A.{ x = 3 }); // heterogeneous, erased to Show
each(); // empty is fine (len 0) each(); // empty is fine (len 0)
0; 0
} }

View File

@@ -21,5 +21,5 @@ main :: () -> s32 {
call(A.{}); call(A.{});
_ = ret(A.{}); _ = ret(A.{});
iter(A.{}); iter(A.{});
0; 0
} }

View File

@@ -28,5 +28,5 @@ fwd_show :: (..xs: Show) -> s64 { return show_all(xx xs); }
main :: () -> s32 { main :: () -> s32 {
print("any={}\n", fwd_any(1, "hi", 2.5)); // 3 print("any={}\n", fwd_any(1, "hi", 2.5)); // 3
print("show={}\n", fwd_show(A.{}, B.{ s = "x" }, A.{})); // A B A, 3 print("show={}\n", fwd_show(A.{}, B.{ s = "x" }, A.{})); // A B A, 3
0; 0
} }

View File

@@ -21,5 +21,5 @@ main :: () -> s32 {
b : Box(bool, string, bool) = ---; // Ts=[string, bool], pair: (string, bool) b : Box(bool, string, bool) = ---; // Ts=[string, bool], pair: (string, bool)
b.pair = ("x", true); b.pair = ("x", true);
print("b: 0={} 1={}\n", b.pair.0, b.pair.1); print("b: 0={} 1={}\n", b.pair.0, b.pair.1);
0; 0
} }

View File

@@ -25,5 +25,5 @@ main :: () -> s32 {
c.sources = (xx IntCell.{ v = 10 }, xx StrCell.{ s = "hi" }); c.sources = (xx IntCell.{ v = 10 }, xx StrCell.{ s = "hi" });
c.value = 99; c.value = 99;
print("{} {} {}\n", c.sources.0.get(), c.sources.1.get(), c.value); // 10 hi 99 print("{} {} {}\n", c.sources.0.get(), c.sources.1.get(), c.value); // 10 hi 99
0; 0
} }

View File

@@ -23,5 +23,5 @@ make :: (..sources: VL) -> s64 {
main :: () -> s32 { main :: () -> s32 {
print("{}\n", make(IntCell.{ v = 7 })); // 7 print("{}\n", make(IntCell.{ v = 7 })); // 7
0; 0
} }

View File

@@ -24,5 +24,5 @@ build :: (..sources: VL) -> void {
main :: () -> s32 { main :: () -> s32 {
build(IntCell.{ v = 10 }, StrCell.{ s = "hi" }); // 10 hi build(IntCell.{ v = 10 }, StrCell.{ s = "hi" }); // 10 hi
0; 0
} }

View File

@@ -14,5 +14,5 @@ apply :: (mapper: Closure(s64, s64) -> s64, ..sources: VL) -> s64 {
main :: () -> s32 { main :: () -> s32 {
print("{}\n", apply((a, b) => a + b, IntCell.{ v = 40 }, IntCell.{ v = 2 })); // 42 print("{}\n", apply((a, b) => a + b, IntCell.{ v = 40 }, IntCell.{ v = 2 })); // 42
0; 0
} }

View File

@@ -32,5 +32,5 @@ map :: (mapper: Closure(..sources.T) -> $R, ..sources: VL) -> VL($R) {
main :: () -> s32 { main :: () -> s32 {
r := map((a, b) => a + b, IntCell.{ v = 40 }, IntCell.{ v = 2 }); r := map((a, b) => a + b, IntCell.{ v = 40 }, IntCell.{ v = 2 });
print("{}\n", r.get()); // 42 print("{}\n", r.get()); // 42
0; 0
} }

View File

@@ -2,7 +2,7 @@
#import "modules/math"; #import "modules/math";
test :: () -> s32 { test :: () -> s32 {
0; 0
} }
Vec4 :: Vector(4,f32); Vec4 :: Vector(4,f32);

View File

@@ -15,12 +15,12 @@ R :: struct { x: s32; }
bug :: (cmd: [:0]u8) -> ?R { bug :: (cmd: [:0]u8) -> ?R {
f := popen(cmd, "r"); f := popen(cmd, "r");
if cast(s64) f == 0 { return null; } if cast(s64) f == 0 { return null; }
R.{ x = 1 }; R.{ x = 1 }
} }
post_link :: () -> bool { post_link :: () -> bool {
if r := bug("echo hi") { puts("ok"); } else { puts("null"); } if r := bug("echo hi") { puts("ok"); } else { puts("null"); }
true; true
} }
configure :: () { configure :: () {

View File

@@ -17,7 +17,7 @@ cb :: () -> bool {
puts("2-arg ok"); puts("2-arg ok");
c := format("{} {} {}", "x", "y", "z"); c := format("{} {} {}", "x", "y", "z");
puts("3-arg ok"); puts("3-arg ok");
true; true
} }
configure :: () { configure :: () {

View File

@@ -35,7 +35,7 @@ sum_bytes :: (buf: [*]u8) -> s64 {
s : s64 = 0; s : s64 = 0;
i : s64 = 0; i : s64 = 0;
while i < BUF_SIZE { s += xx buf[i]; i += 1; } while i < BUF_SIZE { s += xx buf[i]; i += 1; }
s; s
} }
run_u8 :: () -> s64 { run_u8 :: () -> s64 {
@@ -45,7 +45,7 @@ run_u8 :: () -> s64 {
p.* = 0x42; p.* = 0x42;
s := sum_bytes(buf); s := sum_bytes(buf);
free(xx buf); free(xx buf);
s; s
} }
run_u16 :: () -> s64 { run_u16 :: () -> s64 {
@@ -55,7 +55,7 @@ run_u16 :: () -> s64 {
p.* = 0x0102; p.* = 0x0102;
s := sum_bytes(buf); s := sum_bytes(buf);
free(xx buf); free(xx buf);
s; s
} }
run_u32 :: () -> s64 { run_u32 :: () -> s64 {
@@ -65,7 +65,7 @@ run_u32 :: () -> s64 {
p.* = 0x01020304; p.* = 0x01020304;
s := sum_bytes(buf); s := sum_bytes(buf);
free(xx buf); free(xx buf);
s; s
} }
run_u64 :: () -> s64 { run_u64 :: () -> s64 {
@@ -75,7 +75,7 @@ run_u64 :: () -> s64 {
p.* = 0x0102030405060708; p.* = 0x0102030405060708;
s := sum_bytes(buf); s := sum_bytes(buf);
free(xx buf); free(xx buf);
s; s
} }
run_s8 :: () -> s64 { run_s8 :: () -> s64 {
@@ -85,7 +85,7 @@ run_s8 :: () -> s64 {
p.* = 0x42; p.* = 0x42;
s := sum_bytes(buf); s := sum_bytes(buf);
free(xx buf); free(xx buf);
s; s
} }
run_s16 :: () -> s64 { run_s16 :: () -> s64 {
@@ -95,7 +95,7 @@ run_s16 :: () -> s64 {
p.* = 0x0102; p.* = 0x0102;
s := sum_bytes(buf); s := sum_bytes(buf);
free(xx buf); free(xx buf);
s; s
} }
run_s32 :: () -> s64 { run_s32 :: () -> s64 {
@@ -105,7 +105,7 @@ run_s32 :: () -> s64 {
p.* = 0x01020304; p.* = 0x01020304;
s := sum_bytes(buf); s := sum_bytes(buf);
free(xx buf); free(xx buf);
s; s
} }
run_s64 :: () -> s64 { run_s64 :: () -> s64 {
@@ -115,7 +115,7 @@ run_s64 :: () -> s64 {
p.* = 0x0102030405060708; p.* = 0x0102030405060708;
s := sum_bytes(buf); s := sum_bytes(buf);
free(xx buf); free(xx buf);
s; s
} }
run_bool :: () -> s64 { run_bool :: () -> s64 {
@@ -125,7 +125,7 @@ run_bool :: () -> s64 {
p.* = true; p.* = true;
s := sum_bytes(buf); s := sum_bytes(buf);
free(xx buf); free(xx buf);
s; s
} }
run_f32 :: () -> s64 { run_f32 :: () -> s64 {
@@ -135,7 +135,7 @@ run_f32 :: () -> s64 {
p.* = 1.0; p.* = 1.0;
s := sum_bytes(buf); s := sum_bytes(buf);
free(xx buf); free(xx buf);
s; s
} }
run_f64 :: () -> s64 { run_f64 :: () -> s64 {
@@ -145,7 +145,7 @@ run_f64 :: () -> s64 {
p.* = 1.0; p.* = 1.0;
s := sum_bytes(buf); s := sum_bytes(buf);
free(xx buf); free(xx buf);
s; s
} }
// ── comptime-baked expected checksums ─────────────────────────────── // ── comptime-baked expected checksums ───────────────────────────────
@@ -169,7 +169,7 @@ EXP_F64 :: #run run_f64();
check :: (label: string, got: s64, want: s64) -> bool { check :: (label: string, got: s64, want: s64) -> bool {
if got == want { return true; } if got == want { return true; }
print("FAIL {}: comptime={} runtime={}\n", label, want, got); print("FAIL {}: comptime={} runtime={}\n", label, want, got);
false; false
} }
main :: () -> s32 { main :: () -> s32 {

View File

@@ -4,9 +4,9 @@
#import "modules/test.sx"; #import "modules/test.sx";
pkg :: #import "modules/testpkg"; pkg :: #import "modules/testpkg";
add :: (a: s32, b: s32) -> s32 { a + b; } add :: (a: s32, b: s32) -> s32 { a + b }
mul :: (a: s32, b: s32) -> s32 { a * b; } mul :: (a: s32, b: s32) -> s32 { a * b }
// #run compile-time constants // #run compile-time constants
CT_VAL :: #run add(10, 15); CT_VAL :: #run add(10, 15);

View File

@@ -13,4 +13,5 @@ main :: () -> s32 {
v:= std.Vector(3,f32).[1,2,3]; v:= std.Vector(3,f32).[1,2,3];
std.print("\n{}\n", v); std.print("\n{}\n", v);
0
} }

View File

@@ -10,5 +10,5 @@ main :: () -> s32 {
b := multiply(5, 6); b := multiply(5, 6);
print("add_numbers(10, 20) = {}\n", a); print("add_numbers(10, 20) = {}\n", a);
print("multiply(5, 6) = {}\n", b); print("multiply(5, 6) = {}\n", b);
0; 0
} }

View File

@@ -6,5 +6,5 @@ main :: () -> s32 {
b := tc.multiply(5, 6); b := tc.multiply(5, 6);
print("tc.add_numbers(10, 20) = {}\n", a); print("tc.add_numbers(10, 20) = {}\n", a);
print("tc.multiply(5, 6) = {}\n", b); print("tc.multiply(5, 6) = {}\n", b);
0; 0
} }

View File

@@ -7,6 +7,6 @@ Wrap :: struct { v: s64 = 0; }
impl Into(Wrap) for s64 { impl Into(Wrap) for s64 {
convert :: (self: s64) -> Wrap { convert :: (self: s64) -> Wrap {
.{ v = self * 10 }; .{ v = self * 10 }
} }
} }

View File

@@ -9,5 +9,5 @@
main :: () -> s32 { main :: () -> s32 {
w : Wrap = xx 3; w : Wrap = xx 3;
print("w.v = {}\n", w.v); print("w.v = {}\n", w.v);
0; 0
} }

View File

@@ -14,5 +14,5 @@ main :: () -> s32 {
print("b_only_fn: {}\n", b_only_fn()); print("b_only_fn: {}\n", b_only_fn());
print("c_only_fn direct: {}\n", c_only_fn()); print("c_only_fn direct: {}\n", c_only_fn());
print("c_only_const direct: {}\n", c_only_const); print("c_only_const direct: {}\n", c_only_const);
0; 0
} }

View File

@@ -1,5 +1,5 @@
#import "c.sx"; #import "c.sx";
b_only_fn :: () -> s32 { b_only_fn :: () -> s32 {
c_only_fn() + c_only_const; c_only_fn() + c_only_const
} }

View File

@@ -1,2 +1,2 @@
c_only_fn :: () -> s32 { 42; } c_only_fn :: () -> s32 { 42 }
c_only_const :: 7; c_only_const :: 7;

View File

@@ -25,5 +25,5 @@ main :: () -> s32 {
case .a: { print("a\n"); } case .a: { print("a\n"); }
case .b: (v) { print("b={}\n", v); } case .b: (v) { print("b={}\n", v); }
} }
0; 0
} }

View File

@@ -16,5 +16,5 @@ build :: (n: s32) -> string {
result = concat(result, line); result = concat(result, line);
i = i + 1; i = i + 1;
} }
result; result
} }

View File

@@ -15,5 +15,5 @@
main :: () -> s32 { main :: () -> s32 {
w : Wrapped = xx 7; w : Wrapped = xx 7;
print("{}\n", w.v); print("{}\n", w.v);
0; 0
} }

Some files were not shown because too many files have changed in this diff Show More