Dear sir, you have built a compiler (2022)
The article humorously illustrates how software developers often underestimate the complexity of creating prototypes, leading to unintentional development of sophisticated compilers due to evolving requirements and design challenges.
Read original articleThe article humorously addresses the common experience of software developers who set out to create a simple prototype but inadvertently end up building a complex compiler. The author recounts the journey of a developer who initially dismisses the need for a sophisticated compiler infrastructure, believing that a simple solution will suffice. However, as the project progresses, the developer faces increasing complexity, including the need to handle various abstract syntax tree (AST) nodes and accommodate user requirements that complicate the codebase. Despite attempts to simplify the process through pre-processing and custom AST libraries, the developer ultimately finds themselves implementing features typical of a full compiler, including parsing, intermediate representations, and code generation. The narrative serves as a cautionary tale about the unforeseen complexities of software development and the tendency to underestimate the requirements of seemingly straightforward tasks.
- Developers often underestimate the complexity of building software prototypes.
- Simplifying assumptions can lead to maintenance challenges later on.
- The journey from a simple task to building a compiler can be gradual and unintentional.
- Real-world requirements often complicate initial design decisions.
- The article highlights the importance of understanding the implications of software architecture choices.
Related
Why We Build Simple Software
Simplicity in software development, likened to a Toyota Corolla's reliability, is crucial. Emphasizing straightforward tools and reducing complexity enhances reliability. Prioritizing simplicity over unnecessary features offers better value and reliability.
We Build Simple Software
Simplicity in software development, likened to a Toyota Corolla's reliability, is crucial. Emphasizing straightforward tools, Pickcode aims for user-friendly experiences. Beware of complex software's pitfalls; prioritize simplicity for better value and reliability.
Htmx: Simplicity in an Age of Complicated Solutions
Erik Heemskerk discusses the pursuit of a 'silver bullet' technology in software development, emphasizing simplicity over complexity. He critiques over-engineering in front-end development, highlighting trade-offs in code solutions for better user experiences.
What 10k Hours of Coding Taught Me: Don't Ship Fast
The article emphasizes the importance of developer experience and software architecture, advocating for simplicity in coding, prioritizing refactoring, and maintaining code quality through structured practices and passion for the craft.
Magic Isn't Real
The article reflects on a software developer's journey from confusion to clarity in programming, emphasizing the importance of experience, continuous learning, and tackling challenges to gain deeper understanding.
- Many developers share experiences of unintentionally building complex systems, often likening it to creating compilers.
- There is a debate on whether starting from scratch or building on existing tools is more effective, with some advocating for intentionality in development choices.
- Several comments highlight the importance of knowledge and experience in avoiding common pitfalls in software development.
- Some commenters express confusion about the article's main message, indicating a need for clearer communication.
- Humor is a recurring theme, with many finding relatable anecdotes in the challenges described.
Lots of developers will find it much more interesting, challenging, rewarding and just plain fun to develop something from scratch, even when there are better things that already exist.
They'll cleverly manipulate and convince the boss, against the better discretion of their elder developers, that they can do it, and if they're one of the better developers, the boss won't want to risk losing them so they'll agree to the escapade.
Then said escapade turns into a shambles, as predicted by the elder devs, and the developer who created the mess simply quits and moves to some other job, in search of more fun and greener pastures. Any developer with decades of experience has probably seen this same pattern multiple times.
Reminds me of the pain of intentionally building a compiler for Java 2 (subset) to MIPS compiler by writing out each AST node class by hand. And, I did it twice, once in C++03 with bison and flex and again in Java 2 with CUP and JFlex... each was developed to build and run as a host portably across Solaris (sparc), Linux (x86), HP-UX (68k), SGI (MIPS), and Windows (x86) with compiled with targets run on the SPIM emulator. It did have dead code, dead string, and dead variable elimination, but that was as far my optimization passes went. I recall the only build tool I used for each was the portable subset of make without GNU extensions.
Speaking of reinventing the wheel, in 1998, I built a flexible almost framework for a "portable" generic installer using Java 2, JWT (native GUI controls), and JNI on Windows to create a program group and desktop shortcut icon. The hilarious part was shipping a full JRE on a CD. It took forever to load but the additional time seemed impressive for expensive, niche software in a way similar to the now fake "loading..." delayed progress bar.
</old-guy-high-school-glory-days-and-nobody-today>
This is written like a Jeopardy answer. I just don't know what the question is.
Can anyone enlighten me?
I've written a dozen different programs that might be considered compilers; some very simple, others very complex and whose life continued once I left the organization. Writing a functional compiler that provides the needs of the organization where existing tooling doesn't takes discipline and focus on what you actually want to accomplish. I don't know what "defining a struct inside a loop" might mean and this strikes me as, very obviously, having no clue what you actually want to build.
Perhaps the issue is not building a compiler but rather the lack of focus to begin with.
Long story short, we thought we were making a new type of N-dimensional spreadsheet, but after 3 semesters of work one of the advisors at MIT told us we need to meet his colleague, and that guy informed us we had a working compiler for a hybrid of Lisp and C.
direct link https://dx.tips/oops-database
"Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp."
But generically, a compiler is the exact kind of thing you want when you're doing "Take this data structure and transform it into this other data structure". In a traditional compiler, we usually deserialize the first data structure from a string (parsing), call that data structure a CST, validate the data structure (syntax & type checking), do the transform, then serialize the output.
This kind of validate and transform pattern is all over programming though. And it's pretty easy to test with things like property tests. So yeah, we should build little compilers more as abstraction boundaries in our code.
The template language intentionally only handles static chunks of HTML, escaping of values, and a little safety guards.
Everything else (including the usual template language behavior like iterating over a collection/stream, such as from a database query result) is done with arbitrary normal Racket language, which the template feature's implementation doesn't have to know about nor handle specially.
https://www.neilvandyke.org/racket/html-template/
More recently (for employability reasons, or under-resourced startup pragmatics), doing Python with Flask, JavaScript with SvelteKit, and Swift with SwiftUI, I still miss the clean simplicity and available power that I had with Scheme/Racket.
Don't get me wrong. I think many language design points should be used more. But starting from scratch makes a ton of sense. Skip the parsing stage and build up supported AST style constructs of your own.
Done simply, this is basically the command pattern. Keep execution separate from declaration and you should be fine?
Sure, you may want a parser for a dedicated serialization language some day. Hard to think you need start there?
But starting with the full AST of an existing language feels like a terrible idea. In any world.
I find ChatGPT to be of great help to explore the area, find relevant keywords or the name of the research domain. Sometimes you really need to know exactly what you are looking for before you can find the link to that one super helpful github library that solves you problem. The of course the next step is figuring out if you want to take on the dependency or not...
I have wasted hours searching for an (analytical) inverse kinematics library for robotic arms. There are tons of slow non analytical libraries out there, and some horrible ones like ikfast that is a effectively a code generator that spits out c that can be compiled with python bindings. I eventually did find https://github.com/Jmeyer1292/opw_kinematics, which someone ported rust (for which it was easy to create python bindings).
Compilers are interesting, but there is literally no proof that they are optimal for any of their popular applications. Which is what I think you are trying to imply by this narrative you have constructed of people constantly reinventing compilers. This is just the same propagandist argument lispweenies make to claim that their language is special.
Imagine a config file with type checking and control flow. You have it-- it's your programming language. you just need to load the code at runtime, like erlang.
Anyone here know where I can find it?
SSA is a nice ish format for representing program code, but it's not the only choice and may or may not be appropriate for your domain. For example, if your language describes data instead of control flow, imo SSA is a bad choice.
I have done this and if you take care to do things right, you won't need to bother with these hacky corner cases.
WORK-n: write an interpreter
WORK-n+1: add indirection
...
Related
Why We Build Simple Software
Simplicity in software development, likened to a Toyota Corolla's reliability, is crucial. Emphasizing straightforward tools and reducing complexity enhances reliability. Prioritizing simplicity over unnecessary features offers better value and reliability.
We Build Simple Software
Simplicity in software development, likened to a Toyota Corolla's reliability, is crucial. Emphasizing straightforward tools, Pickcode aims for user-friendly experiences. Beware of complex software's pitfalls; prioritize simplicity for better value and reliability.
Htmx: Simplicity in an Age of Complicated Solutions
Erik Heemskerk discusses the pursuit of a 'silver bullet' technology in software development, emphasizing simplicity over complexity. He critiques over-engineering in front-end development, highlighting trade-offs in code solutions for better user experiences.
What 10k Hours of Coding Taught Me: Don't Ship Fast
The article emphasizes the importance of developer experience and software architecture, advocating for simplicity in coding, prioritizing refactoring, and maintaining code quality through structured practices and passion for the craft.
Magic Isn't Real
The article reflects on a software developer's journey from confusion to clarity in programming, emphasizing the importance of experience, continuous learning, and tackling challenges to gain deeper understanding.