typing: move iterator methods selection from nitg to typing
authorAlexandre Terrasa <alexadre@moz-code.org>
Tue, 13 Nov 2012 00:57:54 +0000 (19:57 -0500)
committerAlexandre Terrasa <alexadre@moz-code.org>
Tue, 13 Nov 2012 00:57:54 +0000 (19:57 -0500)
Signed-off-by: Alexandre Terrasa <alexadre@moz-code.org>

src/global_compiler.nit
src/typing.nit

index 13932bc..4a30cd0 100644 (file)
@@ -1624,7 +1624,6 @@ redef class AConcreteMethPropdef
                                end
                        end
                end
-
                v.stmt(self.n_block)
        end
 
@@ -2203,21 +2202,31 @@ redef class AForExpr
        redef fun stmt(v)
        do
                var cl = v.expr(self.n_expr, null)
-               var it = v.send(v.get_property("iterator", cl.mtype), [cl])
+               var it_meth = self.method_iterator
+               assert it_meth != null
+               var it = v.send(it_meth, [cl])
                assert it != null
                v.add("for(;;) \{")
-               var ok = v.send(v.get_property("is_ok", it.mtype), [it])
+               var isok_meth = self.method_is_ok
+               assert isok_meth != null
+               var ok = v.send(isok_meth, [it])
                assert ok != null
                v.add("if(!{ok}) break;")
                if self.variables.length == 1 then
-                       var i = v.send(v.get_property("item", it.mtype), [it])
+                       var item_meth = self.method_item
+                       assert item_meth != null
+                       var i = v.send(item_meth, [it])
                        assert i != null
                        v.assign(v.variable(variables.first), i)
                else if self.variables.length == 2 then
-                       var i = v.send(v.get_property("key", it.mtype), [it])
+                       var key_meth = self.method_key
+                       assert key_meth != null
+                       var i = v.send(key_meth, [it])
                        assert i != null
                        v.assign(v.variable(variables[0]), i)
-                       i = v.send(v.get_property("item", it.mtype), [it])
+                       var item_meth = self.method_item
+                       assert item_meth != null
+                       i = v.send(item_meth, [it])
                        assert i != null
                        v.assign(v.variable(variables[1]), i)
                else
@@ -2225,7 +2234,9 @@ redef class AForExpr
                end
                v.stmt(self.n_block)
                v.add("CONTINUE_{v.escapemark_name(escapemark)}: (void)0;")
-               v.send(v.get_property("next", it.mtype), [it])
+               var next_meth = self.method_next
+               assert next_meth != null
+               v.send(next_meth, [it])
                v.add("\}")
                v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;")
        end
index 179597c..ca0c64d 100644 (file)
@@ -724,11 +724,20 @@ end
 redef class AForExpr
        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)
@@ -739,7 +748,7 @@ 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")
@@ -753,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