Commit Graph

2 Commits

Author SHA1 Message Date
agra
116af2359e 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.
2026-06-10 20:30:55 +03:00
agra
0d29f2c286 docs(spec): split range bounds from counts; pin inline-for range semantics (0083)
specs.md lumped `inline for` / `for` range bounds in with counts (array
dimension, Vector lane count, generic value-param count) under the
count negative-rejection rule. A range bound is a range ENDPOINT, not a
count: negative endpoints are valid and an empty/inverted range runs zero
iterations. The compiler already implements this correctly (Agra ruling:
spec-text bug, no code change).

- specs.md: counts and range bounds are now described separately. Counts
  reject negatives; bounds accept any compile-time integer (negatives
  valid, integral floats fold) but still reject a non-integral float
  because the loop cursor must be an integer.
- examples/0612-comptime-inline-for-range-bounds.sx: `inline for -2..1`
  and `for -2..1` both sum -3; `inline for 0..(-2.0)` runs zero
  iterations (empty range). Runtime/comptime parity asserted.
- examples/1138-diagnostics-inline-for-non-integral-bound.sx: a
  non-integral float bound `inline for 0..4.5` is a clean diagnostic,
  exit 1 (must-be-integer still applies to bounds).

Count consumers (1132/1133/1134/1135) unchanged and green.
2026-06-04 15:17:33 +03:00