What a Language Needs Before It Can Compile Itself
Code: Megapixel99/lambda-language lm is a small low-level language I wrote: static types, explicit memory, no closures, no garbage collector, and four independent backends that emit C, WebAssembly, ARM64 and bytecode for a VM. Its compiler is about 4,400 lines of JavaScript. The obvious next question is whether the language can compile itself, and the obvious first step is the lexer, which is 129…
The language Megapixel99/lambda-language (lm) is a small, low-level language with static types and explicit memory management. It lacks closures, garbage collection, and features four independent backends for C, WebAssembly, ARM64, and bytecode VM emission. The compiler is approximately 4,400 lines of JavaScript, with the lexer making up 129 lines. The question arises whether the language can compile itself. The lexer, when ported to lm, is 355 lines long.
The primary reason for the size difference is the absence of certain features in lm. Specifically, six absences account for nearly all of the additional code. These absences include the lack of a single "advance(n)" function that moves position, line, and column together, a function to take the address of a scalar local, and the absence of a character literal and hex literal support. Writing this information down was a planned milestone to understand the language's limitations while the port was still manageable.
The largest source of the size difference is the absence of a function called "advance." This function is called from 14 places and responsible for moving position, line, and column together. Because lm does not have a way to take the address of a scalar local, a function could not mutate a caller's variable, and a function returning three values would need a struct allocated on every call.
This absence leads to 14 separate instances of writing "pos += 1; col += 1;" inline, and for the newline case, the three-line variant. This duplication is the main contributor to the size difference and caused the only correctness bug in the port.
Another notable absence is the lack of a centralized advance function. Instead, all 14 sites write "pos += 1; col += 1;" inline, leading to duplication and potential bugs. Additionally, there are no globals or constants in lm; keyword and operator tables are built at runtime. This results in a waste of resources, as any function needing these tables must pass them as parameters.
Moreover, the language lacks a string type and character literals, leading to decimal number representations for bytes and UTF-8 continuation bytes. Furthermore, the language does not have a growable array or string comparison functions, which complicate the process of recognizing tokens. Lastly, there are no loops with break statements carrying values or labelled loops, resulting in unnecessary comparisons and slower performance.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.