iOS lock step keyboard + metal

This commit is contained in:
agra
2026-05-18 17:40:10 +03:00
parent b43472e6ab
commit f9ecf9d00e
68 changed files with 4794 additions and 203 deletions

View File

@@ -475,6 +475,72 @@ The impl is instantiated per concrete type argument, like generic struct methods
Static dispatch is automatic when the concrete type is known. Dynamic dispatch only when explicitly type-erased via `xx` into a protocol value.
#### Parameterised Protocols (compile-time only)
A protocol with type parameters is compile-time only — it has no vtable
and no boxed instance shape. Each `impl` is monomorphised per
`(ProtocolArgs, Source)` pair. The canonical example is `Into`, declared
in `modules/std.sx`:
```sx
Into :: protocol(Target: Type) {
convert :: () -> Target;
}
```
A user can then add conversions for any `(Source, Target)` pair:
```sx
MyString :: struct { tag: s64 = 0; }
impl Into(MyString) for s64 {
convert :: (self: s64) -> MyString { .{ tag = self }; }
}
main :: () -> s32 {
x : MyString = xx 42; // direct call to monomorphised convert
0;
}
```
The `xx` operator hooks into this mechanism: when an explicit target type
is provided and the built-in coercion ladder doesn't apply,
`xx val : T` lowers to `val.convert()` where `convert` comes from the
visible `impl Into(T) for typeof(val)`. The call is a direct call — no
vtable, no runtime dispatch.
**Source side is a TypeExpr.** Unlike nullary `impl P for SomeStruct`,
the `for`-side of a parameterised impl accepts any type expression,
including closure and function types:
```sx
impl Into(Block) for Closure() -> void { ... }
impl Into(MyBuf) for []u8 { ... }
```
**Lookup rules:**
- **Built-ins win.** The user-space fallback only fires when
`coerceToType` made no progress (numeric narrow/widen, ptr↔int, etc.
take priority).
- **Only at explicit `xx`.** Implicit conversions (assignment,
parameter passing) never trigger user-space coercions.
- **Explicit target required.** `xx val` with no surrounding type
context still defaults to `s64` for legacy reasons; the user-space
fallback only fires when the target was named explicitly.
- **Import-scoped visibility.** An `impl` is visible from a file only
if the file transitively imports the impl's defining module. An impl
in an imported-but-not-directly-related module produces a clean
diagnostic (`no visible xx conversion …`).
- **Duplicate impls error.** If two impls for the same
`(Source, Target)` pair are both visible, the compiler emits a
diagnostic naming both source modules. Same-file duplicates are
caught at registration time. Cross-module duplicates are caught at
the `xx` site.
- **No recursion.** A `convert` body that re-enters `xx self : Target`
for the same `(Source, Target)` pair produces a "recursive xx
conversion" diagnostic; the compiler does not try to monomorphise
the convert into itself.
### Tuple Types
Anonymous product types with optional field names. Tuples are first-class values — they can be stored in variables, passed to functions, and returned.