I Built a Programming Language Called Zen
Building a programming language had been something I wanted to do for a long time.
What I didn't realize when I started was how much work exists beyond parsing a few tokens and generating some code. A language is not just a parser or a compiler backend. It is tooling, developer experience, documentation, installation, error handling, runtime support, and countless design decisions.
After multiple attempts and many lessons learned, I'm excited to share Zen.
Why a Third Attempt?
Zen is not the first language project I started.
My first attempts taught me a lot, but they never reached a stage where I felt comfortable sharing them publicly. The architecture was incomplete, important components were missing, and the overall developer experience wasn't where I wanted it to be.
Instead of abandoning the idea, I kept iterating.
Each attempt helped me better understand:
Compiler architecture
Language design
LLVM
Runtime integration
Tooling and usability
Error handling
Project structure
Zen is the result of those lessons.
What Is Zen?
Zen is a programming language with its own compiler pipeline and LLVM-based backend.
The goal was not just to generate code, but to create a complete language ecosystem that developers can actually install and use.
Zen currently includes:
Lexer
Parser
AST generation
LLVM IR generation
Native executable generation through LLVM
Runtime integration
Standard library integration
Command-line tooling
Installation system
Documentation website
Compiler Pipeline
The compilation process follows a traditional compiler architecture:
Source Code
↓
Lexer
↓
Parser
↓
AST
↓
LLVM IR Generation
↓
LLVM Optimization
↓
Object Files
↓
Native Executable
LLVM handles optimization and machine code generation, allowing Zen to produce native binaries.
Command Line Interface
Zen provides several commands for development and inspection:
zen run
zen build
zen ir
zen ast
zen tokens
zen clean
This allows users to inspect different stages of compilation while also supporting normal build and execution workflows.
Installation
One of my goals was making the language easy to install.
Zen can be installed with a single command:
curl -fsSL https://raw.githubusercontent.com/Jishith-dev/Zen/main/install.sh | bash
The installer:
Checks required dependencies
Downloads Zen
Builds runtime components
Builds standard library objects
Sets up the CLI
Documentation
A language is only as useful as its documentation.
I spent significant time building documentation and a dedicated website so that users can quickly understand the language and get started.
Documentation:
Website:
Challenges
Building Zen involved solving many problems that are easy to underestimate:
Designing compiler architecture
Managing LLVM integration
Runtime linking
Module handling
Error reporting
Cross-platform installation
Documentation structure
Developer experience
Many of these challenges were not obvious when I started.
What I Learned
The biggest lesson was that building a programming language is much more than code generation.
A usable language requires:
Consistent design decisions
Good tooling
Clear documentation
Reliable installation
Helpful diagnostics
Iteration and patience
The compiler itself is only one piece of the overall system.
What's Next?
Zen is stable, but there is still plenty to improve.
Planned future work includes:
Testing framework support (zen test)
Built-in examples (zen example)
Better diagnostics
Additional language features
Tooling improvements
Performance enhancements
Final Thoughts
This project started as an experiment and evolved through multiple iterations before becoming a complete system.
Creating Zen taught me more about compilers, tooling, architecture, and software engineering than I expected when I began.
If you're interested in programming languages, compiler development, or LLVM-based systems, I'd love to hear your feedback.
Links
Documentation: Zen Documentation
Website: Zen website
GitHub: github
Top comments (9)
the
reactivedirective (equivalent of computed in "Web Signals") is the best idea ever, I just wonder how anyone can observe such reactivity to hook itself into possible changes (sensors data, cache invalidation, you name it) ... that bit on the main Website / README would be greatly appreciated, thank you!Thanks you 👍
In Zen, reactivity is handled at compile time using a dependency graph. The compiler figures out dependencies and generates explicit update logic in the IR, instead of runtime observation.
Building a language is one of the best ways to learn where the magic in normal tools actually lives. Even a small interpreter forces you to make decisions about syntax, errors, scope, and tradeoffs that most of us only consume indirectly through other people's languages.
Absolutely. Building a programming language teaches far more than syntax and logic. It forces you to think about semantics, scope, error handling, and architecture from the ground up. It also takes a lot of patience and iteration to get right.
By the way, have you tried my Zen language yet? It's available on Linux at the moment. I've kept v1 intentionally simple, and Windows support will be coming soon.
Exactly. The syntax is almost the easy part. The real learning starts when you decide what an error should mean, how scope should behave, and what tradeoff the runtime is allowed to make. That is why small language projects teach so much about the larger tools we use every day.
Congratulations! I tried my hand at making my own programming language back in the 1990s, with the Dragon Book in hand. I learned a couple valuable lessons: 1) it's hard, and 2) if it becomes successful, it's a full time job.
Fortunately for me, I gave up after 6 months. It was a bigger committment than I could dedicate enough time to.
But even more fortunate for me, about 3 months after I gave up, I stumbled across another language that was already complete, and was 95%+ similar (both semantics and syntax!) to what I was trying to achieve.
Talk about having my dream handed to me on a silver platter!
That programming language is the D programming language, by Walter Bright. Later joined with Andrei Alexandresu for D 2.0. Still one of my favorite languages (along with Python, F#, Lua, and Elm).
For anyone who wants to try their hand at making their own language, take heart that Rich Hickey's Clojure was his fifth language attempt. Niklaus Wirth made nine languages, and an untold number of experimental languages that never saw the light of day.
(I'm also sending out good vibes to Jeaye Wilkerson who is working on Jank programming language. Godspeed, Jaeye!)
Thank you for the encouragement .Those references are really motivating.
In my case, lack of access to a laptop never stopped me. Started with a quick prototype in browser JS, then moved to Node.js on my phone using Termux as the CLI environment and SpckEditor and Acode as my IDE. That's where Zen was actually built.
This is my third attempt and Still a lot ahead but glad it's out here
This is an impressive achievement—building a full programming language, compiler pipeline, and developer ecosystem from scratch is no small feat. I really appreciate how you emphasized tooling, documentation, installation, and developer experience alongside the compiler itself. Too often, language projects focus purely on parsing and codegen, but Zen demonstrates the importance of a complete ecosystem for adoption.
I’d love to collaborate or exchange ideas, particularly around LLVM integration, runtime linking, cross-platform installation, and diagnostics tooling. Exploring testing frameworks, built-in examples, or language feature extensions together could accelerate Zen’s maturity and real-world applicability.
Would you be open to discussing collaboration or sharing insights on improving language usability and developer workflows?
Thank you! Zen is completely open source, and all compiler, runtime, tooling, and documentation code is available on GitHub.
GitHub: github.com/Jishith-dev/Zen
I'd be happy to discuss ideas around LLVM integration, tooling, diagnostics, and language design. Feedback and contributions are always welcome.