Source Blocks & Components
Every source block in a workbook is a potential WASM component. The OQL kernel
reads the block's language, its heading's :PROPERTIES: drawer, and the block's
own header args to build the component spec that goes into the build plan.
The component model
A source block paired with a heading that has :in: / :out: properties
constitutes a component: a named, typed unit of work with declared inputs and
outputs. The runtime compiles the block to a WASM module, wraps it in a WIT
interface matching the declared types, and wires it to other components via the
edge map in the build plan.
:in: and :out: properties
Declare input and output variable names on the heading:
** Compute result
:PROPERTIES:
:in: x y
:out: result
:END:
#+begin_src javascript
export function compute(x, y) {
return { result: x + y };
}
#+end_src
Multiple names are space-separated. The OQL kernel matches :in: names to
exported function parameters and :out: names to returned object keys. The
return value must be an object whose keys include every declared :out: name.
:deps: — component dependencies
:deps: on a heading declares that this component depends on another named block:
** Parse input
:PROPERTIES:
:out: parsed
:END:
#+begin_src javascript
export function parse_input() {
return { parsed: JSON.parse(inputRaw) };
}
#+end_src
** Process
:PROPERTIES:
:deps: parse-input
:in: parsed
:out: result
:END:
#+begin_src javascript
export function process(parsed) {
return { result: parsed.value * 2 };
}
#+end_src
:deps: adds edges to the build plan DAG: the output of parse-input feeds the
input of process. The runtime resolves the parsed value by running the
upstream component first.
:sig: — explicit type signature
By default, the OQL kernel infers component types from the :in: / :out:
property names. Use :sig: for explicit WIT-style signatures:
** Score items
:PROPERTIES:
:sig: score(items: list<string>) -> list<f64>
:END:
The :sig: value is a WIT function signature. Supported primitive types:
string, s32, s64, f32, f64, bool, list<T>, option<T>,
result<T,E>. When :sig: is present it overrides :in: / :out: inference.
Header args
Source block header args control export and execution behaviour. These are standard Org Babel headers:
| Header | Effect |
:exports code | Render the block as code only (default for most langs) |
:exports results | Render execution results only |
:exports both | Render both block and results |
:exports none | Compile but render nothing |
:eval no | Do not execute this block |
:noweb yes | Allow <<block-name>> references inside the block |
Example:
#+begin_src sh :exports code
echo "this shows in the rendered output"
#+end_src
Language support
| Language | Compiler path | Notes |
javascript | Javy → WASM | Subset of JS; no DOM, no Node built-ins |
rust | mrustc.wasm → clang.wasm | no_std by default inside sandbox |
c | clang.wasm | C99, standard library via WASI |
zig | Zig WASM target | Zig stdlib available |
sh | Exec on host | Not sandboxed; runs in workdir |
The Rust path uses mrustc.wasm (a Rust compiler compiled to WASM) to produce LLVM
IR, then clang.wasm to compile to wasm32-wasi. This runs entirely inside the
WASM sandbox — no native Rust toolchain needed at runtime.
Block naming
The component ID in the build plan is derived from the heading title: lowercased, spaces replaced with hyphens. The heading:
** Parse User Input
:PROPERTIES:
:out: parsed
:END:
...becomes component ID parse-user-input in the build plan. Use this ID in
:deps: references from other components.
Anonymous blocks
Source blocks without a parent heading that has :in:, :out:, or :deps:
are anonymous — they appear in the build plan with no wiring. They are compiled
if their language has a WASM backend, but are not connected to any edge. Useful
for utility code referenced via :noweb:.