aboutsummaryrefslogtreecommitdiff
path: root/src/lux/analyser/case.clj
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lux/analyser/case.clj119
1 files changed, 99 insertions, 20 deletions
diff --git a/src/lux/analyser/case.clj b/src/lux/analyser/case.clj
index 0c9c55cf8..c33e32af1 100644
--- a/src/lux/analyser/case.clj
+++ b/src/lux/analyser/case.clj
@@ -20,6 +20,19 @@
[["lux;Meta" [_ pattern*]]]
;; (assert false)
(do (prn 'analyse-pattern/pattern* (aget pattern* 0))
+ (when (= "lux;Form" (aget pattern* 0))
+ (prn 'analyse-pattern/_2 (aget pattern* 1 0)) ;; "lux;Cons"
+ (prn 'analyse-pattern/_2 (aget pattern* 1 1 0 0)) ;; "lux;Meta"
+ (prn 'analyse-pattern/_2 (alength (aget pattern* 1 1 0 1)))
+ (prn 'analyse-pattern/_2 (aget pattern* 1 1 0 1 1 0)) ;; "lux;Tag"
+ (prn 'analyse-pattern/_2 [(aget pattern* 1 1 0 1 1 1 0) (aget pattern* 1 1 0 1 1 1 1)]) ;; ["" "Cons"]
+ (prn 'analyse-pattern/_2 (aget pattern* 1 1 1 0)) ;; "lux;Cons"
+ (prn 'analyse-pattern/_2 (aget pattern* 1 1 1 1 0)) ;; #<Object[] [Ljava.lang.Object;@63c7c38b>
+ (prn 'analyse-pattern/_2 (aget pattern* 1 1 1 1 1 0)) ;; "lux;Nil"
+ )
+ ;; ["lux;Form" ["lux;Cons" [["lux;Meta" [_ ["lux;Tag" [?module ?name]]]]
+ ;; ["lux;Cons" [?value
+ ;; ["lux;Nil" _]]]]]]
(matchv ::M/objects [pattern*]
[["lux;Symbol" [?module ?name]]]
(return (&/T (inc idx) (&/V "StoreTestAC" (&/T idx (str ?module ";" ?name) value-type))))
@@ -49,9 +62,9 @@
(&/|range (&/|length ?members)))
_ (&type/check value-type (&/V "lux;TupleT" =vars))
[idx* tests] (&/fold% (fn [idx+subs mv]
- (|let [[idx subs] idx+subs
+ (|let [[_idx subs] idx+subs
[?member ?var] mv]
- (|do [[idx* test] (analyse-pattern idx ?var ?member)]
+ (|do [[idx* test] (analyse-pattern _idx ?var ?member)]
(return (&/T idx* (&/|cons test subs))))))
(&/T idx (&/|list))
(&/zip2 ?members =vars))]
@@ -62,21 +75,27 @@
(&/|range (&/|length ?fields)))
_ (&type/check value-type (&/V "lux;RecordT" (&/zip2 (&/|keys ?fields) =vars)))
tests (&/fold% (fn [idx+subs mv]
- (|let [[idx subs] idx+subs
+ (|let [[_idx subs] idx+subs
[[slot value] ?var] mv]
- (|do [[idx* test] (analyse-pattern idx ?var value)]
+ (|do [[idx* test] (analyse-pattern _idx ?var value)]
(return (&/T idx* (&/|cons (&/T slot test) subs))))))
(&/T idx (&/|list)) (&/zip2 ?fields =vars))]
(return (&/V "RecordTestAC" tests)))
- [["lux;Tag" ?tag]]
- (analyse-variant analyse-pattern idx value-type ?tag (&/V "lus;Meta" (&/T (&/T "" -1 -1)
- (&/V "lux;Tuple" (&/|list)))))
+ [["lux;Tag" [?module ?name]]]
+ (|do [module* (if (= "" ?module)
+ &/get-module-name
+ (return ?module))]
+ (analyse-variant analyse-pattern idx value-type (str module* ";" ?name) (&/V "lux;Meta" (&/T (&/T "" -1 -1)
+ (&/V "lux;Tuple" (&/|list))))))
- [["lux;Form" ["lux;Cons" [["lus;Meta" [_ ["lux;Tag" ?tag]]]
+ [["lux;Form" ["lux;Cons" [["lux;Meta" [_ ["lux;Tag" [?module ?name]]]]
["lux;Cons" [?value
["lux;Nil" _]]]]]]]
- (analyse-variant analyse-pattern idx value-type ?tag ?value)
+ (|do [module* (if (= "" ?module)
+ &/get-module-name
+ (return ?module))]
+ (analyse-variant analyse-pattern idx value-type (str module* ";" ?name) ?value))
))
))
@@ -110,9 +129,11 @@
(let [compare-kv #(compare (aget %1 0) (aget %2 0))]
(defn ^:private merge-total [struct test+body]
+ (prn 'merge-total (aget struct 0) (class test+body))
+ (prn 'merge-total (aget struct 0) (aget test+body 0))
(prn 'merge-total (aget struct 0) (aget test+body 0 0))
(matchv ::M/objects [test+body]
- [[test _]]
+ [[test ?body]]
(matchv ::M/objects [struct test]
[["DefaultTotal" total?] ["StoreTestAC" [?idx ?name type]]]
(return (&/V "DefaultTotal" true))
@@ -152,7 +173,7 @@
[["DefaultTotal" total?] ["TupleTestAC" ?tests]]
(|do [structs (&/map% (fn [t]
- (merge-total (&/V "DefaultTotal" total?) t))
+ (merge-total (&/V "DefaultTotal" total?) (&/T t ?body)))
?tests)]
(return (&/V "TupleTotal" (&/T total? structs))))
@@ -160,7 +181,7 @@
(if (= (&/|length ?values) (&/|length ?tests))
(|do [structs (&/map% (fn [vt]
(|let [[v t] vt]
- (merge-total v t)))
+ (merge-total v (&/T t ?body))))
(&/zip2 ?values ?tests))]
(return (&/V "TupleTotal" (&/T total? structs))))
(fail "[Pattern-matching error] Inconsistent tuple-size."))
@@ -168,7 +189,7 @@
[["DefaultTotal" total?] ["RecordTestAC" ?tests]]
(|do [structs (&/map% (fn [t]
(|let [[slot value] t]
- (|do [struct (merge-total (&/V "DefaultTotal" total?) value)]
+ (|do [struct (merge-total (&/V "DefaultTotal" total?) (&/T value ?body))]
(return (&/T slot struct)))))
(sort compare-kv ?tests))]
(return (&/V "RecordTotal" (&/T total? structs))))
@@ -178,7 +199,7 @@
(|do [structs (&/map% (fn [lr]
(|let [[[lslot struct] [rslot value]] lr]
(if (= lslot rslot)
- (|do [struct (merge-total (&/V "DefaultTotal" total?) value)]
+ (|do [struct (merge-total (&/V "DefaultTotal" total?) (&/T value ?body))]
(return (&/T lslot struct)))
(fail "[Pattern-matching error] Record slots mismatch."))))
(&/zip2 ?values
@@ -187,13 +208,13 @@
(fail "[Pattern-matching error] Inconsistent record-size."))
[["DefaultTotal" total?] ["VariantTestAC" [?tag ?test]]]
- (|do [struct (merge-total (&/V "DefaultTotal" total?) ?test)]
- (return (&/V "VariantTotal" (&/T total? (&/|list (&/T ?tag struct))))))
+ (|do [struct (merge-total (&/V "DefaultTotal" total?) (&/T ?test ?body))]
+ (return (&/V "VariantTotal" (&/T total? (&/|put ?tag struct (&/|table))))))
[["VariantTotal" [total? ?branches]] ["VariantTestAC" [?tag ?test]]]
(|do [struct (merge-total (or (&/|get ?tag ?branches)
(&/V "DefaultTotal" total?))
- ?test)]
+ (&/T ?test ?body))]
(return (&/V "VariantTotal" (&/T total? (&/|put ?tag struct ?branches)))))
))))
@@ -203,11 +224,68 @@
[["MatchAC" ?tests]]
(&/fold% merge-total (&/V "DefaultTotal" false) ?tests))))
+(defn ^:private resolve-type [type]
+ (matchv ::M/objects [type]
+ [["lux;VarT" ?idx]]
+ (&type/deref ?idx)
+
+ [_]
+ (return type)))
+
(defn ^:private check-totality [value-type struct]
(prn 'check-totality (aget value-type 0) (aget struct 0) (&type/show-type value-type))
(matchv ::M/objects [value-type struct]
+ [_ ["BoolTotal" [?total _]]]
+ (|do [_ (&type/check value-type &type/Bool)]
+ (return ?total))
+
+ [_ ["IntTotal" [?total _]]]
+ (|do [_ (&type/check value-type &type/Int)]
+ (return ?total))
+
+ [_ ["RealTotal" [?total _]]]
+ (|do [_ (&type/check value-type &type/Real)]
+ (return ?total))
+
+ [_ ["CharTotal" [?total _]]]
+ (|do [_ (&type/check value-type &type/Char)]
+ (return ?total))
+
+ [_ ["TextTotal" [?total _]]]
+ (|do [_ (&type/check value-type &type/Text)]
+ (return ?total))
+
+ [_ ["TupleTotal" [?total ?structs]]]
+ (|do [elems-vars (&/map% (constantly &type/fresh-var) (&/|range (&/|length ?structs)))
+ _ (&type/check value-type (&/V "lux;TupleT" elems-vars))
+ totals (&/map% (fn [sv]
+ (|let [[struct tvar] sv]
+ (check-totality tvar struct)))
+ (&/zip2 ?structs elems-vars))]
+ (return (or ?total
+ (every? true? totals))))
+
+ [_ ["RecordTotal" [?total ?structs]]]
+ (|do [elems-vars (&/map% (constantly &type/fresh-var) (&/|range (&/|length ?structs)))
+ :let [structs+vars (&/zip2 ?structs elems-vars)
+ record-type (&/V "lux;RecordT" (&/|map (fn [sv]
+ (|let [[[k v] tvar] sv]
+ (&/T k tvar)))
+ structs+vars))]
+ _ (&type/check value-type record-type)
+ totals (&/map% (fn [sv]
+ (|let [[[k v] tvar] sv]
+ (check-totality tvar v)))
+ structs+vars)]
+ (return (or ?total
+ (every? true? totals))))
+
+ [_ ["VariantTotal" [?total ?structs]]]
+ (|do [real-type (resolve-type value-type)]
+ (assert false))
+
[_ ["DefaultTotal" true]]
- true
+ (return true)
))
;; [Exports]
@@ -217,9 +295,10 @@
(analyse-branch analyse exo-type value-type pattern body match)))
(&/V "MatchAC" (&/|list))
branches)
- struct (totality-struct false =match)]
+ struct (totality-struct false =match)
+ ? (check-totality value-type struct)]
(matchv ::M/objects [=match]
[["MatchAC" ?tests]]
- (if (check-totality value-type struct)
+ (if ?
(return (&/V "MatchAC" (&/|reverse ?tests)))
(fail "[Pattern-maching error] Pattern-matching is non-total.")))))