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:
@@ -1,5 +1,5 @@
|
||||
#import "modules/std.sx";
|
||||
|
||||
main :: () -> s32 {
|
||||
main :: () -> i32 {
|
||||
if false then 40 else 42
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
#import "modules/std.sx";
|
||||
main :: () -> s32 {
|
||||
main :: () -> i32 {
|
||||
x := 42;
|
||||
{
|
||||
print("scope opened\n");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#import "modules/std.sx";
|
||||
main :: () -> s32 {
|
||||
main :: () -> i32 {
|
||||
defer print("still here\n");
|
||||
return 42;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#import "modules/std.sx";
|
||||
|
||||
sumOf10 :: () -> s32 {
|
||||
sumOf10 :: () -> i32 {
|
||||
i:= 1;
|
||||
s:=0;
|
||||
while i <= 10 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,6 @@ do_it :: () -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
main :: () -> s32 {
|
||||
main :: () -> i32 {
|
||||
if do_it() then 0 else 1
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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); }
|
||||
|
||||
|
||||
@@ -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]);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 :: () {
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) }
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
Json :: enum {
|
||||
str: string;
|
||||
int_: s64;
|
||||
int_: i64;
|
||||
null_;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -5,7 +5,7 @@ Vec4 :: struct {
|
||||
|
||||
Complex :: struct {
|
||||
foo : enum {
|
||||
S: s32;
|
||||
S: i32;
|
||||
B: struct {
|
||||
val: string;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 :: () {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Overlay :: union {
|
||||
f: f32;
|
||||
i: s32;
|
||||
i: i32;
|
||||
}
|
||||
|
||||
Vec2 :: union {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"); }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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: ");
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
Foo :: struct {
|
||||
running: bool = true;
|
||||
x: s32 = 42;
|
||||
x: i32 = 42;
|
||||
name: string = "default";
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ ok :: () -> Handle { 0 }
|
||||
|
||||
g : Handle = 0;
|
||||
|
||||
main :: () -> s32 {
|
||||
main :: () -> i32 {
|
||||
g = ok();
|
||||
if g == 0 then 0 else 1
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 :: () {
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 } ];
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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]]));
|
||||
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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 = ---;
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) = ---;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user