OJaml / docsProject documentation

Reference

Implementation Correspondence

Look up syntax, contracts, layouts, algorithms, and exact behavior.

The paper maps directly onto the repository. The language core is not distributed across hidden build steps: each stage has a focused TypeScript module, and the public editor route composes those modules rather than replacing them. A reconstruction should preserve this correspondence so paper claims can be checked against concrete files.

src/lexer.ts        tokens, nested comments, string escapes
src/parser.ts       recursive-descent parser and source spans
src/ast.ts          Program, Declaration, Expr, Pattern types
src/check.ts        type graph, unification, stdlib schemes, hover tokens
src/compiler.ts     WAT emission, heap layouts, closures, stdlib runtime
src/runtime.ts      WABT conversion, imports, execution result
src/monacoOJaml.ts  diagnostics, completions, hovers, signature help
tests/*.test.ts     positive runtime tests and negative checker tests
Source map. The implementation is stage-shaped, so every concept in the paper has a concrete module.

The most important cross-file invariant is name agreement. Standard-library names are parsed as identifiers, typed by check.ts, assigned arities and return shapes by compiler.ts, emitted as WebAssembly-safe names by safe(name), and surfaced to Monaco through the shared signature list. If one stage adds a builtin without the others, the language becomes inconsistent.

name∈Stdlib⁡check⇒name∈Arities⁡emit∧safe(name)∈WAT⁡name \in \operatorname{Stdlib}_{check} \Rightarrow name \in \operatorname{Arities}_{emit} \land safe(name) \in \operatorname{WAT}
Builtin consistency. A builtin is complete only when the checker, emitter, and generated WebAssembly agree on its identity and arity.

The second cross-file invariant is representation agreement. The checker distinguishes int, float, bool, string, unit, tuples, records, arrays, lists, sets, maps, and functions. The emitter erases those distinctions to i32 only after type checking. Runtime helpers then interpret the i32 according to the static type that selected the helper.

  • Extending modules further requires file imports, functors, and richer namespace export rules beyond the current compile-time module surface.
  • Adding richer collection exhaustiveness requires rules that describe exact-length arrays, stored-order sets, and stored-order maps without pretending those forms cover every possible value.
  • Adding garbage collection requires replacing the monotonic allocator without changing the checker-facing value model.