A Clojure x86 compiler of an extended version of Latte programming language NOTE: though published (and 1.0'd), the project is far from done. As my first serious-ish Clojure project, the style is, well, bad. I am, however, working on improving it.
Table of Contents generated with DocToc
- ordering of helper functions by purpose would be nice
- intermediate representation of compiled code
- peephole optimization using the former
- registries mgmt
- inlining computations (with overflows, proper modulo etc)
- inlein for shorter startup (after evaluation)
- TBDs
Following extensions have been implemented:
- arrays with a basic for statement (
for ( int a : array)
) - arrays are initialized with
0/false
forint
s andboolean
s, for all others they're filled up withnull
s - classes with single extensions (with virtual methods)
- every class method is considered virtual
- global functions are prioritized over instance methods
self
refers to instance inside instance method (and IS assignable, effective in-scope only)- overrides' of methods arguments need to be not-lower in class hierarchy than originals (except for the class object itself),
reverse for return types;
i.e. if
class A extends B
andclass C
has a methodB doSomething(A thing)
, thenclass D extends C
may overwrite it with a methodA doSomething(B thing)
- only implicit type casts are allowed, except for
null
, which has to be cast explicitly
After calling make
the latc_x86
, latc
and latc_drip
binaries are ready to use. Calling latc_x86 foo/bar/baz.lat
(or latc foo/bar/baz.lat
, or latc_drip foo/bar/baz.lat
) will, should code compile, create files baz.s
(x86 assembly code) and baz
(the executable) in the foo/bar
directory.
Works with UNIX line endings only.
Project utilizes Leiningen (script provided in lib/) to manage dependencies (requires Internet connection!)
Also, since Clojure's really slowing down JVM start time (all core namespaces need to be loaded, which slows down the compilator), drip is provided to be used (optionally, through latc_drip
or setting LATC_DRIP_ENABLED
envvar to 1
).
The dependencies include
- basic Clojure package with core.match for pattern matching and algo.monads for monads support
- instaparse for ABNF grammar parsing
- resources - Clojure resources dir, contains the grammar
- src - sources (
src/latte_compiler
- Clojure sources,src/utils.c
- helper functions library) - lib - directory containing leiningen & drip script
- project.clj - leiningen config
Since Clojure core namespaces load on every execution, the JVM startup is really sluggish. Hence the latc_drip
and latc_drip_cleanup
binaries. They utilize drip, a small lib keeping the JVM running for another run, so that every second compilation does not have to load all namespaces (the JVM instance is killed after 30 minutes if not used). Note that every recompilation, kill and such may corrupt the classpath loader, and upon such the latc_drip_cleanup
script should be called to fix that.
latc_drip
is to be used instead of latc
or latc
should be called with LATC_DRIP_ENABLED
var set to 1
.
Note that while that approach is generally faster (up to 2x) for a number of consecutive runs, it may cause problems should the classpath be corrupted and as such, it may be worth to re-run compilation after cleanup or on regular JVM if compilation stalls/weird errors are thrown.