feat: tuple syntax cutover — Tuple(...) type + .(...) value
Replace the bare-paren tuple grammar with explicit, position-unambiguous
forms, mirroring how structs work:
type `(A, B)` -> `Tuple(A, B)` (named keeps `:`)
value `(a, b)` -> `.(a, b)` (named uses `=`)
typed (new) -> `Tuple(A, B).(a, b)` (like `Point.{...}`)
failable `-> (T, !)` -> `-> T !`
`-> (T1, T2, !)`-> `-> Tuple(T1, T2) !` (channel outside Tuple)
Bare `(...)` is now grouping only, everywhere; a comma in bare parens is a
hard error with a migration hint. Grouping, function types `(A, B) -> R`,
param lists, lambdas, and match bindings are unaffected.
`Tuple(...)` is strictly a TYPE in every position (including `size_of` /
`type_info` args); a tuple VALUE comes only from `.(...)` (anonymous) or
`Tuple(...).(...)` (explicitly typed). A bare `Tuple(1, 2)` is a tuple
type with non-type elements -> rejected.
The ~110 tuple-bearing corpus files were migrated with a one-shot
AST-aware migrator (the `sx migrate` tool from the prior commit, removed
here). New examples: 0130 (new syntax), 0131 (typed construction), 1060
(named-tuple failable return). 1116 golden updated for the new hint text.
This commit is contained in:
@@ -14,7 +14,7 @@ impl Box(i64) for IntCell { get :: (self: *IntCell) -> i64 => self.v; }
|
||||
impl Box(string) for StrCell { get :: (self: *StrCell) -> string => self.s; }
|
||||
|
||||
snapshot :: (..xs: Box) -> void {
|
||||
t := (..xs.get); // tuple (i64, string) materialized from the pack
|
||||
t := .(..xs.get); // tuple (i64, string) materialized from the pack
|
||||
print("0={} 1={}\n", t.0, t.1);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ impl Box(i64) for Dbl { get :: (self: *Dbl) -> i64 => self.n * 2; }
|
||||
// Tuple type `(..xs.T)` — heterogeneous (i64, string), matched by the
|
||||
// value-projection `(..xs.get)`.
|
||||
snap :: (..xs: Box) -> void {
|
||||
t : (..xs.T) = (..xs.get);
|
||||
t : Tuple(..xs.T) = .(..xs.get);
|
||||
print("0={} 1={}\n", t.0, t.1);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,19 +7,19 @@
|
||||
|
||||
Box :: struct($R: Type, ..$Ts: []Type) {
|
||||
r: $R;
|
||||
pair: (..$Ts); // tuple of the pack's element types
|
||||
pair: Tuple(..$Ts); // tuple of the pack's element types
|
||||
}
|
||||
|
||||
main :: () -> i32 {
|
||||
// Box(i64, i32, string): R=i64, Ts=[i32, string], pair: (i32, string).
|
||||
a : Box(i64, i32, string) = ---;
|
||||
a.r = 7;
|
||||
a.pair = (42, "hi"); // whole-tuple field store
|
||||
a.pair = .(42, "hi"); // whole-tuple field store
|
||||
print("a: r={} 0={} 1={}\n", a.r, a.pair.0, a.pair.1);
|
||||
|
||||
// A different shape → a different per-position tuple field.
|
||||
b : Box(bool, string, bool) = ---; // Ts=[string, bool], pair: (string, bool)
|
||||
b.pair = ("x", true);
|
||||
b.pair = .("x", true);
|
||||
print("b: 0={} 1={}\n", b.pair.0, b.pair.1);
|
||||
0
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ impl VL(i64) for IntCell { get :: (self: *IntCell) -> i64 => self.v; }
|
||||
impl VL(string) for StrCell { get :: (self: *StrCell) -> string => self.s; }
|
||||
|
||||
Combined :: struct($R: Type, ..$Ts: []Type) {
|
||||
sources: (..VL(Ts)); // (VL(T0), VL(T1), …) — tuple of protocol values
|
||||
sources: Tuple(..VL(Ts)); // (VL(T0), VL(T1), …) — tuple of protocol values
|
||||
value: $R;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ main :: () -> i32 {
|
||||
// Combined(i64, i64, string): R=i64, Ts=[i64, string],
|
||||
// sources: (VL(i64), VL(string)).
|
||||
c : Combined(i64, i64, string) = ---;
|
||||
c.sources = (xx IntCell.{ v = 10 }, xx StrCell.{ s = "hi" });
|
||||
c.sources = .(xx IntCell.{ v = 10 }, xx StrCell.{ s = "hi" });
|
||||
c.value = 99;
|
||||
print("{} {} {}\n", c.sources.0.get(), c.sources.1.get(), c.value); // 10 hi 99
|
||||
0
|
||||
|
||||
@@ -11,7 +11,7 @@ IntCell :: struct { v: i64; }
|
||||
impl VL(i64) for IntCell { get :: (self: *IntCell) -> i64 => self.v; }
|
||||
|
||||
Combined :: struct($R: Type, ..$Ts: []Type) {
|
||||
sources: (..VL(Ts));
|
||||
sources: Tuple(..VL(Ts));
|
||||
value: $R;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,13 +12,13 @@ impl VL(i64) for IntCell { get :: (self: *IntCell) -> i64 => self.v; }
|
||||
impl VL(string) for StrCell { get :: (self: *StrCell) -> string => self.s; }
|
||||
|
||||
Combined :: struct($R: Type, ..$Ts: []Type) {
|
||||
sources: (..VL(Ts));
|
||||
sources: Tuple(..VL(Ts));
|
||||
value: $R;
|
||||
}
|
||||
|
||||
build :: (..sources: VL) -> void {
|
||||
c : Combined(i64, ..sources.T) = ---;
|
||||
c.sources = (..sources); // pack → tuple, per-element erase
|
||||
c.sources = .(..sources); // pack → tuple, per-element erase
|
||||
print("{} {}\n", c.sources.0.get(), c.sources.1.get());
|
||||
}
|
||||
|
||||
|
||||
@@ -17,14 +17,14 @@ IntCell :: struct { v: i64; }
|
||||
impl VL(i64) for IntCell { get :: (self: *IntCell) -> i64 => self.v; }
|
||||
|
||||
Combined :: struct($R: Type, ..$Ts: []Type) {
|
||||
sources: (..VL(Ts));
|
||||
sources: Tuple(..VL(Ts));
|
||||
value: $R;
|
||||
}
|
||||
impl VL($R) for Combined($R, ..$Ts) { get :: (self: *Combined) -> $R => self.value; }
|
||||
|
||||
map :: (mapper: Closure(..sources.T) -> $R, ..sources: VL) -> VL($R) {
|
||||
c : Combined($R, ..sources.T) = ---;
|
||||
c.sources = (..sources);
|
||||
c.sources = .(..sources);
|
||||
c.value = mapper(..sources.get);
|
||||
return xx c;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user