aboutsummaryrefslogtreecommitdiff
path: root/src/lux/type.clj
diff options
context:
space:
mode:
Diffstat (limited to 'src/lux/type.clj')
-rw-r--r--src/lux/type.clj49
1 files changed, 42 insertions, 7 deletions
diff --git a/src/lux/type.clj b/src/lux/type.clj
index 9d9cf77aa..0c1b34070 100644
--- a/src/lux/type.clj
+++ b/src/lux/type.clj
@@ -1,5 +1,5 @@
(ns lux.type
- (:refer-clojure :exclude [resolve apply])
+ (:refer-clojure :exclude [deref apply merge])
(:require [clojure.core.match :refer [match]]
[lux.util :as &util :refer [exec return* return fail fail*
repeat-m try-m try-all-m map-m
@@ -9,7 +9,7 @@
;; [Util]
(def ^:private success (return nil))
-(defn ^:private resolve [id]
+(defn ^:private deref [id]
(fn [state]
(if-let [top+bottom (get-in state [::&util/types ::mappings id])]
[::&util/ok [state top+bottom]]
@@ -45,7 +45,7 @@
;; success
;; [_ [::var ?id]]
-;; (exec [[=top =bottom] (resolve ?id)]
+;; (exec [[=top =bottom] (deref ?id)]
;; (try-all-m [(exec [_ (solve expected =top)]
;; success)
;; (exec [_ (solve =top expected)
@@ -54,7 +54,7 @@
;; success)]))
;; [[::var ?id] _]
-;; (exec [[=top =bottom] (resolve ?id)]
+;; (exec [[=top =bottom] (deref ?id)]
;; (try-all-m [(exec [_ (solve =bottom actual)]
;; success)
;; (exec [_ (solve actual =bottom)
@@ -99,7 +99,7 @@
(defn clean [type]
(match type
[::var ?id]
- (exec [[=top =bottom] (resolve ?id)]
+ (exec [[=top =bottom] (deref ?id)]
(clean =top))
[::function ?args ?return]
@@ -110,8 +110,9 @@
;; ::any
;; (return [::object "java.lang.Object" []])
- _
- (return type)))
+ ;; _
+ ;; (return type)
+ ))
;; Java Reflection
(def success (return nil))
@@ -160,6 +161,40 @@
(solve n!output g!output))
))
+(let [&& #(and %1 %2)]
+ (defn merge [x y]
+ (match [x y]
+ [_ [::Nothing]]
+ (return x)
+
+ [[::Nothing] _]
+ (return y)
+
+ [[::Variant x!cases] [::Variant y!cases]]
+ (and (reduce && true
+ (for [[xslot xtype] (keys x!cases)]
+ (if-let [ytype (get y!cases xslot)]
+ (= xtype ytype)
+ true)))
+ (reduce && true
+ (for [[yslot ytype] (keys y!cases)]
+ (if-let [xtype (get x!cases yslot)]
+ (= xtype ytype)
+ true))))
+ (return [::Variant (clojure.core/merge x!cases y!cases)])
+ (fail (str "Incompatible variants: " (pr-str x) " and " (pr-str y)))
+
+ [[::Record x!fields] [::Record y!fields]]
+ (if (and (= (keys x!fields) (keys y!fields))
+ (->> (keys x!fields)
+ (map #(= (get x!fields %) (get y!fields %)))
+ (reduce && true)))
+ (return x)
+ (fail (str "Incompatible records: " (pr-str x) " and " (pr-str y))))
+
+ :else
+ (fail (str "Can't merge types: " (pr-str x) " and " (pr-str y))))))
+
(comment
;; Types
[::Any]