Skip to content

Latest commit

 

History

History
389 lines (287 loc) · 9.67 KB

File metadata and controls

389 lines (287 loc) · 9.67 KB

Error-Lang Language Specification

1. Abstract

Error-Lang ("Error Language") is a teaching-first programming language where code intentionally breaks. The first task in any Error-Lang exercise is to make it build.

Error-Lang turns the compiler toolchain into the curriculum. Every run produces at least one new syntax error, but students can always make progress because the system is designed for recovery and diagnosis.

2. Non-Goals

  • Error-Lang is NOT for production use

  • Error-Lang is NOT a replacement for any serious language

  • Error-Lang does NOT aim for performance

  • Error-Lang errors are NOT bugs - they are the curriculum

3. Design Principles

3.1. Errors Are Features

Every injected error has:

  • A unique error code (E0001, E0002, etc.)

  • A learning objective

  • A recovery path

  • A lesson in the curriculum

3.2. The Jenga Semantics (Optional)

Error-Lang maintains a Stability Score starting at 100. Each run’s injected error reduces the score. At S=0, execution still works but output becomes "wobbly":

  • Variables reorder in debug printing

  • Whitespace in pretty printer gets chaotic

  • Semantics remain deterministic

This creates the "it’s working, but it’s falling apart" aesthetic.

3.3. Structured Loss Is Visible (Echo)

Where Jenga Semantics decay the whole program, Echo types decay a single value — deliberately, observably, and irreversibly. Error-Lang is a decompositional language: when structure is lost, the loss must be seen.

  • Echo<A, B> — a retained witness x : A plus the visible output y : B it reached.

  • EchoR<A, B> — the non-recoverable residue after erasure (the witness is gone).

  • echo_to_residue(e) — the explicit decomposition step, Echo<A,B> → EchoR<A,B>, which debits the Stability Score.

The governing rule is decomposition must be visible: echo_to_residue is never a silent cast, EchoR is never an Echo with a missing field, and the stability debit is never hidden. See docs/Echo-Decomposition.adoc and spec/type-system.md §7.

3.4. Always Recoverable

The parser is error-tolerant. Every injected error is:

  • Bounded to a specific zone

  • Recoverable (parser continues after error)

  • Explainable (clear diagnostic message)

4. Syntax Reference

Error-Lang uses a Julia-inspired, block-based syntax.

4.1. Program Structure

# A complete Error-Lang program

main
    let greeting = "Hello, Error-Lang!"
    println(greeting)

    gutter
        # Error injection zone - something WILL break here
        let broken = "this might not parse
    end

    println("Still running!")
end

4.2. Tokens

4.2.1. Keywords

Keyword Purpose

main

Program entry point block

end

Block terminator

let

Variable binding

gutter

Error injection zone (safe to break)

if / else

Conditionals (Stage 2+)

function

Function definition (Stage 2+)

Echo

Fibre type: retained witness + visible output (Echo<A, B>)

EchoR

Residue type: non-recoverable remains after erasure (EchoR<A, B>)

4.2.2. Literals

Type Example Notes

Integer

42, -17

64-bit signed

Float

3.14, -0.5

IEEE 754 double

String

"hello"

Double-quoted, escapes supported

Boolean

true, false

4.2.3. Operators

Precedence Operators

Highest

() grouping

*, /, % multiplicative

+, - additive

==, !=, <, >, , >= comparison

Lowest

and, or logical

4.3. Statements

4.3.1. Variable Binding

let x = 42
let message = "Hello"
let result = x + 10
let e: Echo<Int, String> = echo(42, "answer")   # type annotation: a fibre witness

4.3.2. Echo: Structured Loss

let e = echo(42, "answer")        # Echo<Int, String>: witness 42 reached "answer"
let i = echo_input(e)             # 42  — recover the witness
let o = echo_output(e)            # "answer" — the visible output

let r = echo_to_residue(e)        # EchoR<Int, String> — witness erased; stability drops
let still = echo_output(r)        # "answer" — output survives erasure
let lost = residue_strictly_loses(r)   # true — non-recoverability is observable
# echo_input(r)                   # ERROR: the witness is gone (decomposition is real)

4.3.3. Output

print("no newline")
println("with newline")
println(42)
println("value: ", x)

4.3.4. Gutter Block (Error Zone)

The gutter block is a designated area where errors will be injected. The parser will encounter an error here on some runs.

gutter
    # Anything here might break
    let x = ...
end

Parser recovery rule: on gutter error, skip tokens until end and continue main program execution.

5. Error Model

5.1. Error Structure

