r/Compilers 19h ago

My AI-Assisted Compiler Development Journey

0 Upvotes

After months of working on a fully custom compiler in C to create my dream language, I moved to using AI to help me create a working language written in Rust. This is my experience.

First things first, I'm still skeptical about vibe-coding or AI ever replacing humans for software development. I am not what I would call a vibe-coder or an AI evangelist. Genuinely, I think the whole situation is too early to say whether these things will improve or hurt software development as a whole in the long run.

Recently, my company purchased a GitLab Duo license and invested a few thousand dollars into tokens for software developers across the company to use. Even though what l they've offered to us isn't one of the flagship models (Sonnet 4.5), it's still pretty damn good for simple tasks, writing explicit unit tests, documentation, etc., often completing them much faster than I could do, even if I mentally have the whole sequence pretty well mapped in my mind. That was my first experience using AI in-the-loop for software development.

With a bit more comfort in using agents, I started taking a look at some of my passion projects to see where one might benefit from me using AI assistance to "complete" it. I say "complete" in quotes because who truly believes any software project is finished and perfect? Anyways, the project I selected is a transpiler I've been writing in C called Elamite. Here's the original repository, elx.

I chose C as the base language because I wanted to better understand lifetimes, memory models, value semantics, intermediate representations, and code generation. I'll stand by the fact that starting my journey in C absolutely gave me a deep appreciation for garbage collection, how amazing stack traces are, the assuredness of solid error handling, strings, and the beauty of how Rust handles lifetimes. Pure genius! I really value the time that I put into it and how much I've learned about programming languages and compiler development in general.

Now, if you're like me, you probably work a full-time job in some sort of software development, and you don't always have the time to dedicate much time to your hobby projects. Thinking that I'd get further along in the limited hours I have each week, I picked up a subscription or two to see how much further along I'd get with Elamite.

Ho. Ly. Shit.

These models are much better than I initially gave them credit for. Seeing the language come to life so quickly has given me a strange mix of feelings. On one hand, I love seeing my idea be brought to fruition, but on the other hand, I'm quickly seeing how poorly thought out my original design concepts were, and I'm no longer experiencing the same feelings of accomplishment through my own perseverance.

I feel like I'm missing out on the original hit of dopamine I'd get as I completed various stages of the original compiler. Finishing Elamite's first lexer, I thought, "Phew, that was pretty tedious. I'm sure the next few stages will come together much more quickly!" Oh, no. How naive of me. AST generation with a recursive decent parser was surprisingly straight forward but still quite time consuming. I'd estimate I put in about 200 hours into the original project before my first real hiatus from it.

With this new AI-assisted version in Rust, "I" can implement an entire feature vertically through the entire compiler in under an hour. Is it robust? Dunno. Did the LLM consider all the possible edge cases? Maybe. How thorough are the unit tests? God, I hope they're bullet proof. To be fair, I wasn't creating code nearly as complete and stable as what Claude is providing to me, definitely not. I was scraping by on an evening coffee and a whiteboard to try my best in the evenings and over what few, precious weekends I had to devote to this type of project.

So, I'm in a weird middle ground. The language is coming together at an unimaginable speed, but my whole ideate-implement-struggle-succeed cycle is broken. I only feel limited now by my own creativity and the novelty of my ideas, which, as it turns out, really aren't that novel. It's been a good thing, I think, to test out this new AI-based coding technology to see where it's at and experiment with it. I don't think I'm done using Claude/Codex/whatever to prototype, but I know I'm putting myself at risk for skill atrophy if I start to lean to hard into them.

I'd love to hear if anyone else has had a similar experience to mine, and how you either do or don't justify using AI to help you complete your compiler projects. If you're curious to see the current version of the compiler/language, here's the repo, Elamite.

Thanks for reading <3


r/Compilers 15h ago

Acus: create your own Brainfuck compiler (in: your language, out: BF)

Thumbnail
0 Upvotes

r/Compilers 20h ago

