aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduardo Julian2015-03-12 01:25:06 -0400
committerEduardo Julian2015-03-12 01:25:06 -0400
commitaecb050cfba1c272274e9737b6c9b5b45309a900 (patch)
treeb18ed566164c79ce45cf905b531e968aea2674df
parent8e82cb7ab2276c5622af30cf43527aa79c8d36e5 (diff)
- Added a special form for testing if references are null.
- Added bitwise operators. - Added synchronization primitives (monitor enter & exit). - Added exception-handling. - Added conversions between primitive values.
-rw-r--r--src/lux.clj6
-rw-r--r--src/lux/analyser.clj110
-rw-r--r--src/lux/analyser/host.clj76
-rw-r--r--src/lux/compiler.clj87
-rw-r--r--src/lux/compiler/host.clj130
5 files changed, 399 insertions, 10 deletions
diff --git a/src/lux.clj b/src/lux.clj
index a8bdd4f31..f69bdf9dc 100644
--- a/src/lux.clj
+++ b/src/lux.clj
@@ -6,16 +6,10 @@
;; TODO: Finish type system.
;; TODO: Re-implement compiler in language.
;; TODO: Adding metadata to global vars.
- ;; TODO: throw, try, catch, finally
;; TODO: Allow setting fields.
- ;; TODO: monitor enter & monitor exit.
;; TODO: Add column & line numbers for syntactic elements.
;; TODO: Add source-file information to .class files for easier debugging.
- ;; TODO: Add conversions between primitives
- ;; TODO: Being able to ask if a value is null or not. (null?)
;; TODO: invokespecial & invokeinterface
- ;; TODO: bitwise operators
- ;; TODO: multianewarray
;; TODO:
(time (&compiler/compile-all ["lux"]))
diff --git a/src/lux/analyser.clj b/src/lux/analyser.clj
index ad21eadd1..41e304521 100644
--- a/src/lux/analyser.clj
+++ b/src/lux/analyser.clj
@@ -14,6 +14,20 @@
[host :as &&host])))
;; [Utils]
+(defn ^:private parse-handler [[catch+ finally+] token]
+ (matchv ::M/objects [token]
+ [["Form" ["Cons" [["Ident" "jvm-catch"]
+ ["Cons" [["Ident" ?ex-class]
+ ["Cons" [["Ident" ?ex-arg]
+ ["Cons" [?catch-body
+ ["Nil" _]]]]]]]]]]]
+ [(concat catch+ (list [?ex-class ?ex-arg ?catch-body])) finally+]
+
+ [["Form" ["Cons" [["Ident" "jvm-finally"]
+ ["Cons" [?finally-body
+ ["Nil" _]]]]]]]
+ [catch+ ?finally-body]))
+
(defn ^:private analyse-basic-ast [analyse-ast token]
;; (prn 'analyse-basic-ast token (&/show-ast token))
(matchv ::M/objects [token]
@@ -181,6 +195,9 @@
(&&host/analyse-jvm-dgt analyse-ast ?x ?y)
;; Objects
+ [["Form" ["Cons" [["Ident" "jvm-null?"] ["Cons" [?object ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-null? analyse-ast ?object)
+
[["Form" ["Cons" [["Ident" "jvm-new"]
["Cons" [["Ident" ?class]
["Cons" [["Tuple" ?classes]
@@ -219,6 +236,99 @@
["Nil" _]]]]]]]]]]]]]]]
(&&host/analyse-jvm-invokevirtual analyse-ast ?class ?method (&/->seq ?classes) ?object (&/->seq ?args))
+ ;; Exceptions
+ [["Form" ["Cons" [["Ident" "jvm-try"]
+ ["Cons" [?body
+ ?handlers]]]]]]
+ (&&host/analyse-jvm-try analyse-ast ?body (reduce parse-handler [(list) nil] (&/->seq ?handlers)))
+
+ [["Form" ["Cons" [["Ident" "jvm-throw"]
+ ["Cons" [?ex
+ ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-throw analyse-ast ?ex)
+
+ ;; Syncronization/monitos
+ [["Form" ["Cons" [["Ident" "jvm-monitorenter"]
+ ["Cons" [?monitor
+ ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-monitorenter analyse-ast ?monitor)
+
+ [["Form" ["Cons" [["Ident" "jvm-monitorexit"]
+ ["Cons" [?monitor
+ ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-monitorexit analyse-ast ?monitor)
+
+ ;; Primitive conversions
+ [["Form" ["Cons" [["Ident" "jvm-d2f"] ["Cons" [?value ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-d2f analyse-ast ?value)
+
+ [["Form" ["Cons" [["Ident" "jvm-d2i"] ["Cons" [?value ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-d2i analyse-ast ?value)
+
+ [["Form" ["Cons" [["Ident" "jvm-d2l"] ["Cons" [?value ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-d2l analyse-ast ?value)
+
+ [["Form" ["Cons" [["Ident" "jvm-f2d"] ["Cons" [?value ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-f2d analyse-ast ?value)
+
+ [["Form" ["Cons" [["Ident" "jvm-f2i"] ["Cons" [?value ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-f2i analyse-ast ?value)
+
+ [["Form" ["Cons" [["Ident" "jvm-f2l"] ["Cons" [?value ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-f2l analyse-ast ?value)
+
+ [["Form" ["Cons" [["Ident" "jvm-i2b"] ["Cons" [?value ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-i2b analyse-ast ?value)
+
+ [["Form" ["Cons" [["Ident" "jvm-i2c"] ["Cons" [?value ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-i2c analyse-ast ?value)
+
+ [["Form" ["Cons" [["Ident" "jvm-i2d"] ["Cons" [?value ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-i2d analyse-ast ?value)
+
+ [["Form" ["Cons" [["Ident" "jvm-i2f"] ["Cons" [?value ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-i2f analyse-ast ?value)
+
+ [["Form" ["Cons" [["Ident" "jvm-i2l"] ["Cons" [?value ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-i2l analyse-ast ?value)
+
+ [["Form" ["Cons" [["Ident" "jvm-i2s"] ["Cons" [?value ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-i2s analyse-ast ?value)
+
+ [["Form" ["Cons" [["Ident" "jvm-l2d"] ["Cons" [?value ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-l2d analyse-ast ?value)
+
+ [["Form" ["Cons" [["Ident" "jvm-l2f"] ["Cons" [?value ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-l2f analyse-ast ?value)
+
+ [["Form" ["Cons" [["Ident" "jvm-l2i"] ["Cons" [?value ["Nil" _]]]]]]]
+ (&&host/analyse-jvm-l2i analyse-ast ?value)
+
+ ;; Bitwise operators
+ [["Form" ["Cons" [["Ident" "jvm-iand"] ["Cons" [?x ["Cons" [?y ["Nil" _]]]]]]]]]
+ (&&host/analyse-jvm-iand analyse-ast ?x ?y)
+
+ [["Form" ["Cons" [["Ident" "jvm-ior"] ["Cons" [?x ["Cons" [?y ["Nil" _]]]]]]]]]
+ (&&host/analyse-jvm-ior analyse-ast ?x ?y)
+
+ [["Form" ["Cons" [["Ident" "jvm-land"] ["Cons" [?x ["Cons" [?y ["Nil" _]]]]]]]]]
+ (&&host/analyse-jvm-land analyse-ast ?x ?y)
+
+ [["Form" ["Cons" [["Ident" "jvm-lor"] ["Cons" [?x ["Cons" [?y ["Nil" _]]]]]]]]]
+ (&&host/analyse-jvm-lor analyse-ast ?x ?y)
+
+ [["Form" ["Cons" [["Ident" "jvm-lxor"] ["Cons" [?x ["Cons" [?y ["Nil" _]]]]]]]]]
+ (&&host/analyse-jvm-lxor analyse-ast ?x ?y)
+
+ [["Form" ["Cons" [["Ident" "jvm-lshl"] ["Cons" [?x ["Cons" [?y ["Nil" _]]]]]]]]]
+ (&&host/analyse-jvm-lshl analyse-ast ?x ?y)
+
+ [["Form" ["Cons" [["Ident" "jvm-lshr"] ["Cons" [?x ["Cons" [?y ["Nil" _]]]]]]]]]
+ (&&host/analyse-jvm-lshr analyse-ast ?x ?y)
+
+ [["Form" ["Cons" [["Ident" "jvm-lushr"] ["Cons" [?x ["Cons" [?y ["Nil" _]]]]]]]]]
+ (&&host/analyse-jvm-lushr analyse-ast ?x ?y)
+
;; Arrays
[["Form" ["Cons" [["Ident" "jvm-new-array"] ["Cons" [["Ident" ?class] ["Cons" [["Int" ?length] ["Nil" _]]]]]]]]]
(&&host/analyse-jvm-new-array analyse-ast ?class ?length)
diff --git a/src/lux/analyser/host.clj b/src/lux/analyser/host.clj
index f6f20d695..fd4244178 100644
--- a/src/lux/analyser/host.clj
+++ b/src/lux/analyser/host.clj
@@ -8,7 +8,8 @@
[parser :as &parser]
[type :as &type]
[host :as &host])
- (lux.analyser [base :as &&])))
+ (lux.analyser [base :as &&]
+ [env :as &&env])))
;; [Utils]
(defn ^:private ->seq [xs]
@@ -127,6 +128,10 @@
]
(return (list [::&&/Expression [::&&/jvm-invokevirtual =class ?method =classes =object =args] =return]))))
+(defn analyse-jvm-null? [analyse ?object]
+ (exec [=object (&&/analyse-1 analyse ?object)]
+ (return (list [::&&/Expression [::&&/jvm-null? =object] [::&type/Data "java.lang.Boolean"]]))))
+
(defn analyse-jvm-new [analyse ?class ?classes ?args]
(exec [=class (&host/full-class-name ?class)
=classes (map-m &host/extract-jvm-param ?classes)
@@ -175,8 +180,8 @@
["Nil" _]]]]]]]]
["Nil" _]]]]]]]]]
(do ;; (prn 'analyse-jvm-interface ?member-name ?inputs ?output)
- (exec [?inputs (map-m extract-ident (&/->seq ?inputs))]
- (return [?member-name [?inputs ?output]])))
+ (exec [?inputs (map-m extract-ident (&/->seq ?inputs))]
+ (return [?member-name [?inputs ?output]])))
[_]
(fail "[Analyser Error] Invalid method signature!")))
@@ -192,3 +197,68 @@
=exprs (mapcat-m analyse ?exprs)
=exprs-types (map-m &&/expr-type =exprs)]
(return (list [::&&/Expression [::&&/exec =exprs] (last =exprs-types)]))))
+
+(defn analyse-jvm-try [analyse ?body [?catches ?finally]]
+ (exec [=body (&&/analyse-1 analyse ?body)
+ =catches (map-m (fn [[?ex-class ?ex-arg ?catch-body]]
+ (&&env/with-local ?ex-arg [::&type/Data ?ex-class]
+ (exec [=catch-body (&&/analyse-1 analyse ?catch-body)]
+ (return [?ex-class ?ex-arg =catch-body]))))
+ ?catches)
+ =finally (&&/analyse-1 analyse ?finally)
+ =body-type (&&/expr-type =body)]
+ (return (list [::&&/Expression [::&&/jvm-try =body =catches =finally] =body-type]))))
+
+(defn analyse-jvm-throw [analyse ?ex]
+ (exec [=ex (&&/analyse-1 analyse ?ex)]
+ (return (list [::&&/Expression [::&&/jvm-throw =ex] [::&type/Nothing]]))))
+
+(defn analyse-jvm-monitorenter [analyse ?monitor]
+ (exec [=monitor (&&/analyse-1 analyse ?monitor)]
+ (return (list [::&&/Expression [::&&/jvm-monitorenter =monitor] [::&type/Any]]))))
+
+(defn analyse-jvm-monitorexit [analyse ?monitor]
+ (exec [=monitor (&&/analyse-1 analyse ?monitor)]
+ (return (list [::&&/Expression [::&&/jvm-monitorexit =monitor] [::&type/Any]]))))
+
+(do-template [<name> <tag> <from-class> <to-class>]
+ (defn <name> [analyse ?value]
+ (exec [=value (&&/analyse-1 analyse ?value)]
+ (return (list [::&&/Expression [<tag> =value] [::&type/Data <to-class>]]))))
+
+ analyse-jvm-d2f ::&&/jvm-d2f "java.lang.Double" "java.lang.Float"
+ analyse-jvm-d2i ::&&/jvm-d2i "java.lang.Double" "java.lang.Integer"
+ analyse-jvm-d2l ::&&/jvm-d2l "java.lang.Double" "java.lang.Long"
+
+ analyse-jvm-f2d ::&&/jvm-f2d "java.lang.Float" "java.lang.Double"
+ analyse-jvm-f2i ::&&/jvm-f2i "java.lang.Float" "java.lang.Integer"
+ analyse-jvm-f2l ::&&/jvm-f2l "java.lang.Float" "java.lang.Long"
+
+ analyse-jvm-i2b ::&&/jvm-i2b "java.lang.Integer" "java.lang.Byte"
+ analyse-jvm-i2c ::&&/jvm-i2c "java.lang.Integer" "java.lang.Character"
+ analyse-jvm-i2d ::&&/jvm-i2d "java.lang.Integer" "java.lang.Double"
+ analyse-jvm-i2f ::&&/jvm-i2f "java.lang.Integer" "java.lang.Float"
+ analyse-jvm-i2l ::&&/jvm-i2l "java.lang.Integer" "java.lang.Long"
+ analyse-jvm-i2s ::&&/jvm-i2s "java.lang.Integer" "java.lang.Short"
+
+ analyse-jvm-l2d ::&&/jvm-l2d "java.lang.Long" "java.lang.Double"
+ analyse-jvm-l2f ::&&/jvm-l2f "java.lang.Long" "java.lang.Float"
+ analyse-jvm-l2i ::&&/jvm-l2i "java.lang.Long" "java.lang.Integer"
+ )
+
+(do-template [<name> <tag> <from-class> <to-class>]
+ (defn <name> [analyse ?value]
+ (exec [=value (&&/analyse-1 analyse ?value)]
+ (return (list [::&&/Expression [<tag> =value] [::&type/Data <to-class>]]))))
+
+ analyse-jvm-iand ::&&/jvm-iand "java.lang.Integer" "java.lang.Integer"
+ analyse-jvm-ior ::&&/jvm-ior "java.lang.Integer" "java.lang.Integer"
+
+ analyse-jvm-land ::&&/jvm-land "java.lang.Long" "java.lang.Long"
+ analyse-jvm-lor ::&&/jvm-lor "java.lang.Long" "java.lang.Long"
+ analyse-jvm-lxor ::&&/jvm-lxor "java.lang.Long" "java.lang.Long"
+
+ analyse-jvm-lshl ::&&/jvm-lshl "java.lang.Long" "java.lang.Integer"
+ analyse-jvm-lshr ::&&/jvm-lshr "java.lang.Long" "java.lang.Integer"
+ analyse-jvm-lushr ::&&/jvm-lushr "java.lang.Long" "java.lang.Integer"
+ )
diff --git a/src/lux/compiler.clj b/src/lux/compiler.clj
index 2fa180aea..62a11868d 100644
--- a/src/lux/compiler.clj
+++ b/src/lux/compiler.clj
@@ -186,6 +186,9 @@
[::&a/jvm-null]
(&&host/compile-jvm-null compile-expression ?type)
+
+ [::&a/jvm-null? ?object]
+ (&&host/compile-jvm-null? compile-expression ?type ?object)
[::&a/jvm-new ?class ?classes ?args]
(&&host/compile-jvm-new compile-expression ?type ?class ?classes ?args)
@@ -209,7 +212,89 @@
(&&host/compile-jvm-aastore compile-expression ?type ?array ?idx ?elem)
[::&a/jvm-aaload ?array ?idx]
- (&&host/compile-jvm-aaload compile-expression ?type ?array ?idx))
+ (&&host/compile-jvm-aaload compile-expression ?type ?array ?idx)
+
+ [::&a/jvm-try ?body ?catches ?finally]
+ (&&host/compile-jvm-try compile-expression ?type ?body ?catches ?finally)
+
+ [::&a/jvm-throw ?ex]
+ (&&host/compile-jvm-throw compile-expression ?type ?ex)
+
+ [::&a/jvm-monitorenter ?monitor]
+ (&&host/compile-jvm-monitorenter compile-expression ?type ?monitor)
+
+ [::&a/jvm-monitorexit ?monitor]
+ (&&host/compile-jvm-monitorexit compile-expression ?type ?monitor)
+
+ [::&a/jvm-d2f ?value]
+ (&&host/compile-jvm-d2f compile-expression ?type ?value)
+
+ [::&a/jvm-d2i ?value]
+ (&&host/compile-jvm-d2i compile-expression ?type ?value)
+
+ [::&a/jvm-d2l ?value]
+ (&&host/compile-jvm-d2l compile-expression ?type ?value)
+
+ [::&a/jvm-f2d ?value]
+ (&&host/compile-jvm-f2d compile-expression ?type ?value)
+
+ [::&a/jvm-f2i ?value]
+ (&&host/compile-jvm-f2i compile-expression ?type ?value)
+
+ [::&a/jvm-f2l ?value]
+ (&&host/compile-jvm-f2l compile-expression ?type ?value)
+
+ [::&a/jvm-i2b ?value]
+ (&&host/compile-jvm-i2b compile-expression ?type ?value)
+
+ [::&a/jvm-i2c ?value]
+ (&&host/compile-jvm-i2c compile-expression ?type ?value)
+
+ [::&a/jvm-i2d ?value]
+ (&&host/compile-jvm-i2d compile-expression ?type ?value)
+
+ [::&a/jvm-i2f ?value]
+ (&&host/compile-jvm-i2f compile-expression ?type ?value)
+
+ [::&a/jvm-i2l ?value]
+ (&&host/compile-jvm-i2l compile-expression ?type ?value)
+
+ [::&a/jvm-i2s ?value]
+ (&&host/compile-jvm-i2s compile-expression ?type ?value)
+
+ [::&a/jvm-l2d ?value]
+ (&&host/compile-jvm-l2d compile-expression ?type ?value)
+
+ [::&a/jvm-l2f ?value]
+ (&&host/compile-jvm-l2f compile-expression ?type ?value)
+
+ [::&a/jvm-l2i ?value]
+ (&&host/compile-jvm-l2i compile-expression ?type ?value)
+
+ [::&a/jvm-iand ?x y]
+ (&&host/compile-jvm-iand compile-expression ?type ?x y)
+
+ [::&a/jvm-ior ?x y]
+ (&&host/compile-jvm-ior compile-expression ?type ?x y)
+
+ [::&a/jvm-land ?x y]
+ (&&host/compile-jvm-land compile-expression ?type ?x y)
+
+ [::&a/jvm-lor ?x y]
+ (&&host/compile-jvm-lor compile-expression ?type ?x y)
+
+ [::&a/jvm-lxor ?x y]
+ (&&host/compile-jvm-lxor compile-expression ?type ?x y)
+
+ [::&a/jvm-lshl ?x y]
+ (&&host/compile-jvm-lshl compile-expression ?type ?x y)
+
+ [::&a/jvm-lshr ?x y]
+ (&&host/compile-jvm-lshr compile-expression ?type ?x y)
+
+ [::&a/jvm-lushr ?x y]
+ (&&host/compile-jvm-lushr compile-expression ?type ?x y)
+ )
_
(fail "[Compiler Error] Can't compile statements as expressions.")))
diff --git a/src/lux/compiler/host.clj b/src/lux/compiler/host.clj
index 9805d2c70..18695522d 100644
--- a/src/lux/compiler/host.clj
+++ b/src/lux/compiler/host.clj
@@ -204,6 +204,20 @@
:let [_ (.visitInsn *writer* Opcodes/ACONST_NULL)]]
(return nil)))
+(defn compile-jvm-null? [compile *type* ?object]
+ (exec [*writer* &/get-writer
+ _ (compile ?object)
+ :let [$then (new Label)
+ $end (new Label)
+ _ (doto *writer*
+ (.visitJumpInsn Opcodes/IFNULL $then)
+ (.visitFieldInsn Opcodes/GETSTATIC (&host/->class "java.lang.Boolean") "FALSE" (&host/->type-signature "java.lang.Boolean"))
+ (.visitJumpInsn Opcodes/GOTO $end)
+ (.visitLabel $then)
+ (.visitFieldInsn Opcodes/GETSTATIC (&host/->class "java.lang.Boolean") "TRUE" (&host/->type-signature "java.lang.Boolean"))
+ (.visitLabel $end))]]
+ (return nil)))
+
(defn compile-jvm-new [compile *type* ?class ?classes ?args]
(exec [*writer* &/get-writer
:let [init-sig (str "(" (reduce str "" (map &host/->type-signature ?classes)) ")V")
@@ -301,3 +315,119 @@
(butlast ?exprs))
_ (compile (last ?exprs))]
(return nil)))
+
+(defn compile-jvm-try [compile *type* ?body ?catches ?finally]
+ (exec [*writer* &/get-writer
+ :let [$from (new Label)
+ $to (new Label)
+ $end (new Label)
+ $catch-finally (new Label)
+ compile-finally (if ?finally
+ (exec [_ (return nil)
+ _ (compile ?finally)
+ :let [_ (doto *writer*
+ (.visitInsn Opcodes/POP)
+ (.visitJumpInsn Opcodes/GOTO $end))]]
+ (return nil))
+ (exec [_ (return nil)
+ :let [_ (.visitJumpInsn *writer* Opcodes/GOTO $end)]]
+ (return nil)))
+ _ (.visitLabel *writer* $from)]
+ _ (compile ?body)
+ :let [_ (.visitLabel *writer* $to)]
+ _ compile-finally
+ handlers (map-m (fn [[?ex-class ?ex-arg ?catch-body]]
+ (exec [:let [$handler-start (new Label)
+ $handler-end (new Label)]
+ _ (compile ?catch-body)
+ :let [_ (.visitLabel *writer* $handler-end)]
+ _ compile-finally]
+ (return [?ex-class $handler-start $handler-end])))
+ ?catches)
+ :let [_ (.visitLabel *writer* $catch-finally)]
+ _ (if ?finally
+ (exec [_ (compile ?finally)
+ :let [_ (doto *writer*
+ (.visitInsn Opcodes/POP)
+ (.visitInsn Opcodes/ATHROW))]]
+ (return nil))
+ (exec [_ (return nil)
+ :let [_ (.visitInsn *writer* Opcodes/ATHROW)]]
+ (return nil)))
+ :let [_ (.visitJumpInsn *writer* Opcodes/GOTO $end)]
+ :let [_ (.visitLabel *writer* $end)]
+ :let [_ (doseq [[?ex-class $handler-start $handler-end] handlers]
+ (doto *writer*
+ (.visitTryCatchBlock $from $to $handler-start ?ex-class)
+ (.visitTryCatchBlock $handler-start $handler-end $catch-finally nil))
+ )
+ _ (.visitTryCatchBlock *writer* $from $to $catch-finally nil)]]
+ (return nil)))
+
+(defn compile-jvm-throw [compile *type* ?ex]
+ (exec [*writer* &/get-writer
+ _ (compile ?ex)
+ :let [_ (.visitInsn *writer* Opcodes/ATHROW)]]
+ (return nil)))
+
+(do-template [<name> <op>]
+ (defn <name> [compile *type* ?monitor]
+ (exec [*writer* &/get-writer
+ _ (compile ?monitor)
+ :let [_ (doto *writer*
+ (.visitInsn <op>)
+ (.visitInsn Opcodes/ACONST_NULL))]]
+ (return nil)))
+
+ compile-jvm-monitorenter Opcodes/MONITORENTER
+ compile-jvm-monitorexit Opcodes/MONITOREXIT
+ )
+
+(do-template [<name> <op> <from-class> <to-class>]
+ (defn <name> [compile *type* ?value]
+ (exec [*writer* &/get-writer
+ _ (compile ?value)
+ :let [_ (doto *writer*
+ (.visitInsn <op>))]]
+ (return nil)))
+
+ compile-jvm-d2f Opcodes/D2F "java.lang.Double" "java.lang.Float"
+ compile-jvm-d2i Opcodes/D2I "java.lang.Double" "java.lang.Integer"
+ compile-jvm-d2l Opcodes/D2L "java.lang.Double" "java.lang.Long"
+
+ compile-jvm-f2d Opcodes/F2D "java.lang.Float" "java.lang.Double"
+ compile-jvm-f2i Opcodes/F2I "java.lang.Float" "java.lang.Integer"
+ compile-jvm-f2l Opcodes/F2L "java.lang.Float" "java.lang.Long"
+
+ compile-jvm-i2b Opcodes/I2B "java.lang.Integer" "java.lang.Byte"
+ compile-jvm-i2c Opcodes/I2C "java.lang.Integer" "java.lang.Character"
+ compile-jvm-i2d Opcodes/I2D "java.lang.Integer" "java.lang.Double"
+ compile-jvm-i2f Opcodes/I2F "java.lang.Integer" "java.lang.Float"
+ compile-jvm-i2l Opcodes/I2L "java.lang.Integer" "java.lang.Long"
+ compile-jvm-i2s Opcodes/I2S "java.lang.Integer" "java.lang.Short"
+
+ compile-jvm-l2d Opcodes/L2D "java.lang.Long" "java.lang.Double"
+ compile-jvm-l2f Opcodes/L2F "java.lang.Long" "java.lang.Float"
+ compile-jvm-l2i Opcodes/L2I "java.lang.Long" "java.lang.Integer"
+ )
+
+(do-template [<name> <op> <from-class> <to-class>]
+ (defn <name> [compile *type* ?x ?y]
+ (exec [*writer* &/get-writer
+ _ (compile ?x)
+ _ (compile ?y)
+ :let [_ (doto *writer*
+ (.visitInsn <op>))]]
+ (return nil)))
+
+ compile-jvm-iand Opcodes/IAND "java.lang.Integer" "java.lang.Integer"
+ compile-jvm-ior Opcodes/IOR "java.lang.Integer" "java.lang.Integer"
+
+ compile-jvm-land Opcodes/LAND "java.lang.Long" "java.lang.Long"
+ compile-jvm-lor Opcodes/LOR "java.lang.Long" "java.lang.Long"
+ compile-jvm-lxor Opcodes/LXOR "java.lang.Long" "java.lang.Long"
+
+ compile-jvm-lshl Opcodes/LSHL "java.lang.Long" "java.lang.Integer"
+ compile-jvm-lshr Opcodes/LSHR "java.lang.Long" "java.lang.Integer"
+ compile-jvm-lushr Opcodes/LUSHR "java.lang.Long" "java.lang.Integer"
+ )