Merge branch 'flow/sx-foundation/F0.4' into dist-foundation
This commit is contained in:
69
examples/0140-types-named-const-array-dim.sx
Normal file
69
examples/0140-types-named-const-array-dim.sx
Normal file
@@ -0,0 +1,69 @@
|
||||
// A fixed array whose dimension is a module-global named constant
|
||||
// (`N :: 16; [N]T`) has the same layout as a literal-dimension array
|
||||
// (`[16]T`): correct length and element stride for scalar, slice/pointer
|
||||
// (string), and struct element types — on EVERY type-resolution path:
|
||||
// direct local decls, type aliases (`Arr :: [N]T`), nested fixed arrays
|
||||
// (`[N][M]T`), and inline union fields. The named dim must resolve to the
|
||||
// same length whether it flows through the stateful body-lowering resolver
|
||||
// or the stateless registration-time resolver (type_bridge).
|
||||
// Regression (issue 0083): a named-const dim resolved to length 0, giving a
|
||||
// 0-byte alloca — scalar reads returned garbage and string/struct elements
|
||||
// bus-errored. The alias and union-field paths went through the stateless
|
||||
// resolver, which had no const table and silently fabricated a 0 length.
|
||||
#import "modules/std.sx";
|
||||
|
||||
N :: 4;
|
||||
M :: 3;
|
||||
|
||||
P :: struct { x: s64; y: s64; }
|
||||
|
||||
// Type aliases whose dimension is the named const N (stateless registration).
|
||||
Arr :: [N]s64;
|
||||
SArr :: [N]string;
|
||||
|
||||
// Inline union field with a named-const dimension (stateless registration).
|
||||
U :: union { a: [N]s64; tag: s64; }
|
||||
|
||||
main :: () {
|
||||
// Scalar elements (direct local): store then read back.
|
||||
a : [N]s64 = ---;
|
||||
a[0] = 7;
|
||||
a[3] = 42;
|
||||
print("scalar a0={} a3={}\n", a[0], a[3]);
|
||||
|
||||
// Slice/pointer elements (string, direct local): used to bus-error.
|
||||
s : [N]string = ---;
|
||||
s[0] = "hi";
|
||||
s[1] = "yo";
|
||||
print("string s0={} s1={}\n", s[0], s[1]);
|
||||
|
||||
// Struct elements (direct local).
|
||||
ps : [N]P = ---;
|
||||
ps[0] = P.{ x = 1, y = 2 };
|
||||
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`.
|
||||
aa : Arr = ---;
|
||||
aa[0] = 11;
|
||||
aa[3] = 99;
|
||||
print("alias a0={} a3={}\n", aa[0], aa[3]);
|
||||
|
||||
// Type-alias dimension (string): no bus error, correct reads.
|
||||
sa : SArr = ---;
|
||||
sa[0] = "al";
|
||||
sa[2] = "ok";
|
||||
print("alias s0={} s2={}\n", sa[0], sa[2]);
|
||||
|
||||
// Nested fixed array `[N][M]s64`: both dimensions are named consts.
|
||||
grid : [N][M]s64 = ---;
|
||||
grid[0][0] = 1;
|
||||
grid[3][2] = 8;
|
||||
print("nested g00={} g32={}\n", grid[0][0], grid[3][2]);
|
||||
|
||||
// Inline union field with a named-const dimension.
|
||||
u : U = ---;
|
||||
u.a[0] = 70;
|
||||
u.a[3] = 7;
|
||||
print("union u0={} u3={}\n", u.a[0], u.a[3]);
|
||||
}
|
||||
34
examples/0141-types-slice-literal-direct-call-arg.sx
Normal file
34
examples/0141-types-slice-literal-direct-call-arg.sx
Normal file
@@ -0,0 +1,34 @@
|
||||
// A `.[...]` array/slice literal passed DIRECTLY as a call argument behaves
|
||||
// identically to binding it to a typed local first: the literal is
|
||||
// materialized into addressable storage and a {ptr,len} slice header is built
|
||||
// over it, so the callee reads the element CONTENTS correctly.
|
||||
// Regression (issue 0084): a direct literal arg passed the raw array value
|
||||
// where a slice was expected, so the callee read its header off the wrong
|
||||
// bytes and returned garbage (0).
|
||||
#import "modules/std.sx";
|
||||
|
||||
count_nope :: (xs: []string) -> s64 {
|
||||
n := 0;
|
||||
i := 0;
|
||||
while i < xs.len { if xs[i] == "nope" { n += 1; } i += 1; }
|
||||
return n;
|
||||
}
|
||||
|
||||
sum :: (xs: []s64) -> s64 {
|
||||
s := 0;
|
||||
i := 0;
|
||||
while i < xs.len { s += xs[i]; i += 1; }
|
||||
return s;
|
||||
}
|
||||
|
||||
main :: () {
|
||||
// string slice: direct literal vs local-bound — both see 2 "nope"s.
|
||||
print("str direct={}\n", count_nope(.["a", "nope", "b", "nope"]));
|
||||
local : []string = .["a", "nope", "b", "nope"];
|
||||
print("str local={}\n", count_nope(local));
|
||||
|
||||
// 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];
|
||||
print("num local={}\n", sum(nums));
|
||||
}
|
||||
44
examples/0142-types-nested-slice-literal-elements.sx
Normal file
44
examples/0142-types-nested-slice-literal-elements.sx
Normal file
@@ -0,0 +1,44 @@
|
||||
// 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`
|
||||
// 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
|
||||
// under an element type of `[]T`, so the outer aggregate's elements were arrays
|
||||
// where slice {ptr,len} headers were expected; indexing the inner slice read a
|
||||
// garbage pointer and segfaulted. The per-element array->slice materialization
|
||||
// recurses with the nesting, so every level coerces.
|
||||
#import "modules/std.sx";
|
||||
|
||||
sum_nested :: (xss: [][]s64) -> s64 {
|
||||
total := 0;
|
||||
i := 0;
|
||||
while i < xss.len {
|
||||
j := 0;
|
||||
while j < xss[i].len { total += xss[i][j]; j += 1; }
|
||||
i += 1;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
count_x :: (xss: [][]string) -> s64 {
|
||||
n := 0;
|
||||
i := 0;
|
||||
while i < xss.len {
|
||||
j := 0;
|
||||
while j < xss[i].len { if xss[i][j] == "x" { n += 1; } j += 1; }
|
||||
i += 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
main :: () {
|
||||
// numeric [][]s64 — local-bound vs direct-arg both sum to 10.
|
||||
local : [][]s64 = .[.[1, 2], .[3, 4]];
|
||||
print("num local={}\n", sum_nested(local));
|
||||
print("num direct={}\n", sum_nested(.[.[1, 2], .[3, 4]]));
|
||||
|
||||
// string [][]string — local-bound vs direct-arg both count 4 "x"s.
|
||||
slocal : [][]string = .[.["x", "a"], .["b", "x"], .["x", "x"]];
|
||||
print("str local={}\n", count_x(slocal));
|
||||
print("str direct={}\n", count_x(.[.["x", "a"], .["b", "x"], .["x", "x"]]));
|
||||
}
|
||||
65
examples/0143-types-typed-const-array-dim.sx
Normal file
65
examples/0143-types-typed-const-array-dim.sx
Normal file
@@ -0,0 +1,65 @@
|
||||
// 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
|
||||
// through a type alias (`Arr :: [N]T`), and regardless of whether the const is
|
||||
// declared before or after the alias that consumes it.
|
||||
//
|
||||
// Regression (issue 0083): the stateless registration-time resolver
|
||||
// (type_bridge) only saw module consts that were already in `module_const_map`
|
||||
// when a type alias resolved its dimension. Typed consts register in a later
|
||||
// pass, and a forward-declared untyped const had not registered yet — so the
|
||||
// alias dimension fabricated length 0 (a 0-byte alloca), and element access
|
||||
// returned garbage (scalars) or bus-errored (slice/struct elements). Module
|
||||
// consts are now pre-registered before any alias resolves, and both the
|
||||
// stateful and stateless paths share one dimension resolver.
|
||||
#import "modules/std.sx";
|
||||
|
||||
NT : s64 : 8; // typed const used as a dimension
|
||||
|
||||
P :: struct { x: s64; y: s64; }
|
||||
|
||||
// Type aliases whose dimension is the TYPED const NT (stateless registration).
|
||||
TArr :: [NT]s64;
|
||||
TSArr :: [NT]string;
|
||||
TPArr :: [NT]P;
|
||||
|
||||
// Forward reference: this alias is declared BEFORE its dimension const NF.
|
||||
FArr :: [NF]s64;
|
||||
NF :: 5;
|
||||
|
||||
main :: () {
|
||||
// Typed-const dimension, DIRECT local decl.
|
||||
d : [NT]s64 = ---;
|
||||
d[0] = 3;
|
||||
d[7] = 21;
|
||||
print("direct d0={} d7={} len={}\n", d[0], d[7], d.len);
|
||||
|
||||
// Typed-const dimension via ALIAS (scalar): same layout as the direct form.
|
||||
a : TArr = ---;
|
||||
a[0] = 7;
|
||||
a[7] = 99;
|
||||
print("alias a0={} a7={} len={}\n", a[0], a[7], a.len);
|
||||
|
||||
// Typed-const dimension via ALIAS (string elements): no bus error.
|
||||
s : TSArr = ---;
|
||||
s[0] = "hi";
|
||||
s[7] = "yo";
|
||||
print("alias s0={} s7={}\n", s[0], s[7]);
|
||||
|
||||
// Typed-const dimension via ALIAS (struct elements).
|
||||
ps : TPArr = ---;
|
||||
ps[0] = P.{ x = 1, y = 2 };
|
||||
ps[7] = P.{ x = 5, y = 6 };
|
||||
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[0][0] = 1;
|
||||
grid[7][7] = 10;
|
||||
print("nested g00={} g77={}\n", grid[0][0], grid[7][7]);
|
||||
|
||||
// Forward-referenced alias dimension (untyped const declared after it).
|
||||
f : FArr = ---;
|
||||
f[0] = 4;
|
||||
f[4] = 40;
|
||||
print("fwd f0={} f4={} len={}\n", f[0], f[4], f.len);
|
||||
}
|
||||
77
examples/0144-types-const-expr-array-dim.sx
Normal file
77
examples/0144-types-const-expr-array-dim.sx
Normal file
@@ -0,0 +1,77 @@
|
||||
// A constant-FOLDABLE expression array dimension (`[M + 1]`, `[M * N]`,
|
||||
// `[N - M]`, nested `[M + N - 1]`, parenthesised `[(M + 1) * 2]`, and an
|
||||
// expression mixing an untyped and a typed module const) resolves to its
|
||||
// evaluated length — IDENTICALLY whether used DIRECTLY (`a : [M + 1]T`) or
|
||||
// through a type alias (`A :: [M + 1]T`), and for scalar, string (slice/pointer
|
||||
// class), and struct element types.
|
||||
//
|
||||
// Regression (issue 0083): the shared array-dimension resolver only looked up a
|
||||
// bare named const or a literal; any const-foldable EXPRESSION dimension was
|
||||
// rejected as "not a compile-time integer constant". It now routes the
|
||||
// dimension through the shared comptime integer-expression evaluator
|
||||
// (`program_index.evalConstIntExpr`), so integer `+ - * /` and parenthesisation
|
||||
// over literals and module consts fold on BOTH the stateful (direct) and
|
||||
// stateless (alias) paths — they share the one evaluator and cannot diverge.
|
||||
#import "modules/std.sx";
|
||||
|
||||
M :: 4;
|
||||
N :: 6;
|
||||
TK : s64 : 2; // typed const, used inside an expression dimension
|
||||
|
||||
P :: struct { x: s64; y: s64; }
|
||||
|
||||
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
|
||||
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_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_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_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_a : NestAlias = ---;
|
||||
paren_d : [(M + 1) * 2]s64 = ---;
|
||||
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_a : TypedAlias = ---;
|
||||
print("typed direct.len={} alias.len={}\n", typ_d.len, typ_a.len);
|
||||
|
||||
// string elements (slice/pointer class) — no bus error, correct reads.
|
||||
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]);
|
||||
|
||||
// struct elements.
|
||||
ps : StructAlias = ---;
|
||||
ps[0] = P.{ x = 1, y = 2 };
|
||||
ps[4] = P.{ x = 5, y = 6 };
|
||||
print("struct alias.len={} p0x={} p4y={}\n", ps.len, ps[0].x, ps[4].y);
|
||||
}
|
||||
29
examples/0145-types-integral-float-array-dim.sx
Normal file
29
examples/0145-types-integral-float-array-dim.sx
Normal file
@@ -0,0 +1,29 @@
|
||||
// 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.
|
||||
//
|
||||
// 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".
|
||||
// The shared const-int evaluator now folds an integral float literal (and a
|
||||
// float-typed module const) via `program_index.floatToIntExact`; a non-integral
|
||||
// float (`4.5`) is still rejected (see 1132).
|
||||
#import "modules/std.sx";
|
||||
|
||||
N : f64 : 4.0; // float-typed const
|
||||
M :: 4.0; // untyped float const
|
||||
|
||||
main :: () {
|
||||
a : [N]s64 = ---; // 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[1] = 21;
|
||||
print("b len={} b1={}\n", b.len, b[1]);
|
||||
|
||||
c : [4.0]s64 = ---; // direct integral-float-literal dim
|
||||
c[2] = 32;
|
||||
print("c len={} c2={}\n", c.len, c[2]);
|
||||
}
|
||||
68
examples/0146-types-comptime-count-matrix.sx
Normal file
68
examples/0146-types-comptime-count-matrix.sx
Normal file
@@ -0,0 +1,68 @@
|
||||
// The comptime-int COUNT surface is uniform: every count consumer — array
|
||||
// dimension (direct `[N]T` and via type alias), `Vector` lane, generic
|
||||
// value-param (struct AND type-fn binder), and `inline for 0..N` — folds the
|
||||
// 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
|
||||
// (`F :: 4.0` ≡ 4), and an ALIASED integer constraint (`Count :: u32`,
|
||||
// `Small :: s8`) 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
|
||||
// count ("not a compile-time integer constant") — `moduleConstInt` read only a
|
||||
// literal RHS; it now folds the RHS through the shared `evalConstIntExpr`. (2) An
|
||||
// aliased integer constraint (`$K: Count`) bypassed the value-param range gate,
|
||||
// which only matched builtin constraint names; the constraint now resolves to
|
||||
// its underlying builtin before range-checking, so `$K: Count` behaves exactly
|
||||
// like `$K: u32`.
|
||||
#import "modules/std.sx";
|
||||
|
||||
M :: 2; // untyped int const
|
||||
N :: M + 1; // named const, EXPRESSION RHS (== 3)
|
||||
S : s64 : 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
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
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;
|
||||
print("dim.direct.expr: len={} a0={} a2={}\n", a.len, a[0], a[2]);
|
||||
f : [F]s64 = ---; f[3] = 40;
|
||||
print("dim.direct.float: len={} f3={}\n", f.len, f[3]);
|
||||
|
||||
// array dimension — via type ALIAS
|
||||
aa : ArrN = ---; aa[2] = 99; print("dim.alias.expr: len={} aa2={}\n", aa.len, aa[2]);
|
||||
af : ArrF = ---; print("dim.alias.float: len={}\n", af.len);
|
||||
az : ArrS = ---; print("dim.alias.typed: len={}\n", az.len);
|
||||
|
||||
// Vector lane — expression const (3) and integral float (4)
|
||||
v3 : Vector(N, f32) = .[1.0, 2.0, 3.0];
|
||||
print("lane.expr3: {} {} {}\n", v3.x, v3.y, v3.z);
|
||||
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 — type-fn binder: expr const
|
||||
mk : Make(N, s64) = ---; 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
|
||||
t := 0; inline for 0..F: (i) { t += i; } print("for.float: {}\n", t); // 0+1+2+3 = 6
|
||||
}
|
||||
19
examples/0147-types-zero-count-context.sx
Normal file
19
examples/0147-types-zero-count-context.sx
Normal file
@@ -0,0 +1,19 @@
|
||||
// Zero is a context-dependent count. An array dimension and a generic
|
||||
// value-param count both ACCEPT zero — `[0]T` is a valid empty (zero-length)
|
||||
// array, and `Box(0)` is a length-0 instantiation. (A `Vector` lane count
|
||||
// rejects zero — see 1505.) This pins the zero-accepting half of the
|
||||
// context-dependent count rule documented in specs.md (Array Types).
|
||||
//
|
||||
// Regression (F0.4 attempt 12): the spec previously claimed every count must be
|
||||
// "positive integral", which wrongly implied `[0]T` / `Box(0)` are illegal.
|
||||
#import "modules/std.sx";
|
||||
|
||||
Box :: struct($N: u32) { items: [N]s64; }
|
||||
|
||||
main :: () {
|
||||
a : [0]s64 = ---;
|
||||
print("array_dim={}\n", a.len);
|
||||
|
||||
b : Box(0) = ---;
|
||||
print("value_param={}\n", b.items.len);
|
||||
}
|
||||
29
examples/0207-generics-value-param-const.sx
Normal file
29
examples/0207-generics-value-param-const.sx
Normal file
@@ -0,0 +1,29 @@
|
||||
// A generic value parameter (`$K: u32`) bound from a named const or a
|
||||
// constant-foldable expression resolves to the SAME monomorphised instantiation
|
||||
// as the literal form: `Vec(N, f32)` (N a module const) and `Vec(M + 1, f32)`
|
||||
// (a const expression) are both `Vec(3, f32)`. The struct-copy assignment is the
|
||||
// proof — it type-checks only because the two spellings name one instantiation.
|
||||
//
|
||||
// Regression (issue 0083): the value-param binder hand-rolled an `else => 0`
|
||||
// switch, so a named-const value arg either fabricated a 0 binding under a wrong
|
||||
// mangled name or was rejected outright as "unknown type 'N'". It now folds
|
||||
// through the shared const-int evaluator (`program_index.evalConstIntExpr`).
|
||||
#import "modules/std.sx";
|
||||
|
||||
N :: 3;
|
||||
M :: 2;
|
||||
|
||||
Vec :: struct ($K: u32, $T: Type) { data: [K]T; }
|
||||
|
||||
main :: () {
|
||||
a : Vec(N, f32) = ---; // named-const value param
|
||||
a.data[0] = 10.0; a.data[1] = 20.0; a.data[2] = 30.0;
|
||||
print("named: len={} a0={} a2={}\n", a.data.len, a.data[0], a.data[2]);
|
||||
|
||||
e : Vec(M + 1, f32) = ---; // const-expr value param (M + 1 == 3)
|
||||
e.data[0] = 1.0; e.data[2] = 9.0;
|
||||
print("expr: len={} e2={}\n", e.data.len, e.data[2]);
|
||||
|
||||
b : Vec(3, f32) = a; // same instantiation → struct copy type-checks
|
||||
print("copy: len={} b2={}\n", b.data.len, b.data[2]);
|
||||
}
|
||||
32
examples/0208-generics-value-param-type-function.sx
Normal file
32
examples/0208-generics-value-param-type-function.sx
Normal file
@@ -0,0 +1,32 @@
|
||||
// A type-RETURNING function with a value parameter (`$K: u32`) used as a TYPE
|
||||
// annotation: `b : Make(N, s64)` where `Make :: ($K, $T) -> Type { return [K]T; }`.
|
||||
// A named-const value arg (`Make(N, s64)`), a const-expression value arg
|
||||
// (`Make(M + 1, s64)`), and the literal form (`Make(3, s64)`) all instantiate to
|
||||
// the SAME type — the array copy `b : Make(3, s64) = a` type-checks only because
|
||||
// the three spellings name one `[3]s64`.
|
||||
//
|
||||
// Regression (issue 0083 / F0.4 attempt 6): the unknown-type checker walked the
|
||||
// value-param position as a type name ("unknown type 'N'"), and the
|
||||
// parameterized-type-annotation path never routed to `instantiateTypeFunction`,
|
||||
// nor did that binder resolve a non-struct/union return shape (`return [K]T`).
|
||||
// The value arg now folds through the shared const-int evaluator and the type
|
||||
// function resolves its general return-type expression with bindings active.
|
||||
#import "modules/std.sx";
|
||||
|
||||
N :: 3;
|
||||
M :: 2;
|
||||
|
||||
Make :: ($K: u32, $T: Type) -> Type { return [K]T; }
|
||||
|
||||
main :: () {
|
||||
a : Make(N, s64) = ---; // named-const value param
|
||||
a[0] = 10; a[1] = 20; a[2] = 30;
|
||||
print("named: len={} a0={} a2={}\n", a.len, a[0], a[2]);
|
||||
|
||||
e : Make(M + 1, s64) = ---; // const-expr value param (M + 1 == 3)
|
||||
e[0] = 1; e[2] = 9;
|
||||
print("expr: len={} e2={}\n", e.len, e[2]);
|
||||
|
||||
b : Make(3, s64) = a; // same instantiation → array copy type-checks
|
||||
print("copy: len={} b2={}\n", b.len, b[2]);
|
||||
}
|
||||
19
examples/0209-generics-value-param-integral-float.sx
Normal file
19
examples/0209-generics-value-param-integral-float.sx
Normal file
@@ -0,0 +1,19 @@
|
||||
// A generic value parameter (`$K: u32`) binds a literal (`Vec(3, s64)`) and an
|
||||
// integral-float named const (`Vec(L, s64)` with `L : f64 : 4.0`) to the same
|
||||
// integer a plain `4` would — the value-param arg folds through the shared
|
||||
// const-int evaluator, so the integral-float rule (F0.4 attempt 8, Agra ruling)
|
||||
// reaches value params too. The folded value is the array length `[K]s64`.
|
||||
//
|
||||
// The bind is range-checked against the declared `u32` (an out-of-range arg is a
|
||||
// clean compile error — see 1134); a valid in-range value binds normally.
|
||||
#import "modules/std.sx";
|
||||
|
||||
Vec :: struct ($K: u32, $T: Type) { data: [K]T; }
|
||||
|
||||
L : f64 : 4.0;
|
||||
|
||||
main :: () {
|
||||
a : Vec(3, s64) = ---; // literal value param
|
||||
b : Vec(L, s64) = ---; // integral-float named-const value param → 4
|
||||
print("a.len={} b.len={}\n", a.data.len, b.data.len); // 3 and 4
|
||||
}
|
||||
23
examples/0610-comptime-inline-for-const-bound.sx
Normal file
23
examples/0610-comptime-inline-for-const-bound.sx
Normal file
@@ -0,0 +1,23 @@
|
||||
// `inline for 0..K` with a named-const or constant-foldable bound unrolls at
|
||||
// compile time, just like a literal bound.
|
||||
//
|
||||
// Regression (issue 0083): the inline-for bound folder (`evalComptimeInt`) only
|
||||
// handled literals, comptime cursors, and `<pack>.len`, so `inline for 0..M`
|
||||
// (M a module const) and `inline for 0..(M + 1)` (a const expression) both
|
||||
// failed with "range end is not a compile-time integer". `evalComptimeInt` now
|
||||
// delegates to the single shared const-int evaluator
|
||||
// (`program_index.evalConstIntExpr`), so the inline-for bound and an array
|
||||
// dimension fold the same shapes to the same value.
|
||||
#import "modules/std.sx";
|
||||
|
||||
M :: 3;
|
||||
|
||||
main :: () {
|
||||
s := 0;
|
||||
inline for 0..M: (i) { s += i; }
|
||||
print("sum 0..M = {}\n", s); // 0 + 1 + 2 = 3
|
||||
|
||||
t := 0;
|
||||
inline for 0..(M + 1): (i) { t += i; }
|
||||
print("sum 0..(M+1) = {}\n", t); // 0 + 1 + 2 + 3 = 6
|
||||
}
|
||||
14
examples/0611-comptime-integral-float-inline-for.sx
Normal file
14
examples/0611-comptime-integral-float-inline-for.sx
Normal file
@@ -0,0 +1,14 @@
|
||||
// An `inline for 0..M` bound accepts an integral float constant — `M :: 3.0`
|
||||
// unrolls the same three iterations as `M :: 3`. The inline-for bound folder
|
||||
// (`evalComptimeInt`) delegates to the shared const-int evaluator, so the
|
||||
// integral-float rule (issue 0083 / F0.4 attempt 8, Agra ruling) applies here
|
||||
// too.
|
||||
#import "modules/std.sx";
|
||||
|
||||
M :: 3.0;
|
||||
|
||||
main :: () {
|
||||
s := 0;
|
||||
inline for 0..M: (i) { s += i; }
|
||||
print("sum 0..M = {}\n", s); // 0 + 1 + 2 = 3
|
||||
}
|
||||
24
examples/0612-comptime-inline-for-range-bounds.sx
Normal file
24
examples/0612-comptime-inline-for-range-bounds.sx
Normal file
@@ -0,0 +1,24 @@
|
||||
// An `inline for` / `for` range bound is a range ENDPOINT, not a count, so the
|
||||
// count negative-rejection rule does NOT apply to it: negative endpoints are
|
||||
// valid and an empty/inverted range simply runs zero iterations.
|
||||
//
|
||||
// Regression (F0.4 attempt 11, Agra ruling): the spec wrongly lumped inline-for
|
||||
// bounds with counts (array dim / Vector lane / value-param), which reject
|
||||
// negatives. Bounds are exempt — `inline for -2..1` iterates -2,-1,0 and an
|
||||
// integral-float empty range `0..(-2.0)` runs zero iterations. Comptime and
|
||||
// runtime loops must agree.
|
||||
#import "modules/std.sx";
|
||||
|
||||
main :: () {
|
||||
s := 0;
|
||||
inline for -2..1: (i) { s += i; }
|
||||
print("inline for -2..1 sum = {}\n", s); // -2 + -1 + 0 = -3
|
||||
|
||||
r := 0;
|
||||
for -2..1: (i) { r += i; }
|
||||
print("for -2..1 sum = {}\n", r); // -2 + -1 + 0 = -3 (runtime parity)
|
||||
|
||||
e := 0;
|
||||
inline for 0..(-2.0): (i) { e += i; }
|
||||
print("inline for 0..(-2.0) sum = {}\n", e); // empty range -> 0 iterations
|
||||
}
|
||||
24
examples/1129-diagnostics-array-dim-not-const.sx
Normal file
24
examples/1129-diagnostics-array-dim-not-const.sx
Normal file
@@ -0,0 +1,24 @@
|
||||
// An array dimension that is not a compile-time integer constant is a hard
|
||||
// error, not a silently-fabricated 0-length array. Here a type alias's
|
||||
// dimension is a runtime function call (`get()`), which is genuinely not
|
||||
// compile-time-known — the registration-time resolver cannot evaluate it.
|
||||
//
|
||||
// (A const-FOLDABLE expression dimension such as `[M + 1]` is NOT an error — it
|
||||
// folds; see examples/0144-types-const-expr-array-dim.sx. Only a dimension with
|
||||
// a genuinely runtime operand halts here.)
|
||||
//
|
||||
// Regression (issue 0083): the stateless resolver printed a non-fatal warning
|
||||
// and fabricated length 0, then let compilation continue — producing a 0-byte
|
||||
// alloca and corrupt element access. It now yields the `.unresolved` sentinel,
|
||||
// which the alias registration surfaces as this diagnostic, aborting the build
|
||||
// with a non-zero exit.
|
||||
#import "modules/std.sx";
|
||||
|
||||
get :: () -> s64 { return 5; }
|
||||
BadArr :: [get()]s64;
|
||||
|
||||
main :: () {
|
||||
a : BadArr = ---;
|
||||
a[0] = 7;
|
||||
print("a0={}\n", a[0]);
|
||||
}
|
||||
15
examples/1130-diagnostics-array-dim-oversized-u32.sx
Normal file
15
examples/1130-diagnostics-array-dim-oversized-u32.sx
Normal file
@@ -0,0 +1,15 @@
|
||||
// An array dimension that folds to a valid compile-time integer but exceeds a
|
||||
// `u32` (`[5_000_000_000]s64`) is a hard error — a clean sx diagnostic with a
|
||||
// non-zero exit, NOT a compiler panic.
|
||||
//
|
||||
// Regression (issue 0087 / F0.4 attempt 6): the dimension folded to a valid i64
|
||||
// (5e9) and was then narrowed with an unchecked `@intCast` to u32, aborting the
|
||||
// COMPILER with "integer does not fit in destination type". Every dim/lane fold
|
||||
// now narrows through the single range-checked `program_index.foldDimU32`, which
|
||||
// reports an out-of-u32-range dimension as this diagnostic and halts the build.
|
||||
#import "modules/std.sx";
|
||||
|
||||
main :: () {
|
||||
a : [5000000000]s64 = ---;
|
||||
print("unreachable: {}\n", a.len);
|
||||
}
|
||||
24
examples/1131-diagnostics-array-dim-oversized-u32-alias.sx
Normal file
24
examples/1131-diagnostics-array-dim-oversized-u32-alias.sx
Normal file
@@ -0,0 +1,24 @@
|
||||
// An array dimension that folds to a valid compile-time integer but exceeds a
|
||||
// `u32` is a hard error — and it must report the SAME precise diagnostic whether
|
||||
// the array is written directly (`a : [5_000_000_000]s64`, see example 1130) or
|
||||
// behind a type ALIAS (`Big :: [5_000_000_000]s64`, here). Both forms now route
|
||||
// the dimension through one shared folder + one shared message map, so they
|
||||
// cannot diverge.
|
||||
//
|
||||
// Regression (issue 0083 / F0.4 attempt 7): the stateless alias-registration
|
||||
// path collapsed `foldDimU32`'s distinct `.too_large` outcome into `null` and
|
||||
// emitted ONE generic "an array dimension is not a compile-time integer
|
||||
// constant" message — FALSE, since 5_000_000_000 IS a compile-time integer
|
||||
// constant; it merely doesn't fit a `u32`. The alias path now consults the
|
||||
// shared fold and emits the precise "does not fit in u32" message, matching the
|
||||
// direct form. (A genuinely non-const alias dim still gets the generic message —
|
||||
// see example 1129.)
|
||||
#import "modules/std.sx";
|
||||
|
||||
Big :: [5000000000]s64;
|
||||
|
||||
main :: () {
|
||||
a : Big = ---;
|
||||
a[0] = 7;
|
||||
print("unreachable: {}\n", a[0]);
|
||||
}
|
||||
14
examples/1132-diagnostics-array-dim-non-integral-float.sx
Normal file
14
examples/1132-diagnostics-array-dim-non-integral-float.sx
Normal file
@@ -0,0 +1,14 @@
|
||||
// A NON-integral float constant (`4.5`) used as an array dimension is a hard
|
||||
// error — only an integral float (`4.0`) folds to a count. Clean diagnostic +
|
||||
// non-zero exit, NOT a fabricated length.
|
||||
//
|
||||
// Regression (F0.4 attempt 8, Agra ruling): the integral-float rule accepts
|
||||
// `4.0` as a dimension but must keep rejecting `4.5` (it is not an integer).
|
||||
#import "modules/std.sx";
|
||||
|
||||
N : f64 : 4.5;
|
||||
|
||||
main :: () {
|
||||
a : [N]s64 = ---;
|
||||
print("unreachable: {}\n", a.len);
|
||||
}
|
||||
12
examples/1133-diagnostics-array-dim-negative-float.sx
Normal file
12
examples/1133-diagnostics-array-dim-negative-float.sx
Normal file
@@ -0,0 +1,12 @@
|
||||
// A NEGATIVE integral float (`-2.0`) used as an array dimension is a hard error.
|
||||
// The integral-float rule folds and negates it to `-2`, then the shared u32 dim
|
||||
// gate rejects a below-minimum dimension — a clean diagnostic + non-zero exit.
|
||||
//
|
||||
// Regression (F0.4 attempt 8, Agra ruling): integral floats fold, but a negative
|
||||
// result is still rejected (a dimension must be non-negative).
|
||||
#import "modules/std.sx";
|
||||
|
||||
main :: () {
|
||||
a : [-2.0]s64 = ---;
|
||||
print("unreachable: {}\n", a.len);
|
||||
}
|
||||
17
examples/1134-diagnostics-value-param-u32-overflow.sx
Normal file
17
examples/1134-diagnostics-value-param-u32-overflow.sx
Normal file
@@ -0,0 +1,17 @@
|
||||
// A generic value-param arg that does not fit the param's declared integer type
|
||||
// (`Box(5_000_000_000)` for `$K: u32`) is a hard error — a clean diagnostic +
|
||||
// non-zero exit, NOT a silent truncating bind.
|
||||
//
|
||||
// Regression (F0.4 attempt 8, item 1): `resolveValueParamArg` bound the folded
|
||||
// i64 without range-checking the declared type, so an out-of-u32 arg compiled
|
||||
// and ran. The bind now routes a `u32` count through the shared
|
||||
// `program_index.foldDimU32` gate (the same one array dims / Vector lanes use),
|
||||
// so an oversized value is rejected before instantiation.
|
||||
#import "modules/std.sx";
|
||||
|
||||
Box :: struct ($K: u32) { value: s64; }
|
||||
|
||||
main :: () {
|
||||
b : Box(5000000000) = ---;
|
||||
print("unreachable\n");
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// A generic value-param arg that does not fit the param's declared integer type
|
||||
// is a hard error even when that type is reached through a type ALIAS
|
||||
// (`$K: Count` where `Count :: u32`, `$K: Small` where `Small :: s8`) — a clean
|
||||
// diagnostic + non-zero exit, NOT a silent truncating bind.
|
||||
//
|
||||
// Regression (issue 0083): the value-param range gate matched only BUILTIN
|
||||
// constraint names, so an aliased constraint slipped past `intTypeRange` and
|
||||
// `Box(5_000_000_000)` with `$K: Count` compiled and bound a truncated value.
|
||||
// The constraint now resolves to its underlying builtin (`Count` → u32,
|
||||
// `Small` → s8) before range-checking, so an aliased integer constraint behaves
|
||||
// exactly like the builtin it names — at both the struct and type-fn binders.
|
||||
#import "modules/std.sx";
|
||||
|
||||
Count :: u32;
|
||||
Small :: s8;
|
||||
Box :: struct ($K: Count) { value: s64; }
|
||||
Tiny :: struct ($K: Small) { value: s64; }
|
||||
|
||||
main :: () {
|
||||
b : Box(5000000000) = ---;
|
||||
t : Tiny(300) = ---;
|
||||
print("unreachable {} {}\n", b.value, t.value);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// A DIRECT array dimension that is genuinely not a compile-time integer (a
|
||||
// runtime call) is a hard error — ONE clean diagnostic + non-zero exit. Crucially
|
||||
// it must NOT fabricate a length and must NOT crash later in lowering: the bad
|
||||
// var is used downstream (element store + read, `.len`), and lowering has to bail
|
||||
// gracefully on the `.unresolved` type rather than `@panic` in `sizeOf` or pile
|
||||
// on cascade errors.
|
||||
//
|
||||
// Regression (issue 0083): the stateful `resolveArrayLen` emitted the diagnostic
|
||||
// then `return 0` — fabricating a 0-length array (0-byte alloca, OOB access) to
|
||||
// dodge the `sizeOf` panic. It now returns null → the `.unresolved` sentinel; the
|
||||
// binding's lowering bails on it (a field access on an already-diagnosed
|
||||
// `.unresolved` value stays silent), so the single real diagnostic aborts the
|
||||
// build with no fabrication and no panic.
|
||||
#import "modules/std.sx";
|
||||
|
||||
get :: () -> s64 { return 5; }
|
||||
|
||||
main :: () {
|
||||
a : [get()]s64 = ---;
|
||||
a[0] = 7;
|
||||
print("unreachable: {} {}\n", a.len, a[0]);
|
||||
}
|
||||
27
examples/1137-diagnostics-value-param-type-fn-no-cascade.sx
Normal file
27
examples/1137-diagnostics-value-param-type-fn-no-cascade.sx
Normal file
@@ -0,0 +1,27 @@
|
||||
// A FAILED value-param bind on a type-RETURNING FUNCTION must emit exactly its
|
||||
// own diagnostic and NOT cascade a bogus `field '…' not found on '<fn>'` when the
|
||||
// binding is later field-accessed. The type-fn binder must poison the binding to
|
||||
// `.unresolved` (the diagnosed-poison sentinel) — exactly like the struct binder —
|
||||
// so the downstream `.len` is suppressed, not reported as a second error.
|
||||
//
|
||||
// Regression (issue 0083): the type-fn path (`instantiateTypeFunction`) fell
|
||||
// through to an empty-struct placeholder named after the function on a failed
|
||||
// value-param bind, so `a.len` produced a second `field 'len' not found on
|
||||
// 'MakeC'` error. The struct binder already returned `.unresolved` here; the
|
||||
// type-fn binder now matches it. Three failure modes, three clean diagnostics,
|
||||
// zero field cascades:
|
||||
// - value-param overflow via an aliased integer constraint (`$K: Count`),
|
||||
// - a non-const value-param arg (`get()`),
|
||||
// - an unknown TYPE arg (`NoSuchType`) — must still report the unknown type.
|
||||
#import "modules/std.sx";
|
||||
|
||||
Count :: u32;
|
||||
MakeC :: ($K: Count, $T: Type) -> Type { return [K]T; }
|
||||
get :: () -> u32 { return 4; }
|
||||
|
||||
main :: () {
|
||||
a : MakeC(5000000000, s64) = ---;
|
||||
b : MakeC(get(), s64) = ---;
|
||||
c : MakeC(3, NoSuchType) = ---;
|
||||
print("unreachable {} {} {}\n", a.len, b.len, c.len);
|
||||
}
|
||||
14
examples/1138-diagnostics-inline-for-non-integral-bound.sx
Normal file
14
examples/1138-diagnostics-inline-for-non-integral-bound.sx
Normal file
@@ -0,0 +1,14 @@
|
||||
// A NON-integral float (`4.5`) as an `inline for` range bound is a hard error:
|
||||
// the loop cursor must be a compile-time integer, so only an integral float
|
||||
// (`4.0`, `-2.0`) folds. Clean diagnostic + non-zero exit.
|
||||
//
|
||||
// Regression (F0.4 attempt 11, Agra ruling): range bounds are exempt from the
|
||||
// count negative-rejection (negatives are valid endpoints), but the
|
||||
// must-be-integer requirement still applies — `4.5` has no integer value.
|
||||
#import "modules/std.sx";
|
||||
|
||||
main :: () {
|
||||
s := 0;
|
||||
inline for 0..4.5: (i) { s += i; }
|
||||
print("unreachable: {}\n", s);
|
||||
}
|
||||
35
examples/1501-vectors-const-lane.sx
Normal file
35
examples/1501-vectors-const-lane.sx
Normal file
@@ -0,0 +1,35 @@
|
||||
// A `Vector` lane count from a named const or a constant-foldable expression
|
||||
// resolves to the SAME layout as a literal lane — DIRECT (param / return type)
|
||||
// and via a type ALIAS. A 3-lane (named const `N`) and a 4-lane (const expr
|
||||
// `M + 1`) prove the lane VALUE is folded, not fabricated: reading `.w` requires
|
||||
// the 4-lane vector to actually have four lanes.
|
||||
//
|
||||
// Regression (issue 0083): the stateful Vector lane resolvers hand-rolled an
|
||||
// `else => 0` switch, so a module-const lane (`Vector(N, f32)`) lowered a 0-lane
|
||||
// `<0 x float>` and died in LLVM verification ("huge alignment values are
|
||||
// unsupported"); a const-expr lane (`Vector(M + 1, f32)`) was rejected at parse.
|
||||
// Both now fold through the single shared const-int evaluator
|
||||
// (`program_index.evalConstIntExpr`) — the same one the array-dimension path
|
||||
// uses — so a named-const / const-expr lane is identical to a literal lane.
|
||||
#import "modules/std.sx";
|
||||
|
||||
N :: 3;
|
||||
M :: 3;
|
||||
|
||||
LaneAlias :: Vector(N, f32); // ALIAS: 3-lane via named const.
|
||||
ExprAlias :: Vector(M + 1, f32); // ALIAS: 4-lane via const expression.
|
||||
|
||||
mk3 :: () -> Vector(N, f32) { .[1.0, 2.0, 3.0] } // DIRECT named-const lane.
|
||||
mk4 :: () -> Vector(M + 1, f32) { .[1.0, 2.0, 3.0, 4.0] } // DIRECT const-expr lane.
|
||||
|
||||
main :: () {
|
||||
a := mk3();
|
||||
print("direct3: {} {} {}\n", a.x, a.y, a.z);
|
||||
b := mk4();
|
||||
print("direct4: {} {} {} {}\n", b.x, b.y, b.z, b.w);
|
||||
|
||||
c : LaneAlias = .[5.0, 6.0, 7.0];
|
||||
print("alias3: {}\n", c.z);
|
||||
d : ExprAlias = .[5.0, 6.0, 7.0, 8.0];
|
||||
print("alias4: {}\n", d.w);
|
||||
}
|
||||
16
examples/1502-vectors-runtime-lane-not-const.sx
Normal file
16
examples/1502-vectors-runtime-lane-not-const.sx
Normal file
@@ -0,0 +1,16 @@
|
||||
// A `Vector` lane count that is not a compile-time integer (here a runtime
|
||||
// function call) is a hard error — a clean sx diagnostic with a non-zero exit,
|
||||
// NOT a fabricated `<0 x float>` lane that crashes LLVM verification.
|
||||
//
|
||||
// Regression (issue 0083): the Vector lane resolver hand-rolled an `else => 0`
|
||||
// switch that silently fabricated a 0-lane vector for a non-const lane. It now
|
||||
// folds the lane through the shared const-int evaluator and, when that yields no
|
||||
// compile-time integer, emits this diagnostic and halts the build.
|
||||
#import "modules/std.sx";
|
||||
|
||||
lanes :: () -> u32 { return 3; }
|
||||
|
||||
main :: () {
|
||||
v : Vector(lanes(), f32) = ---;
|
||||
print("unreachable: {}\n", v.x);
|
||||
}
|
||||
15
examples/1503-vectors-oversized-lane-not-u32.sx
Normal file
15
examples/1503-vectors-oversized-lane-not-u32.sx
Normal file
@@ -0,0 +1,15 @@
|
||||
// A `Vector` lane count that folds to a valid compile-time integer but exceeds a
|
||||
// `u32` (`Vector(5_000_000_000, f32)`) is a hard error — a clean sx diagnostic
|
||||
// with a non-zero exit, NOT a compiler panic.
|
||||
//
|
||||
// Regression (issue 0087 / F0.4 attempt 6): the lane folded to a valid i64 (5e9)
|
||||
// and was then narrowed with an unchecked `@intCast` to u32, aborting the
|
||||
// COMPILER with "integer does not fit in destination type". The lane now narrows
|
||||
// through the single range-checked `program_index.foldDimU32`, which reports an
|
||||
// out-of-u32-range lane as this diagnostic and halts the build.
|
||||
#import "modules/std.sx";
|
||||
|
||||
main :: () {
|
||||
v : Vector(5000000000, f32) = ---;
|
||||
print("unreachable: {}\n", v.x);
|
||||
}
|
||||
12
examples/1504-vectors-integral-float-lane.sx
Normal file
12
examples/1504-vectors-integral-float-lane.sx
Normal file
@@ -0,0 +1,12 @@
|
||||
// A Vector lane count accepts an integral float constant — `L : f64 : 4.0` lays
|
||||
// out the same `Vector(4, f32)` as the literal `4`. The lane resolver shares the
|
||||
// const-int evaluator with the array-dim path, so the integral-float rule
|
||||
// (issue 0083 / F0.4 attempt 8, Agra ruling) applies uniformly.
|
||||
#import "modules/std.sx";
|
||||
|
||||
L : f64 : 4.0;
|
||||
|
||||
main :: () {
|
||||
v : Vector(L, f32) = .[1.0, 2.0, 3.0, 4.0];
|
||||
print("v0={} v2={} v3={}\n", v[0], v[2], v[3]);
|
||||
}
|
||||
15
examples/1505-vectors-zero-lane-rejected.sx
Normal file
15
examples/1505-vectors-zero-lane-rejected.sx
Normal file
@@ -0,0 +1,15 @@
|
||||
// A zero `Vector` lane count is rejected — a vector must have at least one lane
|
||||
// (strictly positive). Contrast with an array dimension / value-param count,
|
||||
// where zero is a valid length-0 instantiation (see 0147). This pins the
|
||||
// zero-rejecting half of the context-dependent count rule (specs.md, Array
|
||||
// Types).
|
||||
//
|
||||
// Regression (F0.4 attempt 12): the spec now states the zero rule per consumer;
|
||||
// the `Vector` lane count stays strictly positive while array dims / value-param
|
||||
// counts accept zero.
|
||||
#import "modules/std.sx";
|
||||
|
||||
main :: () {
|
||||
v : Vector(0, f32) = ---;
|
||||
print("unreachable: {}\n", v.x);
|
||||
}
|
||||
1
examples/expected/0140-types-named-const-array-dim.exit
Normal file
1
examples/expected/0140-types-named-const-array-dim.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
scalar a0=7 a3=42
|
||||
string s0=hi s1=yo
|
||||
struct p0x=1 p0y=2 p2x=5
|
||||
alias a0=11 a3=99
|
||||
alias s0=al s2=ok
|
||||
nested g00=1 g32=8
|
||||
union u0=70 u3=7
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
str direct=2
|
||||
str local=2
|
||||
num direct=100
|
||||
num local=100
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
num local=10
|
||||
num direct=10
|
||||
str local=4
|
||||
str direct=4
|
||||
1
examples/expected/0143-types-typed-const-array-dim.exit
Normal file
1
examples/expected/0143-types-typed-const-array-dim.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
direct d0=3 d7=21 len=8
|
||||
alias a0=7 a7=99 len=8
|
||||
alias s0=hi s7=yo
|
||||
alias p0x=1 p0y=2 p7x=5
|
||||
nested g00=1 g77=10
|
||||
fwd f0=4 f4=40 len=5
|
||||
1
examples/expected/0144-types-const-expr-array-dim.exit
Normal file
1
examples/expected/0144-types-const-expr-array-dim.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
1
examples/expected/0144-types-const-expr-array-dim.stderr
Normal file
1
examples/expected/0144-types-const-expr-array-dim.stderr
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
7
examples/expected/0144-types-const-expr-array-dim.stdout
Normal file
7
examples/expected/0144-types-const-expr-array-dim.stdout
Normal file
@@ -0,0 +1,7 @@
|
||||
add direct.len=5 alias.len=5 d4=7 a4=7
|
||||
mul direct.len=24 alias.len=24 d23=230 a23=230
|
||||
sub direct.len=2 alias.len=2 d1=9 a1=9
|
||||
nest direct.len=9 alias.len=9 paren direct.len=10 alias.len=10
|
||||
typed direct.len=6 alias.len=6
|
||||
str alias.len=5 s0=hi s4=yo
|
||||
struct alias.len=5 p0x=1 p4y=6
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
a len=4 a0=10 a3=40
|
||||
b len=4 b1=21
|
||||
c len=4 c2=32
|
||||
1
examples/expected/0146-types-comptime-count-matrix.exit
Normal file
1
examples/expected/0146-types-comptime-count-matrix.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
13
examples/expected/0146-types-comptime-count-matrix.stdout
Normal file
13
examples/expected/0146-types-comptime-count-matrix.stdout
Normal file
@@ -0,0 +1,13 @@
|
||||
dim.direct.expr: len=3 a0=7 a2=9
|
||||
dim.direct.float: len=4 f3=40
|
||||
dim.alias.expr: len=3 aa2=99
|
||||
dim.alias.float: len=4
|
||||
dim.alias.typed: len=5
|
||||
lane.expr3: 1.000000 2.000000 3.000000
|
||||
lane.float4: 4.000000
|
||||
vp.struct.expr: len=3 v=30
|
||||
vp.struct.alias.u32: len=3 v=31
|
||||
vp.struct.alias.s8: len=4 v=32
|
||||
vp.typefn.expr: len=3 v=33
|
||||
for.expr: 3
|
||||
for.float: 6
|
||||
1
examples/expected/0147-types-zero-count-context.exit
Normal file
1
examples/expected/0147-types-zero-count-context.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
2
examples/expected/0147-types-zero-count-context.stdout
Normal file
2
examples/expected/0147-types-zero-count-context.stdout
Normal file
@@ -0,0 +1,2 @@
|
||||
array_dim=0
|
||||
value_param=0
|
||||
1
examples/expected/0207-generics-value-param-const.exit
Normal file
1
examples/expected/0207-generics-value-param-const.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
1
examples/expected/0207-generics-value-param-const.stderr
Normal file
1
examples/expected/0207-generics-value-param-const.stderr
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
3
examples/expected/0207-generics-value-param-const.stdout
Normal file
3
examples/expected/0207-generics-value-param-const.stdout
Normal file
@@ -0,0 +1,3 @@
|
||||
named: len=3 a0=10.000000 a2=30.000000
|
||||
expr: len=3 e2=9.000000
|
||||
copy: len=3 b2=30.000000
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
named: len=3 a0=10 a2=30
|
||||
expr: len=3 e2=9
|
||||
copy: len=3 b2=30
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
a.len=3 b.len=4
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
sum 0..M = 3
|
||||
sum 0..(M+1) = 6
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
sum 0..M = 3
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
inline for -2..1 sum = -3
|
||||
for -2..1 sum = -3
|
||||
inline for 0..(-2.0) sum = 0
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: type alias 'BadArr' could not be resolved: an array dimension is not a compile-time integer constant
|
||||
--> examples/1129-diagnostics-array-dim-not-const.sx:18:11
|
||||
|
|
||||
18 | BadArr :: [get()]s64;
|
||||
| ^^^^^^^^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: array dimension 5000000000 does not fit in u32
|
||||
--> examples/1130-diagnostics-array-dim-oversized-u32.sx:13:10
|
||||
|
|
||||
13 | a : [5000000000]s64 = ---;
|
||||
| ^^^^^^^^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: array dimension 5000000000 does not fit in u32
|
||||
--> examples/1131-diagnostics-array-dim-oversized-u32-alias.sx:18:9
|
||||
|
|
||||
18 | Big :: [5000000000]s64;
|
||||
| ^^^^^^^^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: array dimension must be a compile-time integer constant
|
||||
--> examples/1132-diagnostics-array-dim-non-integral-float.sx:12:10
|
||||
|
|
||||
12 | a : [N]s64 = ---;
|
||||
| ^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: array dimension must be non-negative, got -2
|
||||
--> examples/1133-diagnostics-array-dim-negative-float.sx:10:10
|
||||
|
|
||||
10 | a : [-2.0]s64 = ---;
|
||||
| ^^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: value 5000000000 does not fit in u32 parameter K
|
||||
--> examples/1134-diagnostics-value-param-u32-overflow.sx:15:13
|
||||
|
|
||||
15 | b : Box(5000000000) = ---;
|
||||
| ^^^^^^^^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,11 @@
|
||||
error: value 5000000000 does not fit in u32 parameter K
|
||||
--> examples/1135-diagnostics-value-param-alias-constraint-overflow.sx:20:13
|
||||
|
|
||||
20 | b : Box(5000000000) = ---;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: value 300 does not fit in s8 parameter K
|
||||
--> examples/1135-diagnostics-value-param-alias-constraint-overflow.sx:21:14
|
||||
|
|
||||
21 | t : Tiny(300) = ---;
|
||||
| ^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: array dimension must be a compile-time integer constant
|
||||
--> examples/1136-diagnostics-array-dim-nonconst-direct-no-crash.sx:19:10
|
||||
|
|
||||
19 | a : [get()]s64 = ---;
|
||||
| ^^^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,17 @@
|
||||
error: unknown type 'NoSuchType'
|
||||
--> examples/1137-diagnostics-value-param-type-fn-no-cascade.sx:25:18
|
||||
|
|
||||
25 | c : MakeC(3, NoSuchType) = ---;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: value 5000000000 does not fit in u32 parameter K
|
||||
--> examples/1137-diagnostics-value-param-type-fn-no-cascade.sx:23:15
|
||||
|
|
||||
23 | a : MakeC(5000000000, s64) = ---;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: generic value parameter 'K' must be a compile-time integer constant
|
||||
--> examples/1137-diagnostics-value-param-type-fn-no-cascade.sx:24:15
|
||||
|
|
||||
24 | b : MakeC(get(), s64) = ---;
|
||||
| ^^^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: inline for: range end is not a compile-time integer
|
||||
--> examples/1138-diagnostics-inline-for-non-integral-bound.sx:12:19
|
||||
|
|
||||
12 | inline for 0..4.5: (i) { s += i; }
|
||||
| ^^^
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user