Eisen is a toolkit that supports the development of programmable applications and domain-specific languages (DSL).
Eisen is designed to be an embedded language with the semantics of Clojure and a syntax similar to Standard ML.
Eisen compiles to Clojure, which compiles to Java bytecode.
The Eisen library offers the following facilities:
- Access to the host data and functions from user code.
- Running user code from a host program.
- Functions for parsing and running Eisen code at the Clojure REPL.
- A simple Eisen REPL.
- The compiler's parsing and translation functions.
- Compiler hooks for extending Eisen or writing DSLs.
<dependency> <groupId>org.blancas</groupId> <artifactId>eisen</artifactId> <version>0.1.0</version> </dependency>
The following sections show parts of two samples in order to highlight some of Eisen's features.
The Snake Game
The Snake sample is a modified version of the game in the book Programming Clojure that may be changed and extended. The host program declares a mutable model for the user code to read and change.
(host-model width 75 height 50 win-length 2 point-size 10 body (list [1 1]) dir [1 0] add-points (fn [& pts] (vec (apply map + pts))))
The game reads the user code pasted on a simple text field and evaluates it.
(defn run-eisen  (let [code (JOptionPane/showInputDialog nil "Paste your code here:" "Change the game" JOptionPane/PLAIN_MESSAGE)] (when (seq code) (let [result (eisen code)] (when-not (:ok result) (JOptionPane/showMessageDialog nil (:error result)))))))
On the Eisen side, this code makes the snake wrap around the borders.
fun add p1 p2 = let p = map `+` p1 p2; x = first p; y = second p in cond x > _width => #[1, y]; x < 0 => #[_width, y]; y > _height => #[x, 1]; y < 0 => #[x, _height]; :else => #[x, y] end end
The following line installs the function
add above, which the host calls as
setv add-points = add
A Buddhabrot Fractal
The main program defines the model shared with the user code. Function
start was modified to setup the Eisen library and evaluate the user code.
(host-model sqrt #(java.lang.Math/sqrt %) ;; Package Java interop for user code. generate identity) ;; Generation function to be replaced. ;; Start the computation using user code. (defn start [fractal] (init-eisen) (eisenf user-code) (future (call generate fractal)))
These are some of the functions that compute the fractal. (Note that destructuring is not currently supported.)
(* Computes a point's path. *) fun calcPath x y max = let c = #[x, y] in loop z = c; path = #; iter = 0 in if iter > max then # else if abs z > 2.0 then z : path else recur (add c (mult z z)) (z : path) (inc iter) end end (* Translates a point into a screen coordinate. *) fun point2coord size c = let real = first c; imag = second c in #[ int (0.3 * size * (real + 0.5) + size / 2), int (0.3 * size * imag + size / 2) ] end (* Sets a point into the fractal's buffer. *) fun bufferSet fractal point = let size = get fractal :size; buffer = get fractal :buffer; p = point2coord size point; x = first p; y = second p in if x > 0 && y > 0 && x < size && y < size then `aset-int` buffer y x (aget buffer y x + 1) end (* Generates the fractal image. *) fun compute fractal = let buffer = get fractal :buffer; iter = get fractal :iteration in doseq [point <- iterate inc 1] let x = rand 6 - 3; y = rand 6 - 3; path = calcPath x y iter; in if point % 1000000 == 0 then println "Point:" point; doseq [p <- path] bufferSet fractal p end end end end (* Installs the local function. *) setv generate = compute
- Pattern matching.
- A uniform mechanism for function calls.
- Peephole optimizations.
Eisen is documented in the Wiki.
Browse the Codox Eisen v0.1.0 API.
To generate the API docs (in the
Copyright © 2013 Armando Blancas.
Licensed under the Eclipse Public License.