# vuurraaf/v A complete toolchain for **VuurRaaf**, written in V from scratch: a compiler, an assembler, a linker, and a stack-based runtime. Everything — including the object file format and the virtual machine — lives in this repository. ``` .vr --compiler--> .vobj --linker--> .vbin --vm--> output .vasm --assembler--> .vobj ``` ## Build Requires [V](https://vlang.io) (`v` in your PATH). ```bash v -o bin/vr . # build the toolchain ./bin/vr up # or rebuild from inside the toolchain ./bin/vr symlink # optionally symlink bin/vr into your PATH ``` > Note: build with `v .` from the project root. Building via an explicit file > or path argument makes V pick tcc without the Boehm GC, a combination that > miscompiles this codebase (`vr up` already does the right thing). ## Usage ``` vr compile [-o out.vobj] source -> object vr assemble [-o out.vobj] assembly -> object vr link [more.vobj ...] [-o out] objects -> executable (.vbin) vr run compile+link+run, or run a binary vr debug interactive debugger (breakpoints, step, locals) vr profile run and report per-function instruction counts vr fuzz [--seed N] [--iters N] fuzz the compiler and VM for crashes/hangs vr test run every test_* function vr bench [iterations] benchmark main() vr make [target] [args...] run build.vrmm (target = main) vr make -f [target] [args...] run another build module vr build [target] [args...] alias for make vr clean remove .vobj/.vbin artifacts vr up rebuild bin/vr vr symlink link bin/vr into your PATH vr config [set ] toolchain config (outdir, verbose) vr repl interactive session vr lsp language server (JSON-RPC over stdio) vr fmt [-w] format source (keeps comments) vr init [name] scaffold a project (vr.mod + main.vr) vr get fetch a package into vendor/ vr install install dependencies from vr.mod vr list show the project manifest vr info | loader | alloc | version | help ``` ```bash ./bin/vr repl # try expressions and functions interactively ./bin/vr fmt -w f.vr # normalize a file's indentation/spacing in place ./bin/vr init myproj # start a project; vr get owner/repo fetches packages ./bin/vr run -w f.vr # watch f.vr and rerun on every save ./bin/vr test examples # run every test_* fn in every .vr file under examples/ ./bin/vr lsp # language server for editors (diagnostics, go-to-def) ./bin/vr run --profile f.vr # hot-function report (instructions + calls) ``` ### Debugging `vr debug` is an interactive debugger. Run to the first breakpoint (or stop at entry), then inspect state: ``` vr debug f.vr --break 12 == stopped at main (line 12, ip 105) — help: h (vr-dbg) l # list locals with values (vr-dbg) p x # print one local (vr-dbg) bt # backtrace (call chain) (vr-dbg) n # next: run to the next line (skips calls) (vr-dbg) s # step: one instruction (vr-dbg) f # finish: run until the current function returns (vr-dbg) b 20 # set another breakpoint (vr-dbg) c # continue ``` Breakpoints stop at the *start* of a source line, so locals hold the values from before that line executes. `vr debug --trace f.vr` keeps the old instruction-by-instruction trace. ### Fuzzing `vr fuzz` generates random programs, compiles them, and runs each one twice with an instruction budget — every case in its own subprocess so a crash in the compiler or VM is isolated and reported instead of killing the run: ``` vr fuzz --seed 42 --iters 500 --save-dir fuzz-repros fuzz: no bugs found ``` Findings (crashes, hangs via `--max-ops`, nondeterminism) are saved as .vr repros; a nonzero exit reports bugs for CI. ### Profiling `vr profile f.vr` (or `vr run --profile f.vr`) counts instructions and calls per function and prints the hot-function table: ``` function calls instr % fib 25 271 96.8% main 0 9 3.2% total 280 ``` Quick start: ```bash ./bin/vr run examples/hello.vr # run a program ./bin/vr test examples/tests.vr # run the tests (one fails on purpose) ./bin/vr debug examples/hello.vr # interactive debugger (breakpoints, step, locals) # the assembler path ./bin/vr assemble examples/math.vasm -o math.vobj ./bin/vr link math.vobj -o math.vbin ./bin/vr run math.vbin # multi-file programs (functions in one file may call functions in another) ./bin/vr compile examples/lib.vr -o lib.vobj ./bin/vr compile examples/use_lib.vr -o use_lib.vobj ./bin/vr link lib.vobj use_lib.vobj -o use_lib.vbin ./bin/vr run use_lib.vbin ``` ## Build modules (.vrmm) A **VuurRaaf Make Module** (`.vrmm`) is build instructions for the toolchain, written in VuurRaaf itself — the same idea as V's `.vsh` scripts. The toolchain compiles the module and runs one of its functions (a *target*) with the `build_*` builtins available, so the script can drive every stage of the pipeline: compile, assemble, link, run, test, bench, clean, and shell out to the host. ``` # build.vrmm fn main() { build_compile("main.vr", "main.vobj") build_link(["main.vobj"], "main.vbin") } fn clean() { build_clean() } ``` ```bash vr make # runs main() from build.vrmm vr make clean # runs the clean() target vr make deploy --prod # runs deploy() with args() == ["--prod"] vr make -f x.vrmm t # run target t from another module ``` A target that returns a nonzero integer, calls `exit(n)` with `n > 0`, or `throw`s fails the build. Paths are relative to the working directory; `build_root()` returns the module's own directory for absolute paths. ### Running build modules as scripts A `.vrmm` (or `.vr`) file may start with a shebang line so it can be executed directly like any script — the toolchain skips the shebang when compiling, so error line numbers stay aligned with the file: ``` #!/usr/bin/env vr fn main() { build_compile("main.vr", "main.vobj") build_link(["main.vobj"], "main.vbin") } ``` ```bash chmod +x build.vrmm ./build.vrmm # equivalent to: vr make ./build.vrmm clean # run the clean() target ./build.vrmm deploy --prod ``` The kernel invokes `vr