aboutsummaryrefslogtreecommitdiff
path: root/src/lux/analyser.clj
diff options
context:
space:
mode:
Diffstat (limited to 'src/lux/analyser.clj')
-rw-r--r--src/lux/analyser.clj281
1 files changed, 178 insertions, 103 deletions
diff --git a/src/lux/analyser.clj b/src/lux/analyser.clj
index eb6ca7fdd..6b823b3ee 100644
--- a/src/lux/analyser.clj
+++ b/src/lux/analyser.clj
@@ -476,18 +476,38 @@
(defn ->token [x]
;; (prn '->token x)
(match x
- [::&parser/tag ?tag]
+ [::&parser/bool ?bool]
(doto (.newInstance (.loadClass loader "test2.Variant1"))
- (-> .-tag (set! "Tag"))
- (-> .-_1 (set! ?tag)))
+ (-> .-tag (set! "Bool"))
+ (-> .-_1 (set! ?bool)))
+ [::&parser/int ?int]
+ (doto (.newInstance (.loadClass loader "test2.Variant1"))
+ (-> .-tag (set! "Int"))
+ (-> .-_1 (set! ?int)))
+ [::&parser/real ?real]
+ (doto (.newInstance (.loadClass loader "test2.Variant1"))
+ (-> .-tag (set! "Real"))
+ (-> .-_1 (set! ?real)))
+ [::&parser/char ?elem]
+ (doto (.newInstance (.loadClass loader "test2.Variant1"))
+ (-> .-tag (set! "Char"))
+ (-> .-_1 (set! ?elem)))
[::&parser/text ?text]
(doto (.newInstance (.loadClass loader "test2.Variant1"))
(-> .-tag (set! "Text"))
(-> .-_1 (set! ?text)))
+ [::&parser/tag ?tag]
+ (doto (.newInstance (.loadClass loader "test2.Variant1"))
+ (-> .-tag (set! "Tag"))
+ (-> .-_1 (set! ?tag)))
[::&parser/ident ?ident]
(doto (.newInstance (.loadClass loader "test2.Variant1"))
(-> .-tag (set! "Ident"))
(-> .-_1 (set! ?ident)))
+ [::&parser/tuple ?elems]
+ (doto (.newInstance (.loadClass loader "test2.Variant1"))
+ (-> .-tag (set! "Tuple"))
+ (-> .-_1 (set! (->tokens ?elems))))
[::&parser/form ?elems]
(doto (.newInstance (.loadClass loader "test2.Variant1"))
(-> .-tag (set! "Form"))
@@ -508,9 +528,14 @@
(defn ->clojure-token [x]
;; (prn '->clojure-token x (.-tag x))
(case (.-tag x)
+ "Bool" [::&parser/bool (-> x .-_1)]
+ "Int" [::&parser/int (-> x .-_1)]
+ "Real" [::&parser/real (-> x .-_1)]
+ "Char" [::&parser/char (-> x .-_1)]
"Text" [::&parser/text (-> x .-_1)]
- "Ident" [::&parser/ident (-> x .-_1)]
"Tag" [::&parser/tag (-> x .-_1)]
+ "Ident" [::&parser/ident (-> x .-_1)]
+ "Tuple" [::&parser/tuple (-> x .-_1 tokens->clojure)]
"Form" [::&parser/form (-> x .-_1 tokens->clojure)]))
(defn tokens->clojure [xs]
@@ -576,56 +601,87 @@
(exec [=exprs (map-m analyse-form* ?exprs)]
(return (annotated [::do =exprs] (-> =exprs last :type)))))
-(let [fold-branches (fn [struct entry]
- (let [struct* (clojure.core.match/match (nth entry 0)
- [::pm-text ?text]
- (clojure.core.match/match (:type struct)
- ::text-tests (update-in struct [:patterns ?text] (fn [bodies]
- (if bodies
- (conj bodies (nth entry 1))
- #{(nth entry 1)})))
- nil (-> struct
- (assoc :type ::text-tests)
- (assoc-in [:patterns ?text] #{(nth entry 1)}))
- _ (assert false "Can't do match."))
- [::pm-variant ?tag ?members]
- (clojure.core.match/match (:type struct)
- ::adt (update-in struct [:patterns]
- (fn [branches]
- (if-let [{:keys [arity cases]} (get branches ?tag)]
- (if (= arity (count ?members))
- (-> branches
- (update-in [?tag :cases] conj {:case ?members
- :body (nth entry 1)})
- (update-in [?tag :branches] conj (nth entry 1)))
- (assert false (str "Arity doesn't match. " (count ?members) "=/=" arity)))
- (assoc branches ?tag {:arity (count ?members)
- :cases [{:case ?members
- :body (nth entry 1)}]
- :branches #{(nth entry 1)}}))))
- nil (-> struct
- (assoc :type ::adt)
- (assoc-in [:patterns ?tag] {:arity (count ?members)
- :cases [{:case ?members
- :body (nth entry 1)}]
- :branches #{(nth entry 1)}}))
- _ (assert false "Can't do match."))
-
- [::pm-local ?local]
- (update-in struct [:defaults] conj [::default ?local (nth entry 1)]))]
- (update-in struct* [:branches] conj (nth entry 1))))
+(let [fold-branch (fn [struct entry]
+ (let [struct* (clojure.core.match/match (nth entry 0)
+ [::pm-text ?text]
+ (clojure.core.match/match (:type struct)
+ ::text-tests (update-in struct [:patterns ?text] (fn [bodies]
+ (if bodies
+ (conj bodies (nth entry 1))
+ #{(nth entry 1)})))
+ nil (-> struct
+ (assoc :type ::text-tests)
+ (assoc-in [:patterns ?text] #{(nth entry 1)}))
+ _ (assert false "Can't do match."))
+
+ [::pm-local ?local]
+ (update-in struct [:defaults] conj [::default ?local (nth entry 1)])
+
+ [::pm-tuple ?members]
+ (clojure.core.match/match (:type struct)
+ ::tuple (update-in struct [:patterns]
+ (fn [{:keys [arity cases] :as branch}]
+ (if (= arity (count ?members))
+ (-> branch
+ (update-in [:cases] conj {:case ?members
+ :body (nth entry 1)})
+ (update-in [:branches] conj (nth entry 1)))
+ (assert false (str "Arity doesn't match. " (count ?members) "=/=" arity)))))
+ nil (-> struct
+ (assoc :type ::tuple)
+ (assoc :patterns {:arity (count ?members)
+ :cases [{:case ?members
+ :body (nth entry 1)}]
+ :branches #{(nth entry 1)}}))
+ _ (assert false "Can't do match."))
+
+ [::pm-variant ?tag ?members]
+ (clojure.core.match/match (:type struct)
+ ::adt (update-in struct [:patterns]
+ (fn [branches]
+ (if-let [{:keys [arity cases]} (get branches ?tag)]
+ (if (= arity (count ?members))
+ (-> branches
+ (update-in [?tag :cases] conj {:case ?members
+ :body (nth entry 1)})
+ (update-in [?tag :branches] conj (nth entry 1)))
+ (assert false (str "Arity doesn't match. " (count ?members) "=/=" arity)))
+ (assoc branches ?tag {:arity (count ?members)
+ :cases [{:case ?members
+ :body (nth entry 1)}]
+ :branches #{(nth entry 1)}}))))
+ nil (-> struct
+ (assoc :type ::adt)
+ (assoc-in [:patterns ?tag] {:arity (count ?members)
+ :cases [{:case ?members
+ :body (nth entry 1)}]
+ :branches #{(nth entry 1)}}))
+ _ (assert false "Can't do match."))
+ )]
+ (update-in struct* [:branches] conj (nth entry 1))))
base-struct {:type nil
:patterns {}
:defaults []
:branches #{}}
generate-branches (fn generate-branches [data]
- (let [branches* (reduce fold-branches base-struct data)]
+ (let [branches* (reduce fold-branch base-struct data)]
;; (prn 'generate-branches data)
;; (prn 'branches* branches*)
;; (.print System/out (prn-str 'branches* branches*))
;; (.print System/out (prn-str '(:type branches*) (:type branches*)))
(clojure.core.match/match (:type branches*)
::text-tests branches*
+ ::tuple (do (assert (<= (count (:defaults branches*)) 1))
+ {:type ::tuple*
+ :patterns (into {} (for [[?tag ?struct] {nil (:patterns branches*)}
+ ;; :let [_ (prn '(:patterns branches*) ?tag ?struct)]
+ ]
+ [?tag {:parts (let [grouped-parts (apply map list (for [{:keys [case body]} (:cases ?struct)]
+ (map #(vector % body) case)))]
+ (map generate-branches grouped-parts))
+ :branches (:branches ?struct)}]))
+ :default (-> branches* :defaults first)
+ :branches (:branches branches*)})
::adt (do (assert (<= (count (:defaults branches*)) 1))
{:type ::adt*
:patterns (into {} (for [[?tag ?struct] (:patterns branches*)
@@ -648,36 +704,43 @@
:branches (:branches branches*)})))
get-vars (fn get-vars [pattern]
(clojure.core.match/match pattern
- [::&parser/ident ?name]
- (list ?name)
+ [::&parser/text ?text]
+ '()
[::&parser/tag _]
'()
- [::&parser/form ([[::&parser/tag _] & ?members] :seq)]
+ [::&parser/ident ?name]
+ (list ?name)
+
+ [::&parser/tuple ?members]
(mapcat get-vars ?members)
[::&parser/variant ?tag ?members]
(mapcat get-vars ?members)
-
- [::&parser/text ?text]
- '()))
+
+ [::&parser/form ([[::&parser/tag _] & ?members] :seq)]
+ (mapcat get-vars ?members)
+ ))
->instructions (fn ->instructions [locals pattern]
(clojure.core.match/match pattern
+ [::&parser/text ?text]
+ [::pm-text ?text]
+
[::&parser/tag ?tag]
[::pm-variant ?tag '()]
- [::&parser/form ([[::&parser/tag ?tag] & ?members] :seq)]
- [::pm-variant ?tag (map (partial ->instructions locals) ?members)]
+ [::&parser/ident ?name]
+ [::pm-local (get locals ?name)]
+
+ [::&parser/tuple ?members]
+ [::pm-tuple (map (partial ->instructions locals) ?members)]
[::&parser/variant ?tag ?members]
[::pm-variant ?tag (map (partial ->instructions locals) ?members)]
-
- [::&parser/ident ?name]
- [::pm-local (get locals ?name)]
-
- [::&parser/text ?text]
- [::pm-text ?text]
+
+ [::&parser/form ([[::&parser/tag ?tag] & ?members] :seq)]
+ [::pm-variant ?tag (map (partial ->instructions locals) ?members)]
))]
(defn ->decision-tree [$scope $base branches]
(let [;; Step 1: Get all vars
@@ -706,52 +769,64 @@
]
[max-registers branch-mappings (generate-branches branches**)])))
-(defanalyser analyse-case
- [::&parser/form ([[::&parser/ident "case"] ?variant & ?branches] :seq)]
- (exec [=variant (analyse-form* ?variant)
- ;; :let [_ (prn 'analyse-case '=variant =variant)]
- $scope scope-id
- ;; :let [_ (prn 'analyse-case '$scope $scope)]
- $base next-local-idx
- ;; :let [_ (prn 'analyse-case '$base $base)]
- [registers mappings tree] (exec [=branches (map-m (fn [[?pattern ?body]]
- ;; (prn '?branch ?branch)
- (match ?pattern
- [::&parser/ident ?name]
- (exec [=body (with-locals {?name (annotated [::local $scope $base] [::&type/object "java.lang.Object" []])}
- (analyse-form* ?body))]
- (return [::case-branch [::&parser/ident ?name] =body]))
-
- [::&parser/tag ?tag]
- (exec [=body (analyse-form* ?body)]
- (return [::case-branch [::&parser/variant ?tag '()] =body]))
-
- [::&parser/form ([[::&parser/tag ?tag] & ?members] :seq)]
- (exec [[_ locals+] (reduce-m (fn member-fold [[$local locals-map] ?member]
- (match ?member
- [::&parser/ident ?name]
- (return [(inc $local) (assoc locals-map ?name (annotated [::local $scope $local] [::&type/object "java.lang.Object" []]))])
-
- [::&parser/form ([[::&parser/tag ?subtag] & ?submembers] :seq)]
- (reduce-m member-fold [$local locals-map] ?submembers)
-
- _
- (return [$local locals-map])
- ))
- [$base {}]
- ?members)
- ;; :let [_ (prn 'analyse-case 'locals+ locals+)]
- =body (with-locals locals+
- (analyse-form* ?body))
- ;; :let [_ (prn 'analyse-case '=body =body)]
- ]
- (return [::case-branch [::&parser/variant ?tag ?members] =body]))
- ))
- (partition 2 ?branches))]
- (return (->decision-tree $scope $base =branches)))
- ;; :let [_ (prn 'analyse-case '[registers mappings tree] [registers mappings tree])]
- ]
- (return (annotated [::case (dec $base) =variant registers mappings tree] ::&type/nothing))))
+(let [locals-getter (fn [$scope]
+ (fn member-fold [[$local locals-map] ?member]
+ (match ?member
+ [::&parser/ident ?name]
+ (return [(inc $local) (assoc locals-map ?name (annotated [::local $scope $local] [::&type/object "java.lang.Object" []]))])
+
+ [::&parser/tuple ?submembers]
+ (reduce-m member-fold [$local locals-map] ?submembers)
+
+ [::&parser/form ([[::&parser/tag ?subtag] & ?submembers] :seq)]
+ (reduce-m member-fold [$local locals-map] ?submembers)
+
+ _
+ (return [$local locals-map])
+ )))]
+ (defanalyser analyse-case
+ [::&parser/form ([[::&parser/ident "case"] ?variant & ?branches] :seq)]
+ (exec [=variant (analyse-form* ?variant)
+ ;; :let [_ (prn 'analyse-case '=variant =variant)]
+ $scope scope-id
+ ;; :let [_ (prn 'analyse-case '$scope $scope)]
+ $base next-local-idx
+ ;; :let [_ (prn 'analyse-case '$base $base)]
+ [registers mappings tree] (exec [=branches (map-m (fn [[?pattern ?body]]
+ ;; (prn '?branch ?branch)
+ (match ?pattern
+ [::&parser/ident ?name]
+ (exec [=body (with-locals {?name (annotated [::local $scope $base] [::&type/object "java.lang.Object" []])}
+ (analyse-form* ?body))]
+ (return [::case-branch [::&parser/ident ?name] =body]))
+
+ [::&parser/tag ?tag]
+ (exec [=body (analyse-form* ?body)]
+ (return [::case-branch [::&parser/variant ?tag '()] =body]))
+
+ [::&parser/tuple ?members]
+ (exec [[_ locals+] (reduce-m (locals-getter $scope) [$base {}] ?members)
+ ;; :let [_ (prn 'analyse-case 'locals+ locals+)]
+ =body (with-locals locals+
+ (analyse-form* ?body))
+ ;; :let [_ (prn 'analyse-case '=body =body)]
+ ]
+ (return [::case-branch [::&parser/tuple ?members] =body]))
+
+ [::&parser/form ([[::&parser/tag ?tag] & ?members] :seq)]
+ (exec [[_ locals+] (reduce-m (locals-getter $scope) [$base {}] ?members)
+ ;; :let [_ (prn 'analyse-case 'locals+ locals+)]
+ =body (with-locals locals+
+ (analyse-form* ?body))
+ ;; :let [_ (prn 'analyse-case '=body =body)]
+ ]
+ (return [::case-branch [::&parser/variant ?tag ?members] =body]))
+ ))
+ (partition 2 ?branches))]
+ (return (->decision-tree $scope $base =branches)))
+ ;; :let [_ (prn 'analyse-case '[registers mappings tree] [registers mappings tree])]
+ ]
+ (return (annotated [::case (dec $base) =variant registers mappings tree] ::&type/nothing)))))
(defanalyser analyse-let
[::&parser/form ([[::&parser/ident "let"] [::&parser/ident ?label] ?value ?body] :seq)]