If It Can Be Compiled, It Will Be

Dec 4, 2021

The first programming languages were interpreted, not "compiled".

The first high-level programming language was Plankalkül, created by Konrad Zuse between 1942 and 1945. The first high-level language to have an associated compiler was created by Corrado Böhm in 1951, for his PhD thesis. The first commercially available language was FORTRAN (FORmula TRANslation), developed in 1956 (first manual appeared in 1956, but first developed in 1954) by a team led by John Backus at IBM.

Of course, interpretation doesn't remove the need for compilation entirely, it merely hides some of the compilation from the user.

I'm going to use the term "compiled" here loosely. I'm bundling in preprocessors and transpilers, since to many users, they resemble a build step that's similar to a compile step.

Nearly every language that historically been interpreted is moving compilation steps up the build pipeline and making them user facing.

One consequence of this is that interpreted languages now have compilation steps "bolted-on". You can see this in the clunky user experience to compile Sass to CSS (which requires the OS-dependent libsass) or the slow iteration cycles of JavaScript bundlers like webpack.

Another consequence is that we might need more general-purpose build tools to bring all of these compilation steps together. In the past, you'd compile your program and deploy it. Now, you need to compile multiple parts of your frontend and backend applications. First-generation tools like make aren't sophisticated enough to piece together all of these steps seamlessly.

Some examples of interpreted languages running through a compile build step.

CSS

  • CSS runs through preprocessors for minification, uglification, and language extensions.
  • Languages like Sass, LESS, and scss compile down to CSS.
  • Libraries like Tailwind require (or strongly encourage) bundling steps to remove extraneous classes.

JavaScript

  • Bundlers like webpack and esbuild provide all sorts of utilities to optimize JavaScript for the web like bundling and code splitting.
  • Typescript transpiles to JavaScript. Numerous languages like CoffeeScript and IcedCoffeeScript provide syntactic sugar and transpile to JavaScript.
  • Babel transpiles JavaScript in a variety of ways: turning JSX/TSX into valid JavaScript, supporting old browsers, and more.
  • JavaScript can compile to WebAssembly to produce a binary.

HTML

  • Templating languages like EJS, Jade, Handlebars, Mustache, Liquid, etc. let users embed runtime variables, control loops, and more into static HTML files.

Python

  • Python can be compiled to a self-contained and executable PAR file. This is common inside Google, but I'm not sure how many people are using it otherwise. See the repository on GitHub.
  • Python also has a templating engines like Jinja.

Configuration Languages (JSON, YAML, XML, etc.)

  • Transformation languages like XSLT exist to transpile XML into more XML. I even wrote one for YAML long ago (yamlt).
  • Higher level configuration languages like CUE have their own compiler

Wire formats (protobuf, thrift, etc.)

  • Most of the wire formats come with a code generation build step as part of their workflow. Write a definition in proto, but then generate client and server libraries with protoc.