Bracket Depth Hierarchy
Understanding LOVE-LANG's five-level bracket system and what each level means.
Bracket Depth Hierarchy
Section titled “Bracket Depth Hierarchy”The most distinctive feature of LOVE-LANG is its bracket depth hierarchy — a topological encoding where the number of brackets indicates the semantic ring (level) of an expression.
This is not a quirky syntactic choice. It is a load-bearing architectural invariant that makes the LOVE evaluator’s behaviour provably composable.
The Five Rings
Section titled “The Five Rings”┌─────────────────────────────────────────────────────────────────┐│ [[[[[ L5 — System FFI / I/O / Side-Effects ]]]]] ││ [[[[ L4 — Compiler Directives / Macros ]]]] ││ [[[ L3 — Type Contracts / Structural Schemas ]]] ││ [[ L2 — Pure Operations / Standard Library Math ]] ││ [ L1 — Variables / Primitive References ] │└─────────────────────────────────────────────────────────────────┘Each outer ring encompasses all inner rings. L5 can call L4, which can call L3, and so on. But an inner ring cannot escape to an outer ring without crossing a trust boundary.
L1 — Data Expressions
Section titled “L1 — Data Expressions”“Just data.”
The simplest form. Single brackets wrap a list of atoms and other expressions.
# Primitive listcolours = [red green blue]
# Nested referencespair = [first-name last-name]
# Mixed atomsmeta = ["LOVE" :version 1 true]When to use: Any time you are grouping values, building a list, or referencing other variables.
L2 — Pure Operations
Section titled “L2 — Pure Operations”“Pure computation. No surprises.”
Double brackets invoke a pure function from the standard library. These expressions always produce the same output for the same input. No I/O, no state mutation.
sum = [[ + 1 2 3 ]]product = [[ * 6 7 ]]greeted = [[ String.concat "Hello, " name ]]validated = [[ List.contains allowed-roles :admin ]]When to use: Mathematical operations, string manipulation, list processing.
L3 — Type Contracts
Section titled “L3 — Type Contracts”“Proofs about shape.”
Triple brackets define structural schemas — compile-time type checks that validate the shape of data flowing through your programme.
# Define a type contractUserPayload = [[[ name @[String] email @[String] age @[Number] roles @[List]]]]
# Use it as a validatorvalidated-user = [[[ UserPayload ]]] raw-inputWhen to use: Defining data shapes, validating inputs at API boundaries, and describing record structures.
L4 — Compiler Directives
Section titled “L4 — Compiler Directives”“Talking to the compiler.”
Quadruple brackets issue compile-time instructions to the LOVE evaluator itself. These control optimization, code generation mode, and inlining behaviour.
build-config = [[[[ #mode Production #target wasm #inline true #strict type-checking]]]]
# Using a macroexpanded = [[[[ @macro[repeat 5] [print "hello"]]]]]When to use: Setting build modes, defining macros, compiler hints.
L5 — System FFI / I/O
Section titled “L5 — System FFI / I/O”“Where programmes meet the world.”
Five brackets are the most powerful and most dangerous ring. They cross the boundary from pure computation into the real world: databases, networks, files, screen output.
# Write to a database[[[[[ @sql_write "users" [[[ UserPayload ]]] { :name user-name :hash hashed-pass }]]]]]
# HTTP request[[[[[ @http_post endpoint-url payload]]]]]
# Display to user[[[[[ @print "Programme complete."]]]]]When to use: Any side-effecting operation. These must be declared as effectors in model.edn.
Mixing Levels
Section titled “Mixing Levels”Levels compose naturally. Inner expressions resolve first:
# L2 wrapping an L1result = [[ + [1 2 3] 10 ]]
# L5 wrapping L3 wrapping L1[[[[[ @sql_write "records" [[[ RecordSchema ]]] { :id [generate-uuid] :data payload }]]]]]Quick Reference
Section titled “Quick Reference”| Brackets | Level | Name | Side-Effects? | Compile-Time? |
|---|---|---|---|---|
[ ] | L1 | Data | ✗ | ✗ |
[[ ]] | L2 | Operations | ✗ | ✗ |
[[[ ]]] | L3 | Contracts | ✗ | ✓ (type phase) |
[[[[ ]]]] | L4 | Directives | ✗ | ✓ |
[[[[[ ]]]]] | L5 | System FFI | ✓ | ✗ |