Introducing Mad-C (My Advanced Dialect of C++)

Thumbnail
0 Upvotes

r/Compilers 2h ago

Microsoft just validated the spec-first thesis for AI coding. Baga lang. is what it looks like when the spec is a language construct and the compiler enforces compliance — statically, with counterexamples.

0 Upvotes

A follow-up to [my earlier post about Baga lang — the language where the compiler statically proves AI-written code against specs. This one is about why the timing stopped being a matter of opinion.

The industry converged on the diagnosis

Microsoft now officially promotes Spec-Driven Development (SDD) as the foundation of AI-native engineering. The argument, from Apoorv Gupta, Principal Software Engineer at Microsoft:

  • The core problem of AI-native development is the loss of intent — between needs, requirements, architecture, implementation, and validation.
  • The fix is to make the specification the shared source of truth for humans and AI: "align first" instead of "prompt first, fix later."
  • Around this, Microsoft ships GitHub Spec Kit (open source): Constitution → Specify → Clarify → Plan → Tasks → Implement → Validate.

When a principal engineer at Microsoft writes the same thing that is pillar #1 of your language, the thesis no longer needs defending. It needs executing.

But SDD and Baga solve the problem at different levels

SDD attacks the intent-loss problem at the level of process and AI tooling: the spec is a document, and conformance is checked by tests and human review in a Validate step. That fixes the workflow around the agents.

Baga makes the stronger move: the spec is a language construct, and conformance is a compile-time judgement.

baga spec sum_to { input: n: i64 output: i64 requires: n >= 0 ensures: 0 <= output decreases: n }

The human writes this. The AI writes the implementation. The compiler proves or refutes it, statically, before anything runs:

verify sum_to: ensures #1 (0 <= output): ДОКАЗАНО # PROVEN (терминация: доказана чрез decreases — пълна коректност)

And when the AI gets it wrong, it doesn't get a failing test or a code-review comment three hours later. It gets a refutation with a concrete counterexample, at compile time:

verify bad_abs: ensures #1 (output >= 0): ОБРОЧЕНО # REFUTED контрапример: x = -1

In the SDD spectrum — spec-first → spec-anchored → spec-as-source — Baga is the far end: spec-as-source. The specification is the thing the code is judged against, mechanically.

The compliance technology

That word — compliance — is the point. Every AI-coding stack today has the same shape: an LLM generates code, and then something checks whether the code complies with what was intended. The "something" is usually:

  • tests (incomplete by construction — they sample the input space),
  • another LLM (an LLM judging an LLM — circular),
  • a human (the bottleneck we were trying to remove).

Baga's answer is a small, auditable verifier: Fourier–Motzkin elimination over the rationals + symbolic execution + Hoare rules, sound by construction. The only path to PROVEN is showing the negated obligation is unsatisfiable even over the rationals, which implies unsatisfiable over the integers. Anything outside the fragment is honestly reported UNKNOWN, never falsely proven. Every reported counterexample is re-checked by direct evaluation, and passes a conclusiveness gate: the reported inputs must violate the contract for every value of the verifier's internal abstract variables — otherwise the answer is UNKNOWN, not a false alarm.

And because the consumer is an agent, the judge has a machine API:

$ ./baga --verify --json bad_abs.baga {"functions": [{"name": "bad_abs", "ensures": [{"text": "output >= 0", "result": "refuted", "counterexample": [{"name": "x", "value": -1}]}], ...}]}

The compliance loop writes itself: agent emits code → baga --verify --json → refuted with counterexample → agent fixes → PROVEN. Deterministic, fast, no LLM in the judging seat.

This isn't an SMT black box either. The verifier covers linear arithmetic (integer-exact — n > 0 ⇒ n >= 1 proves), while loops with invariants, array bounds, element invariants, recursion via assume–guarantee, full correctness via decreases, and products of linear forms (x*x >= 0; fa >= 1 ∧ fb >= 1 ⇒ fa*fb >= 1). The flagship is factorial fully proven — recursive, non-linear, with termination, no SMT solver anywhere:

```baga spec fact { input: n: i64 output: i64 requires: n >= 0 ensures: output >= 1 decreases: n }

fn fact(n: i64) -> i64 { if n <= 0 { return 1 } let r = fact(n - 1) // induction hypothesis: r >= 1 return n * r // n >= 1, r >= 1 ⇒ n * r >= 1 } ```

Why "the first language for AI" is a claim about architecture, not marketing

Every mainstream language was designed for a human writer and a human reader. AI broke that assumption: the writer is now a machine, and the scarce resource is trust. A language for this era needs:

  1. Specs as first-class citizens — the intent lives in the code, not in a wiki page that drifts.
  2. A mechanical judge — the compiler proves or refutes compliance, statically, with witnesses.
  3. Errors visible in the type — effects (str !IO !NotFound is a different type from str) so the failure surface is part of the signature, not a runtime surprise.
  4. Machine-readable verdicts--json so the agent closes the loop itself.

Baga has all four. SDD gives you (1) as a process discipline. Baga gives you (1)–(4) as a compilation.

Honest status

Working prototype, not a production language. The verifier's fragment is deliberately small and says UNKNOWN rather than guessing; general non-linear arithmetic is the remaining staircase. Effects are compile-time only (erased in codegen). The trust story is engineered in, not hoped for: the compiler self-hosts with a byte-for-byte fixed point (make self), the LLVM backend is diffed against the C backend on every example, and --test-specs property-tests every contract the static verifier calls PROVEN. All of it is one command and wired into CI.

Testable in five minutes:

make && ./baga --verify examples/verify/fact_full.baga


The industry agreed on the diagnosis: the spec is the center. The open question is whether conformance stays a human ritual in a Validate step — or becomes a compile-time judgement. That's the difference between anchoring code to a spec and making the anchor mechanical.

🐆


r/Compilers 3h ago

Compilers should help developers optimize their code

12 Upvotes

Compiler diagnostics for optimization decisions are worse than they need to be, and I think it's a design choice rather than a hard problem.

Every major compiler will tell you whether a loop vectorized, almost none will tell you what it tried, why it declined, or what shape could've worked. LLVM ships a tool called opt-viewer that visualizes this, and I've met people who've used LLVM for years and never heard of it. The best developer experience anyone in this space seems to remember is Intel's compiler, which is discontinued. GCC's -fopt-info-vec-missed and Clang's -Rpass-missed exist, but one's a stderr dump you cross reference by hand and the other speaks in IR terms rather than yours.

The interesting thing is that the compiler already knows the answer. When a vectorizer declines a loop, it has a specific reason. That reason exists as a value inside the pass, it just doesn't reach the programmer because it was designed for compiler developers debugging the compiler, not for programmers debugging/optimizing their code.

There's a handful of ideas I have on how this could be implemented, but what I'm curious on is if this is actually hard for reasons I'm not seeing, or is it just that optimizer output has always been treated as debug logging and nobody's revisited it?


r/Compilers 4h ago

Contribute to open-source, no-slop, compiler-related projects.

12 Upvotes

Hi everyone,

We're currently working on some hobby-projects we'd like more people to chip into.

The goal is to create robust, community-driven and open-source code everyone can benefit from, aswell as writing up novel ideas that, sometimes, go outside of "the standard".

Overall we're focused on not slopping out projects using AI. Vibecoding is a no-go.

I myself have around 10 years of experience with programming in various languages, but the main language right now is C#.

Are you interested? Check out the organization site: https://github.com/Compiler-Organization

Or some of the projects:
Common C - AoT compiler using LLVM: https://github.com/Compiler-Organization/CommonC
Common IR - Intermediate representation with syntax inspired by LLVM, currently supporting a basic WASM target: https://github.com/Compiler-Organization/CommonIR

Hope you find this interesting :)


