A minimal Lisp interpreter designed as a portable intermediate representation (IR) with clear semantics that can be reimplemented across multiple host environments.
This project provides a tiny, well-specified Lisp evaluator that serves as a reference implementation for portable computation. By keeping the core language extremely small and precisely defined, the same Lisp programs can run identically across different host environments (browser, Python, JVM, Rust, native) with straightforward reimplementation.
Minimal Core Language
- Small expression set:
lambda,if,let,define,quote,begin - Basic primitives: arithmetic, comparisons, string operations
- No I/O in core - host capabilities exposed through explicit boundary
- Tail-recursive, expression-only evaluation (Scheme-ish)
- Purely functional semantics with immutable environments
Portability Through Simplicity
- Reference implementation establishes canonical behavior
- Clear semantic specification enables mechanical consistency across runtimes
- Host-specific capabilities accessed via
(host-call 'name args...) - Same source runs in browser/Python/JVM/Rust with simple interpreter ports
Gram as Serialization Format
- Lisp code serialized as Gram subject patterns
- Implementation-agnostic: Gram is just structured data
- Enables querying and introspection of code structure
- Natural fit for embedding executable definitions in documents
Using Gram subject pattern notation to represent a Lisp function:
[:Function {name: "greet", params: ["name"]} |
[:Call {fn: "string-append"} |
[:String {value: "Hello, "}],
[:Symbol {name: "name"}],
[:String {value: "!"}]
]
]
This is equivalent to the S-expression: (lambda (name) (string-append "Hello, " name "!"))
Both representations describe the same computation - the Gram form makes structure explicit and queryable.
┌─────────────────────────────────────┐
│ Lisp Code (S-expressions) │
│ (lambda (x) (+ x 1)) │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Gram Serialization (optional) │
│ [:Lambda | [:Symbol "x"], │
│ [:Call "+" ...]] │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Pattern Lisp Evaluator │
│ • Parse expressions │
│ • Environment-based evaluation │
│ • Host call boundary │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Host Environment │
│ • Haskell (reference impl) │
│ • Rust / JavaScript / Python │
│ • JVM (Clojure, Java, Kotlin) │
└─────────────────────────────────────┘
- Define a minimal Lisp core with clear, unambiguous semantics
- Implement a reference evaluator in Haskell demonstrating correct behavior
- Provide comprehensive test suite verifying evaluation rules
- Document the specification enabling faithful reimplementation in other languages
- Explore Gram serialization of Lisp code as structured patterns
- Establish host call boundary for platform-specific capabilities
- Rich standard library (intentionally minimal)
- Macros or compile-time metaprogramming
- Performance optimization (clarity over speed)
- Advanced type system or static analysis
- Built-in concurrency or async primitives
While this is a general-purpose portable Lisp, it was designed with specific use cases in mind:
- Embedded scripting: Lightweight extension language for applications
- Configuration with computation: Beyond static config files, allow calculated values
- Cross-platform tools: Define behavior once, run everywhere
- Agent tool definitions: Express executable capabilities in a portable format (see Pattern Agents)
- Educational: Clear reference for understanding evaluation semantics
Phase 1: Core Lisp Evaluator ✅ COMPLETE
The core interpreter is fully functional with:
- ✅ S-expression parser with position-aware error messages
- ✅ Environment-based evaluator with lexical scoping
- ✅ Core language forms:
lambda,if,let,quote,begin,define - ✅ Primitive functions: arithmetic, comparison, string operations
- ✅ Interactive REPL with file loading support
- ✅ Comprehensive test suite (unit, property-based, integration)
- ✅ Example programs demonstrating language features
See Quickstart Guide for detailed usage instructions.
- Cabal: 3.10 or later
- GHC: 9.6.3 (or compatible version)
- Git: For dependency resolution (gram-hs from GitHub)
-
Update Cabal index and resolve dependencies:
cabal update
-
Build all components:
cabal build all
-
Run tests:
cabal test -
Run the CLI executable:
# Start interactive REPL cabal run pattern-lisp # Or execute a file directly cabal run pattern-lisp -- examples/functions.plisp
Start the REPL and try some expressions:
$ cabal run pattern-lisp
> (+ 1 2)
3
> (define square (lambda (x) (* x x)))
square
> (square 4)
16
> :quitRun example programs from the examples/ directory:
# Run a function example
cabal run pattern-lisp -- examples/functions.plisp
# Run a list example
cabal run pattern-lisp -- examples/lists.plispimport PatternLisp.Parser
import PatternLisp.Eval
import PatternLisp.Primitives
main = do
case parseExpr "(+ 1 2)" of
Left err -> print err
Right expr -> case evalExpr expr initialEnv of
Left err -> print err
Right val -> print val -- Output: VNumber 3For more examples and detailed usage, see the Quickstart Guide.
pattern-lisp/
├── src/ # Library code (PatternLisp.* modules)
├── app/ # CLI executable (Main.hs)
├── test/ # Test suite
├── examples/ # Example Lisp programs
├── cabal.project # Multi-package configuration
└── pattern-lisp.cabal # Package definition
- gram-hs: Source repository dependency from GitHub (https://github.com/gram-data/gram-hs)
- Core libraries: text, containers, megaparsec, mtl
- Testing: hspec, QuickCheck
- Quickstart Guide: Get started with Pattern Lisp
- Feature Specification: Complete feature requirements
- Implementation Plan: Technical implementation details
- Examples: Example programs demonstrating language features
- Development Roadmap: Future development phases
See TODO.md for the complete development roadmap.
- gram-hs: Haskell implementation of Gram notation parser
- Scheme R5RS/R7RS-small: Inspiration for minimal, well-specified semantics
- Lua: Model for lightweight embedded scripting language
- WebAssembly: Model for host function boundaries and portable execution
- Pattern Agents: Framework using this Lisp for portable tool definitions
TBD