Strada REPL & Scripting
Interactive shell and script execution via strada-jit — real native compilation (tcc or gcc + dlopen). Supports the full Strada language including closures, try/catch, OOP, const, and enum. tcc is auto-detected for snappy per-line latency; gcc is the fallback and the default for --script.
Quick Start
# Interactive REPL (auto-detects tcc when installed; falls back to gcc)
strada --repl
# Force a specific backend
strada --repl --compiler=gcc
strada --repl --compiler=tcc
# Run a script file (whole-file mode, gcc by default)
strada --script program.strada
# Same, but use tcc for the script compile (faster for small scripts)
strada --script program.strada --compiler=tcc
# Fall back to REPL-style line-by-line evaluation for a script
strada --script program.strada --chunked
--script works: by default it's whole-file mode — the entire file is handed to stradac once and the resulting binary is exec'd. Much faster than feeding the file line-by-line through the REPL eval path (each line otherwise pays a full gcc invocation). --chunked brings back the old line-by-line behaviour for free-form scripts without a main().
interpreter/strada-interp for embedding and experiments. It's no longer built by default — run make interpreter to opt in. The REPL and scripting flow above does not depend on it.
Interactive REPL
The REPL supports readline with line editing, history, and arrow keys. Each balanced chunk you enter is compiled to a small .so via tcc (or gcc) and dlopen'd — so the REPL runs real, fully-typed Strada with closures, try/catch, OOP, the lot.
$ strada --repl
Strada JIT v0.3 (using tcc)
Type .help for help, .quit to exit.
strada> my int $x = 42;
strada> $x * 2
84
strada> my array @nums = (1, 2, 3);
strada> push(@nums, 4);
strada> say(join(", ", @nums))
1, 2, 3, 4
Multi-line Input
The REPL automatically detects incomplete input (unbalanced braces, parentheses, or brackets) and prompts for continuation:
strada> func greet(str $name) void {
... say("Hello, " . $name . "!");
... }
strada> greet("World")
Hello, World!
REPL Commands
| Command | Description |
|---|---|
.help |
Show help message |
.vars |
List variables in scope with current values |
.funcs |
List defined functions with parameter counts |
.load FILE |
Load and execute code from a file (registers functions, skips main) |
.clear |
Reset all state (variables, functions, enums) |
.quit |
Exit the REPL |
OOP in the REPL
Packages, inheritance, and method calls all work interactively:
strada> package Dog;
strada> has ro str $name (required);
strada> func bark(scalar $self) void { say($self->name() . " says woof!"); }
strada> my scalar $d = Dog::new("name", "Rex");
strada> $d->bark()
Rex says woof!
Script Execution
Run Strada programs without writing a separate build step. strada --script compiles the whole file once with gcc and exec's the resulting binary — same level of optimisation as a regular strada build, but you don't have to manage the executable:
# Compile + run a script (whole-file mode; gcc by default)
strada --script program.strada
# With library search paths
strada --script -L lib program.strada
# Pick a different C compiler
strada --script program.strada --compiler=tcc
# Line-by-line REPL semantics for free-form scripts without a main()
strada --script program.strada --chunked
Shebang Scripts
Make a Strada source file directly executable:
#!/usr/bin/env strada
# --script is implied when the file is given as the first arg
func main() int {
say("Hello from script!");
return 0;
}
chmod +x myscript.strada
./myscript.strada
--script (whole-file) vs --script --chunked vs ahead-of-time compile
| Feature | --script (default) |
--script --chunked |
Ahead-of-time (strada foo.strada) |
|---|---|---|---|
| What runs | One full stradac + gcc, exec'd |
Each balanced chunk JIT-compiled via tcc/gcc and dlopen'd | Same as --script, but you keep the binary |
| Startup cost | ~1 sec gcc (or ~50 ms with --compiler=tcc) |
~50 ms per chunk with tcc; ~500 ms per chunk with gcc | One-time at build; instant at runtime |
| Execution speed | Native code, fully optimised | Native code per chunk; less inlining across chunks | Native code, fully optimised |
Needs main()? |
Yes | No — top-level statements run as written | Yes |
| Best for | Scripts you run a few times | REPL-style sequences, free-form scripts | Production binaries |
Command-Line Options (strada --repl / --script)
| Option | Description |
|---|---|
--repl |
Start the interactive REPL (auto-detects tcc/gcc) |
--script FILE |
Compile and run FILE in whole-file mode (default: gcc) |
--compiler=tcc / =gcc |
Force a specific C compiler for the JIT/script path |
--chunked |
For --script: feed the file to the REPL eval path line-by-line instead of whole-file mode |
-L PATH |
Add library search path |
--help |
Show help message |
Embedded eval
If you want to evaluate Strada strings from inside a Strada program, use the Eval library:
use lib "lib";
use Eval;
func main() int {
Strada::Interpreter::init();
my scalar $r = Strada::Interpreter::eval("2 + 2");
say($r); # 4
return 0;
}
The default backend is the tree-walking interpreter, which is always available. Switch to the bytecode VM with Strada::Interpreter::set_eval_backend("vm") — note the VM requires the runtime to be built with -DHAVE_VM (only the standalone strada-interp binary defines it).