Skip to content
Minimal self-hosted JavaScript compiler in 1k lines of code
Branch: master
Clone or download
Latest commit c84d13c Aug 26, 2017
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
bin Update Jul 13, 2017
src Update Jul 13, 2017
stdlib Update Dec 31, 2016
.gitattributes 👾 Added .gitattributes & .gitignore files Dec 29, 2016
.gitignore 👾 Added .gitattributes & .gitignore files Dec 29, 2016
LICENSE Merge remote-tracking branch 'origin/master' Feb 12, 2017
README.md
build.js Update Dec 31, 2016
index.html Update index.html Aug 26, 2017

README.md

This is an experimental source-to-source compiler that understands basic JavaScript and offers two extra language features on top. The compiler is bootstrapped (able to compile itself) and written in only 1k lines of code.

I created this project to give a basic, not too much time-consuming overview, how compilers like Babel work behind the scenes.

Overview:

bin/stub contains the latest generated version (the "compiler.exe")
src/index contains the compiler source code we can edit (gets compiled by our stub)

Usage:

node build

Features:

Pass by reference:
// variables with native types get passed by value in js -
// with 'inout' we tell the compiler to transform passed in variables into referenceable objects
function swap(inout a, inout b) {
  let tmp = a;
  a = b;
  b = tmp;
};
let test1 = 5;
let test2 = 10;
console.log(test1, test2); // 5, 10
swap(test1, test2); // swap both variables
console.log(test1, test2); // 10, 5

Compiles into:

function swap(a, b) {
  let tmp = a.$iov;
  a.$iov = b.$iov;
  b.$iov = tmp;
};
let test1 = { $iov: 5 };
let test2 = { $iov: 10 };
console.log(test1.$iov, test2.$iov); // here we point to the variable's value
swap(test1, test2); // here we pass the variable's reference
console.log(test1.$iov, test2.$iov); // much hax
Enums:
enum Direction {
  Up = 0,
  Down,
  Left,
  Right
}
let dir = .Up || Direction.Right;

Compiles into:

var Direction;
(function(Direction) {
  Direction[Direction['Up'] = 0] = 'Up';
  Direction[Direction['Down'] = 1] = 'Down';
  Direction[Direction['Left'] = 2] = 'Left';
  Direction[Direction['Right'] = 3] = 'Right';
})(Direction || (Direction = {}));
let dir = 0 || 3;

How it works:

The first version of the compiler was written in very simple javascript, using only explicitly necessary language features. The compiler got extended more and more until it was able to parse the required subset of javascript language features, which are needed to parse and transform strings. In the next step the code generator got added which spits out plain javascript without any formatting. This code then turned into the stub file as well as remains our source file.

Stub usage:

let compiler = require("./bin/stub");
compiler.compile("const a = 10;", {
  console: console, // uses log and error method
  error: function(msg) {
    console.error("Error: " + msg); // wat happens on a error
  }
});

See toy-compiler for a more extended version offering classes and a simple preprocessor.

Another compile-to-js project is this one, which offers a Swift-like language with type inference, custom operators, pass-by-reference etc.

You can’t perform that action at this time.