Nominal records at runtime, a first-class address type, and a reference wallet program you can actually run.
- Added a runtime
Value::Record for models/contracts with a nominal type_name and field map.
- Implemented
Display for all runtime values, including pretty-printed records like Wallet{owner=addr:debug, balance=3}.
- Introduced a concrete
address type at runtime with coercion from string when assigning to address-typed locals and params.
- Extended builtin
print(...) to use the Display impl so printing records and primitives behaves like a real language.
- Added a
Wallet model example (wallet.dexa) with new_wallet, credit, debit, and small test functions asserting balances via require.
- Wired the language tour page to show the wallet example end-to-end so the site matches what the interpreter can execute today.
- You can run the reference example via the CLI:
cargo run -- examples/wallet.dexa.
Loops, models/contracts, and human-readable errors
0.0.5 · 2025-12-04
Structured control flow, richer declarations, and errors that don’t feel like a core dump.
- Added
while, loop, break, and continue to the language, fully wired through parser, typechecker, IR, and interpreter.
- Hooked loops into the IR via dedicated
IrStmt::While and IrStmt::Loop forms plus Break/Continue handling.
- Model and contract bodies are now typechecked: field initialisers must match their declared types (e.g.
debug_flag: bool = 1 is rejected).
- Improved diagnostics: parse/type errors include line/column and an inline caret, e.g.
error at 5:11: expected '{' (found Colon).
- Added negative examples (
bad_parse.dexa, bad_type.dexa, bad_model.dexa) to keep error messages honest.
Block scopes, let mut, and assignments
0.0.4 · 2025-12-01
Vars finally behave like a real language instead of a toy script.
- Introduced
let vs let mut with type-checked assignments.
- Disallow writes to immutable bindings at typecheck time (“cannot assign to immutable variable”).
- Implemented block scopes with inner-scope shadowing for local bindings.
- Lowered assignments to IR
Store ops, wired into the interpreter.
fn main() -> int {
let mut x: int = 0;
x = x + 10;
if x > 5 {
let mut x: int = 1;
x = x + 1;
}
return x;
}
Conditionals, booleans, and comparison operators
0.0.3 · 2025-11-30
DEXA can now branch on real boolean logic instead of everything collapsing into ints.
- Added
if / else statements with scoped blocks.
- Introduced
bool literals and logical ops: &&, ||.
- Comparison operators:
<, <=, >, >=, ==, != with type-checked numeric operands.
- Hooked into typechecker so non-bool conditions are rejected.
Functions, calls, and an interpreter that actually runs code
0.0.2 · 2025-11-29
First end-to-end slice: parse → typecheck → IR → interpreter.
- Function declarations with typed params and return types.
- Function calls with arity + param typechecking.
- Binary arithmetic operators:
+ - * / for int/float.
- Simple IR and an interpreter that can run pure integer programs and produce a result.
Initial syntax, lexer, parser
0.0.1 · 2025-11-28
First cut of the DEXA surface syntax and front-end.
- Lexer + parser for functions, models, and contracts.
- Basic literals: int, float, string, bool.
- Block structure and return statements.
- CLI skeleton wired via
cargo run -- <file.dexa>.
Work in progress. Expect breaking changes, sharp edges, and aggressive refactors.