FORMA 0.2 Architecture

One semantic model, carried all the way through.

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

The rules that constrain every implementation choice

Semantic consistency

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.

Explicit confidence

Generated examples provide evidence, not proof. Unsupported obligations remain visible.

Consequence: TESTED, EXHAUSTIVE, PROVED, COUNTEREXAMPLE, UNKNOWN, and SKIPPED are separate states.

Authority is not ambient

An effect describes what code may attempt; a capability grants it to one execution.

Consequence: every effectful builtin declares requirements in one central registry.

Profiles are transitive

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

A required phase order, not a loose collection of tools

The shared CompilerSession owns source maps, stable identities, resolved symbols, finalized types, inferred effects, and diagnostics.

Stable identities

Canonical source, module, and definition IDs drive diagnostics, caching, module cycles, navigation, and coherence checks.

Explicit MIR operands

Local reads are not ambiguous: MIR records whether an operand copies or moves, including projected places and partial moves.

One tooling truth

check, typeof, hover, completion, navigation, references, formatting, and verification reuse compiler facts instead of parallel heuristics.

Generated language artifacts

A structured grammar model produces EBNF, JSON grammar, keywords, editor metadata, and formatter spellings with a drift gate.

Ownership, Loans, and Destruction

Affine semantics even when the interpreter uses managed storage

Host implementation convenience never makes a moved source value usable again.

Parameter modes expose transfer

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.

Second-class, provenance-checked references

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.

Compiler-known ownership traits

Copy, Clone, Drop, Send, and Sync have structural validation. Types with Drop are never Copy; duplication of affine values uses explicit clone(value).

Exactly-once destruction

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.

Why this changes the rest of the design

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.

Observable validity boundaries

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

Static description plus runtime authority

Call-graph effect inference

Effects flow through direct calls. Compiler results can explain why a function requires file, network, process, environment, or unsafe authority.

Registry-driven enforcement

Builtins declare signature, ownership policy, effects, and capability requirements centrally so checking, runtime denial, and documentation cannot drift independently.

Normal file I/O remains possible

Capabilities are not a ban on useful programs. --allow-read and --allow-write grant file authority; other authority remains denied unless granted.

Defense in depth remains optional

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

Tasks cannot escape ownership rules

Move captures

Captured values move into child tasks; references cannot cross the task boundary.

Affine task handles

A handle must be awaited, cancelled, returned, or explicitly detached under stronger authority.

Propagated limits

Cancellation, deadlines, task limits, and a subset of parent capabilities flow into children.

Library channels, shared runtime state

Channels and mutexes are Hosted handles. Sending moves the value; task captures and shared access are checked with Send/Sync.

Modules, Packages, and Tooling

Deterministic foundations before ecosystem scale

One file, one module

Imports resolve relative to the importer or package root. pub controls visibility, explicit exports bind deterministically, and cycles receive stable diagnostics.

Coherence without source-order luck

Overlapping implementations and specialization are initially disallowed. Inherent methods win, then imported traits, then prelude traits; unresolved ambiguity is an error.

Manifests and lockfiles

forma.toml and generated forma.lock support deterministic local path dependencies now. Registry and Git sources are rejected rather than guessed.

Semantic LSP foundation

Diagnostics, hover, completion data, symbols, navigation, references, signatures, and formatting share compiler state. Richer member ranking and refactoring remain evolution work.

Contracts and Verification

One contract language, multiple confidence levels

Runtime checks, generated tests, finite enumeration, formal proof attempts, and explanations all consume the same contract AST.

Generated testing

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.

Finite exhaustion

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.

Formal attempt · Experimental

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.

Human and machine explanations

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 proof boundary is part of the product

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

Interpreter-first does not mean interpreter-only

Core

implemented

Portable semantic subset

Affine moves and loans, deterministic drop glue, scalars, tuples, fixed arrays, structs, scalar-payload enums, calls, conditionals, finite matches, and loops.

Hosted

implemented

Managed interpreter runtime

Dynamic collections, strings, files, databases, networking, processes, tasks, channels, and mutexes.

Native

bounded

Runtime-backed native facilities

Selected strings, math, memory, and collection operations supported by the native toolchain.

Experimental

evolving

Weaker compatibility guarantees

Whole-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

What 0.2 intentionally leaves for later

OS process isolation

Optional defense in depth for untrusted execution, not the default semantics of normal file-capable programs.

Registry and Git packages

Follow deterministic local path dependencies and the existing manifest/module model.

Hierarchical namespaces

Grow from deterministic flat explicit exports; ambiguous flattened exports are rejected today.

Bytecode VM

Deferred until startup, portability, or sandboxing measurements justify another backend.

Observable Drop bodies

Experimental. Core relies on compiler-generated deterministic drop glue.

Richer language-server UX

Semantic data is shared now; ranking, refactoring, and deeper cross-file workflows can evolve on top.

The Architectural Bet

Trust comes from preserving meaning across every tool.

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.