packages/wasmtime/src/interp.nu — a small WebAssembly interpreter (pure NURL).
Executes wasm: i32/i64/f32/f64 const, locals, globals, the integer and float arithmetic/comparison/bitwise ops, all int↔float conversions, structured control flow (block / loop / if / else / br / br_if / return), drop / select, direct and indirect calls, and linear memory load/store. Each value occupies one 64-bit cell; i32 wraps + sign-extends to 32 bits, and floats are held as their IEEE-754 bit pattern (reinterpreted via std/floatbits for arithmetic). Imports (the WASI surface) are the remaining milestone — so this runs self-contained compute modules today.
Control flow uses an explicit control stack. Entering a block/if computes its matching end by a one-pass immediate-skipping scan; br to a loop re-enters at the loop start, to a block jumps past its end.
& m @ rint f x → fround-to-nearest-even (wasm f*.nearest) — libm rint honours the default mode.
: Arg { ( Vec u ) bytes }: Ctrl { i is_loop i start_pc i end_pc i height i arity }: WFd { i kind ( Vec u ) data i pos ( Vec u ) host ( Vec u ) name b writable b dirty }A WASI file descriptor. kind: 0 closed, 1 stdio, 2 preopened dir, 3 file. For a file, data holds the contents (read) or the bytes written so far, pos the read/write offset, host the on-disk path (for open/flush), and name (a dir) the guest-visible preopen name reported by fd_prestat_*.
: Interp: Interp {
s mod // *Module
( Vec i ) vs // value stack
( Vec u ) mem // linear memory (bytes)
i mem_pages // current size in 64 KiB pages
( Vec i ) globals // mutable global values
( Vec s ) argv // *( Vec u ) — WASI program arguments (argv[0] = program)
( Vec s ) fds // *WFd — file-descriptor table (0/1/2 stdio, 3 preopen, …)
b exited // set after proc_exit
i exit_code
b trap
( Vec u ) trapmsg
}
@ interp_new * Module m → *Interp@ interp_free * Interp it → v@ interp_push_arg * Interp it s str → vAppend a program argument (copied from a NUL-terminated host string).
@ interp_set_preopen * Interp it s host_path s guest_name → vGrant the module one preopened host directory, visible to it as guest_name (the path it resolves opens against). Installed as fd 3.
@ exec_func * Interp it i fidx → vpackages/wasmtime/src/module.nu — WebAssembly binary decoder (pure NURL).
Decodes a wasm32 module's structure: the magic/version header and the sections this runtime understands (type, function, table, memory, global, export, element, code, data). Imports and the custom/start sections are skipped. The byte cursor + LEB128 readers here are reused by the interpreter (interp.nu) to walk instruction streams.
: Wc { ( Vec u ) buf i pos i len }@ wc_new ( Vec u ) buf → *Wc@ wc_free * Wc c → vWc does not own buf (the module bytes outlive it); free only the struct.
@ wc_eof * Wc c → b@ wc_u8 * Wc c → i@ wc_peek * Wc c → i@ wc_uleb * Wc c → iUnsigned LEB128 → i (NURL i is 64-bit, covers u32/u64).
@ wc_sleb * Wc c → iSigned LEB128 → i (sign-extended).
@ wc_skip * Wc c i n → vSkip n bytes.
: FuncType { ( Vec i ) params ( Vec i ) results }: WFunc { i typeidx ( Vec i ) locals i code_start i code_end }A defined function: its type index, its declared (non-param) local valtypes expanded flat, and the [start,end) byte range of its instruction stream.
: WExport { ( Vec u ) name i kind i index }: DataSeg { i offset ( Vec u ) bytes }An active data segment: raw bytes to copy into linear memory at offset.
: WImport { ( Vec u ) field i typeidx }An imported function (the only import kind this runtime resolves): its field name selects the host (WASI) implementation; typeidx gives its signature.
: Module: Module {
( Vec s ) types // *FuncType
( Vec i ) functypes // type index per defined function
( Vec s ) funcs // *WFunc
( Vec s ) exports // *WExport
( Vec u ) code // the whole module byte image (functions index into it)
i has_mem
i mem_min // initial pages (64 KiB each)
i mem_max // 0 if unbounded
( Vec s ) datas // *DataSeg
( Vec i ) global_init // initial value per global
( Vec i ) global_mut // 1 if mutable
i has_table
( Vec i ) table // function indices (−1 = empty slot)
( Vec s ) imports // *WImport (imported functions, in index order)
i num_import_funcs // imported funcs occupy func indices 0..n-1
b ok
( Vec u ) err
}
@ module_free * Module m → v@ module_decode ( Vec u ) bytes → *ModuleDecode a whole module. On error, .ok is F and .err carries a message.
@ module_export_func * Module m s name → iFind an exported function index by name (-1 if absent).
packages/wasmtime/src/main.nu — wasmtime: a WebAssembly runtime in pure NURL.
wasmtime run --invoke <export> <module.wasm> [int args…]
Loads a wasm module, invokes an exported function with integer arguments, and prints the integer result. This is the foundation — the integer interpreter core (module.nu + interp.nu). Linear memory, floats, and the WASI surface (incl. --dir) build on top in later milestones.
@ usage → v@ run_invoke s export s path i first_arg i argc → i@ run_command s path i prog_start i argc s dir → iWASI command: run the module's _start with argv = [module, prog args…].
@ main → i