From 7f076e6ca1a107b6b0ce54784e9b9eb2ae715771 Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Sun, 11 Jan 2015 17:55:14 -0400 Subject: - Added integer remainder. - Now, can handle boolean returns from methods. - Static functions now define a "_datum" field containing an empty instance. - Fixed a bug when analysing lambdas that made their arguments get treated like they were closure variables. --- src/lux/analyser.clj | 6 ++++- src/lux/compiler.clj | 72 +++++++++++++++++++++++++++++++++++++--------------- src/lux/parser.clj | 10 +++++--- 3 files changed, 62 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/lux/analyser.clj b/src/lux/analyser.clj index 4866ab04e..1bac77dce 100644 --- a/src/lux/analyser.clj +++ b/src/lux/analyser.clj @@ -188,7 +188,9 @@ (update-in [:env] rest) ;; (update-in [:lambda-scope 1] inc) ) - [(get-in ?state [:lambda-scope 0]) (-> ?state :env first) ?value]]]) + [(get-in ?state [:lambda-scope 0]) + (-> ?state :env first (update-in [:mappings] #(reduce dissoc % args-vars))) + ?value]]]) _ =return))))) @@ -849,6 +851,7 @@ ^:private analyse-jvm-i- ::&parser/jvm-i- ::jvm-i- ^:private analyse-jvm-i* ::&parser/jvm-i* ::jvm-i* ^:private analyse-jvm-idiv ::&parser/jvm-idiv ::jvm-idiv + ^:private analyse-jvm-irem ::&parser/jvm-irem ::jvm-irem ) (def analyse-form @@ -877,6 +880,7 @@ analyse-jvm-i- analyse-jvm-i* analyse-jvm-idiv + analyse-jvm-irem analyse-jvm-getstatic analyse-jvm-invokevirtual])) diff --git a/src/lux/compiler.clj b/src/lux/compiler.clj index 5db85d17f..9ffee56dc 100644 --- a/src/lux/compiler.clj +++ b/src/lux/compiler.clj @@ -81,6 +81,9 @@ ::&type/any (->java-sig [::&type/object "java.lang.Object" []]) + [::&type/primitive "boolean"] + "Z" + [::&type/object ?name []] (->type-signature ?name) @@ -169,6 +172,11 @@ (.visitFieldInsn Opcodes/GETSTATIC (->class (str ?owner-class "$" (normalize-ident ?name))) "_datum" "Ljava/lang/Object;" ;; (->java-sig *type*) )))) +(defcompiler ^:private compile-global-fn + [::&analyser/global-fn ?owner-class ?name] + (let [fn-class (str ?owner-class "$" (normalize-ident ?name))] + (.visitFieldInsn *writer* Opcodes/GETSTATIC (->class fn-class) "_datum" (->type-signature fn-class)))) + ;; (defcompiler ^:private compile-call ;; [::&analyser/call ?fn ?args] ;; (do (prn 'compile-call (:form ?fn) ?fn ?args) @@ -249,23 +257,27 @@ (.visitInsn Opcodes/ACONST_NULL))) )) -(defcompiler ^:private compile-jvm-invokevirtual - [::&analyser/jvm-invokevirtual ?class ?method ?classes ?object ?args] - (let [_ (prn 'compile-jvm-invokevirtual [?class ?method ?classes] '-> *type*) - method-sig (str "(" (reduce str "" (map ->type-signature ?classes)) ")" (->java-sig *type*))] - (compile-form (assoc *state* :form ?object)) - (.visitTypeInsn *writer* Opcodes/CHECKCAST (->class ?class)) - (doseq [[class-name arg] (map vector ?classes ?args)] - (do (compile-form (assoc *state* :form arg)) - (.visitTypeInsn *writer* Opcodes/CHECKCAST (->class class-name)))) - (.visitMethodInsn *writer* Opcodes/INVOKEVIRTUAL (->class ?class) ?method method-sig) - (match *type* - ::&type/nothing - (.visitInsn *writer* Opcodes/ACONST_NULL) - - [::&type/object ?oclass _] - nil) - )) +(let [boolean-class "java.lang.Boolean"] + (defcompiler ^:private compile-jvm-invokevirtual + [::&analyser/jvm-invokevirtual ?class ?method ?classes ?object ?args] + (let [_ (prn 'compile-jvm-invokevirtual [?class ?method ?classes] '-> *type*) + method-sig (str "(" (reduce str "" (map ->type-signature ?classes)) ")" (->java-sig *type*))] + (compile-form (assoc *state* :form ?object)) + (.visitTypeInsn *writer* Opcodes/CHECKCAST (->class ?class)) + (doseq [[class-name arg] (map vector ?classes ?args)] + (do (compile-form (assoc *state* :form arg)) + (.visitTypeInsn *writer* Opcodes/CHECKCAST (->class class-name)))) + (.visitMethodInsn *writer* Opcodes/INVOKEVIRTUAL (->class ?class) ?method method-sig) + (match *type* + ::&type/nothing + (.visitInsn *writer* Opcodes/ACONST_NULL) + + [::&type/primitive "boolean"] + (.visitMethodInsn *writer* Opcodes/INVOKESTATIC (->class boolean-class) "valueOf" (str "(Z)" (->type-signature boolean-class))) + + [::&type/object ?oclass _] + nil) + ))) (defcompiler ^:private compile-if [::&analyser/if ?test ?then ?else] @@ -528,6 +540,7 @@ apply-signature "(Ljava/lang/Object;)Ljava/lang/Object;" real-signature (str "(" (apply str (repeat num-args clo-field-sig)) ")" "Ljava/lang/Object;") current-class (str outer-class "$" (normalize-ident fn-name)) + self-sig (->type-signature current-class) num-captured (dec num-args) init-signature (if (not= 0 num-captured) (str "(" (apply str counter-sig (repeat num-captured clo-field-sig)) ")" "V") @@ -536,9 +549,10 @@ (let [=class (doto (new ClassWriter ClassWriter/COMPUTE_MAXS) (.visit Opcodes/V1_5 (+ Opcodes/ACC_PUBLIC Opcodes/ACC_FINAL Opcodes/ACC_SUPER) current-class nil "java/lang/Object" (into-array ["test2/Function"])) - (-> (doto (.visitField (+ Opcodes/ACC_PRIVATE Opcodes/ACC_FINAL) "_counter" counter-sig nil nil) - (.visitEnd)) - (->> (when (not= 0 num-captured))))) + (.visitField (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "_datum" self-sig nil nil) + (-> (.visitField (+ Opcodes/ACC_PRIVATE Opcodes/ACC_FINAL) "_counter" counter-sig nil nil) + (->> (when (not= 0 num-captured)))) + (.visitEnd)) =impl (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "impl" real-signature nil nil) (.visitCode) (->> (assoc *state* :form body :writer) compile-form) @@ -563,6 +577,19 @@ (.visitInsn Opcodes/RETURN) (.visitMaxs 0 0) (.visitEnd)) + =clinit (doto (.visitMethod =class Opcodes/ACC_PUBLIC "" "()V" nil nil) + (.visitCode) + (.visitTypeInsn Opcodes/NEW current-class) + (.visitInsn Opcodes/DUP) + (-> (doto (.visitLdcInsn (int 0)) + (-> (.visitInsn Opcodes/ACONST_NULL) + (->> (dotimes [_ num-captured])))) + (->> (when (> num-captured 0)))) + (.visitMethodInsn Opcodes/INVOKESPECIAL current-class "" init-signature) + (.visitFieldInsn Opcodes/PUTSTATIC current-class "_datum" self-sig) + (.visitInsn Opcodes/RETURN) + (.visitMaxs 0 0) + (.visitEnd)) =method (let [default-label (new Label) branch-labels (for [_ (range num-captured)] (new Label))] @@ -661,7 +688,7 @@ (defcompiler ^:private compile-lambda [::&analyser/lambda ?scope ?frame ?args ?body] - (let [;; _ (prn '[?scope ?frame] ?scope ?frame) + (let [_ (prn '[?scope ?frame] ?scope ?frame ?args) num-args (count ?args) outer-class (->class *class-name*) clo-field-sig (->type-signature "java.lang.Object") @@ -915,6 +942,7 @@ ^:private compile-jvm-i- ::&analyser/jvm-i- Opcodes/ISUB ^:private compile-jvm-i* ::&analyser/jvm-i* Opcodes/IMUL ^:private compile-jvm-idiv ::&analyser/jvm-idiv Opcodes/IDIV + ^:private compile-jvm-irem ::&analyser/jvm-irem Opcodes/IREM )) (let [+compilers+ [compile-literal @@ -923,6 +951,7 @@ compile-local compile-captured compile-global + compile-global-fn compile-static-call compile-call compile-dynamic-field @@ -942,6 +971,7 @@ compile-jvm-i- compile-jvm-i* compile-jvm-idiv + compile-jvm-irem compile-jvm-getstatic compile-jvm-invokevirtual]] (defn ^:private compile-form [state] diff --git a/src/lux/parser.clj b/src/lux/parser.clj index 4de0b6896..db64adf4a 100644 --- a/src/lux/parser.clj +++ b/src/lux/parser.clj @@ -202,10 +202,11 @@ =y (apply-m parse-form (list ?y))] (return [ =x =y]))) - ^:private parse-jvm-i+ "jvm/i+" ::jvm-i+ - ^:private parse-jvm-i- "jvm/i-" ::jvm-i- - ^:private parse-jvm-i* "jvm/i*" ::jvm-i* - ^:private parse-jvm-idiv "jvm/i/" ::jvm-idiv + ^:private parse-jvm-i+ "jvm/i+" ::jvm-i+ + ^:private parse-jvm-i- "jvm/i-" ::jvm-i- + ^:private parse-jvm-i* "jvm/i*" ::jvm-i* + ^:private parse-jvm-idiv "jvm/i/" ::jvm-idiv + ^:private parse-jvm-irem "jvm/irem" ::jvm-irem ) (def ^:private parse-form @@ -236,6 +237,7 @@ parse-jvm-i- parse-jvm-i* parse-jvm-idiv + parse-jvm-irem parse-jvm-getstatic parse-jvm-invokevirtual parse-fn-call])) -- cgit v1.2.3