ffi: drop legacy name: ..T variadic syntax
Parser hard-rejects the legacy `name: ..T` form with a one-line migration message pointing at the new `..name: []T` shape. The leading-`..` form is the one the lowering paths (`resolveParamType` / `packVariadicCallArgs`) treat as canonical post-issue-0049; leaving both forms accepted invited the same class of cross-module emit crashes any time a `..T`-form decl in stdlib crossed an import boundary. `specs.md` updated alongside: the Variadic Functions section now documents `..name: []T` as the surface form, with notes on homogeneous vs `[]Any` boxing and the `..` spread at call sites. Inline references to `args: ..Any` in §7 and §8 refreshed.
This commit is contained in:
24
specs.md
24
specs.md
@@ -951,14 +951,22 @@ sum :: (a: $T, b: T) -> T {
|
||||
- Multiple type parameters are supported: `(a: $T, b: $U) -> T`
|
||||
|
||||
### Variadic Functions
|
||||
Functions can accept a variable number of arguments using `..Type` syntax:
|
||||
Functions can accept a variable number of arguments using `..name: []Type` syntax:
|
||||
```sx
|
||||
print :: (fmt: string, args: ..Any) { ... }
|
||||
print :: (fmt: string, ..args: []Any) { ... }
|
||||
path_join :: (..parts: []string) -> string { ... }
|
||||
```
|
||||
- `..Any` means zero or more arguments, each boxed into `Any` (type tag + payload)
|
||||
- The variadic parameter must be the last parameter
|
||||
- At call sites, variadic arguments are automatically boxed: `print("x={}, y={}\n", x, y)`
|
||||
- Inside the function body, `args` is accessed as a slice-like sequence
|
||||
- The leading `..` marks the parameter as variadic; the declared type is the
|
||||
slice the body sees (so `..parts: []string` makes `parts` a `[]string` inside).
|
||||
- The variadic parameter must be the last positional parameter.
|
||||
- For homogeneous element types (`[]s32`, `[]string`, ...), the call site packs the
|
||||
trailing args into a stack-allocated `[N x T]` and passes a slice over it.
|
||||
- For `[]Any`, each trailing arg is boxed into `Any` (type tag + payload) before
|
||||
packing; `args[i]` reads back the boxed value.
|
||||
- A `..` spread at the call site unpacks an existing slice/array into the variadic
|
||||
tail: `sum(..arr)`.
|
||||
- The heterogeneous comptime-pack form `..$args: []Type` binds per-position
|
||||
comptime types — see "Variadic heterogeneous type packs" below.
|
||||
|
||||
### Type Inference
|
||||
- `::` bindings infer type from the right-hand side
|
||||
@@ -1663,7 +1671,7 @@ Built-in functions are declared in `std.sx` with the `#builtin` suffix, which te
|
||||
|
||||
### I/O
|
||||
- `out(str: string) -> void` — write a string to standard output
|
||||
- `print(fmt: string, args: ..Any)` — formatted print. Parses `{}` placeholders in the format string and substitutes arguments. When all argument types are statically known, the compiler specializes the call at compile time (no `Any` boxing).
|
||||
- `print(fmt: string, ..args: []Any)` — formatted print. Parses `{}` placeholders in the format string and substitutes arguments. When all argument types are statically known, the compiler specializes the call at compile time (no `Any` boxing).
|
||||
|
||||
### Math
|
||||
- `sqrt(x: $T) -> T` — square root (maps to LLVM intrinsic)
|
||||
@@ -1741,7 +1749,7 @@ response :: format("HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n{}", body.len,
|
||||
// response is a static string constant — no runtime allocation
|
||||
```
|
||||
|
||||
This works for any function, not just `format`. The mechanism is general: the VM compiles the function body (including `#insert` directives, variadic `..Any` args, and calls to other functions) and executes it entirely at compile time. If the VM encounters something it cannot evaluate (e.g., foreign function calls, unsupported operations), it silently falls through to runtime codegen.
|
||||
This works for any function, not just `format`. The mechanism is general: the VM compiles the function body (including `#insert` directives, variadic `..args: []Any` args, and calls to other functions) and executes it entirely at compile time. If the VM encounters something it cannot evaluate (e.g., foreign function calls, unsupported operations), it silently falls through to runtime codegen.
|
||||
|
||||
### Build Configuration
|
||||
|
||||
|
||||
Reference in New Issue
Block a user