diff options
| author | Taylan Kammer <taylan.kammer@gmail.com> | 2026-05-23 22:22:57 +0200 |
|---|---|---|
| committer | Taylan Kammer <taylan.kammer@gmail.com> | 2026-05-23 22:22:57 +0200 |
| commit | 378f8598a5a57b731948241e41f584f5172dc2a2 (patch) | |
| tree | e9352110efe5b204a5abe7e00693be2004aab4e5 /notes/260516-joke-rant.md | |
| parent | f1f134d072e375335be5c1203095115fef1db253 (diff) | |
An update of sorts.
Diffstat (limited to 'notes/260516-joke-rant.md')
| -rw-r--r-- | notes/260516-joke-rant.md | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/notes/260516-joke-rant.md b/notes/260516-joke-rant.md new file mode 100644 index 0000000..a1c6f64 --- /dev/null +++ b/notes/260516-joke-rant.md @@ -0,0 +1,69 @@ +# Compilers are FAKE + +_2026 May NOT_ + +Languages typically either + +- follow the "interpreted language" mentality and at best add things + like bytecode cache files or JIT as behind-the-scenes optimizations, + or + +- follow the "compiled language" mentality where code written in the + language is a representation of the intended behaviour of an + executable that will eventually be produced. + +In the latter model, compile-time logic is often limited to primitive +pre-processors, declarative DSLs or otherwise limited subsystems (C++ +templates, Zig comptime, etc.) and often even offloaded to an entirely +separate "build system" language. In the former model, compilation is +swept under the rug like it's shameful dirt. + +Why? + +How about designing a language that embraces the reality of what it +means to "compile code": Run an executable with source code as input. +Sound familiar? IT'S WHAT AN INTERPRETER DOES! So, in my preferred +language: + +- The "interpreter" includes APIs for explicitly compiling any of the + currently defined functions, modules, etc. straight from their in + memory representation (be it AST or bytecode) into native code or + assembly snippets, with the ability to then "serialize" or assemble + and link these to create object files or executables. + +- The "compiler" is just a thin wrapper around these APIs, loading + some source files that define functions and globals etc. (all of + which is first interpreted) then compiling them and producing + executables. + +- The "top level" of any source file is naturally executed at compile + time. You get meta programming and a build system language "for + free" since these kinds of features can simply be libraries. + +Some lisp/scheme implementations already contain an interpreter and +compiler in one, exposing parts of the compiler through APIs, and +allow full compile time code execution via macros. However, in my +experience, they still tend to embrace the traditional interpreted +vs. compiled mentality, which sometimes just makes things awkward. +For example, GNU Guile insists on automatically compiling everything +into a bytecode cache on the filesystem, unless you pass a CLI flag +disabling this behavior. And if you write a Guile Scheme codebase, +you still typically use Autotools and Make to call `guild` to compile +the Scheme files. Just why? You have the full Guile runtime at your +disposal, at compile time... I propose a change in mentality. + +## Dial the schizophrenia to 11 + +Compilers are all FAKE. They just pretend to be compilers. All a +compiler is, is an interpreter for a language that pretends to be a +"compiled language" when in reality it's just an interpreted DSL for +declaring the desired behavior of an executable, which is produced +when the codebase written in this DSL is interpreted ("compiled") by +the interpreter ("compiler"). + +They have played us for absolute fools. + +C is a declarative, interpreted DSL to describe executables. + +GCC is an interpreter that runs C, a declarative DSL describing the +executable that GCC should shit out. |
