Design Principles
Calor is built on five core principles that guide every language design decision. These principles serve a deeper goal: enabling verification. Every design choice makes contracts and effects machine-checkable, not just human-readable.
The Five Principles
| Principle | Implementation | Agent Benefit |
|---|---|---|
| Explicit over implicit | Effects declared with §E{cw,fs:r,net:rw} | Know side effects without reading implementation |
| Contracts are code | First-class §Q (requires) and §S (ensures) | Generate tests from specs, verify correctness |
| Stable IDs when you want them | §F{f001:Main}, §L{l001:i:1:100:1} (IDs optional) | Precise references that survive refactoring |
| Indent-based blocks | Python-style indentation — no closer tags to mismatch | Lower edit cost; familiar from training data |
| Machine-readable semantics | Lisp-style operators (+ a b) | Symbolic manipulation without text parsing |
1. Explicit Over Implicit
In traditional languages, side effects are implicit. You have to read the entire function body to know if it:
- Writes to console
- Reads from files
- Makes network calls
- Accesses a database
Calor requires explicit effect declarations:
§F{f001:SaveUser:pub}
§I{User:user}
§O{bool}
§E{db:rw,net:rw} // Explicit: database and network effects
// ... implementationAgent benefit: An agent can immediately filter functions by their effects without analyzing implementation details.
Effect Codes
| Code | Effect |
|---|---|
cw | Console write |
cr | Console read |
fs:w | Filesystem write |
fs:r | Filesystem read |
fs:rw | Filesystem read/write |
net:r | Network read |
net:w | Network write |
net:rw | Network read/write |
db:r | Database read |
db:w | Database write |
db:rw | Database read/write |
2. Contracts Are Code
Preconditions and postconditions aren't comments or assertions buried in code - they're first-class syntax elements:
§F{f001:Divide:pub}
§I{i32:a}
§I{i32:b}
§O{i32}
§Q (!= b 0) // Requires: b is not zero
§Q (>= a 0) // Requires: a is non-negative
§S (>= result 0) // Ensures: result is non-negative
§R (/ a b)Agent benefit:
- Automatic test generation from contracts
- Static verification of caller sites
- Clear documentation of function behavior
Contract Syntax
| Tag | Purpose | Example |
|---|---|---|
§Q | Precondition (requires) | §Q (> x 0) |
§S | Postcondition (ensures) | §S (!= result null) |
§Q{message="..."} | With custom error | §Q{message="x must be positive"} (> x 0) |
3. Everything Has an ID
Every structural element has a unique identifier that persists across refactoring:
§M{m001:Calculator} // Module ID: m001
§F{f001:Add:pub} // Function ID: f001
§L{for1:i:1:100:1} // Loop ID: for1
§IF{if1} (> i 50) // Conditional ID: if1
// ...Agent benefit:
- "Edit function f001" is unambiguous
- IDs survive code movement and renaming
- No reliance on line numbers that change
ID Conventions
Production code uses ULID-based IDs with kind prefixes:
| Element | Prefix | Example |
|---|---|---|
| Modules | m_ | §M{m_01J5X7K9M2NPQRSTABWXYZ12:Calculator} |
| Functions | f_ | §F{f_01J5X7K9M2NPQRSTABWXYZ12:Add:pub} |
| Classes | c_ | §CL{c_01J5X7K9M2NPQRSTABWXYZ12:MyClass} |
| Methods | mt_ | §MT{mt_01J5X7K9M2NPQRSTABWXYZ12:Process:pub} |
Short test IDs (f001, m001) are allowed only in tests/, docs/, and examples.
Learn more: Stable Identifiers - Why IDs matter and how challenges are overcome
4. Indent-Based Structure
Blocks are delimited by indentation (Python-style). Each opening tag introduces a block whose body must indent further; the block ends at the next line that dedents back to the parent column.
§M{Example}
§F{Main:pub}
§L{i:1:10:1}
§IF (> i 5)
// ...Agent benefit:
- Familiar to any agent trained on Python; no closer tag to forget or mismatch
- Lower edit cost (in our edit-workload studies, indent form reduced agent token cost by ~16% with no regression in correctness)
- Structure is visually unambiguous
Legacy Closer Tags
Pre-Phase-4d Calor used explicit closer tags such as §/M{m001} and
§/F{f001} (removed in Phase 4d). Modern Calor is indent-only; bulk-migrate
older sources with calor format.
5. Machine-Readable Semantics
Expressions use Lisp-style prefix notation that's directly manipulable:
// Calor: Clear AST structure
(+ (* a b) (- c d))
// Equivalent infix: Requires precedence parsing
a * b + c - d // Wait, is this (a*b)+(c-d) or a*(b+c)-d?Agent benefit:
- No operator precedence ambiguity
- Direct AST manipulation
- Symbolic computation without parsing
Operators
| Category | Operators |
|---|---|
| Arithmetic | +, -, *, /, % |
| Comparison | ==, !=, <, <=, >, >= |
| Logical | &&, ||, ! |
Principle Interactions
These principles reinforce each other:
- Stable IDs + Indentation = Unambiguous scope references and refactoring-safe edits
- Contracts + Explicit effects = Complete behavioral specification
- Lisp syntax + Contracts = Symbolic verification possible
- IDs + Contracts = Traceable invariants across refactoring
Next
- Stable Identifiers - Deep dive into language-level IDs
- Tradeoffs - What Calor gives up for these principles