diff options
-rw-r--r-- | src/lux.clj | 2 | ||||
-rw-r--r-- | src/lux/analyser.clj | 19 | ||||
-rw-r--r-- | src/lux/compiler.clj | 34 | ||||
-rw-r--r-- | src/lux/parser.clj | 18 | ||||
-rw-r--r-- | src/lux/type.clj | 23 | ||||
-rw-r--r-- | test2.lux | 13 |
6 files changed, 90 insertions, 19 deletions
diff --git a/src/lux.clj b/src/lux.clj index 3c466e86f..517396182 100644 --- a/src/lux.clj +++ b/src/lux.clj @@ -20,10 +20,8 @@ ;; TODO: Add extra arities (apply2, apply3, ..., apply16) ;; TODO: When doing partial application, skip "apply" and just call constructor appropiatedly. ;; TODO: Add "new". Allow setting fields. - ;; TODO: Don't take into account newlines in strings unless they come from \n to allow better coding. ;; TODO: monitor enter & monitor exit. ;; TODO: Reinplement "if" as a macro on top of case. - ;; TODO: Eliminate the reliance of variants upon tuples for storage. ;; TODO: (let [source-code (slurp "test2.lux") diff --git a/src/lux/analyser.clj b/src/lux/analyser.clj index e21431cef..f45ed4c2d 100644 --- a/src/lux/analyser.clj +++ b/src/lux/analyser.clj @@ -764,6 +764,19 @@ [::&parser/quote ?quoted] (return (annotated [::quote ?quoted] ::&type/nothing))) +(do-template [<name> <input-tag> <output-tag>] + (defanalyser <name> + [<input-tag> ?x ?y] + (exec [=x (analyse-form* ?x) + =y (analyse-form* ?y)] + (return (annotated [<output-tag> =x =y] [::&type/object "java.lang.Integer" []])))) + + ^:private analyse-jvm-i+ ::&parser/jvm-i+ ::jvm-i+ + ^: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 + ) + (def analyse-form (try-all-m [analyse-bool analyse-int @@ -786,7 +799,11 @@ analyse-defmacro analyse-import analyse-use - analyse-quote])) + analyse-quote + analyse-jvm-i+ + analyse-jvm-i- + analyse-jvm-i* + analyse-jvm-idiv])) ;; [Interface] (defn analyse [module-name tokens] diff --git a/src/lux/compiler.clj b/src/lux/compiler.clj index d603df4df..c95beeb7f 100644 --- a/src/lux/compiler.clj +++ b/src/lux/compiler.clj @@ -1,7 +1,8 @@ (ns lux.compiler (:refer-clojure :exclude [compile]) - (:require [clojure.string :as string] - [clojure.set :as set] + (:require (clojure [string :as string] + [set :as set] + [template :refer [do-template]]) [clojure.core.match :refer [match]] (lux [util :as &util :refer [exec return* return fail fail* repeat-m try-m try-all-m map-m reduce-m @@ -76,7 +77,7 @@ (match type ::&type/any (->java-sig [::&type/object "java.lang.Object" []]) - + [::&type/object ?name []] (->type-signature ?name) @@ -879,6 +880,27 @@ [::&analyser/quote ?quoted] (compile-form (assoc *state* :form (quoted->token ?quoted)))) +(let [+int-class+ (->class "java.lang.Integer")] + (do-template [<name> <tag> <opcode>] + (defcompiler <name> + [<tag> ?x ?y] + (do (compile-form (assoc *state* :form ?x)) + (doto *writer* + (.visitTypeInsn Opcodes/CHECKCAST +int-class+) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL +int-class+ "intValue" "()I")) + (compile-form (assoc *state* :form ?y)) + (doto *writer* + (.visitTypeInsn Opcodes/CHECKCAST +int-class+) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL +int-class+ "intValue" "()I") + (.visitInsn <opcode>) + (.visitMethodInsn Opcodes/INVOKESTATIC +int-class+ "valueOf" (str "(I)" (->type-signature "java.lang.Integer")))))) + + ^:private compile-jvm-i+ ::&analyser/jvm-i+ Opcodes/IADD + ^: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 + )) + (let [+compilers+ [compile-literal compile-variant compile-tuple @@ -900,7 +922,11 @@ compile-definterface compile-import compile-use - compile-quote]] + compile-quote + compile-jvm-i+ + compile-jvm-i- + compile-jvm-i* + compile-jvm-idiv]] (defn ^:private compile-form [state] ;; (prn 'compile-form/state state) (or (some #(% state) +compilers+) diff --git a/src/lux/parser.clj b/src/lux/parser.clj index a383e78a5..bfc23fef8 100644 --- a/src/lux/parser.clj +++ b/src/lux/parser.clj @@ -180,6 +180,20 @@ ?args)] (return [::fn-call =f =args]))) +;; Java interop +(do-template [<name> <ident> <tag>] + (defparser <name> + [::&lexer/list ([[::&lexer/ident <ident>] ?x ?y] :seq)] + (exec [=x (apply-m parse-form (list ?x)) + =y (apply-m parse-form (list ?y))] + (return [<tag> =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 + ) + (def ^:private parse-form (try-all-m [parse-bool parse-int @@ -205,6 +219,10 @@ parse-definterface parse-import parse-use + parse-jvm-i+ + parse-jvm-i- + parse-jvm-i* + parse-jvm-idiv parse-fn-call])) ;; [Interface] diff --git a/src/lux/type.clj b/src/lux/type.clj index b29fcd5d1..854610de7 100644 --- a/src/lux/type.clj +++ b/src/lux/type.clj @@ -65,15 +65,20 @@ _ (update ?id =top actual)] success)])) - [[::primitive ?prim] _] - (let [as-obj (case ?prim - "boolean" [:lang.type/object "java.lang.Boolean" []] - "int" [:lang.type/object "java.lang.Integer" []] - "long" [:lang.type/object "java.lang.Long" []] - "char" [:lang.type/object "java.lang.Character" []] - "float" [:lang.type/object "java.lang.Float" []] - "double" [:lang.type/object "java.lang.Double" []])] - (solve as-obj actual)) + ;; [[::primitive ?prim] _] + ;; (let [as-obj (case ?prim + ;; "boolean" [:lang.type/object "java.lang.Boolean" []] + ;; "int" [:lang.type/object "java.lang.Integer" []] + ;; "long" [:lang.type/object "java.lang.Long" []] + ;; "char" [:lang.type/object "java.lang.Character" []] + ;; "float" [:lang.type/object "java.lang.Float" []] + ;; "double" [:lang.type/object "java.lang.Double" []])] + ;; (solve as-obj actual)) + + [[::primitive ?e-prim] [::primitive ?a-prim]] + (if (= ?e-prim ?a-prim) + success + (fail (str "Can't solve types: " (pr-str expected actual)))) [[::object ?eclass []] [::object ?aclass []]] (if (.isAssignableFrom (Class/forName ?eclass) (Class/forName ?aclass)) @@ -135,9 +135,12 @@ ## #when true] ## (meme yolo foo)) -#( (def (+ x y) - (jvm/i+ x y)) +(def (+ x y) + (do ## (:: (:: System out) (println "x = ")) (:: (:: System out) (println x)) + ## (:: (:: System out) (println "y = ")) (:: (:: System out) (println y)) + (jvm/i+ x y))) +#( (def inc (+ 1)) (def (fold f init values) @@ -180,7 +183,11 @@ (def (main args) (case (' ((~ "Oh yeah..."))) (#Form (#Cons (#Text text) #Nil)) - (:: (:: System out) (println text)) + (do (:: (:: System out) (println text)) + (:: (:: System out) (println (+ 10 20))) + (:: (:: System out) (println (jvm/i- 10 20))) + (:: (:: System out) (println (jvm/i* 10 20))) + (:: (:: System out) (println (jvm/i/ 10 2)))) )) #( |