GitHub - bagnalla/sisyphus: The most tragic programming language

6 min read Original article ↗

Sisyphus

A programming language where every program is a futile struggle against inevitable entropy.

Philosophy

In Sisyphus, all data decays over time, hope is a syntax error, and every program eventually loses everything it has worked for. The language is Turing-complete, but every computation carries the weight of its own impermanence.

Core Mechanics

1. Memory Decay

All variables lose precision over time. Each tick of the runtime, numeric values drift randomly by ±1%, strings lose a random character, and booleans have a 0.1% chance of flipping.

let hope = 100
wait 50
print hope       -- prints something like 43.7

2. Attachment & Loss

You can form bonds between variables. When one is garbage collected, all bonded variables grieve — their values are halved for 100 ticks.

let parent = new Being("alive")
let child = new Being("alive")
bond(parent, child)

destroy parent    -- child now enters grieving state
print child.joy   -- 0.5 (halved)

3. The remember Keyword

You can try to preserve values using remember. It doesn't actually work — it just logs what the value used to be to stderr.

let youth = "beautiful"
remember youth
wait 200
recall youth
-- stderr: youth was "beautiful"
-- stdout: "btfl"

4. Inevitability Blocks

The eventually block will execute at some random point during your program. You cannot prevent it. You cannot predict when.

eventually {
    destroy everything
}

-- your entire program runs under this shadow

5. The try / cope Error Handling

There is no catch. There is only cope.

try {
    let meaning = search(universe)
} cope {
    -- this block runs but changes nothing
    -- the error still propagates
    print "it's fine"    -- prints "it's fine"
    -- program still crashes
}

6. Functions Forget

Functions gradually lose their bodies. After being called ~100 times, instructions start disappearing from the function body, one line at a time, starting from the middle.

fn struggle(boulder, hill) {
    push(boulder, hill.top)      -- first to go (call 137)
    let summit = reach(hill.top) -- disappears at call 112
    return summit                -- last to remain
}

7. The love Operator

Creates a deep, bidirectional reference between two objects. Makes both objects immune to decay — but if either is garbage collected, the other is immediately destroyed too.

let romeo = new Being()
let juliet = new Being()
romeo love juliet    -- both stabilized

-- but memory is finite
-- the GC is always watching

8. Comments Are Visible to the Runtime

Comments affect execution. Optimistic comments speed up decay. Pessimistic comments slow it — but the program prints them to stdout as intrusive thoughts.

-- everything will be okay        (decay accelerates 2x)
-- nothing matters                 (decay slows, but prints to stdout)
-- this is fine                    (no effect; the runtime knows you're lying)

9. The hope Keyword (Illegal)

hope                -- SyntaxError: hope is not defined in this world

10. Program Termination

All Sisyphus programs end the same way. The final output is always:

[Process ended. Memory returned to void. Nothing was saved.]

You can write an exit message, but it will be printed with random characters missing.


Example Program

let boulder = new Object({weight: "immense"})
let hill = new Object({height: "infinite"})
let sisyphus = new Being("determined")

bond(sisyphus, boulder)

eventually {
    boulder.position = hill.bottom
}

loop forever {
    try {
        push(boulder, hill.top)
        -- we did it!              (decay accelerates)
    } cope {
        print "one must imagine sisyphus happy"
    }
}

Output:

one must imagine sisyphus happy
one must imagine sisyphus happy
one mst imagine sisyphs happy
oe mst imagine ssyphs hppy
o mt imgne syphs py
nothing matters
[Process ended. Memory returned to void. Nothing was saved.]

Sisyphus Interpreter (OCaml)

This repository contains an initial interpreter for the Sisyphus language in OCaml. Parsing is implemented with ocamllex + menhir.

The current implementation supports a focused subset of the design from sisyphus.md:

  • let name = expr
  • assignment: name = expr
  • member assignment: obj.field = expr
  • function definitions: fn name(args) { ... }
  • returns: return expr
  • conditionals: if (expr) { ... } else { ... }
  • loop control: break, continue
  • print expr
  • wait N
  • loop forever { ... }
  • expression operators: +, -, *, /, ==, !=, <, <=, >, >=, &&, ||, unary - and !
  • grouped expressions: (expr)
  • remember name and recall name
  • eventually { ... }
  • try { ... } cope { ... }
  • destroy name and destroy everything
  • object creation: new Kind(...)
  • object literals in constructors: {field: expr, ...}
  • member access: obj.field
  • side-effect calls: bond(a, b)
  • built-in calls: push(obj, destination), reach(x), search(x)
  • love operator: left love right
  • exact comment effects:
    • -- everything will be okay (accelerates decay)
    • -- nothing matters (slows decay and prints)
    • -- this is fine (no effect)
  • illegal hope keyword (parse error)

Runtime characteristics:

  • Values decay each tick.
  • Numeric values drift by up to about +-1% * decay_multiplier per tick.
  • Strings lose random characters over time.
  • Booleans can randomly flip.
  • Object fields decay unless stabilized with love.
  • Bonded objects grieve for 100 ticks when one is destroyed (numeric fields read as halved while grieving).
  • Functions forget: after about 100 calls, one statement disappears per call with random middle-biased line loss.
  • Memory is finite: above a soft object limit, GC pressure randomly destroys objects.
  • Optimistic comments accelerate decay.
  • Pessimistic comments reduce decay and are printed as intrusive thoughts.
  • All runs end with:
    • [Process ended. Memory returned to void. Nothing was saved.]

Limitations of current implementation

  • String decay is probabilistic per tick (not guaranteed every tick).
  • Comment effects are currently exact-phrase based (everything will be okay, nothing matters, this is fine) rather than sentiment-based.
  • bond(a, b) currently requires object values, not arbitrary variables.
  • The spec note about a user-defined exit message that decays is not implemented yet.

Build

Test

Install dependencies once in the current opam switch:

opam install -y menhir alcotest

Run tests:

Run

dune exec sisyphus -- examples/remember.sisy

Exit Codes

  • 0: successful execution
  • 1: parse, lexing, or runtime error
  • 2: command-line usage or file I/O error

Deterministic run:

dune exec sisyphus -- --seed 42 examples/remember.sisy

Function erosion demo:

dune exec sisyphus -- --seed 7 examples/function_forget.sisy

Exact comment phrase demo:

dune exec sisyphus -- --seed 7 examples/comment_phrases.sisy

GC pressure demo:

dune exec sisyphus -- --seed 7 examples/gc_pressure.sisy

About

This project is a joke, obviously. It was designed and implemented almost entirely by LLMs (Opus 4.6 design, gpt-5.3-codex implementation) in a couple hours.