Expand the abbreviated string type and its conversion builtin to the full
word everywhere:
str -> string (the immutable-string type)
str(x) -> str -> string(x) -> string (the stringify builtin;
what `{…}` interpolation calls)
Types are recognized by identifier, and llty maps both spellings to LLVM
`ptr`, so this is an atomic source rewrite: type annotations, the Ludic
type tags, the builtin name/dispatch, and the interpolation desugar, plus
the grammars, LSP, docs (type-str -> type-string, fn-str -> fn-string), and
inventory. int/bool stay (universally accepted, like Math).
Reseeded; C-free fixpoint holds; all suites green (45/24/29); site + check.py OK.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1.3 KiB
1.3 KiB
id: kw-extern name: extern category: structure kind: keyword tokens: extern sig: extern function name(a: T) -> R = "symbol" tip: Bind a name to an external native symbol — the seam for platform and library calls. order: 12
An extern function declares a function whose body lives outside Ludic and binds it to a native symbol resolved at link time. It is the seam through which Ludic reaches anything with a native interface — a system library, a math routine, or even another .ludic file compiled as a module. You write the Ludic signature you want to call and give the real symbol name after =; the linker connects them (pass -L/-l to ludicc to point at the library). Types must match the foreign ABI, so map each parameter and the return to the right Ludic type (int, fixed, ptr, …).
Parameters:
a— a typed argument passed straight through to the foreign symbol
program Physics {
extern function c_hypot(a: fixed, b: fixed) -> fixed = "hypot_fx"
property Velocity { delta_x: int = 0, delta_y: int = 0 }
model Projectile { Velocity }
handler MeasureSpeed phase Update {
for (velocity) in query [Velocity, {Projectile}] {
let speed = c_hypot(a: fx(velocity.delta_x), b: fx(velocity.delta_y))
Screen.status(string(flr(speed)))
}
}
}