Files
sx/examples/packs/0534-packs-pack-type-projection.sx
agra 989e18b760 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.
2026-06-25 17:53:57 +03:00

39 lines
1.3 KiB
Plaintext

// Feature 1 — TYPE-position pack projection `xs.T`. The per-element protocol
// type-arg `T` projects into a Pack of types, usable in type/signature
// positions: a tuple type `(..xs.T)` and a closure signature
// `Closure(..xs.T) -> R`. (`T` of each element comes from its
// `impl Box(T) for <elem>`.)
#import "modules/std.sx";
Box :: protocol(T: Type) {
get :: (self: *Self) -> T;
}
IntCell :: struct { v: i64; }
StrCell :: struct { s: string; }
Dbl :: struct { n: i64; }
impl Box(i64) for IntCell { get :: (self: *IntCell) -> i64 => self.v; }
impl Box(string) for StrCell { get :: (self: *StrCell) -> string => self.s; }
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 : Tuple(..xs.T) = .(..xs.get);
print("0={} 1={}\n", t.0, t.1);
}
// Closure signature `Closure(..xs.T) -> i64` — here `Closure(i64, i64) -> i64`.
// The closure literal's params are contextually typed from the projection.
fold :: (..xs: Box) -> i64 {
cb : Closure(..xs.T) -> i64 = (a, b) => a + b;
return cb(xs[0].get(), xs[1].get());
}
main :: () -> i32 {
snap(IntCell.{ v = 42 }, StrCell.{ s = "hi" }); // (i64, string)
print("fold={}\n", fold(IntCell.{ v = 10 }, Dbl.{ n = 5 })); // 10 + 10 = 20
0
}