Skip to main content

Module abi

Module abi 

Source
Expand description

The C ABI a JavaScript embedder calls, and the two allocation primitives that make it usable.

§Why there is no wasm-bindgen

This workspace has exactly one third-party dependency (toml, in cove-sema); the CLI parses its own arguments and writes its own JSON. A binding generator would be the largest dependency in the tree, and a probe established before any of this was written that it buys nothing here: five extern "C" functions and a length prefix are the whole of what crossing this boundary needs.

Five and not four because a debug run was added after the first four shipped. That it was one more extern "C" function taking two more integers, with nothing else about the boundary moved, is the strongest evidence available that the probe’s conclusion was right.

Six and not five for the same reason a second time: syntax highlighting was added, and it is cove_lex — one more extern "C" function taking the two integers every one of them takes, answering the same length-prefixed JSON. Three additions in a row that cost one function each is the evidence, and it is now hard to argue with.

Seven and not six because the disassembly pane wanted colouring too, and it is cove_lex_ir: the same two integers, the same length-prefixed JSON, the same tiling. Four in a row.

§The calling convention

Two directions, one shape each.

Into the module: the caller asks for n bytes with cove_alloc, writes UTF-8 into the module’s exported memory at the returned offset, and passes (offset, n). It owns those bytes and releases them with cove_free; nothing here takes them.

Out of the module: cove_compile, cove_run, cove_debug, cove_lex and cove_lex_ir each answer one offset into the same memory. The four bytes there are a little-endian u32 length, and the n bytes after them are UTF-8 JSON. The caller decodes them and releases the whole block with cove_free(offset, n + 4).

The length prefix is what removes the alternative — a second exported function answering “how long was the last answer?” — and with it the module-level state such a function would need. Two calls in flight at once would have raced over it. This has nothing to race over.

§The one import

cove.cove_now_millis() -> f64, described by cove_runtime’s wallclock module. It is the monotonic clock, and without it a deadline could not be enforced. A module instantiated without it does not load.

Functions§

cove_alloc
Reserves len bytes of the module’s memory and answers where they start.
cove_compile
Checks and lowers source, and answers the diagnostics and the disassembly as an answer block. See crate::compile_json.
cove_debug
Checks, lowers and runs source under a recording debugger, and answers what cove_run answers plus the recording. See crate::debug_json.
cove_free
Releases a block cove_alloc answered, or an answer block one of the entry points answered.
cove_lex
Lexes source and answers a colour for every part of it, as an answer block. See crate::lex_json.
cove_lex_ir
Colours the disassembly in text and answers a tiling of it, as an answer block. See crate::lex_ir_json.
cove_run
Checks, lowers and runs source, and answers what it printed, what it produced and how it ended. See crate::run_json.