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
How --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().
Older interpreter (opt-in): a bytecode VM / tree-walking interpreter still exists at 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).