diff options
author | Eduardo Julian | 2015-04-15 19:26:37 -0400 |
---|---|---|
committer | Eduardo Julian | 2015-04-15 19:26:37 -0400 |
commit | f6dc520d04b517cd8e907d4738aae60b279c3877 (patch) | |
tree | f17b4a609619d364d241f71801f6da7d6b620e22 /src | |
parent | ed1163370cd37f15d18e2b3d6cb6ecc13cd50243 (diff) |
- Fixed a few type-related bugs.
- Variants now need types to be specified both when constructing them as when deconstructing them (in pattern-matching).
- Simplified DataT types by no-longer requiring a list of params, so only the tame name is necessary.
Diffstat (limited to 'src')
-rw-r--r-- | src/lux/analyser.clj | 14 | ||||
-rw-r--r-- | src/lux/analyser/base.clj | 24 | ||||
-rw-r--r-- | src/lux/analyser/case.clj | 32 | ||||
-rw-r--r-- | src/lux/analyser/host.clj | 16 | ||||
-rw-r--r-- | src/lux/analyser/lux.clj | 132 | ||||
-rw-r--r-- | src/lux/base.clj | 10 | ||||
-rw-r--r-- | src/lux/compiler/host.clj | 10 | ||||
-rw-r--r-- | src/lux/host.clj | 14 | ||||
-rw-r--r-- | src/lux/type.clj | 357 |
9 files changed, 284 insertions, 325 deletions
diff --git a/src/lux/analyser.clj b/src/lux/analyser.clj index 156af6631..39eaf9e16 100644 --- a/src/lux/analyser.clj +++ b/src/lux/analyser.clj @@ -38,19 +38,19 @@ (matchv ::M/objects [token] ;; Standard special forms [["lux;Meta" [meta ["lux;Bool" ?value]]]] - (return (&/|list (&/V "Expression" (&/T (&/V "bool" ?value) (&/V "lux;DataT" (&/T "java.lang.Boolean" (|list))))))) + (return (&/|list (&/V "Expression" (&/T (&/V "bool" ?value) &type/Bool)))) [["lux;Meta" [meta ["lux;Int" ?value]]]] - (return (&/|list (&/V "Expression" (&/T (&/V "int" ?value) (&/V "lux;DataT" (&/T "java.lang.Long" (|list))))))) + (return (&/|list (&/V "Expression" (&/T (&/V "int" ?value) &type/Int)))) [["lux;Meta" [meta ["lux;Real" ?value]]]] - (return (&/|list (&/V "Expression" (&/T (&/V "real" ?value) (&/V "lux;DataT" (&/T "java.lang.Double" (|list))))))) + (return (&/|list (&/V "Expression" (&/T (&/V "real" ?value) &type/Real)))) [["lux;Meta" [meta ["lux;Char" ?value]]]] - (return (&/|list (&/V "Expression" (&/T (&/V "char" ?value) (&/V "lux;DataT" (&/T "java.lang.Character" (|list))))))) + (return (&/|list (&/V "Expression" (&/T (&/V "char" ?value) &type/Char)))) [["lux;Meta" [meta ["lux;Text" ?value]]]] - (return (&/|list (&/V "Expression" (&/T (&/V "text" ?value) (&/V "lux;DataT" (&/T "java.lang.String" (|list))))))) + (return (&/|list (&/V "Expression" (&/T (&/V "text" ?value) &type/Text)))) [["lux;Meta" [meta ["lux;Tuple" ?elems]]]] (&&lux/analyse-tuple analyse exo-type ?elems) @@ -62,7 +62,7 @@ (&&lux/analyse-variant analyse exo-type ?ident (_meta (&/V "lux;Tuple" (|list)))) [["lux;Meta" [meta ["lux;Symbol" [_ "jvm-null"]]]]] - (return (&/|list (&/V "Expression" (&/T (&/V "jvm-null" nil) (&/V "lux;DataT" (&/T "null" (|list))))))) + (return (&/|list (&/V "Expression" (&/T (&/V "jvm-null" nil) (&/V "lux;DataT" "null"))))) [["lux;Meta" [meta ["lux;Symbol" ?ident]]]] (&&lux/analyse-symbol analyse exo-type ?ident) @@ -422,7 +422,7 @@ (fail (str "[Analyser Error] Unmatched token: " (&/show-ast token))))) (defn ^:private analyse-ast [eval! exo-type token] - ;; (prn 'analyse-ast token) + ;; (prn 'analyse-ast (aget token 0)) (matchv ::M/objects [token] [["lux;Meta" [meta ["lux;Form" ["lux;Cons" [["lux;Meta" [_ ["lux;Tag" ?ident]]] ?values]]]]]] (do (assert (= 1 (&/|length ?values)) "[Analyser Error] Can only tag 1 value.") diff --git a/src/lux/analyser/base.clj b/src/lux/analyser/base.clj index b287b545f..0d2d8304a 100644 --- a/src/lux/analyser/base.clj +++ b/src/lux/analyser/base.clj @@ -11,7 +11,7 @@ (matchv ::M/objects [syntax+] [["Expression" [_ type]]] (do ;; (prn 'expr-type (&type/show-type type)) - (return type)) + (return type)) [["Statement" _]] (fail (str "[Analyser Error] Can't retrieve the type of a statement: " (pr-str syntax+))))) @@ -19,26 +19,26 @@ (defn analyse-1 [analyse exo-type elem] (|do [output (analyse exo-type elem)] (do ;; (prn 'analyse-1 (aget output 0)) - (matchv ::M/objects [output] - [["lux;Cons" [x ["lux;Nil" _]]]] - (return x) + (matchv ::M/objects [output] + [["lux;Cons" [x ["lux;Nil" _]]]] + (return x) - [_] - (fail "[Analyser Error] Can't expand to other than 1 element."))))) + [_] + (fail "[Analyser Error] Can't expand to other than 1 element."))))) (defn analyse-2 [analyse el1 el2] (|do [output (&/flat-map% analyse (&/|list el1 el2))] (do ;; (prn 'analyse-2 (aget output 0)) - (matchv ::M/objects [output] - [["lux;Cons" [x ["lux;Cons" [y ["lux;Nil" _]]]]]] - (return [x y]) + (matchv ::M/objects [output] + [["lux;Cons" [x ["lux;Cons" [y ["lux;Nil" _]]]]]] + (return [x y]) - [_] - (fail "[Analyser Error] Can't expand to other than 2 elements."))))) + [_] + (fail "[Analyser Error] Can't expand to other than 2 elements."))))) (defn with-var [k] (|do [=var &type/fresh-var - =ret (k =var)] + =ret (k =var)] (matchv ::M/objects [=ret] [["Expression" [?expr ?type]]] (|do [=type (&type/clean =var ?type)] diff --git a/src/lux/analyser/case.clj b/src/lux/analyser/case.clj index c33e32af1..6b2fe7a03 100644 --- a/src/lux/analyser/case.clj +++ b/src/lux/analyser/case.clj @@ -9,9 +9,7 @@ ;; [Utils] (defn ^:private analyse-variant [analyse-pattern idx value-type tag value] - (|do [=var &type/fresh-var - _ (&type/check value-type (&/V "lux;VariantT" (&/|list (&/T tag =var)))) - [idx* test] (analyse-pattern idx =var value)] + (|do [[idx* test] (analyse-pattern idx value-type value)] (return (&/T idx* (&/V "VariantTestAC" (&/T tag test)))))) (defn ^:private analyse-pattern [idx value-type pattern] @@ -19,17 +17,17 @@ (matchv ::M/objects [pattern] [["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" - ) + (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" _]]]]]] @@ -281,8 +279,10 @@ (every? true? totals)))) [_ ["VariantTotal" [?total ?structs]]] - (|do [real-type (resolve-type value-type)] - (assert false)) + (&/try-all% (&/|list (|do [real-type (resolve-type value-type) + :let [_ (prn 'real-type (&type/show-type real-type))]] + (assert false)) + (fail "[Pattern-maching error] Can't pattern-match on an unknown variant type."))) [_ ["DefaultTotal" true]] (return true) diff --git a/src/lux/analyser/host.clj b/src/lux/analyser/host.clj index 6fce672de..33ceb2b22 100644 --- a/src/lux/analyser/host.clj +++ b/src/lux/analyser/host.clj @@ -20,8 +20,8 @@ ;; [Resources] (do-template [<name> <output-tag> <input-class> <output-class>] - (let [input-type (&/V "lux;DataT" (to-array [<input-class> (&/V "lux;Nil" nil)])) - output-type (&/V "lux;DataT" (to-array [<output-class> (&/V "lux;Nil" nil)]))] + (let [input-type (&/V "lux;DataT" <input-class>) + output-type (&/V "lux;DataT" <output-class>)] (defn <name> [analyse ?x ?y] (|do [[=x =y] (&&/analyse-2 analyse ?x ?y) =x-type (&&/expr-type =x) @@ -126,17 +126,17 @@ (defn analyse-jvm-null? [analyse ?object] (|do [=object (&&/analyse-1 analyse ?object)] - (return (&/|list (&/V "Expression" (&/T (&/V "jvm-null?" =object) (&/V "lux;DataT" (&/T "java.lang.Boolean" (&/V "lux;Nil" nil))))))))) + (return (&/|list (&/V "Expression" (&/T (&/V "jvm-null?" =object) (&/V "lux;DataT" "java.lang.Boolean"))))))) (defn analyse-jvm-new [analyse ?class ?classes ?args] (|do [=class (&host/full-class-name ?class) =classes (&/map% &host/extract-jvm-param ?classes) =args (&/flat-map% analyse ?args)] - (return (&/|list (&/V "Expression" (&/T (&/V "jvm-new" (&/T =class =classes =args)) (&/V "lux;DataT" (&/T =class (&/V "lux;Nil" nil))))))))) + (return (&/|list (&/V "Expression" (&/T (&/V "jvm-new" (&/T =class =classes =args)) (&/V "lux;DataT" =class))))))) (defn analyse-jvm-new-array [analyse ?class ?length] (|do [=class (&host/full-class-name ?class)] - (return (&/|list (&/V "Expression" (&/T (&/V "jvm-new-array" (&/T =class ?length)) (&/V "array" (&/T (&/V "lux;DataT" (to-array [=class (&/V "lux;Nil" nil)])) + (return (&/|list (&/V "Expression" (&/T (&/V "jvm-new-array" (&/T =class ?length)) (&/V "array" (&/T (&/V "lux;DataT" =class) (&/V "lux;Nil" nil))))))))) (defn analyse-jvm-aastore [analyse ?array ?idx ?elem] @@ -198,7 +198,7 @@ (defn analyse-jvm-try [analyse ?body [?catches ?finally]] (|do [=body (&&/analyse-1 analyse ?body) =catches (&/map% (fn [[?ex-class ?ex-arg ?catch-body]] - (&&env/with-local ?ex-arg (&/V "lux;DataT" (&/T ?ex-class (&/V "lux;Nil" nil))) + (&&env/with-local ?ex-arg (&/V "lux;DataT" ?ex-class) (|do [=catch-body (&&/analyse-1 analyse ?catch-body)] (return [?ex-class ?ex-arg =catch-body])))) ?catches) @@ -221,7 +221,7 @@ (do-template [<name> <tag> <from-class> <to-class>] (defn <name> [analyse ?value] (|do [=value (&&/analyse-1 analyse ?value)] - (return (&/|list (&/V "Expression" (&/T (&/V <tag> =value) (&/V "lux;DataT" (&/T <to-class> (&/V "lux;Nil" nil))))))))) + (return (&/|list (&/V "Expression" (&/T (&/V <tag> =value) (&/V "lux;DataT" <to-class>))))))) analyse-jvm-d2f "jvm-d2f" "java.lang.Double" "java.lang.Float" analyse-jvm-d2i "jvm-d2i" "java.lang.Double" "java.lang.Integer" @@ -246,7 +246,7 @@ (do-template [<name> <tag> <from-class> <to-class>] (defn <name> [analyse ?value] (|do [=value (&&/analyse-1 analyse ?value)] - (return (&/|list (&/V "Expression" (&/T (&/V <tag> =value) (&/V "lux;DataT" (&/T <to-class> (&/V "lux;Nil" nil))))))))) + (return (&/|list (&/V "Expression" (&/T (&/V <tag> =value) (&/V "lux;DataT" <to-class>))))))) analyse-jvm-iand "jvm-iand" "java.lang.Integer" "java.lang.Integer" analyse-jvm-ior "jvm-ior" "java.lang.Integer" "java.lang.Integer" diff --git a/src/lux/analyser/lux.clj b/src/lux/analyser/lux.clj index 61ca08b42..a9a42ffe3 100644 --- a/src/lux/analyser/lux.clj +++ b/src/lux/analyser/lux.clj @@ -19,30 +19,53 @@ ;; [Exports] (defn analyse-tuple [analyse exo-type ?elems] - (|do [=elems (&/map% (analyse-1+ analyse) ?elems) - =elems-types (&/map% &&/expr-type =elems) - ;; :let [_ (prn 'analyse-tuple =elems)] - :let [endo-type (&/V "lux;TupleT" =elems-types)] - _ (&type/check exo-type endo-type) - ;; :let [_ (prn 'analyse-tuple 'DONE)] - ] + (prn 'analyse-tuple (str "[" (->> ?elems (&/|map &/show-ast) (&/|interpose " ") (&/fold str "")) "]") + (&type/show-type exo-type)) + (|do [members-vars (&/map% (constantly &type/fresh-var) ?elems) + _ (&type/check exo-type (&/V "lux;TupleT" members-vars)) + =elems (&/map% (fn [ve] + (|let [[=var elem] ve] + (|do [output (&&/analyse-1 analyse =var elem)] + (matchv ::M/objects [output] + [["Expression" [?val ?type]]] + (|do [=val-type (&type/clean =var ?type)] + (return (&/V "Expression" (&/T ?val exo-type)))))))) + (&/zip2 members-vars ?elems))] (return (&/|list (&/V "Expression" (&/T (&/V "tuple" =elems) exo-type)))))) (defn analyse-variant [analyse exo-type ident ?value] (|let [[?module ?name] ident] - (|do [module (if (= "" ?module) - &/get-module-name - (return ?module)) - :let [?tag (str module ";" ?name)] - =value ((analyse-1+ analyse) ?value) - =value-type (&&/expr-type =value) - :let [endo-type (&/V "lux;VariantT" (|list (&/T ?tag =value-type)))] - _ (&type/check exo-type endo-type) - ;; :let [_ (prn 'analyse-variant 'DONE)] - ] - (return (&/|list (&/V "Expression" (&/T (&/V "variant" (&/T ?tag =value)) - exo-type))))))) + (do (prn 'analyse-variant (str ?module ";" ?name) (&/show-ast ?value)) + (|do [:let [_ (prn 'analyse-variant/exo-type (&type/show-type exo-type))] + module (if (= "" ?module) + &/get-module-name + (return ?module)) + :let [?tag (str module ";" ?name)] + exo-type* (matchv ::M/objects [exo-type] + [["lux;VarT" ?id]] + (|do [? (&type/bound? ?id)] + (if ? + (|do [exo-type (&type/deref ?id)] + (&type/actual-type exo-type)) + (|do [_ (&type/set-var ?id &type/Type)] + (&type/actual-type &type/Type)))) + + [_] + (&type/actual-type exo-type)) + :let [_ (prn 'exo-type* (&type/show-type exo-type*))]] + (matchv ::M/objects [exo-type*] + [["lux;VariantT" ?cases]] + (if-let [vtype (&/|get ?tag ?cases)] + (|do [:let [_ (prn 'VARIANT_BODY ?tag (&/show-ast ?value) (&type/show-type vtype))] + =value (&&/analyse-1 analyse vtype ?value) + :let [_ (prn 'GOT_VALUE =value)]] + (return (&/|list (&/V "Expression" (&/T (&/V "variant" (&/T ?tag =value)) + exo-type))))) + (fail (str "[Analyser Error] There is no case " ?tag " for variant type " (&type/show-type exo-type*)))) + + [_] + (fail (str "[Analyser Error] Can't create a variant if the expected type is " (&type/show-type exo-type*)))))))) (defn analyse-record [analyse exo-type ?elems] (|do [=elems (&/map% (fn [kv] @@ -162,39 +185,41 @@ (defn analyse-lambda [analyse exo-type ?self ?arg ?body] ;; (prn 'analyse-lambda ?self ?arg ?body) - (|do [=lambda-type* &type/fresh-lambda] + (|do [=lambda-type* &type/fresh-lambda + _ (&type/check exo-type =lambda-type*)] (matchv ::M/objects [=lambda-type*] [["lux;LambdaT" [=arg =return]]] (|do [[=scope =captured =body] (&&lambda/with-lambda ?self =lambda-type* ?arg =arg (&&/analyse-1 analyse =return ?body)) =lambda-type** (&type/clean =return =lambda-type*) - =bound-arg (&type/lookup =arg) - =lambda-type (matchv ::M/objects [=arg =bound-arg] - [["lux;VarT" id] ["lux;Some" bound]] - (&type/clean =arg =lambda-type**) - - [["lux;VarT" id] ["lux;None" _]] - (let [var-name (str (gensym "")) - bound (&/V "lux;BoundT" var-name)] - (|do [_ (&type/reset id bound) - lambda-type (&type/clean =arg =lambda-type**)] - (return (&/V "lux;AllT" (&/T (&/|list) "" var-name lambda-type))))))] + =lambda-type (matchv ::M/objects [=arg] + [["lux;VarT" ?id]] + (&/try-all% (&/|list (|do [bound (&type/deref ?id)] + (&type/clean =arg =lambda-type**)) + (let [var-name (str (gensym ""))] + (|do [_ (&type/set-var ?id (&/V "lux;BoundT" var-name)) + lambda-type (&type/clean =arg =lambda-type**)] + (return (&/V "lux;AllT" (&/T (&/|list) "" var-name lambda-type))))))) + + [_] + (fail ""))] (return (&/|list (&/V "Expression" (&/T (&/V "lambda" (&/T =scope =captured =body)) =lambda-type)))))))) (defn analyse-def [analyse exo-type ?name ?value] - ;; (prn 'analyse-def ?name ?value) - (|do [_ (&type/check &type/Nothing exo-type) - module-name &/get-module-name] - (&/if% (&&def/defined? module-name ?name) - (fail (str "[Analyser Error] Can't redefine " ?name)) - (|do [=value (&/with-scope ?name - (&&/with-var - #(&&/analyse-1 analyse % ?value))) - =value-type (&&/expr-type =value) - :let [_ (prn 'analyse-def ?name (&type/show-type =value-type))] - _ (&&def/define module-name ?name =value-type)] - (return (&/|list (&/V "Statement" (&/V "def" (&/T ?name =value))))))))) + (prn 'analyse-def ?name (&/show-ast ?value)) + (|do [_ (&type/check exo-type &type/Nothing) + module-name &/get-module-name + ? (&&def/defined? module-name ?name)] + (if ? + (fail (str "[Analyser Error] Can't redefine " ?name)) + (|do [=value (&/with-scope ?name + (&&/with-var + #(&&/analyse-1 analyse % ?value))) + =value-type (&&/expr-type =value) + :let [_ (prn 'analyse-def ?name (&type/show-type =value-type))] + _ (&&def/define module-name ?name =value-type)] + (return (&/|list (&/V "Statement" (&/V "def" (&/T ?name =value))))))))) (defn analyse-declare-macro [exo-type ident] (|let [[?module ?name] ident] @@ -211,23 +236,24 @@ (defn analyse-check [analyse eval! exo-type ?type ?value] (println "analyse-check#0") (|do [=type (&&/analyse-1 analyse &type/Type ?type) - :let [_ (println "analyse-check#1")] - ==type (eval! =type) - _ (&type/check exo-type ==type) - :let [_ (println "analyse-check#4" (&type/show-type ==type))] - =value (&&/analyse-1 analyse ==type ?value) - :let [_ (println "analyse-check#5")]] + ;; =type ((analyse-1+ analyse) ?type) + :let [_ (println "analyse-check#1")] + ==type (eval! =type) + _ (&type/check exo-type ==type) + :let [_ (println "analyse-check#4" (&type/show-type ==type))] + =value (&&/analyse-1 analyse exo-type ?value) + :let [_ (println "analyse-check#5")]] (matchv ::M/objects [=value] [["Expression" [?expr ?expr-type]]] (|do [:let [_ (println "analyse-check#6" (&type/show-type ?expr-type))] - _ (&type/check ==type ?expr-type) - :let [_ (println "analyse-check#7")]] + _ (&type/check ==type ?expr-type) + :let [_ (println "analyse-check#7")]] (return (&/|list (&/V "Expression" (&/T ?expr ==type)))))))) (defn analyse-coerce [analyse eval! exo-type ?type ?value] (|do [=type (&&/analyse-1 analyse &type/Type ?type) - ==type (eval! =type) - =value (&&/analyse-1 analyse ==type ?value)] + ==type (eval! =type) + =value (&&/analyse-1 analyse ==type ?value)] (matchv ::M/objects [=value] [["Expression" [?expr ?expr-type]]] (return (&/|list (&/V "Expression" (&/T ?expr ==type))))))) diff --git a/src/lux/base.clj b/src/lux/base.clj index a8649816a..91519eb0c 100644 --- a/src/lux/base.clj +++ b/src/lux/base.clj @@ -125,6 +125,7 @@ ;; [Resources/Monads] (defn fail [message] (fn [_] + (prn 'FAIL message) (V "lux;Left" message))) (defn return [value] @@ -144,8 +145,7 @@ [["lux;Right" [?state ?datum]]] (let [next-fn (step ?datum)] (when (not (fn? next-fn)) - (prn 'bind (aget next-fn 0) - (aget next-fn 1))) + (prn 'bind (aget next-fn 0) (aget next-fn 1))) (next-fn ?state)) [["lux;Left" _]] @@ -676,7 +676,7 @@ (monad state)) (defn show-ast [ast] - (prn 'show-ast (aget ast 0)) + ;; (prn 'show-ast (aget ast 0)) ;; (prn 'show-ast (aget ast 1 1 0)) ;; (cond (= "lux;Meta" (aget ast 1 1 0)) ;; (prn 'EXTRA 'show-ast (aget ast 1 1 1 1 0)) @@ -706,7 +706,9 @@ (str "#" ?module ";" ?tag) [["lux;Meta" [_ ["lux;Symbol" [?module ?ident]]]]] - (str ?module ";" ?ident) + (if (= "" ?module) + ?ident + (str ?module ";" ?ident)) [["lux;Meta" [_ ["lux;Tuple" ?elems]]]] (str "[" (->> ?elems (|map show-ast) (|interpose " ") (fold str "")) "]") diff --git a/src/lux/compiler/host.clj b/src/lux/compiler/host.clj index f289ed6ba..184c6a4f4 100644 --- a/src/lux/compiler/host.clj +++ b/src/lux/compiler/host.clj @@ -43,19 +43,19 @@ [["lux;NothingT" nil]] (.visitInsn *writer* Opcodes/ACONST_NULL) - [["lux;DataT" ["char" _]]] + [["lux;DataT" "char"]] (.visitMethodInsn *writer* Opcodes/INVOKESTATIC (&host/->class char-class) "valueOf" (str "(C)" (&host/->type-signature char-class))) - [["lux;DataT" ["int" _]]] + [["lux;DataT" "int"]] (.visitMethodInsn *writer* Opcodes/INVOKESTATIC (&host/->class integer-class) "valueOf" (str "(I)" (&host/->type-signature integer-class))) - [["lux;DataT" ["long" _]]] + [["lux;DataT" "long"]] (.visitMethodInsn *writer* Opcodes/INVOKESTATIC (&host/->class long-class) "valueOf" (str "(J)" (&host/->type-signature long-class))) - [["lux;DataT" ["boolean" _]]] + [["lux;DataT" "boolean"]] (.visitMethodInsn *writer* Opcodes/INVOKESTATIC (&host/->class boolean-class) "valueOf" (str "(Z)" (&host/->type-signature boolean-class))) - [["lux;DataT" [_ _]]] + [["lux;DataT" _]] nil) *writer*)) diff --git a/src/lux/host.clj b/src/lux/host.clj index b10b23995..4d1fef04a 100644 --- a/src/lux/host.clj +++ b/src/lux/host.clj @@ -20,13 +20,8 @@ (.getSimpleName class)))] (if (= "void" base) (return (&/V "lux;NothingT" nil)) - (let [base* (&/V "lux;DataT" (&/T base (&/V "lux;Nil" nil)))] - (if arr-level - (return (reduce (fn [inner _] - (&/V "array" (&/V "lux;Cons" (&/T inner (&/V "lux;Nil" nil))))) - base* - (range (/ (count arr-level) 2.0)))) - (return base*))) + (return (&/V "lux;DataT" (str (reduce str "" (repeat (int (/ (count arr-level) 2)) "[")) + base))) ))) (defn ^:private method->type [method] @@ -87,10 +82,7 @@ [["lux;NothingT" _]] "V" - [["lux;DataT" ["array" ["lux;Cons" [?elem ["lux;Nil" _]]]]]] - (str "[" (->java-sig ?elem)) - - [["lux;DataT" [?name ?params]]] + [["lux;DataT" ?name]] (->type-signature ?name) [["lux;LambdaT" [_ _]]] diff --git a/src/lux/type.clj b/src/lux/type.clj index 1fbaa78c0..0cd839cf2 100644 --- a/src/lux/type.clj +++ b/src/lux/type.clj @@ -1,41 +1,50 @@ (ns lux.type - (:refer-clojure :exclude [deref apply merge]) + (:refer-clojure :exclude [deref apply merge bound?]) (:require [clojure.core.match :as M :refer [match matchv]] clojure.core.match.array [lux.base :as & :refer [|do return* return fail fail* assert! |let]])) -;; [Util] -(def ^:private success (return nil)) - -(defn lookup [type] - (matchv ::M/objects [type] - [["lux;VarT" id]] - (fn [state] - (if-let [type* (->> state (&/get$ "lux;types") (&/get$ "lux;mappings") (&/|get id))] - (return* state type*) - (fail* (str "Unknown type-var: " id)))) +(declare show-type) - [_] - (fail "[Type Error] Can't lookup non-vars."))) - -(defn deref [id] +;; [Util] +(defn bound? [id] (fn [state] (if-let [type* (->> state (&/get$ "lux;types") (&/get$ "lux;mappings") (&/|get id))] (matchv ::M/objects [type*] - [["lux;Some" type]] - (return* state type) + [["lux;Some" _]] + (return* state true) [["lux;None" _]] - (fail* (str "Unbound type-var: " id))) + (return* state false)) (fail* (str "Unknown type-var: " id))))) -(defn reset [id type] +(defn deref [id] (fn [state] - (if-let [_ (->> state (&/get$ "lux;types") (&/get$ "lux;mappings") (&/|get id))] - (return* (&/update$ "lux;types" (fn [ts] (&/update$ "lux;mappings" #(&/|put id (&/V "lux;Some" type) %) - ts)) - state) - nil) + (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)) + (matchv ::M/objects [type*] + [["lux;Some" type]] + (return* state type) + + [["lux;None" _]] + (fail* (str "Unbound type-var: " id)))) + (fail* (str "Unknown type-var: " id))))))) + +(defn set-var [id type] + (fn [state] + (if-let [tvar (->> state (&/get$ "lux;types") (&/get$ "lux;mappings") (&/|get id))] + (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))) + + [["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))))) ;; [Exports] @@ -50,7 +59,7 @@ (def fresh-lambda (|do [=arg fresh-var - =return fresh-var] + =return fresh-var] (return (&/V "lux;LambdaT" (&/T =arg =return))))) (defn clean [tvar type] @@ -59,19 +68,18 @@ (matchv ::M/objects [type] [["lux;VarT" ?id]] (if (= ?tid ?id) - (&/try-all% (&/|list (|do [=type (deref ?id)] - (clean tvar =type)) - (return type))) + (|do [=type (deref ?id)] + (clean tvar =type)) (return type)) [["lux;LambdaT" [?arg ?return]]] (|do [=arg (clean tvar ?arg) - =return (clean tvar ?return)] + =return (clean tvar ?return)] (return (&/V "lux;LambdaT" (&/T =arg =return)))) [["lux;AppT" [?lambda ?param]]] (|do [=lambda (clean tvar ?lambda) - =param (clean tvar ?param)] + =param (clean tvar ?param)] (return (&/V "lux;AppT" (&/T =lambda =param)))) [["lux;TupleT" ?members]] @@ -80,23 +88,23 @@ [["lux;VariantT" ?members]] (|do [=members (&/map% (fn [[k v]] - (|do [=v (clean tvar v)] - (return (&/T k =v)))) - ?members)] + (|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)] + (|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)] + (|do [=v (clean tvar v)] + (return (&/T k =v)))) + ?env)] (return (&/V "lux;AllT" (&/T =env ?name ?arg ?body)))) [_] @@ -112,8 +120,8 @@ [["lux;NothingT" _]] "Nothing" - [["lux;DataT" [name params]]] - (str "(^ " name " [" (->> params (&/|map show-type) (&/|interpose " ") (&/fold str "")) "])") + [["lux;DataT" name]] + (str "(^ " name ")") [["lux;TupleT" elems]] (if (&/|empty? elems) @@ -166,10 +174,8 @@ [["lux;NothingT" _] ["lux;NothingT" _]] true - [["lux;DataT" [xname xparams]] ["lux;DataT" [yname yparams]]] - (&/fold (fn [old xy] (and old (type= (aget xy 0) (aget xy 1)))) - (= xname yname) - (&/zip2 xparams yparams)) + [["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)))) @@ -261,9 +267,6 @@ [["lux;TupleT" ?members]] (&/V "lux;TupleT" (&/|map (partial beta-reduce env) ?members)) - [["lux;DataT" [?name ?params]]] - (&/V "lux;DataT" (&/T ?name (&/|map (partial beta-reduce env) ?params))) - [["lux;AppT" [?type-fn ?type-arg]]] (&/V "lux;AppT" (&/T (beta-reduce env ?type-fn) (beta-reduce env ?type-arg))) @@ -316,28 +319,40 @@ ;; (prn 'check* (show-type expected) (show-type actual)) (matchv ::M/objects [expected actual] [["lux;AnyT" _] _] - success + (return (&/T fixpoints nil)) [_ ["lux;NothingT" _]] - success - + (return (&/T fixpoints nil)) + + [["lux;VarT" ?eid] ["lux;VarT" ?aid]] + (if (= ?eid ?aid) + (return (&/T fixpoints nil)) + (&/try-all% (&/|list (|do [ebound (deref ?eid)] + (check* fixpoints ebound actual)) + (|do [abound (deref ?aid)] + (check* fixpoints expected abound)) + (|do [_ (set-var ?eid actual)] + (return (&/T fixpoints nil)))))) + [["lux;VarT" ?id] _] - (&/try-all% (&/|list (|do [bound (deref ?id)] - (check* fixpoints bound actual)) - (reset ?id actual))) + (&/try-all% (&/|list (|do [_ (set-var ?id actual)] + (return (&/T fixpoints nil))) + (|do [bound (deref ?id)] + (check* fixpoints bound actual)))) [_ ["lux;VarT" ?id]] - (&/try-all% (&/|list (|do [bound (deref ?id)] - (check* fixpoints expected bound)) - (reset ?id expected))) + (&/try-all% (&/|list (|do [_ (set-var ?id expected)] + (return (&/T fixpoints nil))) + (|do [bound (deref ?id)] + (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)]] (matchv ::M/objects [(fp-get fp-pair fixpoints)] [["lux;Some" ?]] (if ? - success + (return (&/T fixpoints nil)) (fail (check-error expected actual))) [["lux;None" _]] @@ -349,68 +364,72 @@ [["lux;AllT" _] _] (|do [$var fresh-var - expected* (apply-type expected $var)] + expected* (apply-type expected $var)] (check* fixpoints expected* actual)) [_ ["lux;AllT" _]] (|do [$var fresh-var - actual* (apply-type actual $var)] + actual* (apply-type actual $var)] (check* fixpoints expected actual*)) - [["lux;DataT" [e!name e!params]] ["lux;DataT" [a!name a!params]]] - (cond (not= e!name a!name) - (fail (str "[Type Error] Names don't match: " e!name " & " a!name)) - - (not= (&/|length e!params) (&/|length a!params)) - (fail "[Type Error] Params don't match in size.") - - :else - (|do [_ (&/map% (fn [ea] - (|let [[e a] ea] - (check* fixpoints e a))) - (&/zip2 e!params a!params))] - success)) + [["lux;DataT" e!name] ["lux;DataT" a!name]] + (if (= e!name a!name) + (return (&/T fixpoints nil)) + (fail (str "[Type Error] Names don't match: " e!name " & " a!name))) [["lux;LambdaT" [eI eO]] ["lux;LambdaT" [aI aO]]] - (|do [_ (check* fixpoints aI eI)] - (check* fixpoints eO aO)) + (|do [[fixpoints* _] (check* fixpoints aI eI)] + (check* fixpoints* eO aO)) [["lux;TupleT" e!members] ["lux;TupleT" a!members]] - (if (= (&/|length e!members) (&/|length a!members)) - (|do [_ (&/map% (fn [ea] - (|let [[e a] ea] - (do ;; (prn "lux;TupleT" 'ITER (show-type e) (show-type a)) - (check* fixpoints e a)))) - (&/zip2 e!members a!members)) - ;; :let [_ (prn "lux;TupleT" 'DONE)] - ] - success) - (do ;; (prn "lux;TupleT" (&/|length e!members) (&/|length a!members)) - ;; (prn "lux;TupleT" - ;; (&/fold str "" (&/|interpose " " (&/|map show-type e!members))) - ;; (&/fold str "" (&/|interpose " " (&/|map show-type a!members)))) - ;; (prn "lux;TupleT#fail" (fail "[Type Error] Tuples don't match in size.")) - (fail "[Type Error] Tuples don't match in size."))) + (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] + (do ;; (prn "lux;TupleT" 'ITER (show-type e) (show-type a)) + (|do [[fixp* _] (check* fixp e a)] + (return fixp*))))) + fixpoints + (&/zip2 e!members a!members)) + ;; :let [_ (prn "lux;TupleT" 'DONE)] + ] + (return (&/T fixpoints* nil))) + (do ;; (prn "lux;TupleT" (&/|length e!members) (&/|length a!members)) + ;; (prn "lux;TupleT" + ;; (&/fold str "" (&/|interpose " " (&/|map show-type e!members))) + ;; (&/fold str "" (&/|interpose " " (&/|map show-type a!members)))) + ;; (prn "lux;TupleT#fail" (fail "[Type Error] Tuples don't match in size.")) + (fail "[Type Error] Tuples don't match in size.")))) [["lux;VariantT" e!cases] ["lux;VariantT" a!cases]] - (|do [_ (&/map% (fn [kv] - (|let [[k av] kv] - (if-let [ev (&/|get k e!cases)] - (check* fixpoints ev av) - (fail (str "[Type Error] The expected variant cannot handle case: #" k))))) - a!cases)] - success) + (if (= (&/|length e!cases) (&/|length a!cases)) + (|do [fixpoints* (&/fold% (fn [fixp slot] + (prn "lux;VariantT" 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)] + (return fixp*)) + (fail (check-error expected actual))) + (fail (check-error expected actual)))) + fixpoints + (&/|keys e!cases))] + (return (&/T fixpoints* nil))) + (fail "[Type Error] Variants don't match in size.")) [["lux;RecordT" e!fields] ["lux;RecordT" a!fields]] (if (= (&/|length e!fields) (&/|length a!fields)) - (|do [_ (&/map% (fn [slot] - (if-let [e!type (&/|get e!fields slot)] - (if-let [a!type (&/|get a!fields slot)] - (check* fixpoints e!type a!type) - (fail (check-error expected actual))) - (fail (check-error expected actual)))) - (&/|keys e!fields))] - success) + (|do [fixpoints* (&/fold% (fn [fixp slot] + (prn "lux;RecordT" 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)] + (return fixp*)) + (fail (check-error expected actual))) + (fail (check-error expected actual)))) + fixpoints + (&/|keys e!fields))] + (return (&/T fixpoints* nil))) (fail "[Type Error] Records don't match in size.")) [_ _] @@ -426,7 +445,9 @@ ;; ... )) -(def check (partial check* init-fixpoints)) +(defn check [expected actual] + (|do [_ (check* init-fixpoints expected actual)] + (return nil))) (defn apply-lambda [func param] (matchv ::M/objects [func] @@ -436,20 +457,30 @@ [["lux;AllT" [local-env local-name local-arg local-def]]] (|do [$var fresh-var - func* (apply-type func $var)] + func* (apply-type func $var)] (apply-lambda func* param)) [_] (fail (str "[Type System] Can't apply type " (show-type func) " to type " (show-type param))) )) +(defn actual-type [type] + (matchv ::M/objects [type] + [["lux;AppT" [?all ?param]]] + (|do [type* (apply-type ?all ?param)] + (actual-type type*)) + + [_] + (return type) + )) + (def Any (&/V "lux;AnyT" nil)) (def Nothing (&/V "lux;NothingT" nil)) -(def Bool (&/V "lux;DataT" (&/T "java.lang.Boolean" (&/|list)))) -(def Int (&/V "lux;DataT" (&/T "java.lang.Long" (&/|list)))) -(def Real (&/V "lux;DataT" (&/T "java.lang.Double" (&/|list)))) -(def Char (&/V "lux;DataT" (&/T "java.lang.Character" (&/|list)))) -(def Text (&/V "lux;DataT" (&/T "java.lang.String" (&/|list)))) +(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 @@ -460,16 +491,15 @@ (&/V "lux;BoundT" "a"))))))))))) (def Type - (let [Type (&/V "lux;AppT" (&/T (&/V "lux;BoundT" "Type") (&/V "lux;BoundT" ""))) + (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)) - TypeList (&/V "lux;AppT" (&/T List Type)) TypePair (&/V "lux;TupleT" (&/|list Type Type))] - (&/V "lux;AppT" (&/T (&/V "lux;AllT" (&/T (&/|list) "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" (&/V "lux;TupleT" (&/|list Text TypeList))) - (&/T "lux;TupleT" TypeList) + (&/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) @@ -479,94 +509,3 @@ (&/T "lux;AppT" TypePair) )))) (&/V "lux;NothingT" nil))))) - -(let [&& #(and %1 %2)] - (defn merge [x y] - (matchv ::M/objects [x y] - [_ ["lux;AnyT" _]] - (return y) - - [["lux;AnyT" _] _] - (return x) - - [_ ["lux;NothingT" _]] - (return x) - - [["lux;NothingT" _] _] - (return y) - - [["lux;DataT" [xname xparams]] ["lux;DataT" [yname yparams]]] - (if (and (= xname yname) - (= (&/|length xparams) (&/|length yparams))) - (fail (str "[Type System Error] Can't merge types: " (show-type x) " and " (show-type y))) - (|do [xyparams (&/map% (fn [xy] - (|let [[xp yp] xy] - (merge xp yp))) - (&/zip2 xparams yparams))] - (return (&/V "lux;DataT" (&/T xname xyparams))))) - - [["lux;TupleT" xmembers] ["lux;TupleT" ymembers]] - (if (= (&/|length xmembers) (&/|length ymembers)) - (fail (str "[Type System Error] Can't merge types: " (show-type x) " and " (show-type y))) - (|do [xymembers (&/map% (fn [xy] - (|let [[xp yp] xy] - (merge xp yp))) - (&/zip2 xmembers ymembers))] - (return (&/V "lux;TupleT" xymembers)))) - - [["lux;VariantT" x!cases] ["lux;VariantT" y!cases]] - (|do [cases (&/fold% (fn [cases kv] - (matchv ::M/objects [kv] - [[k v]] - (if-let [cv (&/|get k cases)] - (|do [v* (merge cv v)] - (return (&/|put k v* cases))) - (return (&/|put k v cases))))) - x!cases - y!cases)] - (return (&/V "lux;VariantT" cases))) - - [["lux;RecordT" x!fields] ["lux;RecordT" y!fields]] - (if (= (&/|length x!fields) (&/|length y!fields)) - (|do [fields (&/fold% (fn [fields kv] - (matchv ::M/objects [kv] - [[k v]] - (if-let [cv (&/|get k fields)] - (|do [v* (merge cv v)] - (return (&/|put k v* fields))) - (fail (str "[Type System Error] Incompatible records: " (show-type x) " and " (show-type y)))))) - x!fields - y!fields)] - (return (&/V "lux;RecordT" fields))) - (fail (str "[Type System Error] Incompatible records: " (show-type x) " and " (show-type y)))) - - [["lux;LambdaT" [xinput xoutput]] ["lux;LambdaT" [yinput youtput]]] - (|do [xyinput (check xinput yinput) - xyoutput (check xoutput youtput)] - (return (&/V "lux;LambdaT" (&/T xyinput xyoutput)))) - - [_ _] - (fail (str "[Type System Error] Can't merge types: " (show-type x) " and " (show-type y)))))) - -(comment - (do (def Real (&/V "lux;DataT" (&/T "java.lang.Long" (&/|list)))) - (def RealT (&/V "lux;VariantT" (&/|list (&/T "lux;DataT" (&/V "lux;TupleT" (&/|list Text - (&/V "lux;VariantT" (&/|list (&/T "lux;Nil" (&/V "lux;TupleT" (&/|list))))))))))) - ) - - (matchv ::M/objects [((check Type RealT) - (&/init-state nil))] - [["lux;Left" ?msg]] - (assert false ?msg) - - [_] - (println "YEAH!")) - - (matchv ::M/objects [((check List (&/V "lux;AppT" (&/T List Real))) - (&/init-state nil))] - [["lux;Left" ?msg]] - (assert false ?msg) - - [_] - (println "YEAH!")) - ) |