Project

go-joker

active

Performance-optimised Clojure-like Lisp interpreter with five execution tiers, native helpers and web notebooks.

Overview

I forked Joker because I wanted a Clojure-like extension language inside gi, without starting a JVM. The original interpreter was useful for scripting and linting, but loops and arithmetic were slow enough to get in the way. Most of the work went into making those parts faster while keeping the tree-walker available for code the compiler cannot handle.

The fork also has a browser notebook, graphics and PDF libraries, and an HTTP server. I use it as a small, self-contained place to run Clojure code and inspect what it does.

How it works

The reader and parser build expressions that can take one of five execution paths. Eligible recursive integer functions become native Go closures; numeric loops can run through wazero's WebAssembly JIT. Typed IR handles primitive values without boxing, boxed IR handles collections, and the tree-walker executes the remaining forms. Which path runs depends on the expression.

Performance depends on the code you write and which execution path it takes. The benchmarks compare portable Joker programs and native helpers separately, alongside Python, Bun, Goja and let-go.

Features
Native integer functions

Recursive integer defn bodies can compile to Go closures, avoiding the allocation and dispatch overhead of the interpreter.

🧮
WASM execution

Eligible numeric loops run through wazero. joker.jit/compile-wasm exposes this for explicit kernels, including the notebook's image-rendering examples.

📦
Typed and boxed IR

Primitive loops avoid Object boxing; collection code uses boxed values. Transient vectors and maps support mutable construction before returning persistent collections.

🌐
Web applications

A Ring-style HTTP server supports WebSockets and server-sent events. The router includes path parameters, middleware and CORS handling.

🎨
Graphics and documents

joker.imaging, joker.svg and joker.pdf provide image manipulation, SVG generation and PDF output from scripts.

🔧
Runtime inspection

Disassemble compiled functions, inspect allocation and GC statistics, and profile or benchmark code from the REPL.

📓
Browser notebooks

EDN notebooks combine executable cells with charts, diagrams and images. The local interface uses CodeMirror, ECharts and Mermaid without a CDN; notebooks can also run headlessly and export to Markdown.

Architecture
Clojure Source .joke scripts Reader + Parser AST · TCO rewrite IR Compiler 45+ opcodes Native integer fib(35) · 0.5s WASM / wazero numeric loop JIT Typed IR primitive loops Boxed IR collections · transients Tree-walker full semantics Result Object value fallback go-joker — five execution tiers selected per expression
Posts
Not a Joke
Notes for May 3-10