FNL

Sunday, 19 July 2026
AI Compiler FNL Programming Language

image

It All Started with "I Want a Compiler for..."

Building a programming language with an AI coding agent.

On June 10, 2026, driven by my long-standing passion for compilers and programming languages—and curious to see how far AI coding tools could take me—I opened OpenAI Codex and wrote a single prompt.

"I want a compiler for a programming language written in Go..."

The rest of the prompt described a compiler that would generate Windows x64 binaries from a tiny programming language supporting arithmetic, variables, a handwritten recursive descent parser, print(), and if/else.

The AI replied:

"I'll build this as a small Go compiler project from scratch: lexer, recursive descent parser, basic semantic checks, and Windows x64 executable output..."

That was the beginning of FNL (Farzan's Neat Language).

Compiler construction has fascinated me for many years. I have read books, watched talks, experimented with parser theory, and always wanted to build a compiler of my own. This project was less about creating a production language and more about exploring one of my favorite areas of computer science practically.

Looking back, I thought I was starting a coding project.

What I was really starting was a journey into programming language design.


AI Wrote the Code. I Designed the Language.

One point is worth making from the beginning. I did not write the compiler. Every line of Go code was generated by the AI. That does not mean I was a passive requester.

Throughout the project, I acted as the architect, language designer, reviewer, tester, and ultimately the person responsible for every engineering decision. I was not simply asking the AI to generate code.

I was making engineering decisions, and that was the interesting part.

The AI proposed implementations, challenged my ideas, suggested alternatives, and occasionally made assumptions of its own. Sometimes I accepted them. Sometimes I rejected them. Quite often, we spent considerably more time discussing a feature than implementing it.

The AI implemented the compiler.

I designed the language and directed its evolution.


Learning a Compiler by Building One

From the beginning, I deliberately constrained the project.

I specifically asked for a handwritten recursive descent parser because I wanted a compiler whose code I could comfortably read and understand. Parser generators are powerful, but they were not what I wanted to learn from.

Very quickly, I discovered that implementing the compiler was not the hardest part. Designing the language was.

Strings sounded like an easy feature until we started discussing them.

Should they be ASCII, UTF-8, UTF-16, or UTF-32?

Should string length mean bytes or Unicode code points?

Should comparisons be locale-aware?

Then came conversions.

Should assigning an int to a double happen automatically?

Should "123" become an integer?

How far should implicit conversions go before convenience becomes surprising behaviour?

None of these questions has a universally correct answer. Every decision simplifies one aspect of the language while complicating another.

Fortunately, FNL is still young. I do not have to worry about backward compatibility yet, so I can revisit earlier decisions whenever I discover a better design.


The Compiler Became My Laboratory

Eventually, I stopped testing the compiler with isolated snippets and started writing real programs in FNL.

The repository now includes a Hello World program, a Fibonacci sequence generator, a square root calculator, a π approximation, and a simple guessing game.

Those programs became much more than examples. They became the language's first users.

Almost every one of them revealed something missing.

While writing Fibonacci, I realised I needed break and exit().

While writing the guessing game, I discovered there was no random number generator, which later became math_random().

Later, I accidentally declared a variable named signed instead of sign. FNL accepted it, but the generated C backend failed because signed is a C keyword. Instead of leaking C restrictions into FNL, I introduced symbol mangling so backend names became independent from source names.

Over time, I realised that I did not really get to know my language while designing it. I got to know it while writing software with it.


"You Cheated."

One of the funniest moments came early in the project.

I asked the AI to generate Windows executables.

Instead of generating machine code directly, it quietly decided that the compiler should transpile FNL code to C11 and then invoke a C compiler.

My first reaction was simple.

"You cheated."

After thinking about it, I realised it was a sensible engineering decision.

The interesting part of this project was never the instruction encoding.

It was language design, lexing, parsing, semantic analysis, symbol resolution, and code generation.

Delegating the final machine code generation to mature C compilers allowed me to focus on the parts I wanted to understand.

Today, FNL supports MSVC, GCC, and Clang backends and can also emit LLVM IR directly.


More Than a Code Generator

Before starting this project, I thought AI would mainly save me from writing code.

It certainly did.

But that turned out to be only a small part of the story.

The AI did not teach me compiler design.

I learned compiler design by building a compiler with the AI.

Knowledge mattered throughout the project.

Without understanding compiler concepts, I would not have known to ask for a recursive descent parser, question a design proposal, recognise a flawed trade-off, or steer the language in a particular direction.

The AI accelerated the implementation dramatically. It never replaced engineering judgement.

If anything, this project convinced me that expertise becomes even more valuable when an AI can implement ideas almost instantly.


Where FNL Goes Next

FNL is still a small language.

There is plenty left to build.

  • Functions
  • Structs and user-defined types
  • Arrays
  • A richer standard library
  • A built-in linter
  • Better debugging support
  • File I/O

One day, I also hope to reach the milestone many language designers dream about:

Bootstrapping.

Writing the FNL compiler in FNL itself.

There is still a long way to go before that becomes realistic, but it gives the project a clear direction.


Final Thoughts

I started this project because compilers have always fascinated me.

I expected to learn about lexers, parsers, ASTs, semantic analysis, and code generation.

I did not expect to spend so much time thinking about Unicode, type conversions, debugger design, standard library architecture, symbol mangling, and language philosophy.

Looking back, the biggest lesson was not technical.

It was that AI works best as an implementation partner, not a replacement for understanding.

The compiler may have been written by AI.

The language was shaped one engineering decision at a time.

If you are interested in compilers or language design, I hope you find FNL as enjoyable to follow as I found it to build. The source code and example programs are available in the project's Git repository, and I would be happy to hear your thoughts or suggestions.

If this project sparked your curiosity, you're welcome to explore the source code on GitHub. The repository contains everything related to FNL, including the compiler itself, the example programs, and the design notes that document its evolution.

The examples folder contains sample FNL programs, while PROJECT_NOTES.md covers the technical aspects of the compiler, including the language's reference grammar in both BNF and EBNF notations. If you're interested in how many of the design decisions came about, FNL_R_AND_D.md is a journal generated from my conversations with the AI throughout the project.

Top