Commit Graph

21 Commits

Author SHA1 Message Date
Oleksandr Kozachuk 4f96f8860a release: 0.2.8
CI / check (push) Has been cancelled
Ships the self-guard expansion, and corrects what the benchmark tables claim.
Measured with wafer, gforth and SwiftForth all native on x86-64 -- the macOS
sf64 build runs under Rosetta 2 and flatters us -- Fibonacci is 1.16x rather
than 0.83x, so sf64 still wins it and wafer takes the other four. README and
OPTIMIZATIONS now carry both tables.
2026-08-10 12:48:33 +02:00
Oleksandr Kozachuk e963e636d3 perf(core): test a recursive word's base case at the call site
CI / check (push) Has been cancelled
A recursive Forth word almost always opens with a guard that returns early,
so every leaf of the recursion costs a call whose whole body is that test.
`Call(self)` now compiles as `<guard> IF <what the guard returns> ELSE
Call(self) THEN`, which is what the callee would have done on entry anyway.
Half of fib's nodes are leaves: Fibonacci(25) 356 -> 237 us, 1.24x sf64 ->
0.83x, so all five benchmarks now beat it.

The guard runs twice along the recursive path, hence the bounds: at most six
effect-free operations, at most four call sites, never a tail call. WS-018.
2026-08-09 18:27:25 +02:00
Oleksandr Kozachuk 3bb613ece0 release: 0.2.7
Version bump plus a doc sweep: the benchmark tables in README and
docs/OPTIMIZATIONS.md were still from before the typed calling convention,
OPTIMIZATIONS listed BEGIN loop promotion as not started, and the
subroutine-threading section of docs/WAFER.md described the memory ABI as
the only one.
2026-08-09 17:36:52 +02:00
Oleksandr Kozachuk b8dcc021a2 perf(core): promote per region, promote BEGIN loops, keep loops off the memory stack
Promotion was all-or-nothing per word, so one `.` or one host call put the
whole body -- hot loops included -- on the memory data stack, where a
loop-carried add costs 2.2 ns/iteration instead of 0.31. The stack simulator
now runs over each promotable stretch of a word; BEGIN/UNTIL, BEGIN/AGAIN and
BEGIN/WHILE/REPEAT join DO/LOOP as promotable when the construct is provably
stack-neutral; and the inliner no longer moves a loop-bearing callee into a
caller that can never be promoted.

Fixes a bug the BEGIN work uncovered, present since promotion was introduced
and shipped in 0.2.6: the loop fixup and the IF join copied locals one slot at
a time in index order, so a body that permutes the stack lost a value --
`: C 3 4 2 0 DO SWAP LOOP . . ;` printed `4 4` where gforth prints `4 3`.

Four of five benchmarks now beat sf64: Factorial 0.29x, Collatz 0.30x,
NestedLoops 0.27x, GCD 0.67x. Only Fibonacci is behind, at 1.24x. Also scale
GCD, Factorial and NestedLoops, which ran in 14-51 us where scatter and fixed
costs dominated -- that is what exposed GCD as a loss and pointed at BEGIN.
WS-014, WS-015, WS-016, WS-019.
2026-08-09 17:25:21 +02:00
Oleksandr Kozachuk fc34bd9b24 perf(core): typed calling convention for words with a known stack effect
Such a word now compiles to a fast entry (i32 x p) -> (i32 x q) carrying
its stack items as WASM values, plus the usual ( -- ) wrapper that keeps
the table slot, so EXECUTE / interpreter / host words / CATCH see the
unchanged memory ABI. Fib(25) 1035 -> 366 us, 4.3x slower than sf64 ->
1.2x; the default guards-on config 1740 -> 361 us. WS-006.
2026-08-09 09:20:10 +02:00
Oleksandr Kozachuk 9b1cc0cace feat(core): INCLUDE, error overhaul, sf64 lane, WORDS ALL, .RS
WS-012 -- INCLUDE/INCLUDED:
- Injected source loader (core stays IO-free: CLI installs a
  filesystem reader, web leaves it unset -> defined error). Recursive
  include_file feeds files line-by-line through evaluate, so compile
  state and SEE capture span lines for free. Cycle detection, depth
  cap 16, paths relative to the including file, SOURCE-ID per nesting
  level, parent input restored on success/error/BYE.
