Implements plans/01-see-introspection.md, all phases.
- see.rs: feature-free IR pretty-printer (format_ir/format_ir_with),
exhaustive over IrOp -- a new variant fails the build, not the output.
- SEE-IR <name>: post-optimization IR view with resolved callee names,
immediate/does> annotations; host-word and interpreter-token stubs.
- SEE <name>: verbatim source capture for colon words (multi-line,
comments preserved, EVALUATE-nesting safe, error-path wiped, MARKER/
REMEMBER/EMPTY roll word sources back too). Data definers (VARIABLE/
CONSTANT/CREATE/BUFFER:/2*/F*/SYNONYM) record synthesized one-liners
at definition time; VALUE/2VALUE/FVALUE/DEFER synthesize at SEE time
so current values and IS targets show. Fallback chain ends at IR dump
or host-word stub -- SEE never dead-ends on a defined word.
- HELP [<name>]: wordhelp.rs doc table with stack effect + one-line
description for EVERY word in a fresh VM (300+ dictionary words plus
all outer-interpreter tokens); a coverage test fails the build if a
word is ever added undocumented. User words echo their leading
( ... -- ... ) comment. SEE/SEE-IR prepend the HELP line as a
\ comment. Bare HELP prints usage.
- boot.fth colon definitions get real sources for free (they flow
through evaluate); INTERPRETER_TOKENS gained the missing ?DO.
524 unit + 11 compliance + 9 comparison + 5 crypto + 1 bench green;
fmt/clippy clean; core still builds --no-default-features; web
wasm-pack build unchanged.
Introduces a `crypto` feature (on by default) that wires the RustCrypto
sha1/sha2 crates into a small `HashAlgo` registry. `register_primitives`
iterates `crypto::ALGOS` and installs one Forth host word per algorithm,
each with the stack effect
( c-addr u -- c-addr2 u2 )
reading `u` bytes from `c-addr` and writing the digest into a shared
`HASH_SCRATCH` region in linear memory (carved out between the float
stack and the dictionary).
Adding a new hash is a one-line entry in `ALGOS`. `register_host_primitive`
is now `pub` so downstream crates can extend the VM with their own I/O
host words without forking WAFER — kelvar (a deterministic password
manager on WAFER) is the first consumer.
- 4 unit tests (lib-level sha1/256/512 + registry sanity)
- 5 integration tests (in-VM `SHA1`/`SHA256`/`SHA512` against RFC-3174,
FIPS-180, and the first-round S/KEY seed used by `hel`)
- All 437 existing lib tests still pass; `wafer-web` still builds for
`wasm32-unknown-unknown` with the feature enabled
Decouple ForthVM from wasmtime via a Runtime trait so the same outer
interpreter, compiler, and 200+ word definitions work on both native
(wasmtime) and browser (js-sys WebAssembly API) backends.
Runtime trait (runtime.rs):
- HostAccess trait for memory/global ops inside host function closures
- HostFn type: Box<dyn Fn(&mut dyn HostAccess) -> Result<()>>
- Runtime trait: memory, globals, table, instantiate, call, register
NativeRuntime (runtime_native.rs):
- Wraps wasmtime Engine/Store/Memory/Table/Global/Func
- CallerHostAccess bridges HostAccess to wasmtime Caller API
- Feature-gated behind "native" (default)
outer.rs refactor:
- ForthVM<R: Runtime> — generic over execution backend
- All 87 host functions converted from Func::new closures to HostFn
- All memory access via rt.mem_read/write_*, global access via rt.get/set_*
- Zero logic changes — pure API conversion
wafer-core feature gates:
- default = ["native"] includes wasmtime + all native modules
- Without "native": pure Rust only (outer, codegen, optimizer, dictionary)
Browser REPL (crates/web):
- WebRuntime: js-sys WebAssembly.Memory/Table/Global/Module/Instance
- WaferRepl: wasm-bindgen entry point (evaluate, data_stack, reset)
- WebAssembly.Function with Safari fallback (wrapper module)
- Frontend: dark terminal UI, word panel, init code editor, history
- Build: wasm-pack build --target web
All 452 tests pass (431 unit + 1 benchmark + 9 comparison + 11 compliance).
Add `wafer build` to compile Forth source files to standalone .wasm modules,
and `wafer run` to execute them. The same .wasm file works with both the
wafer runtime (via wasmtime) and in browsers (via generated JS loader).
New CLI subcommands:
- `wafer build file.fth -o file.wasm` — compile to standalone WASM
- `wafer build file.fth -o file.wasm --js` — also generate JS/HTML loader
- `wafer build file.fth --entry WORD` — custom entry point
- `wafer run file.wasm` — execute pre-compiled module
Entry point resolution: --entry flag > MAIN word > recorded top-level execution.
Memory snapshot embedded as WASM data section preserves VARIABLE/CONSTANT state.
Metadata in custom "wafer" section enables the runner to provide host functions.
New modules: export.rs (orchestration), runner.rs (wasmtime host), js_loader.rs
(browser support). Refactored codegen.rs to share logic between consolidation
and export via compile_multi_word_module(). Added ir_bodies tracking for
VARIABLE, CONSTANT, CREATE, VALUE, DEFER, BUFFER:, MARKER, 2CONSTANT,
2VARIABLE, 2VALUE, FVARIABLE defining words.
Removed dead code: dot_func field, unused wafer-web stub crate, wasmtime-wasi
dependency from CLI, orphaned --consolidate/--output CLI flags.
425 tests pass (414 original + 11 new including 7 round-trip integration tests).
All were planning artifacts never imported or loaded:
- forth/ (4 .fth files): commented-out TODO stubs, never loaded at startup
- crates/core/src/words/mod.rs: empty module with commented-out submodules
- compiler.rs: placeholder, all compiler logic lives in outer.rs
- primitives.rs: placeholder, all primitives registered in outer.rs
- types.rs: StackType/StackEffect defined but never imported anywhere
Optimizing Forth 2012 compiler targeting WebAssembly with IR-based
compilation pipeline, multi-typed stack inference, subroutine threading,
and JIT/consolidation modes. Rust kernel with ~35 primitives and Forth
standard library for core/core-ext word sets.