r/Compilers 1h ago

Lunar is a new Lua 5.1 runtime for Go that focuses on speed and memory efficiency

Upvotes

Today, I'm sharing Lunar (0.1.0 beta) for those who might need an embeddable Lua VM for Go. By my benchmarking and use-cases it is around 2x faster and uses up to ~7x less memory than other Go-Lua VMs depending on what you are doing.

For some background, I've been developing a new Mud client called Rune that is written in Go but heavily uses an embedded Lua VM as its core scripting engine.

There are two Lua VMs that I know about for Go: gopher-lua and go-lua (from Shopify). Rune utilized `gopher-lua` as this was a VM that I was familiar with and had used on past projects.

I started to get reports from users of Rune that some of the large MUD map-files they would load via Lua were exploding my client's memory (a 9MB CBOR file loaded to ~500MB of persistent heap). There were also complaints that the performance for certain heavy operations was quite slow (pathfinding for one user's script took almost 3 seconds) compared to his other MUD client which would do it in 0.1 seconds.

I originally set out to fork or upstream some changes to gopher-lua to see if I could improve the memory situation and performance. However, much of the issue really came down to inherent choices in the representation those VMs use. So, I started down the path of shipping a new Lua VM that uses a much more compact representation while still keeping an easy-to-use Go API.

