LLMs as compilers
August 29, 2025
The existence of LLMs as a tool changes the engineering equations. If I’m going to have to write and maintain the code that runs a non-techie’s website, then I’m going to settle for wordpress and deal with some of the ugliness and complexity because they can probably find an existing theme they like and can probably do most of the content editing. But if an llm can generate the whole thing from scratch after I’ve given detailed instructions, then I’m doing bare metal. No frameworks, no libraries. If an llm is writing the code, Spring just gets in the way by making context implicit. Who needs React if the llm will happily hard code the dom updates for every event. The hard coded vanilla runs faster and is easier for the llm to change because the context is explicit. It is true that this vanilla code is probably a spagetti mess (which is what drove us to the endless parade of JS frameworks), but the maintainability of that code is as irrelevant as the maintainability of the JVM bytecode compiled from a Java application is to the Spring developer.
All of the abstractions we have built in programming were built around our human limitations and strengths. We aren’t good at reading binary so let’s make assembly. We aren’t good at holding everything in our head at the same time so let’s create c and get functions and modules where we can focus on little pieces of code and then glue them together. We are good at working with metaphors and patterns so let’s do object orientation. We don’t like wasting time writing what we can copy, so let’s make libraries. But llms don’t share those strengths or weaknesses. And every layer of abstraction introduces leaks and indirection. The old joke was that “a sufficiently intelligent compiler would be able to …”. Maybe LLMs can be that. A human would write “code” (more likely something conceptually like a spec) at a very high level, the llm implements that in a specialized middle level suited to the LLM’s strengths, and then a compiler converts to machine. And a person almost never sees or needs to see that middle level anymore than I need to review llvm bytecode.
I don’t think LLMs would thrive writing binary. But my intuition is that the sweet spot for an LLM is closer to assembly than it is to python. My intuition is that we need to move in that direction. Not where LLMs are tasked with being “junior developers” operating as partners at our level of abstraction. Not where we review the code they write. But rather where we step up to a higher level of abstraction and we write some sort of specification that the llm turns into code we don’t care about because new tools let us be confident that the llm produced code is to spec. We may cache the llm produced code to save time but we wouldn’t check it into source control. The spec is the new source, and the llm becomes essentially a step in the compiler. The spec establishes goals and guardrails. Tools take the spec and run a whole series of LLM agents until all of the goals are met and the tests generated from the spec pass.
Ruby on rails is a tool designed for people to use – every goal of the project is human-centered: fun, beauty, DRY, convention over configuration. An LLM is not bothered at all by constantly spitting out f, err := foo("arg") if err != nil {log.Fatal(err)}. Every implicit convention hides context from an LLM which by definition has no model of the world (in which implicit conventions exist) and can only process explicit inputs. If LLMs are going to be tools (perhaps core tools) for development, then we should re-engineer our development tools around that.