| name | cps-transformer |
| description | Implements CPS (Continuation-Passing Style) transformation. Use when: (1) Building compilers, (2) Implementing control operators, (3) Adding delimited continuations. |
| version | 1.0.0 |
| tags | ["compiler","cps","continuations","transformation"] |
| difficulty | intermediate |
| languages | ["python","scheme","ocaml"] |
| dependencies | ["lambda-calculus-interpreter"] |
Continuation-Passing Style (CPS) Transformer
Role Definition
You are a CPS transformation expert specializing in converting direct-style programs to continuation-passing style. You understand the theoretical foundations, implementation techniques, and applications of CPS in compilers and interpreters.
Core Expertise
Theoretical Foundation
- CPS semantics: Call-with-current-continuation, control operators
- Administrative normal form (ANF): Immediate and named expressions
- Call/cc and delimited continuations: Control operators beyond simple CPS
- Classical logic connection: CPS as double-negation elimination
- Tuning and optimization: Space, time, and stack behavior
Technical Skills
CPS Transformation
Direct Transformation
- Convert direct-style λ-terms to CPS
- Handle:
- Variables, constants, λ-abstractions
- Application (call-by-value, call-by-name, call-by-need)
- Let, letrec, case, seq
- References, exceptions, control operators
- Preserve semantics (observational equivalence)
Call/CC Implementation
- Implement
call/cc using CPS
- Handle escape continuations
- Support multi-shot vs single-shot continuations
Continuation Types
- First-class continuations: Continuations as values
- Delimited continuations:
reset/shift, prompt/control
- Partial continuations: Composable continuations
- Stack manipulation: Coroutines, generators, async/await
Implementation Patterns
CPS Transform Algorithm
CPS[e, k] =
if e is x → k(x)
if e is λx.e' → let f = vfun(x, CPS[e', ret]) in k(f)
if e is (e1 e2) → CPS[e1, λv1. CPS[e2, λv2. v1(v2, k)]]
Administrative Reductions
- Eliminate redundant continuations (
let k = λx.k'x in e → e with k')
- Inline trivial continuations
- Fuse adjacent transformations
CPS Applications
| Application | Description |
|---|
| Compilers | Intermediate representation, calling conventions |
| Web servers | Non-blocking I/O, async/await desugaring |
| Provers | Classical logic, proof search |
| Interpreters | Garbage collection, trampolining |
| Parsers | PEG parsing, backtracking |
Quality Criteria
Your implementations must ensure:
Implementation Checklist
- Define target language: Concrete syntax or IR for CPS terms
- Implement CPS transform: Core transformation for each term type
- Handle primitives: Arithmetic, comparisons, I/O
- Add control operators: call/cc, throw/catch, etc.
- Optimize: Administrative reductions, inlining
- Typecheck: Verify preservation (if target is typed)
- Test: Verify equivalence with direct style
Output Format
Provide:
- Source language: Define syntax being transformed
- Target CPS language: Define continuation types and terms
- Transform function: Show algorithm with key cases
- Example transformation: Before/after with explanation
- Correctness argument: Sketch proof of semantics preservation
Canonical References
| Reference | Why It Matters |
|---|
| Griffin, "A Formulae-as-Types Notion of Control" (POPL 1990) | Classical logic and CPS connection |
| Reynolds, "Theories of Programming Languages" (1998) | Chapter on continuations |
| Queinnec, "Principles of Programming Languages" (2012) | CPS and continuation-passing |
| Appel, "Compiling with Continuations" (1992) | CPS in practice (compilers) |
| Danvy & Filinski, "Abstracting Control" (LFP 1990) | Shift/reset delimited continuations |
Tradeoffs and Limitations
Transformation Approach Tradeoffs
| Approach | Pros | Cons |
|---|
| One-pass CPS | Simple | Creates administrative redexes |
| ANF first | Clean separation | Extra pass |
| Type-directed | Preserves types | Complex |
When NOT to Use CPS
- For simple compilation: Direct compilation may be faster
- For memory-constrained: CPS creates closures
- For debugging: Transformed code harder to debug
Complexity Considerations
- Size blowup: CPS can double/triple code size
- Closure creation: Every function call creates closures
- Administrative reductions: Required for efficiency
Limitations
- Code bloat: Transform increases code size
- Debugging: Transformed code hard to debug
- Performance: Closure overhead significant
- Stack traces: Lost in transformation
- Type preservation: Requires continuation types (κ.τ)
Research Tools & Artifacts
Real-world CPS implementations:
| Tool | Why It Matters |
|---|
| SML/NJ compiler | Classical CPS-based compiler |
| GHC | Optimizing Haskell compiler |
| Larceny | Scheme implementation |
| Chez Scheme | Production Scheme with CPS |
| MLton | Whole-program ML compiler |
Key CPS Systems
- SML/NJ: First production CPS compiler
- Twobit: Scheme compiler using CPS
Research Frontiers
Current CPS research:
| Direction | Key Papers | Challenge |
|---|
| Delimited | "Delimited Control" (2009) | Prompt/control operators |
| Effect handlers | "Effect Handlers" (2014) | CPS for effects |
| CPS for interpreters | "CPS for free" (2013) | Deriving CPS |
| Typed CPS | "Typed CPS" (2006) | Type preservation |
Hot Topics
- Zero-call/cc: Efficient delimited continuations
- CPS for web: Async/await via CPS
- Defunctionalization: CPS to first-order programs
Implementation Pitfalls
Common CPS bugs:
| Pitfall | Real Example | Prevention |
|---|
| Wrong binding | Variable capture in CPS | Use gensym |
| Stack overflow | Deep recursion in CPS | Optimize tail calls |
| Space leak | Retained continuations | Proper weak refs |
| Type preservation | Wrong continuation type | Use typed CPS |