Why Continuations Are the Universal Semantic Kernel
What Is a Continuation?
A continuation is "the rest of the computation from this point onward." It represents the future of a program—everything that will happen next.
If your VM can:
- Capture the continuation (save the future)
- Resume it (jump back to saved future)
- Pass it as a value (like a function)
- Store it (even persistently)
- Transfer it across machines
…then almost every language feature becomes a special case of manipulating continuations.
Continuations as a Universal Encoding
Here's the key insight: continuations can encode the semantics of nearly every programming language feature. Let's see how.
a. Exceptions
An exception is:
"Jump to a continuation representing the nearest handler."When you throw, you abandon the current continuation and resume a saved continuation (the catch block).
b. Async/Await
An await is:
"Suspend the continuation; resume later when value arrives."The async runtime saves your continuation, does other work, then restores it when the promise resolves.
c. Generators / Iterators
A generator is:
"A function that yields by suspending its continuation, then resumes from that point."Each yield saves the continuation. Each next() restores it.
d. Coroutines
Same idea, except the continuation is passed explicitly between peers.
e. Backtracking (Prolog)
A choice point is:
"A saved continuation of the entire search state."Prolog saves continuations at every decision point. Backtracking = restoring an earlier continuation.
f. Delimited Control / Effect Handlers
Effects are:
"Intercept the continuation, wrap it, resume it with transformed context."Effect handlers capture the continuation up to a delimiter, transform it, and resume it with new context.
g. Tail-Call Optimization
A tail call is:
"Replace current continuation with another one."Instead of pushing a new frame, you replace the continuation entirely.
h. Actor-Style Concurrency (Erlang)
Actor mailbox processing is:
"A loop of message-triggered continuations."Each message handler is a continuation that processes one message and yields the next continuation.
i. Green Threads / Lightweight Processes
A thread is:
"A continuation stored in the scheduler, resumed by cooperative scheduling."The scheduler maintains a queue of continuations and switches between them.
j. Checkpointing / Migration
A checkpoint is:
"A continuation serialized and moved."Serialize the continuation, send it to another machine, deserialize, resume.
Everything Is Just Continuation Manipulation
Everything above can be implemented without adding new primitives—just using:
- Continuation capture
- Continuation resume
- A small amount of state
This is why languages like Scheme and SML/NJ with call/cc were considered insanely expressive.
Why Yin Can Encode All This Directly
Because Yin makes continuations:
- First-class — they are values you can pass around
- Serializable — they can be saved to disk or sent over the network
- Datoms — they are facts in the database
- Network-transferable — they can migrate between machines
- Persistent — they survive process restarts
This is NOT the case for: JVM, WASM, LLVM, BEAM, or most other IRs.
In Yin, a continuation is literally just data in DaoDB:
[:cont/id 1234
:cont/op :apply
:cont/env {...}
:cont/next 5678]Because it's data:
- Languages can construct continuations
- Modify them
- Store them
- Send them across processes
- Reify them for debugging
- Query them using Datalog
- Patch them using LLMs
Yin is a continuation machine at its foundation (a CESK machine).
Why Don't Other IRs Support Continuations?
Because full first-class continuations make optimizing compilers and runtimes much harder.
This is the key point.
Reason 1: Hard for Stack-Based VMs
JVM, WASM, Lua VM, CPython:
- Use stacks and frames
- Continuations require capturing the full stack
- But stacks were not designed to be copied or mutated
- JVM stack frames contain return addresses, local variables, polymorphic registers—too tied to runtime layout
So they intentionally avoid supporting continuations.
Reason 2: Hard for SSA-Based IRs (LLVM)
LLVM uses Static Single Assignment (SSA):
- Continuations require non-local control flow
- Captured continuations introduce φ-node explosion
- The CFG (control flow graph) becomes extremely complex
- Optimization passes (inlining, LICM, GVN, SROA) break under dynamic control flow
LLVM designers explicitly forbade continuations because:
They make optimizing dataflow IRs extremely difficult.
Reason 3: Most Languages Didn't Need Them
Most mainstream languages choose simpler models:
- Java: exceptions, threads, no coroutines
- Go: goroutines but no first-class continuations
- Rust: async state machines, not continuations
- JavaScript: async/await with hidden continuation-passing but no access to the raw continuation
Exposing real continuations would expose too much of the runtime's guts.
Reason 4: Security and Portability Concerns
Continuation capture:
- Freezes dynamic environment
- Often includes references to runtime internals or sensitive state
- Makes sandboxing difficult in JVM/WASM
Yin doesn't have this problem because:
- Continuations are just EDN/datom structures
- They contain only what your VM defines
- They are designed from the start to be serializable and capability-safe
Reason 5: Distributed Computation Was Not the Goal
None of those IRs were designed for:
- Migrating computations across nodes
- Pausing/resuming a process on another machine
- Storing active execution in a database
- Composing computations symbolically
Continuation capture + datoms is PERFECT for this. JVM/WASM/LLVM aren't trying to solve that domain.
What Makes Yin Unique?
A. Continuations Are the Universal Semantics Kernel
Instead of:
Building separate primitives for exceptions, threads, async, streams, coroutines, actors, generators, backtracking…
Yin uses:
One core thing: continuation.
This drastically simplifies the VM core and maximizes expressive power.
B. Continuations Are Data
Unlike all other IRs:
- Yin stores continuations as datoms
- The continuation graph is literally a knowledge graph
- You can query continuations with Datalog
- You can patch them
- You can migrate them
- You can approximate or explain them using LLMs
No other VM in history does this.
C. Continuations Unify Computation and Representation
Because continuations are AST segments:
code = data = execution state
There is no gap between "program" and "process."
The same DaoDB holds:
- AST nodes
- Continuation nodes
- Type/ontology nodes
- Runtime facts
This is why the system is so cohesive.
The Justification: Why Continuations?
Continuations allow representing many different language semantics directly because:
- Continuations generalize all control-flow constructs — everything from exceptions to coroutines to async is just a continuation transform.
- They give a uniform encoding for effects — Monad, async, generator, actor = continuation pattern.
- They allow languages to embed arbitrary execution models — laziness (thunks), logic programming (choice points), concurrency (green threads), backtracking (saved states), delimited control.
- They allow a small universal kernel — Many surface-level details of languages collapse into just a few continuation ops.
- Continuations are composable and serializable in Yin — unlike JVM/WASM/LLVM stacks or SSA CFGs.
Other IRs avoided continuations not because they are weak, but because they are too powerful and break their optimization/security model.
Yin Flips the Design
Yin makes a different choice:
- Power is the goal
- Optimization is local-first
- Security is capability-based
- Semantic clarity > CFG-based speed
TLDR
Continuations are powerful enough to encode the semantics of nearly any programming language directly.
Other IRs don't support them because:
- Their architectures (stacks, SSA, CFGs) make continuations difficult or impossible to handle
- Full continuations complicate optimization and security
- They weren't designed for distributed, reflective computation
Yin is unique because:
- Continuations are first-class
- Continuations are datoms
- Continuations are portable
- Continuations are serializable
- Continuations unify AST, execution, effects, and distribution
This is why Yin can serve as a universal intermediate representation for programming languages. Continuations are the semantic kernel. Everything else is just a pattern.
Learn more:
- AST as Higher Dimensional Construction of Datom Streams (how ASTs are materialized views over datom streams)
- Yin.vm: Chinese Characters for Programming Languages (how the Universal AST enables cross-language interoperability)
- Why yin.vm Succeeds Where Previous Attempts Failed (addressing skeptical objections to continuation-based mobile computation)
- DaoDB (the Datalog database powering datom streams)
- Yin VM Documentation (technical deep dive)