Affine
Source-level ownership from the first interpreter
FORMA 0.2 Architecture
FORMA’s central architectural choice is consistency: parsing, type resolution, effects, ownership, tooling, interpretation, native compilation, and verification consume the same resolved program and typed MIR.
Status, not aspiration
The 0.2 semantic foundation is implemented. Whole-program LLVM parity, the SMT-supported subset, and observable user-defined destructors remain Experimental and are reported as such.
Affine
Source-level ownership from the first interpreter
Pre-opt
Ownership gates run before optimization
Tiered
Tests, finite exhaustion, and formal attempts stay distinct
Profiled
Core, Hosted, Native, and Experimental support
Design Invariants
An optimized program cannot acquire different move, loan, drop, contract, or invariant behavior.
Consequence: ownership checks and drop elaboration precede optimization and backend selection; invariant boundaries are semantic, not backend conventions.
Generated examples provide evidence, not proof. Unsupported obligations remain visible.
Consequence: TESTED, EXHAUSTIVE, PROVED, COUNTEREXAMPLE, UNKNOWN, and SKIPPED are separate states.
An effect describes what code may attempt; a capability grants it to one execution.
Consequence: every effectful builtin declares requirements in one central registry.
A wrapper around a Hosted operation does not become Core because its own syntax looks portable.
Consequence: backend support propagates through direct calls and appears per function.
Semantic Compiler Spine
The shared CompilerSession owns source maps, stable identities, resolved symbols, finalized types, inferred effects, and diagnostics.
lossless CST
↓
semantic AST
↓
name resolution → type + trait resolution → effect inference
↓
typed high-level IR
↓
MIR construction
↓
ownership + borrow analysis
↓
drop elaboration
↓
optimization
↓
interpreter · LLVM · semantic tooling · verifier
Canonical source, module, and definition IDs drive diagnostics, caching, module cycles, navigation, and coherence checks.
Local reads are not ambiguous: MIR records whether an operand copies or moves, including projected places and partial moves.
check, typeof, hover, completion, navigation, references, formatting, and verification reuse compiler facts instead of parallel heuristics.
A structured grammar model produces EBNF, JSON grammar, keywords, editor metadata, and formatter spellings with a drift gate.
Ownership, Loans, and Destruction
Host implementation convenience never makes a moved source value usable again.
f consume(items: Vec[Item])
f inspect(ref items: Vec[Item])
f update(ref mut items: Vec[Item])
Owned non-Copy values move. Shared references read; mutable references are exclusive. mv can document a move but is not required for an owned transfer.
References cannot be stored in ordinary aggregates, captured by escaping closures, or sent to tasks. A returned reference is allowed only when derived from a reference parameter under elision rules.
Copy, Clone, Drop, Send, and Sync have structural validation. Types with Drop are never Copy; duplication of affine values uses explicit clone(value).
CFG and overwrite drop elaboration destroy each owned place once. Partial moves drop only initialized fields. The initial panic strategy is abort; compiler-generated cleanup covers abort and contract paths.
Affine task handles must be consumed; channel sends move values; package and backend checks must preserve ownership; verification models cannot silently duplicate an affine input. Ownership is not a standalone feature—it constrains concurrency, effects, optimization, and proof semantics.
Named structs may declare @inv clauses. In the Hosted interpreter, construction, function entry/return, and ref mut return are checked boundaries. Exclusive mutation can update coupled fields in stages, but cannot return an invalid value. The SMT verifier now models supported named structs and tuples structurally: valid entry values become assumptions, projected updates are tracked symbolically, and construction, direct pure-call, and return boundaries generate establishment or preservation obligations. Native check injection and formal reference reasoning remain future work.
Effects and Capabilities
Effects flow through direct calls. Compiler results can explain why a function requires file, network, process, environment, or unsafe authority.
Builtins declare signature, ownership policy, effects, and capability requirements centrally so checking, runtime denial, and documentation cannot drift independently.
Capabilities are not a ban on useful programs. --allow-read and --allow-write grant file authority; other authority remains denied unless granted.
Interpreter containment, limits, denial, and solver process cleanup ship in 0.2. OS process isolation is an additional option for untrusted playgrounds, verification, build scripts, or third-party code.
Structured Concurrency
Captured values move into child tasks; references cannot cross the task boundary.
A handle must be awaited, cancelled, returned, or explicitly detached under stronger authority.
Cancellation, deadlines, task limits, and a subset of parent capabilities flow into children.
Channels and mutexes are Hosted handles. Sending moves the value; task captures and shared access are checked with Send/Sync.
Modules, Packages, and Tooling
Imports resolve relative to the importer or package root. pub controls visibility, explicit exports bind deterministically, and cycles receive stable diagnostics.
Overlapping implementations and specialization are initially disallowed. Inherent methods win, then imported traits, then prelude traits; unresolved ambiguity is an error.
forma.toml and generated forma.lock support deterministic local path dependencies now. Registry and Git sources are rejected rather than guessed.
Diagnostics, hover, completion data, symbols, navigation, references, signatures, and formatting share compiler state. Richer member ranking and refactoring remain evolution work.
Contracts and Verification
Runtime checks, generated tests, finite enumeration, formal proof attempts, and explanations all consume the same contract AST.
forma verify rules.forma \
--level test --examples 200 --seed 42
Reproducible generated inputs run under step and time limits. Passing samples produce TESTED, never PROVED.
forma verify rules.forma \
--level exhaustive --max-domain 4096
Supported finite parameter domains are enumerated completely. Reports state the tested domain and return UNKNOWN if it is unsupported or too large.
forma verify rules.forma \
--level formal --report
The SMT backend covers acyclic signed-64-bit Int/Bool logic plus structural tuples and named structs made from those leaves. It proves construction, projection, equality, projected updates, and struct-invariant establishment/preservation; unsupported or timed-out work remains UNKNOWN.
forma explain rules.forma --format human
forma explain rules.forma --format json
Contracts can be explained for reviewers or automation without creating a second interpretation of their meaning.
The structural verifier has been exercised with real Z3: supported Switchyard obligations are discharged, while an invalid invariant-bearing construction yields a solver counterexample. Arrays and vectors, indexing, enums, loops, recursive or indirect calls, references, unsafe operations without models, Hosted effects, and backend gaps must still produce UNKNOWN or SKIPPED—not optimistic success.
Execution and Profiles
Core
implementedAffine moves and loans, deterministic drop glue, scalars, tuples, fixed arrays, structs, scalar-payload enums, calls, conditionals, finite matches, and loops.
Hosted
implementedDynamic collections, strings, files, databases, networking, processes, tasks, channels, and mutexes.
Native
boundedSelected strings, math, memory, and collection operations supported by the native toolchain.
Experimental
evolvingWhole-program LLVM parity, SMT verification, and user-defined observable destructor bodies.
Backend honesty: support is reported per function and transitively through direct calls. A wrapper around a Hosted-only builtin remains unsupported by Core LLVM or formal verification.
Deliberate Boundaries
Optional defense in depth for untrusted execution, not the default semantics of normal file-capable programs.
Follow deterministic local path dependencies and the existing manifest/module model.
Grow from deterministic flat explicit exports; ambiguous flattened exports are rejected today.
Deferred until startup, portability, or sandboxing measurements justify another backend.
Experimental. Core relies on compiler-generated deterministic drop glue.
Semantic data is shared now; ranking, refactoring, and deeper cross-file workflows can evolve on top.
The Architectural Bet
FORMA 0.2 is less about collecting features than making them agree: ownership constrains concurrency, effects constrain authority and proof, profiles constrain backend claims, and one compiler session keeps diagnostics and execution on the same semantic ground.