rontolisp:wasm-export
(rontolisp:wasm-export 'name :as "alias" :params '(type...) :returns type :async t)
Marks a top-level defun as host-callable when compiling to a WebAssembly core
module, declaring the WASM-boundary types of its parameters and result. It is a
compile-time directive, not an ordinary function: on the interpreter and
JVM backends it is a no-op that simply returns the named symbol, so the same
source runs on every backend. See
Compiling to WebAssembly for the full guide.
Arguments
- A quoted symbol naming the top-level
defunto export. It resolves in the current package like adefunname. :as— the WASM export name, as a string (e.g."factorial", or a camelCase name for a JavaScript-facing API). Defaults to the bare Lisp name (fact, without any package qualifier).:params— a list of boundary type designators, one per parameter. Omitted,nilor'()means no arguments.:returns— the result boundary type designator. Omitted,nil,'()or:voiddeclares a void result (the Lisp return value is discarded).:async—tlifts the export as an async component-model function under--component, so I/O inside it (print,rontolisp:fetch, ...) works instead of trapping. Defaults tonil(a synchronous, pure-compute lift). Meaningful only under--component: Preview 1 /--no-wasicore exports ignore it, and--no-gc --componentrejects it.
The type designators and their boundary representations are:
| Designator | WASM boundary | Notes |
|---|---|---|
:int | i32 | 31-bit signed range (the internal i31ref) |
:long | i64 | --no-gc only; full 64-bit signed range, matching the scalar backend's internal i64 (no wrap/extend at the boundary) |
:float | f64 | |
:bool | i32 | 0 is nil, any non-zero value is t |
:string | (ptr, len) | UTF-8 bytes in linear memory |
:s-expr | (ptr, len) | s-expression text in linear memory (any value except a function) |
With the default (GC) backend, :int crosses the boundary as i32 but the
internal integer is an i31ref, so a value returned through :int is truncated
past the 32-bit boundary. On the non-GC backend (--no-gc) integers are computed
as i64, so use :long when a parameter or result can exceed the 32-bit range —
it exposes the full width with no wrap/extend conversion.
Limitations
- Under
--component, an export becomes a typed component-model export callable with WAVE syntax (wasmtime run --invoke 'name(args)')::int/:float/:bool/void,:stringand:s-expras component-modelstring(plus:longwith--no-gc, which has no:s-expr). A sync (default) export must be pure-compute — I/O inside it traps; declare:async twhen the export prints or fetches. Under--no-gc --component,:asyncis rejected but printing works in the sync export itself, through a built-in WASI 0.2 stdio micro-adapter wired in only when the program prints. The export name must be lower-kebab-case (rename with:asotherwise). See Component-model function exports and Compact component output. On the interpreter and JVM the directive just returns the named symbol. - Only a top-level
defuncan be exported; the declared parameter count must match its arity, and functions that take or return function values are out of scope. - Outside
--component, the exported function is pure-compute: any I/O (printing, reading, time, random, or a top-level I/O form) traps under--no-wasiand is otherwise unsupported. One exception: under--no-gc,print/princ/terpriwork through a singlefd_writeimport that is added only when the program prints (see Printing). - The non-GC backend (
--no-gc) supports:int/:long/:float/:bool/:stringbut not:s-expr, which needs the cons/reader/printer runtime.:longis--no-gc-only: the GC backend rejects it (its integers arei31ref, which cannot hold ani64), pointing you at--no-gc.