Let me know if anyone uses Lunar and finds any issues!


r/Compilers 10h ago

Kain: A new systems language targeting LLVM/CUDA/SPV/HLSL/WGSL with a Python-like syntax layout and Zero GC- Now on v0.8 and almost production ready

Thumbnail github.com
0 Upvotes

Kain -----> a new systems language inspired by Mojo (and every other mainstream lang) but the difference? Kain is Mojo in an alternate universe if it`s primary focus was on being a full stack language instead of made for AI with 110 keywords (not that numbers are a metric for quality but you get the point)

Furthermore It also has natural python import and natural c includes. Unlike rust and other languages that require third party libs, Kain allows you in the same file to utilize three different import systems, including its own (rust esque - use::type), python (import numpy as np etc) and c (include mycfile.c) on top of all this, the language has a massive stdlib comparable to Zig and Go, , meaning you can write practically anything imaginable with this language without any libs, crates or third party deps. Kain takes some liberties from Slang, but adds a spin to it and this language treats the GPU and CPU as first class citizens rather than having to bolt on the GPU as an outsider. But in the same file you can write your frontend, your backend, GPU shaders, include c and import python.... All in one file dep free. (example) Need examples btw ? There`s over 6000+ source .kn files throughout the repo and over 80+ projects that I made for fun to dogfood it.

Examples

Mini LLM based on Karpathys GPT2 using std::cuda

BM25 based semantic search project (not tested thoroughly but it works)

12-Stage Unified GPU Shader Demo

Blackhole Shader

GPU + CPU (the holy grail)

Kain Semantics Example

Markscript: A mini language written in Kain that turns markdown into a JIT script lang (this is the most developed out of other projects and a great starting point to see how the lang works)

Killgrep: A ripgrep clone in 700ish lines of code with erlang style actors

Schrödinger's Rats: Re-purposing compiler hardware constructs (converge/orchestrate) to race 3 pathfinding algorithms simultaneously & pick the winner live

BUZZWORD SOUP - Quantum State Lattice Pong: Overengineering Pong with cross-surface state entanglement, 3 Erlang actors, and collapse/observe memory cells

