First a simple version, equivalent to yours but more readable.

(defmacro compile-instructions
 [instructions]
 (let [memory (gensym "memory-")]
   `(fn [~memory]
          ~@(map (fn [[op m1 m2]]
                 `(aset ~memory ~m1 (~op (aget ~memory ~m1) (aget ~memory
~m2))))
               instructions))))


(def memory (into-array Integer/TYPE (range 4)))
(def compiled (compile-instructions ([+ 2 3] [- 0 1] [+ 1 0])))


And another one to workaround the JVM 64K "feature". I split the generated
code into blocks of 500 instructions.

(def length-threshold 500)

(defmacro protected-fn [binding-form & body]
   (if (<= (count body) length-threshold)
          `(fn ~binding-form ~...@body)
       (let [small-funs  (partition length-threshold  length-threshold ()
body)
             let-block (map (fn [bod] (let [name (gensym "let-")] [name
 `(fn [...@binding-form] ~@ bod)] )) small-funs)]
          `(let [~@(apply concat let-block)]
             (protected-fn [...@binding-form] ~@(map (fn [[name code]] `(~name
~...@binding-form)) let-block))))))

(defmacro compile-instructions-2
 [instructions]
 (let [memory (gensym "memory-")]
   `(protected-fn [~memory]
          ~@(map (fn [[op m1 m2]]
                 `(aset ~memory ~m1 (~op (aget ~memory ~m1) (aget ~memory
~m2))))
               instructions))))

(def compiled-2 (eval `(compile-instructions-2 ~(take 1150 (cycle '([+ 2 3]
[- 0 1] [+ 1 0]))))))

This last line is quite ugly. In fact, if you want to use
compile-instruction programatically, maybe it should not be a macro but a
function.
Then using a code-generating function in a macro is easy.

Plus, it is easy to eval the generated code.
But, be careful, you have to eval it once, just after the compiling phase.
Then, you get a real function.
eval is evil, but eval is not evil is a compiler (you have to evaluate the
code you read).
However eval is evil again in an "embedded compiler", when you use macro to
extend Clojure.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to