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 +++++--- test2.lux | 47 +++++++++++++++++++++------------- 4 files changed, 92 insertions(+), 43 deletions(-) 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])) diff --git a/test2.lux b/test2.lux index 19054e699..9cea62d8a 100644 --- a/test2.lux +++ b/test2.lux @@ -67,6 +67,10 @@ [java.lang.Object _5] [java.lang.Object _6] [java.lang.Object _7] [java.lang.Object _8]]) +(def (println x) + (jvm/invokevirtual java.io.PrintStream "println" [Object] + (jvm/getstatic System out) [x])) + (def (++ xs ys) (case xs #Nil @@ -139,22 +143,26 @@ (def inc (+ 1)) -#( (def (fold f init values) - (case values - #Nil - init - (#Cons x xs) - (fold f (f init x) xs))) +(def (id x) + x) - (def length (fold inc 0)) +(def (fold f init values) + (case values + #Nil + init + (#Cons x xs) + (fold f (f init x) xs))) - (def (mod dividend divisor) - (jvm/imod dividend divisor)) +(def length (fold (lambda [l x] (inc l)) 0)) - (def (= x y) - (.equals x y)) +(def (rem dividend divisor) + (jvm/irem dividend divisor)) - (def (as-pairs list) +(def (= x y) + (jvm/invokevirtual Object "equals" [Object] + x [y])) + +#( (def (as-pairs list) (case list (#Cons x (#Cons y list*)) (#Cons [x y] (as-pairs list*)) @@ -175,10 +183,6 @@ (as-pairs steps)) (#Text "Oh no!")))) )# -(def (println x) - (jvm/invokevirtual java.io.PrintStream "println" [Object] - (jvm/getstatic System out) [x])) - ## Program (def (main args) (case (' ((~ "Oh yeah..."))) @@ -188,7 +192,16 @@ (println (inc 10)) (println (jvm/i- 10 20)) (println (jvm/i* 10 20)) - (println (jvm/i/ 10 2))) + (println (jvm/i/ 10 2)) + (let list (#Cons 1 (#Cons 2 (#Cons 3 (#Cons 4 (#Cons 5 (#Cons 6 #Nil)))))) + (do (println (fold + 0 list)) + (println (length list)))) + (println (rem 21 6)) + (println (rem 21 7)) + (println (= false false)) + (println (= false true)) + (println (= true false)) + (println (= true true))) )) #( (def (main args) -- cgit v1.2.3