lang: for-loop by-ref element capture (for xs: (*x))

(*x) binds x to a pointer into the collection (index_gep) instead of a per-element value copy: passing it on (e.g. to a *T param) is zero-copy and mutations write back. In a value position x auto-derefs — a binary-op operand loads the element, a pointer-typed slot keeps the pointer, and an 'if x == {...}' match derefs the pointee for its tag/payload. Arrays GEP through their storage so writes hit the original. Regression test: examples/for-by-ref-capture.sx.
This commit is contained in:
agra
2026-05-31 10:29:16 +03:00
parent 4415274894
commit 185df9afb7
6 changed files with 88 additions and 10 deletions

View File

@@ -2864,6 +2864,7 @@ pub const Parser = struct {
var capture_name: []const u8 = "";
var index_name: ?[]const u8 = null;
var capture_by_ref = false;
if (range_end != null) {
// Range capture is the optional cursor: `(i)` or nothing.
@@ -2875,9 +2876,14 @@ pub const Parser = struct {
try self.expect(.r_paren);
}
} else {
// Collection form: `: (capture, index?)`.
// Collection form: `: (capture, index?)`. A leading `*` on the
// capture (`(*x)`) binds it by pointer into the collection.
try self.expect(.colon);
try self.expect(.l_paren);
if (self.current.tag == .star) {
capture_by_ref = true;
self.advance();
}
if (self.current.tag != .identifier) return self.fail("expected capture variable name");
capture_name = self.tokenSlice(self.current);
self.advance();
@@ -2898,6 +2904,7 @@ pub const Parser = struct {
.capture_name = capture_name,
.index_name = index_name,
.range_end = range_end,
.capture_by_ref = capture_by_ref,
} });
}