Hardening records + address + IR validation firewall
0.0.8 · 2025-12-17
This release is about locking semantics so later backends can’t “interpret” the language differently.
Records are stricter, address is enforced end-to-end, and IR now has a validation pass
that fails fast before runtime.
- Added builtin
address("...") (typechecked + runtime-supported).
- Removed implicit
string <-> address compatibility (no silent coercions).
- Runtime now has a concrete
Value::Address and it is enforced.
- Record literals now materialize defaults during lowering (not runtime).
- Missing required record fields are hard errors (compiler must reject).
- Address defaults require explicit
address("...").
- Record update (
..base) merges base + overrides correctly.
- Lowering uses a
ProgramCtx to access model/contract declarations.
- Added IR validation pass: rejects unknown record types, duplicate fields, unknown fields, and non-materialized record literals.
- New tests around IR validation and record correctness (unknown record/field, duplicates, base type mismatch cases).
The interpreter now returns a structured ProgramResult with value, captured prints,
an execution trace, and a gas-like step counter, and classifies require failures as data.
- Interpreter entry now yields
ProgramResult::Ok { value, prints, trace, gas } instead of a bare value.
print(expr) appends to prints: Vec<String> rather than writing to stdout.
require(cond, msg?) returns ProgramResult::RequireFail { message, trace, gas } on failure.
- Added
ExecutionTrace (function-level trace) and GasMeter (deterministic step counter) to every run.
- New tests:
trace_includes_main, trace_records_nested_calls_in_order, gas_increases_with_work.
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 nominal type_name and field map.
- Implemented
Display for runtime values, including record printing.
- Introduced a concrete
address type at runtime (initially with coercion from string when binding locals/params).
- Extended builtin
print(...) to use Display output for records and primitives.
- Added
Wallet model example (wallet.dexa) with new_wallet, credit, debit.
- Wired the tour page to show the wallet example end-to-end so the site matches what runs today.
- Run:
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, continue end-to-end (parser → typechecker → IR → interpreter).
- Dedicated IR forms:
IrStmt::While, IrStmt::Loop, plus Break/Continue.
- Model and contract bodies are typechecked; invalid field types are rejected.
- Diagnostics include line/column and an inline caret for parse/type errors.
- Added negative examples to keep errors honest (
bad_parse.dexa, bad_type.dexa, bad_model.dexa).
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.
- Typechecker rejects non-bool conditions.
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.
- Interpreter can run simple programs and return a value.
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.