typing: change abort to assert in ASendExpr
[nit.git] / src / typing.nit
index 6bb4898..1f97347 100644 (file)
@@ -722,17 +722,25 @@ redef class ALoopExpr
 end
 
 redef class AForExpr
-       var coltype: nullable MGenericType
+       var coltype: nullable MClassType
+
+       var method_iterator: nullable MMethod
+       var method_is_ok: nullable MMethod
+       var method_item: nullable MMethod
+       var method_next: nullable MMethod
+       var method_key: nullable MMethod
 
        private fun do_type_iterator(v: TypeVisitor, mtype: MType)
        do
                var objcla = v.get_mclass(self, "Object")
                if objcla == null then return
 
+               var is_col = false
+               var is_map = false
+
                var colcla = v.try_get_mclass(self, "Collection")
                if colcla != null and v.is_subtype(mtype, colcla.get_mtype([objcla.mclass_type.as_nullable])) then
                        var coltype = mtype.supertype_to(v.mmodule, v.anchor, colcla)
-                       assert coltype isa MGenericType
                        self.coltype = coltype
                        var variables =  self.variables
                        if variables.length != 1 then
@@ -740,13 +748,12 @@ redef class AForExpr
                        else
                                variables.first.declared_type = coltype.arguments.first
                        end
-                       return
+                       is_col = true
                end
 
                var mapcla = v.try_get_mclass(self, "Map")
                if mapcla != null and v.is_subtype(mtype, mapcla.get_mtype([objcla.mclass_type.as_nullable, objcla.mclass_type.as_nullable])) then
                        var coltype = mtype.supertype_to(v.mmodule, v.anchor, mapcla)
-                       assert coltype isa MGenericType
                        self.coltype = coltype
                        var variables = self.variables
                        if variables.length != 2 then
@@ -755,6 +762,57 @@ redef class AForExpr
                                variables[0].declared_type = coltype.arguments[0]
                                variables[1].declared_type = coltype.arguments[1]
                        end
+                       is_map = true
+               end
+
+               if is_col or is_map then
+                       # get iterator method
+                       var coltype = self.coltype.as(not null)
+                       var itdef = v.get_method(self, coltype, "iterator", true)
+                       var itdefsign = itdef.msignature
+                       if itdef == null or itdefsign == null then
+                               v.error(self, "Type Error: Expected method 'iterator' in type {coltype}")
+                               return
+                       end
+                       self.method_iterator = itdef.mproperty
+
+                       # get iterator type
+                       var ittype = v.resolve_signature_for(itdefsign, mtype, false).return_mtype
+                       if ittype == null then
+                               v.error(self, "Type Error: Expected method 'iterator' to return an Iterator type")
+                               return
+                       end
+
+                       # get methods is_ok, next, item
+                       var ikdef = v.get_method(self, ittype, "is_ok", false)
+                       if ikdef == null then
+                               v.error(self, "Type Error: Expected method 'is_ok' in Iterator type {ittype}")
+                               return
+                       end
+                       self.method_is_ok = ikdef.mproperty
+
+                       var itemdef = v.get_method(self, ittype, "item", false)
+                       if itemdef == null then
+                               v.error(self, "Type Error: Expected method 'item' in Iterator type {ittype}")
+                               return
+                       end
+                       self.method_item = itemdef.mproperty
+
+                       var nextdef = v.get_method(self, ittype, "next", false)
+                       if nextdef == null then
+                               v.error(self, "Type Error: Expected method 'next' in Iterator type {ittype}")
+                               return
+                       end
+                       self.method_next = nextdef.mproperty
+
+                       if is_map then
+                               var keydef = v.get_method(self, ittype, "key", false)
+                               if keydef == null then
+                                       v.error(self, "Type Error: Expected method 'key' in Iterator type {ittype}")
+                                       return
+                               end
+                               self.method_key = keydef.mproperty
+                       end
                        return
                end
 
@@ -928,8 +986,11 @@ end
 redef class ARangeExpr
        redef fun accept_typing(v)
        do
-               var t1 = v.visit_expr(self.n_expr)
-               var t2 = v.visit_expr(self.n_expr2)
+               var discrete_class = v.get_mclass(self, "Discrete")
+               if discrete_class == null then return # Forward error
+               var discrete_type = discrete_class.mclassdefs.first.bound_mtype
+               var t1 = v.visit_expr_subtype(self.n_expr, discrete_type)
+               var t2 = v.visit_expr_subtype(self.n_expr2, discrete_type)
                if t1 == null or t2 == null then return
                var mclass = v.get_mclass(self, "Range")
                if mclass == null then return # Forward error
@@ -1035,7 +1096,7 @@ redef class ASendExpr
                var mproperty = propdef.mproperty
                self.mproperty = mproperty
                var msignature = propdef.msignature
-               if msignature == null then abort # Forward error
+               assert msignature != null # msignature should never be null here
 
                var for_self = self.n_expr isa ASelfExpr
                msignature = v.resolve_signature_for(msignature, recvtype, for_self)