“I looked at the compiler’s output and thought: this cannot be mine. I couldn’t believe what had happened. I am happier than I have been in 20 years.”

Prologue: A Seed Planted Thirty Years Ago

In the late 1980s and early 1990s, I was a student, and I built my first Pascal compiler. It was based on PascalS from ETH Zürich. While it was a modest academic project, something happened to me during that time — I fell in love with the intricate puzzle of transforming human-readable code into something a machine could execute.

Then life happened. Career. Responsibilities. Decades passed.

By 2023, I had been working in IT for over 30 years. I was successful by most measures. But I felt empty. My profession no longer provided what I craved: innovation. I had always seen myself as a creative person, and that creative part of me was starving.

I didn’t know it yet, but I was searching for something. And I was about to find it.


Chapter 1: The Spark

It started with a small book.

I had begun studying compiler construction again — partly out of nostalgia, partly out of a nameless hunger for something new. I worked through materials from McGill University, from a Danish university, from the Hasso Plattner Institute in Germany, and of course from ETH Zürich.

Then I discovered a thin volume about PL/0, a minimalist teaching language created by Niklaus Wirth.

Who Was Niklaus Wirth?

Niklaus Wirth (1934–2024) was one of the giants of computer science. A Swiss professor at ETH Zürich, he created languages that shaped how generations of programmers think: Pascal (1970), Modula-2 (1978), and Oberon (1987). He won the Turing Award — the “Nobel Prize of Computing” — in 1984.

His philosophy was radical simplicity. He believed that understanding comes from building things that are complete but small. Not toy projects that cut corners, but real systems stripped to their essence.

PL/0 was his teaching language for compiler construction. It had only a handful of keywords, no complex features, but it contained the complete essence of a compiler: lexical analysis, parsing, symbol tables, code generation. Everything a compiler needs, nothing more.

When I opened that book in 2023, something clicked. I didn’t just see a teaching exercise — I saw a path. A dream began to form: what if I could build a compiler that generates real machine code? Not a toy. A real compiler.

I chose Go as my implementation language and VS Code as my editor. I created an empty directory and started typing.


Chapter 2: Two Traditions — Pascal vs. C

As I dove deeper into compiler construction, I realized I was stepping into a story much larger than myself. A story about two competing visions of what programming should be.

The European tradition: In 1970, at ETH Zürich, Wirth created Pascal. Clarity above all. Strong typing. Structured programming. Code that reads almost like prose. Pascal became the teaching language of choice for decades. Millions of students — including me — learned to program with it. Turbo Pascal dominated the PC era. Delphi carried the torch into the Windows age.

The American tradition: Two years later, at Bell Labs, Dennis Ritchie created C. Efficiency above all. Direct hardware access. Minimal abstraction. C was designed to rewrite UNIX. It wasn’t meant to be pretty; it was meant to be powerful.

Here’s the uncomfortable truth that took me years to fully accept: C won. Despite Pascal’s elegance, despite its educational value, despite Wirth’s genius — C became the foundation of modern computing. Linux, Windows, macOS, PostgreSQL, the Python interpreter, nginx, your car’s firmware — all C or C++. The TIOBE Index ranks C among the top three languages after five decades.

Why? Because in systems programming, performance trumps clarity. When you’re building an operating system kernel, you need control over every byte.

As I studied compiler construction in 2023, I found myself caught between these two worlds. I loved Pascal’s clarity. But I respected C’s power. Could there be a bridge? Could a language have Pascal’s readability and C’s efficiency?

I didn’t have an answer yet. But the question lodged itself in my mind.


Chapter 3: Building Piece by Piece

I worked on the compiler alongside my regular job, stealing hours where I could. Piece by piece, it grew.

The scanner came first — the component that reads raw characters and groups them into tokens. When it sees var count := 42;, it produces KEYWORD:var IDENTIFIER:count OPERATOR::= NUMBER:42 SYMBOL:;. Sounds simple; it’s not. Comments, string literals with escape sequences, Unicode, error recovery — I spent weeks on the scanner alone.

The parser came next — building structure from the token stream, understanding that 42 + x * 3 means “multiply x by 3, then add 42.” I implemented a recursive descent parser, where each grammar rule becomes a function. Elegant when it works, maddening when it doesn’t.

The symbol table tracked every declaration. The Abstract Syntax Tree and Semantic Analyzer separated a serious compiler from a simple one.

