diff options
Diffstat (limited to 'src/lux/type.clj')
-rw-r--r-- | src/lux/type.clj | 972 |
1 files changed, 0 insertions, 972 deletions
diff --git a/src/lux/type.clj b/src/lux/type.clj deleted file mode 100644 index d387053dc..000000000 --- a/src/lux/type.clj +++ /dev/null @@ -1,972 +0,0 @@ -;; Copyright (c) Eduardo Julian. All rights reserved. -;; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -;; If a copy of the MPL was not distributed with this file, -;; You can obtain one at http://mozilla.org/MPL/2.0/. - -(ns lux.type - (:refer-clojure :exclude [deref apply merge bound?]) - (:require [clojure.template :refer [do-template]] - clojure.core.match - clojure.core.match.array - (lux [base :as & :refer [|do return* return fail fail* assert! |let |case]]) - [lux.type.host :as &&host])) - -(declare show-type - type=) - -;; [Utils] -(defn |list? [xs] - (|case xs - (&/$Nil) - true - - (&/$Cons x xs*) - (|list? xs*) - - _ - false)) - -(def empty-env &/$Nil) - -(def Bool (&/$NamedT (&/T ["lux" "Bool"]) (&/$HostT "java.lang.Boolean" &/$Nil))) -(def Nat (&/$NamedT (&/T ["lux" "Nat"]) (&/$HostT &&host/nat-data-tag &/$Nil))) -(def Frac (&/$NamedT (&/T ["lux" "Frac"]) (&/$HostT &&host/frac-data-tag &/$Nil))) -(def Int (&/$NamedT (&/T ["lux" "Int"]) (&/$HostT "java.lang.Long" &/$Nil))) -(def Real (&/$NamedT (&/T ["lux" "Real"]) (&/$HostT "java.lang.Double" &/$Nil))) -(def Char (&/$NamedT (&/T ["lux" "Char"]) (&/$HostT "java.lang.Character" &/$Nil))) -(def Text (&/$NamedT (&/T ["lux" "Text"]) (&/$HostT "java.lang.String" &/$Nil))) -(def Ident (&/$NamedT (&/T ["lux" "Ident"]) (&/$ProdT Text Text))) - -(def Bottom - (&/$NamedT (&/T ["lux" "Bottom"]) - (&/$UnivQ empty-env - (&/$BoundT 1)))) - -(def IO - (&/$NamedT (&/T ["lux/codata" "IO"]) - (&/$UnivQ empty-env - (&/$LambdaT &/$VoidT (&/$BoundT 1))))) - -(def List - (&/$NamedT (&/T ["lux" "List"]) - (&/$UnivQ empty-env - (&/$SumT - ;; lux;Nil - &/$UnitT - ;; lux;Cons - (&/$ProdT (&/$BoundT 1) - (&/$AppT (&/$BoundT 0) - (&/$BoundT 1))))))) - -(def Maybe - (&/$NamedT (&/T ["lux" "Maybe"]) - (&/$UnivQ empty-env - (&/$SumT - ;; lux;None - &/$UnitT - ;; lux;Some - (&/$BoundT 1)) - ))) - -(def Type - (&/$NamedT (&/T ["lux" "Type"]) - (let [Type (&/$AppT (&/$BoundT 0) (&/$BoundT 1)) - TypeList (&/$AppT List Type) - TypePair (&/$ProdT Type Type)] - (&/$AppT (&/$UnivQ empty-env - (&/$SumT - ;; HostT - (&/$ProdT Text TypeList) - (&/$SumT - ;; VoidT - &/$UnitT - (&/$SumT - ;; UnitT - &/$UnitT - (&/$SumT - ;; SumT - TypePair - (&/$SumT - ;; ProdT - TypePair - (&/$SumT - ;; LambdaT - TypePair - (&/$SumT - ;; BoundT - Nat - (&/$SumT - ;; VarT - Nat - (&/$SumT - ;; ExT - Nat - (&/$SumT - ;; UnivQ - (&/$ProdT TypeList Type) - (&/$SumT - ;; ExQ - (&/$ProdT TypeList Type) - (&/$SumT - ;; AppT - TypePair - ;; NamedT - (&/$ProdT Ident Type))))))))))))) - ) - &/$VoidT)))) - -(def Ann-Value - (&/$NamedT (&/T ["lux" "Ann-Value"]) - (let [Ann-Value (&/$AppT (&/$BoundT 0) (&/$BoundT 1))] - (&/$AppT (&/$UnivQ empty-env - (&/$SumT - ;; BoolM - Bool - (&/$SumT - ;; NatM - Nat - (&/$SumT - ;; IntM - Int - (&/$SumT - ;; FracM - Frac - (&/$SumT - ;; RealM - Real - (&/$SumT - ;; CharM - Char - (&/$SumT - ;; TextM - Text - (&/$SumT - ;; IdentM - Ident - (&/$SumT - ;; ListM - (&/$AppT List Ann-Value) - ;; DictM - (&/$AppT List (&/$ProdT Text Ann-Value))))))))))) - ) - &/$VoidT)))) - -(def Anns - (&/$NamedT (&/T ["lux" "Anns"]) - (&/$AppT List (&/$ProdT Ident Ann-Value)))) - -(def Macro) - -(defn set-macro-type! [type] - (def Macro type) - nil) - -(defn bound? [id] - (fn [state] - (if-let [type (->> state (&/get$ &/$type-vars) (&/get$ &/$mappings) (&/|get id))] - (|case type - (&/$Some type*) - (return* state true) - - (&/$None) - (return* state false)) - (fail* (str "[Type Error] <bound?> Unknown type-var: " id))))) - -(defn deref [id] - (fn [state] - (if-let [type* (->> state (&/get$ &/$type-vars) (&/get$ &/$mappings) (&/|get id))] - (|case type* - (&/$Some type) - (return* state type) - - (&/$None) - (fail* (str "[Type Error] Unbound type-var: " id))) - (fail* (str "[Type Error] <deref> Unknown type-var: " id))))) - -(defn deref+ [type] - (|case type - (&/$VarT id) - (deref id) - - _ - (fail (str "[Type Error] Type is not a variable: " (show-type type))) - )) - -(defn set-var [id type] - (fn [state] - (if-let [tvar (->> state (&/get$ &/$type-vars) (&/get$ &/$mappings) (&/|get id))] - (|case tvar - (&/$Some bound) - (if (type= type bound) - (return* state nil) - (fail* (str "[Type Error] Can't re-bind type var: " id " | Current type: " (show-type bound)))) - - (&/$None) - (return* (&/update$ &/$type-vars (fn [ts] (&/update$ &/$mappings #(&/|put id (&/$Some type) %) - ts)) - state) - nil)) - (fail* (str "[Type Error] <set-var> Unknown type-var: " id " | " (->> state (&/get$ &/$type-vars) (&/get$ &/$mappings) &/|length)))))) - -(defn reset-var [id type] - (fn [state] - (if-let [tvar (->> state (&/get$ &/$type-vars) (&/get$ &/$mappings) (&/|get id))] - (return* (&/update$ &/$type-vars (fn [ts] (&/update$ &/$mappings #(&/|put id (&/$Some type) %) - ts)) - state) - nil) - (fail* (str "[Type Error] <set-var> Unknown type-var: " id " | " (->> state (&/get$ &/$type-vars) (&/get$ &/$mappings) &/|length)))))) - -(defn unset-var [id] - (fn [state] - (if-let [tvar (->> state (&/get$ &/$type-vars) (&/get$ &/$mappings) (&/|get id))] - (return* (&/update$ &/$type-vars (fn [ts] (&/update$ &/$mappings #(&/|put id &/$None %) - ts)) - state) - nil) - (fail* (str "[Type Error] <set-var> Unknown type-var: " id " | " (->> state (&/get$ &/$type-vars) (&/get$ &/$mappings) &/|length)))))) - -;; [Exports] -;; Type vars -(def create-var - (fn [state] - (let [id (->> state (&/get$ &/$type-vars) (&/get$ &/$counter))] - (return* (&/update$ &/$type-vars #(->> % - (&/update$ &/$counter inc) - (&/update$ &/$mappings (fn [ms] (&/|put id &/$None ms)))) - state) - id)))) - -(def existential - ;; (Lux Type) - (|do [seed &/gen-id] - (return (&/$ExT seed)))) - -(declare clean*) -(defn delete-var [id] - (|do [? (bound? id) - _ (if ? - (return nil) - (|do [ex existential] - (set-var id ex)))] - (fn [state] - ((|do [mappings* (&/map% (fn [binding] - (|let [[?id ?type] binding] - (if (.equals ^Object id ?id) - (return binding) - (|case ?type - (&/$None) - (return binding) - - (&/$Some ?type*) - (|case ?type* - (&/$VarT ?id*) - (if (.equals ^Object id ?id*) - (return (&/T [?id &/$None])) - (return binding)) - - _ - (|do [?type** (clean* id ?type*)] - (return (&/T [?id (&/$Some ?type**)])))) - )))) - (->> state (&/get$ &/$type-vars) (&/get$ &/$mappings)))] - (fn [state] - (return* (&/update$ &/$type-vars #(&/set$ &/$mappings (&/|remove id mappings*) %) - state) - nil))) - state)))) - -(defn with-var [k] - (|do [id create-var - output (k (&/$VarT id)) - _ (delete-var id)] - (return output))) - -(defn clean* [?tid type] - (|case type - (&/$VarT ?id) - (if (.equals ^Object ?tid ?id) - (|do [? (bound? ?id)] - (if ? - (deref ?id) - (return type))) - (|do [? (bound? ?id)] - (if ? - (|do [=type (deref ?id) - ==type (clean* ?tid =type)] - (|case ==type - (&/$VarT =id) - (if (.equals ^Object ?tid =id) - (|do [_ (unset-var ?id)] - (return type)) - (|do [_ (reset-var ?id ==type)] - (return type))) - - _ - (|do [_ (reset-var ?id ==type)] - (return type)))) - (return type))) - ) - - (&/$HostT ?name ?params) - (|do [=params (&/map% (partial clean* ?tid) ?params)] - (return (&/$HostT ?name =params))) - - (&/$LambdaT ?arg ?return) - (|do [=arg (clean* ?tid ?arg) - =return (clean* ?tid ?return)] - (return (&/$LambdaT =arg =return))) - - (&/$AppT ?lambda ?param) - (|do [=lambda (clean* ?tid ?lambda) - =param (clean* ?tid ?param)] - (return (&/$AppT =lambda =param))) - - (&/$ProdT ?left ?right) - (|do [=left (clean* ?tid ?left) - =right (clean* ?tid ?right)] - (return (&/$ProdT =left =right))) - - (&/$SumT ?left ?right) - (|do [=left (clean* ?tid ?left) - =right (clean* ?tid ?right)] - (return (&/$SumT =left =right))) - - (&/$UnivQ ?env ?body) - (|do [=env (&/map% (partial clean* ?tid) ?env) - body* (clean* ?tid ?body)] ;; TODO: DON'T CLEAN THE BODY - (return (&/$UnivQ =env body*))) - - (&/$ExQ ?env ?body) - (|do [=env (&/map% (partial clean* ?tid) ?env) - body* (clean* ?tid ?body)] ;; TODO: DON'T CLEAN THE BODY - (return (&/$ExQ =env body*))) - - _ - (return type) - )) - -(defn clean [tvar type] - (|case tvar - (&/$VarT ?id) - (clean* ?id type) - - _ - (fail (str "[Type Error] Not type-var: " (show-type tvar))))) - -(defn ^:private unravel-fun [type] - (|case type - (&/$LambdaT ?in ?out) - (|let [[??out ?args] (unravel-fun ?out)] - (&/T [??out (&/$Cons ?in ?args)])) - - _ - (&/T [type &/$Nil]))) - -(defn ^:private unravel-app [fun-type] - (|case fun-type - (&/$AppT ?left ?right) - (|let [[?fun-type ?args] (unravel-app ?left)] - (&/T [?fun-type (&/|++ ?args (&/|list ?right))])) - - _ - (&/T [fun-type &/$Nil]))) - -(do-template [<tag> <flatten> <at> <desc>] - (do (defn <flatten> [type] - "(-> Type (List Type))" - (|case type - (<tag> left right) - (&/$Cons left (<flatten> right)) - - _ - (&/|list type))) - - (defn <at> [tag type] - "(-> Int Type (Lux Type))" - (|case type - (&/$NamedT ?name ?type) - (<at> tag ?type) - - (<tag> ?left ?right) - (|case (&/T [tag ?right]) - [0 _] (return ?left) - [1 (<tag> ?left* _)] (return ?left*) - [1 _] (return ?right) - [_ (<tag> _ _)] (<at> (dec tag) ?right) - _ (fail (str "[Type Error] " <desc> " lacks member: " tag " | " (show-type type)))) - - _ - (fail (str "[Type Error] Type is not a " <desc> ": " (show-type type)))))) - - &/$SumT flatten-sum sum-at "Sum" - &/$ProdT flatten-prod prod-at "Product" - ) - -(do-template [<name> <ctor> <unit>] - (defn <name> [types] - "(-> (List Type) Type)" - (|case (&/|reverse types) - (&/$Cons last prevs) - (&/fold (fn [right left] (<ctor> left right)) last prevs) - - (&/$Nil) - <unit>)) - - Variant$ &/$SumT &/$VoidT - Tuple$ &/$ProdT &/$UnitT - ) - -(defn show-type [^objects type] - (|case type - (&/$HostT name params) - (|case params - (&/$Nil) - (str "(host " name ")") - - _ - (str "(host " name " " (->> params (&/|map show-type) (&/|interpose " ") (&/fold str "")) ")")) - - (&/$VoidT) - "Void" - - (&/$UnitT) - "Unit" - - (&/$ProdT _) - (str "[" (->> (flatten-prod type) (&/|map show-type) (&/|interpose " ") (&/fold str "")) "]") - - (&/$SumT _) - (str "(| " (->> (flatten-sum type) (&/|map show-type) (&/|interpose " ") (&/fold str "")) ")") - - (&/$LambdaT input output) - (|let [[?out ?ins] (unravel-fun type)] - (str "(-> " (->> ?ins (&/|map show-type) (&/|interpose " ") (&/fold str "")) " " (show-type ?out) ")")) - - (&/$VarT id) - (str "⌈v:" id "⌋") - - (&/$ExT ?id) - (str "⟨e:" ?id "⟩") - - (&/$BoundT idx) - (str idx) - - (&/$AppT _ _) - (|let [[?call-fun ?call-args] (unravel-app type)] - (str "(" (show-type ?call-fun) " " (->> ?call-args (&/|map show-type) (&/|interpose " ") (&/fold str "")) ")")) - - (&/$UnivQ ?env ?body) - (str "(All " (show-type ?body) ")") - - (&/$ExQ ?env ?body) - (str "(Ex " (show-type ?body) ")") - - (&/$NamedT ?name ?type) - (&/ident->text ?name) - - _ - (assert false (prn-str 'show-type (&/adt->text type))))) - -(defn type= [x y] - (or (clojure.lang.Util/identical x y) - (let [output (|case [x y] - [(&/$NamedT [?xmodule ?xname] ?xtype) (&/$NamedT [?ymodule ?yname] ?ytype)] - (and (= ?xmodule ?ymodule) - (= ?xname ?yname)) - - [(&/$HostT xname xparams) (&/$HostT yname yparams)] - (and (.equals ^Object xname yname) - (= (&/|length xparams) (&/|length yparams)) - (&/fold2 #(and %1 (type= %2 %3)) true xparams yparams)) - - [(&/$VoidT) (&/$VoidT)] - true - - [(&/$UnitT) (&/$UnitT)] - true - - [(&/$ProdT xL xR) (&/$ProdT yL yR)] - (and (type= xL yL) - (type= xR yR)) - - [(&/$SumT xL xR) (&/$SumT yL yR)] - (and (type= xL yL) - (type= xR yR)) - - [(&/$LambdaT xinput xoutput) (&/$LambdaT yinput youtput)] - (and (type= xinput yinput) - (type= xoutput youtput)) - - [(&/$VarT xid) (&/$VarT yid)] - (.equals ^Object xid yid) - - [(&/$BoundT xidx) (&/$BoundT yidx)] - (= xidx yidx) - - [(&/$ExT xid) (&/$ExT yid)] - (.equals ^Object xid yid) - - [(&/$AppT xlambda xparam) (&/$AppT ylambda yparam)] - (and (type= xlambda ylambda) (type= xparam yparam)) - - [(&/$UnivQ xenv xbody) (&/$UnivQ yenv ybody)] - (type= xbody ybody) - - [(&/$NamedT ?xname ?xtype) _] - (type= ?xtype y) - - [_ (&/$NamedT ?yname ?ytype)] - (type= x ?ytype) - - [_ _] - false - )] - output))) - -(defn ^:private fp-get [k fixpoints] - (|let [[e a] k] - (|case fixpoints - (&/$Nil) - &/$None - - (&/$Cons [[e* a*] v*] fixpoints*) - (if (and (type= e e*) - (type= a a*)) - (&/$Some v*) - (fp-get k fixpoints*)) - ))) - -(defn ^:private fp-put [k v fixpoints] - (&/$Cons (&/T [k v]) fixpoints)) - -(defn show-type+ [type] - (|case type - (&/$VarT ?id) - (fn [state] - (|case ((deref ?id) state) - (&/$Right state* bound) - (return* state (str (show-type type) " = " (show-type bound))) - - (&/$Left _) - (return* state (show-type type)))) - - _ - (return (show-type type)))) - -(defn ^:private check-error [err expected actual] - (|do [=expected (show-type+ expected) - =actual (show-type+ actual)] - (&/fail-with-loc (str (if (= "" err) err (str err "\n")) - "[Type Checker]\n" - "Expected: " =expected "\n\n" - "Actual: " =actual - "\n")))) - -(defn beta-reduce [env type] - (|case type - (&/$HostT ?name ?params) - (&/$HostT ?name (&/|map (partial beta-reduce env) ?params)) - - (&/$SumT ?left ?right) - (&/$SumT (beta-reduce env ?left) (beta-reduce env ?right)) - - (&/$ProdT ?left ?right) - (&/$ProdT (beta-reduce env ?left) (beta-reduce env ?right)) - - (&/$AppT ?type-fn ?type-arg) - (&/$AppT (beta-reduce env ?type-fn) (beta-reduce env ?type-arg)) - - (&/$UnivQ ?local-env ?local-def) - (|case ?local-env - (&/$Nil) - (&/$UnivQ env ?local-def) - - _ - type) - - (&/$ExQ ?local-env ?local-def) - (|case ?local-env - (&/$Nil) - (&/$ExQ env ?local-def) - - _ - type) - - (&/$LambdaT ?input ?output) - (&/$LambdaT (beta-reduce env ?input) (beta-reduce env ?output)) - - (&/$BoundT ?idx) - (|case (&/|at ?idx env) - (&/$Some bound) - (beta-reduce env bound) - - _ - (assert false (str "[Type Error] Unknown var: " ?idx " | " (&/->seq (&/|map show-type env))))) - - _ - type - )) - -(defn apply-type [type-fn param] - (|case type-fn - (&/$UnivQ local-env local-def) - (return (beta-reduce (->> local-env - (&/$Cons param) - (&/$Cons type-fn)) - local-def)) - - (&/$ExQ local-env local-def) - (return (beta-reduce (->> local-env - (&/$Cons param) - (&/$Cons type-fn)) - local-def)) - - (&/$AppT F A) - (|do [type-fn* (apply-type F A)] - (apply-type type-fn* param)) - - (&/$NamedT ?name ?type) - (apply-type ?type param) - - ;; TODO: This one must go... - (&/$ExT id) - (return (&/$AppT type-fn param)) - - (&/$VarT id) - (|do [=type-fun (deref id)] - (apply-type =type-fun param)) - - _ - (fail (str "[Type System] Not a type function:\n" (show-type type-fn) "\n")))) - -(def ^:private init-fixpoints &/$Nil) - -(defn ^:private check* [class-loader fixpoints invariant?? expected actual] - (if (clojure.lang.Util/identical expected actual) - (return fixpoints) - (&/with-attempt - (|case [expected actual] - [(&/$VarT ?eid) (&/$VarT ?aid)] - (if (.equals ^Object ?eid ?aid) - (return fixpoints) - (|do [ebound (fn [state] - (|case ((deref ?eid) state) - (&/$Right state* ebound) - (return* state* (&/$Some ebound)) - - (&/$Left _) - (return* state &/$None))) - abound (fn [state] - (|case ((deref ?aid) state) - (&/$Right state* abound) - (return* state* (&/$Some abound)) - - (&/$Left _) - (return* state &/$None)))] - (|case [ebound abound] - [(&/$None _) (&/$None _)] - (|do [_ (set-var ?eid actual)] - (return fixpoints)) - - [(&/$Some etype) (&/$None _)] - (check* class-loader fixpoints invariant?? etype actual) - - [(&/$None _) (&/$Some atype)] - (check* class-loader fixpoints invariant?? expected atype) - - [(&/$Some etype) (&/$Some atype)] - (check* class-loader fixpoints invariant?? etype atype)))) - - [(&/$VarT ?id) _] - (fn [state] - (|case ((set-var ?id actual) state) - (&/$Right state* _) - (return* state* fixpoints) - - (&/$Left _) - ((|do [bound (deref ?id)] - (check* class-loader fixpoints invariant?? bound actual)) - state))) - - [_ (&/$VarT ?id)] - (fn [state] - (|case ((set-var ?id expected) state) - (&/$Right state* _) - (return* state* fixpoints) - - (&/$Left _) - ((|do [bound (deref ?id)] - (check* class-loader fixpoints invariant?? expected bound)) - state))) - - [(&/$AppT (&/$ExT eid) eA) (&/$AppT (&/$ExT aid) aA)] - (if (= eid aid) - (check* class-loader fixpoints invariant?? eA aA) - (check-error "" expected actual)) - - [(&/$AppT (&/$VarT ?id) A1) (&/$AppT F2 A2)] - (fn [state] - (|case ((|do [F1 (deref ?id)] - (check* class-loader fixpoints invariant?? (&/$AppT F1 A1) actual)) - state) - (&/$Right state* output) - (return* state* output) - - (&/$Left _) - (|case F2 - (&/$UnivQ (&/$Cons _) _) - ((|do [actual* (apply-type F2 A2)] - (check* class-loader fixpoints invariant?? expected actual*)) - state) - - (&/$ExT _) - ((|do [fixpoints* (check* class-loader fixpoints invariant?? (&/$VarT ?id) F2)] - (check* class-loader fixpoints* invariant?? A1 A2)) - state) - - _ - ((|do [fixpoints* (check* class-loader fixpoints invariant?? (&/$VarT ?id) F2) - e* (apply-type F2 A1) - a* (apply-type F2 A2)] - (check* class-loader fixpoints* invariant?? e* a*)) - state)))) - - [(&/$AppT F1 A1) (&/$AppT (&/$VarT ?id) A2)] - (fn [state] - (|case ((|do [F2 (deref ?id)] - (check* class-loader fixpoints invariant?? expected (&/$AppT F2 A2))) - state) - (&/$Right state* output) - (return* state* output) - - (&/$Left _) - ((|do [fixpoints* (check* class-loader fixpoints invariant?? F1 (&/$VarT ?id)) - e* (apply-type F1 A1) - a* (apply-type F1 A2)] - (check* class-loader fixpoints* invariant?? e* a*)) - state))) - - [(&/$AppT F A) _] - (let [fp-pair (&/T [expected actual]) - _ (when (> (&/|length fixpoints) 40) - (println 'FIXPOINTS (->> (&/|keys fixpoints) - (&/|map (fn [pair] - (|let [[e a] pair] - (str (show-type e) ":+:" - (show-type a))))) - (&/|interpose "\n\n") - (&/fold str ""))) - (assert false (prn-str 'check* '[(&/$AppT F A) _] (&/|length fixpoints) (show-type expected) (show-type actual))))] - (|case (fp-get fp-pair fixpoints) - (&/$Some ?) - (if ? - (return fixpoints) - (check-error "" expected actual)) - - (&/$None) - (|do [expected* (apply-type F A)] - (check* class-loader (fp-put fp-pair true fixpoints) invariant?? expected* actual)))) - - [_ (&/$AppT (&/$ExT aid) A)] - (check-error "" expected actual) - - [_ (&/$AppT F A)] - (|do [actual* (apply-type F A)] - (check* class-loader fixpoints invariant?? expected actual*)) - - [(&/$UnivQ _) _] - (|do [$arg existential - expected* (apply-type expected $arg)] - (check* class-loader fixpoints invariant?? expected* actual)) - - [_ (&/$UnivQ _)] - (with-var - (fn [$arg] - (|do [actual* (apply-type actual $arg) - =output (check* class-loader fixpoints invariant?? expected actual*) - _ (clean $arg expected)] - (return =output)))) - - [(&/$ExQ e!env e!def) _] - (with-var - (fn [$arg] - (|do [expected* (apply-type expected $arg) - =output (check* class-loader fixpoints invariant?? expected* actual) - _ (clean $arg actual)] - (return =output)))) - - [_ (&/$ExQ a!env a!def)] - (|do [$arg existential - actual* (apply-type actual $arg)] - (check* class-loader fixpoints invariant?? expected actual*)) - - [(&/$HostT e!data) (&/$HostT a!data)] - (&&host/check-host-types (partial check* class-loader fixpoints true) - check-error - fixpoints - existential - class-loader - invariant?? - e!data - a!data) - - [(&/$VoidT) (&/$VoidT)] - (return fixpoints) - - [(&/$UnitT) (&/$UnitT)] - (return fixpoints) - - [(&/$LambdaT eI eO) (&/$LambdaT aI aO)] - (|do [fixpoints* (check* class-loader fixpoints invariant?? aI eI)] - (check* class-loader fixpoints* invariant?? eO aO)) - - [(&/$ProdT eL eR) (&/$ProdT aL aR)] - (|do [fixpoints* (check* class-loader fixpoints invariant?? eL aL)] - (check* class-loader fixpoints* invariant?? eR aR)) - - [(&/$SumT eL eR) (&/$SumT aL aR)] - (|do [fixpoints* (check* class-loader fixpoints invariant?? eL aL)] - (check* class-loader fixpoints* invariant?? eR aR)) - - [(&/$ExT e!id) (&/$ExT a!id)] - (if (.equals ^Object e!id a!id) - (return fixpoints) - (check-error "" expected actual)) - - [(&/$NamedT _ ?etype) _] - (check* class-loader fixpoints invariant?? ?etype actual) - - [_ (&/$NamedT _ ?atype)] - (check* class-loader fixpoints invariant?? expected ?atype) - - [_ _] - (fail "")) - (fn [err] - (check-error err expected actual))))) - -(defn check [expected actual] - (|do [class-loader &/loader - _ (check* class-loader init-fixpoints false expected actual)] - (return nil))) - -(defn actual-type [type] - "(-> Type (Lux Type))" - (|case type - (&/$AppT ?all ?param) - (|do [type* (apply-type ?all ?param)] - (actual-type type*)) - - (&/$VarT id) - (|do [=type (deref id)] - (actual-type =type)) - - (&/$NamedT ?name ?type) - (actual-type ?type) - - _ - (return type) - )) - -(defn type-name [type] - "(-> Type (Lux Ident))" - (|case type - (&/$NamedT name _) - (return name) - - _ - (fail (str "[Type Error] Type is not named: " (show-type type))) - )) - -(defn unknown? [type] - "(-> Type (Lux Bool))" - (|case type - (&/$VarT id) - (|do [? (bound? id)] - (return (not ?))) - - _ - (return false))) - -(defn resolve-type [type] - "(-> Type (Lux Type))" - (|case type - (&/$VarT id) - (|do [? (bound? id)] - (if ? - (deref id) - (return type))) - - _ - (return type))) - -(defn tuple-types-for [size-members type] - "(-> Int Type [Int (List Type)])" - (|let [?member-types (flatten-prod type) - size-types (&/|length ?member-types)] - (if (>= size-types size-members) - (&/T [size-members (&/|++ (&/|take (dec size-members) ?member-types) - (&/|list (|case (->> ?member-types (&/|drop (dec size-members)) (&/|reverse)) - (&/$Cons last prevs) - (&/fold (fn [right left] (&/$ProdT left right)) - last prevs))))]) - (&/T [size-types ?member-types]) - ))) - -(do-template [<name> <zero> <plus>] - (defn <name> [types] - (|case (&/|reverse types) - (&/$Nil) - <zero> - - (&/$Cons type (&/$Nil)) - type - - (&/$Cons last prevs) - (&/fold (fn [r l] (<plus> l r)) last prevs))) - - fold-prod &/$UnitT &/$ProdT - fold-sum &/$VoidT &/$SumT - ) - -(def create-var+ - (|do [id create-var] - (return (&/$VarT id)))) - -(defn ^:private push-app [inf-type inf-var] - (|case inf-type - (&/$AppT inf-type* inf-var*) - (&/$AppT (push-app inf-type* inf-var) inf-var*) - - _ - (&/$AppT inf-type inf-var))) - -(defn ^:private push-name [name inf-type] - (|case inf-type - (&/$AppT inf-type* inf-var*) - (&/$AppT (push-name name inf-type*) inf-var*) - - _ - (&/$NamedT name inf-type))) - -(defn ^:private push-univq [env inf-type] - (|case inf-type - (&/$AppT inf-type* inf-var*) - (&/$AppT (push-univq env inf-type*) inf-var*) - - _ - (&/$UnivQ env inf-type))) - -(defn instantiate-inference [type] - (|case type - (&/$NamedT ?name ?type) - (|do [output (instantiate-inference ?type)] - (return (push-name ?name output))) - - (&/$UnivQ _aenv _abody) - (|do [inf-var create-var - output (instantiate-inference _abody)] - (return (push-univq _aenv (push-app output (&/$VarT inf-var))))) - - _ - (return type))) |