Compiler Pipeline
Understanding LOVE-LANG's three-phase OPERA → MATERIALIZE → SIMULATE compilation workflow.
Compiler Pipeline
Section titled “Compiler Pipeline”LOVE-LANG uses a three-phase compilation pipeline inspired by the SATOR/SOLID synthesis. Every programme passes through these three stages before execution.
Overview
Section titled “Overview”Natural Language Intent │ ▼┌────────────────────┐│ OPERA (Draft) │ .love pseudo-lisp│ /logic/*.love │ Focus on causality└────────────────────┘ │ ▼┌────────────────────┐│ MATERIALIZE (AST) │ .edn strict AST│ /programmes/*.edn │ Correct bracket depths└────────────────────┘ │ ▼┌────────────────────┐│ SIMULATE (Verify) │ .ini invariants│ /simulations/*.ini│ LSP verification└────────────────────┘ │ ▼ ExecutionPhase 1: OPERA (Dependency Inversion)
Section titled “Phase 1: OPERA (Dependency Inversion)”Principle: DIP — High-level policy must not depend on low-level syntax.
The OPERA phase is where you draft the intent of your programme in a relaxed pseudo-lisp format. The goal is to capture logical causality — what causes what — without worrying about bracket depths or type annotations yet.
;; Draft: User Authentication Flow(def raw_pass "password123")(def user_name "alice")
;; 1. Hash the password;; 2. Validate as UserPayload;; 3. Write to database(let [hashed_pass (@hash_pass raw_pass) payload (UserPayload user_name hashed_pass)] (@sql_write "users" payload))OPERA Checklist
Section titled “OPERA Checklist”- Is the logical flow clear?
- Have you identified all inputs and outputs?
- Have you listed all effectors you need?
- Does the logic make sense without any bracket depths?
Phase 2: MATERIALIZE (Open-Closed)
Section titled “Phase 2: MATERIALIZE (Open-Closed)”Principle: OCP — Materialize the draft into strict execution nodes.
The MATERIALIZE phase translates your .love draft into a strict LOVE-LANG EDN AST with correct bracket depths applied.
{:type :programme :id :user-auth :body [raw_pass . "password123" user_name . "alice"
; L2: Pure operation — hashing hashed_pass . [[ @hash_pass [raw_pass] ]]
; L3: Type contract — validate structure ; L5: Side effect — write to database [[[[[ @sql_write "users" [[[ UserPayload ]]] { :name [user_name] :hash [hashed_pass] } ]]]]]]}Bracket Depth Rules
Section titled “Bracket Depth Rules”When materializing, apply the correct level:
| What you’re doing | Level |
|---|---|
| Referencing a variable | L1 [ ] |
| Calling a pure function | L2 [[ ]] |
| Applying a type contract | L3 [[[ ]]] |
| Setting a compiler directive | L4 [[[[ ]]]] |
| Calling an I/O effector | L5 [[[[[ ]]]]] |
Phase 3: SIMULATE (Liskov Substitution)
Section titled “Phase 3: SIMULATE (Liskov Substitution)”Principle: LSP — Define the invariant truths the programme must conserve.
The SIMULATE phase defines a .ini file of expected state changes that the programme must produce. This is verified by the @TENET checker at runtime.
[expected_state]db_table = "users"inserted_keys = "name, hash"hash_matches_raw = falseoutput_count = 1error_state = falseEffector Declaration
Section titled “Effector Declaration”Before using any L5 effector, you must declare it in your model.edn:
{:system::state :listening :effectors [{:id :sql_write :desc "Writes to DB" :arity 2} {:id :hash_pass :desc "Hashes a string" :arity 1} {:id :http_post :desc "HTTP POST request" :arity 2} {:id :print :desc "Print to stdout" :arity 1}]}A Complete Example
Section titled “A Complete Example”-
Draft the intent (OPERA)
/logic/fibonacci.love ;; Compute the nth fibonacci number(def n 10)(let [result (@fibonacci n)](@print result)) -
Materialize the AST (MATERIALIZE)
/programmes/fibonacci.edn {:type :programme:id :fibonacci:body[n . 10result . [[ @fibonacci [n] ]][[[[[ @print [result] ]]]]]]} -
Define the invariants (SIMULATE)
/simulations/fibonacci.ini [expected_state]output_value = 55error_state = false