But there was a problem. I didn’t trust myself to write a machine code generator for AMD64. The x86-64 instruction set is enormous, baroque, filled with historical baggage from the 1970s. So I took a different approach: I built a CPU emulator. My compiler would generate code for this virtual machine, and I could test everything without touching real hardware.

The emulator grew more sophisticated. Its output began to look suspiciously like real Intel assembly code.

I didn’t realize it then, but I was setting the stage for something unexpected.


Chapter 4: The Night Everything Changed

I remember that night vividly. My emulator generated output that looked like this:

    mov     rax, 42
    push    rax
    mov     rax, [rbp-8]
    pop     rbx
    add     rax, rbx

The assembly shown above is from those early days — a naive stack-based approach using push and pop to shuttle values around. The code Mica emits today is far beyond this and avoids dynamic stack manipulation entirely.

This is almost valid Intel x86-64 assembly. My emulator executed this internally, simulating a CPU. But the syntax was so close to real assembly that I wondered — what if I just fed it to a real assembler?

I installed GCC on my Ubuntu machine. I took the assembly output from my compiler and fed it to the GNU Assembler (as). Then I linked it with the GNU linker (ld).

I ran the resulting binary.

It worked.

I ran another example. It worked. I ran all my PL/0 test programs. They all worked.

I sat there in the middle of the night, staring at my screen, trying to process what had just happened. My compiler — my hobby project built from an empty directory — was generating real, executable Linux binaries.

That was Spring 2025. That was the breakthrough.


Chapter 5: A New Name, A New Identity

After that night, everything accelerated. I refactored the compiler fundamentally — implementing a proper AMD64 code emitter, restructuring the entire architecture. And I realized: this wasn’t PL/0 anymore. This was something new.

Following the tradition of Linus Torvalds, I derived a name from my own first name, Michael: Mica. Beyond the personal connection, mica is also a mineral — known for its layered structure, its transparency, its resilience.

The question that had been growing in my mind came roaring back: could a language have Pascal’s readability and C’s efficiency?

The answer was the System V AMD64 ABI.

I could have invented my own calling convention. Many academic compilers do. Instead, I decided to implement full compliance with the standard Linux calling convention — arguments in registers RDI, RSI, RDX, RCX, R8, R9 for integers, XMM0-XMM7 for floating point, proper stack frame layout with 16-byte alignment.

The payoff: zero-overhead C interoperability.

import
    printf from "libc";
    sin, cos from "libm";

var x := sin(3.14159);
printf("Result: %f\n", x);

This calls the actual C library functions — the same functions that GCC-compiled code calls. The CPU doesn’t know or care that the caller was written in Mica. And it works both ways: C programs can call Mica functions. You can link Mica and C object files with the standard linker.

I then implemented DWARF v5 debug information — the latest standard — enabling professional debugging in VS Code and GDB. You can set a breakpoint in C code, and when it calls a Mica function, the debugger steps into the Mica source. Cross-language debugging with a transparent boundary. This is rare for any language, let alone a solo project.


Chapter 6: Into the Valley

Summer 2025. Autumn 2025. The darkest period.

Functions and procedures existed, but they couldn’t take parameters. No arguments. Nothing passed in, nothing passed out. This might sound minor. It’s not. Parameter passing is the backbone of any useful language.

For Mica, it was especially hard because of nested functions. Like Pascal, Mica supports functions defined inside other functions, with access to enclosing scope variables. This requires static links — pointers chaining stack frames together. The compiler must determine which functions access enclosing variables, pass links implicitly alongside regular arguments, generate code following link chains at arbitrary nesting depth, and make all of this work with recursion. While remaining ABI-compatible with C.

The compiler stopped working. Not partially — completely. Every compilation ended in a crash. For weeks, I couldn’t produce a single working binary. I had lost control of my own creation.

I want to be honest: there were moments when I sat in front of my computer and felt like a complete failure. Thirty years of IT experience, and I couldn’t make this work.


Chapter 7: The Quality Offensive

I declared war on instability with three pillars.

Nil-less types. I overhauled the entire type system to eliminate null pointer issues. Pointers are either guaranteed valid or explicitly marked as possibly-nil. The compiler enforces this. Massive change — every data type, structure, and function signature reviewed and hardened.

Quality gates. Validation checkpoints between compilation phases. The AST must be valid before intermediate code generation begins. The IL must be valid before the emitter touches it. Each component makes promises to the next; the gates verify those promises. When something breaks, you know exactly where to look.

