explaingit

kanaka/mal

10,631AssemblyAudience · developerComplexity · 3/5Setup · moderate

TLDR

A guided project for learning how programming languages work by building a Lisp interpreter from scratch in 11 incremental steps, available in 89 languages so you can compare the same concepts across Python, Rust, Bash, and more.

Mindmap

mindmap
  root((Make a Lisp))
    What It Is
      Guided project
      Lisp interpreter
      11 steps
    Languages
      Python
      Rust
      JavaScript
      89 total
    Key Concepts
      Parser
      Evaluator
      Macros
      Self-hosting
    Use Cases
      Learn interpreters
      Compare languages
    Audience
      Developers
      CS students
Click or tap to explore — scroll the page freely

Code map

Detail Auto

An interactive map of this repo's files and how they connect — its source is parsed live in your browser. Click Visualize to build it.

filefunction / class

Things people build with this

USE CASE 1

Build your own Lisp interpreter step by step to understand how parsers, evaluators, environments, and macros work under the hood.

USE CASE 2

Compare how interpreter concepts like tail calls and closures look across very different languages by browsing the 89 implementations.

USE CASE 3

Use the self-hosting final step to verify your interpreter is fully functional by running mal code written in mal itself.

USE CASE 4

Follow the 11 testable milestones to systematically learn language implementation with a structured process guide.

Tech stack

PythonJavaScriptRustJavaBashAssembly

Getting it running

Difficulty · moderate Time to first run · 1h+

In plain English

Mal, which stands for Make a Lisp, is a project designed to teach people how programming languages work by having them build one. Specifically, it guides you through creating an interpreter for a dialect of Lisp, a family of programming languages with a long history in computer science. Lisp is known for its simple, highly regular syntax, which makes it an ideal subject for a language-building exercise. The project breaks the work into 11 incremental steps, each self-contained and testable. You start with a basic read-evaluate-print loop (a shell that accepts input and shows output), then gradually add evaluation, variables, functions, error handling, file loading, macros, and more. The final step results in an interpreter that can run mal written in mal itself, which is called self-hosting. This is a meaningful milestone in language design. What makes this project unusual is the breadth of languages it has been implemented in. The repository contains 89 different language implementations, covering everything from common choices like Python, JavaScript, Java, and Rust, to unusual ones like Bash, GNU Make, PostScript, PL/pgSQL (a database query language), LaTeX3, and NASM assembly. Each implementation follows the same 11-step structure, so you can compare how the same concepts look across very different languages. For anyone learning about interpreters, compilers, or how programming languages actually work under the hood, mal serves as a structured guided project rather than just a finished piece of software. A detailed process guide walks through each step with explanations and architectural diagrams. There is also a Discord community for people building or studying implementations. The README is primarily a reference index listing all implementations and their contributors. The full README is longer than what was shown.

Copy-paste prompts

Prompt 1
I'm working through step 3 of Make a Lisp in Python. I need to implement a REPL environment with def! and let*. Show me how to structure the environment as a dictionary with a reference to an outer scope.
Prompt 2
In the Make a Lisp project, what does self-hosting mean and why does it matter as the goal of step 11?
Prompt 3
I want to implement Make a Lisp in TypeScript. Walk me through setting up the step 1 read-eval-print loop with a basic tokenizer and reader.
Prompt 4
Help me understand how macros work in the Make a Lisp Lisp dialect and what I need to implement in step 8 to support quasiquoting.
Prompt 5
What is the difference between a special form and a regular function call in Make a Lisp, and how do I handle each case in the eval function?
Open on GitHub → Explain another repo

← kanaka on gitmyhub — every repo by this author, as a profile.

Verify against the repo before relying on details.