Every Error-Lang error follows this format:

Error-LangError: <file>:<line>:<col>: <message> [code=E#### run=NNN]

Example:

Error-LangError: hello.err:7:23: unterminated string literal [code=E0002 run=3]

5.2. Error Codes

Code Description Learning Objective

E0001

Unexpected token

Token classification

E0002

Unterminated string

String literal rules

E0003

Invalid escape sequence

Escape processing

E0004

Illegal character

Character sets

E0005

Missing 'end'

Block structure

E0006

Unmatched parenthesis

Expression nesting

E0007

Unicode/smart quote

Encoding awareness

E0008

Identifier rules violation

Naming conventions

E0009

Reserved keyword misuse

Keyword awareness

E0010

Whitespace significance

Indentation rules

5.3. Run Counter

Error-Lang tracks execution count in .error-lang/state.json:

{
  "runCounter": 5,
  "stabilityScore": 80,
  "lastError": "E0002",
  "seed": 12345
}

Each run:

  1. Reads current run counter

  2. Selects error injection based on (seed, runCounter)

  3. Injects error into gutter zone

  4. Parses with recovery

  5. Executes valid portions

  6. Updates state file

6. CLI Reference

6.1. error-lang run

error-lang run file.err           # Run program
error-lang run file.err --seed 42 # Deterministic mode
error-lang run file.err --run-id 5 # Specific run number

6.2. error-lang doctor

error-lang doctor                 # Check environment
error-lang doctor --verbose       # Detailed diagnostics

6.3. error-lang explain

error-lang explain E0002          # Explain error code
error-lang explain --all          # List all error codes

6.4. error-lang fix

error-lang fix file.err           # Generate patched file
error-lang fix file.err --diff    # Show minimal fix

7. Grammar (EBNF)

program     = main_block ;

main_block  = "main" , statements , "end" ;

statements  = { statement } ;

statement   = let_stmt
            | print_stmt
            | gutter_block
            | expression ;

let_stmt    = "let" , IDENTIFIER , "=" , expression ;

print_stmt  = ( "print" | "println" ) , "(" , [ expr_list ] , ")" ;

gutter_block = "gutter" , { token } , "end" ;

expr_list   = expression , { "," , expression } ;

expression  = logical_or ;

logical_or  = logical_and , { "or" , logical_and } ;
logical_and = equality , { "and" , equality } ;
equality    = comparison , { ( "==" | "!=" ) , comparison } ;
comparison  = term , { ( "<" | ">" | "<=" | ">=" ) , term } ;
term        = factor , { ( "+" | "-" ) , factor } ;
factor      = unary , { ( "*" | "/" | "%" ) , unary } ;
unary       = ( "-" | "not" ) , unary | primary ;
primary     = INTEGER | FLOAT | STRING | BOOL | IDENTIFIER | "(" , expression , ")" ;

IDENTIFIER  = LETTER , { LETTER | DIGIT | "_" } ;
INTEGER     = [ "-" ] , DIGIT , { DIGIT } ;
FLOAT       = INTEGER , "." , DIGIT , { DIGIT } ;
STRING      = '"' , { character } , '"' ;
BOOL        = "true" | "false" ;

8. Implementation Notes

8.1. Toolchain

  • Compiler: ReScript (compiles to JS)

  • CLI: Deno (JavaScript runtime)

  • Docs: AsciiDoc

8.2. Architecture

.err file
    │
    ▼
┌─────────┐    tokens    ┌────────┐    AST    ┌──────────┐
│  Lexer  │ ──────────▶  │ Parser │ ───────▶  │ Executor │
└─────────┘              └────────┘            └──────────┘
    │                        │                      │
    │                        │                      ▼
    └────────┬───────────────┴──────────────▶  Output
             │
             ▼
      ┌─────────────┐
      │ Diagnostics │ ──▶ Error-LangError messages
      └─────────────┘

9. Conformance Levels

9.1. Level 1: Core (Stage 1)

MUST implement:

  • main/end blocks

  • let bindings

  • print/println

  • Integer and string literals

  • Basic arithmetic

  • gutter block with recovery

  • Single error injection per run

  • Run counter tracking

9.2. Level 2: Teaching (Stage 2)

MUST implement Level 1 plus:

  • error-lang doctor

  • error-lang explain

  • Deterministic --seed mode

  • 10 error codes minimum

9.3. Level 3: Classroom (Stage 3+)

MUST implement Level 2 plus:

  • Multiple error zones

  • Stability score

  • LSP-lite support

  • Autograder mode

10. License

Error-Lang is licensed under MPL-2.0.