A compiled implementation of ES5, targetting C. I've finished the project as it now supports the parts of the language I found most interesting for a compiled implementation:
- ✅ closures
- ✅ garbage collection
- ✅ exceptions
- ✅ event based IO
- ✅ object system - prototypes etc
Read my notes for a rough dev notes, or read more polished write ups on my blog.
Next thing to do - see TODO.md.
The following JS
function fact(n) {
return n < 3 ? n : n * fact(n - 1);
}
console.log(fact(5));
outputs as a C program. For instance the compiled fact
function looks like:
// ...
JsValue *fact_1(Env *env) {
JsValue *return_2;
JsValue *left_5 = (envGet(env, interned_7) /* n */);
JsValue *right_6 = (jsValueCreateNumber(3));
JsValue *conditionalPredicate_4 = (LTOperator(left_5, right_6));
JsValue *conditionalValue_3;
if (isTruthy(conditionalPredicate_4)) {
return_2 = (envGet(env, interned_7) /* n */);
} else {
JsValue *left_8 = (envGet(env, interned_7) /* n */);
JsValue *callee_10 = (envGet(env, interned_11) /* fact */);
JsValue *left_12 = (envGet(env, interned_7) /* n */);
JsValue *right_13 = (jsValueCreateNumber(1));
JsValue *call10Arg_0 = (subtractOperator(left_12, right_13));
JsValue *args_10[] = {call10Arg_0};
JsValue *right_9 = (functionRunWithArguments(callee_10, env, args_10, 1));
return_2 = (multiplyOperator(left_8, right_9));
}
return return_2;
}
// ...
./runtime
the C implementation of the language runtime
./src
the TypeScript compiler
Run npm test
to run/update tests. ./scripts/test-by-name $name
to run a single test.
Failed tests provide a command to compile and run the C program with the debugger.
The runtime has unit tests - use the make test
in ./runtime
to run them, and ./runtime/scripts/compile-test-loop test-file-basename
.
Runtime C libraries for js-to-c.
Dependencies:
- clang
- Make
- CMake (for libuv)
I'm trying to limit my focus to learning about compilation, so I've made no attempt to make this cross platform. It shouldn't be too tricky, libuv is the big dependency and it's cross platform.
make install
Builds and runs all tests:
make test
See lib
- currently just
- debug.h
- debug macros
The runtime is built into a dynamic library to avoid recompiling. There's also a prelude, which allows langauge features to be implemented in JS that's pre-compiled to C.
Files prefixed _
are private to the runtime and should not be relied on.
grep
for HMM
to see potential problems I'm leaving alone for now as they seem tricky to solve properly/I'm unsure they'll be a problem in practice. Good place to look if weird bugs occur.