Skip to main content

Crate elly_wasm

Crate elly_wasm 

Source
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 — reserve len bytes 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-endian u32 byte length followed by that many bytes of UTF-8 JSON (see below).
  • elly_free(ptr, len) — release a block obtained from elly_alloc.

The module imports its system surface from elly_host (the Sys shim):

  • elly_host_write(stream, ptr, len) — IO.print/write (stream 1) and IO.error (stream 2).
  • elly_host_read(ptr, len, out_len) -> ptr — the source of the module file at the path (ptr, len), or 0 if there is none. The host allocates the block with elly_alloc, writes its length as a u32 at out_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 IO in scope;
  • a module declaring __main, run the way the elly binary runs a program, with its imports resolved below /lib through elly_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 ran IO.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.raise or a host failure like .div_by_zero); the AST is still shown.
  • {"module":true,…} — the same value / exit / error shapes 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 an Exit payload.

Structs§

Session
One realm and the IO capability built over it. elly_run keeps 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 stage there 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 len bytes of linear memory and hand ownership to the caller.
elly_free⚠
Release a block previously returned by elly_alloc (same len).
elly_run⚠
Run len UTF-8 bytes at ptr through the pipeline; return length-prefixed JSON.