model: add for on maps
authorJean Privat <jean@pryen.org>
Thu, 24 May 2012 14:02:16 +0000 (10:02 -0400)
committerJean Privat <jean@pryen.org>
Mon, 2 Jul 2012 20:36:36 +0000 (16:36 -0400)
workaround implementation waiting for closures.

Signed-off-by: Jean Privat <jean@pryen.org>

src/global_compiler.nit
src/naive_interpreter.nit
src/rapid_type_analysis.nit
src/typing.nit

index 9b5dbb6..d001cfe 100644 (file)
@@ -1939,9 +1939,20 @@ redef class AForExpr
                var ok = v.send(v.get_property("is_ok", it.mtype), [it])
                assert ok != null
                v.add("if(!{ok}) break;")
-               var i = v.send(v.get_property("item", it.mtype), [it])
-               assert i != null
-               v.assign(v.variable(variables.first), i)
+               if self.variables.length == 1 then
+                       var i = v.send(v.get_property("item", it.mtype), [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])
+                       assert i != null
+                       v.assign(v.variable(variables[0]), i)
+                       i = v.send(v.get_property("item", it.mtype), [it])
+                       assert i != null
+                       v.assign(v.variable(variables[1]), i)
+               else
+                       abort
+               end
                v.stmt(self.n_block)
                v.add("CONTINUE_{escapemark.object_id}: (void)0;")
                v.send(v.get_property("next", it.mtype), [it])
index 03df69f..e1cd4ae 100644 (file)
@@ -1015,9 +1015,18 @@ redef class AForExpr
                loop
                        var isok = v.send(v.mainmodule.force_get_primitive_method("is_ok", iter.mtype), [iter]).as(not null)
                        if not isok.is_true then return
-                       var item = v.send(v.mainmodule.force_get_primitive_method("item", iter.mtype), [iter]).as(not null)
-                       #self.debug("item {item}")
-                       v.frame.map[self.variables.first] = item
+                       if self.variables.length == 1 then
+                               var item = v.send(v.mainmodule.force_get_primitive_method("item", iter.mtype), [iter]).as(not null)
+                               #self.debug("item {item}")
+                               v.frame.map[self.variables.first] = item
+                       else if self.variables.length == 2 then
+                               var key = v.send(v.mainmodule.force_get_primitive_method("key", iter.mtype), [iter]).as(not null)
+                               v.frame.map[self.variables[0]] = key
+                               var item = v.send(v.mainmodule.force_get_primitive_method("item", iter.mtype), [iter]).as(not null)
+                               v.frame.map[self.variables[1]] = item
+                       else
+                               abort
+                       end
                        v.stmt(self.n_block)
                        if v.is_break(self.escapemark) then return
                        v.is_continue(self.escapemark) # Clear the break
index 69be178..d1fbbed 100644 (file)
@@ -569,12 +569,20 @@ redef class AForExpr
        redef fun accept_rapid_type_vistor(v)
        do
                var recvtype = self.n_expr.mtype.as(not null)
-               var colltype = v.get_class("Collection").mclassdefs.first.bound_mtype
-               v.add_send(recvtype, v.get_method(colltype, "iterator"))
-               var iteratortype = v.get_class("Iterator").mclassdefs.first.bound_mtype
+               var colltype = self.coltype.as(not null)
+               var itmeth = v.get_method(colltype, "iterator")
+               v.add_send(recvtype, itmeth)
+               var iteratortype = itmeth.intro.msignature.return_mtype.as(MClassType).mclass.mclassdefs.first.bound_mtype
                var objtype = v.get_class("Object").mclass_type
                v.add_send(objtype, v.get_method(iteratortype, "is_ok"))
-               v.add_send(objtype, v.get_method(iteratortype, "item"))
+               if self.variables.length == 1 then
+                       v.add_send(objtype, v.get_method(iteratortype, "item"))
+               else if self.variables.length == 2 then
+                       v.add_send(objtype, v.get_method(iteratortype, "key"))
+                       v.add_send(objtype, v.get_method(iteratortype, "item"))
+               else
+                       abort
+               end
                v.add_send(objtype, v.get_method(iteratortype, "next"))
        end
 end
index 64f33f2..8a36223 100644 (file)
@@ -704,6 +704,7 @@ redef class ALoopExpr
 end
 
 redef class AForExpr
+       var coltype: nullable MGenericType
        redef fun accept_typing(v)
        do
                var mtype = v.visit_expr(n_expr)
@@ -713,15 +714,29 @@ redef class AForExpr
                if colcla == null then return
                var objcla = v.get_mclass(self, "Object")
                if objcla == null then return
+               var mapcla = v.get_mclass(self, "Map")
+               if mapcla == null then return
                if 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
                                v.error(self, "Type Error: Expected one variable")
                        else
                                variables.first.declared_type = coltype.arguments.first
                        end
+               else if 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
+                               v.error(self, "Type Error: Expected two variables")
+                       else
+                               variables[0].declared_type = coltype.arguments[0]
+                               variables[1].declared_type = coltype.arguments[1]
+                       end
                else
                        v.modelbuilder.error(self, "TODO: Do 'for' on {mtype}")
                end