lang: inline for element form over packs — multi-iterable parity

This commit is contained in:
agra
2026-06-11 14:42:59 +03:00
parent 03dc10bba3
commit 40805e08ec
15 changed files with 277 additions and 40 deletions

View File

@@ -0,0 +1,63 @@
// `inline for` element form over a pack — multi-iterable parity with the
// runtime for-loop. Position 0 drives the unroll count (a pack's arity or a
// bounded range's span); trailing iterables pair with it. A pack capture is
// the concrete per-position element viewed through the constraint protocol
// (same semantics as `xs[i]`); a range capture is a comptime cursor.
//
// inline for xs (x) — element form
// inline for xs, 0.. (x, i) — element + paired index
// inline for 0..xs.len, xs (i, x) — range driver, trailing pack
// inline for xs { } — captureless; N=0 unrolls nothing
#import "modules/std.sx";
Show :: protocol { show :: () -> string; }
IntBox :: struct { v: s64; }
StrBox :: struct { s: string; }
impl Show for IntBox { show :: (self: *IntBox) -> string { int_to_string(self.v) } }
impl Show for StrBox { show :: (self: *StrBox) -> string { self.s } }
bare :: (..xs: Show) {
inline for xs (x) {
print("bare: {}\n", x.show());
}
}
elem_and_index :: (..xs: Show) {
inline for xs, 0.. (x, i) {
print("{}: {}\n", i, x.show());
}
}
range_driver :: (..xs: Show) {
inline for 0..xs.len, xs (i, x) {
print("r{}: {}\n", i, x.show());
}
}
offset_index :: (..xs: Show) {
inline for xs, 10.. (x, i) {
print("{} -> {}\n", i, x.show());
}
}
captureless :: (..xs: Show) {
n := 0;
inline for xs { n += 1; }
print("ran {}\n", n);
}
value_pos :: (..xs: Show) {
inline for xs (x) {
print("val: {}\n", x);
}
}
empty :: (..xs: Show) {
inline for xs (x) { print("never\n"); }
print("empty ok\n");
}
main :: () {
bare(IntBox.{ v = 7 }, StrBox.{ s = "hi" });
elem_and_index(IntBox.{ v = 7 }, StrBox.{ s = "hi" });
range_driver(IntBox.{ v = 1 }, StrBox.{ s = "two" });
offset_index(StrBox.{ s = "x" }, StrBox.{ s = "y" });
captureless(IntBox.{ v = 0 }, IntBox.{ v = 0 }, IntBox.{ v = 0 });
value_pos(IntBox.{ v = 42 });
empty();
}

View File

@@ -0,0 +1,31 @@
// `inline for` pack rejections: (1) a pack-element capture exposes only the
// constraint protocol's interface (same rule as `xs[i]`, example 0530);
// (2) a pack element cannot be captured by reference (`(*x)` — an element is
// an AST-substituted call arg, no storage); (3) a trailing pack shorter than
// the driving iterable; (4) a non-pack, non-range iterable.
#import "modules/std.sx";
Show :: protocol { show :: () -> string; }
IntBox :: struct { v: s64; }
impl Show for IntBox { show :: (self: *IntBox) -> string { int_to_string(self.v) } }
leak :: (..xs: Show) {
inline for xs (x) {
print("{}\n", x.v);
}
}
borrow :: (..xs: Show) {
inline for xs (*x) { }
}
short :: (..xs: Show) {
inline for 0..5, xs (i, x) { }
}
main :: () {
leak(IntBox.{ v = 5 });
borrow(IntBox.{ v = 5 });
short(IntBox.{ v = 1 }, IntBox.{ v = 2 });
arr := .[1, 2, 3];
inline for arr (x) { }
}

View File

@@ -37,7 +37,7 @@ error: pack 'xs' has no runtime value — a pack is comptime-only and can't be u
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
help: to iterate at comptime use `inline for xs (x)` (or `inline for 0..xs.len (i)` for the index); 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
| ^^

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,11 @@
bare: 7
bare: hi
0: 7
1: hi
r0: 1
r1: two
10 -> x
11 -> y
ran 3
val: IntBox{v: 42}
empty ok

View File

@@ -0,0 +1,23 @@
error: 'v' is not part of protocol 'Show' — a pack element exposes only the protocol's interface
--> examples/1164-diagnostics-inline-for-pack-rejections.sx:15:23
|
15 | print("{}\n", x.v);
| ^^^
error: a pack element cannot be captured by reference
--> examples/1164-diagnostics-inline-for-pack-rejections.sx:19:21
|
19 | inline for xs (*x) { }
| ^
error: inline for: pack 'xs' has 2 elements but the unroll is 5 iterations
--> examples/1164-diagnostics-inline-for-pack-rejections.sx:22:22
|
22 | inline for 0..5, xs (i, x) { }
| ^^
error: inline for: each iterable must be a comptime range or a pack — `inline for 0..N (i) { }` / `inline for xs (x) { }`
--> examples/1164-diagnostics-inline-for-pack-rejections.sx:30:16
|
30 | inline for arr (x) { }
| ^^^