Distilled from
docs/GRAMMAR.md,docs/ARCHITECTURE.md, anddocs/LANGUAGE_DESIGN.mdin black-candle-technologies/rexlang.
Rex source → compiler → Rex bytecode (.rexl) → virtual machine
Two Rust components: the compiler translates Rex source to bytecode; the VM executes it. Packed executables bundle the VM via rex-runner.
| Crate | Path | Responsibility |
|---|---|---|
rex-lexer |
crates/lexer |
Tokenizes Rex source text |
rex-parser |
crates/parser |
Parses tokens into an AST |
rex-compiler |
crates/compiler |
Compiles AST to bytecode; encodes/decodes .rexl |
rex-resolver |
crates/resolver |
Loads source files, resolves package imports, drives compilation |
rex-vm |
crates/vm |
Executes bytecode (stack-based VM) |
rex-runner |
crates/runner |
Launcher embedded into packed executables + payload format |
rex-cli |
crates/cli |
The rex binary (run, build, pack) |
Each pipeline crate depends only on the stage before it. The resolver owns everything file-shaped (source loading, import discovery, error rendering). The compiler owns language semantics (visibility, signatures, entrypoint rules) and never touches the filesystem.
@import("std") is a compile-time builtin. std combines embedded Rex source (packages/std/eq.rex) with native-backed VM intrinsics (unix_time, format_timestamp).User without colliding.program = package_decl? const_decl* declaration+
declaration = contract_decl | struct_decl | satisfy_decl | native_function | function
package_decl = "package" identifier ";"
contract_decl = visibility? "contract" identifier "{" (field | contract_method)* "}"
struct_decl = visibility? "struct" identifier "{" (field | method)* "}"
("satisfies" path ("," path)* ";")?
satisfy_decl = "satisfy" identifier "for" identifier "{" method* "}"
function = visibility? "fn" identifier "(" parameters? ")" ("->" type)? block
visibility = "private" | "protected" | "public"
type = "bool" | "int" | "string" | "void"
statement = let_statement | for_statement | expression ";"
let_statement = "let" identifier (":" type)? "=" expression ";"
for_statement = "for" identifier "in" expression block
expression = if_expression | equality
Operator precedence: ** (right-assoc) → unary -/! → *// → +/- → comparisons → ==/!= → if expressions.
main returning bool, int, or void.void may return implicitly.print writes a value's representation + newline, returns void. String formats support named local interpolation ({name}), positional args ({}), escaped braces ({{, }}). format uses the same rules without producing output; formatting a struct calls its std.Display.format.From LANGUAGE_DESIGN.md: Rex takes Rust's ownership model, Go's concurrency and package-level modules, and Zig's error handling, aiming for a memory-safe language with a small, readable core. Execution speed and portability are the primary implementation goals.
See also: RexLang overview