Runners¶
Kiwi supports multiple execution modes via the IRunner interface. Each mode is designed for a specific workflow — from running scripts to debugging syntax to interactive development.
Execution Modes¶
| Runner | Purpose | Input | Example |
|---|---|---|---|
VMScriptRunner |
Run .kiwi files (default) |
File path | kiwi script.kiwi |
ScriptRunner |
Run via tree-walking interpreter | File path | kiwi --tree-walker script.kiwi |
CodeRunner |
Execute a code string inline | -e flag |
kiwi -e 'println "hi"' |
StdInRunner |
Run from piped stdin | stdin |
cat script.kiwi \| kiwi |
REPLRunner |
Interactive shell | Keyboard | kiwi or kiwi -i |
DebugRunner |
Step-debug a script (kdb) | File | kiwi --debug script.kiwi |
SyntaxChecker |
Check a file for syntax errors | File | kiwi --check script.kiwi |
ASTPrinter |
Print AST for debugging | File | kiwi --ast script.kiwi |
TokenPrinter |
Print tokens for debugging | File | kiwi --tokens script.kiwi |
How They Work¶
All runners follow the same core pipeline:
- Load Standard Library (once, unless debugging)
- Lex -> Parse -> Compile -> Execute (VM) or Lex -> Parse -> Interpret (tree-walker)
- Handle errors gracefully
- Pass CLI args to
Interpreter.CliArgs
VMScriptRunner – Run a File (Default)¶
Use Case: Production scripts, CLI tools, automation.
- Compiles the script (plus the
standard library) to bytecode - Executes in the bytecode VM
- Executes top-level code and
main()if defined
ScriptRunner – Tree-Walking Interpreter¶
Use Case: Compatibility, debugging, or when the VM is not desired.
- Loads the
standard libraryfirst - Then loads
hello.kiwi - Executes top-level code and
main()if defined via the tree-walking interpreter
CodeRunner – Execute Inline Code¶
Use Case: Quick one-liners, shell aliases, scripted invocations without a file.
- Accepts a string of Kiwi code as the argument
- Loads the standard library (use
-nsto skip) - Supports multi-line code via shell
$'...'quoting:
- Can be combined with key-value args:
StdInRunner – Run from Pipe¶
Use Case: Shell pipelines, filters, one-liners.
Selected automatically when no script is given and stdin is not a terminal (i.e. it is piped or redirected).
echo "println 'Hello from pipe'" | kiwi
# Hello from pipe
cat script.kiwi | kiwi -theme=dark
find . -name "*.kiwi" | xargs -I {} sh -c "echo '--- {} ---'; kiwi {}"
- Reads all input from
stdin - No file path needed
- 40 MB limit (configurable)
- Does not close stdin — safe in pipelines
REPLRunner – Interactive Mode¶
Use Case: Learning, debugging, rapid prototyping.
Selected automatically when no script is given and stdin is a terminal. Can also be forced explicitly.
kiwi # auto-selected when stdin is a terminal
kiwi -i # explicit short form
kiwi --interactive # explicit long form
kiwi -name=scotty # key-value args are available inside the session
Features¶
- Multi-line input with
\continuation - Immediate execution
.exitto quit- Full access to the standard library and CLI args
SyntaxChecker – Check for Errors¶
Use Case: Validate a script before running it; integrate with editors or CI.
Parses the script (including the standard library) and reports all syntax errors — not just the first one. The script is never executed.
- Exits
0and prints a confirmation message if no errors are found. - Exits
1and prints every error (with file, line, column, and source context) if any are found.
Sample output — clean file:
Sample output — file with errors:
[SyntaxError]: Unexpected token `*`.
File: script.kiwi:1:9
x = 1 + *
^
[SyntaxError]: Unexpected token `/`.
File: script.kiwi:2:9
y = 2 + /
^
ASTPrinter – Debug the Parser¶
Use Case: Understand how code is parsed.
Sample Output:
DebugRunner – Interactive Debugger (kdb)¶
Use Case: Step through code, inspect variables, set breakpoints.
Launches the kdb interactive debugger. Starts paused at the first statement.
kdb - Kiwi Debugger
Debugging: script.kiwi
Type 'h' for help, 's' to step, 'r' to run.
=> script.kiwi:3
1: fn greet(name)
2: println "Hello, ${name}!"
=> 3: greet("world")
(kdb)
Commands¶
| Command | Alias | Description |
|---|---|---|
run |
r |
Run to next breakpoint (or end) |
step |
s |
Step into next statement |
next |
n |
Step over (skip into function calls) |
finish |
f |
Step out of current function |
b <line> |
Set breakpoint at line in current file | |
b <file>:<line> |
Set breakpoint at file:line | |
d <n> |
Delete breakpoint #n | |
info b |
List all breakpoints | |
p <expr> |
Evaluate and print an expression | |
locals |
l |
Show local variables in current scope |
backtrace |
bt |
Show call stack |
list [line] |
Show source around current or given line | |
help |
h |
Show command help |
quit |
q |
Exit debugger |
Standard library files are automatically skipped — the debugger only pauses in user code.
TokenPrinter – Debug the Lexer¶
Use Case: Fix syntax errors, learn tokenization.
Sample Output:
Tokenizing: hello.kiwi
Token # Type Name Text
------- ---- ---- ----
1 Keyword KW_PrintLn println
2 String Default Hello, World!
3 Eof Default
Standard Library¶
- Loaded automatically in
VMScriptRunner,ScriptRunner,CodeRunner,StdInRunner,REPLRunner, andSyntaxChecker - Skipped in
--astand--tokens - Configured in
kiwi-settings.json - Last file wins (for overrides)
Error Handling¶
All runners catch:
- KiwiError → Pretty-print error type, message, and file/line to stderr
- Exception → Print message and stack trace to stderr
Multiple syntax errors¶
When a script contains syntax errors, the parser reports all of them rather than stopping at the first. After each error the parser recovers and continues from the next statement, so every problem in the file is surfaced in one pass. This applies to all runners — ScriptRunner, SyntaxChecker, etc.
Crash dump logging is opt-in via the -cd/--crash-dump flag (or by setting "crashdump_path" in kiwi-settings.json). When enabled, errors are also appended to the configured log file.
Quick Testing¶
# REPL (auto, stdin is a terminal)
kiwi
# REPL with args
kiwi -name=scotty
# REPL (explicit)
kiwi -i
# Run a script (VM, default)
kiwi test.kiwi
# Run via tree-walking interpreter
kiwi --tree-walker test.kiwi
# Execute inline code
kiwi -e 'println("hello")'
# Pipe input
echo "println 100" | kiwi
# Step debugger
kiwi -d test.kiwi
# Check for syntax errors
kiwi -c test.kiwi
# Debug parser
kiwi -a test.kiwi
# Debug lexer
kiwi -t test.kiwi