Eulisp Documentation
*1. Eulisp,
Eulisp is a small, expression-based language where programs describe effects as data, and the runtime (Ω) decides how and when to execute them safely.
Programs do not “do things” directly. They declare effects. Execution authority lives outside the language.
2. What Is Eulisp?
Eulisp is built around three core ideas:
- Effects are data
- Control flow is forbidden inside effect declarations
- All execution authority lives outside the language
You construct a dependency graph of effect descriptions. Ω (the Governor) later admits, orders, executes, and records them.
3. Who This Is For
This guide is for:
- complete beginners (including people who have never programmed)
- people who want practical copy-paste examples
- contributors who want a quick mental model before reading dev docs
For runtime internals, see docs/dev-docs.org.
4. Start Here (No Prior Programming Needed)
4.1. Key Idea 1: Everything Is an Expression
In Eulisp, everything is an expression. An expression produces a value.
42
"hello"
(add 2 3)
4.2. Key Idea 2: Effects Are Data First
When you write:
(print "hello")
It does not immediately print.
It creates an EffectDescription.
Ω executes it later.
5. Execution Model
An eulisp program goes through four stages:
- Parsing Source code → S-expressions.
- Elaboration Syntax → AST. Ethical and structural constraints are enforced here.
- Evaluation (Pure) Expressions evaluate. Effects are collected, not executed.
- Governance & Execution
Governor decides:
- which effects are admissible
- when they can run
- whether dependencies are satisfied
Then it executes them and records them in a ledger.
5.1. Multi-Pass Execution
Execution proceeds in dependency-aware passes:
- Effects with satisfied dependencies are ready.
- Ready effects execute (or reuse cached results).
- Successful IDs and results are stored.
- Dependents of changed results are marked dirty.
- If no progress can be made, remaining effects are rejected.
- Stop at fixpoint (or max pass limit).
- Execution is deterministic and idempotent.
6. Your First Program
(effect main ()
(print "Hello from Eulisp"))
What happens:
maindescribes one print effect.- Governor executes it.
- You see output.
7. Language Concepts
7.1. Literals
42
"hello"
7.2. Variables
x
7.3. Let Bindings
(let (x 10)
(add x 5))
7.4. Conditionals
(if (gt x 0) (print "positive") (print "non-positive"))
7.5. Sequences
(seq expr1 expr2 expr3)
7.6. Lambdas
(lambda (x y)
(add x y))
Pure vs Effect Functions
Functions are defined at the top level using pure or effect.
7.7. Pure Functions
May compute values but must not directly emit effects.
(pure add-two (x) (add x 2))
7.8. Effect Functions
Must contain exactly one expression. That expression must not contain control flow.
(effect say-hi (name) (print name))
Inside an effect function body, do not use:
ifletseq- nested function definitions
This keeps effect descriptions non-decisional and auditable.
8. Effects As Values
Effects are created using primitives like:
(print "hello") (write-file "out.txt" "data") (read-file "out.txt") (done "finished") (sleep 1000)
These do not perform IO immediately.
They return structured values of type EffectDescription.
Effects may be:
- stored
- returned
- composed
- placed in lists
At the end of evaluation, all effects reachable from main are collected.
9. Useful Effect Primitives
; file artifact with optional dependencies (emit-artifact "artifact.txt" "content") (emit-artifact "artifact.txt" "content" (list dep-id)) ; read realized result of an effect (result some-effect)
A Practical File Example
(effect main () ((lambda (template templateRead0) ((lambda (templateRead) (list template templateRead (emit-artifact "todo-today.txt" (concat "# Daily Checklist\n\n" (result templateRead) "\nGenerated by eulisp.\n") (list (hash templateRead))) (done "demo complete"))) (depend (hash template) templateRead0))) (emit-artifact "todo-template.txt" "- [ ] Review priorities\n- [ ] Ship one thing\n") (read-file "todo-template.txt")))
10. Dependencies
Dependencies are explicit and manual.
(depend (hash first-effect) second-effect)
Meaning second-effect may run only after first-effect succeeds.
Multiple dependencies:
(depend (list h1 h2 h3) effect)
10.1. Chain (Simple Linear Sequence)
(chain (print "a") (print "b") (print "c"))
Each effect depends on the previous one.
11. Lists and Higher-Order Construction
You can declaratively build effect graphs:
(let (effects (map sleep (list 100 200 300))) (depend (map hash effects) (print "all done")))
No loops. No runtime branching. Just graph construction.
12. Data Primitives
12.1. Concat
Strings:
(concat "hello" " " "world")
Lists:
(concat (list 1 2) (list 3 4))
12.2. String Escapes
\n newline
\t tab
\r carriage return
\ backslash
" quote
Example:
(print "line1\nline2")
13. Effect Identity
Every effect has a cryptographic identity: SHA256(canonical encoding of EffectDescription)
(hash (print "hello"))
Properties:
- identical descriptions → identical IDs
- IDs are 256-bit SHA digests
- identity is content-addressed
- no counters
- no runtime integers
- runtime result does not affect identity
14. Governor
Ω is not part of the language syntax. It is the runtime authority.
Responsibilities:
- admit or reject effects
- enforce idempotence (via SHA256 identity)
- resolve dependencies
- execute effects in parallel waves
- record an immutable ledger
- verify outcomes
- detect cycles and unresolved deadlocks
- pre-validate dependency graph
The ledger is:
- append-only
- deterministic (sorted by EffectID)
- persisted in sqlite
Each entry stores:
- pass number
- decision
- outcome
- structured result
15. Structured Logging
Runtime logs are structured.
Modes:
- default → pretty structured logs
--json-logs→ JSON log lines--silent→ hide system logs (userprintanddonestill visible)
Example JSON log:
{"timestamp":"...","level":"info","event":"effect.print","message":"hello"}
16. CLI Flags
Common flags:
--ledger--print-ledger--clear-ledger--debug--print-graph--json-logs--silent
17. Tiny Copy-Paste Examples
17.1. Minimal Hello
(effect main ()
(print "hello"))
17.2. Parallel Sleeps Then Final Message
(effect main () ((lambda (sleeps) (list sleeps (depend (map hash sleeps) (print "all tasks complete")))) (map (lambda (id) (sleep id 500)) (list "a" "b" "c"))))
17.3. Write → Read → Print
(effect main () ((lambda (w r0) ((lambda (r) (list w r (depend (hash r) (print (result r))))) (depend (hash w) r0))) (write-file "x.txt" "hello from file") (read-file "x.txt")))
Plan / Status
