This document is the starting point for anyone — human or AI agent — arriving at this repository without context. Read it before touching code.
Error-Lang is an educational programming language built around one idea: make the ways programs go wrong visible, measurable, and explorable.
Most teaching languages hide complexity until it bites you. Error-Lang does the opposite — it surfaces failure modes as first-class citizens. You write programs, they partially decay, type structures collapse, stability scores drop, and you see exactly why.
The result is that learners develop intuition about language design, type systems, and failure semantics before those failures become production incidents.
A dissembling, decompositional programming language where programs, types, and semantics can decay over time — and the language makes that decay visible rather than hiding it.
| Feature | What it means |
|---|---|
Stability Score |
Every program execution produces a 0–100 stability score. Code choices (and decay) debit this score in real time, like a craftsperson’s quality gauge. |
Echo Types |
Structured loss is first-class: |
The Gutter Zone |
The |
Computational Haptics |
An animated stability bar, color coding, and sparkline history give you visceral feedback about code quality — you feel the consequences of design decisions. |
Paradoxes |
Ten deliberate quirks (positional operators, scope leakage, temporal corruption…) make implicit language assumptions explicit through contradiction. |
Every program starts at 100. Actions that introduce uncertainty, complexity, or structured loss debit the score. The score is visible at all times and cannot be hidden — that’s the point.
Key debits (from docs/Error-Categories.adoc):
| Action | Score Debit |
|---|---|
Security error |
−20 |
Logical error / Interface error |
−15 |
Echo erasure ( |
−15 |
Runtime / Resource / Arithmetic error |
−10 |
Semantic error |
−10 |
Syntax / Linker error |
−5 |
Echo types are Error-Lang’s first-class shape for structured loss — situations where information is necessarily shed, but where that loss must be visible and costed.
Decomposition must be visible.
echo_to_residueis never a silent cast.EchoRis never anEchowith a missing field. The stability debit is never hidden.
let e : Echo<Int, String> = echo(42, "answer")
# e carries BOTH the witness (42) and the output ("answer")
# echo_input(e) → 42
# echo_output(e) → "answer"
let r : EchoR<Int, String> = echo_to_residue(e)
# Stability: 100 → 85 (the [Stab-Erase] debit fires here)
# r carries ONLY the output — the witness is genuinely gone
# echo_output(r) → "answer" (output survives)
# echo_input(r) → TYPE ERROR and RUNTIME ERROR (non-recoverable)| Builtin | Signature | Notes |
|---|---|---|
|
|
Construct witness + output |
|
|
Erase witness; debits stability |
|
|
Illegal on |
|
|
Output survives erasure |
|
|
Always |
Echo<A,B> and EchoR<A,B> are distinct types — they never unify. You cannot cast
a residue back into an Echo. This models real information loss: once a hash replaces a
plaintext, or a summary replaces a document, the original is gone. Error-Lang makes
that boundary visible at compile time and enforces it at runtime.
See docs/Echo-Decomposition.adoc and spec/type-system.md §7 for the full specification.
Ten core quirks make implicit language assumptions explicit:
-
Type Quantum Superposition — unannotated variables exist in multiple types until first use
-
Scope Leakage — variables escape blocks on prime-numbered lines
-
Positional Operator Semantics —
+adds on even columns, concatenates on odd -
Context-Collapse Keywords —
maybe,sometimes,usuallyaffect runtime semantics -
Temporal Corruption — previous run history infects current execution
-
Reserved Word Roulette — keywords shift meaning by context
-
Arithmetic Drift — math accumulates small deterministic errors
-
Null Propagation Cascade — null spreads like a virus through dependent variables
-
Global State Entanglement — globals affect each other in non-local ways
-
Memory Phantom — freed memory sometimes persists
main
let e = echo(42, "answer")
let r = echo_to_residue(e) # stability 100 → 85
gutter
# Code here is executed but errors are contained.
# A residue cannot recover its witness — this is both
# a type error and a runtime error:
println(echo_input(r))
end
println("Still running after the gutter.")
endThe gutter block is the pedagogically-safe error zone: errors inside it are
injected, observed, and then recovered from — the program continues. It teaches
error handling without halting the learning session.
-
Deno (runtime)
git clone https://github.com/hyperpolymath/error-lang.git
cd error-lang
deno run -A cli/runtime.js examples/01-hello-world.err
deno run -A cli/runtime.js examples/11-echo-decomposition.errdeno run -A cli/runtime.js <program.err> # Run a program
deno run -A cli/analyze.js <program.err> # Stability analysis
deno run -A cli/five-whys.js <program.err> # Root cause trace
deno run -A cli/layer-navigator.js <program.err> # Five-layer view
deno run -A cli/visual-feedback.js <program.err> # Haptics outputSource (.err)
│
▼ [Lexer — tokenizes; Echo/EchoR are keywords]
│
▼ [Parser — produces AST; parses Echo<A,B> type annotations]
│
▼ [Type Checker — unifies types; enforces Echo/EchoR irreversibility]
│
▼ [Codegen — emits bytecode; Echo builtins map to dedicated opcodes]
│
▼ [VM — executes; echo_to_residue debits stability score]
│
Output + Stability Score + Haptics| Path | What lives there |
|---|---|
|
Token and type AST definitions (including |
|
Tokenizer; |
|
AST builder; type expression parser (handles |
|
Type inference + unification; Echo builtin rules |
|
|
|
Stack VM; |
|
AST → bytecode; Echo builtins → dedicated opcodes |
|
Type-checker, parser, lexer, and runtime tests |
|
Deno-based CLI tools (the runnable implementation) |
|
Annotated |
|
EBNF grammar, type-system spec, axiomatic/operational semantics |
|
Human-readable design documents (AsciiDoc) |
|
Operational invariants, recovery semantics, trust, roadmap |
|
Machine-readable manifests (STATE, META, AGENTIC, etc.) |
|
Note
|
compiler/src/.res is a *reference frontend written in a non-standard ReScript
dialect. The runnable implementation is cli/. The ReScript tree does not build against
mainstream ReScript — this is a pre-existing intentional choice pending AffineScript
re-target. Do not attempt to fix it by removing .res files.
|
The compiler/ directory uses an early, non-standard ReScript dialect:
return/break statements, dict<K,V> with non-string keys, and element-returning
arr[i]. This dialect predates any standard toolchain. A formal
AffineScript re-target (ADR-pending) will migrate the reference frontend to standard
tooling. Until then, follow each file’s established idioms when extending the compiler.
| Document | Purpose |
|---|---|
Project overview and quick-start (GitHub landing page) |
|
This file — comprehensive orientation |
|
Type system specification (including §7 Echo Types) |
|
Canonical EBNF grammar |
|
Echo types — authoritative narrative |
|
Why the language is designed this way |
|
Full language reference |
|
Nine error categories + stability debits |
|
Lesson sequence (Lessons 1–11) |
|
Pedagogy and learning theory |
|
Operational framework overview |
|
Current project state (for AI agents) |
|
AI agent gateway manifest (read first) |
-
AffineScript re-target — migrate
compiler/src/*.resto a standard, buildable dialect. This resolves thegovernance / Language / package anti-pattern policyCI failure (ReScript ban) that currently hits every PR frommain.
-
First-class functions in VM — enables whole-fibre
Echo(the full Agda proof thatf x ≡ y, not just a pairing); the current single-witness runtime is a stepping stone.
-
Formal Echo soundness proof in Agda — the
echo-typesrepo carries the Agda mechanization; Error-Lang will eventually include a formal bridge between its runtime model and the Agda proof. -
Benchmark lineage chains — measure erasure cost against the theoretical Landauer bound; link Error-Lang’s
echoEraseCostto the physics.
Read 0-AI-MANIFEST.a2ml first — it is the canonical gateway for AI agents. Then read STATE.a2ml for current project state.
Key constraints (from AGENTIC.a2ml):
-
Never make
echo_to_residuea silent cast -
Never let
EchoR<A,B>unify with or coerce toEcho<A,B> -
Never hide the erasure stability debit (
[Stab-Erase]) -
Never delete spec files (
spec/grammar.ebnf,spec/SPEC.core.scm) -
Never use banned languages (TypeScript, Python, Go, Node.js)
-
Never commit secrets
-
All new GitHub Actions must be SHA-pinned
-
All new source files must have SPDX-License-Identifier headers
-
Never use the AGPL license (use MPL-2.0)
-
SCM files live ONLY in
.machine_readable/— root copies are symlinks