diff options
author | Eduardo Julian | 2015-04-16 15:37:27 -0400 |
---|---|---|
committer | Eduardo Julian | 2015-04-16 15:37:27 -0400 |
commit | 12aed842461ecc596c07227dcefce36d440e2c85 (patch) | |
tree | ee4275cf2ffd89192f91414134cd38982003fb4a /src/lux/type.clj | |
parent | f6dc520d04b517cd8e907d4738aae60b279c3877 (diff) |
- Type-vars can now be deleted and be scoped (through with-var).
- Fixed a few bugs with types and pattern-matching.
- Fixed a bug wherein primitive-analysis did now unify the primitive type with the exotype.
- Modified lambda-analysis so functions subject to universal quantification can manage better the universally-quantified variables.
Diffstat (limited to '')
-rw-r--r-- | src/lux/type.clj | 413 |
1 files changed, 232 insertions, 181 deletions
diff --git a/src/lux/type.clj b/src/lux/type.clj index 0cd839cf2..4eeea30aa 100644 --- a/src/lux/type.clj +++ b/src/lux/type.clj @@ -7,6 +7,42 @@ (declare show-type) ;; [Util] +(def Any (&/V "lux;AnyT" nil)) +(def Nothing (&/V "lux;NothingT" nil)) +(def Bool (&/V "lux;DataT" "java.lang.Boolean")) +(def Int (&/V "lux;DataT" "java.lang.Long")) +(def Real (&/V "lux;DataT" "java.lang.Double")) +(def Char (&/V "lux;DataT" "java.lang.Character")) +(def Text (&/V "lux;DataT" "java.lang.String")) +(def Unit (&/V "lux;TupleT" (&/|list))) + +(def List + (&/V "lux;AllT" (&/T (&/|table) "List" "a" + (&/V "lux;VariantT" (&/|list (&/T "lux;Nil" (&/V "lux;TupleT" (&/|list))) + (&/T "lux;Cons" (&/V "lux;TupleT" (&/|list (&/V "lux;BoundT" "a") + (&/V "lux;AppT" (&/T (&/V "lux;BoundT" "List") + (&/V "lux;BoundT" "a"))))))))))) + +(def Type + (let [Type (&/V "lux;AppT" (&/T (&/V "lux;BoundT" "Type") (&/V "lux;BoundT" "_"))) + TypeEnv (&/V "lux;AppT" (&/T List (&/V "lux;TupleT" (&/|list Text Type)))) + Unit (&/V "lux;TupleT" (&/|list)) + TypePair (&/V "lux;TupleT" (&/|list Type Type))] + (&/V "lux;AppT" (&/T (&/V "lux;AllT" (&/T (&/|list) "Type" "_" + (&/V "lux;VariantT" (&/|list (&/T "lux;AnyT" Unit) + (&/T "lux;NothingT" Unit) + (&/T "lux;DataT" Text) + (&/T "lux;TupleT" (&/V "lux;AppT" (&/T List Type))) + (&/T "lux;VariantT" TypeEnv) + (&/T "lux;RecordT" TypeEnv) + (&/T "lux;LambdaT" TypePair) + (&/T "lux;BoundT" Text) + (&/T "lux;VarT" Int) + (&/T "lux;AllT" (&/V "lux;TupleT" (&/|list TypeEnv Text Text Type))) + (&/T "lux;AppT" TypePair) + )))) + (&/V "lux;NothingT" nil))))) + (defn bound? [id] (fn [state] (if-let [type* (->> state (&/get$ "lux;types") (&/get$ "lux;mappings") (&/|get id))] @@ -16,21 +52,21 @@ [["lux;None" _]] (return* state false)) - (fail* (str "Unknown type-var: " id))))) + (fail* (str "[Type Error] Unknown type-var: " id))))) (defn deref [id] (fn [state] (let [mappings (->> state (&/get$ "lux;types") (&/get$ "lux;mappings"))] (do (prn 'deref/mappings (&/->seq (&/|keys mappings))) (if-let [type* (->> mappings (&/|get id))] - (do (prn 'deref/type* (aget type* 0)) + (do ;; (prn 'deref/type* (aget type* 0)) (matchv ::M/objects [type*] [["lux;Some" type]] (return* state type) [["lux;None" _]] - (fail* (str "Unbound type-var: " id)))) - (fail* (str "Unknown type-var: " id))))))) + (fail* (str "[Type Error] Unbound type-var: " id)))) + (fail* (str "[Type Error] Unknown type-var: " id))))))) (defn set-var [id type] (fn [state] @@ -38,17 +74,17 @@ (do ;; (prn 'set-var (aget tvar 0)) (matchv ::M/objects [tvar] [["lux;Some" bound]] - (fail* (str "Can't rebind type var: " id " | Current type: " (show-type bound))) + (fail* (str "[Type Error] Can't rebind type var: " id " | Current type: " (show-type bound))) [["lux;None" _]] (return* (&/update$ "lux;types" (fn [ts] (&/update$ "lux;mappings" #(&/|put id (&/V "lux;Some" type) %) ts)) state) nil))) - (fail* (str "Unknown type-var: " id))))) + (fail* (str "[Type Error] Unknown type-var: " id))))) ;; [Exports] -(def fresh-var +(def create-var (fn [state] (let [id (->> state (&/get$ "lux;types") (&/get$ "lux;counter"))] (return* (&/update$ "lux;types" #(->> % @@ -57,59 +93,79 @@ state) (&/V "lux;VarT" id))))) -(def fresh-lambda - (|do [=arg fresh-var - =return fresh-var] - (return (&/V "lux;LambdaT" (&/T =arg =return))))) - -(defn clean [tvar type] - (matchv ::M/objects [tvar] - [["lux;VarT" ?tid]] - (matchv ::M/objects [type] - [["lux;VarT" ?id]] - (if (= ?tid ?id) - (|do [=type (deref ?id)] - (clean tvar =type)) - (return type)) - - [["lux;LambdaT" [?arg ?return]]] - (|do [=arg (clean tvar ?arg) - =return (clean tvar ?return)] - (return (&/V "lux;LambdaT" (&/T =arg =return)))) - - [["lux;AppT" [?lambda ?param]]] - (|do [=lambda (clean tvar ?lambda) - =param (clean tvar ?param)] - (return (&/V "lux;AppT" (&/T =lambda =param)))) - - [["lux;TupleT" ?members]] - (|do [=members (&/map% (partial clean tvar) ?members)] - (return (&/V "lux;TupleT" =members))) - - [["lux;VariantT" ?members]] - (|do [=members (&/map% (fn [[k v]] - (|do [=v (clean tvar v)] - (return (&/T k =v)))) - ?members)] - (return (&/V "lux;VariantT" =members))) - - [["lux;RecordT" ?members]] - (|do [=members (&/map% (fn [[k v]] - (|do [=v (clean tvar v)] - (return (&/T k =v)))) - ?members)] - (return (&/V "lux;RecordT" =members))) - - [["lux;AllT" [?env ?name ?arg ?body]]] - (|do [=env (&/map% (fn [[k v]] - (|do [=v (clean tvar v)] - (return (&/T k =v)))) - ?env)] - (return (&/V "lux;AllT" (&/T =env ?name ?arg ?body)))) - - [_] - (return type) - ))) +(defn delete-var [id] + (fn [state] + (prn 'delete-var id) + (if-let [tvar (->> state (&/get$ "lux;types") (&/get$ "lux;mappings") (&/|get id))] + (return* (&/update$ "lux;types" (fn [ts] (&/update$ "lux;mappings" #(&/|remove id %) + ts)) + state) + nil) + (fail* (str "[Type Error] Unknown type-var: " id))))) + +(defn var-id [type] + (matchv ::M/objects [type] + [["lux;VarT" ?id]] + (return ?id) + + [_] + (fail (str "[Type Error] Not type-var: " (show-type type))))) + +(defn clean [?tid type] + (matchv ::M/objects [type] + [["lux;VarT" ?id]] + (if (= ?tid ?id) + (|do [=type (deref ?id)] + (clean ?tid =type)) + (return type)) + + [["lux;LambdaT" [?arg ?return]]] + (|do [=arg (clean ?tid ?arg) + =return (clean ?tid ?return)] + (return (&/V "lux;LambdaT" (&/T =arg =return)))) + + [["lux;AppT" [?lambda ?param]]] + (|do [=lambda (clean ?tid ?lambda) + =param (clean ?tid ?param)] + (return (&/V "lux;AppT" (&/T =lambda =param)))) + + [["lux;TupleT" ?members]] + (|do [=members (&/map% (partial clean ?tid) ?members)] + (return (&/V "lux;TupleT" =members))) + + [["lux;VariantT" ?members]] + (|do [=members (&/map% (fn [[k v]] + (|do [=v (clean ?tid v)] + (return (&/T k =v)))) + ?members)] + (return (&/V "lux;VariantT" =members))) + + [["lux;RecordT" ?members]] + (|do [=members (&/map% (fn [[k v]] + (|do [=v (clean ?tid v)] + (return (&/T k =v)))) + ?members)] + (return (&/V "lux;RecordT" =members))) + + [["lux;AllT" [?env ?name ?arg ?body]]] + (|do [=env (&/map% (fn [[k v]] + (|do [=v (clean ?tid v)] + (return (&/T k =v)))) + ?env) + body* (clean ?tid ?body)] + (return (&/V "lux;AllT" (&/T =env ?name ?arg body*)))) + + [_] + (return type) + )) + +(defn with-var [k] + (|do [=var create-var + id (var-id =var) + type (k =var)] + (|do [type* (clean id type) + _ (delete-var id)] + (return type*)))) (defn show-type [type] ;; (prn 'show-type (aget type 0)) @@ -167,80 +223,88 @@ )) (defn type= [x y] - (matchv ::M/objects [x y] - [["lux;AnyT" _] ["lux;AnyT" _]] - true - - [["lux;NothingT" _] ["lux;NothingT" _]] - true - - [["lux;DataT" xname] ["lux;DataT" yname]] - (= xname yname) - - [["lux;TupleT" xelems] ["lux;TupleT" yelems]] - (&/fold (fn [old xy] (and old (type= (aget xy 0) (aget xy 1)))) - true - (&/zip2 xelems yelems)) - - [["lux;VariantT" xcases] ["lux;VariantT" ycases]] - (&/fold (fn [old cases] - (matchv ::M/objects [cases] - [[[xtag xtype] [ytag ytype]]] - (and (= xtag ytag) - (type= xtype ytype)))) - true (&/zip2 xcases ycases)) - - - [["lux;RecordT" xfields] ["lux;RecordT" yfields]] - (&/fold (fn [old cases] - (matchv ::M/objects [cases] - [[[xtag xtype] [ytag ytype]]] - (and (= xtag ytag) - (type= xtype ytype)))) - true (&/zip2 xfields yfields)) - - [["lux;LambdaT" [xinput xoutput]] ["lux;LambdaT" [yinput youtput]]] - (and (type= xinput yinput) - (type= xoutput youtput)) - - [["lux;VarT" xid] ["lux;VarT" yid]] - (= xid yid) - - [["lux;BoundT" xname] ["lux;BoundT" yname]] - (= xname yname) - - [["lux;AppT" [xlambda xparam]] ["lux;AppT" [ylambda yparam]]] - (and (type= xlambda ylambda) - (type= xparam yparam)) - - [["lux;AllT" [xenv xname xarg xbody]] ["lux;AllT" [yenv yname yarg ybody]]] - (and (&/fold (fn [old cases] - (matchv ::M/objects [cases] - [[[xtag xtype] [ytag ytype]]] - (and (= xtag ytag) - (type= xtype ytype)))) - true (&/zip2 xenv yenv)) - (= xname yname) - (= xarg yarg) - (type= xbody ybody)) - - [_ _] - (do ;; (prn 'type= (show-type x) (show-type y)) - false) - )) - -(defn ^:private fp-get [k xs] - (matchv ::M/objects [k] - [[e a]] - (matchv ::M/objects [xs] + (let [output (matchv ::M/objects [x y] + [["lux;AnyT" _] ["lux;AnyT" _]] + true + + [["lux;NothingT" _] ["lux;NothingT" _]] + true + + [["lux;DataT" xname] ["lux;DataT" yname]] + (= xname yname) + + [["lux;TupleT" xelems] ["lux;TupleT" yelems]] + (&/fold (fn [old xy] + (|let [[x* y*] xy] + (and old + (type= x* y*)))) + true + (&/zip2 xelems yelems)) + + [["lux;VariantT" xcases] ["lux;VariantT" ycases]] + (and (= (&/|length xcases) (&/|length ycases)) + (&/fold (fn [old case] + (and old + (type= (&/|get case xcases) (&/|get case ycases)))) + true + (&/|keys xcases))) + + [["lux;RecordT" xfields] ["lux;RecordT" yfields]] + (and (= (&/|length xfields) (&/|length yfields)) + (&/fold (fn [old field] + (and old + (type= (&/|get field xfields) (&/|get field yfields)))) + true + (&/|keys xfields))) + + [["lux;LambdaT" [xinput xoutput]] ["lux;LambdaT" [yinput youtput]]] + (and (type= xinput yinput) + (type= xoutput youtput)) + + [["lux;VarT" xid] ["lux;VarT" yid]] + (= xid yid) + + [["lux;BoundT" xname] ["lux;BoundT" yname]] + (= xname yname) + + [["lux;AppT" [xlambda xparam]] ["lux;AppT" [ylambda yparam]]] + (and (type= xlambda ylambda) + (type= xparam yparam)) + + [["lux;AllT" [xenv xname xarg xbody]] ["lux;AllT" [yenv yname yarg ybody]]] + (do ;; (prn 'TESTING_ALLT + ;; 'NAME [xname yname] (= xname yname) + ;; 'ARG (= xarg yarg) + ;; 'LENGTH [(&/|length xenv) (&/|length yenv)] (= (&/|length xenv) (&/|length yenv))) + (and (= xname yname) + (= xarg yarg) + (type= xbody ybody) + ;; (= (&/|length xenv) (&/|length yenv)) + ;; (&/fold (fn [old bname] + ;; (and old + ;; (type= (&/|get bname xenv) (&/|get bname yenv)))) + ;; true + ;; (&/|keys xenv)) + )) + + [_ _] + (do (prn 'type= (show-type x) (show-type y)) + false) + )] + ;; (prn 'type= output (show-type x) (show-type y)) + output)) + +(defn ^:private fp-get [k fixpoints] + (|let [[e a] k] + (matchv ::M/objects [fixpoints] [["lux;Nil" _]] (&/V "lux;None" nil) - [["lux;Cons" [[[e* a*] v*] xs*]]] + [["lux;Cons" [[[e* a*] v*] fixpoints*]]] (if (and (type= e e*) (type= a a*)) (&/V "lux;Some" v*) - (fp-get k xs*)) + (fp-get k fixpoints*)) ))) (defn ^:private fp-put [k v fixpoints] @@ -315,7 +379,7 @@ (def init-fixpoints (&/|list)) (defn ^:private check* [fixpoints expected actual] - (prn 'check* (aget expected 0) (aget actual 0)) + ;; (prn 'check* (aget expected 0) (aget actual 0)) ;; (prn 'check* (show-type expected) (show-type actual)) (matchv ::M/objects [expected actual] [["lux;AnyT" _] _] @@ -347,8 +411,17 @@ (check* fixpoints expected bound)))) [["lux;AppT" [F A]] _] - (|do [expected* (apply-type F A) - :let [fp-pair (&/T expected actual)]] + (let [fp-pair (&/T expected actual) + _ (prn 'LEFT_APP (&/|length fixpoints)) + _ (when (> (&/|length fixpoints) 10) + (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))] (matchv ::M/objects [(fp-get fp-pair fixpoints)] [["lux;Some" ?]] (if ? @@ -356,21 +429,34 @@ (fail (check-error expected actual))) [["lux;None" _]] - (check* (fp-put fp-pair true fixpoints) expected* actual))) + (|do [expected* (apply-type F A)] + (check* (fp-put fp-pair true fixpoints) expected* actual)))) [_ ["lux;AppT" [F A]]] (|do [actual* (apply-type F A)] (check* fixpoints expected actual*)) [["lux;AllT" _] _] - (|do [$var fresh-var - expected* (apply-type expected $var)] - (check* fixpoints expected* actual)) + (with-var + (fn [$arg] + (|do [expected* (apply-type expected $arg)] + (check* fixpoints expected* actual)))) [_ ["lux;AllT" _]] - (|do [$var fresh-var - actual* (apply-type actual $var)] - (check* fixpoints expected actual*)) + (with-var + (fn [$arg] + (|do [actual* (apply-type actual $arg)] + (check* fixpoints expected actual*)))) + + ;; [["lux;AllT" _] _] + ;; (|do [$arg create-var + ;; expected* (apply-type expected $arg)] + ;; (check* fixpoints expected* actual)) + + ;; [_ ["lux;AllT" _]] + ;; (|do [$arg create-var + ;; actual* (apply-type actual $arg)] + ;; (check* fixpoints expected actual*)) [["lux;DataT" e!name] ["lux;DataT" a!name]] (if (= e!name a!name) @@ -382,8 +468,8 @@ (check* fixpoints* eO aO)) [["lux;TupleT" e!members] ["lux;TupleT" a!members]] - (do (do (prn 'e!members (&/|length e!members)) - (prn 'a!members (&/|length a!members))) + (do ;; (do (prn 'e!members (&/|length e!members)) + ;; (prn 'a!members (&/|length a!members))) (if (= (&/|length e!members) (&/|length a!members)) (|do [fixpoints* (&/fold% (fn [fixp ea] (|let [[e a] ea] @@ -405,7 +491,7 @@ [["lux;VariantT" e!cases] ["lux;VariantT" a!cases]] (if (= (&/|length e!cases) (&/|length a!cases)) (|do [fixpoints* (&/fold% (fn [fixp slot] - (prn "lux;VariantT" slot) + (prn 'VARIANT_CASE slot) (if-let [e!type (&/|get slot e!cases)] (if-let [a!type (&/|get slot a!cases)] (|do [[fixp* _] (check* fixp e!type a!type)] @@ -420,7 +506,7 @@ [["lux;RecordT" e!fields] ["lux;RecordT" a!fields]] (if (= (&/|length e!fields) (&/|length a!fields)) (|do [fixpoints* (&/fold% (fn [fixp slot] - (prn "lux;RecordT" slot) + (prn 'RECORD_FIELD slot) (if-let [e!type (&/|get slot e!fields)] (if-let [a!type (&/|get slot a!fields)] (|do [[fixp* _] (check* fixp e!type a!type)] @@ -456,9 +542,10 @@ (return output)) [["lux;AllT" [local-env local-name local-arg local-def]]] - (|do [$var fresh-var - func* (apply-type func $var)] - (apply-lambda func* param)) + (with-var + (fn [$arg] + (|do [func* (apply-type func $arg)] + (apply-lambda func* param)))) [_] (fail (str "[Type System] Can't apply type " (show-type func) " to type " (show-type param))) @@ -473,39 +560,3 @@ [_] (return type) )) - -(def Any (&/V "lux;AnyT" nil)) -(def Nothing (&/V "lux;NothingT" nil)) -(def Bool (&/V "lux;DataT" "java.lang.Boolean")) -(def Int (&/V "lux;DataT" "java.lang.Long")) -(def Real (&/V "lux;DataT" "java.lang.Double")) -(def Char (&/V "lux;DataT" "java.lang.Character")) -(def Text (&/V "lux;DataT" "java.lang.String")) -(def Unit (&/V "lux;TupleT" (&/|list))) - -(def List - (&/V "lux;AllT" (&/T (&/|table) "List" "a" - (&/V "lux;VariantT" (&/|list (&/T "lux;Nil" (&/V "lux;TupleT" (&/|list))) - (&/T "lux;Cons" (&/V "lux;TupleT" (&/|list (&/V "lux;BoundT" "a") - (&/V "lux;AppT" (&/T (&/V "lux;BoundT" "List") - (&/V "lux;BoundT" "a"))))))))))) - -(def Type - (let [Type (&/V "lux;AppT" (&/T (&/V "lux;BoundT" "Type") (&/V "lux;BoundT" "_"))) - TypeEnv (&/V "lux;AppT" (&/T List (&/V "lux;TupleT" (&/|list Text Type)))) - Unit (&/V "lux;TupleT" (&/|list)) - TypePair (&/V "lux;TupleT" (&/|list Type Type))] - (&/V "lux;AppT" (&/T (&/V "lux;AllT" (&/T (&/|list) "Type" "_" - (&/V "lux;VariantT" (&/|list (&/T "lux;AnyT" Unit) - (&/T "lux;NothingT" Unit) - (&/T "lux;DataT" Text) - (&/T "lux;TupleT" (&/V "lux;AppT" (&/T List Type))) - (&/T "lux;VariantT" TypeEnv) - (&/T "lux;RecordT" TypeEnv) - (&/T "lux;LambdaT" TypePair) - (&/T "lux;BoundT" Text) - (&/T "lux;VarT" Int) - (&/T "lux;AllT" (&/V "lux;TupleT" (&/|list TypeEnv Text Text Type))) - (&/T "lux;AppT" TypePair) - )))) - (&/V "lux;NothingT" nil))))) |