- CLI file mode now runs through the include machinery: `wafer x.fth`
  gets file:line error context and a base dir for nested INCLUDEs.
- Unlocks the REMEMBER+INCLUDE reload loop.

WS-008 -- error reporting remainder:
- Errors inside included files carry `file.fth:12:` context
  (anyhow context chain; CLI prints {e:#}).
- describe_uncaught now returns typed WaferError::UncaughtThrow
  { code, message } -- display text unchanged, THROW code reachable
  via downcast for CLI/web consumers.
- compile_word emits a WASM name section; wasmtime trap backtraces
  name the faulting word and runtime_native prefixes "in <WORD>:".
  Batch/consolidated modules stay unnamed (no name plumbing there;
  boot primitives rarely trap).

WS-003 -- SwiftForth correctness lane:
- compare_all_programs_sf64 runs the program corpus with sf64 as
  oracle; whitespace-token comparison (sf64 prints numbers
  space-prefixed and echoes piped lines). 34/35 parity; dot-quote
  skipped (interpret-mode ." is a SwiftForth no-op). #[ignore]d like
  the gforth lane; `just compare-correctness` runs both.

WS-011 leftovers:
- WORDS ALL: grouped full view -- one section per wordlist (search
  order first), then internal words, each with counts. Backed by
  Dictionary::visible_entries (name, wid, internal); visible_words
  now derives from it.
- .RS / RDEPTH: return-stack introspection in boot.fth over a new
  RP@ primitive (IrOp::RpFetch); BEGIN/WHILE walk so the walk never
  touches the stack it prints. SPACES clamped per 6.1.2230.

549 unit + 11 compliance + 9(+2) comparison + 5 crypto + 1 bench
green; fmt/clippy clean; --no-default-features and wasm32 web checks
pass.
2026-08-06 12:44:33 +02:00
Oleksandr Kozachuk dc6e0d45e1 feat(core): SEE, SEE-IR, HELP introspection trio (WS-010)
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.
2026-08-06 12:44:32 +02:00
ok2 397ab7000c Update README for runtime abstraction and browser REPL
Add browser REPL and runtime abstraction to highlights, update
architecture diagram with Runtime trait / NativeRuntime / WebRuntime,
add Web REPL build instructions, add missing Core Plus compliance row,
remove browser target from roadmap (done).
2026-04-13 10:52:11 +02:00
ok2 13a16ae2a4 Update docs: performance results, new optimizations, test counts
- README: add performance section (beats gforth 2-10x), update test
  commands, note self-recursive direct calls and loop promotion
- CLAUDE.md: update test counts (427 unit + comparison tests)
- OPTIMIZATIONS.md: stack-to-local Phase 1→Phase 2 (loops + IF),
  DO/LOOP locals done, J as IR done, add section 14 (self-recursive
  direct call), add current performance table vs gforth
- WAFER.md: document self-recursive call optimization, CONSOLIDATE,
  update test commands and line counts
- FORTH.md: expanded space history, add FORTH-IN-SPACE.md reference
- FORTH-IN-SPACE.md: new document with verified spacecraft history
2026-04-09 20:00:55 +02:00
ok2 f3fabc30ad Fix dprint markdown formatting in README 2026-04-02 14:00:19 +02:00
ok2 1c0df608c3 Remove unused stub files: forth/, words/, compiler.rs, primitives.rs, types.rs
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
2026-04-02 13:52:45 +02:00
ok2 8c53afa28a Update all docs to reflect current state
README: 392 tests, 200+ words, 12 word sets, optimization pipeline described
CLAUDE.md: 200+ words, 12 word sets, 392 tests, added optimizer/config/consolidate to key files
OPTIMIZATIONS.md: update all 14 section statuses (12 done, 2 not started)
WAFER.md: correct line counts, add optimizer/config/consolidate/types to project layout, add FSP global
2026-04-02 12:47:50 +02:00
ok2 8c38487390 Update README: 12 word sets at 100%, 200+ words, floating-point complete 2026-04-01 20:40:50 +02:00
ok2 37c583f8d7 Add working compliance test harness, 11 word sets at 100%
Replace placeholder compliance tests with real harness that boots WAFER,
loads Gerry Jackson's test suite, and asserts 0 errors per word set.

Passing word sets (11/13):
  Core, Core Plus, Core Ext, Exception, Double-Number, String,
  Search-Order, Memory-Allocation, Programming-Tools, Facility, Locals

Not yet: File-Access (needs WASI), Floating-Point, Extended-Character
272 total tests (261 unit + 11 compliance)
2026-03-31 15:25:02 +02:00
ok2 dd389c6a3d Implement Double-Number and String word sets, fix memory panics
Double-Number (19 words): D+ D- DNEGATE DABS D2* D2/ D0= D0< D= D< DU<
  DMAX DMIN D>S M+ M*/ D. D.R 2ROT 2CONSTANT 2VARIABLE 2VALUE 2LITERAL
  Double-number literal parsing (tokens ending with '.')
String (5 words): COMPARE SEARCH /STRING BLANK -TRAILING SLITERAL
Fix all memory access panics with bounds checking throughout host functions.

8 word sets at 100%: Core, Core Ext, Exception, Double, String,
  Search-Order, Memory-Allocation, Programming-Tools
2026-03-31 14:43:30 +02:00
ok2 7507b1f164 Achieve 100% Core Extensions compliance, 261 tests
Implement 25+ Core Extension words:
- VALUE/TO, DEFER/IS/ACTION-OF, :NONAME
- CASE/OF/ENDOF/ENDCASE, ?DO, AGAIN
- PARSE, PARSE-NAME, S\", C", HOLDS, BUFFER:
- 2>R, 2R>, 2R@, U>, .R, U.R, PAD, ERASE, UNUSED
- REFILL, SOURCE-ID, MARKER (stub)

Fix panic on invalid memory access (bounds check in FIND).
Rewrite FIND/WORD host functions for inline operation.
Add BeginAgain IR variant and codegen.

Three word sets at 100%: Core, Core Extensions, Exception.
2026-03-30 22:19:49 +02:00
ok2 b52b4a79ce Achieve 100% Core compliance, implement CATCH/THROW
Core word set: 0 errors on Gerry Jackson's forth2012-test-suite/core.fr
- Fix POSTPONE for non-immediate words via COMPILE, mechanism
- Fix double-DOES> (WEIRD: pattern) with does-body scanning and
  runtime patching via _DOES_PATCH_
- Implement CATCH/THROW exception handling using wasmtime trap
  mechanism with stack pointer save/restore
- 232 tests passing
2026-03-30 21:26:21 +02:00
ok2 8aaffad6b5 Reach 97% Core compliance: 58 errors down to 3
- Fix HERE corruption: sync user_here before writing to shared cell
- Fix DOES> without CREATE: patch most-recent word, not read new name
- Implement >BODY via word_pfa_map tracking parameter field addresses
- Nested BEGIN...WHILE...WHILE...REPEAT...ELSE...THEN support
- DEPTH overflow protection
- Forth 2012 core.fr: 3 errors remaining (POSTPONE edge case,
  double-DOES>, NOP meta-programming)
2026-03-30 21:02:00 +02:00
ok2 d9cd6f2b10 Add DOES>, EVALUATE, double-cell arithmetic, and 20+ more Core words
- DOES> with split-compilation for defining words (CREATE , DOES> @ pattern)
- EVALUATE for string interpretation
- Double-cell: M* UM* UM/MOD FM/MOD SM/REM S>D */ */MOD
- Parsing: WORD FIND COUNT >NUMBER >IN STATE
- Memory: CMOVE CMOVE>
- Compile-time: ABORT" S" (compile mode)
- 219 tests passing, ~90% Core word set coverage
- Update docs to reflect current implementation
2026-03-29 23:40:37 +02:00
ok2 ca07d358fb Update documentation to reflect current implementation state
README now documents all 70+ implemented words, working examples,
architecture overview, and accurate compliance status.
CLAUDE.md updated with actual file descriptions, patterns for adding
new words, and current test count.
2026-03-29 23:14:54 +02:00
ok2 7d9937d0d8 Initial commit: WAFER (WebAssembly Forth Engine in Rust)
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.
2026-03-29 22:30:18 +02:00