aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduardo Julian2015-12-06 19:10:38 -0400
committerEduardo Julian2015-12-06 19:10:38 -0400
commit31b986e80335bf262997b97e3d22486a7b91cc4b (patch)
treef4f66249fa51a3b859fcea67f546291fed6d8022
parent2c392029d19aee4962f3b37b4f10eb79f7c01e3f (diff)
- Better handling generics when analysing class methods.
-rw-r--r--src/lux/analyser/host.clj25
1 files changed, 16 insertions, 9 deletions
diff --git a/src/lux/analyser/host.clj b/src/lux/analyser/host.clj
index b4d862be2..a119ba981 100644
--- a/src/lux/analyser/host.clj
+++ b/src/lux/analyser/host.clj
@@ -496,11 +496,13 @@
"[Ljava.lang.Object;")
))
-(defn generic-class->type [gclass]
- "(-> GenericClass (Lux Type))"
+(defn generic-class->type [env gclass]
+ "(-> (List (, TypeVar Type)) GenericClass (Lux Type))"
(|case gclass
(&/$GenericTypeVar var-name)
- (return (&type/Data$ "java.lang.Object" &/Nil$))
+ (if-let [ex (&/|get var-name env)]
+ (return ex)
+ (fail (str "[Analysis Error] Unknown type var: " var-name)))
(&/$GenericClass name params)
(case name
@@ -514,23 +516,28 @@
"char" (return (&type/Data$ "java.lang.Character" (&/|list)))
"void" (return &type/Unit)
;; else
- (|do [=params (&/map% generic-class->type params)]
+ (|do [=params (&/map% (partial generic-class->type env) params)]
(return (&type/Data$ name =params))))
(&/$GenericArray param)
- (|do [=param (generic-class->type param)]
+ (|do [=param (generic-class->type env param)]
(return (&type/Data$ &host-type/array-data-tag (&/|list =param))))
))
(defn ^:private analyse-method [analyse class-decl method]
(|do [:let [[?cname ?cparams] class-decl
- class-type (&type/Data$ ?cname &/Nil$)
+ class-type (&/V &/$GenericClass (&/T ?cname &/Nil$))
[?decl ?body] method
- [_ _ _ _ _ ?inputs ?output] ?decl]
- output-type (generic-class->type ?output)
+ [_ _ _ ?gvars ?exs ?inputs ?output] ?decl
+ all-gvars (&/|++ ?cparams ?gvars)]
+ gvar-env (&/map% (fn [gvar]
+ (|do [ex &type/existential]
+ (return (&/T gvar ex))))
+ all-gvars)
+ output-type (generic-class->type gvar-env ?output)
=body (&/fold (fn [body* input*]
(|do [:let [[iname itype*] input*]
- itype (generic-class->type itype*)]
+ itype (generic-class->type gvar-env itype*)]
(&&env/with-local iname itype
body*)))
(&&/analyse-1 analyse output-type ?body)