AI assistance. I leaned on Claude and ChatGPT to analyze errors, review code, explain concepts. The project was bigger than my ego. Accepting help doesn’t diminish the achievement; it enables it.

Week after week, I fixed bugs. Improved error handling. Strengthened validations. Gradually, crashes became rare. Then rarer. Then the exception.

Parameter passing worked. Nested functions worked. Recursion worked. C interoperability worked.


Chapter 8: From Compiler to Platform

The compiler was stable, but limited to single-file compilation. I began another restructuring: a multi-file compilation pipeline, GNU binutils integration, cross-file symbol resolution, and static library creation.

From this emerged what I consider one of Mica’s most elegant features — the unified Import Declaration:

import
    printf, scanf from "libc";
    sin, cos, tan from "libm";
    myHelper from "helpers";
    getpid, fork, exec from "posix";

One syntax. Any source — another Mica file, a Mica library, or any C library in existence. The entire POSIX ecosystem and Linux system API became accessible to Mica programs with zero friction.

When I released version 4.0.0 and looked at what Mica could do — multi-file projects, static libraries, full C interoperability, DWARF v5 debugging, cross-language debugging, VS Code integration — I thought: this cannot be my compiler.

A single developer, working part-time, building a complete compiler platform from scratch? With native code generation and full ABI compliance and debugger support?

And yet, here it was.


Chapter 9: What Mica Is Today

At the end of 2025, my wife and I founded Mica Development UG. This wasn’t just about the compiler anymore — it was about building something that could grow.

Mica today is approximately 45,000 lines of Go code with zero external dependencies. It generates native x86_64 binaries via the GNU toolchain. It has a VS Code extension, comprehensive tutorials, video documentation, and a growing ecosystem.

The roadmap reaches into 2027: structs, arrays, memory and pointer safety, automatic memory disposal, SSA based optimization, AI-native data types, ARM64 support, macOS platform, and much more.

We chose a green dragon as the logo — symbolizing sustainable computing. Every line of code has an environmental footprint. Mica’s direct compilation to native assembly, zero-overhead interoperability, and absence of garbage collection mean programs run faster with less energy. No interpreter tax. No JIT warm-up. No GC pauses.


What This Means to Me

Building Mica taught me things I want to share.

It’s never too late. I started this project in my late fifties, after thirty years in IT. The conventional wisdom says you should be winding down. The conventional wisdom is wrong.

Obstacles exist to be overcome. I nearly quit multiple times. The parameter passing implementation broke me. But “nearly” is not “actually.” Stubborn persistence matters more than talent.

One person can do more than you think. Modern tools are extraordinary. A single developer with Go, VS Code, and determination can build what once required a team.

The journey matters as much as the destination. Yes, I built a compiler. But I also rediscovered creativity. Rekindled passion. Found fulfillment. The compiler is wonderful, but the transformation is priceless.


Technical Summary

ParadigmStatically typed, compiled, procedural
InspirationPascal clarity + C efficiency
Type SystemStrong with type inference
StringsUTF-8 and UTF-32 support
Nested FunctionsFull lexical scoping with static links
C InteropZero-overhead, System V AMD64 ABI compliant
Compiler~45,000 lines of Go, zero external dependencies
Targetx86_64 Linux (native assembly via GNU toolchain)
DebuggingDWARF v5, GDB, VS Code

Resources


Timeline

1980s-90s     First Pascal compiler (student project at ETH Zürich)
   ↓
30 years      Career in IT
   ↓
2023          Rediscovery of PL/0 — the journey begins
   ↓
Feb 2024      v1.0.0 — First working compiler
   ↓
Mar 2024      v2.0.0 — AST architecture, semantic analysis
   ↓
May 2024      v2.2.0 — Enhanced emulator
   ↓
Mar 2025      v2.3.0 — CFG foundations
   ↓
Spring 2025   THE BREAKTHROUGH — Native code generation works
   ↓
Aug 2025      v3.0.1 — Full x86_64 support, DWARF debugging
   ↓
Late 2025     v4.0.0 — Multi-file support, import system
   ↓
2025-2026     Mica Development UG founded
   ↓
2026-2027     The road ahead

If you have a dream you’ve been putting off — something that seems too big, too late, too impossible — I hope this story encourages you. Start anyway. You might surprise yourself.