Here is one try, stored in a file knucleotide.clj. It is not the
complete program, but it does exhibit the error I'm having trouble
with, and is significantly shorter than what I started with.
--------------------------------------------------
(ns knucleotide
(:gen-class))
(set! *warn-on-reflection* true)
(definterface IByteString
(calculateHash [b offset]))
(deftype ByteString [^{:unsynchronized-mutable true :tag bytes} byteArr
^{:unsynchronized-mutable true :tag int} hashVal
^{:unsynchronized-mutable true :tag int} cnt]
IByteString
(calculateHash [this b offset]
(let [^bytes buf b
len (int (alength byteArr))]
(loop [i (int 0)
offset (int offset)
temp (int 0)]
(if (== i len)
;; Following line is bad for Clojure 1.3alpha4
(set! hashVal temp)
;; Following line is OK, but not the behavior I want.
;; temp
(let [b (int (aget buf offset))
bb (byte b)]
(aset byteArr i bb)
(recur (inc i) (inc offset) (+ (* temp 31) b))))))))
(defn -main [& args]
)
--------------------------------------------------
Then I try to do AOT compilation with this command, and get the errors
shown below. It appears that I'm not doing type hinting correctly so
that 1.3 knows that the local temp is an int. Can anyone see how to
make something similar that works?
% java -Dclojure.compile.path=. -cp /Users/andy/lein/clj-1.3.0-alpha4/
lib/clojure-1.3.0-alpha4.jar:. clojure.lang.Compile knucleotide
Compiling knucleotide to .
Exception in thread "main" java.lang.VerifyError: (class: knucleotide/
ByteString, method: calculateHash signature: (Ljava/lang/Object;Ljava/
lang/Object;)Ljava/lang/Object;) Expecting to find integer on stack,
compiling:(knucleotide.clj:9)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3212)
at clojure.lang.Compiler.compile1(Compiler.java:6712)
at clojure.lang.Compiler.compile(Compiler.java:6773)
at clojure.lang.RT.compile(RT.java:368)
at clojure.lang.RT.load(RT.java:407)
at clojure.lang.RT.load(RT.java:381)
at clojure.core$load$fn__4389.invoke(core.clj:5306)
at clojure.core$load.doInvoke(core.clj:5305)
at clojure.lang.RestFn.invoke(RestFn.java:409)
at clojure.core$load_one.invoke(core.clj:5130)
at clojure.core$compile$fn__4394.invoke(core.clj:5317)
at clojure.core$compile.invoke(core.clj:5316)
at clojure.lang.Var.invoke(Var.java:401)
at clojure.lang.Compile.main(Compile.java:56)
Caused by: java.lang.VerifyError: (class: knucleotide/ByteString,
method: calculateHash signature: (Ljava/lang/Object;Ljava/lang/
Object;)Ljava/lang/Object;) Expecting to find integer on stack
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at knucleotide$fn__4.invoke(knucleotide.clj:9)
at clojure.lang.AFn.applyToHelper(AFn.java:159)
at clojure.lang.AFn.applyTo(AFn.java:151)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3207)
... 13 more
Thanks,
Andy
...
> (loop [i (int 0)
> offset (int offset)
> temp (int 0)]
As far as I am aware, 1.3 doesn't do local primitives like this
anymore. Just using the literal 0 for i and temp will make them
primitive longs. As for offset, (long offset) might work. On the other
hand, Java wants ints rather than longs for things like array indices
and I don't know if auto-demotion will happen (in Java you'd get an
error about not being allowed to do an implicit narrowing conversion,
and you'd have to explicitly cast long to int).
It may be worth a try, anyway.