60 lines
2.5 KiB
Markdown
60 lines
2.5 KiB
Markdown
# 🪸 ReefVM
|
|
|
|
It's where Shrimp live.
|
|
|
|
## Quickstart
|
|
|
|
bun install
|
|
bun test
|
|
|
|
## Use it
|
|
|
|
Execute text bytecode:
|
|
|
|
./bin/reef examples/loop.reef
|
|
|
|
Validate bytecode:
|
|
|
|
./bin/validate examples/loop.reef
|
|
|
|
Run the simple debugger to see what the instructions are doing:
|
|
|
|
./bin/debug examples/loop.reef
|
|
./bin/debug -h examples/loop.reef
|
|
|
|
Interactive REPL for exploring instructions:
|
|
|
|
./bin/repl
|
|
|
|
Type opcodes interactively and see the stack and variables update in real-time.
|
|
|
|
Commands: `clear`, `reset`, `exit`.
|
|
|
|
## Features
|
|
|
|
- Stack operations (PUSH, POP, DUP)
|
|
- Arithmetic operations (ADD, SUB, MUL, DIV, MOD)
|
|
- Comparison operations (EQ, NEQ, LT, GT, LTE, GTE)
|
|
- Logical operations (NOT, AND/OR patterns with short-circuiting)
|
|
- Variable operations (LOAD, STORE) with **emoji and Unicode support** (💎 = 5)
|
|
- Control flow with **relative jumps** (JUMP, JUMP_IF_FALSE, JUMP_IF_TRUE, BREAK, CONTINUE)
|
|
- Array operations (MAKE_ARRAY, ARRAY_GET, ARRAY_SET, ARRAY_PUSH, ARRAY_LEN)
|
|
- Dictionary operations (MAKE_DICT, DICT_GET, DICT_SET, DICT_HAS)
|
|
- Function operations (MAKE_FUNCTION, CALL, TAIL_CALL, RETURN) with parameter binding
|
|
- Variadic functions with positional rest parameters (`...rest`)
|
|
- Named arguments (named) that collect unmatched named args into a dict (`@named`)
|
|
- Mixed positional and named arguments with proper priority binding
|
|
- Tail call optimization with unbounded recursion (10,000+ iterations without stack overflow)
|
|
- Exception handling (PUSH_TRY, PUSH_FINALLY, POP_TRY, THROW) with nested try/finally blocks and call stack unwinding
|
|
- Native function interop with auto-wrapping for native TypeScript types
|
|
- Native functions stored in scope, called via LOAD + CALL
|
|
- Pass functions directly to `run(bytecode, { fnName: fn })` or `new VM(bytecode, { fnName: fn })`
|
|
|
|
## Design Decisions
|
|
|
|
- Relative jumps: All JUMP instructions use PC-relative offsets instead of absolute addresses, making bytecode position-independent
|
|
- Truthiness: Only `null` and `false` are falsy (unlike JavaScript where `0`, `""`, etc. are also falsy)
|
|
- Short-circuiting via compiler: No AND/OR opcodes—compilers use JUMP patterns for proper short-circuit evaluation
|
|
- Variadic parameters: Functions can collect remaining positional arguments into an array using `...rest` syntax
|
|
- Named parameters: Functions can collect unmatched named arguments into a dict using `@named` syntax
|
|
- Argument binding priority: Named args bind to regular params first, with unmatched ones going to `@named` |