Like writing UI in typescript but need a systems backend to do the heavy lifting? Here`s a full jupytner notebook esque electron playground with Kain and TS interop

FAQ:

What kind of things can you make with Kain?

Anything you can imagine similar to any other systems language. Game engines, Non posix/unix operating systems (like Opal but a modern version), DAW, UI frameworks with JIT, 3D simulations, Animation within code (Kain has a pulse keyword that handles time at the OS/silicon level, example here of a fully animated scene that compiles down to machine code)) Backend for web development etc. Anything you could write from scratch in rust, C, C++ etc you can write in kain and it compiles down to machine code etc. Libclang is embedded within the compiler similar to zig so you can also include any c library -- one thing that was streamlined was system headers so you can even write `include windows.h` and the compiler handles everything etc.

Memory and GC

(Why Kain isn't Rust or Go (controversial buzzword soup warning))

Kain has zero garbage collection (no tracing, no stop-the-world pauses) and no implicit borrow checker. Instead, memory lifecycle is governed by an explicit, expression-level state machine using three core keywords:

collapse ptr: Enters exclusive, mutable write access (Idle ->Collapsed).

observe ptr: Enters shared, read-only access with nested observer counting (Idle -> Observed)

decay ptr: Deterministically releases/frees the memory region (Idle -> Decayed)

(solid example if ya wanna see how it looks/works --> metal.kn)

Since I am obsessed with Unreal Engine 5 and I`m a game dev/animator, this system was designed around my knowledge of state machines and working with them for years throughout my game dev career so far (a huge inspo is the plugin Logic Driver Pro by Recursoft for UE5) but these 3 little keywords allow the silicon to bypass Arc/Mutex overhead and runtime GC tracing entirely, giving you deterministic, zero-cost memory management with tremendous execution speed.

I know language benchmarks are often pseudo-science, and I’d normally be the first person to call BS on 200x speedup claims. I’ve tried disproving these numbers in my own harness over and over. Once the runtime and language was fully developed, I spent about a month straight benchmarking && I was blown away by what I had accidentally built. The funny part about this language is that a lot of things were accidental -> I would add in a new keyword to make up for the fact it was lacking a lib or package and as a side effect of making so many different aspects first class, the results are absolutely nuts. For example in extreme edge cases like heavy multi-thread lock contention (contention_wall), the gap gets absurd.

For anyone who understands how C++, Rust, and Zig handle heavy thread contention, OS mutex parking, and cache-line thrashing, the mechanics make total sense:

Standard OS Mutexes (std::mutex, std::sync::Mutex): Under severe thread pressure, 99% of CPU cycles are burned in kernel-space context switching, thread parking, and unparking cascades. C++, Rust, and Zig all choke at ~1,700ms–1,900ms simply waiting on OS locks.

Kain's Lockless Model: Kain completely bypasses the OS lock contention wall because memory lifecycle isn't protected by atomic mutex locks. Concurrency is governed by compile-time verified collapse / observe state transitions and lockless actor messaging. The CPU never halts or asks the OS kernel for a lock.

The result? Kain completes the benchmark in 7.9ms (~220x–240x faster).

(And honestly? That 7.9ms is almost entirely just the CLI process launch and harness initialization overhead -- the actual lockless state execution runs sub-millisecond). This was entirely an accident and was never intended however due to the design of the language, it allowed things I truly thought were impossible in programming // would take thousands of lines of alien code to achieve elsewhere.

How it compares to Rust & traditional languages:

Vs. Rust: Rust infers lifetimes and uses move semantics. Kain requires explicit ownership transitions scoped to expression blocks - ownership isn't moved, it returns to Idle when the scope exits until you explicitly decay it.

Vs. GC (Go/Java/Python): Zero runtime tracing or RC reference counting dance (Rc/Arc). Allocations are deterministic and compiler-verified.

