lang: rename signed integer types sN -> iN

Surface rename of the signed integer family: s1..s64 become i1..i64
(u1..u64, usize, isize unchanged). 'string' keeps the s-prefix arm in
name classification; width parsing moves to the i-prefix arm next to
isize.

Internal TypeId tags follow the surface (.s8/.s16/.s32/.s64 ->
.i8/.i16/.i32/.i64), as do mono-key mangle fragments (ptr_i64,
tu_i64_bool) and all display/diagnostic formatting (i{d}).

Migrated in the same sweep: stdlib + examples + issue repros + FFI C
companions (shared symbol names like ffi_id_i64), expected
stdout/stderr/ir snapshots, specs.md, readme.md, CLAUDE.md/AGENTS.md,
implementation_plan.md, docs/, issue writeups. Vendored stb_image and
historical flow state left untouched.

zig build test: 426/426; examples suite: 595/595.
This commit is contained in:
agra
2026-06-12 09:31:53 +03:00
parent 515ecebea7
commit d8076b9333
1054 changed files with 6836 additions and 6839 deletions

View File

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

View File

@@ -1,5 +1,5 @@
#import "modules/std.sx";
main :: () -> s32 {
main :: () -> i32 {
x := 42;
{
print("scope opened\n");

View File

@@ -1,5 +1,5 @@
#import "modules/std.sx";
main :: () -> s32 {
main :: () -> i32 {
defer print("still here\n");
return 42;
}

View File

@@ -1,6 +1,6 @@
#import "modules/std.sx";
sumOf10 :: () -> s32 {
sumOf10 :: () -> i32 {
i:= 1;
s:=0;
while i <= 10 {

View File

@@ -1,7 +1,7 @@
#import "modules/std.sx";
quick_sort :: (items: []$T) {
partition :: (items: []T, lo: s64, hi: s64) -> s64 {
partition :: (items: []T, lo: i64, hi: i64) -> i64 {
pivot := items[hi];
i := lo - 1;
j := lo;
@@ -17,7 +17,7 @@ quick_sort :: (items: []$T) {
i
}
sort :: (items: []T, lo: s64, hi: s64) {
sort :: (items: []T, lo: i64, hi: i64) {
if lo < hi {
pi := partition(items, lo, hi);
sort(items, lo, pi - 1);
@@ -29,7 +29,7 @@ quick_sort :: (items: []$T) {
}
main :: () {
arr : []s64 = .[333, 2, 3, 5, 2, 2, 3, 4, 5, 6, 6, 1];
arr : []i64 = .[333, 2, 3, 5, 2, 2, 3, 4, 5, 6, 6, 1];
quick_sort(arr);
print("{}\n", arr);
}

View File

@@ -24,7 +24,7 @@ Vec2 :: struct {
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 } }
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) -> i32 { xx (v.x + v.y) }
}
EdgeInsets :: struct {
@@ -39,16 +39,16 @@ EdgeInsets :: struct {
}
Trio :: struct {
a: s32;
b: s32;
c: s32;
a: i32;
b: i32;
c: i32;
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 }
make :: (a: i32, b: i32, c: i32) -> Trio { Trio.{ a = a, b = b, c = c } }
sum :: (t: Trio) -> i32 { t.a + t.b + t.c }
}
Result :: enum {
ok: s32;
ok: i32;
err: string;
}
@@ -121,7 +121,7 @@ main :: () {
// T8: .variant(payload) as function argument (match-as-expression)
{
describe :: (sh: Shape) -> s32 {
describe :: (sh: Shape) -> i32 {
if sh == {
case .circle: 10;
case .rect: 20;
@@ -145,7 +145,7 @@ main :: () {
// T10: Match as expression returning tagged enum
{
select :: (n: s32) -> Shape {
select :: (n: i32) -> Shape {
if n == {
case 0: .none;
case 1: .circle(1.0);
@@ -243,7 +243,7 @@ main :: () {
// E2: Function taking both types — each resolves correctly
{
use_both :: (sh: Shape, v: Vec2) {
ms : s32 = 0;
ms : i32 = 0;
if sh == { case .circle: (r) { ms = xx r; } else: {} }
print("E2: {} {} {}\n", ms, v.x, v.y);
}
@@ -252,7 +252,7 @@ main :: () {
// E3: Bare .variant (no parens) as function arg
{
check_none :: (sh: Shape) -> s32 {
check_none :: (sh: Shape) -> i32 {
if sh == { case .none: 1; else: 0; }
}
print("E3: {}\n", check_none(.none));
@@ -268,7 +268,7 @@ main :: () {
// E5: Tagged enum .variant(payload) in match-as-expression
{
sh : Shape = .circle(42.0);
r : s32 = 0;
r : i32 = 0;
if sh == {
case .circle: (v) { r = xx v; }
case .rect: (sz) { r = xx sz.w; }
@@ -280,7 +280,7 @@ main :: () {
// E6: Color enum (plain, not tagged) still works with bare .variant
{
c : Color = .green;
ci : s32 = xx c;
ci : i32 = xx c;
print("E6: {}\n", ci);
}

View File

@@ -11,6 +11,6 @@ do_it :: () -> bool {
true
}
main :: () -> s32 {
main :: () -> i32 {
if do_it() then 0 else 1
}

View File

@@ -9,21 +9,21 @@
#import "modules/std.sx";
double :: (x: s32) -> s32 => x * 2;
double :: (x: i32) -> i32 => x * 2;
sum :: (a: s32, b: s32) -> s32 => a + b;
sum :: (a: i32, b: i32) -> i32 => a + b;
answer :: () -> s32 => 42;
answer :: () -> i32 => 42;
Point :: struct {
x: s32;
y: s32;
x: i32;
y: i32;
total :: (self: *Point) -> s32 => self.x + self.y;
scaled :: (self: *Point, by: s32) -> s32 => (self.x + self.y) * by;
total :: (self: *Point) -> i32 => self.x + self.y;
scaled :: (self: *Point, by: i32) -> i32 => (self.x + self.y) * by;
}
main :: () -> s32 {
main :: () -> i32 {
print("double: {}\n", double(7));
print("sum: {}\n", sum(3, 4));
print("answer: {}\n", answer());

View File

@@ -9,7 +9,7 @@
Show :: protocol {
show :: () -> string;
}
A :: struct { x: s64; }
A :: struct { x: i64; }
B :: struct { s: string; }
impl Show for A { show :: (self: *A) -> string => "A"; }
impl Show for B { show :: (self: *B) -> string => "B"; }
@@ -21,7 +21,7 @@ each :: (..xs: Show) -> void {
}
}
main :: () -> s32 {
main :: () -> i32 {
// Runtime range, cursor used.
for 0..3 (i) { print("i={}\n", i); }

View File

@@ -7,9 +7,9 @@ Shape :: enum {
none;
}
main :: () -> s32 {
main :: () -> i32 {
// By-ref mutation writes back into the array (impossible with a value copy).
xs : [3]s64 = .[1, 2, 3];
xs : [3]i64 = .[1, 2, 3];
for xs (*x) { x.* = x + 100; }
print("{} {} {}\n", xs[0], xs[1], xs[2]);

View File

@@ -4,23 +4,23 @@
#import "modules/std.sx";
Box :: struct {
v: s64;
boxed :: (self: Box) -> s64 { self.v } // value receiver
v: i64;
boxed :: (self: Box) -> i64 { self.v } // value receiver
}
sum_ptr :: (xs: *List(s64)) -> s64 {
total : s64 = 0;
sum_ptr :: (xs: *List(i64)) -> i64 {
total : i64 = 0;
for xs (n) { total = total + n; } // iterate through a *List
total
}
main :: () -> s32 {
xs := List(s64).{};
main :: () -> i32 {
xs := List(i64).{};
xs.append(10);
xs.append(20);
xs.append(30);
s : s64 = 0;
s : i64 = 0;
for xs (n) { s = s + n; } // value capture
print("sum {}\n", s); // 60
@@ -33,7 +33,7 @@ main :: () -> s32 {
bs := List(Box).{};
bs.append(.{ v = 7 });
bt : s64 = 0;
bt : i64 = 0;
for bs (*b) { bt = bt + b.boxed(); } // *Box receiver, value-self method
print("boxes {}\n", bt); // 7
0

View File

@@ -45,7 +45,7 @@ END;
print("heredoc: {}\n", hd);
// Undefined with type
undef_val : s32 = ---;
undef_val : i32 = ---;
undef_val = 77;
print("undef-then-set: {}\n", undef_val);
@@ -54,7 +54,7 @@ END;
print("enum-lit: {}\n", c);
// Null pointer
np : *s32 = null;
np : *i32 = null;
print("null-ptr: {}\n", np);
// String .len

View File

@@ -4,17 +4,17 @@
#import "modules/std/test.sx";
pkg :: #import "tests/fixtures/testpkg";
add :: (a: s32, b: s32) -> s32 { a + b }
add :: (a: i32, b: i32) -> i32 { a + b }
mul :: (a: s32, b: s32) -> s32 { a * b }
mul :: (a: i32, b: i32) -> i32 { a * b }
// P4 edge: Chained default→default calls
Chained :: protocol {
base :: (msg: string) -> s32;
wrap :: (msg: string) -> s32 {
base :: (msg: string) -> i32;
wrap :: (msg: string) -> i32 {
self.base(msg) + 1
}
double_wrap :: (msg: string) -> s32 {
double_wrap :: (msg: string) -> i32 {
self.wrap(msg) + self.wrap(msg)
}
}
@@ -136,31 +136,31 @@ main :: () {
// Implicit widening conversions
wu : u8 = 200;
ws : s64 = wu;
print("widen-u8-s64: {}\n", ws);
ws : i64 = wu;
print("widen-u8-i64: {}\n", ws);
wi3 : s32 = 42;
wi3 : i32 = 42;
wf : f64 = wi3;
print("widen-s32-f64: {}\n", wf);
print("widen-i32-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);
ws2 : i16 = wu2;
print("widen-u8-i16: {}\n", ws2);
// More xx narrowing
xl : s64 = 12345;
xs : s32 = xx xl;
print("xx-s64-s32: {}\n", xs);
xl : i64 = 12345;
xs : i32 = xx xl;
print("xx-i64-i32: {}\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);
xdi : i32 = xx xdf;
print("xx-f64-i32: {}\n", xdi);
}

View File

@@ -116,7 +116,7 @@ main :: () {
print("nested-break: {} {}\n", nb_outer, nb_icount);
// For loop basic
farr : [4]s32 = .[10, 20, 30, 40];
farr : [4]i32 = .[10, 20, 30, 40];
out("for:");
for farr (it) {
out(" ");
@@ -163,7 +163,7 @@ main :: () {
out("\n");
// For on slice
fsl : []s32 = .[10, 20, 30];
fsl : []i32 = .[10, 20, 30];
out("for-slice:");
for fsl (it) {
print(" {}", it);
@@ -178,8 +178,8 @@ main :: () {
out("\n");
// Nested for
nf_a : [2]s32 = .[0, 1];
nf_b : [2]s32 = .[0, 1];
nf_a : [2]i32 = .[0, 1];
nf_b : [2]i32 = .[0, 1];
out("for-nested:");
for nf_a (oa) {
for nf_b (ob) {
@@ -189,7 +189,7 @@ main :: () {
out("\n");
// For with break preserving index
fbi : [5]s32 = .[10, 20, 30, 40, 50];
fbi : [5]i32 = .[10, 20, 30, 40, 50];
fbi_idx := 0;
for fbi, 0.. (it, ix) {
if it == 30 { fbi_idx = ix; break; }

View File

@@ -4,23 +4,23 @@
#import "modules/std/test.sx";
pkg :: #import "tests/fixtures/testpkg";
add :: (a: s32, b: s32) -> s32 { a + b }
add :: (a: i32, b: i32) -> i32 { a + b }
mul :: (a: s32, b: s32) -> s32 { a * b }
mul :: (a: i32, b: i32) -> i32 { a * b }
identity :: (x: $T) -> T { x }
pair_add :: (a: $T, b: $U) -> s64 {
cast(s64) a + cast(s64) b
pair_add :: (a: $T, b: $U) -> i64 {
cast(i64) a + cast(i64) b
}
typed_sum :: (..args: []s32) -> s32 {
typed_sum :: (..args: []i32) -> i32 {
result := 0;
for args (it) { result = result + it; }
result
}
apply :: (f: (s32, s32) -> s32, x: s32, y: s32) -> s32 {
apply :: (f: (i32, i32) -> i32, x: i32, y: i32) -> i32 {
f(x, y)
}
@@ -28,11 +28,11 @@ void_return :: () {
return;
}
implicit_return :: (x: s32) -> s32 {
implicit_return :: (x: i32) -> i32 {
x * 2
}
early_return :: (x: s32) -> s32 {
early_return :: (x: i32) -> i32 {
if x > 10 { return 99; }
x
}
@@ -53,7 +53,7 @@ main :: () {
print("typed-const: {}\n", TYPED_PI);
// Variable with default init
di : s32;
di : i32;
print("default-init: {}\n", di);
// Implicit return
@@ -68,7 +68,7 @@ main :: () {
print("void-return: ok\n");
// Generic — single param
print("generic-s32: {}\n", identity(42));
print("generic-i32: {}\n", identity(42));
print("generic-f32: {}\n", identity(1.5));
print("generic-bool: {}\n", identity(true));
@@ -76,7 +76,7 @@ main :: () {
print("generic-multi: {}\n", pair_add(10, 20));
// Lambda
double :: (x: s32) => x * 2;
double :: (x: i32) => x * 2;
print("lambda: {}\n", double(7));
// Lambda with return type
@@ -84,7 +84,7 @@ main :: () {
print("lambda-ret: {}\n", halve(10.0));
// Local function (non-lambda)
local_add :: (a: s32, b: s32) -> s32 { a + b }
local_add :: (a: i32, b: i32) -> i32 { a + b }
print("local-fn: {}\n", local_add(3, 4));
// Nested function calls
@@ -94,11 +94,11 @@ main :: () {
print("varargs: {}\n", typed_sum(1, 2, 3, 4, 5));
// Spread
spread_arr : [3]s32 = .[10, 20, 30];
spread_arr : [3]i32 = .[10, 20, 30];
print("spread: {}\n", typed_sum(..spread_arr));
// Function pointers
fp : (s32, s32) -> s32 = add;
fp : (i32, i32) -> i32 = add;
print("fp: {}\n", fp(3, 4));
fp = mul;
print("fp-reassign: {}\n", fp(3, 4));

View File

@@ -4,7 +4,7 @@
#import "modules/std/test.sx";
pkg :: #import "tests/fixtures/testpkg";
Point :: struct { x, y: s32; }
Point :: struct { x, y: i32; }
Color :: enum { red; green; blue; }
@@ -29,14 +29,14 @@ main :: () {
print("sqrt-f64: {}\n", sqrt(16.0));
// size_of
print("sizeof-s32: {}\n", size_of(s32));
print("sizeof-i32: {}\n", size_of(i32));
print("sizeof-f64: {}\n", size_of(f64));
print("sizeof-struct: {}\n", size_of(Point));
// align_of
print("alignof-u8: {}\n", align_of(u8));
print("alignof-s32: {}\n", align_of(s32));
print("alignof-s64: {}\n", align_of(s64));
print("alignof-i32: {}\n", align_of(i32));
print("alignof-i64: {}\n", align_of(i64));
print("alignof-struct: {}\n", align_of(Point));
// type_of + category matching
@@ -121,7 +121,7 @@ main :: () {
// cast
cval : f64 = 3.7;
print("cast: {}\n", cast(s32) cval);
cv2 : s32 = 42;
print("cast: {}\n", cast(i32) cval);
cv2 : i32 = 42;
print("cast-int-f64: {}\n", cast(f64) cv2);
}

View File

@@ -4,7 +4,7 @@
#import "modules/std/test.sx";
pkg :: #import "tests/fixtures/testpkg";
Point :: struct { x, y: s32; }
Point :: struct { x, y: i32; }
Shape :: enum {
circle: f32;

View File

@@ -4,9 +4,9 @@
#import "modules/std/test.sx";
pkg :: #import "tests/fixtures/testpkg";
Point :: struct { x, y: s32; }
Point :: struct { x, y: i32; }
point_sum :: (p: Point) -> s32 { p.x + p.y }
point_sum :: (p: Point) -> i32 { p.x + p.y }
// #run compile-time constants

View File

@@ -4,7 +4,7 @@
#import "modules/std/test.sx";
pkg :: #import "tests/fixtures/testpkg";
Point :: struct { x, y: s32; }
Point :: struct { x, y: i32; }
main :: () {

View File

@@ -11,7 +11,7 @@ main :: () {
// ========================================================
print("=== 25. Array Loop Mutation ===\n");
{
arr : [4]s32 = .[0, 0, 0, 0];
arr : [4]i32 = .[0, 0, 0, 0];
i := 0;
while i < 4 {
arr[i] = xx (i + 1);

View File

@@ -10,7 +10,7 @@ main :: () {
{
print("=== UFCS Aliases ===\n");
num_sum :: (a: s64, b: s64) -> s64 { a + b }
num_sum :: (a: i64, b: i64) -> i64 { a + b }
sum :: ufcs num_sum;
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", 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: i64, b: i64, c: i64, d: i64) -> i64 { a + b * c - d }
calc :: ufcs compute;
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
// Tuple return type
swap :: (a: s64, b: s64) -> (s64, s64) { (b, a) }
swap :: (a: i64, b: i64) -> (i64, i64) { (b, a) }
s := swap(1, 2);
a := s.0;
b := s.1;
print("{}\n", a); // 2
print("{}\n", b); // 1
wrap :: (x: s64) -> (s64) { (x,) }
wrap :: (x: i64) -> (i64) { (x,) }
t := wrap(99);
print("{}\n", t.0); // 99
}

View File

@@ -4,7 +4,7 @@
#import "modules/std/test.sx";
pkg :: #import "tests/fixtures/testpkg";
add :: (a: s32, b: s32) -> s32 { a + b }
add :: (a: i32, b: i32) -> i32 { a + b }
main :: () {
@@ -23,12 +23,12 @@ main :: () {
assert(v.w == 4.0);
// Function call with trailing comma
add :: (a: s64, b: s64) -> s64 { return a + b; }
add :: (a: i64, b: i64) -> i64 { return a + b; }
r := add(10, 20,);
assert(r == 30);
// Array literal with trailing comma
arr := s64.[1, 2, 3,];
arr := i64.[1, 2, 3,];
assert(arr[2] == 3);
print("trailing commas ok\n");

View File

@@ -14,15 +14,15 @@
E :: error { Neg }
// dead `return 99;` after an unconditional return
const_one :: () -> s64 { return 1; return 99; }
const_one :: () -> i64 { return 1; return 99; }
// dead `return x;` after an unconditional raise (the failable closure shape)
always_raise :: (x: s64) -> (s64, !E) { raise error.Neg; return x; }
always_raise :: (x: i64) -> (i64, !E) { raise error.Neg; return x; }
// guard: a conditional return must still fall through to the trailing return
clamp :: (x: s64) -> s64 { if x > 10 { return 10; } return x; }
clamp :: (x: i64) -> i64 { if x > 10 { return 10; } return x; }
main :: () -> s32 {
main :: () -> i32 {
print("const_one={}\n", const_one()); // 1
print("raised={}\n", always_raise(5) catch (e) 0); // 0
print("clamp_hi={}\n", clamp(42)); // 10

View File

@@ -7,14 +7,14 @@
#import "modules/std.sx";
Counter :: struct { n: s32; }
Counter :: struct { n: i32; }
// FREE functions (defined outside the struct), pointer first param.
bump :: ufcs (c: *Counter) -> s32 { c.n += 1; return c.n; }
bump :: ufcs (c: *Counter) -> i32 { c.n += 1; return c.n; }
// reached ONLY via UFCS — must still be emitted.
reset :: ufcs (c: *Counter) { c.n = 0; }
main :: () -> s32 {
main :: () -> i32 {
c := Counter.{ n = 10 };
a := c.bump(); // 11, mutates c
b := c.bump(); // 12

View File

@@ -12,22 +12,22 @@
#import "modules/std.sx";
// Implicit return: trailing expression, no `;`.
double :: (n: s32) -> s32 { n * 2 }
double :: (n: i32) -> i32 { n * 2 }
// if/else as a value — each branch's last expression has no `;`.
sign :: (n: s32) -> s32 {
sign :: (n: i32) -> i32 {
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 {
sum3 :: (a: i32, b: i32, c: i32) -> i32 {
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 {
classify :: (n: i32) -> i32 {
if n == {
case 0: 100;
case 1: 10;
@@ -35,8 +35,8 @@ classify :: (n: s32) -> s32 {
}
}
main :: () -> s32 {
total : s32 = 0;
main :: () -> i32 {
total : i32 = 0;
total = total + double(10); // 20
total = total + sign(-7); // -1
total = total + sum3(1, 2, 3); // 6

View File

@@ -6,8 +6,8 @@
#import "modules/std.sx";
// `n * 2;` discards the value → the function returns nothing.
double :: (n: s32) -> s32 {
double :: (n: i32) -> i32 {
n * 2;
}
main :: () -> s32 { double(5) }
main :: () -> i32 { double(5) }

View File

@@ -8,9 +8,9 @@
#import "modules/std.sx";
pair :: () -> (s32, s32) { (5, 7) }
pair :: () -> (i32, i32) { (5, 7) }
main :: () -> s32 {
main :: () -> i32 {
// destructure decl inside a value-bound block
sum := {
a, b := pair();

View File

@@ -9,14 +9,14 @@
#import "modules/std.sx";
sign :: (n: s32) -> s32 {
sign :: (n: i32) -> i32 {
if n == {
case 0: 0;
else: if n > 0 then 1 else -1;
}
}
classify :: (n: s32) -> s32 {
classify :: (n: i32) -> i32 {
if n == {
case 0: 100;
case 1: 10;
@@ -24,7 +24,7 @@ classify :: (n: s32) -> s32 {
}
}
main :: () -> s32 {
main :: () -> i32 {
print("sign: {} {} {}\n", sign(-9), sign(0), sign(9)); // -1 0 1
print("classify: {} {} {}\n", classify(0), classify(1), classify(5)); // 100 10 -1
0

View File

@@ -6,9 +6,9 @@
#import "modules/std.sx";
scale :: (n: s32, factor: s32 = 2) -> s32 { n * factor }
scale :: (n: i32, factor: i32 = 2) -> i32 { n * factor }
label :: (n: s32, prefix: string = "v", suffix: string = "!") -> s32 {
label :: (n: i32, prefix: string = "v", suffix: string = "!") -> i32 {
print("{}{}{}\n", prefix, n, suffix);
n
}

View File

@@ -11,7 +11,7 @@
Json :: enum {
str: string;
int_: s64;
int_: i64;
null_;
}

View File

@@ -1,9 +1,9 @@
// Integer `{}` formatting across the full signed/unsigned range.
//
// Regression (issue 0090): the `{}` formatter was s64-based — it negated
// the value to print the sign (so s64::MIN, whose magnitude is
// unrepresentable as a positive s64, rendered as a bare "-"), and it had
// no unsigned-aware path (so a u64 all-ones value printed as the s64
// Regression (issue 0090): the `{}` formatter was i64-based — it negated
// the value to print the sign (so i64::MIN, whose magnitude is
// unrepresentable as a positive i64, rendered as a bare "-"), and it had
// no unsigned-aware path (so a u64 all-ones value printed as the i64
// reinterpretation, "-1"). Both extremes now render correctly: signed
// MIN prints all its digits, and unsigned integers print as unsigned
// decimal across all 64 bits.
@@ -12,16 +12,16 @@
main :: () {
// Signed extreme: magnitude is never negated, so MIN survives.
print("s64.min={}\n", s64.min);
print("s64.max={}\n", s64.max);
print("i64.min={}\n", i64.min);
print("i64.max={}\n", i64.max);
// Unsigned extreme: all 64 bits as unsigned decimal, not -1.
print("u64.max={}\n", u64.max);
// Spread across widths — signed.
print("s8.min={} s8.max={}\n", s8.min, s8.max);
print("s16.min={} s16.max={}\n", s16.min, s16.max);
print("s32.min={} s32.max={}\n", s32.min, s32.max);
print("i8.min={} i8.max={}\n", i8.min, i8.max);
print("i16.min={} i16.max={}\n", i16.min, i16.max);
print("i32.min={} i32.max={}\n", i32.min, i32.max);
// Spread across widths — unsigned (max is all-ones for that width).
print("u8.max={} u16.max={}\n", u8.max, u16.max);
@@ -31,7 +31,7 @@ main :: () {
print("u8.min={} u64.min={} zero={}\n", u8.min, u64.min, 0);
// Ordinary signed/unsigned values still print correctly.
neg : s32 = -42;
neg : i32 = -42;
pos : u32 = 4000000000;
print("neg={} pos={}\n", neg, pos);
}

View File

@@ -8,10 +8,10 @@
#import "modules/std.sx";
main :: () -> s32 {
main :: () -> i32 {
sum := 0;
for 0..1000000 (i) {
buf : [128]s64 = ---;
buf : [128]i64 = ---;
buf[0] = i;
sum += buf[0];
}

View File

@@ -8,8 +8,8 @@
#import "modules/std.sx";
main :: () -> s32 {
arr : [4096]s64 = ---;
main :: () -> i32 {
arr : [4096]i64 = ---;
i := 0;
while i < 4096 { arr[i] = i; i += 1; }
sum := 0;
@@ -17,7 +17,7 @@ main :: () -> s32 {
print("sum={}\n", sum);
// By-value capture is a copy: mutating it leaves the array untouched.
small : [3]s64 = .[10, 20, 30];
small : [3]i64 = .[10, 20, 30];
for small (x) { x += 100; }
print("copy-guard: {} {} {}\n", small[0], small[1], small[2]);
0

View File

@@ -6,7 +6,7 @@
#import "modules/std.sx";
main :: () -> s32 {
main :: () -> i32 {
for 0..3 (i) {
defer print("cleanup {}\n", i);
if i == 1 { break; }

View File

@@ -1,29 +1,29 @@
#import "modules/std.sx";
pair_sum :: (xs: []s64, ys: []s64) -> s64 {
pair_sum :: (xs: []i64, ys: []i64) -> i64 {
total := 0;
for xs, ys (x, y) { total += x * y; }
total
}
make :: () -> [3]s64 {
r : [3]s64 = .[7, 8, 9];
make :: () -> [3]i64 {
r : [3]i64 = .[7, 8, 9];
r
}
main :: () -> s32 {
main :: () -> i32 {
// Agra's example: a 1..5 inclusive, b open-ended following along.
for 1..=5, 0.. (a, b) { print("{}:{} ", a, b); }
print("\n");
// Index idiom replacing the old (x, i) form.
xs : [3]s64 = .[10, 20, 30];
xs : [3]i64 = .[10, 20, 30];
for xs, 0.. (x, i) { print("[{}]={} ", i, x); }
print("\n");
// Parallel slices.
a4 : [4]s64 = .[1, 2, 3, 4];
b4 : [4]s64 = .[10, 20, 30, 40];
a4 : [4]i64 = .[1, 2, 3, 4];
b4 : [4]i64 = .[10, 20, 30, 40];
print("dot={}\n", pair_sum(a4, b4));
// Arrow bodies.

View File

@@ -7,7 +7,7 @@
#import "modules/std.sx";
main :: () -> s32 {
main :: () -> i32 {
for 0<..<5 (i) { print("{} ", i); }
print("| 0<..<5\n");
for 0=..=5 (i) { print("{} ", i); }
@@ -22,7 +22,7 @@ main :: () -> s32 {
print("| 0..=5\n");
// Exclusive-start open range following a bounded first iterable.
xs : [3]s64 = .[10, 20, 30];
xs : [3]i64 = .[10, 20, 30];
for xs, 2<.. (x, i) { print("{}@{} ", x, i); }
print("| xs, 2<..\n");

View File

@@ -6,15 +6,15 @@
#import "modules/std.sx";
dump :: (s: []s64, tag: string) {
dump :: (s: []i64, tag: string) {
print("{}: ", tag);
for s (v) { print("{} ", v); }
print("(len {})\n", s.len);
}
main :: () -> s32 {
xs : [6]s64 = .[10, 11, 12, 13, 14, 15];
full : []s64 = xs[0..6];
main :: () -> i32 {
xs : [6]i64 = .[10, 11, 12, 13, 14, 15];
full : []i64 = xs[0..6];
dump(full[1..=3], "1..=3"); // 11 12 13
dump(full[0<..<4], "0<..<4"); // 11 12 13

View File

@@ -8,17 +8,17 @@
#import "modules/std.sx";
bump :: (x: s64) -> s64 { x + 1 }
bump2 :: ufcs (x: s64) -> s64 { x + 2 }
bump :: (x: i64) -> i64 { x + 1 }
bump2 :: ufcs (x: i64) -> i64 { x + 2 }
bump3 :: ufcs bump;
Counter :: struct { n: s64; }
inc :: ufcs (c: *Counter, by: s64) -> s64 { c.n += by; c.n }
Counter :: struct { n: i64; }
inc :: ufcs (c: *Counter, by: i64) -> i64 { c.n += by; c.n }
gfirst :: ufcs (xs: []$T) -> T { xs[0] }
main :: () {
f : s64 = 40;
f : i64 = 40;
print("marked: {}\n", f.bump2()); // 42
print("alias: {}\n", f.bump3()); // 41
print("direct: {}\n", bump(f)); // 41 — plain fn, direct
@@ -29,7 +29,7 @@ main :: () {
print("ptr-recv: {}\n", c.inc(5)); // 15 — auto address-of receiver
arr := .[7, 8, 9];
xs : []s64 = arr;
xs : []i64 = arr;
print("generic-dot: {}\n", xs.gfirst()); // 7
print("generic-direct: {}\n", gfirst(xs)); // 7 — plan types it s64, not a T stub
print("generic-direct: {}\n", gfirst(xs)); // 7 — plan types it i64, not a T stub
}

View File

@@ -7,19 +7,19 @@
#import "modules/std.sx";
Point :: struct {
x: s64;
scaled :: (self: Point, k: s64 = 2) -> s64 { return self.x * k; }
x: i64;
scaled :: (self: Point, k: i64 = 2) -> i64 { return self.x * k; }
}
bump :: ufcs (p: Point, by: s64 = 10) -> s64 { return p.x + by; }
bump :: ufcs (p: Point, by: i64 = 10) -> i64 { return p.x + by; }
sum_var :: (..xs: []s64) -> s64 {
sum_var :: (..xs: []i64) -> i64 {
t := 0;
for xs (x) { t = t + x; }
return t;
}
here :: (loc: Source_Location = #caller_location) -> s64 { return loc.line; }
here :: (loc: Source_Location = #caller_location) -> i64 { return loc.line; }
main :: () {
p := Point.{ x = 5 };

View File

@@ -13,7 +13,7 @@
#import "modules/std.sx";
checksum :: () -> s64 {
checksum :: () -> i64 {
buf : [65536]u8 = ---;
i := 0;
while i < 65536 {
@@ -29,14 +29,14 @@ checksum :: () -> s64 {
return sum;
}
big :: () -> s64 {
buf : [131072]s64 = ---;
big :: () -> i64 {
buf : [131072]i64 = ---;
buf[0] = 11;
buf[131071] = 31;
return buf[0] + buf[131071];
}
main :: () -> s32 {
main :: () -> i32 {
out(int_to_string(checksum()));
out("\n");
out(int_to_string(big()));

View File

@@ -5,7 +5,7 @@ Vec4 :: struct {
Complex :: struct {
foo : enum {
S: s32;
S: i32;
B: struct {
val: string;
};

View File

@@ -1,7 +1,7 @@
#import "modules/std.sx";
SPECIAL_VALUE :u8: 42;
resolve :: (x: u8) -> s32 {
resolve :: (x: u8) -> i32 {
return 12 + x;
}
@@ -9,7 +9,7 @@ Foo :: struct {
a : u2; // this will have 0 as default
b : u8 = SPECIAL_VALUE;
c : u8 = ---; // default for c is undefined
d : u8 = #run xx resolve(5); // converts s32 to u8
d : u8 = #run xx resolve(5); // converts i32 to u8
}
main :: () {
@@ -38,6 +38,6 @@ Pack :: struct {
c: u8;
d: u32;
f: u64;
v: s32;
v: i32;
x: f32;
}

View File

@@ -1,11 +1,11 @@
#import "modules/std.sx";
Point :: struct {
x, y: s32;
x, y: i32;
}
Color :: struct {
r, g, b: s32;
r, g, b: i32;
}
main :: () {

View File

@@ -2,7 +2,7 @@
Overlay :: union {
f: f32;
i: s32;
i: i32;
}
Vec2 :: union {

View File

@@ -54,12 +54,12 @@ main :: () {
// Explicit values
w :WindowFlags = .vsync | .resizable;
print("\nwindow: {}\n", w);
print("raw value: {}\n", cast(s64) w);
print("raw value: {}\n", cast(i64) w);
// Backing type on plain enums
c :Color = .blue;
print("\ncolor: {}\n", c);
print("raw: {}\n", cast(s64) c);
print("raw: {}\n", cast(i64) c);
// Bitwise ops work on plain integers too
x := 0xFF & 0x0F;

View File

@@ -3,16 +3,16 @@
#import "modules/std.sx";
g_add : s64 = 10;
g_sub : s64 = 10;
g_mul : s64 = 10;
g_div : s64 = 100;
g_mod : s64 = 10;
g_and : s64 = 0xff;
g_or : s64 = 0x0f;
g_xor : s64 = 0xff;
g_shl : s64 = 1;
g_shr : s64 = 256;
g_add : i64 = 10;
g_sub : i64 = 10;
g_mul : i64 = 10;
g_div : i64 = 100;
g_mod : i64 = 10;
g_and : i64 = 0xff;
g_or : i64 = 0x0f;
g_xor : i64 = 0xff;
g_shl : i64 = 1;
g_shr : i64 = 256;
main :: () -> void {
// += repeated: should accumulate, not reset

View File

@@ -5,7 +5,7 @@
#import "modules/std.sx";
main :: () -> void {
x : s64 = 42;
x : i64 = 42;
// OK: comparison in statement context
if x != 0 { out("ok\n"); }

View File

@@ -5,19 +5,19 @@
#import "modules/std.sx";
// 40-byte struct — triggers the bug.
// Shrink to [4]s64 (32 bytes) and the bug goes away.
// Shrink to [4]i64 (32 bytes) and the bug goes away.
BigNode :: struct {
data: [5]s64; // 40 bytes
data: [5]i64; // 40 bytes
}
Tree :: struct {
nodes: List(BigNode); // items(8) + len(8) + cap(8) = 24 bytes
generation: s64; // 8 bytes — total 32 bytes
generation: i64; // 8 bytes — total 32 bytes
}
Container :: struct {
tree: Tree;
sentinel: s64;
sentinel: i64;
do_work :: (self: *Container) {
self.tree.nodes.items = xx 0; // BUG: corrupts self.sentinel

View File

@@ -3,7 +3,7 @@
#import "modules/std.sx";
g_counter : s64 = 0;
g_counter : i64 = 0;
tick :: () {
g_counter += 1;
@@ -14,7 +14,7 @@ main :: () -> void {
// Test 1: += always produces 1 (BUG)
out("--- Test 1: += (broken) ---\n");
out("Expected: 1, 2, 3\n");
i : s64 = 0;
i : i64 = 0;
while i < 3 {
tick();
i += 1;

View File

@@ -3,7 +3,7 @@
#import "modules/std.sx";
VALS : [4]s32 = .[-2, -1, 42, 99];
VALS : [4]i32 = .[-2, -1, 42, 99];
main :: () {
out("VALS: ");

View File

@@ -5,7 +5,7 @@
Foo :: struct {
running: bool = true;
x: s32 = 42;
x: i32 = 42;
name: string = "default";
}

View File

@@ -10,7 +10,7 @@ ok :: () -> Handle { 0 }
g : Handle = 0;
main :: () -> s32 {
main :: () -> i32 {
g = ok();
if g == 0 then 0 else 1
}

View File

@@ -1,7 +1,7 @@
// Pre-fix: `resolveType(null)` silently returned `.s64`, so a top-level
// var without a type annotation got typed as `s64` regardless of what
// Pre-fix: `resolveType(null)` silently returned `.i64`, so a top-level
// var without a type annotation got typed as `i64` regardless of what
// the initializer was. For `g_pi := 3.14;` this meant the float literal
// was assigned to an s64 slot, producing a wrong value at runtime or
// was assigned to an i64 slot, producing a wrong value at runtime or
// the wrong codegen shape.
//
// After the fix `lowerVarDecl` at the top level mirrors the local-scope
@@ -9,11 +9,11 @@
// the initializer's type. Mirrors how `:=` already worked for locals.
#import "modules/std.sx";
g_count := 42; // inferred s64
g_pi := 3.14; // inferred f64 — used to silently become s64
g_count := 42; // inferred i64
g_pi := 3.14; // inferred f64 — used to silently become i64
g_flag := true; // inferred bool
main :: () -> s32 {
main :: () -> i32 {
print("count = {}\n", g_count);
print("pi = {}\n", g_pi);
print("flag = {}\n", g_flag);

View File

@@ -7,7 +7,7 @@
//
// This test exercises the builder directly (no `#insert`, no impl
// wiring) — three pack shapes through the same `void`-returning
// wrapper plus one non-void `s32`-returning wrapper to pin the
// wrapper plus one non-void `i32`-returning wrapper to pin the
// `return typed_fn(...)` branch. The expected output captures the
// generated source verbatim so any formatting drift surfaces here
// rather than as a downstream compile error inside the eventual
@@ -20,15 +20,15 @@ preview_void :: (..$args) -> string {
return build_block_convert($args, void);
}
preview_s32 :: (..$args) -> string {
return build_block_convert($args, s32);
preview_i32 :: (..$args) -> string {
return build_block_convert($args, i32);
}
run_all :: () {
print("--- void / 0 args ---\n{}\n", preview_void());
print("--- void / bool ---\n{}\n", preview_void(true));
print("--- void / s64, string ---\n{}\n", preview_void(42, "hi"));
print("--- s32 / f64 ---\n{}\n", preview_s32(3.14));
print("--- void / i64, string ---\n{}\n", preview_void(42, "hi"));
print("--- i32 / f64 ---\n{}\n", preview_i32(3.14));
}
#run run_all();

View File

@@ -2,7 +2,7 @@
// `align_of` accept pointer (`*T`), optional (`?T`), array (`[N]T`),
// function (`(A) -> B`), and tuple (`(A, B)`) types directly. Also
// const-decl RHS aliases through the same forms (`Ptr :: *u8;` etc).
// Same shape as the existing `size_of(s32)` baseline path.
// Same shape as the existing `size_of(i32)` baseline path.
#import "modules/std.sx";
@@ -10,9 +10,9 @@
Ptr :: *u8;
Maybe :: ?u8;
Arr :: [3]u8;
Cb :: (s32) -> s32;
Cb :: (i32) -> i32;
main :: () -> s32 {
main :: () -> i32 {
// Direct: parser fix for *T, ?T + existing [N]T path.
print("size_of(*u8) = {}\n", size_of(*u8));
print("align_of(*u8) = {}\n", align_of(*u8));
@@ -20,10 +20,10 @@ main :: () -> s32 {
print("size_of([3]u8) = {}\n", size_of([3]u8));
// Function-type literal in expression position.
print("size_of((s32)->s32) = {}\n", size_of((s32) -> s32));
print("size_of((i32)->i32) = {}\n", size_of((i32) -> i32));
// Tuple literal reinterpreted as tuple type at the type-demanding site.
print("size_of((s32, s32)) = {}\n", size_of((s32, s32)));
print("size_of((i32, i32)) = {}\n", size_of((i32, i32)));
// Aliases.
print("size_of(Ptr) = {}\n", size_of(Ptr));

View File

@@ -1,19 +1,19 @@
// Type alias resolution through `size_of` / `align_of` — a const-decl
// alias (`MyInt :: s32;`, `MyChain :: MyInt;`, `WideAlias :: Wide;`)
// alias (`MyInt :: i32;`, `MyChain :: MyInt;`, `WideAlias :: Wide;`)
// resolves through `type_alias_map` when used as a `$T: Type` argument.
// Covers chains and struct-name aliases, not just structural-type
// aliases (those land in `examples/182-compound-type-in-expression.sx`).
#import "modules/std.sx";
MyInt :: s32;
MyInt :: i32;
MyChain :: MyInt;
Wide :: struct { a: s64; b: s64; }
Wide :: struct { a: i64; b: i64; }
WideAlias :: Wide;
main :: () -> s32 {
print("direct s32: {}\n", size_of(s32));
print("alias s32: {}\n", size_of(MyInt));
print("chain s32: {}\n", size_of(MyChain));
main :: () -> i32 {
print("direct i32: {}\n", size_of(i32));
print("alias i32: {}\n", size_of(MyInt));
print("chain i32: {}\n", size_of(MyChain));
print("align alias: {}\n", align_of(MyInt));
print("align chain: {}\n", align_of(MyChain));
print("size struct-alias: {}\n", size_of(WideAlias));

View File

@@ -17,7 +17,7 @@
g_s: string = "";
main :: () -> s32 {
main :: () -> i32 {
cl := (s: string) => { g_s = s; };
b : Block = xx cl;
invoke_fn : (*Block, string) -> void callconv(.c) = xx b.invoke;

View File

@@ -12,7 +12,7 @@
// ── Test fixtures ─────────────────────────────────────────────
Point :: struct { x: s32; y: s32; }
Point :: struct { x: i32; y: i32; }
Color :: enum { red; green; blue; }
@@ -24,7 +24,7 @@ identity :: ($T: Type, val: T) -> T => val;
// time fold via type_eq → const_bool → inline-if folds the
// branch away).
describe :: ($T: Type) -> string {
inline if type_eq(T, s64) { return "int64"; }
inline if type_eq(T, i64) { return "int64"; }
inline if type_eq(T, string) { return "text"; }
inline if type_eq(T, bool) { return "boolean"; }
return "other";
@@ -34,7 +34,7 @@ describe :: ($T: Type) -> string {
type_list :: (..$args) -> string {
list := $args;
s := "[";
i : s64 = 0;
i : i64 = 0;
while i < list.len {
if i > 0 { s = concat(s, ", "); }
s = concat(s, type_name(list[i]));
@@ -46,21 +46,21 @@ type_list :: (..$args) -> string {
// Type stored in a struct field.
TypeHolder :: struct { t: Type; }
main :: () -> s32 {
main :: () -> i32 {
// ── 1. Type literal equality ────────────────────────────
print("=== 1. literal == ===\n");
print("s64 == s64: {}\n", s64 == s64);
print("s64 == string: {}\n", s64 == string);
print("i64 == i64: {}\n", i64 == i64);
print("i64 == string: {}\n", i64 == string);
print("*u8 == *u8: {}\n", *u8 == *u8);
print("?s64 == ?s64: {}\n", ?s64 == ?s64);
print("?s64 == ?s32: {}\n", ?s64 == ?s32);
print("?i64 == ?i64: {}\n", ?i64 == ?i64);
print("?i64 == ?i32: {}\n", ?i64 == ?i32);
// ── 2. type_of(value) ───────────────────────────────────
print("=== 2. type_of(value) == T ===\n");
a : s64 = 42;
a : i64 = 42;
b : f64 = 3.14;
s : string = "hi";
print("type_of(a) == s64: {}\n", type_of(a) == s64);
print("type_of(a) == i64: {}\n", type_of(a) == i64);
print("type_of(b) == f64: {}\n", type_of(b) == f64);
print("type_of(s) == string: {}\n", type_of(s) == string);
print("type_of(a) == f64: {}\n", type_of(a) == f64);
@@ -77,7 +77,7 @@ main :: () -> s32 {
// ── 4. type_name on literals + variables ────────────────
print("=== 4. type_name ===\n");
print("type_name(s64): {}\n", type_name(s64));
print("type_name(i64): {}\n", type_name(i64));
print("type_name(*u8): {}\n", type_name(*u8));
print("type_name(Point): {}\n", type_name(Point));
print("type_name(Color): {}\n", type_name(Color));
@@ -86,39 +86,39 @@ main :: () -> s32 {
// ── 5. Print Type values directly ───────────────────────
print("=== 5. print Type values ===\n");
print("literal: {}\n", s64);
print("literal: {}\n", i64);
t = string;
print("var: {}\n", t);
print("type_of(b): {}\n", type_of(b));
// ── 6. Generic dispatch via $T: Type ────────────────────
print("=== 6. generic dispatch ===\n");
print("describe(s64): {}\n", describe(s64));
print("describe(i64): {}\n", describe(i64));
print("describe(string): {}\n", describe(string));
print("describe(bool): {}\n", describe(bool));
print("describe(f64): {}\n", describe(f64));
// ── 7. identity(T, val) ─────────────────────────────────
print("=== 7. identity($T, val) ===\n");
print("identity(s64, 7): {}\n", identity(s64, 7));
print("identity(i64, 7): {}\n", identity(i64, 7));
print("identity(string, hi): {}\n", identity(string, "hi"));
print("identity(bool, true): {}\n", identity(bool, true));
// ── 8. Comptime-generated struct (Wrap($T)) ─────────────
print("=== 8. Wrap($T) ===\n");
w_int := Wrap(s64).{ v = 42 };
w_int := Wrap(i64).{ v = 42 };
w_str := Wrap(string).{ v = "wrapped" };
print("Wrap(s64).v: {}\n", w_int.v);
print("Wrap(i64).v: {}\n", w_int.v);
print("Wrap(string).v: {}\n", w_str.v);
// ── 9. Reflection builtins on Types ─────────────────────
print("=== 9. reflection on Type ===\n");
print("size_of(s64): {}\n", size_of(s64));
print("size_of(i64): {}\n", size_of(i64));
print("size_of(*u8): {}\n", size_of(*u8));
print("align_of(f64): {}\n", align_of(f64));
print("field_count(Point): {}\n", field_count(Point));
print("type_eq(s64, s64): {}\n", type_eq(s64, s64));
print("type_eq(s64, string): {}\n", type_eq(s64, string));
print("type_eq(i64, i64): {}\n", type_eq(i64, i64));
print("type_eq(i64, string): {}\n", type_eq(i64, string));
// ── 10. Type pack (..$args) walking ─────────────────────
print("=== 10. ..$args walking ===\n");
@@ -129,15 +129,15 @@ main :: () -> s32 {
// ── 11. Type in struct field ────────────────────────────
print("=== 11. Type in struct field ===\n");
h := TypeHolder.{ t = s64 };
print("h.t == s64: {}\n", h.t == s64);
h := TypeHolder.{ t = i64 };
print("h.t == i64: {}\n", h.t == i64);
print("h.t == string: {}\n", h.t == string);
print("type_name(h.t): {}\n", type_name(h.t));
// ── 12. Compound type literals ──────────────────────────
print("=== 12. compound literals ===\n");
print("type_name(*Point): {}\n", type_name(*Point));
print("type_name([4]s32): {}\n", type_name([4]s32));
print("type_name([4]i32): {}\n", type_name([4]i32));
print("type_name([]bool): {}\n", type_name([]bool));
print("type_name(?f64): {}\n", type_name(?f64));
@@ -146,13 +146,13 @@ main :: () -> s32 {
// ** stdout **
// === 1. literal == ===
// s64 == s64: true
// s64 == string: false
// i64 == i64: true
// i64 == string: false
// *u8 == *u8: true
// ?s64 == ?s64: true
// ?s64 == ?s32: false
// ?i64 == ?i64: true
// ?i64 == ?i32: false
// === 2. type_of(value) == T ===
// type_of(a) == s64: true
// type_of(a) == i64: true
// type_of(b) == f64: true
// type_of(s) == string: true
// type_of(a) == f64: false
@@ -162,45 +162,45 @@ main :: () -> s32 {
// after reassign t == string: true
// t == bool: true
// === 4. type_name ===
// type_name(s64): s64
// type_name(i64): i64
// type_name(*u8): *u8
// type_name(Point): Point
// type_name(Color): Color
// type_name(t): f64
// === 5. print Type values ===
// literal: s64
// literal: i64
// var: string
// type_of(b): f64
// === 6. generic dispatch ===
// describe(s64): int64
// describe(i64): int64
// describe(string): text
// describe(bool): boolean
// describe(f64): other
// === 7. identity($T, val) ===
// identity(s64, 7): 7
// identity(i64, 7): 7
// identity(string, hi): hi
// identity(bool, true): true
// === 8. Wrap($T) ===
// Wrap(s64).v: 42
// Wrap(i64).v: 42
// Wrap(string).v: wrapped
// === 9. reflection on Type ===
// size_of(s64): 8
// size_of(i64): 8
// size_of(*u8): 8
// align_of(f64): 8
// field_count(Point): 2
// type_eq(s64, s64): true
// type_eq(s64, string): false
// type_eq(i64, i64): true
// type_eq(i64, string): false
// === 10. ..$args walking ===
// type_list(): []
// type_list(1): [s64]
// type_list(1, "x"): [s64, string]
// type_list(1): [i64]
// type_list(1, "x"): [i64, string]
// type_list(true, 3.14): [bool, f64]
// === 11. Type in struct field ===
// h.t == s64: true
// h.t == i64: true
// h.t == string: false
// type_name(h.t): s64
// type_name(h.t): i64
// === 12. compound literals ===
// type_name(*Point): *Point
// type_name([4]s32): [4]s32
// type_name([4]i32): [4]i32
// type_name([]bool): []bool
// type_name(?f64): ?f64

View File

@@ -2,16 +2,16 @@
// return, and operators. Regression for the tuple-construction bug where
// an inferred `:=` tuple literal lowered its element values under the
// enclosing fn's (narrower) return `target_type`, mismatching the
// independently-inferred s64 field types and yielding garbage on read.
// independently-inferred i64 field types and yielding garbage on read.
#import "modules/std.sx";
Box :: struct { xs: (s32, s32); }
Box :: struct { xs: (i32, i32); }
swap :: (a: s64, b: s64) -> (s64, s64) { (b, a) }
fst :: (t: (s64, s64)) -> s64 { t.0 }
swap :: (a: i64, b: i64) -> (i64, i64) { (b, a) }
fst :: (t: (i64, i64)) -> i64 { t.0 }
main :: () -> s32 {
main :: () -> i32 {
// Inferred positional tuple + numeric field access.
pair := (40, 2);
print("pair {} {}\n", pair.0, pair.1);
@@ -21,8 +21,8 @@ main :: () -> s32 {
print("named {} {} {}\n", named.x, named.0, named.1);
// Element into a typed local (access path, not just print).
a : s64 = pair.0;
b : s64 = pair.1;
a : i64 = pair.0;
b : i64 = pair.1;
print("locals {} {}\n", a, b);
// Tuple-typed struct field: store a tuple value, read both elements.
@@ -46,9 +46,9 @@ main :: () -> s32 {
print("mem {}\n", 3 in (1, 2, 3));
print("lex {}\n", (1, 2) < (1, 3));
// Mixed-size fields: a tuple with both an s64 and a string (16-byte fat
// Mixed-size fields: a tuple with both an i64 and a string (16-byte fat
// pointer). Field types are tracked per-position, so reading each back is
// typed correctly (s64 prints as a number, string as text).
// typed correctly (i64 prints as a number, string as text).
mixed := (42, "hi");
print("mixed {} {}\n", mixed.0, mixed.1);
0

View File

@@ -7,15 +7,15 @@
#import "modules/std.sx";
main :: () -> s32 {
main :: () -> i32 {
// Positional element assignment.
a : (s32, string) = ---;
a : (i32, string) = ---;
a.0 = 11;
a.1 = "x";
print("a: {} {}\n", a.0, a.1);
// Named tuple: write + read by name, and read by position.
p : (x: s32, y: string) = ---;
p : (x: i32, y: string) = ---;
p.x = 22;
p.y = "y";
print("p: x={} y={} .0={}\n", p.x, p.y, p.0);

View File

@@ -4,7 +4,7 @@
#import "modules/std/test.sx";
pkg :: #import "tests/fixtures/testpkg";
Point :: struct { x, y: s32; }
Point :: struct { x, y: i32; }
Color :: enum { red; green; blue; }
@@ -16,7 +16,7 @@ Shape :: enum {
Overlay :: union {
f: f32;
i: s32;
i: i32;
}
Vec2 :: union {
@@ -25,27 +25,27 @@ Vec2 :: union {
}
Defaults :: struct {
a: s32;
b: s32 = 99;
c: s32 = ---;
a: i32;
b: i32 = 99;
c: i32 = ---;
}
MyFloat :: f64;
Status :: enum u8 { ok; err; timeout; }
add :: (a: s32, b: s32) -> s32 { a + b }
add :: (a: i32, b: i32) -> i32 { a + b }
mul :: (a: s32, b: s32) -> s32 { a * b }
mul :: (a: i32, b: i32) -> i32 { a * b }
vec3 :: (x: f32, y: f32, z: f32) -> Vector(3, f32) {
.[x, y, z]
}
// Global variable for address-of test
g_smoke_val : s32 = 42;
g_smoke_val : i32 = 42;
write_to_ptr :: (p: *s32) {
write_to_ptr :: (p: *i32) {
p.* = 99;
}
@@ -57,15 +57,15 @@ main :: () {
print("=== 3. Types ===\n");
// Primitive types
v_s8 : s8 = 127;
v_s16 : s16 = 32000;
v_s32 : s32 = 100000;
v_i8 : i8 = 127;
v_i16 : i16 = 32000;
v_i32 : i32 = 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("i8: {}\n", v_i8);
print("i16: {}\n", v_i16);
print("i32: {}\n", v_i32);
print("u8: {}\n", v_u8);
print("u16: {}\n", v_u16);
print("u32: {}\n", v_u32);
@@ -88,8 +88,8 @@ main :: () {
print("struct-named: {}\n", p3);
// Shorthand (variable name = field name)
x : s32 = 5;
y : s32 = 6;
x : i32 = 5;
y : i32 = 6;
p4 := Point.{ x, y };
print("struct-shorthand: {}\n", p4);
@@ -226,7 +226,7 @@ main :: () {
o : Overlay = ---;
o.f = 3.14;
print("union-f: {}\n", o.f);
// Type punning — read same bits as s32
// Type punning — read same bits as i32
print("union-i: {}\n", o.i);
// Union member promotion
@@ -237,22 +237,22 @@ main :: () {
print("promoted-data0: {}\n", uv.data[0]);
// --- Arrays ---
arr : [5]s32 = .[10, 20, 30, 40, 50];
arr : [5]i32 = .[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 : [3]i32 = .[1, 2, 3];
aa[1] = 99;
print("arr-assign: {}\n", aa);
// --- Slices ---
sl : []s32 = .[1, 2, 3, 4, 5];
sl : []i32 = .[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 : []i32 = .[10, 20, 30];
sla[1] = 55;
print("sl-assign: {}\n", sla);
@@ -265,7 +265,7 @@ main :: () {
print("tail: {}\n", tail);
// Slice of slice
sos : []s32 = .[10, 20, 30, 40, 50];
sos : []i32 = .[10, 20, 30, 40, 50];
mid := sos[1..4];
inner := mid[0..2];
print("slice-of-slice: {}\n", inner);
@@ -289,18 +289,18 @@ main :: () {
print("auto-deref: {}\n", ptr.x);
// Many-pointer
mp : [*]s32 = @arr[0];
mp : [*]i32 = @arr[0];
print("mp[0]: {}\n", mp[0]);
print("mp[3]: {}\n", mp[3]);
// Many-pointer write
mpw : [5]s32 = .[10, 20, 30, 40, 50];
mpw_ptr : [*]s32 = @mpw[0];
mpw : [5]i32 = .[10, 20, 30, 40, 50];
mpw_ptr : [*]i32 = @mpw[0];
mpw_ptr[2] = 99;
print("mp-write: {}\n", mpw[2]);
// Pointer-null comparison
np : *s32 = null;
np : *i32 = null;
print("ptr==null: {}\n", np == null);
print("ptr!=null: {}\n", np != null);
np2 := @pv.x;
@@ -309,13 +309,13 @@ main :: () {
// Pointer to nested struct field
Inner3 :: struct { a: f32; b: f32; c: f32; }
Outer3 :: struct { key: s32; inner: Inner3; }
Outer3 :: struct { key: i32; inner: Inner3; }
out3 := Outer3.{ key = 42, inner = Inner3.{ a = 1.0, b = 2.0, c = 3.0 } };
ip3 := @out3.inner;
print("ptr-nested-field: {} {} {}\n", ip3.a, ip3.b, ip3.c);
// Store to many-pointer field must not corrupt adjacent memory
MpHolder :: struct { items: [*]s64; sentinel: s64; }
MpHolder :: struct { items: [*]i64; sentinel: i64; }
mph := MpHolder.{ items = xx 0, sentinel = 42 };
mph.items = xx 0;
print("mp-store-sentinel: {}\n", mph.sentinel);

View File

@@ -42,12 +42,12 @@ main :: () {
print("flags-all: {}\n", pall);
// Cast to int
print("flags-raw: {}\n", cast(s64) perm);
print("flags-raw: {}\n", cast(i64) perm);
// Flags with explicit values
wf : WindowFlags = .vsync | .resizable;
print("flags-explicit: {}\n", wf);
print("flags-explicit-raw: {}\n", cast(s64) wf);
print("flags-explicit-raw: {}\n", cast(i64) wf);
// --- Multi-target assignment (swap) ---
print("--- swap ---\n");
@@ -62,7 +62,7 @@ main :: () {
// Array element swap
{
sarr : [3]s64 = .[1, 2, 3];
sarr : [3]i64 = .[1, 2, 3];
sarr[0], sarr[2] = sarr[2], sarr[0];
print("arr swap: {} {}\n", sarr[0], sarr[2]);
}
@@ -87,7 +87,7 @@ main :: () {
// Destructure from function return
{
dswap :: (a: s64, b: s64) -> (s64, s64) { (b, a) }
dswap :: (a: i64, b: i64) -> (i64, i64) { (b, a) }
dx, dy := dswap(1, 2);
print("fn: {} {}\n", dx, dy);
}

View File

@@ -16,9 +16,9 @@ main :: () {
ca_a += ca_b;
print("f64+=f32: {}\n", ca_a);
ca_c : s64 = 100;
ca_d : s32 = 7;
ca_c : i64 = 100;
ca_d : i32 = 7;
ca_c -= ca_d;
print("s64-=s32: {}\n", ca_c);
print("i64-=i32: {}\n", ca_c);
}
}

View File

@@ -4,7 +4,7 @@
#import "modules/std/test.sx";
pkg :: #import "tests/fixtures/testpkg";
Point :: struct { x, y: s32; }
Point :: struct { x, y: i32; }
main :: () {

View File

@@ -1,4 +1,4 @@
// A local declared with a reserved/builtin type-name spelling (`s2` is the
// A local declared with a reserved/builtin type-name spelling (`i2` is the
// arbitrary-width `sN` integer type) is rejected at the declaration site.
// Previously such a name parsed as a `.type_expr`, so address-of sites
// mis-lowered it (load-by-value to a `ptr` param → LLVM verifier abort, or a
@@ -6,8 +6,8 @@
// error at the declaration; exit 1.
#import "modules/std.sx";
main :: () -> s32 {
s2 := 42;
print("s2: {}\n", s2);
main :: () -> i32 {
i2 := 42;
print("i2: {}\n", i2);
return 0;
}

View File

@@ -11,7 +11,7 @@ main :: () {
// ========================================================
print("=== 23. Nested Arrays ===\n");
{
matrix : [2][3]s32 = .[ .[1, 2, 3], .[4, 5, 6] ];
matrix : [2][3]i32 = .[ .[1, 2, 3], .[4, 5, 6] ];
print("m[0][0]: {}\n", matrix[0][0]);
print("m[0][2]: {}\n", matrix[0][2]);
print("m[1][0]: {}\n", matrix[1][0]);

View File

@@ -9,25 +9,25 @@ main :: () {
// === 26. #using struct composition ===
print("=== 26. #using ===\n");
{
UBase :: struct { x: s32; y: s32; }
UExt :: struct { #using UBase; z: s32; }
UBase :: struct { x: i32; y: i32; }
UExt :: struct { #using UBase; z: i32; }
e := UExt.{ x = 1, y = 2, z = 3 };
print("using-x: {}\n", e.x);
print("using-y: {}\n", e.y);
print("using-z: {}\n", e.z);
// #using in middle position
UHeader :: struct { version: s32; }
UPacket :: struct { id: s32; #using UHeader; payload: s32; }
UHeader :: struct { version: i32; }
UPacket :: struct { id: i32; #using UHeader; payload: i32; }
p := UPacket.{ id = 10, version = 42, payload = 99 };
print("pkt-id: {}\n", p.id);
print("pkt-ver: {}\n", p.version);
print("pkt-pay: {}\n", p.payload);
// Multiple #using
UPos :: struct { px: s32; py: s32; }
UCol :: struct { r: s32; g: s32; }
USprite :: struct { #using UPos; #using UCol; scale: s32; }
UPos :: struct { px: i32; py: i32; }
UCol :: struct { r: i32; g: i32; }
USprite :: struct { #using UPos; #using UCol; scale: i32; }
s := USprite.{ px = 10, py = 20, r = 255, g = 128, scale = 1 };
print("sprite-px: {}\n", s.px);
print("sprite-r: {}\n", s.r);

View File

@@ -20,7 +20,7 @@ main :: () {
single := (42,);
print("{}\n", single.0);
zeroed : (s32, s32) = ---;
zeroed : (i32, i32) = ---;
print("{}\n", zeroed.0);
print("{}\n", zeroed.1);
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,28 +4,28 @@
#import "modules/std/test.sx";
pkg :: #import "tests/fixtures/testpkg";
Point :: struct { x, y: s32; }
Point :: struct { x, y: i32; }
add :: (a: s32, b: s32) -> s32 { a + b }
add :: (a: i32, b: i32) -> i32 { a + b }
Counter :: protocol {
inc :: ();
get :: () -> s32;
get :: () -> i32;
}
Summable :: protocol {
sum :: () -> s32;
sum :: () -> i32;
}
SimpleCounter :: struct { val: s32; }
SimpleCounter :: struct { val: i32; }
impl Counter for SimpleCounter {
inc :: (self: *SimpleCounter) { self.val += 1; }
get :: (self: *SimpleCounter) -> s32 { self.val }
get :: (self: *SimpleCounter) -> i32 { self.val }
}
impl Summable for Point {
sum :: (self: *Point) -> s32 { self.x + self.y }
sum :: (self: *Point) -> i32 { self.x + self.y }
}
// Phase 2: #inline protocol for dynamic dispatch
@@ -37,7 +37,7 @@ Pair :: struct ($T: Type) {
}
impl Summable for Pair($T) {
sum :: (self: *Pair(T)) -> s32 {
sum :: (self: *Pair(T)) -> i32 {
xx self.a + xx self.b
}
}
@@ -46,10 +46,10 @@ impl Summable for Pair($T) {
// Init block test struct
Builder :: struct {
total: s32;
count: s32;
total: i32;
count: i32;
add :: (self: *Builder, val: s32) {
add :: (self: *Builder, val: i32) {
self.total += val;
self.count += 1;
}
@@ -104,7 +104,7 @@ main :: () {
// IB5: init block + auto type erasure combined
{
use_counter :: (c: Counter) -> s32 { c.inc(); c.inc(); c.get() }
use_counter :: (c: Counter) -> i32 { c.inc(); c.inc(); c.get() }
result := use_counter(SimpleCounter.{ val = 0 } {
self.val = 50;
});
@@ -138,10 +138,10 @@ main :: () {
// SM2: Shorthand in variable declaration with explicit type
{
Pair :: struct {
a: s64;
b: s64;
a: i64;
b: i64;
make :: (a: s64, b: s64) -> Pair {
make :: (a: i64, b: i64) -> Pair {
Pair.{ a = a, b = b }
}
}
@@ -188,13 +188,13 @@ main :: () {
c : usize = a + 8;
print("usize+8: {}\n", c);
// coercion from s32
x : s32 = 10;
// coercion from i32
x : i32 = 10;
y : usize = xx x;
print("s32->usize: {}\n", y);
print("i32->usize: {}\n", y);
// coercion to s64
z : s64 = xx a;
print("usize->s64: {}\n", z);
// coercion to i64
z : i64 = xx a;
print("usize->i64: {}\n", z);
}
}

View File

@@ -1,6 +1,6 @@
// Forward identifier type alias — an alias whose target is declared LATER
// in the file resolves the same as an ordered one. `MyChain :: MyInt;`
// appears before `MyInt :: s32;`, yet `MyChain` resolves to `s32` and a
// appears before `MyInt :: i32;`, yet `MyChain` resolves to `i32` and a
// forward chain (`A :: B; B :: C; C :: u8;`) converges too.
// Regression (issue 0069): the scan only registered identifier aliases whose
// target was already known, so a forward alias was falsely flagged
@@ -8,17 +8,17 @@
#import "modules/std.sx";
MyChain :: MyInt;
MyInt :: s32;
MyInt :: i32;
A :: B;
B :: C;
C :: u8;
main :: () -> s32 {
main :: () -> i32 {
v: MyChain = 7;
n: A = 3;
print("chain s32: {}\n", size_of(MyChain));
print("chain i32: {}\n", size_of(MyChain));
print("forward u8: {}\n", size_of(A));
print("v + n: {}\n", v + cast(s32) n);
print("v + n: {}\n", v + cast(i32) n);
return v;
}

View File

@@ -1,6 +1,6 @@
// Forward identifier type alias as a TOP-LEVEL annotation — a global var
// and a typed module constant whose annotation is a forward alias
// (`A :: B; B :: s32;`) resolve to the alias target, the same as the
// (`A :: B; B :: i32;`) resolve to the alias target, the same as the
// ordered form, instead of a fabricated stub.
// Regression (issue 0070): top-level global / typed-const annotations were
// resolved inside the scan loop BEFORE the forward-alias fixpoint ran, so
@@ -10,12 +10,12 @@
#import "modules/std.sx";
A :: B;
B :: s32;
B :: i32;
g : A = 7;
K : A : 35;
main :: () -> s32 {
main :: () -> i32 {
print("global g: {}\n", g);
print("const K: {}\n", K);
return g + K;

View File

@@ -1,18 +1,18 @@
// Top-level global initialized from a module constant copies the constant's
// value (not a silent zero). `K : A : 42; g : A = K;` resolves the forward
// alias `A` to `s32` and materializes `g`'s static initializer from `K`.
// alias `A` to `i32` and materializes `g`'s static initializer from `K`.
// Regression (issue 0071): `registerTopLevelGlobal`'s init_val switch only
// handled literals/array/struct literals; an identifier initializer fell
// through to a null payload and the global silently zero-initialized.
#import "modules/std.sx";
A :: B;
B :: s32;
B :: i32;
K : A : 42;
g : A = K;
main :: () -> s32 {
main :: () -> i32 {
print("g={}\n", g);
return g;
}

View File

@@ -7,14 +7,14 @@
// type-named identifiers).
#import "modules/std.sx";
Hasher :: struct { total: s64 = 0; count: s64 = 0; }
Hasher :: struct { total: i64 = 0; count: i64 = 0; }
update :: ufcs (self: *Hasher, n: s64) {
update :: ufcs (self: *Hasher, n: i64) {
self.total += n;
self.count += 1;
}
main :: () -> s32 {
main :: () -> i32 {
hasher := Hasher.{ total = 0, count = 0 };
update(@hasher, 10); // explicit address-of receiver
hasher.update(20); // autoref receiver

View File

@@ -9,14 +9,14 @@
#import "modules/std.sx";
g : [3]s64 = .[10, 20, 30];
g : [3]i64 = .[10, 20, 30];
Pair :: struct { a: s64; b: s64; }
Pair :: struct { a: i64; b: i64; }
gp : [2]Pair = .[ .{ a = 1, b = 2 }, .{ a = 3, b = 4 } ];
grid : [2][3]s64 = .[ .[0, 0, 0], .[0, 0, 0] ];
grid : [2][3]i64 = .[ .[0, 0, 0], .[0, 0, 0] ];
write_global :: (i: s64, v: s64) { g[i] = v; }
write_global :: (i: i64, v: i64) { g[i] = v; }
main :: () {
// Scalar global array — const index.
@@ -39,7 +39,7 @@ main :: () {
print("gp[0]={},{}\n", gp[0].a, gp[0].b); // 10,20
print("gp[j]={},{}\n", gp[j].a, gp[j].b); // 30,40
// Nested-array global — element is [3]s64, recursive indexed lvalue.
// Nested-array global — element is [3]i64, recursive indexed lvalue.
grid[1][2] = 7;
r := 0;
grid[r][0] = 5;

View File

@@ -11,8 +11,8 @@
#import "modules/std.sx";
Pair :: struct { a: s64; b: s64; }
WithArr :: struct { id: s64; xs: [3]s64; }
Pair :: struct { a: i64; b: i64; }
WithArr :: struct { id: i64; xs: [3]i64; }
// global array of struct literals
pairs : [2]Pair = .[ .{ a = 1, b = 2 }, .{ a = 3, b = 4 } ];

View File

@@ -7,19 +7,19 @@
// `.null_literal` arm, so a `null` in a pointer field made the whole aggregate
// look non-constant and the global was rejected with "must be initialized by a
// compile-time constant". The fix serializes a null literal to a constant zero
// pointer (the same way a top-level pointer global `p : *s64 = null;` does)
// pointer (the same way a top-level pointer global `p : *i64 = null;` does)
// while still rejecting genuinely non-constant fields (see diagnostics 1126).
#import "modules/std.sx";
Box :: struct { p: *s64; marker: s64; }
Inner :: struct { q: *s64; tag: s64; }
Outer :: struct { inner: Inner; label: s64; }
Box :: struct { p: *i64; marker: i64; }
Inner :: struct { q: *i64; tag: i64; }
Outer :: struct { inner: Inner; label: i64; }
// array-of-struct with null pointer fields + scalar neighbors
boxes : [2]Box = .[ .{ p = null, marker = 11 }, .{ p = null, marker = 22 } ];
// global array of all-null pointers
ptrs : [3]*s64 = .[ null, null, null ];
ptrs : [3]*i64 = .[ null, null, null ];
// nested: struct containing a struct with a null pointer field
nested : [2]Outer = .[
.{ inner = .{ q = null, tag = 1 }, label = 100 },

View File

@@ -19,7 +19,7 @@ Color :: enum u8 { red; green; blue; }
Code :: enum u16 { ok :: 200; not_found :: 404; teapot :: 418; }
Pair :: struct { a: Color; b: Color; }
Row :: struct { status: Code; pad: s64; }
Row :: struct { status: Code; pad: i64; }
// scalar enum global
chosen : Color = .green;

View File

@@ -15,18 +15,18 @@
N :: 4;
M :: 3;
P :: struct { x: s64; y: s64; }
P :: struct { x: i64; y: i64; }
// Type aliases whose dimension is the named const N (stateless registration).
Arr :: [N]s64;
Arr :: [N]i64;
SArr :: [N]string;
// Inline union field with a named-const dimension (stateless registration).
U :: union { a: [N]s64; tag: s64; }
U :: union { a: [N]i64; tag: i64; }
main :: () {
// Scalar elements (direct local): store then read back.
a : [N]s64 = ---;
a : [N]i64 = ---;
a[0] = 7;
a[3] = 42;
print("scalar a0={} a3={}\n", a[0], a[3]);
@@ -35,7 +35,7 @@ main :: () {
s : [N]string = ---;
s[0] = "hi";
s[1] = "yo";
print("string s0={} s1={}\n", s[0], s[1]);
print("string i0={} i1={}\n", s[0], s[1]);
// Struct elements (direct local).
ps : [N]P = ---;
@@ -43,7 +43,7 @@ main :: () {
ps[2] = P.{ x = 5, y = 6 };
print("struct p0x={} p0y={} p2x={}\n", ps[0].x, ps[0].y, ps[2].x);
// Type-alias dimension (scalar): same layout as the direct `[N]s64`.
// Type-alias dimension (scalar): same layout as the direct `[N]i64`.
aa : Arr = ---;
aa[0] = 11;
aa[3] = 99;
@@ -53,10 +53,10 @@ main :: () {
sa : SArr = ---;
sa[0] = "al";
sa[2] = "ok";
print("alias s0={} s2={}\n", sa[0], sa[2]);
print("alias i0={} i2={}\n", sa[0], sa[2]);
// Nested fixed array `[N][M]s64`: both dimensions are named consts.
grid : [N][M]s64 = ---;
// Nested fixed array `[N][M]i64`: both dimensions are named consts.
grid : [N][M]i64 = ---;
grid[0][0] = 1;
grid[3][2] = 8;
print("nested g00={} g32={}\n", grid[0][0], grid[3][2]);

View File

@@ -7,14 +7,14 @@
// bytes and returned garbage (0).
#import "modules/std.sx";
count_nope :: (xs: []string) -> s64 {
count_nope :: (xs: []string) -> i64 {
n := 0;
i := 0;
while i < xs.len { if xs[i] == "nope" { n += 1; } i += 1; }
return n;
}
sum :: (xs: []s64) -> s64 {
sum :: (xs: []i64) -> i64 {
s := 0;
i := 0;
while i < xs.len { s += xs[i]; i += 1; }
@@ -29,6 +29,6 @@ main :: () {
// numeric slice: direct literal vs local-bound — both sum to 100.
print("num direct={}\n", sum(.[10, 20, 30, 40]));
nums : []s64 = .[10, 20, 30, 40];
nums : []i64 = .[10, 20, 30, 40];
print("num local={}\n", sum(nums));
}

View File

@@ -1,5 +1,5 @@
// A nested array/slice literal (`.[.[1, 2], .[3, 4]]`) at an expected slice-of-
// slices type (`[][]s64`) materializes each inner `[N]T` literal as a real `[]T`
// slices type (`[][]i64`) materializes each inner `[N]T` literal as a real `[]T`
// slice, so indexing the inner slice in the callee reads element contents
// correctly — for both the local-bound form and the direct-call-argument form.
// Regression (issue 0085): inner literals were appended as raw `[N]T` arrays
@@ -9,7 +9,7 @@
// recurses with the nesting, so every level coerces.
#import "modules/std.sx";
sum_nested :: (xss: [][]s64) -> s64 {
sum_nested :: (xss: [][]i64) -> i64 {
total := 0;
i := 0;
while i < xss.len {
@@ -20,7 +20,7 @@ sum_nested :: (xss: [][]s64) -> s64 {
return total;
}
count_x :: (xss: [][]string) -> s64 {
count_x :: (xss: [][]string) -> i64 {
n := 0;
i := 0;
while i < xss.len {
@@ -32,8 +32,8 @@ count_x :: (xss: [][]string) -> s64 {
}
main :: () {
// numeric [][]s64 — local-bound vs direct-arg both sum to 10.
local : [][]s64 = .[.[1, 2], .[3, 4]];
// numeric [][]i64 — local-bound vs direct-arg both sum to 10.
local : [][]i64 = .[.[1, 2], .[3, 4]];
print("num local={}\n", sum_nested(local));
print("num direct={}\n", sum_nested(.[.[1, 2], .[3, 4]]));

View File

@@ -1,5 +1,5 @@
// A named-const array dimension lays out identically whether the const is
// TYPED (`N : s64 : 16`) or untyped (`N :: 16`), used DIRECTLY (`a : [N]T`) or
// TYPED (`N : i64 : 16`) or untyped (`N :: 16`), used DIRECTLY (`a : [N]T`) or
// through a type alias (`Arr :: [N]T`), and regardless of whether the const is
// declared before or after the alias that consumes it.
//
@@ -13,22 +13,22 @@
// stateful and stateless paths share one dimension resolver.
#import "modules/std.sx";
NT : s64 : 8; // typed const used as a dimension
NT : i64 : 8; // typed const used as a dimension
P :: struct { x: s64; y: s64; }
P :: struct { x: i64; y: i64; }
// Type aliases whose dimension is the TYPED const NT (stateless registration).
TArr :: [NT]s64;
TArr :: [NT]i64;
TSArr :: [NT]string;
TPArr :: [NT]P;
// Forward reference: this alias is declared BEFORE its dimension const NF.
FArr :: [NF]s64;
FArr :: [NF]i64;
NF :: 5;
main :: () {
// Typed-const dimension, DIRECT local decl.
d : [NT]s64 = ---;
d : [NT]i64 = ---;
d[0] = 3;
d[7] = 21;
print("direct d0={} d7={} len={}\n", d[0], d[7], d.len);
@@ -43,7 +43,7 @@ main :: () {
s : TSArr = ---;
s[0] = "hi";
s[7] = "yo";
print("alias s0={} s7={}\n", s[0], s[7]);
print("alias i0={} i7={}\n", s[0], s[7]);
// Typed-const dimension via ALIAS (struct elements).
ps : TPArr = ---;
@@ -52,7 +52,7 @@ main :: () {
print("alias p0x={} p0y={} p7x={}\n", ps[0].x, ps[0].y, ps[7].x);
// Nested fixed array whose both dimensions are the typed const NT.
grid : [NT][NT]s64 = ---;
grid : [NT][NT]i64 = ---;
grid[0][0] = 1;
grid[7][7] = 10;
print("nested g00={} g77={}\n", grid[0][0], grid[7][7]);

View File

@@ -16,50 +16,50 @@
M :: 4;
N :: 6;
TK : s64 : 2; // typed const, used inside an expression dimension
TK : i64 : 2; // typed const, used inside an expression dimension
P :: struct { x: s64; y: s64; }
P :: struct { x: i64; y: i64; }
AddAlias :: [M + 1]s64; // 5
MulAlias :: [M * N]s64; // 24
SubAlias :: [N - M]s64; // 2
NestAlias :: [M + N - 1]s64; // 9
ParenAlias :: [(M + 1) * 2]s64; // 10
TypedAlias :: [M + TK]s64; // 6
AddAlias :: [M + 1]i64; // 5
MulAlias :: [M * N]i64; // 24
SubAlias :: [N - M]i64; // 2
NestAlias :: [M + N - 1]i64; // 9
ParenAlias :: [(M + 1) * 2]i64; // 10
TypedAlias :: [M + TK]i64; // 6
StrAlias :: [M + 1]string; // 5, slice/pointer elements
StructAlias :: [M + 1]P; // 5, struct elements
main :: () {
// const + literal: direct and via alias resolve to the same length.
add_d : [M + 1]s64 = ---;
add_d : [M + 1]i64 = ---;
add_a : AddAlias = ---;
add_d[4] = 7;
add_a[4] = 7;
print("add direct.len={} alias.len={} d4={} a4={}\n", add_d.len, add_a.len, add_d[4], add_a[4]);
// const * const.
mul_d : [M * N]s64 = ---;
mul_d : [M * N]i64 = ---;
mul_a : MulAlias = ---;
mul_d[23] = 230;
mul_a[23] = 230;
print("mul direct.len={} alias.len={} d23={} a23={}\n", mul_d.len, mul_a.len, mul_d[23], mul_a[23]);
// const - const.
sub_d : [N - M]s64 = ---;
sub_d : [N - M]i64 = ---;
sub_a : SubAlias = ---;
sub_d[1] = 9;
sub_a[1] = 9;
print("sub direct.len={} alias.len={} d1={} a1={}\n", sub_d.len, sub_a.len, sub_d[1], sub_a[1]);
// nested and parenthesised forms (direct vs alias).
nest_d : [M + N - 1]s64 = ---;
nest_d : [M + N - 1]i64 = ---;
nest_a : NestAlias = ---;
paren_d : [(M + 1) * 2]s64 = ---;
paren_d : [(M + 1) * 2]i64 = ---;
paren_a : ParenAlias = ---;
print("nest direct.len={} alias.len={} paren direct.len={} alias.len={}\n", nest_d.len, nest_a.len, paren_d.len, paren_a.len);
// typed const inside the expression dimension.
typ_d : [M + TK]s64 = ---;
typ_d : [M + TK]i64 = ---;
typ_a : TypedAlias = ---;
print("typed direct.len={} alias.len={}\n", typ_d.len, typ_a.len);
@@ -67,7 +67,7 @@ main :: () {
str_a : StrAlias = ---;
str_a[0] = "hi";
str_a[4] = "yo";
print("str alias.len={} s0={} s4={}\n", str_a.len, str_a[0], str_a[4]);
print("str alias.len={} i0={} i4={}\n", str_a.len, str_a[0], str_a[4]);
// struct elements.
ps : StructAlias = ---;

View File

@@ -1,8 +1,8 @@
// An array dimension accepts any compile-time numeric constant whose value is a
// positive INTEGRAL number — an integral float (`4.0`) folds to its integer just
// like `4`. A float-typed const (`N : f64 : 4.0`), an untyped-float const
// (`M :: 4.0`), and a direct float literal (`[4.0]s64`) all lay out the same
// `[4]s64` as the integer spelling, so element store/read is in bounds.
// (`M :: 4.0`), and a direct float literal (`[4.0]i64`) all lay out the same
// `[4]i64` as the integer spelling, so element store/read is in bounds.
//
// Regression (issue 0083 / F0.4 attempt 8, Agra ruling): an integral float used
// as a dimension was wrongly rejected "must be a compile-time integer constant".
@@ -15,15 +15,15 @@ N : f64 : 4.0; // float-typed const
M :: 4.0; // untyped float const
main :: () {
a : [N]s64 = ---; // dim from a float-typed const
a : [N]i64 = ---; // dim from a float-typed const
a[0] = 10; a[3] = 40;
print("a len={} a0={} a3={}\n", a.len, a[0], a[3]);
b : [M]s64 = ---; // dim from an untyped float const
b : [M]i64 = ---; // dim from an untyped float const
b[1] = 21;
print("b len={} b1={}\n", b.len, b[1]);
c : [4.0]s64 = ---; // direct integral-float-literal dim
c : [4.0]i64 = ---; // direct integral-float-literal dim
c[2] = 32;
print("c len={} c2={}\n", c.len, c[2]);
}

View File

@@ -4,9 +4,9 @@
// SAME leaf forms to the SAME value through one shared evaluator
// (`program_index.evalConstIntExpr` / `moduleConstInt`). The leaf forms
// exercised here: untyped int const (`M`), a named const with an EXPRESSION RHS
// (`N :: M + 1`), a typed-int const (`S : s64 : 5`), an integral float const
// (`N :: M + 1`), a typed-int const (`S : i64 : 5`), an integral float const
// (`F :: 4.0` ≡ 4), and an ALIASED integer constraint (`Count :: u32`,
// `Small :: s8`) on a value-param.
// `Small :: i8`) on a value-param.
//
// Regression (issue 0083): two cells of this surface diverged from the rest.
// (1) A named const whose RHS is an expression (`N :: M + 1`) did not fold as a
@@ -20,27 +20,27 @@
M :: 2; // untyped int const
N :: M + 1; // named const, EXPRESSION RHS (== 3)
S : s64 : 5; // typed-int const
S : i64 : 5; // typed-int const
KU : u32 : 3; // typed-u32 const
F :: 4.0; // integral float const (== 4)
Count :: u32; // integer ALIAS — value-param constraint
Small :: s8; // integer ALIAS — value-param constraint
Small :: i8; // integer ALIAS — value-param constraint
ArrN :: [N]s64; // array dim via alias: expression const (3)
ArrF :: [F]s64; // array dim via alias: integral float (4)
ArrS :: [S]s64; // array dim via alias: typed const (5)
ArrN :: [N]i64; // array dim via alias: expression const (3)
ArrF :: [F]i64; // array dim via alias: integral float (4)
ArrS :: [S]i64; // array dim via alias: typed const (5)
Buf :: struct ($K: u32, $T: Type) { data: [K]T; }
BufC :: struct ($K: Count, $T: Type) { data: [K]T; } // ALIASED u32 constraint
BufS :: struct ($K: Small, $T: Type) { data: [K]T; } // ALIASED s8 constraint
BufS :: struct ($K: Small, $T: Type) { data: [K]T; } // ALIASED i8 constraint
Make :: ($K: u32, $T: Type) -> Type { return [K]T; } // type-fn value-param
main :: () {
// array dimension — DIRECT
a : [N]s64 = ---; a[0] = 7; a[2] = 9;
a : [N]i64 = ---; a[0] = 7; a[2] = 9;
print("dim.direct.expr: len={} a0={} a2={}\n", a.len, a[0], a[2]);
f : [F]s64 = ---; f[3] = 40;
f : [F]i64 = ---; f[3] = 40;
print("dim.direct.float: len={} f3={}\n", f.len, f[3]);
// array dimension — via type ALIAS
@@ -54,13 +54,13 @@ main :: () {
v4 : Vector(F, f32) = .[1.0, 2.0, 3.0, 4.0];
print("lane.float4: {}\n", v4.w);
// generic value-param — struct binder: expr const, aliased u32, aliased s8
bn : Buf(N, s64) = ---; bn.data[2] = 30; print("vp.struct.expr: len={} v={}\n", bn.data.len, bn.data[2]);
bc : BufC(KU, s64) = ---; bc.data[2] = 31; print("vp.struct.alias.u32: len={} v={}\n", bc.data.len, bc.data[2]);
bs : BufS(4, s64) = ---; bs.data[3] = 32; print("vp.struct.alias.s8: len={} v={}\n", bs.data.len, bs.data[3]);
// generic value-param — struct binder: expr const, aliased u32, aliased i8
bn : Buf(N, i64) = ---; bn.data[2] = 30; print("vp.struct.expr: len={} v={}\n", bn.data.len, bn.data[2]);
bc : BufC(KU, i64) = ---; bc.data[2] = 31; print("vp.struct.alias.u32: len={} v={}\n", bc.data.len, bc.data[2]);
bs : BufS(4, i64) = ---; bs.data[3] = 32; print("vp.struct.alias.i8: len={} v={}\n", bs.data.len, bs.data[3]);
// generic value-param — type-fn binder: expr const
mk : Make(N, s64) = ---; mk[2] = 33; print("vp.typefn.expr: len={} v={}\n", mk.len, mk[2]);
mk : Make(N, i64) = ---; mk[2] = 33; print("vp.typefn.expr: len={} v={}\n", mk.len, mk[2]);
// inline-for bound — expr const (3) and integral float (4)
s := 0; inline for 0..N (i) { s += i; } print("for.expr: {}\n", s); // 0+1+2 = 3

View File

@@ -8,10 +8,10 @@
// "positive integral", which wrongly implied `[0]T` / `Box(0)` are illegal.
#import "modules/std.sx";
Box :: struct($N: u32) { items: [N]s64; }
Box :: struct($N: u32) { items: [N]i64; }
main :: () {
a : [0]s64 = ---;
a : [0]i64 = ---;
print("array_dim={}\n", a.len);
b : Box(0) = ---;

View File

@@ -5,61 +5,61 @@
// `usize`/`isize` (target-width). Usable in expressions and in array-dimension
// position via the comptime-int path (`[u8.max]T`).
//
// The extreme values that the s64-based integer formatter cannot render
// directly — `s64.min` (i64::MIN) and the all-ones `u64.max`/`usize.max` — are
// The extreme values that the i64-based integer formatter cannot render
// directly — `i64.min` (i64::MIN) and the all-ones `u64.max`/`usize.max` — are
// asserted EXACTLY via comparison and untagged-union bit reinterpret, never via
// the formatter (which prints i64::MIN as a bare "-" and u64.max as "-1").
#import "modules/std.sx";
// Untagged union for the exact u64.max bit-reinterpret check.
UU :: union { u: u64; s: s64; }
UU :: union { u: u64; s: i64; }
main :: () -> s32 {
main :: () -> i32 {
// Sub-byte widths — arbitrary bit-width arithmetic, not a per-name table.
print("s1.min={} s1.max={}\n", s1.min, s1.max); // -1 0
print("s2.min={} s2.max={}\n", s2.min, s2.max); // -2 1
print("s3.max={}\n", s3.max); // 3
print("i1.min={} i1.max={}\n", i1.min, i1.max); // -1 0
print("i2.min={} i2.max={}\n", i2.min, i2.max); // -2 1
print("i3.max={}\n", i3.max); // 3
print("u1.min={} u1.max={}\n", u1.min, u1.max); // 0 1
print("u2.max={}\n", u2.max); // 3
// Byte / word widths.
print("s8.min={} s8.max={}\n", s8.min, s8.max); // -128 127
print("i8.min={} i8.max={}\n", i8.min, i8.max); // -128 127
print("u8.max={}\n", u8.max); // 255
print("s32.min={} s32.max={}\n", s32.min, s32.max); // -2147483648 2147483647
print("i32.min={} i32.max={}\n", i32.min, i32.max); // -2147483648 2147483647
// s64 extremes: max prints; min (i64::MIN) is pinned by relation since the
// i64 extremes: max prints; min (i64::MIN) is pinned by relation since the
// formatter cannot render it (this is independent of this feature).
print("s64.max={}\n", s64.max); // 9223372036854775807
print("s64.min+1 == -(s64.max): {}\n", s64.min + 1 == -9223372036854775807); // true
print("s64.min + s64.max == -1: {}\n", s64.min + s64.max == -1); // true
print("i64.max={}\n", i64.max); // 9223372036854775807
print("i64.min+1 == -(i64.max): {}\n", i64.min + 1 == -9223372036854775807); // true
print("i64.min + i64.max == -1: {}\n", i64.min + i64.max == -1); // true
// u64.max / usize.max = all-ones (18446744073709551615); reinterpret to s64
// u64.max / usize.max = all-ones (18446744073709551615); reinterpret to i64
// to confirm the bit pattern is -1 (and NOT a mangled value).
o : UU = ---;
o.u = u64.max;
print("u64.max as s64 == -1: {}\n", o.s == -1); // true
print("u64.max as i64 == -1: {}\n", o.s == -1); // true
o.u = usize.max;
print("usize.max as s64 == -1: {}\n", o.s == -1); // true (host = u64)
print("usize.max as i64 == -1: {}\n", o.s == -1); // true (host = u64)
print("usize.max == u64.max: {}\n", usize.max == u64.max); // true
print("isize.min == s64.min: {}\n", isize.min == s64.min); // true (host = s64)
print("isize.min == i64.min: {}\n", isize.min == i64.min); // true (host = i64)
// Result carries the QUERIED type: each binding is declared with the queried
// type and round-trips, so a mistyped fold (e.g. boxed as Any / widened)
// would not type-check here.
m3 : s3 = s3.max;
m3 : i3 = i3.max;
mu : u8 = u8.max;
ms : s8 = s8.min;
ms : i8 = i8.min;
print("typed: m3={} mu={} ms={}\n", m3, mu, ms); // 3 255 -128
// Array-dimension / comptime-int path: `[u8.max]T` and `[s16.max]T` are
// Array-dimension / comptime-int path: `[u8.max]T` and `[i16.max]T` are
// valid counts (255 and 32767), usable end-to-end.
a : [u8.max]u8 = ---;
a[254] = 7;
print("[u8.max]u8 len={} a[254]={}\n", a.len, a[254]); // 255 7
b : [s16.max]u8 = ---;
b : [i16.max]u8 = ---;
b[32766] = 9;
print("[s16.max]u8 len={} b[32766]={}\n", b.len, b[32766]); // 32767 9
print("[i16.max]u8 len={} b[32766]={}\n", b.len, b[32766]); // 32767 9
return 0;
}

View File

@@ -8,9 +8,9 @@
// Each case is accurate and located at the access; the program exits non-zero.
#import "modules/std.sx";
MyStruct :: struct { a: s64; }
MyStruct :: struct { a: i64; }
main :: () -> s32 {
main :: () -> i32 {
b := bool.max;
s := MyStruct.min;
v := void.max;

View File

@@ -1,10 +1,10 @@
// Backtick raw-identifier escape: a leading backtick makes the following
// identifier RAW — its text excludes the backtick and it is never the
// reserved/builtin keyword, so a reserved type-name spelling (`s2`, `u8`, …)
// reserved/builtin keyword, so a reserved type-name spelling (`i2`, `u8`, …)
// can be used as an ordinary identifier. Exercised in every VALUE position:
// global, local, param, struct field + member access, function name + call,
// and a later reference. (A raw identifier in TYPE position references a
// backtick-declared type instead — see examples/0154.) A *bare* `s2` is still
// backtick-declared type instead — see examples/0154.) A *bare* `i2` is still
// the reserved type name (see examples/1119), so the escape is the only way to
// spell these as values.
// Regression (issue 0089).
@@ -14,22 +14,22 @@
`u8 := 100;
// Function whose name is a reserved type spelling, with a reserved-name param.
`s2 :: (`s1: s64) -> s64 { return `s1 * 2; }
`i2 :: (`i1: i64) -> i64 { return `i1 * 2; }
Point :: struct {
`s2: f64; // field name is a reserved type spelling
`u16: s64;
`i2: f64; // field name is a reserved type spelling
`u16: i64;
}
main :: () {
// Local with a reserved type spelling; later reference resolves to it.
`s64 := 7;
`s64 = `s64 + 1;
print("local = {}\n", `s64);
`i64 := 7;
`i64 = `i64 + 1;
print("local = {}\n", `i64);
print("global = {}\n", `u8);
print("fn = {}\n", `s2(21)); // calls the `s2 function
print("fn = {}\n", `i2(21)); // calls the `i2 function
p := Point.{ `s2 = 2.5, `u16 = 9 };
print("field = {} {}\n", p.`s2, p.`u16);
p := Point.{ `i2 = 2.5, `u16 = 9 };
print("field = {} {}\n", p.`i2, p.`u16);
}

View File

@@ -1,5 +1,5 @@
// Backtick raw identifier across every control-flow / capture / binding form,
// plus bare later uses. A reserved type-name spelling (`s2`, `u8`, …) works as a
// plus bare later uses. A reserved type-name spelling (`i2`, `u8`, …) works as a
// binding name in a destructure, an `if`/`while` optional binding, a `for`
// capture + index, and a match-arm capture; a backtick-named function is
// bare-callable; and a backtick struct field is bare- or backtick-accessible.
@@ -10,37 +10,37 @@
// Regression (issue 0089 — attempt-2 completeness across binding forms).
#import "modules/std.sx";
pair :: () -> (s64, s64) { (1, 2) }
maybe :: () -> ?s64 { return 42; }
pair :: () -> (i64, i64) { (1, 2) }
maybe :: () -> ?i64 { return 42; }
// Function named with a reserved spelling — bare-callable (no backtick at call).
`s2 :: (n: s64) -> s64 { return n + 1; }
`i2 :: (n: i64) -> i64 { return n + 1; }
Quad :: struct { `s1: s32; `s2: s32; }
Quad :: struct { `i1: i32; `i2: i32; }
main :: () -> s32 {
main :: () -> i32 {
// destructure binding names
`u8, rest := pair();
print("dstr = {} {}\n", `u8, rest);
// if optional binding + bare-position reference inside the branch
if `s16 := maybe() {
print("if = {}\n", `s16);
if `i16 := maybe() {
print("if = {}\n", `i16);
}
// while optional binding (name only — the while binding isn't body-exposed)
while `s32 := maybe() {
while `i32 := maybe() {
break;
}
// for capture + index names
xs := [3]s64.{ 10, 20, 30 };
xs := [3]i64.{ 10, 20, 30 };
for xs, 0.. (`bool, `u16) {
print("for = {} @ {}\n", `bool, `u16);
}
// match-arm capture
opt: ?s64 = 5;
opt: ?i64 = 5;
m := if opt == {
case .some: (`string) { `string * 2 }
case .none: { 0 }
@@ -48,10 +48,10 @@ main :: () -> s32 {
print("match = {}\n", m);
// backtick function called BARE and via backtick — both resolve to the fn
print("call = {} {}\n", s2(10), `s2(10));
print("call = {} {}\n", i2(10), `i2(10));
// struct field named with a reserved spelling: bare + backtick member access
q := Quad.{ `s1 = 7, `s2 = 9 };
print("field = {} {} | {} {}\n", q.s1, q.s2, q.`s1, q.`s2);
q := Quad.{ `i1 = 7, `i2 = 9 };
print("field = {} {} | {} {}\n", q.i1, q.i2, q.`i1, q.`i2);
return 0;
}

View File

@@ -1,22 +1,22 @@
// Backtick raw-identifier escape at the `::` declaration sites: a leading
// backtick makes a CONSTANT name and a FUNCTION name raw, so a reserved type
// spelling (`s2`, `u8`) can be declared and used. Complements examples/0151
// spelling (`i2`, `u8`) can be declared and used. Complements examples/0151
// (var / param / field / global). The backtick fn is callable both via the
// backtick (`` `u8(5) ``) and bare (`u8(5)`) — the bare reserved-name callee
// resolves to the raw fn because its declaration is raw (issue 0089). A *bare*
// `s2 :: …` / `u8 :: …` declaration is still the reserved-name error (see
// `i2 :: …` / `u8 :: …` declaration is still the reserved-name error (see
// examples/1140).
// Regression (issue 0089).
#import "modules/std.sx";
// Constant whose name is a reserved type spelling.
`s2 :: 2.5;
`i2 :: 2.5;
// Function whose name is a reserved type spelling.
`u8 :: (n: s64) -> s64 { return n + 7; }
`u8 :: (n: i64) -> i64 { return n + 7; }
main :: () -> s32 {
print("const = {}\n", `s2);
main :: () -> i32 {
print("const = {}\n", `i2);
print("fn tick = {}\n", `u8(5));
print("fn bare = {}\n", u8(5));
return 0;

View File

@@ -1,8 +1,8 @@
// Backtick raw identifier in TYPE position (the universal model, issue 0089):
// `` `name `` is the LITERAL identifier `name` used as a type reference, never
// the builtin/reserved spelling. A reserved type spelling (`s2`, `u8`, …) can
// the builtin/reserved spelling. A reserved type spelling (`i2`, `u8`, …) can
// therefore both DECLARE a type (struct / enum / union / error-set / alias) and
// be REFERENCED as that type via the backtick — while a BARE `s2` in type
// be REFERENCED as that type via the backtick — while a BARE `i2` in type
// position remains the signed-int type (see `add` below) and a bare reserved-
// name declaration still errors (see examples/1141). The backtick is required
// to declare or reference these names; it is never part of the name's text.
@@ -10,18 +10,18 @@
#import "modules/std.sx";
// Type-introducing decls whose NAME is a reserved spelling.
`s2 :: struct { x: s64; }
`s8 :: enum { A; B; }
`u16 :: union { i: s32; f: f32; }
`i2 :: struct { x: i64; }
`i8 :: enum { A; B; }
`u16 :: union { i: i32; f: f32; }
`u32 :: error { Bad, Empty }
RawAlias :: `s2; // alias to a backtick-declared struct
RawAlias :: `i2; // alias to a backtick-declared struct
// A bare `s2` in type position is still the 2-bit signed int.
add :: (a: s2, b: s2) -> s2 { return a + b; }
// A bare `i2` in type position is still the 2-bit signed int.
add :: (a: i2, b: i2) -> i2 { return a + b; }
main :: () -> s32 {
main :: () -> i32 {
// Reference the backtick struct as a type; field access works.
v : `s2 = ---;
v : `i2 = ---;
v.x = 7;
// Reference via a normal alias too.
@@ -29,7 +29,7 @@ main :: () -> s32 {
a.x = 11;
// Backtick enum / union type references.
e : `s8 = .A;
e : `i8 = .A;
u : `u16 = ---;
u.i = 5;
@@ -37,6 +37,6 @@ main :: () -> s32 {
print("alias = {}\n", a.x);
print("enum = {}\n", e == .A);
print("union = {}\n", u.i);
print("bare = {}\n", add(1, 0)); // bare s2 = the 2-bit int type
print("bare = {}\n", add(1, 0)); // bare i2 = the 2-bit int type
return 0;
}

View File

@@ -1,24 +1,24 @@
// Backtick raw identifier at the two remaining binding positions (issue 0089,
// attempt-4): a TYPED constant (`` `s2 : s64 : 5 ``) and a union TAG / field
// (`` `s2: s32 ``). The typed-const form previously slipped past the decl check
// without a name span (caret at 1:1); a bare `s2 : s64 : 5` is still rejected
// attempt-4): a TYPED constant (`` `i2 : i64 : 5 ``) and a union TAG / field
// (`` `i2: i32 ``). The typed-const form previously slipped past the decl check
// without a name span (caret at 1:1); a bare `i2 : i64 : 5` is still rejected
// with the caret ON the name (see examples/1141). A union tag spelled with a
// reserved name works and is accessible bare or backticked.
// Regression (issue 0089 — attempt-4 typed const + union tag).
#import "modules/std.sx";
// Typed constant whose name is a reserved type spelling.
`s2 : s64 : 5;
`i2 : i64 : 5;
// Union whose tags are reserved type spellings.
Mix :: union { `s1: s32; `u8: f32; }
Mix :: union { `i1: i32; `u8: f32; }
main :: () -> s32 {
print("typed const = {}\n", `s2);
main :: () -> i32 {
print("typed const = {}\n", `i2);
m : Mix = ---;
m.`s1 = 42;
print("union tick = {}\n", m.`s1); // backtick member access
print("union bare = {}\n", m.s1); // bare member access — same field
m.`i1 = 42;
print("union tick = {}\n", m.`i1); // backtick member access
print("union bare = {}\n", m.i1); // bare member access — same field
return 0;
}

View File

@@ -1,7 +1,7 @@
// Backtick raw-identifier escape at a STRUCT-BODY constant — both the untyped
// `` `name :: value `` and the typed `` `name : T : value `` forms. A struct
// member constant is a binding site like any top-level const (examples/0153),
// so a reserved type spelling (`s2`, `u8`) needs the backtick to be used as the
// so a reserved type spelling (`i2`, `u8`) needs the backtick to be used as the
// constant's name; the value is read back via `Holder.`name`. A *bare*
// reserved-name struct const still errors with the caret on the name (see
// examples/1142). The backtick is never part of the name's text.
@@ -10,12 +10,12 @@
#import "modules/std.sx";
Holder :: struct {
`s2 :: 5; // untyped raw struct-body const
`u8 : s64 : 9; // typed raw struct-body const
`i2 :: 5; // untyped raw struct-body const
`u8 : i64 : 9; // typed raw struct-body const
}
main :: () -> s32 {
print("untyped = {}\n", Holder.`s2);
main :: () -> i32 {
print("untyped = {}\n", Holder.`i2);
print("typed = {}\n", Holder.`u8);
return 0;
}

View File

@@ -1,26 +1,26 @@
// Backtick raw identifier in PARAMETERIZED type position. A raw type reference
// (`` `s2 ``) flows through the SAME type-expression continuations as a bare
// (`` `i2 ``) flows through the SAME type-expression continuations as a bare
// name, so a reserved-spelled GENERIC template can be instantiated
// (`` `s2(s64) ``) and the result composes under pointer/field wrappers
// (`` *`s2(s64) ``, a struct field typed `` `s2(s64) ``). A bare `s2` in type
// (`` `i2(i64) ``) and the result composes under pointer/field wrappers
// (`` *`i2(i64) ``, a struct field typed `` `i2(i64) ``). A bare `i2` in type
// position is still the 2-bit signed int. Complements examples/0154 (nullary
// raw type references).
// Regression (issue 0089 — attempt-5: the raw type atom no longer parses as a
// terminal `type_expr`; it reaches the parameterized + wrapper continuations).
#import "modules/std.sx";
`s2 :: struct($T: Type) {
`i2 :: struct($T: Type) {
x: $T;
}
Wrapper :: struct {
inner: `s2(s64); // raw parameterized type as a struct field
inner: `i2(i64); // raw parameterized type as a struct field
}
main :: () -> s32 {
v : `s2(s64);
main :: () -> i32 {
v : `i2(i64);
v.x = 7;
p : *`s2(s64) = @v; // pointer to a raw parameterized type
p : *`i2(i64) = @v; // pointer to a raw parameterized type
w : Wrapper = ---;
w.inner.x = 12;
print("val = {}\n", v.x);

View File

@@ -1,14 +1,14 @@
// Reserved-name MEMBER positions are EXEMPT from the reserved-type-name rule:
// a bare reserved spelling (`s2`, `u8`, `s1`, …) is legal as a struct FIELD
// a bare reserved spelling (`i2`, `u8`, `i1`, …) is legal as a struct FIELD
// name, a union TAG name, and a protocol METHOD-SIGNATURE name. These are
// unambiguous — the name sits in a member slot and is reached via `obj.name`
// (or dispatched by string), so it is never type-classified and never
// mislowers. The backtick form is optional there and resolves to the same
// member. Backtick access (`obj.`s2`) and bare access (`obj.s2`) both work.
// member. Backtick access (`obj.`i2`) and bare access (`obj.i2`) both work.
//
// The exemption stops at member SIGNATURES: an `impl` method DEFINITION is a
// real function, so its name is a declaration site (like a free function) and a
// reserved spelling still needs the backtick (`` `s2 :: (self) ``) — bare would
// reserved spelling still needs the backtick (`` `i2 :: (self) ``) — bare would
// be type-classified and mislower (the issue-0076 protection). A bare reserved
// VALUE binding / declaration name still errors (see examples/1119, 1141, 1142).
// Regression (issue 0089 — attempt-7: pins the Agra-ruled member-name exemption).
@@ -16,40 +16,40 @@
// Struct fields spelled with reserved type names — bare is legal.
Holder :: struct {
s2: s64;
u8: s64;
i2: i64;
u8: i64;
}
// Union tags spelled with reserved type names — bare is legal.
Tag :: union {
s1: s32;
i1: i32;
u16: f64;
}
// Protocol method SIGNATURE spelled with a reserved type name — bare is legal.
Speaker :: protocol {
s2 :: () -> s64;
i2 :: () -> i64;
}
Dog :: struct { n: s64; }
Dog :: struct { n: i64; }
impl Speaker for Dog {
`s2 :: (self: *Dog) -> s64 { self.n } // impl DEFINITION → backtick required
`i2 :: (self: *Dog) -> i64 { self.n } // impl DEFINITION → backtick required
}
main :: () -> s32 {
h := Holder.{ s2 = 10, u8 = 20 };
print("fields bare = {} {}\n", h.s2, h.u8); // bare member access
print("fields tick = {} {}\n", h.`s2, h.`u8); // backtick member access
h.s2 = 11;
main :: () -> i32 {
h := Holder.{ i2 = 10, u8 = 20 };
print("fields bare = {} {}\n", h.i2, h.u8); // bare member access
print("fields tick = {} {}\n", h.`i2, h.`u8); // backtick member access
h.i2 = 11;
h.`u8 = 21; // backtick write
print("fields set = {} {}\n", h.s2, h.u8);
print("fields set = {} {}\n", h.i2, h.u8);
t : Tag = ---;
t.s1 = 5;
print("union = {} {}\n", t.s1, t.`s1); // bare + backtick — same tag
t.i1 = 5;
print("union = {} {}\n", t.i1, t.`i1); // bare + backtick — same tag
items : List(Speaker) = .{};
items.append(Dog.{ n = 7 });
print("dispatch = {}\n", items.items[0].s2()); // bare reserved-name method call
print("dispatch = {}\n", items.items[0].i2()); // bare reserved-name method call
return 0;
}

View File

@@ -26,13 +26,13 @@
// `bits` mirrors each float's raw IEEE-754 storage. f64 needs 64 bits, f32 32.
// The f64 union's `bits` (u64) view reads the all-ones-ish positive patterns as
// their true magnitude; its `s` (s64) view pins the negative `f64.min` pattern
// their true magnitude; its `s` (i64) view pins the negative `f64.min` pattern
// (0xFFEF…), whose unsigned form overflows the u64 literal parser, by comparing
// the signed reinterpret to -4503599627370497.
Uf64 :: union { f: f64; bits: u64; s: s64; }
Uf64 :: union { f: f64; bits: u64; s: i64; }
Uf32 :: union { f: f32; bits: u32; }
main :: () -> s32 {
main :: () -> i32 {
o : Uf64 = ---;
// Read `.true_min` (a subnormal) FIRST and through the union only — never via
@@ -45,7 +45,7 @@ main :: () -> s32 {
o.f = f64.max;
print("f64.max {}\n", o.bits == 0x7FEFFFFFFFFFFFFF); // true
// f64.min = -max; its bit pattern 0xFFEFFFFFFFFFFFFF overflows an unsigned u64
// literal, so it is pinned directly via the SIGNED s64 view: -4503599627370497.
// literal, so it is pinned directly via the SIGNED i64 view: -4503599627370497.
o.f = f64.min;
print("f64.min {}\n", o.s == -4503599627370497); // true (bits 0xFFEFFFFFFFFFFFFF)
o.f = f64.epsilon;

View File

@@ -4,8 +4,8 @@
// type, or ANY accessor to a non-numeric type, is a clean compile error — never
// a silent value, never the `.unresolved` sentinel reaching codegen.
//
// - float-only accessor on an integer (`s32.epsilon`, `u8.inf`,
// `s64.true_min`) → a dedicated "applies only to float types" diagnostic
// - float-only accessor on an integer (`i32.epsilon`, `u8.inf`,
// `i64.true_min`) → a dedicated "applies only to float types" diagnostic
// from the accessor intercept, located at the access;
// - any accessor on a non-numeric builtin (`bool.nan`, `string.max`) → the
// "numeric limits apply only to integer and float types" diagnostic;
@@ -14,12 +14,12 @@
// Each case is accurate and located at the access; the program exits non-zero.
#import "modules/std.sx";
MyStruct :: struct { a: s64; }
MyStruct :: struct { a: i64; }
main :: () -> s32 {
a := s32.epsilon;
main :: () -> i32 {
a := i32.epsilon;
b := u8.inf;
c := s64.true_min;
c := i64.true_min;
d := bool.nan;
e := string.max;
f := MyStruct.epsilon;

View File

@@ -1,9 +1,9 @@
// Numeric-limit accessor vs. a raw value binding that shadows a builtin type
// name. A backtick raw identifier (F0.6) can legitimately bind a value whose
// spelling is a reserved numeric type name (`` `f64 ``, `` `s32 ``, `` `u8 ``).
// spelling is a reserved numeric type name (`` `f64 ``, `` `i32 ``, `` `u8 ``).
// Field access on such a value is an ORDINARY field read — the numeric-limit
// intercept (NL.1 integer `.min`/`.max`, NL.2 float `.epsilon`/… ) must NOT
// hijack it. An adjacent BARE `f64.epsilon` / `s32.max` / `u8.max` — which the
// hijack it. An adjacent BARE `f64.epsilon` / `i32.max` / `u8.max` — which the
// parser classifies as a type receiver, not the raw value — STILL folds to the
// numeric limit. Both behaviors coexist: the raw receiver reads the value, the
// bare receiver folds the limit.
@@ -11,59 +11,59 @@
// A raw value binding can reach the intercept through THREE sources, exactly
// mirroring the ordinary identifier field-access path (scope / globals / module
// consts). This example exercises all three: a GLOBAL `` `f32 ``, a MODULE-CONST
// `` `s16 ``, and LOCAL `` `f64 ``/`` `s32 ``/`` `u8 `` — each reads its field,
// `` `i16 ``, and LOCAL `` `f64 ``/`` `i32 ``/`` `u8 `` — each reads its field,
// and the bare spelling of each STILL folds.
//
// Regression (issues 0092 local, 0093 global + module-const): the intercept
// previously treated any identifier whose text matched a builtin numeric type
// name as a TYPE receiver, silently shadowing the in-scope value binding
// (`` `f64.epsilon `` folded to 2^-52, `` `s32.max `` folded to 2147483647 —
// (`` `f64.epsilon `` folded to 2^-52, `` `i32.max `` folded to 2147483647 —
// a silent wrong value). The attempt-3 fix guarded only lexical scope, so
// GLOBAL and MODULE-CONST raw bindings still folded (issue 0093).
#import "modules/std.sx";
FBox :: struct { epsilon: s64; max: s64; min_positive: s64; }
IBox :: struct { max: s64; min: s64; }
UBox :: struct { max: s64; }
FBox :: struct { epsilon: i64; max: i64; min_positive: i64; }
IBox :: struct { max: i64; min: i64; }
UBox :: struct { max: i64; }
// GLOBAL raw value binding whose spelling shadows the builtin `f32`. Reachable
// via `program_index.global_names`, not lexical scope (issue 0093).
`f32 := FBox.{ epsilon = 44, max = 55, min_positive = 66 };
// MODULE-CONST raw value binding whose spelling shadows the builtin `s16`.
// MODULE-CONST raw value binding whose spelling shadows the builtin `i16`.
// Reachable via `program_index.module_const_map` (issue 0093, const variant).
`s16 :: IBox.{ max = 99, min = -99 };
`i16 :: IBox.{ max = 99, min = -99 };
main :: () -> s32 {
main :: () -> i32 {
// LOCAL raw value bindings whose spelling shadows a builtin numeric type name.
`f64 := FBox.{ epsilon = 11, max = 22, min_positive = 33 };
`s32 := IBox.{ max = 78, min = -78 };
`i32 := IBox.{ max = 78, min = -78 };
`u8 := UBox.{ max = 7 };
// Raw receiver → ordinary field READ (the value), never the numeric limit.
print("local f64: epsilon={} max={} min_positive={}\n",
`f64.epsilon, `f64.max, `f64.min_positive); // 11 22 33
print("local s32: max={} min={}\n", `s32.max, `s32.min); // 78 -78
print("local i32: max={} min={}\n", `i32.max, `i32.min); // 78 -78
print("local u8: max={}\n", `u8.max); // 7
// GLOBAL raw receiver → ordinary field READ (issue 0093).
print("global f32: epsilon={} max={} min_positive={}\n",
`f32.epsilon, `f32.max, `f32.min_positive); // 44 55 66
// MODULE-CONST raw receiver → ordinary field READ (issue 0093).
print("const s16: max={} min={}\n", `s16.max, `s16.min); // 99 -99
print("const i16: max={} min={}\n", `i16.max, `i16.min); // 99 -99
// The value-field read carries the field type (s64 here): round-trips
// The value-field read carries the field type (i64 here): round-trips
// through a typed binding, so a mistyped/boxed read would not type-check.
e : s64 = `f64.epsilon;
e : i64 = `f64.epsilon;
print("typed val e={}\n", e); // 11
// Bare receiver (a type receiver, NOT the raw value) → STILL folds to the
// numeric limit, even though a LOCAL (`s32`/`u8`/`f64`), GLOBAL (`f32`), or
// MODULE-CONST (`s16`) value of the same spelling is bound. The bare receiver
// numeric limit, even though a LOCAL (`i32`/`u8`/`f64`), GLOBAL (`f32`), or
// MODULE-CONST (`i16`) value of the same spelling is bound. The bare receiver
// is never blocked by any of the three value sources.
print("lim s32.max={} s32.min={}\n", s32.max, s32.min); // 2147483647 -2147483648
print("lim i32.max={} i32.min={}\n", i32.max, i32.min); // 2147483647 -2147483648
print("lim u8.max={}\n", u8.max); // 255
print("lim s16.max={} s16.min={}\n", s16.max, s16.min); // 32767 -32768
print("lim i16.max={} i16.min={}\n", i16.max, i16.min); // 32767 -32768
// Bare float accessors still fold; the formatter is crude (issue 0090), so
// pin the values by their defining properties rather than by printing.

View File

@@ -1,16 +1,16 @@
// Valid typed module-level constants compile, fold, and print correctly across
// every initializer/annotation pairing the registrar accepts:
// - integer literal → integer (`K : s64 : 4`) — usable as an array count too
// - integer literal → integer (`K : i64 : 4`) — usable as an array count too
// - integer literal → float (`W : f32 : 800`)
// - float literal → float (`PI : f32 : 3.14159`)
// - string literal → string (`S : string : "hi"`)
// - null → pointer (`P : *void : null`)
// - integer EXPRESSION → integer (`KE : s64 : M + 2`) — usable as a count too
// - integer EXPRESSION → integer (`KE : i64 : M + 2`) — usable as a count too
// - integer EXPRESSION → float (`WE : f32 : M + 2`)
// - MIXED int+float EXPRESSION → float (`MF : f64 : M + 0.5`, both operand orders)
// - INTEGRAL float literal → integer (`KF : s64 : 4.0` → 4) — folds under the
// - INTEGRAL float literal → integer (`KF : i64 : 4.0` → 4) — folds under the
// unified narrowing rule (F0.11), usable as a count too
// - INTEGRAL float EXPRESSION → integer (`KFE : s64 : M + 2.0` → 4)
// - INTEGRAL float EXPRESSION → integer (`KFE : i64 : M + 2.0` → 4)
//
// Companion to the negative example 1143: the issue-0088 fix rejects a typed
// const whose initializer mismatches its annotation, and these correctly-typed
@@ -25,21 +25,21 @@
M :: 2;
K : s64 : 4;
K : i64 : 4;
W : f32 : 800;
PI : f32 : 3.14159;
S : string : "hi";
P : *void : null;
KE : s64 : M + 2;
KE : i64 : M + 2;
WE : f32 : M + 2;
MF : f64 : M + 0.5;
MFR : f64 : 0.5 + M;
KF : s64 : 4.0; // integral float literal → folds to 4
KFE : s64 : M + 2.0; // integral float expression → folds to 4
KF : i64 : 4.0; // integral float literal → folds to 4
KFE : i64 : M + 2.0; // integral float expression → folds to 4
main :: () {
// Integer const: prints AND drives an array dimension (len 4).
a : [K]s64 = ---;
a : [K]i64 = ---;
a[0] = 10;
a[3] = 40;
print("K={} len={} a0={} a3={}\n", K, a.len, a[0], a[3]);
@@ -54,7 +54,7 @@ main :: () {
print("P_is_null={}\n", P == null);
// Integer const-EXPRESSION: prints AND drives an array dimension (len 4).
b : [KE]s64 = ---;
b : [KE]i64 = ---;
print("KE={} len={} WE={}\n", KE, b.len, WE);
// Mixed int+float const-EXPRESSION folds to the promoted float (2.5),
@@ -63,6 +63,6 @@ main :: () {
// Integral float const (literal + expression): folds to its integer under
// the unified narrowing rule; `KF` also drives an array dimension (len 4).
cc : [KF]s64 = ---;
cc : [KF]i64 = ---;
print("KF={} len={} KFE={}\n", KF, cc.len, KFE);
}

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