Toy compiler and runtime from the Compilers class at Northeastern, targeting x86. Supports:
- Primitives:
- Ints
- Bools
- Heap-allocated structures:
- Tuples (homogenous and heterogenous)
- First-class lambda functions (with free-variable capture)
- Simple unary operators:
printto display valuesadd1andsub1on ints!(not) on boolsisnum,isbool, andistuple
- Simple binary operators:
==on all types (reference equality on tuples and lambdas)+,-,*,<,>,<=, and=>on ints&&and||on bools
- Tuple getters and setters:
- Expression-as-key for homogenous tuples
- Constant-as-key for heterogenous tuples
- Conditional branching with
if-else - Local variable bindings with
let(lexical scope) - Simple typechecking, with Hindley-Milner type inference and support for explicit annotations
- Tail-call elimination
- Recursive and mutually-recursive lambda definitions
- Semispace gargage collection using Cheney's algorithm
- Simple optimizations:
- Constant folding
- Common subexpression elimination
- Dead assignment elimination
See test.ml for examples, along with examples of error-flagging.
First get required tools. On OSX:
$ brew install nasm ocaml opam
$ opam init
$ opam install batteries extlib ounitThen build and run the regression suite, to be sure everything works:
$ make test && ./testNOTE: A number of tests will be auto-skipped on OS X. They depend on Valgrind, which still doesn't seem to work properly on Macs. Everything should work on Ubuntu (provided valgrind is installed).
# Write a program:
$ cat <<EOF > input/my-program.snake
let fact = (lambda n:
let rec tail_fact = (lambda m, acc:
if (m == 0): acc
else: tail_fact(m - 1, m * acc)) in
tail_fact(n, 1)) in
fact(10)
EOF
# Compile the program:
$ make output/my-program.run
# Run the program:
$ ./output/my-program.run