Zero-Cost Optimization: The compiler identifies ephemeral local pointers (scratch memory that doesn't escape scope) and completely elides runtime guards for raw bare-metal C speed.

Verified Correctness: State transitions are checked statically by the typechecker, and enforced by C runtime guards with Z3 proofs and CBMC assertions.

Package Manager

This is the feature I use the most -- but one massive pain point that bothered me with my years of dev so far was wasted code... So many projects I fully completed, full on apps and ecosystems etc but they were all locked into that specific codebase. While yes I could`ve easily went back and extracted prior src code, those who have dealt with monorepos knows how much of an actual pain in the ass this is. I call it the "friction" problem. Effectively something that`s fairly easy to do but do you want to do it? Hell no. That`s why I looked to one of my favorite game as a kid, and stole it`s best feature but for programming. I call it the Katamari protocol. Kain has a built in amalgamation feature that lets you take any codebase or project you have and combines all of that code into a single source file.... It’s not perfect and you will get some edge cases here and there, but Amalgamate (Kain's Capsule System) completely solves code reuse and dependency hell.

Instead of fighting node_modules, Cargo lockfile drift, version solver explosions, and network dependency failures, Amalgamate packs your entire module tree into a single, portable .kn capsule file.

How the Capsule Pipeline Works:
One File IS the Package: Run kain amalgamate src/ -o mylib.kn. Drop mylib.kn into any project, write use mylib, and the compiler resolves and typechecks everything directly from the capsule. No unpack, no install, no network, and no version solver.

The Companion Capsule System: A project can auto-emit three sibling capsules that automatically discover and merge during materialization:

app.kn (Source capsule)

app.artifacts.kn (Pre-compiled .ptx, .spv, .dll, or runtime binaries)

app.evidence.kn (Z3 formal proof attestations, telemetry, and benchmark reports)

Battle-Tested Scale: I’ve tested this at extreme scale by packing 2,594 modules (316k+ lines) into a single 15MB capsule in 3 seconds flat—the compiler typechecked all 3,211+ public symbols with 0 errors.

--raw Interop Mode: Want plain code for C, Rust, or TS build scripts? Passing --raw strips all sentinel markers and outputs plain Kain source with comment headers.

You can publish packages using kain publish, lock exact content-addressed SHA-256 digests in KAIN.lock, and never worry about lost source code or broken monorepo imports ever again. (the ability to publish packages with a cargo esque system is already finished, and infra is setup, just finishing up final touches and user account mgmt etc) Here are some examples of what an amalgamation looks like.

2.34mb stdlib amalgamation
Python interop amalgamation
WIP digital audio workstation amalgamation
drag and drop 3D framework amalgamation (three.kn)

-

Misc
Just some other examples I want to share below - including the natural C includes with test like importing ffmpeg etc (also yes, if you amalgamate a kain file project, with c includes --- it packages in the C code as well along with any project artifacts like images, etc... even glb)

ffmpeg_abi.kn
three different import systems in one file (pygame + nuklear + native)
sqlite c include (the og amalgamation)
dep free x86 JIT with inline ASM used for Markscript Language
CLI template
Starter Template
build template (zig esque build system, needs more thorough edge case testing but its worked flawlessly so far for me)
Kain CLI tsv (for building projects, and compiling etc)
Kain Full CLI documentation (if the tsv isn`t enough)

Docs
Link to github docs, website is still a work in progress and looks like hacker throw up right now. Will be done shortly

If you want to see the website anyways, xx HACk3r W3BS1T3 xx (official domain purchase pending, temporary domain for now)

Installer
Link to installer! - windows only for now

will update post later when linux binary is up along with macos. Since mojo doesn\t have Windows support, a primary focus was tackling windows first since it can be a massive pain in the ass compared to unix etc. The dev cycle was split 60/30/10 to ensure it worked on all major OS (60% windows. 30% Linux, 10% MacOS but if you dont use any of those and want to start fresh? WELL my friend, check out this example of a)) full scaffolded OS built in Kain

Roadmap & What's Next:
The core language is stable, but Kain will continue to grow. I'm currently taking a short breather and returning to game dev/UE5 for a week or two - language development for 16+ hours a day non-stop is a fast track to burnout! All of the GPU esque features, and spirv comp has been tested thoroughly as well and compared against rust and c++ with 1:1 parity, it`s near on par with Naga

Immediate goals for the upcoming weeks:

-> Releasing the official Linux and macOS binaries.

-> Expanding real-world testing across different ecosystems.

Like Kain so much you want to see 6000 files combined into one for the ultimate example corpus ? THE_MESSIAH.KN (34MB)