/eclj

Extensible Clojure

Primary LanguageClojureEclipse Public License 1.0EPL-1.0

Extensible Clojure

An extensible, symbolic, functionally-pure Clojure interpreter.

Extensible Clojure aims to completely virtualize the Clojure language, such that portable Clojure code can be run within a precisely controlled environment. Proper tail calls are supported via delimited continuations, which enables all effects to be modeled as pure data. Effects, including bidirectional interop, are processed at the top-level of the interpreter loop, so they too are fully programmable.

This project's ambitious goals are based on a vast academic foundation. Oleg Kiselyov's Extensible Effects & Interpreters page provides an excellent entry point. I'm also interested in building an evaluator that includes an extensible abstract interpreter and extensible JIT compiler. See Lancet.

Status

Experimental and unstable!

Development temporarily halted because I couldn't wrap my head around how to write a compiler for this thing. In the interim, I've developed Meta-Clojure, which may get me over the hump.

Platform

Runs on the JVM with Clojure 1.6.0.

Standalone deployment and cross-compilation to alternative platforms are goals.

Evaluator

The base interpreter is written in a trampolined continuation-passing style. It is complete enough to be self-applicable. There is also a meta-circular interpreter written in a direct style, utilizing constant space tail calls and the effect system. This meta-interpreter is highly experimental and will form the foundation of the forthcoming JIT compiler.

Libraries

The core libraries are currently a hybrid of compiled functions borrowed from clojure.core and symbolic EClj ports. Borrowed functions are actively being ported and abstracted to facilitate partial evaluation, utilize the effect system, and ease future targeting of non-JVM platforms.

Types

Clojure's primary data structures (those defined in Java) are the primary data structures used throughout EClj as well. Ultimately, EClj will provide additional implementations of these data structures wherever possible, but will maintain interop via the existing Java interfaces. The goal is for EClj to use the most appropriate data structures for the host.

Type defining forms (reify, deftype, and defrecord) delegate to the Clojure compiler to create the JVM type, but methods are interpreted by EClj. Effects cannot (yet) propagate across JVM method call boundaries.

Not In Scope

  • monitor-enter
  • monitor-exit

Usage

Only eclj.core provides a stable(-ish) public API at this time. It exports the same functionality as clojure.core with some to-be-documented extensions.

You can evaluate individual forms with eclj.core/eval and load .eclj files with eclj.core/require or related namespace & code loading functions. EClj can interop with normal Clojure code seamlessly, but clojure.core/ns can't load EClj. Of course, eclj.core/ns can require either file type.

Various caveats apply, but the list is too volatile to justify enumerating now.

License

Portions of this project derived from Clojure:
Copyright © 2006-2014 Rich Hickey

Original code and Clojure modifications:
Copyright © 2014 Brandon Bloom

Both are distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.