diff options
Diffstat (limited to 'src/lang')
-rw-r--r-- | src/lang/analyser.clj | 211 | ||||
-rw-r--r-- | src/lang/compiler.clj | 156 | ||||
-rw-r--r-- | src/lang/parser.clj | 19 | ||||
-rw-r--r-- | src/lang/util.clj | 16 |
4 files changed, 309 insertions, 93 deletions
diff --git a/src/lang/analyser.clj b/src/lang/analyser.clj index 4436b0b61..7c94c77d5 100644 --- a/src/lang/analyser.clj +++ b/src/lang/analyser.clj @@ -4,7 +4,7 @@ [template :refer [do-template]]) [clojure.core.match :refer [match]] (lang [util :as &util :refer [exec return* return fail fail* - repeat-m try-m try-all-m map-m + repeat-m try-m try-all-m map-m reduce-m apply-m within]] [parser :as &parser] [type :as &type]))) @@ -37,6 +37,10 @@ (fn [state] [::&util/ok [state (-> state :env first :counter)]])) +(def ^:private scope-id + (fn [state] + [::&util/ok [state (-> state :env first :id)]])) + (def ^:private my-frame (fn [state] [::&util/ok [state (-> state :env first)]])) @@ -53,6 +57,20 @@ _ =return)))) +(defn ^:private with-scoped-name [name type body] + (fn [state] + (let [=return (body (update-in state [:env] + #(cons (assoc-in (first %) [:mappings name] (annotated [::global (:name state) name] type)) + (rest %))))] + (match =return + [::&util/ok [?state ?value]] + [::&util/ok [(update-in ?state [:env] #(cons (update-in (first %) [:mappings] dissoc name) + (rest %))) + ?value]] + + _ + =return)))) + (defn ^:private with-lambda-scope [body] (fn [state] (let [;; _ (prn 'with-lambda-scope (get-in state [:lambda-scope 0]) (get-in state [:lambda-scope 1])) @@ -99,6 +117,36 @@ =return) ))) +(defn ^:private with-anon-locals [amount k] + (fn [state] + (let [env (-> state :env first) + $scope (:id env) + =locals (for [$local (take amount (iterate inc (:counter env)))] + (annotated [::local $scope $local] [::&type/object "java.lang.Object" []])) + =return ((k =locals) (update-in state [:env] #(cons (update-in (first %) [:counter] + amount) (rest %))))] + (match =return + [::&util/ok [?state ?value]] + (do ;; (prn 'POST-WITH-LOCAL name (-> ?state :env first)) + [::&util/ok [(update-in ?state [:env] #(cons (update-in (first %) [:counter] - amount) (rest %))) + ?value]]) + + _ + =return)))) + +(defn ^:private with-locals [mappings monad] + (fn [state] + (let [=return (monad (update-in state [:env] #(cons (update-in (first %) [:mappings] merge mappings) + (rest %))))] + (match =return + [::&util/ok [?state ?value]] + (do ;; (prn 'POST-WITH-LOCAL name (-> ?state :env first)) + [::&util/ok [(update-in ?state [:env] #(cons (assoc (first %) :mappings (-> state :env first :mappings)) + (rest %))) + ?value]]) + + _ + =return)))) + (defn ^:private with-fresh-env [[args-vars args-types] body] (with-lambda-scope (fn [state] @@ -119,12 +167,12 @@ (match =return [::&util/ok [?state ?value]] (do ;; (prn 'PRE-LAMBDA (:env state)) - ;; (prn 'POST-LAMBDA (:env ?state) ?value) - [::&util/ok [(-> ?state - (update-in [:env] rest) - ;; (update-in [:lambda-scope 1] inc) - ) - [(get-in ?state [:lambda-scope 0]) (-> ?state :env first) ?value]]]) + ;; (prn 'POST-LAMBDA (:env ?state) ?value) + [::&util/ok [(-> ?state + (update-in [:env] rest) + ;; (update-in [:lambda-scope 1] inc) + ) + [(get-in ?state [:lambda-scope 0]) (-> ?state :env first) ?value]]]) _ =return))))) @@ -221,12 +269,12 @@ ) (defanalyser analyse-variant - [::&parser/tagged ?tag ?value] + [::&parser/variant ?tag ?data] (exec [;; :let [_ (prn 'analyse-variant [?tag ?value])] - =value (analyse-form* ?value) + =data (map-m analyse-form* ?data) ;; :let [_ (prn '=value =value)] ] - (return (annotated [::variant ?tag =value] [::&type/variant ?tag (:type =value)])))) + (return (annotated [::variant ?tag =data] [::&type/variant ?tag (map :type =data)])))) (defanalyser analyse-tuple [::&parser/tuple ?elems] @@ -239,7 +287,9 @@ ;; ;; :let [_ (prn 'analyse-ident ?ident _env)] ;; ] ;; (resolve ?ident)) - (exec [=ident (resolve ?ident) + (exec [;; :let [_ (prn 'analyse-ident '?ident ?ident)] + =ident (resolve ?ident) + ;; :let [_ (prn 'analyse-ident '=ident =ident)] ;; :let [_ (prn 'analyse-ident ?ident =ident)] ;; state &util/get-state ;; :let [_ (prn 'analyse-ident ?ident (:form =ident) (:env state))] @@ -378,21 +428,117 @@ (exec [;; :let [_ (prn '?variant ?variant)] =variant (analyse-form* ?variant) ;; :let [_ (prn '=variant =variant)] - =branches (map-m (fn [branch] - ;; (prn 'branch branch) - (match branch - [::&parser/case-branch [::&parser/tagged ?tag [::&parser/ident ?label]] ?body] - (exec [;; :let [_ (prn ?tag ?label '?body ?body)] - idx next-local-idx - =body (with-local ?label [::&type/object "java.lang.Object" []] - (analyse-form* ?body)) - ;; :let [_ (prn ?tag ?label '=body =body)] - ] - (return [?tag ?label idx =body])))) - ?branches) + ;; {:registers 3, + ;; :patterns {"Cons" {:arity 2, :branches [{:test [:lang/case-try "Cons" [[:lang/case-sub-bind 1] [:lang/case-sub-bind 2]]], :link 1}]}, + ;; "Nil" {:arity 0, :branches [{:test [:lang/case-try "Nil" []], :link 0}]}}, + ;; :paths {:total 2, + ;; :links {1 [:lang.parser/variant "Cons" ([:lang.parser/ident "x"] [:lang.parser/fn-call [:lang.parser/ident "++"] ([:lang.parser/ident "xs*"] [:lang.parser/ident "ys"])])], + ;; 0 [:lang.parser/ident "ys"]}}} + [$base =branches] (with-anon-locals 1 + (fn [=locals] + ;; (prn 'analyse-case '=locals (map :form =locals)) + (exec [=branches (map-m (fn [?branch] + ;; (prn '?branch ?branch) + (match ?branch + [::&parser/case-branch [::&parser/variant ?tag ?members] ?body] + (let [num-members (count ?members)] + (with-anon-locals num-members + (fn [=locals] + ;; (prn '?branch/=locals (map :form =locals)) + (exec [=members (reduce-m (fn [[locals-map =members] [?local ?member]] + (match ?member + [::&parser/ident ?name] + (return [(assoc locals-map ?name ?local) (conj =members (:form ?local))]))) + [{} []] + (map vector =locals ?members)) + ;; :let [_ (prn (first =members) ?body)] + =body (with-locals (first =members) + (analyse-form* ?body)) + ;; :let [_ (prn '?body ?body =body)] + ] + (return [num-members [::branch-adt ?tag (second =members) =body]]))))))) + ?branches)] + (return [(first =locals) =branches])))) + :let [total-registers (reduce + 1 (map first =branches)) + ;; _ (prn '=branches total-registers (map second =branches)) + ;; _ (assert false) + ] + ;; ([::&parser/case-branch [::&parser/variant "Nil" ()] + ;; [::&parser/ident "ys"]] + ;; [::&parser/case-branch [::&parser/variant "Cons" ([::&parser/ident "x"] [::&parser/ident "xs*"])] + ;; [::&parser/variant "Cons" ([::&parser/ident "x"] [::&parser/fn-call [::&parser/ident "++"] ([::&parser/ident "xs*"] [::&parser/ident "ys"])])]]) + ;; :let [_ (prn '?branches ?branches) + ;; case-analysis (let [gen-impl (fn gen-impl [offset pattern] + ;; (clojure.core.match/match pattern + ;; [::&parser/ident _] + ;; [1 [::case-bind -1 offset]] + + ;; [::&parser/variant ?tag ?members] + ;; (let [regs+insns (mapv (fn [idx member] + ;; (clojure.core.match/match member + ;; [::&parser/ident _] + ;; [1 [::case-sub-bind (+ offset (inc idx))]])) + ;; (range (count ?members)) + ;; ?members)] + ;; [(reduce + 1 (map first regs+insns)) [::case-try ?tag (mapv second regs+insns)]]) + ;; (reduce + (count ?members) (map gen-impl ?members))))] + ;; (reduce (fn [accum branch] + ;; (clojure.core.match/match branch + ;; [::&parser/case-branch ?pattern ?body] + ;; (clojure.core.match/match ?pattern + ;; [::&parser/variant ?tag ?members] + ;; (let [[extra-registers impl] (gen-impl 0 ?pattern) + ;; _ (prn 'impl extra-registers impl) + ;; $branch (get-in accum [:paths :total])] + ;; (-> accum + ;; (update-in [:patterns] + ;; (fn [patterns] + ;; (if (contains? patterns ?tag) + ;; (if (= (get patterns [?tag :arity]) (count ?members)) + ;; (update-in patterns [?tag :branches] conj {:test impl + ;; :link $branch}) + ;; (assert "Pattern arity doesn't match!")) + ;; (assoc patterns ?tag {:arity (count ?members) + ;; :branches [{:test impl + ;; :link $branch}]})))) + ;; (update-in [:paths] + ;; (fn [paths] + ;; (-> paths + ;; (update-in [:total] inc) + ;; (assoc-in [:links $branch] ?body)))) + ;; (update-in [:registers] + (dec extra-registers))))) + ;; )) + ;; {:registers 1 + ;; :patterns {} + ;; :paths {:total 0 + ;; :links {}}} + ;; ?branches)) + ;; _ (prn 'case-analysis case-analysis) + ;; _ (assert false)] + ;; =branches (map-m identity ;; (fn [branch] + ;; ;; ;; (prn 'branch branch) + ;; ;; (match branch + ;; ;; [::&parser/case-branch [::&parser/variant ?tag ?parts] ?body] + ;; ;; (exec [;; :let [_ (prn ?tag ?label '?body ?body)] + ;; ;; ;; (reduce-m (fn [?part] + ;; ;; ;; (match ?part + ;; ;; ;; [::&parser/ident ?label] + ;; ;; ;; (exec [idx next-local-idx + ;; ;; ;; =body (with-local ?label [::&type/object "java.lang.Object" []] + ;; ;; ;; (analyse-form* ?body))] + ;; ;; ;; (return ...))) + ;; ;; ;; ) + ;; ;; ;; ?parts) + ;; ;; idx next-local-idx + ;; ;; =body (with-local ?label [::&type/object "java.lang.Object" []] + ;; ;; (analyse-form* ?body)) + ;; ;; ;; :let [_ (prn ?tag ?label '=body =body)] + ;; ;; ] + ;; ;; (return [?tag ?label idx =body])))) + ;; ?branches) ;; :let [_ (prn '=branches =branches)] ] - (return (annotated [::case =variant =branches] ::&type/nothing)))) + (return (annotated [::case $base =variant total-registers (map second =branches)] ::&type/nothing)))) (defanalyser analyse-let [::&parser/let ?label ?value ?body] @@ -426,9 +572,9 @@ [::&parser/ident ?name] (exec [=value (with-scope ?name (analyse-form* ?value)) - _ (define ?name {:mode ::constant + _ (define ?name {:mode ::constant :access ::public - :type (:type =value)})] + :type (:type =value)})] (return (annotated [::def ?name =value] ::&type/nothing))) [::&parser/fn-call [::&parser/ident ?name] ?args] @@ -443,17 +589,18 @@ ;; (into (map vector args =args))) ;; _ (prn 'env env)] =value (with-scope ?name - (reduce (fn [inner [label type]] - (with-local label type inner)) - (analyse-form* ?value) - (reverse (map vector args =args)))) + (with-scoped-name ?name =function + (reduce (fn [inner [label type]] + (with-local label type inner)) + (analyse-form* ?value) + (reverse (map vector args =args))))) ;; :let [_ (prn '=value =value)] =function (within :types (exec [_ (&type/solve =return (:type =value))] (&type/clean =function))) ;; :let [_ (prn '=function =function)] - _ (define ?name {:mode ::function + _ (define ?name {:mode ::function :access ::public - :type =function})] + :type =function})] (return (annotated [::def [?name args] =value] ::&type/nothing)))) )) diff --git a/src/lang/compiler.clj b/src/lang/compiler.clj index 1595fe58e..e425fa0f1 100644 --- a/src/lang/compiler.clj +++ b/src/lang/compiler.clj @@ -20,7 +20,29 @@ (with-open [stream (java.io.BufferedOutputStream. (java.io.FileOutputStream. file))] (.write stream data))) -(def ^:private +variant-class+ "test2.Tagged") +(defn ^:private normalize-char [char] + (case char + \* "_ASTER_" + \+ "_PLUS_" + \- "_DASH_" + \/ "_SLASH_" + \_ "_UNDERS_" + \% "_PERCENT_" + \$ "_DOLLAR_" + \! "_BANG_" + \' "_QUOTE_" + \` "_BQUOTE_" + \@ "_AT_" + \^ "_CARET_" + \& "_AMPERS_" + \= "_EQ_" + ;; default + char)) + +(defn ^:private normalize-ident [ident] + (reduce str "" (map normalize-char ident))) + +(def ^:private +variant-class+ "test2.Variant") (defmacro ^:private defcompiler [name match body] `(defn ~name [~'*state*] @@ -28,6 +50,7 @@ ~'*writer* (:writer ~'*state*) ~'*parent* (:parent ~'*state*) ~'*type* (:type (:form ~'*state*))] + ;; (prn '~name (:form (:form ~'*state*))) (match (:form (:form ~'*state*)) ~match (do ~body @@ -58,6 +81,9 @@ (defn ^:private ->java-sig [type] (match type + ::&type/any + (->java-sig [::&type/object "java.lang.Object" []]) + [::&type/object ?name []] (->type-signature ?name) @@ -143,7 +169,7 @@ (do ;; (prn 'GLOBAL ?owner-class ?name *type*) ;; (prn 'compile-global (->class (str ?owner-class "$" ?name)) "_datum") (doto *writer* - (.visitFieldInsn Opcodes/GETSTATIC (->class (str ?owner-class "$" ?name)) "_datum" "Ljava/lang/Object;" ;; (->java-sig *type*) + (.visitFieldInsn Opcodes/GETSTATIC (->class (str ?owner-class "$" (normalize-ident ?name))) "_datum" "Ljava/lang/Object;" ;; (->java-sig *type*) )))) ;; (defcompiler ^:private compile-call @@ -169,7 +195,7 @@ signature (if (> (count ?args) 1) (str "(" (apply str counter-sig (repeat (dec num-args) clo-field-sig)) ")" "V") (str "()" "V")) - call-class (str (->class ?owner-class) "$" ?fn-name)] + call-class (str (->class ?owner-class) "$" (normalize-ident ?fn-name))] (doto *writer* (.visitTypeInsn Opcodes/NEW call-class) (.visitInsn Opcodes/DUP) @@ -220,14 +246,15 @@ (defcompiler ^:private compile-dynamic-method [::&analyser/dynamic-method ?target ?owner ?method-name ?method-type ?args] - (do ;; (prn 'compile-dynamic-access ?target ?owner ?method-name ?method-type ?args) + (do ;; (prn 'compile-dynamic-method ?target ?owner ?method-name ?method-type ?args) ;; (assert false) (do (compile-form (assoc *state* :form ?target)) (doseq [arg ?args] (compile-form (assoc *state* :form arg))) (doto *writer* (.visitMethodInsn Opcodes/INVOKEVIRTUAL (->class ?owner) ?method-name (method->sig ?method-type)) - (.visitInsn Opcodes/ACONST_NULL))) + (.visitInsn Opcodes/ACONST_NULL) + )) )) (defcompiler ^:private compile-if @@ -235,16 +262,18 @@ (let [else-label (new Label) end-label (new Label)] ;; (println "PRE") - (assert (compile-form (assoc *state* :form ?test)) "CAN't COMPILE TEST") + (compile-form (assoc *state* :form ?test)) (doto *writer* (.visitMethodInsn Opcodes/INVOKEVIRTUAL (->class "java.lang.Boolean") "booleanValue" "()Z") (.visitJumpInsn Opcodes/IFEQ else-label)) ;; (prn 'compile-if/?then (:form ?then)) - (assert (compile-form (assoc *state* :form ?then)) "CAN't COMPILE THEN") + (compile-form (assoc *state* :form ?then)) + ;; (.visitInsn *writer* Opcodes/POP) (doto *writer* (.visitJumpInsn Opcodes/GOTO end-label) (.visitLabel else-label)) - (assert (compile-form (assoc *state* :form ?else)) "CAN't COMPILE ELSE") + (compile-form (assoc *state* :form ?else)) + ;; (.visitInsn *writer* Opcodes/POP) (.visitLabel *writer* end-label))) (defcompiler ^:private compile-do @@ -257,34 +286,48 @@ (let [oclass (->class "java.lang.Object") equals-sig (str "(" (->type-signature "java.lang.Object") ")Z")] (defcompiler ^:private compile-case - [::&analyser/case ?variant ?branches] - (do (compile-form (assoc *state* :form ?variant)) - (let [end-label (new Label)] - (doseq [[?tag ?label ?idx ?body] ?branches] - ;; (prn '[?tag ?label ?idx ?body] [?tag ?label ?idx ?body]) - (let [else-label (new Label)] - (doto *writer* - (.visitInsn Opcodes/DUP) - (.visitFieldInsn Opcodes/GETFIELD (->class +variant-class+) "tag" "Ljava/lang/String;") - (.visitLdcInsn ?tag) - (.visitMethodInsn Opcodes/INVOKEVIRTUAL oclass "equals" equals-sig) - (.visitJumpInsn Opcodes/IFEQ else-label)) - (let [start-label (new Label) - end-label (new Label)] - (doto *writer* - (.visitInsn Opcodes/DUP) - (.visitFieldInsn Opcodes/GETFIELD (->class +variant-class+) "value" (->type-signature "java.lang.Object"))) - (.visitLocalVariable *writer* ?label (->type-signature "java.lang.Object") nil start-label end-label ?idx) - (doto *writer* - (.visitVarInsn Opcodes/ASTORE ?idx) - (.visitLabel start-label) - (.visitInsn Opcodes/POP)) - (compile-form (assoc *state* :form ?body)) - (.visitLabel *writer* end-label)) - (doto *writer* - (.visitJumpInsn Opcodes/GOTO end-label) - (.visitLabel else-label)))) - (.visitLabel *writer* end-label)) + ;; [::&analyser/case ?variant ?branches] + [::&analyser/case ?base ?variant ?registers ?branches] + (do ;; (prn [:case ?base ?variant ?registers ?branches]) + (match (:form ?base) + [::&analyser/local _ ?base-idx] + (let [start-label (new Label) + end-label (new Label)] + (dotimes [idx ?registers] + (.visitLocalVariable *writer* (str "__" idx "__") (->java-sig ::&type/any) nil start-label end-label (+ ?base-idx idx))) + (.visitLabel *writer* start-label) + (compile-form (assoc *state* :form ?variant)) + (.visitVarInsn *writer* Opcodes/ASTORE ?base-idx) + (let [variant-class* (->class +variant-class+)] + (doseq [?branch ?branches + :let [else-label (new Label)]] + (match ?branch + [::&analyser/branch-adt ?tag ?members ?body] + (let [tuple-class (str "test2/Tuple" (count ?members))] + (when (not (empty? ?members)) + (do (doto *writer* + (.visitVarInsn Opcodes/ALOAD ?base-idx) + (.visitFieldInsn Opcodes/GETFIELD variant-class* "value" (->type-signature "java.lang.Object")) + (.visitTypeInsn Opcodes/CHECKCAST tuple-class)) + (doseq [[?tfield member] (map vector (range (count ?members)) ?members)] + (match member + [:lang.analyser/local 0 ?idx] + (doto *writer* + (.visitInsn Opcodes/DUP) + (.visitFieldInsn Opcodes/GETFIELD tuple-class (str "_" ?tfield) (->type-signature "java.lang.Object")) + (.visitVarInsn Opcodes/ASTORE ?idx)))) + (.visitInsn *writer* Opcodes/POP))) + (doto *writer* + (.visitVarInsn Opcodes/ALOAD ?base-idx) + (.visitFieldInsn Opcodes/GETFIELD variant-class* "tag" (->type-signature "java.lang.String")) + (.visitLdcInsn ?tag) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL oclass "equals" equals-sig) + (.visitJumpInsn Opcodes/IFEQ else-label) + (do (compile-form (assoc *state* :form ?body))) + (.visitJumpInsn Opcodes/GOTO end-label) + (.visitLabel else-label)))))) + (.visitInsn *writer* Opcodes/ACONST_NULL) + (.visitLabel *writer* end-label))) ))) (defcompiler ^:private compile-let @@ -293,7 +336,7 @@ end-label (new Label) ?idx (int ?idx)] ;; (prn '(:type ?value) (:type ?value) (->java-sig (:type ?value))) - (.visitLocalVariable *writer* ?label (->java-sig (:type ?value)) nil start-label end-label ?idx) + (.visitLocalVariable *writer* (normalize-ident ?label) (->java-sig (:type ?value)) nil start-label end-label ?idx) (assert (compile-form (assoc *state* :form ?value)) "CAN't COMPILE LET-VALUE") (doto *writer* (.visitVarInsn Opcodes/ASTORE ?idx) @@ -307,7 +350,7 @@ counter-sig "I" 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 "$" fn-name) + current-class (str outer-class "$" (normalize-ident fn-name)) num-captured (dec num-args) init-signature (if (not= 0 num-captured) (str "(" (apply str counter-sig (repeat num-captured clo-field-sig)) ")" "V") @@ -420,7 +463,7 @@ =method (doto (.visitMethod *writer* (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) ?name signature nil nil) (.visitCode))] ;; (prn 'FN/?body ?body) - (assert (compile-form (assoc *state* :parent *writer* :writer =method :form ?body)) (str "Body couldn't compile: " (pr-str ?body))) + (compile-form (assoc *state* :parent *writer* :writer =method :form ?body)) (doto =method (.visitInsn Opcodes/RETURN) (.visitMaxs 0 0) @@ -605,7 +648,7 @@ (.write stream (.toByteArray =interface))))) (defcompiler ^:private compile-variant - [::&analyser/variant ?tag ?value] + [::&analyser/variant ?tag ?members] (let [variant-class* (->class +variant-class+)] ;; (prn 'compile-variant ?tag ?value) (doto *writer* @@ -614,9 +657,18 @@ (.visitMethodInsn Opcodes/INVOKESPECIAL variant-class* "<init>" "()V") (.visitInsn Opcodes/DUP) (.visitLdcInsn ?tag) - (.visitFieldInsn Opcodes/PUTFIELD variant-class* "tag" "Ljava/lang/String;") + (.visitFieldInsn Opcodes/PUTFIELD variant-class* "tag" (->type-signature "java.lang.String")) (.visitInsn Opcodes/DUP)) - (assert (compile-form (assoc *state* :form ?value)) (pr-str "Can't compile value: " ?value)) + (let [tuple-class (str "test2/Tuple" (count ?members))] + (doto *writer* + (.visitTypeInsn Opcodes/NEW tuple-class) + (.visitInsn Opcodes/DUP) + (.visitMethodInsn Opcodes/INVOKESPECIAL tuple-class "<init>" "()V")) + (doseq [[?tfield ?member] (mapv vector (range (count ?members)) ?members)] + (doto *writer* + (.visitInsn Opcodes/DUP) + (do (compile-form (assoc *state* :form ?member))) + (.visitFieldInsn Opcodes/PUTFIELD tuple-class (str "_" ?tfield) "Ljava/lang/Object;")))) (doto *writer* (.visitFieldInsn Opcodes/PUTFIELD variant-class* "value" "Ljava/lang/Object;")) )) @@ -681,13 +733,15 @@ (when (not (compile-form (assoc state :form input))) (assert false input))) (.visitEnd =class) - (.toByteArray =class)) - - (comment - (-> (java.io.File. "./") .toURL vector into-array java.net.URLClassLoader. (.loadClass "test2")) - (-> (java.io.File. "./") .toURL vector into-array java.net.URLClassLoader. (.loadClass "test2.Function")) - (let [test2 (-> (java.io.File. "./") .toURL vector into-array java.net.URLClassLoader. (.loadClass "test2")) - main (first (.getDeclaredMethods test2))] - (.invoke main nil (to-array [nil]))) - ) + (let [=array (.toByteArray =class)] + ;; (prn 'compile class-name =array) + =array)) + + ;; (comment + ;; (-> (java.io.File. "./") .toURL vector into-array java.net.URLClassLoader. (.loadClass "test2")) + ;; (-> (java.io.File. "./") .toURL vector into-array java.net.URLClassLoader. (.loadClass "test2.Function")) + ;; (let [test2 (-> (java.io.File. "./") .toURL vector into-array java.net.URLClassLoader. (.loadClass "test2")) + ;; main (first (.getDeclaredMethods test2))] + ;; (.invoke main nil (to-array [nil]))) + ;; ) ) diff --git a/src/lang/parser.clj b/src/lang/parser.clj index 376e376d6..48f624ba4 100644 --- a/src/lang/parser.clj +++ b/src/lang/parser.clj @@ -137,10 +137,19 @@ [?member [(map ident->string ?inputs) (ident->string ?output)]]))] (return [::definterface ?name members]))) -(defparser ^:private parse-tagged - [::&lexer/list ([[::&lexer/tag ?tag] ?data] :seq)] - (exec [=data (apply-m parse-form (list ?data))] - (return [::tagged ?tag =data]))) +(defparser ^:private parse-variant + ?token + (match ?token + [::&lexer/tag ?tag] + (return [::variant ?tag '()]) + + [::&lexer/list ([[::&lexer/tag ?tag] & ?data] :seq)] + (exec [=data (map-m #(apply-m parse-form (list %)) + ?data)] + (return [::variant ?tag =data])) + + _ + (fail (str "Unmatched token: " ?token)))) (defparser ^:private parse-get [::&lexer/list ([[::&lexer/ident "get@"] [::&lexer/tag ?tag] ?record] :seq)] @@ -191,7 +200,7 @@ parse-do parse-case parse-let - parse-tagged + parse-variant parse-get parse-set parse-remove diff --git a/src/lang/util.clj b/src/lang/util.clj index cdfa8555d..e2edfb550 100644 --- a/src/lang/util.clj +++ b/src/lang/util.clj @@ -59,14 +59,14 @@ (match (monad state) [::ok [?state ?head]] (do ;; (prn 'repeat-m/?state ?state) - (match ((repeat-m monad) ?state) - [::ok [?state* ?tail]] - (do ;; (prn 'repeat-m/?state* ?state*) - (return* ?state* (cons ?head ?tail))))) + (match ((repeat-m monad) ?state) + [::ok [?state* ?tail]] + (do ;; (prn 'repeat-m/?state* ?state*) + (return* ?state* (cons ?head ?tail))))) [::failure ?message] (do ;; (println "Failed at last:" ?message) - (return* state '()))))) + (return* state '()))))) (defn try-all-m [monads] (fn [state] @@ -89,6 +89,12 @@ outputs (map-m f (rest inputs))] (return (conj outputs output))))) +(defn reduce-m [f init inputs] + (if (empty? inputs) + (return init) + (exec [init* (f init (first inputs))] + (reduce-m f init* (rest inputs))))) + (defn apply-m [monad call-state] (fn [state] ;; (prn 'apply-m monad call-state) |