Expand description
A wasm32-unknown-unknown wrapper exposing the elly parse + eval
pipeline to JavaScript, with IO and imports through elly_host.
The elly and muon crates are no_std; this thin shim links std only
for the allocator that wasm32-unknown-unknown provides, so no
wasm-bindgen (or any post-processing tool) is needed — the .wasm is
loaded directly.
§Session
The module keeps one realm — an elly::Ctx and the IO built over it —
for as long as the instance lives. Every elly_run evaluates in it, so the
builtin modules keep their identity across runs and an imported module loads
once. IO.Proc.exit ends the session: the host is expected to drop the
instance and make a new one (see elly_host_exit below).
§ABI
Strings cross the boundary as (ptr, len) into wasm linear memory:
elly_alloc(len) -> ptr— reservelenbytes for JS to write UTF-8 into.elly_run(ptr, len) -> out— parse and evaluate those bytes; returns a pointer to a length-prefixed result: a little-endianu32byte length followed by that many bytes of UTF-8 JSON (see below).elly_free(ptr, len)— release a block obtained fromelly_alloc.
The module imports its system surface from elly_host (the Sys shim):
elly_host_write(stream, ptr, len)—IO.print/write(stream 1) andIO.error(stream 2).elly_host_read(ptr, len, out_len) -> ptr— the source of the module file at the path(ptr, len), or0if there is none. The host allocates the block withelly_alloc, writes its length as au32atout_len, and hands ownership over.elly_host_exit(code)—IO.Proc.exit. It must not return: the host throws, which abandons the run and the instance with it.
The source is one of two things:
- an expression, resolved with
IOin scope; - a module declaring
__main, run the way theellybinary runs a program, with its imports resolved below/libthroughelly_host::FsResolver. A source is taken as a module when it does not parse as an expression but does compile as a module.
The JSON result is one of:
{"ast":<expr>,"value":"<display>"}— an expression, evaluated.<expr>is the tagged AST dump (elly::Expr::to_json).{"ast":<expr>,"exit":N}— the expression ranIO.Proc.return N.{"ast":<expr>,"error":{"stage":"eval","raised":"<display>"}}— parsed, but evaluation raised a value that unwound to the top level (an explicit__Err.raiseor a host failure like.div_by_zero); the AST is still shown.{"module":true,…}— the samevalue/exit/errorshapes for a module’s__main, without an AST, plus"error":{"stage":"load","kind":"…"}when the module or one of its imports would not load, or it has no__main.{"error":{"stage":"parse","kind":"…"}}— a valid Muon tree but not a valid Elly program in this subset.{"error":{"stage":"syntax","offset":N,"kind":"…"}}— the syntax layer (Muon) rejected the input.
Modules§
- native
- Native builds have no page to import from. This side stands in for it, so
a test can run the playground’s examples (
tests/examples.rs, which compiles this file in as a module): files come from a table the test sets, writes are recorded, and an exit unwinds with anExitpayload.
Structs§
- Session
- One realm and the
IOcapability built over it.elly_runkeeps one per instance; a native test makes its own.
Enums§
- Outcome
- How one run of a source ended. Each kind maps to one shape of the JSON
described in the module docs. The
stagethere mirrors the pipeline vocabulary:syntax(the Muon layer),parse(Muon tree → Elly AST),load(a module graph),eval(a raise that unwound to the top level).
Functions§
- elly_
alloc - Reserve
lenbytes of linear memory and hand ownership to the caller. - elly_
free ⚠ - Release a block previously returned by
elly_alloc(samelen). - elly_
run ⚠ - Run
lenUTF-8 bytes atptrthrough the pipeline; return length-prefixed JSON.