lang: multi-iterable for loops — drop ':', add '..=', open ranges, arrow bodies
The for header is now a comma-separated list of iterables with a
positional capture group and no ':' separator:
for xs (x) { } // collection
for 0..n (i) { } // range (end exclusive)
for 1..=5 (a) { } // ..= inclusive end
for xs, 0.. (x, i) { } // index idiom (replaces (x, i))
for xs, ys (x, y) { } // parallel (zip) iteration
for xs (x) => sum += x; // arrow body (full statement)
First-iterable-wins: the first iterable's length drives the loop and
must be bounded; the other positions follow by their own cursors (a
non-first range's end is not consulted or evaluated; a shorter
non-first collection is read past its length on mismatch). The old
single-iterable index capture is replaced by the trailing open range.
Capture/call disambiguation is positional: the paren group immediately
before '{' or '=>' is the capture, every earlier top-level group is a
call. 'for zip(a, b) (x, y)' calls zip; 'for f(n) { }' reads (n) as
the capture and errors with a parenthesize/add-capture hint. The old
':' form errors with a migration hint.
Lowering is unified across forms: one cursor slot per position (ranges
start at their start, collections at 0), all advanced together, the
first position's bound terminating. inline for keeps the single
bounded comptime range.
Migrated the full corpus (examples, library modules, issue repros,
in-source test strings). New coverage: examples/0050 (the full feature
surface) and examples/1149-1155 (seven diagnostic faces). specs.md For
Loop section + grammar rewritten; readme teaser updated.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// Range-based for loops: `for start..end: (i) { }` (cursor optional, `end`
|
||||
// exclusive) is a runtime counting loop; `inline for start..end: (i) { }`
|
||||
// Range-based for loops: `for start..end (i) { }` (cursor optional, `end`
|
||||
// exclusive) is a runtime counting loop; `inline for start..end (i) { }`
|
||||
// is comptime-unrolled — the cursor is a compile-time constant each
|
||||
// iteration, so `xs[i]` over a heterogeneous pack substitutes the concrete
|
||||
// per-position element (this is what drives pack iteration).
|
||||
@@ -16,14 +16,14 @@ impl Show for B { show :: (self: *B) -> string => "B"; }
|
||||
|
||||
// Comptime-unrolled iteration over a pack; cursor `i` indexes the pack.
|
||||
each :: (..xs: Show) -> void {
|
||||
inline for 0..xs.len: (i) {
|
||||
inline for 0..xs.len (i) {
|
||||
print("[{}]={}\n", i, xs[i].show());
|
||||
}
|
||||
}
|
||||
|
||||
main :: () -> s32 {
|
||||
// Runtime range, cursor used.
|
||||
for 0..3: (i) { print("i={}\n", i); }
|
||||
for 0..3 (i) { print("i={}\n", i); }
|
||||
|
||||
// Runtime range, no cursor — body runs `end - start` times.
|
||||
n := 0;
|
||||
@@ -31,7 +31,7 @@ main :: () -> s32 {
|
||||
print("n={}\n", n);
|
||||
|
||||
// Non-zero start.
|
||||
for 2..5: (j) { print("j={}\n", j); }
|
||||
for 2..5 (j) { print("j={}\n", j); }
|
||||
|
||||
// Inline unroll over a heterogeneous pack.
|
||||
each(A.{ x = 1 }, B.{ s = "hi" }, A.{ x = 3 });
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// `for xs: (*x)` binds each element by pointer — no per-element copy.
|
||||
// `for xs (*x)` binds each element by pointer — no per-element copy.
|
||||
// Mutations write back, and a pointer subject matches through the deref.
|
||||
#import "modules/std.sx";
|
||||
|
||||
@@ -10,12 +10,12 @@ Shape :: enum {
|
||||
main :: () -> s32 {
|
||||
// By-ref mutation writes back into the array (impossible with a value copy).
|
||||
xs : [3]s64 = .[1, 2, 3];
|
||||
for xs: (*x) { x.* = x + 100; }
|
||||
for xs (*x) { x.* = x + 100; }
|
||||
print("{} {} {}\n", xs[0], xs[1], xs[2]);
|
||||
|
||||
// Pointer subject matches through the deref; payload reads through the ref.
|
||||
shapes : [2]Shape = .[.circle(2.0), .none];
|
||||
for shapes: (*s) {
|
||||
for shapes (*s) {
|
||||
if s == {
|
||||
case .circle: (r) { print("circle {}\n", r); }
|
||||
case .none: { print("none\n"); }
|
||||
|
||||
@@ -10,7 +10,7 @@ Box :: struct {
|
||||
|
||||
sum_ptr :: (xs: *List(s64)) -> s64 {
|
||||
total : s64 = 0;
|
||||
for xs: (n) { total = total + n; } // iterate through a *List
|
||||
for xs (n) { total = total + n; } // iterate through a *List
|
||||
total
|
||||
}
|
||||
|
||||
@@ -21,12 +21,12 @@ main :: () -> s32 {
|
||||
xs.append(30);
|
||||
|
||||
s : s64 = 0;
|
||||
for xs: (n) { s = s + n; } // value capture
|
||||
for xs (n) { s = s + n; } // value capture
|
||||
print("sum {}\n", s); // 60
|
||||
|
||||
for xs: (*n) { n.* = n + 100; } // by-ref: writes back
|
||||
for xs (*n) { n.* = n + 100; } // by-ref: writes back
|
||||
s = 0;
|
||||
for xs: (n) { s = s + n; }
|
||||
for xs (n) { s = s + n; }
|
||||
print("sum2 {}\n", s); // 360
|
||||
|
||||
print("via ptr {}\n", sum_ptr(@xs)); // 360
|
||||
@@ -34,7 +34,7 @@ main :: () -> s32 {
|
||||
bs := List(Box).{};
|
||||
bs.append(.{ v = 7 });
|
||||
bt : s64 = 0;
|
||||
for bs: (*b) { bt = bt + b.boxed(); } // *Box receiver, value-self method
|
||||
for bs (*b) { bt = bt + b.boxed(); } // *Box receiver, value-self method
|
||||
print("boxes {}\n", bt); // 7
|
||||
0
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ main :: () {
|
||||
// For loop basic
|
||||
farr : [4]s32 = .[10, 20, 30, 40];
|
||||
out("for:");
|
||||
for farr: (it) {
|
||||
for farr (it) {
|
||||
out(" ");
|
||||
out(int_to_string(it));
|
||||
}
|
||||
@@ -126,14 +126,14 @@ main :: () {
|
||||
|
||||
// For with print
|
||||
out("for-print:");
|
||||
for farr: (it) {
|
||||
for farr (it) {
|
||||
print(" {}", it);
|
||||
}
|
||||
out("\n");
|
||||
|
||||
// For with index
|
||||
out("for-idx:");
|
||||
for farr: (_, ix) {
|
||||
for farr, 0.. (_, ix) {
|
||||
out(" ");
|
||||
out(int_to_string(ix));
|
||||
}
|
||||
@@ -141,14 +141,14 @@ main :: () {
|
||||
|
||||
// For with print two args
|
||||
out("for-2arg:");
|
||||
for farr: (it, ix) {
|
||||
for farr, 0.. (it, ix) {
|
||||
print(" {}@{}", it, ix);
|
||||
}
|
||||
out("\n");
|
||||
|
||||
// For with break
|
||||
out("for-break:");
|
||||
for farr: (it) {
|
||||
for farr (it) {
|
||||
if it == 30 { break; }
|
||||
print(" {}", it);
|
||||
}
|
||||
@@ -156,7 +156,7 @@ main :: () {
|
||||
|
||||
// For with continue
|
||||
out("for-continue:");
|
||||
for farr: (it) {
|
||||
for farr (it) {
|
||||
if it == 20 { continue; }
|
||||
print(" {}", it);
|
||||
}
|
||||
@@ -165,14 +165,14 @@ main :: () {
|
||||
// For on slice
|
||||
fsl : []s32 = .[10, 20, 30];
|
||||
out("for-slice:");
|
||||
for fsl: (it) {
|
||||
for fsl (it) {
|
||||
print(" {}", it);
|
||||
}
|
||||
out("\n");
|
||||
|
||||
// For on slice with index
|
||||
out("for-slice-idx:");
|
||||
for fsl: (it, ix) {
|
||||
for fsl, 0.. (it, ix) {
|
||||
print(" {}:{}", ix, it);
|
||||
}
|
||||
out("\n");
|
||||
@@ -181,8 +181,8 @@ main :: () {
|
||||
nf_a : [2]s32 = .[0, 1];
|
||||
nf_b : [2]s32 = .[0, 1];
|
||||
out("for-nested:");
|
||||
for nf_a: (oa) {
|
||||
for nf_b: (ob) {
|
||||
for nf_a (oa) {
|
||||
for nf_b (ob) {
|
||||
print(" ({},{})", oa, ob);
|
||||
}
|
||||
}
|
||||
@@ -191,7 +191,7 @@ main :: () {
|
||||
// For with break preserving index
|
||||
fbi : [5]s32 = .[10, 20, 30, 40, 50];
|
||||
fbi_idx := 0;
|
||||
for fbi: (it, ix) {
|
||||
for fbi, 0.. (it, ix) {
|
||||
if it == 30 { fbi_idx = ix; break; }
|
||||
}
|
||||
print("for-break-idx: {}\n", fbi_idx);
|
||||
|
||||
@@ -16,7 +16,7 @@ pair_add :: (a: $T, b: $U) -> s64 {
|
||||
|
||||
typed_sum :: (..args: []s32) -> s32 {
|
||||
result := 0;
|
||||
for args: (it) { result = result + it; }
|
||||
for args (it) { result = result + it; }
|
||||
result
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
main :: () -> s32 {
|
||||
sum := 0;
|
||||
for 0..1000000: (i) {
|
||||
for 0..1000000 (i) {
|
||||
buf : [128]s64 = ---;
|
||||
buf[0] = i;
|
||||
sum += buf[0];
|
||||
@@ -18,8 +18,8 @@ main :: () -> s32 {
|
||||
print("sum={}\n", sum);
|
||||
|
||||
n := 0;
|
||||
for 0..3000000: (i) {
|
||||
for 0..1: (j) { n += 1; }
|
||||
for 0..3000000 (i) {
|
||||
for 0..1 (j) { n += 1; }
|
||||
}
|
||||
print("n={}\n", n);
|
||||
0
|
||||
|
||||
@@ -13,12 +13,12 @@ main :: () -> s32 {
|
||||
i := 0;
|
||||
while i < 4096 { arr[i] = i; i += 1; }
|
||||
sum := 0;
|
||||
for arr: (x) { sum += x; }
|
||||
for arr (x) { sum += x; }
|
||||
print("sum={}\n", sum);
|
||||
|
||||
// By-value capture is a copy: mutating it leaves the array untouched.
|
||||
small : [3]s64 = .[10, 20, 30];
|
||||
for small: (x) { x += 100; }
|
||||
for small (x) { x += 100; }
|
||||
print("copy-guard: {} {} {}\n", small[0], small[1], small[2]);
|
||||
0
|
||||
}
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
#import "modules/std.sx";
|
||||
|
||||
main :: () -> s32 {
|
||||
for 0..3: (i) {
|
||||
for 0..3 (i) {
|
||||
defer print("cleanup {}\n", i);
|
||||
if i == 1 { break; }
|
||||
print("body {}\n", i);
|
||||
}
|
||||
print("after break loop\n");
|
||||
|
||||
for 0..3: (i) {
|
||||
for 0..3 (i) {
|
||||
defer print("c2 {}\n", i);
|
||||
if i == 1 { continue; }
|
||||
print("b2 {}\n", i);
|
||||
@@ -33,7 +33,7 @@ main :: () -> s32 {
|
||||
|
||||
// A break inside a nested block drains the nested block's defers AND the
|
||||
// loop body's, in LIFO order.
|
||||
for 0..2: (j) {
|
||||
for 0..2 (j) {
|
||||
defer print("outer {}\n", j);
|
||||
{
|
||||
defer print("inner {}\n", j);
|
||||
|
||||
54
examples/0050-basic-for-multi-iterable.sx
Normal file
54
examples/0050-basic-for-multi-iterable.sx
Normal file
@@ -0,0 +1,54 @@
|
||||
#import "modules/std.sx";
|
||||
|
||||
pair_sum :: (xs: []s64, ys: []s64) -> s64 {
|
||||
total := 0;
|
||||
for xs, ys (x, y) { total += x * y; }
|
||||
total
|
||||
}
|
||||
|
||||
make :: () -> [3]s64 {
|
||||
r : [3]s64 = .[7, 8, 9];
|
||||
r
|
||||
}
|
||||
|
||||
main :: () -> s32 {
|
||||
// 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];
|
||||
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];
|
||||
print("dot={}\n", pair_sum(a4, b4));
|
||||
|
||||
// Arrow bodies.
|
||||
s := 0;
|
||||
for 0..4 (i) => s += i;
|
||||
print("arrow-range s={}\n", s);
|
||||
t := 0;
|
||||
for xs (x) => t += x;
|
||||
print("arrow-coll t={}\n", t);
|
||||
|
||||
// Call iterable + capture (first group = args, last group = capture).
|
||||
for make() (v) { print("v{} ", v); }
|
||||
print("\n");
|
||||
|
||||
// No-capture call iterable via leading-group escape.
|
||||
n := 0;
|
||||
for (make()) { n += 1; }
|
||||
print("escape n={}\n", n);
|
||||
|
||||
// Three-way zip: two collections + cursor.
|
||||
for a4, b4, 100.. (p, q, k) { print("{}/{}/{} ", p, q, k); }
|
||||
print("\n");
|
||||
|
||||
// By-ref capture in a multi-iterable header.
|
||||
for a4, 0.. (*p, i) { p.* += i; }
|
||||
print("after ref: {} {} {} {}\n", a4[0], a4[1], a4[2], a4[3]);
|
||||
0
|
||||
}
|
||||
@@ -16,7 +16,7 @@ main :: () {
|
||||
spts : [2]Point = .[Point.{1, 2}, Point.{3, 4}];
|
||||
spt2 := spts[1];
|
||||
print("arr-struct-x: {}\n", spt2.x);
|
||||
for spts: (it) {
|
||||
for spts (it) {
|
||||
print("for-struct: {}\n", it);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,6 @@ main :: () {
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ main :: () -> s32 {
|
||||
|
||||
// for capture + index names
|
||||
xs := [3]s64.{ 10, 20, 30 };
|
||||
for xs: (`bool, `u16) {
|
||||
for xs, 0.. (`bool, `u16) {
|
||||
print("for = {} @ {}\n", `bool, `u16);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ pair_add :: (a: $T, b: $U) -> s64 {
|
||||
|
||||
typed_sum :: (..args: []s32) -> s32 {
|
||||
result := 0;
|
||||
for args: (it) { result = result + it; }
|
||||
for args (it) { result = result + it; }
|
||||
result
|
||||
}
|
||||
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
sum :: (..args: []s32) -> s32 {
|
||||
result := 0;
|
||||
for args: (it) {
|
||||
for args (it) {
|
||||
result = result + it;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
print_all :: (..args: []s32) {
|
||||
for args: (it) {
|
||||
for args (it) {
|
||||
out(int_to_string(it));
|
||||
out(" ");
|
||||
}
|
||||
@@ -26,7 +26,7 @@ main :: () -> s32 {
|
||||
out(int_to_string(sum(..arr)));
|
||||
out("\n");
|
||||
|
||||
for arr: (it) {
|
||||
for arr (it) {
|
||||
out(int_to_string(it));
|
||||
out(" ");
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ Point :: struct {
|
||||
|
||||
// Print all arguments — accepts any type, dispatches via type-switch
|
||||
print_any :: (..args: []Any) {
|
||||
for args: (it) {
|
||||
for args (it) {
|
||||
type := type_of(it);
|
||||
if type == {
|
||||
case int: out(int_to_string(cast(s32) it));
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// constant (a literal, or an `inline for` cursor). A runtime index (here a
|
||||
// `while`-loop counter) must produce a clear diagnostic, not the confusing
|
||||
// "unresolved 'args'" the slice-index fall-through used to give. To walk a
|
||||
// pack, use `inline for 0..args.len: (i) { ... }`, which unrolls so each
|
||||
// pack, use `inline for 0..args.len (i) { ... }`, which unrolls so each
|
||||
// `args[i]` is a comptime index.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
@@ -14,7 +14,7 @@ sink :: (v: s64) -> void { _ = v; }
|
||||
storage :: (..xs: Show) -> void { y := xs; _ = y; } // A: store
|
||||
call :: (..xs: Show) -> void { sink(xs); } // B: pass to a call
|
||||
ret :: (..xs: Show) -> s64 { return xs; } // C: return
|
||||
iter :: (..xs: Show) -> void { for xs : (x) { _ = x; } } // D: runtime iterate
|
||||
iter :: (..xs: Show) -> void { for xs (x) { _ = x; } } // D: runtime iterate
|
||||
|
||||
main :: () -> s32 {
|
||||
storage(A.{});
|
||||
|
||||
@@ -14,10 +14,10 @@ M :: 3;
|
||||
|
||||
main :: () {
|
||||
s := 0;
|
||||
inline for 0..M: (i) { s += i; }
|
||||
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; }
|
||||
inline for 0..(M + 1) (i) { t += i; }
|
||||
print("sum 0..(M+1) = {}\n", t); // 0 + 1 + 2 + 3 = 6
|
||||
}
|
||||
|
||||
@@ -9,6 +9,6 @@ M :: 3.0;
|
||||
|
||||
main :: () {
|
||||
s := 0;
|
||||
inline for 0..M: (i) { s += i; }
|
||||
inline for 0..M (i) { s += i; }
|
||||
print("sum 0..M = {}\n", s); // 0 + 1 + 2 = 3
|
||||
}
|
||||
|
||||
@@ -11,14 +11,14 @@
|
||||
|
||||
main :: () {
|
||||
s := 0;
|
||||
inline for -2..1: (i) { s += i; }
|
||||
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; }
|
||||
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; }
|
||||
inline for 0..(-2.0) (i) { e += i; }
|
||||
print("inline for 0..(-2.0) sum = {}\n", e); // empty range -> 0 iterations
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
combine :: (x: s64, y: s64) -> s64 { return x + y; }
|
||||
pick :: (..xs: []s64) -> s64 {
|
||||
result := 0;
|
||||
for xs: (it) { result = result + it; }
|
||||
for xs (it) { result = result + it; }
|
||||
result
|
||||
}
|
||||
from_a_combine :: () -> s64 { return combine(10, 20); }
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// pack, pick subtracts its two fixed args.
|
||||
combine :: (..xs: []s64) -> s64 {
|
||||
result := 0;
|
||||
for xs: (it) { result = result + it; }
|
||||
for xs (it) { result = result + it; }
|
||||
result
|
||||
}
|
||||
pick :: (a: s64, b: s64) -> s64 { return b - a; }
|
||||
|
||||
@@ -17,7 +17,7 @@ g :: () -> !E { return; }
|
||||
f :: () -> !E {
|
||||
defer { return; } // ERROR: return in defer body
|
||||
onfail { try g(); } // ERROR: try in onfail body
|
||||
defer { for 0..1: (i) { break; } } // ERROR: break in defer body (transitive through loop)
|
||||
defer { for 0..1 (i) { break; } } // ERROR: break in defer body (transitive through loop)
|
||||
onfail e { if e == error.Bad { continue; } } // ERROR: continue in onfail body
|
||||
try g();
|
||||
return;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// A by-reference loop capture (`for xs: (*m)`) binds `m` to a `*T`.
|
||||
// A by-reference loop capture (`for xs (*m)`) binds `m` to a `*T`.
|
||||
// Passing it where a `T` value is expected used to slip through to the
|
||||
// LLVM verifier ("Call parameter type does not match function signature").
|
||||
// The compiler now reports it at the call site with a fix-it: write `m.*`.
|
||||
@@ -11,7 +11,7 @@ take :: (m: Move) -> s64 { return m.flag; }
|
||||
|
||||
main :: () -> s32 {
|
||||
moves : [2]Move = .[ Move.{ flag = 1 }, Move.{ flag = 2 } ];
|
||||
for moves: (*m) {
|
||||
for moves (*m) {
|
||||
take(m);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Passing a `*T` where a `T` value is expected is caught at the call site —
|
||||
// not only for `for xs: (*m)` loop captures (see 215) but for any pointer,
|
||||
// not only for `for xs (*m)` loop captures (see 215) but for any pointer,
|
||||
// here a `*Move` parameter forwarded into a by-value parameter. Without the
|
||||
// check this slipped through to the LLVM verifier as "Call parameter type
|
||||
// does not match function signature".
|
||||
|
||||
@@ -19,8 +19,8 @@ main :: () -> s32 {
|
||||
if u8 := maybe() { } // if optional binding
|
||||
while s16 := maybe() { break; } // while optional binding
|
||||
xs := [3]s64.{ 10, 20, 30 };
|
||||
for xs: (bool) { } // for capture name
|
||||
for xs: (v, s32) { } // for index name
|
||||
for xs (bool) { } // for capture name
|
||||
for xs, 0.. (v, s32) { } // for index name
|
||||
opt: ?s64 = 5;
|
||||
r := if opt == { // match-arm capture
|
||||
case .some: (string) { 0 }
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
|
||||
main :: () {
|
||||
s := 0;
|
||||
inline for 0..4.5: (i) { s += i; }
|
||||
inline for 0..4.5 (i) { s += i; }
|
||||
print("unreachable: {}\n", s);
|
||||
}
|
||||
|
||||
9
examples/1149-diagnostics-for-colon-removed.sx
Normal file
9
examples/1149-diagnostics-for-colon-removed.sx
Normal file
@@ -0,0 +1,9 @@
|
||||
// The pre-multi-iterable `for xs: (x)` syntax (colon before the capture) is
|
||||
// rejected with a migration hint.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
main :: () {
|
||||
xs : [2]s64 = .[1, 2];
|
||||
for xs: (x) { }
|
||||
}
|
||||
9
examples/1150-diagnostics-for-capture-arity.sx
Normal file
9
examples/1150-diagnostics-for-capture-arity.sx
Normal file
@@ -0,0 +1,9 @@
|
||||
// A for capture group is positional: one capture per iterable (or none).
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
main :: () {
|
||||
xs : [2]s64 = .[1, 2];
|
||||
ys : [2]s64 = .[3, 4];
|
||||
for xs, ys (x) { }
|
||||
}
|
||||
8
examples/1151-diagnostics-for-open-first.sx
Normal file
8
examples/1151-diagnostics-for-open-first.sx
Normal file
@@ -0,0 +1,8 @@
|
||||
// The FIRST iterable drives the loop, so it must be bounded; an open range
|
||||
// `a..` may only follow it.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
main :: () {
|
||||
for 0.. (i) { }
|
||||
}
|
||||
7
examples/1152-diagnostics-for-inclusive-open.sx
Normal file
7
examples/1152-diagnostics-for-inclusive-open.sx
Normal file
@@ -0,0 +1,7 @@
|
||||
// `..=` is the inclusive bounded form — it requires an end expression.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
main :: () {
|
||||
for 0..= (i) { }
|
||||
}
|
||||
8
examples/1153-diagnostics-for-range-by-ref.sx
Normal file
8
examples/1153-diagnostics-for-range-by-ref.sx
Normal file
@@ -0,0 +1,8 @@
|
||||
// Range elements are synthesized values with no storage — `*` capture is
|
||||
// rejected.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
main :: () {
|
||||
for 0..3 (*i) { }
|
||||
}
|
||||
11
examples/1154-diagnostics-for-call-needs-capture.sx
Normal file
11
examples/1154-diagnostics-for-call-needs-capture.sx
Normal file
@@ -0,0 +1,11 @@
|
||||
// In a for header the trailing paren group is the CAPTURE; a call iterable
|
||||
// therefore needs one too. `()` cannot be a capture — parse error with the
|
||||
// hint (`for f(n) (x) { }` / `for (f(n)) { }` / bind it first).
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
g :: () -> s64 { 1 }
|
||||
|
||||
main :: () {
|
||||
for g() { }
|
||||
}
|
||||
12
examples/1155-diagnostics-for-not-iterable.sx
Normal file
12
examples/1155-diagnostics-for-not-iterable.sx
Normal file
@@ -0,0 +1,12 @@
|
||||
// The collision case of the positional capture rule: `for f(n) { }` reads
|
||||
// `(n)` as the capture, making the iterable `f` itself — not iterable, with
|
||||
// the parenthesize/add-capture hint.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
f :: (n: s64) -> s64 { n }
|
||||
|
||||
main :: () {
|
||||
n := 1;
|
||||
for f(n) { }
|
||||
}
|
||||
1
examples/expected/0050-basic-for-multi-iterable.exit
Normal file
1
examples/expected/0050-basic-for-multi-iterable.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
1
examples/expected/0050-basic-for-multi-iterable.stderr
Normal file
1
examples/expected/0050-basic-for-multi-iterable.stderr
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
9
examples/expected/0050-basic-for-multi-iterable.stdout
Normal file
9
examples/expected/0050-basic-for-multi-iterable.stdout
Normal file
@@ -0,0 +1,9 @@
|
||||
1:0 2:1 3:2 4:3 5:4
|
||||
[0]=10 [1]=20 [2]=30
|
||||
dot=300
|
||||
arrow-range s=6
|
||||
arrow-coll t=60
|
||||
v7 v8 v9
|
||||
escape n=3
|
||||
1/10/100 2/20/101 3/30/102 4/40/103
|
||||
after ref: 1 3 5 7
|
||||
@@ -1,5 +1,5 @@
|
||||
error: pack 'xs' has no runtime value — a pack is comptime-only and can't be used as a value here
|
||||
--> /Users/agra/projects/sx/examples/0536-packs-pack-as-value.sx:14:40
|
||||
--> examples/0536-packs-pack-as-value.sx:14:40
|
||||
|
|
||||
14 | storage :: (..xs: Show) -> void { y := xs; _ = y; } // A: store
|
||||
| ^^
|
||||
@@ -10,7 +10,7 @@ help: to store it, materialize a tuple: `(..xs)`
|
||||
| ^^
|
||||
|
||||
error: pack 'xs' has no runtime value — a pack is comptime-only and can't be used as a value here
|
||||
--> /Users/agra/projects/sx/examples/0536-packs-pack-as-value.sx:15:40
|
||||
--> examples/0536-packs-pack-as-value.sx:15:40
|
||||
|
|
||||
15 | call :: (..xs: Show) -> void { sink(xs); } // B: pass to a call
|
||||
| ^^
|
||||
@@ -21,7 +21,7 @@ help: materialize a tuple `(..xs)` to store it, or `xx xs` to convert it to an e
|
||||
| ^^
|
||||
|
||||
error: pack 'xs' has no runtime value — a pack is comptime-only and can't be used as a value here
|
||||
--> /Users/agra/projects/sx/examples/0536-packs-pack-as-value.sx:16:42
|
||||
--> examples/0536-packs-pack-as-value.sx:16:42
|
||||
|
|
||||
16 | ret :: (..xs: Show) -> s64 { return xs; } // C: return
|
||||
| ^^
|
||||
@@ -32,12 +32,12 @@ help: to return it, return a tuple `(..xs)` and make the return type that tuple
|
||||
| ^^
|
||||
|
||||
error: pack 'xs' has no runtime value — a pack is comptime-only and can't be used as a value here
|
||||
--> /Users/agra/projects/sx/examples/0536-packs-pack-as-value.sx:17:39
|
||||
--> examples/0536-packs-pack-as-value.sx:17:39
|
||||
|
|
||||
17 | iter :: (..xs: Show) -> void { for xs : (x) { _ = x; } } // D: runtime iterate
|
||||
17 | iter :: (..xs: Show) -> void { for xs (x) { _ = x; } } // D: runtime iterate
|
||||
| ^^
|
||||
|
||||
help: to iterate at comptime use `inline for 0..xs.len (i)`; for a runtime loop declare it as `..xs: []P` (a protocol slice) instead of a pack
|
||||
|
|
||||
17 | iter :: (..xs: Show) -> void { for xs : (x) { _ = x; } } // D: runtime iterate
|
||||
17 | iter :: (..xs: Show) -> void { for xs (x) { _ = x; } } // D: runtime iterate
|
||||
| ^^
|
||||
|
||||
@@ -17,16 +17,16 @@ error: 's16' is a reserved type name and cannot be used as an identifier
|
||||
| ^^^
|
||||
|
||||
error: 'bool' is a reserved type name and cannot be used as an identifier
|
||||
--> examples/1121-diagnostics-reserved-name-control-flow.sx:22:14
|
||||
--> examples/1121-diagnostics-reserved-name-control-flow.sx:22:13
|
||||
|
|
||||
22 | for xs: (bool) { } // for capture name
|
||||
| ^^^^
|
||||
22 | for xs (bool) { } // for capture name
|
||||
| ^^^^
|
||||
|
||||
error: 's32' is a reserved type name and cannot be used as an identifier
|
||||
--> examples/1121-diagnostics-reserved-name-control-flow.sx:23:17
|
||||
--> examples/1121-diagnostics-reserved-name-control-flow.sx:23:21
|
||||
|
|
||||
23 | for xs: (v, s32) { } // for index name
|
||||
| ^^^
|
||||
23 | for xs, 0.. (v, s32) { } // for index name
|
||||
| ^^^
|
||||
|
||||
error: 'string' is a reserved type name and cannot be used as an identifier
|
||||
--> examples/1121-diagnostics-reserved-name-control-flow.sx:26:22
|
||||
|
||||
@@ -1,5 +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; }
|
||||
12 | inline for 0..4.5 (i) { s += i; }
|
||||
| ^^^
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: for-loop syntax: the ':' before the capture was removed — write `for xs (x) { }` (index via `for xs, 0.. (x, i)`)
|
||||
--> examples/1149-diagnostics-for-colon-removed.sx:8:11
|
||||
|
|
||||
8 | for xs: (x) { }
|
||||
| ^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: for capture count must match the iterable count — one capture per iterable
|
||||
--> examples/1150-diagnostics-for-capture-arity.sx:8:20
|
||||
|
|
||||
8 | for xs, ys (x) { }
|
||||
| ^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
1
examples/expected/1151-diagnostics-for-open-first.exit
Normal file
1
examples/expected/1151-diagnostics-for-open-first.exit
Normal file
@@ -0,0 +1 @@
|
||||
1
|
||||
5
examples/expected/1151-diagnostics-for-open-first.stderr
Normal file
5
examples/expected/1151-diagnostics-for-open-first.stderr
Normal file
@@ -0,0 +1,5 @@
|
||||
error: the first iterable must have a bounded length (it drives the loop) — an open range 'a..' may only follow it
|
||||
--> examples/1151-diagnostics-for-open-first.sx:7:17
|
||||
|
|
||||
7 | for 0.. (i) { }
|
||||
| ^
|
||||
1
examples/expected/1151-diagnostics-for-open-first.stdout
Normal file
1
examples/expected/1151-diagnostics-for-open-first.stdout
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: '..=' requires an end expression — the open form is 'a..'
|
||||
--> examples/1152-diagnostics-for-inclusive-open.sx:6:14
|
||||
|
|
||||
6 | for 0..= (i) { }
|
||||
| ^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
1
examples/expected/1153-diagnostics-for-range-by-ref.exit
Normal file
1
examples/expected/1153-diagnostics-for-range-by-ref.exit
Normal file
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: a range element cannot be captured by reference
|
||||
--> examples/1153-diagnostics-for-range-by-ref.sx:7:19
|
||||
|
|
||||
7 | for 0..3 (*i) { }
|
||||
| ^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: expected capture variable name (a call iterable also needs a capture: `for f(n) (x) { }`)
|
||||
--> examples/1154-diagnostics-for-call-needs-capture.sx:10:11
|
||||
|
|
||||
10 | for g() { }
|
||||
| ^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
1
examples/expected/1155-diagnostics-for-not-iterable.exit
Normal file
1
examples/expected/1155-diagnostics-for-not-iterable.exit
Normal file
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: cannot iterate this expression — if the parens were call arguments, a call iterable also needs a capture (`for f(n) (x) { }`) or parentheses (`for (f(n)) { }`)
|
||||
--> examples/1155-diagnostics-for-not-iterable.sx:11:9
|
||||
|
|
||||
11 | for f(n) { }
|
||||
| ^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
Reference in New Issue
Block a user