lang: inline for element form over packs — multi-iterable parity
This commit is contained in:
63
examples/0545-packs-inline-for-element.sx
Normal file
63
examples/0545-packs-inline-for-element.sx
Normal 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();
|
||||
}
|
||||
31
examples/1164-diagnostics-inline-for-pack-rejections.sx
Normal file
31
examples/1164-diagnostics-inline-for-pack-rejections.sx
Normal 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) { }
|
||||
}
|
||||
@@ -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
|
||||
| ^^
|
||||
|
||||
1
examples/expected/0545-packs-inline-for-element.exit
Normal file
1
examples/expected/0545-packs-inline-for-element.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
1
examples/expected/0545-packs-inline-for-element.stderr
Normal file
1
examples/expected/0545-packs-inline-for-element.stderr
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
11
examples/expected/0545-packs-inline-for-element.stdout
Normal file
11
examples/expected/0545-packs-inline-for-element.stdout
Normal 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
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -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) { }
|
||||
| ^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
Reference in New Issue
Block a user