diff options
author | Eduardo Julian | 2015-02-18 00:49:55 -0400 |
---|---|---|
committer | Eduardo Julian | 2015-02-18 00:49:55 -0400 |
commit | ef6c934aa876d1c7426ec567a3d7b4cf136d573e (patch) | |
tree | fa49084d3f068fb983d9cbec8986082969b6a7eb | |
parent | ff0bdbddd74a23c59e421403f82a20fd216faf56 (diff) |
Corrections to the super-refactoring: part 4
-rw-r--r-- | src/lux.clj | 12 | ||||
-rw-r--r-- | src/lux/analyser.clj | 115 | ||||
-rw-r--r-- | src/lux/analyser/base.clj | 3 | ||||
-rw-r--r-- | src/lux/analyser/case.clj | 7 | ||||
-rw-r--r-- | src/lux/analyser/env.clj | 23 | ||||
-rw-r--r-- | src/lux/analyser/host.clj | 118 | ||||
-rw-r--r-- | src/lux/analyser/lambda.clj | 160 | ||||
-rw-r--r-- | src/lux/analyser/lux.clj | 81 | ||||
-rw-r--r-- | src/lux/compiler.clj | 69 | ||||
-rw-r--r-- | src/lux/compiler/case.clj | 9 | ||||
-rw-r--r-- | src/lux/compiler/host.clj | 88 | ||||
-rw-r--r-- | src/lux/compiler/lux.clj | 23 | ||||
-rw-r--r-- | src/lux/host.clj | 5 | ||||
-rw-r--r-- | src/lux/lexer.clj | 14 | ||||
-rw-r--r-- | src/lux/parser.clj | 14 | ||||
-rw-r--r-- | src/lux/type.clj | 41 | ||||
-rw-r--r-- | src/lux/util.clj | 119 |
17 files changed, 467 insertions, 434 deletions
diff --git a/src/lux.clj b/src/lux.clj index eb81b43a0..b42d0bb42 100644 --- a/src/lux.clj +++ b/src/lux.clj @@ -1,10 +1,6 @@ (ns lux - (:require (lux [lexer :as &lexer] - [parser :as &parser] - [type :as &type] - [analyser :as &analyser] - [compiler :as &compiler]) - :reload)) + (:require [lux.compiler :as &compiler] + :reload-all)) (comment ;; TODO: Make macros monadic. @@ -23,8 +19,8 @@ ;; TODO: ;; TODO: - (time (&compiler/compile-all ["lux" ;; "test2" - ])) + (time (&compiler/compile-all ["lux"])) + (time (&compiler/compile-all ["lux" "test2"])) ;; jar cvf test2.jar *.class test2 && java -cp "test2.jar" test2 ;; cd output && jar cvf test2.jar * && java -cp "test2.jar" test2 && cd .. diff --git a/src/lux/analyser.clj b/src/lux/analyser.clj index de6058f50..a9cd8670e 100644 --- a/src/lux/analyser.clj +++ b/src/lux/analyser.clj @@ -8,149 +8,150 @@ [type :as &type] [macro :as ¯o] [host :as &host]) - (lux.analyser [base :as &] + (lux.analyser [base :as &&] [lux :as &&lux] [host :as &&host]))) ;; [Utils] (defn ^:private analyse-basic-ast [analyse-ast token] + (prn 'analyse-basic-ast token) (match token ;; Standard special forms - [::&parser/bool ?value] - (return (list [::&/Expression [::bool ?value] [::&type/Data "java.lang.Boolean"]])) + [::&parser/Bool ?value] + (return (list [::&&/Expression [::&&/bool ?value] [::&type/Data "java.lang.Boolean"]])) - [::&parser/int ?value] - (return (list [::&/Expression [::int ?value] [::&type/Data "java.lang.Long"]])) + [::&parser/Int ?value] + (return (list [::&&/Expression [::&&/int ?value] [::&type/Data "java.lang.Long"]])) - [::&parser/real ?value] - (return (list [::&/Expression [::real ?value] [::&type/Data "java.lang.Double"]])) + [::&parser/Real ?value] + (return (list [::&&/Expression [::&&/real ?value] [::&type/Data "java.lang.Double"]])) - [::&parser/char ?value] - (return (list [::&/Expression [::char ?value] [::&type/Data "java.lang.Character"]])) + [::&parser/Char ?value] + (return (list [::&&/Expression [::&&/char ?value] [::&type/Data "java.lang.Character"]])) - [::&parser/text ?value] - (return (list [::&/Expression [::text ?value] [::&type/Data "java.lang.String"]])) + [::&parser/Text ?value] + (return (list [::&&/Expression [::&&/text ?value] [::&type/Data "java.lang.String"]])) - [::&parser/tuple ?elems] + [::&parser/Tuple ?elems] (&&lux/analyse-tuple analyse-ast ?elems) - [::&parser/tag ?tag] - (return (list [::&/Expression [::variant ?tag (list)] [::&type/Variant {?tag [::&type/Tuple (list)]}]])) + [::&parser/Tag ?tag] + (return (list [::&&/Expression [::&&/variant ?tag (list)] [::&type/Variant {?tag [::&type/Tuple (list)]}]])) - [::&parser/ident ?ident] + [::&parser/Ident ?ident] (&&lux/analyse-ident analyse-ast ?ident) - [::&parser/form ([[::&parser/ident "case'"] ?variant & ?branches] :seq)] + [::&parser/Form ([[::&parser/Ident "case'"] ?variant & ?branches] :seq)] (&&lux/analyse-case analyse-ast ?variant ?branches) - [::&parser/form ([[::&parser/ident "lambda'"] [::&parser/ident ?self] [::&parser/ident ?arg] ?body] :seq)] + [::&parser/Form ([[::&parser/Ident "lambda'"] [::&parser/Ident ?self] [::&parser/Ident ?arg] ?body] :seq)] (&&lux/analyse-lambda analyse-ast ?self ?arg ?body) - [::&parser/form ([[::&parser/ident "def'"] [::&parser/ident ?name] ?value] :seq)] + [::&parser/Form ([[::&parser/Ident "def'"] [::&parser/Ident ?name] ?value] :seq)] (&&lux/analyse-def analyse-ast ?name ?value) - [::&parser/form ([[::&parser/ident "declare-macro"] [::&parser/ident ?ident]] :seq)] + [::&parser/Form ([[::&parser/Ident "declare-macro"] [::&parser/Ident ?ident]] :seq)] (&&lux/analyse-declare-macro ?ident) - [::&parser/form ([[::&parser/ident "require"] [::&parser/text ?path]] :seq)] + [::&parser/Form ([[::&parser/Ident "require"] [::&parser/Text ?path]] :seq)] (&&lux/analyse-require analyse-ast ?path) ;; Host special forms - [::&parser/form ([[::&parser/ident "exec"] & ?exprs] :seq)] + [::&parser/Form ([[::&parser/Ident "exec"] & ?exprs] :seq)] (&&host/analyse-exec analyse-ast ?exprs) ;; Integer arithmetic - [::&parser/form ([[::&parser/ident "jvm;iadd"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;iadd"] ?x ?y] :seq)] (&&host/analyse-jvm-iadd analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;isub"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;isub"] ?x ?y] :seq)] (&&host/analyse-jvm-isub analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;imul"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;imul"] ?x ?y] :seq)] (&&host/analyse-jvm-imul analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;idiv"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;idiv"] ?x ?y] :seq)] (&&host/analyse-jvm-idiv analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;irem"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;irem"] ?x ?y] :seq)] (&&host/analyse-jvm-irem analyse-ast ?x ?y) ;; Long arithmetic - [::&parser/form ([[::&parser/ident "jvm;ladd"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;ladd"] ?x ?y] :seq)] (&&host/analyse-jvm-ladd analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;lsub"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;lsub"] ?x ?y] :seq)] (&&host/analyse-jvm-lsub analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;lmul"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;lmul"] ?x ?y] :seq)] (&&host/analyse-jvm-lmul analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;ldiv"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;ldiv"] ?x ?y] :seq)] (&&host/analyse-jvm-ldiv analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;lrem"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;lrem"] ?x ?y] :seq)] (&&host/analyse-jvm-lrem analyse-ast ?x ?y) ;; Float arithmetic - [::&parser/form ([[::&parser/ident "jvm;fadd"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;fadd"] ?x ?y] :seq)] (&&host/analyse-jvm-fadd analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;fsub"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;fsub"] ?x ?y] :seq)] (&&host/analyse-jvm-fsub analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;fmul"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;fmul"] ?x ?y] :seq)] (&&host/analyse-jvm-fmul analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;fdiv"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;fdiv"] ?x ?y] :seq)] (&&host/analyse-jvm-fdiv analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;frem"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;frem"] ?x ?y] :seq)] (&&host/analyse-jvm-frem analyse-ast ?x ?y) ;; Double arithmetic - [::&parser/form ([[::&parser/ident "jvm;dadd"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;dadd"] ?x ?y] :seq)] (&&host/analyse-jvm-dadd analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;dsub"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;dsub"] ?x ?y] :seq)] (&&host/analyse-jvm-dsub analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;dmul"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;dmul"] ?x ?y] :seq)] (&&host/analyse-jvm-dmul analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;ddiv"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;ddiv"] ?x ?y] :seq)] (&&host/analyse-jvm-ddiv analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;drem"] ?x ?y] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;drem"] ?x ?y] :seq)] (&&host/analyse-jvm-drem analyse-ast ?x ?y) - [::&parser/form ([[::&parser/ident "jvm;getstatic"] [::&parser/ident ?class] [::&parser/ident ?field]] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;getstatic"] [::&parser/Ident ?class] [::&parser/Ident ?field]] :seq)] (&&host/analyse-jvm-getstatic analyse-ast ?class ?field) - [::&parser/form ([[::&parser/ident "jvm;getfield"] [::&parser/ident ?class] [::&parser/ident ?field] ?object] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;getfield"] [::&parser/Ident ?class] [::&parser/Ident ?field] ?object] :seq)] (&&host/analyse-jvm-getfield analyse-ast ?class ?field ?object) - [::&parser/form ([[::&parser/ident "jvm;invokestatic"] [::&parser/ident ?class] [::&parser/text ?method] [::&parser/tuple ?classes] [::&parser/tuple ?args]] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;invokestatic"] [::&parser/Ident ?class] [::&parser/Text ?method] [::&parser/Tuple ?classes] [::&parser/Tuple ?args]] :seq)] (&&host/analyse-jvm-invokestatic analyse-ast ?class ?method ?classes ?args) - [::&parser/form ([[::&parser/ident "jvm;invokevirtual"] [::&parser/ident ?class] [::&parser/text ?method] [::&parser/tuple ?classes] ?object [::&parser/tuple ?args]] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;invokevirtual"] [::&parser/Ident ?class] [::&parser/Text ?method] [::&parser/Tuple ?classes] ?object [::&parser/Tuple ?args]] :seq)] (&&host/analyse-jvm-invokevirtual analyse-ast ?class ?method ?classes ?object ?args) - [::&parser/form ([[::&parser/ident "jvm;new"] [::&parser/ident ?class] [::&parser/tuple ?classes] [::&parser/tuple ?args]] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;new"] [::&parser/Ident ?class] [::&parser/Tuple ?classes] [::&parser/Tuple ?args]] :seq)] (&&host/analyse-jvm-new analyse-ast ?class ?classes ?args) - [::&parser/form ([[::&parser/ident "jvm;new-array"] [::&parser/ident ?class] [::&parser/int ?length]] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;new-array"] [::&parser/Ident ?class] [::&parser/Int ?length]] :seq)] (&&host/analyse-jvm-new-array analyse-ast ?class ?length) - [::&parser/form ([[::&parser/ident "jvm;aastore"] ?array [::&parser/int ?idx] ?elem] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;aastore"] ?array [::&parser/Int ?idx] ?elem] :seq)] (&&host/analyse-jvm-aastore analyse-ast ?array ?idx ?elem) - [::&parser/form ([[::&parser/ident "jvm;aaload"] ?array [::&parser/int ?idx]] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;aaload"] ?array [::&parser/Int ?idx]] :seq)] (&&host/analyse-jvm-aaload analyse-ast ?array ?idx) - [::&parser/form ([[::&parser/ident "jvm;class"] [::&parser/ident ?name] [::&parser/ident ?super-class] [::&parser/tuple ?fields]] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;class"] [::&parser/Ident ?name] [::&parser/Ident ?super-class] [::&parser/Tuple ?fields]] :seq)] (&&host/analyse-jvm-class analyse-ast ?name ?super-class ?fields) - [::&parser/form ([[::&parser/ident "jvm;interface"] [::&parser/ident ?name] & ?members] :seq)] + [::&parser/Form ([[::&parser/Ident "jvm;interface"] [::&parser/Ident ?name] & ?members] :seq)] (&&host/analyse-jvm-interface analyse-ast ?name ?members) _ @@ -158,12 +159,13 @@ (defn ^:private analyse-ast [token] (match token - [::&parser/form ([[::&parser/tag ?tag] & ?data] :seq)] + [::&parser/Form ([[::&parser/Tag ?tag] & ?data] :seq)] (exec [=data (mapcat-m analyse-ast ?data) - =data-types (map-m &/expr-type =data)] - (return (list [::&/Expression [::variant ?tag =data] [::&type/Variant {?tag [::&type/Tuple =data-types]}]]))) + :let [_ (prn '=data =data)] + =data-types (map-m &&/expr-type =data)] + (return (list [::&&/Expression [::&&/variant ?tag =data] [::&type/Variant {?tag [::&type/Tuple =data-types]}]]))) - [::&parser/form ([?fn & ?args] :seq)] + [::&parser/Form ([?fn & ?args] :seq)] (try-all-m [(&&lux/analyse-call analyse-ast ?fn ?args) (analyse-basic-ast analyse-ast token)]) @@ -172,5 +174,6 @@ ;; [Resources] (def analyse - (exec [asts &parser/parse] + (exec [asts &parser/parse + :let [_ (prn 'analyse/asts asts)]] (mapcat-m analyse-ast asts))) diff --git a/src/lux/analyser/base.clj b/src/lux/analyser/base.clj index 713b58f18..4ed3ef569 100644 --- a/src/lux/analyser/base.clj +++ b/src/lux/analyser/base.clj @@ -6,12 +6,13 @@ ;; [Resources] (defn expr-type [syntax+] + (prn 'expr-type syntax+) (match syntax+ [::Expression _ type] (return type) _ - (fail "Can't retrieve the type of a non-expression."))) + (fail "[Analyser Error] Can't retrieve the type of a non-expression."))) (defn analyse-1 [analyse elem] (exec [output (analyse elem)] diff --git a/src/lux/analyser/case.clj b/src/lux/analyser/case.clj index 8a914ab70..8fa8ff29f 100644 --- a/src/lux/analyser/case.clj +++ b/src/lux/analyser/case.clj @@ -5,7 +5,8 @@ assert!]] [parser :as &parser] [type :as &type]) - (lux.analyser [env :as &env]))) + (lux.analyser [base :as &&] + [env :as &env]))) ;; [Resources] (defn locals [member] @@ -22,12 +23,12 @@ _ (list))) -(defn analyse-branch [analyse-1 max-registers [bindings body]] +(defn analyse-branch [analyse max-registers [bindings body]] (reduce (fn [body* name] (&env/with-local name :local &type/+dont-care-type+ body*)) (reduce (fn [body* _] (&env/with-local "#" :local &type/+dont-care-type+ body*)) - (analyse-1 body) + (&&/analyse-1 analyse body) (range (- max-registers (count bindings)))) bindings)) diff --git a/src/lux/analyser/env.clj b/src/lux/analyser/env.clj index ef5620e77..177aa54dd 100644 --- a/src/lux/analyser/env.clj +++ b/src/lux/analyser/env.clj @@ -1,8 +1,9 @@ (ns lux.analyser.env (:require [clojure.core.match :refer [match]] (lux [util :as &util :refer [exec return fail - try-all-m map-m mapcat-m reduce-m - assert!]]))) + if-m try-all-m map-m mapcat-m reduce-m + assert!]]) + [lux.analyser.base :as &&])) ;; [Resources] (def next-local-idx @@ -24,7 +25,7 @@ (defn annotate [module name access type] (fn [state] (let [full-name (str module &util/+name-separator+ name) - bound [::Expression [::global module name] type]] + bound [::&&/Expression [::&&/global module name] type]] [::&util/ok [(-> state (assoc-in [::&util/modules module name] {:args-n [:None] :access access @@ -39,11 +40,11 @@ nil]])) (defn define [module name] - (exec [? annotated? - _ (assert! ? (str "[Analyser Error] Can't define an unannotated element: " name))] - (fn [state] - [::&util/ok [(assoc-in state [::&util/modules module name :defined?] true) - nil]]))) + (if-m (annotated? module name) + (fn [state] + [::&util/ok [(assoc-in state [::&util/modules module name :defined?] true) + nil]]) + (fail (str "[Analyser Error] Can't define an unannotated element: " name)))) (defn with-local [name mode type body] (fn [state] @@ -51,11 +52,11 @@ =return (body (update-in state [::&util/local-envs] (fn [[top & stack]] (let [bound-unit (case mode - :self [::self (list)] - :local [::local (get-in top [:locals :counter])])] + :self [::&&/self (list)] + :local [::&&/local (get-in top [:locals :counter])])] (cons (-> top (update-in [:locals :counter] inc) - (assoc-in [:locals :mappings name] [::Expression bound-unit type])) + (assoc-in [:locals :mappings name] [::&&/Expression bound-unit type])) stack)))))] (match =return [::&util/ok [?state ?value]] diff --git a/src/lux/analyser/host.clj b/src/lux/analyser/host.clj index d9804f9e8..5a7585226 100644 --- a/src/lux/analyser/host.clj +++ b/src/lux/analyser/host.clj @@ -7,12 +7,12 @@ [parser :as &parser] [type :as &type] [host :as &host]) - (lux.analyser [base :as &]))) + (lux.analyser [base :as &&]))) ;; [Utils] (defn ^:private extract-ident [ident] (match ident - [::&parser/ident ?ident] + [::&parser/Ident ?ident] (return ?ident) _ @@ -22,88 +22,88 @@ (do-template [<name> <ident> <output-tag> <wrapper-class>] (defn <name> [analyse ?x ?y] (exec [:let [=type [::&type/Data <wrapper-class>]] - [=x =y] (&/analyse-2 analyse ?x ?y) - =x-type (&/expr-type =x) - =y-type (&/expr-type =y) + [=x =y] (&&/analyse-2 analyse ?x ?y) + =x-type (&&/expr-type =x) + =y-type (&&/expr-type =y) _ (&type/solve =type =x-type) _ (&type/solve =type =y-type)] - (return (list [::&/Expression [<output-tag> =x =y] =type])))) - - analyse-jvm-iadd "jvm;iadd" ::jvm-iadd "java.lang.Integer" - analyse-jvm-isub "jvm;isub" ::jvm-isub "java.lang.Integer" - analyse-jvm-imul "jvm;imul" ::jvm-imul "java.lang.Integer" - analyse-jvm-idiv "jvm;idiv" ::jvm-idiv "java.lang.Integer" - analyse-jvm-irem "jvm;irem" ::jvm-irem "java.lang.Integer" - - analyse-jvm-ladd "jvm;ladd" ::jvm-ladd "java.lang.Long" - analyse-jvm-lsub "jvm;lsub" ::jvm-lsub "java.lang.Long" - analyse-jvm-lmul "jvm;lmul" ::jvm-lmul "java.lang.Long" - analyse-jvm-ldiv "jvm;ldiv" ::jvm-ldiv "java.lang.Long" - analyse-jvm-lrem "jvm;lrem" ::jvm-lrem "java.lang.Long" - - analyse-jvm-fadd "jvm;fadd" ::jvm-fadd "java.lang.Float" - analyse-jvm-fsub "jvm;fsub" ::jvm-fsub "java.lang.Float" - analyse-jvm-fmul "jvm;fmul" ::jvm-fmul "java.lang.Float" - analyse-jvm-fdiv "jvm;fdiv" ::jvm-fdiv "java.lang.Float" - analyse-jvm-frem "jvm;frem" ::jvm-frem "java.lang.Float" - - analyse-jvm-dadd "jvm;dadd" ::jvm-dadd "java.lang.Double" - analyse-jvm-dsub "jvm;dsub" ::jvm-dsub "java.lang.Double" - analyse-jvm-dmul "jvm;dmul" ::jvm-dmul "java.lang.Double" - analyse-jvm-ddiv "jvm;ddiv" ::jvm-ddiv "java.lang.Double" - analyse-jvm-drem "jvm;drem" ::jvm-drem "java.lang.Double" + (return (list [::&&/Expression [<output-tag> =x =y] =type])))) + + analyse-jvm-iadd "jvm;iadd" ::&&/jvm-iadd "java.lang.Integer" + analyse-jvm-isub "jvm;isub" ::&&/jvm-isub "java.lang.Integer" + analyse-jvm-imul "jvm;imul" ::&&/jvm-imul "java.lang.Integer" + analyse-jvm-idiv "jvm;idiv" ::&&/jvm-idiv "java.lang.Integer" + analyse-jvm-irem "jvm;irem" ::&&/jvm-irem "java.lang.Integer" + + analyse-jvm-ladd "jvm;ladd" ::&&/jvm-ladd "java.lang.Long" + analyse-jvm-lsub "jvm;lsub" ::&&/jvm-lsub "java.lang.Long" + analyse-jvm-lmul "jvm;lmul" ::&&/jvm-lmul "java.lang.Long" + analyse-jvm-ldiv "jvm;ldiv" ::&&/jvm-ldiv "java.lang.Long" + analyse-jvm-lrem "jvm;lrem" ::&&/jvm-lrem "java.lang.Long" + + analyse-jvm-fadd "jvm;fadd" ::&&/jvm-fadd "java.lang.Float" + analyse-jvm-fsub "jvm;fsub" ::&&/jvm-fsub "java.lang.Float" + analyse-jvm-fmul "jvm;fmul" ::&&/jvm-fmul "java.lang.Float" + analyse-jvm-fdiv "jvm;fdiv" ::&&/jvm-fdiv "java.lang.Float" + analyse-jvm-frem "jvm;frem" ::&&/jvm-frem "java.lang.Float" + + analyse-jvm-dadd "jvm;dadd" ::&&/jvm-dadd "java.lang.Double" + analyse-jvm-dsub "jvm;dsub" ::&&/jvm-dsub "java.lang.Double" + analyse-jvm-dmul "jvm;dmul" ::&&/jvm-dmul "java.lang.Double" + analyse-jvm-ddiv "jvm;ddiv" ::&&/jvm-ddiv "java.lang.Double" + analyse-jvm-drem "jvm;drem" ::&&/jvm-drem "java.lang.Double" ) (defn analyse-jvm-getstatic [analyse ?class ?field] (exec [=class (&host/full-class-name ?class) =type (&host/lookup-static-field =class ?field)] - (return (list [::&/Expression [::jvm-getstatic =class ?field] =type])))) + (return (list [::&&/Expression [::&&/jvm-getstatic =class ?field] =type])))) (defn analyse-jvm-getfield [analyse ?class ?field ?object] (exec [=class (&host/full-class-name ?class) =type (&host/lookup-static-field =class ?field) - =object (&/analyse-1 ?object)] - (return (list [::&/Expression [::jvm-getfield =class ?field =object] =type])))) + =object (&&/analyse-1 ?object)] + (return (list [::&&/Expression [::&&/jvm-getfield =class ?field =object] =type])))) (defn analyse-jvm-invokestatic [analyse ?class ?method ?classes ?args] (exec [=class (&host/full-class-name ?class) =classes (map-m &host/extract-jvm-param ?classes) =return (&host/lookup-virtual-method =class ?method =classes) =args (mapcat-m analyse ?args)] - (return (list [::&/Expression [::jvm-invokestatic =class ?method =classes =args] =return])))) + (return (list [::&&/Expression [::&&/jvm-invokestatic =class ?method =classes =args] =return])))) (defn analyse-jvm-invokevirtual [analyse ?class ?method ?classes ?object ?args] (exec [=class (&host/full-class-name ?class) =classes (map-m &host/extract-jvm-param ?classes) =return (&host/lookup-virtual-method =class ?method =classes) - =object (&/analyse-1 ?object) + =object (&&/analyse-1 ?object) =args (mapcat-m analyse ?args)] - (return (list [::&/Expression [::jvm-invokevirtual =class ?method =classes =object =args] =return])))) + (return (list [::&&/Expression [::&&/jvm-invokevirtual =class ?method =classes =object =args] =return])))) (defn analyse-jvm-new [analyse ?class ?classes ?args] (exec [=class (&host/full-class-name ?class) =classes (map-m &host/extract-jvm-param ?classes) =args (mapcat-m analyse ?args)] - (return (list [::&/Expression [::jvm-new =class =classes =args] [::&type/Data =class]])))) + (return (list [::&&/Expression [::&&/jvm-new =class =classes =args] [::&type/Data =class]])))) (defn analyse-jvm-new-array [analyse ?class ?length] (exec [=class (&host/full-class-name ?class)] - (return (list [::&/Expression [::jvm-new-array =class ?length] [::&type/Array [::&type/Data =class]]])))) + (return (list [::&&/Expression [::&&/jvm-new-array =class ?length] [::&type/Array [::&type/Data =class]]])))) (defn analyse-jvm-aastore [analyse ?array ?idx ?elem] - (exec [[=array =elem] (&/analyse-2 ?array ?elem) - =array-type (&/expr-type =array)] - (return (list [::&/Expression [::jvm-aastore =array ?idx =elem] =array-type])))) + (exec [[=array =elem] (&&/analyse-2 ?array ?elem) + =array-type (&&/expr-type =array)] + (return (list [::&&/Expression [::&&/jvm-aastore =array ?idx =elem] =array-type])))) (defn analyse-jvm-aaload [analyse ?array ?idx] - (exec [=array (&/analyse-1 ?array) - =array-type (&/expr-type =array)] - (return (list [::&/Expression [::jvm-aaload =array ?idx] =array-type])))) + (exec [=array (&&/analyse-1 ?array) + =array-type (&&/expr-type =array)] + (return (list [::&&/Expression [::&&/jvm-aaload =array ?idx] =array-type])))) (defn analyse-jvm-class [analyse ?name ?super-class ?fields] (exec [?fields (map-m (fn [?field] (match ?field - [::&parser/tuple ([[::&parser/ident ?class] [::&parser/ident ?field-name]] :seq)] + [::&parser/Tuple ([[::&parser/Ident ?class] [::&parser/Ident ?field-name]] :seq)] (return [?class ?field-name]) _ @@ -113,27 +113,29 @@ [field {:access :public :type class}]))] $module &util/get-module-name] - (return (list [::&/Statement [::jvm-class [$module ?name] ?super-class =fields {}]])))) + (return (list [::&&/Statement [::&&/jvm-class $module ?name ?super-class =fields {}]])))) (defn analyse-jvm-interface [analyse ?name ?members] - (exec [?members (map-m #(match % - [::&parser/form ([[::&parser/ident ":"] [::&parser/ident ?member-name] - [::&parser/form ([[::&parser/ident "->"] [::&parser/tuple ?inputs] [::&parser/ident ?output]] :seq)]] - :seq)] - (exec [?inputs (map-m extract-ident ?inputs)] - (return [?member-name [?inputs ?output]])) - - _ - (fail "")) + (prn 'analyse-jvm-interface ?name ?members) + (exec [?members (map-m (fn [member] + (match member + [::&parser/Form ([[::&parser/Ident ":"] [::&parser/Ident ?member-name] + [::&parser/Form ([[::&parser/Ident "->"] [::&parser/Tuple ?inputs] [::&parser/Ident ?output]] :seq)]] + :seq)] + (exec [?inputs (map-m extract-ident ?inputs)] + (return [?member-name [?inputs ?output]])) + + _ + (fail ""))) ?members) :let [=methods (into {} (for [[method [inputs output]] ?members] [method {:access :public :type [inputs output]}]))] $module &util/get-module-name] - (return (list [::&/Statement [::jvm-interface [$module ?name] {} =methods]])))) + (return (list [::&&/Statement [::&&/jvm-interface $module ?name =methods]])))) (defn analyse-exec [analyse ?exprs] (exec [_ (assert! (count ?exprs) "\"exec\" expressions can't have empty bodies.") =exprs (mapcat-m analyse ?exprs) - =exprs-types (map-m &/expr-type =exprs)] - (return (list [::&/Expression [::do =exprs] (last =exprs-types)])))) + =exprs-types (map-m &&/expr-type =exprs)] + (return (list [::&&/Expression [::&&/exec =exprs] (last =exprs-types)])))) diff --git a/src/lux/analyser/lambda.clj b/src/lux/analyser/lambda.clj index 2d08ee338..dab4e8901 100644 --- a/src/lux/analyser/lambda.clj +++ b/src/lux/analyser/lambda.clj @@ -3,7 +3,8 @@ (lux [util :as &util :refer [exec return fail try-all-m map-m mapcat-m reduce-m assert!]]) - (lux.analyser [env :as &env]))) + (lux.analyser [base :as &&] + [env :as &env]))) ;; [Resource] (defn with-lambda [self self-type arg arg-type body] @@ -17,142 +18,139 @@ (defn close-over [scope ident register frame] (match register - [::Expression _ register-type] - (let [register* [::Expression [::captured scope (get-in frame [:closure :counter]) register] register-type]] + [::&&/Expression _ register-type] + (let [register* [::&&/Expression [::&&/captured scope (get-in frame [:closure :counter]) register] register-type]] [register* (update-in frame [:closure] #(-> % (update-in [:counter] inc) (assoc-in [:mappings ident] register*)))]))) (defn raise-expr [arg syntax] (match syntax - [::Expression ?form ?type] + [::&&/Expression ?form ?type] (match ?form - [::bool ?value] + [::&&/bool ?value] syntax - [::int ?value] + [::&&/int ?value] syntax - [::real ?value] + [::&&/real ?value] syntax - [::char ?value] + [::&&/char ?value] syntax - [::text ?value] + [::&&/text ?value] syntax - [::tuple ?members] - [::Expression [::tuple (map (partial raise-expr arg) ?members)] ?type] + [::&&/tuple ?members] + [::&&/Expression [::&&/tuple (map (partial raise-expr arg) ?members)] ?type] - [::variant ?tag ?members] - [::Expression [::variant ?tag (map (partial raise-expr arg) ?members)] ?type] + [::&&/variant ?tag ?members] + [::&&/Expression [::&&/variant ?tag (map (partial raise-expr arg) ?members)] ?type] - [::local ?idx] - [::Expression [::local (inc ?idx)] ?type] + [::&&/local ?idx] + [::&&/Expression [::&&/local (inc ?idx)] ?type] - [::captured _ _ ?source] + [::&&/captured _ _ ?source] ?source - [::self ?curried] - [::Expression [::self (cons arg (map (partial raise-expr arg) ?curried))] ?type] + [::&&/self ?curried] + [::&&/Expression [::&&/self (cons arg (map (partial raise-expr arg) ?curried))] ?type] - [::global _ _] + [::&&/global _ _] syntax - [::case ?variant ?base ?num-bindings ?branches] - [::Expression [::case (raise-expr arg ?variant) (inc ?base) ?num-bindings - (for [[?pattern ?body] ?branches] - [?pattern (raise-expr arg ?body)])] + [::&&/case ?variant ?base ?num-bindings ?branches] + [::&&/Expression [::&&/case (raise-expr arg ?variant) (inc ?base) ?num-bindings + (for [[?pattern ?body] ?branches] + [?pattern (raise-expr arg ?body)])] ?type] - [::lambda ?scope ?captured ?args ?value] - [::Expression [::lambda (pop ?scope) - (into {} (for [[?name ?sub-syntax] ?captured] - [?name (raise-expr arg ?sub-syntax)])) - ?args - ?value] + [::&&/lambda ?scope ?captured ?args ?value] + [::&&/Expression [::&&/lambda (pop ?scope) + (into {} (for [[?name ?sub-syntax] ?captured] + [?name (raise-expr arg ?sub-syntax)])) + ?args + ?value] ?type] - [::call ?func ?args] - [::Expression [::call (raise-expr arg ?func) (map (partial raise-expr arg) ?args)] ?type] + [::&&/call ?func ?args] + [::&&/Expression [::&&/call (raise-expr arg ?func) (map (partial raise-expr arg) ?args)] ?type] - [::do ?asts] - [::Expression [::do (map (partial raise-expr arg) ?asts)] ?type] + [::&&/exec ?asts] + [::&&/Expression [::&&/exec (map (partial raise-expr arg) ?asts)] ?type] - [::jvm-getstatic _ _] + [::&&/jvm-getstatic _ _] syntax - [::jvm-invokevirtual ?class ?method ?arg-classes ?obj ?args] - [::Expression [::jvm-invokevirtual ?class ?method ?arg-classes - (raise-expr arg ?obj) - (map (partial raise-expr arg) ?args)] + [::&&/jvm-invokevirtual ?class ?method ?arg-classes ?obj ?args] + [::&&/Expression [::&&/jvm-invokevirtual ?class ?method ?arg-classes + (raise-expr arg ?obj) + (map (partial raise-expr arg) ?args)] ?type] ;; Integer arithmetic - [::jvm-iadd ?x ?y] - [::Expression [::jvm-iadd (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-iadd ?x ?y] + [::&&/Expression [::&&/jvm-iadd (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - [::jvm-isub ?x ?y] - [::Expression [::jvm-isub (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-isub ?x ?y] + [::&&/Expression [::&&/jvm-isub (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - [::jvm-imul ?x ?y] - [::Expression [::jvm-imul (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-imul ?x ?y] + [::&&/Expression [::&&/jvm-imul (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - [::jvm-idiv ?x ?y] - [::Expression [::jvm-idiv (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-idiv ?x ?y] + [::&&/Expression [::&&/jvm-idiv (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - [::jvm-irem ?x ?y] - [::Expression [::jvm-irem (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-irem ?x ?y] + [::&&/Expression [::&&/jvm-irem (raise-expr arg ?x) (raise-expr arg ?y)] ?type] ;; Long arithmetic - [::jvm-ladd ?x ?y] - [::Expression [::jvm-ladd (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-ladd ?x ?y] + [::&&/Expression [::&&/jvm-ladd (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - [::jvm-lsub ?x ?y] - [::Expression [::jvm-lsub (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-lsub ?x ?y] + [::&&/Expression [::&&/jvm-lsub (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - [::jvm-lmul ?x ?y] - [::Expression [::jvm-lmul (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-lmul ?x ?y] + [::&&/Expression [::&&/jvm-lmul (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - [::jvm-ldiv ?x ?y] - [::Expression [::jvm-ldiv (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-ldiv ?x ?y] + [::&&/Expression [::&&/jvm-ldiv (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - [::jvm-lrem ?x ?y] - [::Expression [::jvm-lrem (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-lrem ?x ?y] + [::&&/Expression [::&&/jvm-lrem (raise-expr arg ?x) (raise-expr arg ?y)] ?type] ;; Float arithmetic - [::jvm-fadd ?x ?y] - [::Expression [::jvm-fadd (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-fadd ?x ?y] + [::&&/Expression [::&&/jvm-fadd (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - [::jvm-fsub ?x ?y] - [::Expression [::jvm-fsub (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-fsub ?x ?y] + [::&&/Expression [::&&/jvm-fsub (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - [::jvm-fmul ?x ?y] - [::Expression [::jvm-fmul (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-fmul ?x ?y] + [::&&/Expression [::&&/jvm-fmul (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - [::jvm-fdiv ?x ?y] - [::Expression [::jvm-fdiv (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-fdiv ?x ?y] + [::&&/Expression [::&&/jvm-fdiv (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - [::jvm-frem ?x ?y] - [::Expression [::jvm-frem (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-frem ?x ?y] + [::&&/Expression [::&&/jvm-frem (raise-expr arg ?x) (raise-expr arg ?y)] ?type] ;; Double arithmetic - [::jvm-dadd ?x ?y] - [::Expression [::jvm-dadd (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-dadd ?x ?y] + [::&&/Expression [::&&/jvm-dadd (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - [::jvm-dsub ?x ?y] - [::Expression [::jvm-dsub (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-dsub ?x ?y] + [::&&/Expression [::&&/jvm-dsub (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - [::jvm-dmul ?x ?y] - [::Expression [::jvm-dmul (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-dmul ?x ?y] + [::&&/Expression [::&&/jvm-dmul (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - [::jvm-ddiv ?x ?y] - [::Expression [::jvm-ddiv (raise-expr arg ?x) (raise-expr arg ?y)] ?type] + [::&&/jvm-ddiv ?x ?y] + [::&&/Expression [::&&/jvm-ddiv (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - [::jvm-drem ?x ?y] - [::Expression [::jvm-drem (raise-expr arg ?x) (raise-expr arg ?y)] ?type] - - _ - (assert false syntax) + [::&&/jvm-drem ?x ?y] + [::&&/Expression [::&&/jvm-drem (raise-expr arg ?x) (raise-expr arg ?y)] ?type] ))) diff --git a/src/lux/analyser/lux.clj b/src/lux/analyser/lux.clj index b7aa46cee..ba6f40ff3 100644 --- a/src/lux/analyser/lux.clj +++ b/src/lux/analyser/lux.clj @@ -2,7 +2,7 @@ (:require (clojure [template :refer [do-template]]) [clojure.core.match :refer [match]] (lux [util :as &util :refer [exec return fail - try-all-m map-m mapcat-m reduce-m + if-m try-all-m map-m mapcat-m reduce-m assert!]] [parser :as &parser] [type :as &type] @@ -19,11 +19,11 @@ =elems-types (map-m &/expr-type =elems) ;; :let [_ (prn 'analyse-tuple =elems)] ] - (return (list [::&/Expression [::tuple =elems] [::&type/Tuple =elems-types]])))) + (return (list [::&/Expression [::&/tuple =elems] [::&type/Tuple =elems-types]])))) (defn analyse-ident [analyse ident] (fn [state] - (let [[top & stack*] (::local-envs state)] + (let [[top & stack*] (::&util/local-envs state)] (if-let [=bound (or (get-in top [:locals :mappings ident]) (get-in top [:closure :mappings ident]))] [::&util/ok [state (list =bound)]] @@ -52,7 +52,7 @@ (match =fn [::&/Expression =fn-form =fn-type] (match =fn-form - [::global ?module ?name] + [::&/global ?module ?name] (exec [macro? (&&env/macro? ?module ?name)] (if macro? (let [macro-class (&host/location (list ?name ?module)) @@ -66,11 +66,11 @@ (if (> needs-num provides-num) [needs-num [::&type/function (drop provides-num ?fargs) ?freturn]] [needs-num &type/+dont-care-type+])))]] - (return (list [::&/Expression [::static-call needs-num =fn =args] =return-type]))))) + (return (list [::&/Expression [::&/static-call needs-num =fn =args] =return-type]))))) _ (exec [=args (mapcat-m analyse ?args)] - (return (list [::&/Expression [::call =fn =args] &type/+dont-care-type+])))) + (return (list [::&/Expression [::&/call =fn =args] &type/+dont-care-type+])))) :else (fail "Can't call something without a type.")) @@ -84,57 +84,56 @@ locals-per-branch (map &&case/locals (map first branches)) max-locals (reduce max 0 (map count locals-per-branch))] base-register &&env/next-local-idx - =bodies (map-m (partial &&case/analyse-branch &/analyse-1 max-locals) + =bodies (map-m (partial &&case/analyse-branch analyse max-locals) (map vector locals-per-branch (map second branches))) + :let [_ (prn 'analyse-case/=bodies =bodies)] =body-types (map-m &/expr-type =bodies) =case-type (reduce-m &type/merge [::&type/Nothing] =body-types) :let [=branches (map vector (map first branches) =bodies)]] - (return (list [::&/Expression [::case =variant base-register max-locals =branches] =case-type])))) + (return (list [::&/Expression [::&/case =variant base-register max-locals =branches] =case-type])))) (defn analyse-lambda [analyse ?self ?arg ?body] - (exec [[_ =arg =return :as =function] &type/fresh-function - [=scope =captured =body] (&&lambda/with-lambda ?self =function + (exec [[_ =arg =return :as =lambda-type] &type/fresh-function + [=scope =captured =body] (&&lambda/with-lambda ?self =lambda-type ?arg =arg (&/analyse-1 analyse ?body)) =body-type (&/expr-type =body) - =function (exec [_ (&type/solve =return =body-type)] - (&type/clean =function)) - :let [=lambda (match =body - [::&/Expression [::lambda ?sub-scope ?sub-captured ?sub-args ?sub-body] =body-type] - [::&/Expression [::lambda =scope =captured (cons ?arg ?sub-args) (&&lambda/raise-expr ?arg ?sub-body)] =body-type] + =lambda-type (exec [_ (&type/solve =return =body-type)] + (&type/clean =lambda-type)) + :let [=lambda-form (match =body + [::&/Expression [::&/lambda ?sub-scope ?sub-captured ?sub-args ?sub-body] _] + [::&/lambda =scope =captured (cons ?arg ?sub-args) (&&lambda/raise-expr ?arg ?sub-body)] - _ - [::&/Expression [::lambda =scope =captured (list ?arg) =body] =body-type])]] - (return (list [::&/Expression =lambda =function])))) + _ + [::&/lambda =scope =captured (list ?arg) =body])]] + (return (list [::&/Expression =lambda-form =lambda-type])))) (defn analyse-def [analyse ?name ?value] ;; (prn 'analyse-def ?name ?value) - (exec [def?? (&&env/defined? ?name)] - (if def?? - (fail (str "Can't redefine " ?name)) - (exec [ann?? (&&env/annotated? ?name) - $module &util/get-module-name - =value (&/analyse-1 analyse ?value) - =value (match =value - [::&/Expression =value-form =value-type] - (return (match =value-form - [::lambda ?old-scope ?env ?args ?body] - [::&/Expression [::lambda (list ?name $module) ?env ?args ?body] =value-type] - - _ - =value)) + (exec [module-name &util/get-module-name] + (if-m (&&env/defined? module-name ?name) + (fail (str "Can't redefine " ?name)) + (exec [=value (&/analyse-1 analyse ?value) + =value (match =value + [::&/Expression =value-form =value-type] + (return (match =value-form + [::&/lambda ?old-scope ?env ?args ?body] + [::&/Expression [::&/lambda (list module-name ?name) ?env ?args ?body] =value-type] + + _ + =value)) - _ - (fail "")) - =value-type (&/expr-type =value) - _ (if ann?? - (return nil) - (&&env/annotate ?name ::public false =value-type)) - _ (&&env/define ?name)] - (return (list [::&/Statement [::def ?name =value]])))))) + _ + (fail "")) + =value-type (&/expr-type =value) + _ (if-m (&&env/annotated? module-name ?name) + (return nil) + (&&env/annotate module-name ?name :public =value-type)) + _ (&&env/define module-name ?name)] + (return (list [::&/Statement [::&/def ?name =value]])))))) (defn analyse-declare-macro [?ident] - (exec [_ (&&env/annotate ?ident ::public true [::&type/Any])] + (exec [_ (&&env/annotate ?ident :public [::&type/Any])] (return (list)))) (defn analyse-require [analyse ?path] diff --git a/src/lux/compiler.clj b/src/lux/compiler.clj index bd1df6157..dcfbfed56 100644 --- a/src/lux/compiler.clj +++ b/src/lux/compiler.clj @@ -5,7 +5,7 @@ [template :refer [do-template]]) [clojure.core.match :refer [match]] (lux [util :as &util :refer [exec return* return fail fail* - repeat-m exhaust-m try-m try-all-m map-m reduce-m + repeat-m exhaust-m try-m try-all-m map-m mapcat-m reduce-m apply-m normalize-ident]] [type :as &type] @@ -27,6 +27,7 @@ ;; [Utils/Compilers] (defn ^:private compile-expression [syntax] + (prn 'compile-expression syntax) (match syntax [::&a/Expression ?form ?type] (match ?form @@ -164,49 +165,49 @@ (&&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)) - _ - (fail "[Compiler Error] Can't compile expressions as top-level forms.") - ))) + _ + (fail "[Compiler Error] Can't compile statements as expressions."))) (defn ^:private compile-statement [syntax] + (prn 'compile-statement syntax) (match syntax - [::&a/Expression ?form ?type] + [::&a/Statement ?form] (match ?form - [::&a/def ?form ?body] - (&&lux/compile-def compile-expression ?type ?form ?body) + [::&a/def ?name ?body] + (&&lux/compile-def compile-expression ?name ?body) - [::&a/jvm-interface [?package ?name] ?members] - (&&host/compile-jvm-interface compile-expression ?type ?package ?name ?members) + [::&a/jvm-interface ?package ?name ?methods] + (&&host/compile-jvm-interface compile-expression ?package ?name ?methods) - [::&a/jvm-class [?package ?name] ?super-class ?members] - (&&host/compile-jvm-class compile-expression ?type ?package ?name ?super-class ?members) + [::&a/jvm-class ?package ?name ?super-class ?fields ?methods] + (&&host/compile-jvm-class compile-expression ?package ?name ?super-class ?fields ?methods)) - _ - (fail "[Compiler Error] Can't compile expressions as top-level forms.") - ))) + _ + (fail "[Compiler Error] Can't compile expressions as top-level forms."))) -(let [compiler-step (exec [analysis+ &analyser/analyse] - (map-m compile-statement analysis+))] +(let [compiler-step (exec [analysis+ &analyser/analyse + :let [_ (prn 'analysis+ analysis+)]] + (mapcat-m compile-statement analysis+))] (defn ^:private compile-module [name] - (exec [loader &util/loader] - (fn [state] - (if (-> state ::&util/modules (contains? name)) - (fail "[Compiler Error] Can't redefine a module!") - (let [=class (doto (new ClassWriter ClassWriter/COMPUTE_MAXS) - (.visit Opcodes/V1_5 (+ Opcodes/ACC_PUBLIC Opcodes/ACC_SUPER) - (&host/->class name) nil "java/lang/Object" nil))] - (match (&util/run-state (exhaust-m compiler-step) (assoc state - ::&util/source (slurp (str "source/" name ".lux")) - ::&util/current-module name - ::&util/writer =class)) - [::&util/ok [?state _]] - (do (.visitEnd =class) - (&util/run-state (&&/save-class! name (.toByteArray =class)) ?state)) - - [::&util/failure ?message] - (fail* ?message)))))))) + (fn [state] + (if (-> state ::&util/modules (contains? name)) + (fail "[Compiler Error] Can't redefine a module!") + (let [=class (doto (new ClassWriter ClassWriter/COMPUTE_MAXS) + (.visit Opcodes/V1_5 (+ Opcodes/ACC_PUBLIC Opcodes/ACC_SUPER) + (&host/->class name) nil "java/lang/Object" nil))] + (match (&util/run-state (exhaust-m compiler-step) (assoc state + ::&util/source (slurp (str "source/" name ".lux")) + ::&util/global-env (&util/env name) + ::&util/writer =class)) + [::&util/ok [?state ?vals]] + (do (.visitEnd =class) + (prn 'compile-module/?vals ?vals) + (&util/run-state (&&/save-class! name (.toByteArray =class)) ?state)) + + [::&util/failure ?message] + (fail* ?message))))))) ;; [Resources] (defn compile-all [modules] diff --git a/src/lux/compiler/case.clj b/src/lux/compiler/case.clj index a6a181a6d..2139bb24a 100644 --- a/src/lux/compiler/case.clj +++ b/src/lux/compiler/case.clj @@ -535,25 +535,30 @@ )) (defn ^:private decision-tree [branches] + (prn 'decision-tree branches) (exec [group (reduce-m group-branch [::?PM (list)] branches) :let [[mappings group*] (map-bodies group) paths (valid-paths group*)]] - (sequence-pm paths group*))) + (sequence-pm group*))) ;; [Resources] (let [ex-class (&host/->class "java.lang.IllegalStateException")] (defn compile-case [compile *type* ?variant ?base-register ?num-registers ?branches] (exec [*writer* &util/get-writer + :let [_ (prn "Has writer")] :let [$start (new Label) $end (new Label) _ (dotimes [offset ?num-registers] (let [idx (+ ?base-register offset)] (.visitLocalVariable *writer* (str &&/local-prefix idx) (&host/->java-sig [::&type/Any]) nil $start $end idx)))] + :let [_ (prn "PRE Compiled ?variant")] _ (compile ?variant) + :let [_ (prn "POST Compiled ?variant")] :let [_ (doto *writer* (.visitInsn Opcodes/DUP) (.visitLabel $start))] - :let [[mapping tree] (decision-tree ?branches)] + [mapping tree] (decision-tree ?branches) + :let [_ (assert false "compile-case")] ;; :let [[mappings pm-struct*] (map-bodies pm-struct) ;; entries (for [[?branch ?body] mappings diff --git a/src/lux/compiler/host.clj b/src/lux/compiler/host.clj index 0a11decb4..db62312ec 100644 --- a/src/lux/compiler/host.clj +++ b/src/lux/compiler/host.clj @@ -57,6 +57,48 @@ ;; nil))) ;; [Resources] +(do-template [<name> <opcode> <wrapper-class> <value-method> <value-method-sig> <wrapper-method> <wrapper-method-sig>] + (defn <name> [compile *type* ?x ?y] + (exec [:let [+wrapper-class+ (&host/->class <wrapper-class>)] + *writer* &util/get-writer + _ (compile ?x) + :let [_ (doto *writer* + (.visitTypeInsn Opcodes/CHECKCAST +wrapper-class+) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL +wrapper-class+ <value-method> <value-method-sig>))] + _ (compile ?y) + :let [_ (doto *writer* + (.visitTypeInsn Opcodes/CHECKCAST +wrapper-class+) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL +wrapper-class+ <value-method> <value-method-sig>)) + _ (doto *writer* + (.visitInsn <opcode>) + (.visitMethodInsn Opcodes/INVOKESTATIC +wrapper-class+ <wrapper-method> (str <wrapper-method-sig> (&host/->type-signature <wrapper-class>))))]] + (return nil))) + + compile-jvm-iadd Opcodes/IADD "java.lang.Integer" "intValue" "()I" "valueOf" "(I)" + compile-jvm-isub Opcodes/ISUB "java.lang.Integer" "intValue" "()I" "valueOf" "(I)" + compile-jvm-imul Opcodes/IMUL "java.lang.Integer" "intValue" "()I" "valueOf" "(I)" + compile-jvm-idiv Opcodes/IDIV "java.lang.Integer" "intValue" "()I" "valueOf" "(I)" + compile-jvm-irem Opcodes/IREM "java.lang.Integer" "intValue" "()I" "valueOf" "(I)" + + compile-jvm-ladd Opcodes/LADD "java.lang.Long" "longValue" "()J" "valueOf" "(J)" + compile-jvm-lsub Opcodes/LSUB "java.lang.Long" "longValue" "()J" "valueOf" "(J)" + compile-jvm-lmul Opcodes/LMUL "java.lang.Long" "longValue" "()J" "valueOf" "(J)" + compile-jvm-ldiv Opcodes/LDIV "java.lang.Long" "longValue" "()J" "valueOf" "(J)" + compile-jvm-lrem Opcodes/LREM "java.lang.Long" "longValue" "()J" "valueOf" "(J)" + + compile-jvm-fadd Opcodes/FADD "java.lang.Float" "floatValue" "()F" "valueOf" "(F)" + compile-jvm-fsub Opcodes/FSUB "java.lang.Float" "floatValue" "()F" "valueOf" "(F)" + compile-jvm-fmul Opcodes/FMUL "java.lang.Float" "floatValue" "()F" "valueOf" "(F)" + compile-jvm-fdiv Opcodes/FDIV "java.lang.Float" "floatValue" "()F" "valueOf" "(F)" + compile-jvm-frem Opcodes/FREM "java.lang.Float" "floatValue" "()F" "valueOf" "(F)" + + compile-jvm-dadd Opcodes/DADD "java.lang.Double" "doubleValue" "()D" "valueOf" "(D)" + compile-jvm-dsub Opcodes/DSUB "java.lang.Double" "doubleValue" "()D" "valueOf" "(D)" + compile-jvm-dmul Opcodes/DMUL "java.lang.Double" "doubleValue" "()D" "valueOf" "(D)" + compile-jvm-ddiv Opcodes/DDIV "java.lang.Double" "doubleValue" "()D" "valueOf" "(D)" + compile-jvm-drem Opcodes/DREM "java.lang.Double" "doubleValue" "()D" "valueOf" "(D)" + ) + (defn compile-jvm-invokestatic [compile *type* ?class ?method ?classes ?args] (exec [*writer* &util/get-writer :let [method-sig (str "(" (reduce str "" (map &host/->type-signature ?classes)) ")" (&host/->java-sig *type*))] @@ -138,7 +180,7 @@ :let [_ (.visitFieldInsn *writer* Opcodes/GETFIELD (&host/->class ?class) ?field (&host/->java-sig *type*))]] (return nil))) -(defn compile-jvm-class [compile *type* ?package ?name ?super-class ?fields ?methods] +(defn compile-jvm-class [compile ?package ?name ?super-class ?fields ?methods] (let [parent-dir (&host/->package ?package) full-name (str parent-dir "/" ?name) super-class* (&host/->class ?super-class) @@ -159,7 +201,7 @@ (.mkdirs (java.io.File. (str "output/" parent-dir))))] (&&/save-class! full-name (.toByteArray =class)))) -(defn compile-jvm-interface [compile *type* ?package ?name ?fields ?methods] +(defn compile-jvm-interface [compile ?package ?name ?methods] (let [parent-dir (&host/->package ?package) full-name (str parent-dir "/" ?name) =interface (doto (new ClassWriter ClassWriter/COMPUTE_MAXS) @@ -173,48 +215,6 @@ (.mkdirs (java.io.File. (str "output/" parent-dir))))] (&&/save-class! full-name (.toByteArray =interface)))) -(do-template [<name> <opcode> <wrapper-class> <value-method> <value-method-sig> <wrapper-method> <wrapper-method-sig>] - (defn <name> [compile *type* ?x ?y] - (exec [:let [+wrapper-class+ (&host/->class <wrapper-class>)] - *writer* &util/get-writer - _ (compile ?x) - :let [_ (doto *writer* - (.visitTypeInsn Opcodes/CHECKCAST +wrapper-class+) - (.visitMethodInsn Opcodes/INVOKEVIRTUAL +wrapper-class+ <value-method> <value-method-sig>))] - _ (compile ?y) - :let [_ (doto *writer* - (.visitTypeInsn Opcodes/CHECKCAST +wrapper-class+) - (.visitMethodInsn Opcodes/INVOKEVIRTUAL +wrapper-class+ <value-method> <value-method-sig>)) - _ (doto *writer* - (.visitInsn <opcode>) - (.visitMethodInsn Opcodes/INVOKESTATIC +wrapper-class+ <wrapper-method> (str <wrapper-method-sig> (&host/->type-signature <wrapper-class>))))]] - (return nil))) - - compile-jvm-iadd Opcodes/IADD "java.lang.Integer" "intValue" "()I" "valueOf" "(I)" - compile-jvm-isub Opcodes/ISUB "java.lang.Integer" "intValue" "()I" "valueOf" "(I)" - compile-jvm-imul Opcodes/IMUL "java.lang.Integer" "intValue" "()I" "valueOf" "(I)" - compile-jvm-idiv Opcodes/IDIV "java.lang.Integer" "intValue" "()I" "valueOf" "(I)" - compile-jvm-irem Opcodes/IREM "java.lang.Integer" "intValue" "()I" "valueOf" "(I)" - - compile-jvm-ladd Opcodes/LADD "java.lang.Long" "longValue" "()J" "valueOf" "(J)" - compile-jvm-lsub Opcodes/LSUB "java.lang.Long" "longValue" "()J" "valueOf" "(J)" - compile-jvm-lmul Opcodes/LMUL "java.lang.Long" "longValue" "()J" "valueOf" "(J)" - compile-jvm-ldiv Opcodes/LDIV "java.lang.Long" "longValue" "()J" "valueOf" "(J)" - compile-jvm-lrem Opcodes/LREM "java.lang.Long" "longValue" "()J" "valueOf" "(J)" - - compile-jvm-fadd Opcodes/FADD "java.lang.Float" "floatValue" "()F" "valueOf" "(F)" - compile-jvm-fsub Opcodes/FSUB "java.lang.Float" "floatValue" "()F" "valueOf" "(F)" - compile-jvm-fmul Opcodes/FMUL "java.lang.Float" "floatValue" "()F" "valueOf" "(F)" - compile-jvm-fdiv Opcodes/FDIV "java.lang.Float" "floatValue" "()F" "valueOf" "(F)" - compile-jvm-frem Opcodes/FREM "java.lang.Float" "floatValue" "()F" "valueOf" "(F)" - - compile-jvm-dadd Opcodes/DADD "java.lang.Double" "doubleValue" "()D" "valueOf" "(D)" - compile-jvm-dsub Opcodes/DSUB "java.lang.Double" "doubleValue" "()D" "valueOf" "(D)" - compile-jvm-dmul Opcodes/DMUL "java.lang.Double" "doubleValue" "()D" "valueOf" "(D)" - compile-jvm-ddiv Opcodes/DDIV "java.lang.Double" "doubleValue" "()D" "valueOf" "(D)" - compile-jvm-drem Opcodes/DREM "java.lang.Double" "doubleValue" "()D" "valueOf" "(D)" - ) - (defn compile-exec [compile *type* ?exprs] (exec [*writer* &util/get-writer _ (map-m (fn [expr] diff --git a/src/lux/compiler/lux.clj b/src/lux/compiler/lux.clj index ebf376e39..13925a50c 100644 --- a/src/lux/compiler/lux.clj +++ b/src/lux/compiler/lux.clj @@ -22,7 +22,7 @@ MethodVisitor))) ;; [Utils] -(defn ^:private compile-field [compile *type* ?name body] +(defn ^:private compile-field [compile ?name body] (exec [*writer* &util/get-writer module-name &util/get-module-name :let [outer-class (&host/->class module-name) @@ -172,18 +172,19 @@ )]] (return nil))) -(defn compile-def [compile *type* name value] - (match value - [::&a/Expression ?form _] - (match ?form - [::&a/lambda ?scope ?captured ?args ?body] - (&&lambda/compile-lambda compile *type* ?scope ?captured ?args ?body true false) +(defn compile-def [compile name value] + (exec [value-type (&a/expr-type value)] + (match value + [::&a/Expression ?form _] + (match ?form + [::&a/lambda ?scope ?captured ?args ?body] + (&&lambda/compile-lambda compile value-type ?scope ?captured ?args ?body true false) + _ + (compile-field compile name value)) + _ - (compile-field compile *type* name value)) - - _ - (fail "Can only define expressions."))) + (fail "Can only define expressions.")))) (defn compile-self-call [compile ?assumed-args] (exec [*writer* &util/get-writer diff --git a/src/lux/host.clj b/src/lux/host.clj index b21ed03dc..04d0cd9dd 100644 --- a/src/lux/host.clj +++ b/src/lux/host.clj @@ -82,8 +82,11 @@ (defn ->java-sig [type] (match type - ::&type/Any + [::&type/Any] (->type-signature "java.lang.Object") + + [::&type/Nothing] + "V" [::&type/Data ?name] (->type-signature ?name) diff --git a/src/lux/lexer.clj b/src/lux/lexer.clj index 74291ec71..2e0abea82 100644 --- a/src/lux/lexer.clj +++ b/src/lux/lexer.clj @@ -6,20 +6,20 @@ ;; [Utils] (defn ^:private lex-regex [regex] (fn [state] - (if-let [[match] (re-find regex (::source state))] - (return* (update-in state [::source] #(.substring % (.length match))) match) + (if-let [[match] (re-find regex (::&util/source state))] + (return* (update-in state [::&util/source] #(.substring % (.length match))) match) (fail* (str "[Lexer Error] Pattern failed: " regex))))) (defn ^:private lex-regex2 [regex] (fn [state] - (if-let [[match tok1 tok2] (re-find regex (::source state))] - (return* (update-in state [::source] #(.substring % (.length match))) [tok1 tok2]) + (if-let [[match tok1 tok2] (re-find regex (::&util/source state))] + (return* (update-in state [::&util/source] #(.substring % (.length match))) [tok1 tok2]) (fail* (str "[Lexer Error] Pattern failed: " regex))))) (defn ^:private lex-prefix [prefix] (fn [state] - (if (.startsWith (::source state) prefix) - (return* (update-in state [::source] #(.substring % (.length prefix))) prefix) + (if (.startsWith (::&util/source state) prefix) + (return* (update-in state [::&util/source] #(.substring % (.length prefix))) prefix) (fail* (str "[Lexer Error] Text failed: " prefix))))) (defn ^:private escape-char [escaped] @@ -118,7 +118,7 @@ lex-open-brace lex-close-brace])) -;; [Interface] +;; [Exports] (def lex (try-all-m [lex-white-space lex-comment diff --git a/src/lux/parser.clj b/src/lux/parser.clj index 3430e3675..a74251d6d 100644 --- a/src/lux/parser.clj +++ b/src/lux/parser.clj @@ -5,16 +5,16 @@ [lexer :as &lexer]))) ;; [Utils] -(do-template [<name> <close-token> <description> <ast>] +(do-template [<name> <close-token> <description> <tag>] (defn <name> [parse] (exec [elems (repeat-m parse) token &lexer/lex] (if (= <close-token> token) - (return (list [<ast> (apply concat elems)])) + (return (list [<tag> (apply concat elems)])) (fail (str "[Parser Error] Unbalanced " <description> "."))))) - ^:private parse-form [::&lexer/close-paren] "parantheses" ::form - ^:private parse-tuple [::&lexer/close-bracket] "brackets" ::tuple + ^:private parse-form [::&lexer/close-paren] "parantheses" ::Form + ^:private parse-tuple [::&lexer/close-bracket] "brackets" ::Tuple ) (defn ^:private parse-record [parse] @@ -28,11 +28,13 @@ (fail (str "[Parser Error] Records must have an even number of elements.")) :else - (return (list [::record elems]))))) + (return (list [::Record elems]))))) ;; [Interface] (def parse - (exec [token &lexer/lex] + (exec [token &lexer/lex + ;; :let [_ (prn 'parse/token token)] + ] (match token [::&lexer/white-space _] (return (list)) diff --git a/src/lux/type.clj b/src/lux/type.clj index bb22d343f..f558f1fc8 100644 --- a/src/lux/type.clj +++ b/src/lux/type.clj @@ -11,29 +11,30 @@ (defn ^:private deref [id] (fn [state] - (if-let [top+bottom (get-in state [::&util/types ::mappings id])] + (if-let [top+bottom (get-in state [::&util/types :mappings id])] [::&util/ok [state top+bottom]] [::&util/failure (str "Unknown type-var: " id)]))) (defn ^:private update [id top bottom] (fn [state] - (if-let [top+bottom (get-in state [::&util/types ::mappings id])] - [::&util/ok [(assoc-in state [::&util/types ::mappings id] [top bottom]) nil]] + (if-let [top+bottom (get-in state [::&util/types :mappings id])] + [::&util/ok [(assoc-in state [::&util/types :mappings id] [top bottom]) nil]] [::&util/failure (str "Unknown type-var: " id)]))) ;; [Interface] (def fresh-var (fn [state] - (let [id (::counter state)] - [::&util/ok [(-> state - (update-in [::counter] inc) - (assoc-in [::mappings id] [::any ::nothing])) - [::var id]]]))) + (let [id (-> state ::&util/types :counter)] + [::&util/ok [(update-in state [::&util/types] + #(-> % + (update-in [:counter] inc) + (assoc-in [:mappings id] [[::Any] [::Nothing]]))) + [::Var id]]]))) (def fresh-function (exec [=arg fresh-var =return fresh-var] - (return [::function =arg =return]))) + (return [::Lambda =arg =return]))) ;; (defn solve [expected actual] ;; ;; (prn 'solve expected actual) @@ -98,20 +99,17 @@ (defn clean [type] (match type - [::var ?id] + [::Var ?id] (exec [[=top =bottom] (deref ?id)] (clean =top)) - [::function ?args ?return] - (exec [=args (map-m clean ?args) + [::Lambda ?arg ?return] + (exec [=arg (clean ?arg) =return (clean ?return)] - (return [::function =args =return])) + (return [::Lambda =arg =return])) - ;; ::any - ;; (return [::object "java.lang.Object" []]) - - ;; _ - ;; (return type) + _ + (return type) )) ;; Java Reflection @@ -159,6 +157,13 @@ [[::Lambda n!input n!output] [::Lambda g!input g!output]] (exec [_ (solve g!input n!input)] (solve n!output g!output)) + + [[::Var n!id] _] + (exec [[n!top n!bottom] (deref n!id) + _ (solve n!top given) + _ (solve given n!bottom) + _ (update n!id n!top given)] + success) )) (let [&& #(and %1 %2)] diff --git a/src/lux/util.clj b/src/lux/util.clj index 3139cd20b..c27e05ab8 100644 --- a/src/lux/util.clj +++ b/src/lux/util.clj @@ -66,44 +66,45 @@ (do ;; (println "Failed at last:" ?message) (return* state '()))))) -(defn exhaust-m [monad] +(def source-consumed? (fn [state] - (let [result (monad state)] - (match result - [::ok [?state ?head]] - (if (empty? (:forms ?state)) - (return* ?state (list ?head)) - (let [result* ((exhaust-m monad) ?state)] - (match result* - [::ok [?state* ?tail]] - (return* ?state* (cons ?head ?tail)) - - _ - result*))) - - _ - result)))) + [::ok [state (empty? (::source state))]])) + +(defn exhaust-m [monad] + (exec [output-h monad + ? source-consumed? + output-t (if ? + (return (list)) + (exhaust-m monad))] + (return (cons output-h output-t)))) (defn try-all-m [monads] - (fn [state] - (if (empty? monads) - (fail* "No alternative worked!") + (if (empty? monads) + (fail "Can't try no alternatives!") + (fn [state] (let [output ((first monads) state)] (match output [::ok _] output - :else + + _ (if-let [monads* (seq (rest monads))] ((try-all-m monads*) state) output) ))))) +(defn if-m [text-m then-m else-m] + (exec [? text-m] + (if ? + then-m + else-m))) + (do-template [<name> <joiner>] (defn <name> [f inputs] (if (empty? inputs) (return '()) (exec [output (f (first inputs)) - outputs (map-m f (rest inputs))] + outputs (<name> f (rest inputs))] (return (<joiner> output outputs))))) map-m cons @@ -184,36 +185,54 @@ (defn normalize-ident [ident] (reduce str "" (map normalize-char ident))) -(defn class-loader! [] - (-> (java.io.File. "./output/") .toURL vector into-array java.net.URLClassLoader.)) - (def loader (fn [state] (return* state (::loader state)))) -(def +init-env+ +(def +init-bindings+ {:counter 0 :mappings {}}) -(defn scope [name] +(defn env [name] {:name name - :inner-lambdas 0 - :locals +init-env+ - :closure +init-env+}) + :inner-closures 0 + :locals +init-bindings+ + :closure +init-bindings+}) (defn init-state [] {::source nil - ::current-module nil ::modules {} - ::global-env {} + ::global-env nil ::local-envs (list) - ::types +init-env+ + ::types +init-bindings+ ::writer nil - ::loader (class-loader!)}) + ::loader (-> (java.io.File. "./output/") .toURL vector into-array java.net.URLClassLoader.)}) + +(def get-writer + (fn [state] + (if-let [datum (::writer state)] + [::ok [state datum]] + [::failure "Writer hasn't been set."]))) + +(def get-top-local-env + (fn [state] + (if-let [datum (first (::local-envs state))] + [::ok [state datum]] + [::failure "Module hasn't been set."]))) + +(def get-current-module-env + (fn [state] + (if-let [datum (::global-env state)] + [::ok [state datum]] + [::failure "Module hasn't been set."]))) + +(def get-module-name + (exec [module get-current-module-env] + (return (:name module)))) (defn ^:private with-scope [name body] (fn [state] - (let [output (body (update-in state [::local-envs] conj (scope name)))] + (let [output (body (update-in state [::local-envs] conj (env name)))] (match output [::ok [state* datum]] [::ok [(update-in state* [::local-envs] rest) datum]] @@ -222,27 +241,23 @@ output)))) (defn with-closure [body] - (fn [state] - (let [body* (with-scope (-> state ::local-envs first :inner-closures str) - body)] - (body* (update-in state [::local-envs] - #(cons (update-in (first %) [:inner-closures] inc) - (rest %))))))) - -(do-template [<name> <tag>] - (def <name> + (exec [[local? closure-name] (try-all-m (list (exec [top get-top-local-env] + (return [true (-> top :inner-closures str)])) + (exec [global get-current-module-env] + (return [false (-> global :inner-closures str)]))))] (fn [state] - (if-let [datum (<tag> state)] - [::ok [state datum]] - [::failure (str "Data does not exist: " <tag>)]))) - - get-module-name ::current-module - get-writer ::writer - ) + (let [body* (with-scope closure-name + body)] + (body* (if local? + (update-in state [::local-envs] + #(cons (update-in (first %) [:inner-closures] inc) + (rest %))) + (update-in state [::global-env :inner-closures] inc))))))) (def get-scope-name - (fn [state] - [::ok [state (->> state ::local-envs (map :name) reverse (cons (::current-module state)))]])) + (exec [module-name get-module-name] + (fn [state] + [::ok [state (->> state ::local-envs (map :name) reverse (cons module-name))]]))) (defn with-writer [writer body] (fn [state] |