typing: mark expressions that belong to an array comprehension
authorJean Privat <jean@pryen.org>
Wed, 17 Dec 2014 18:45:58 +0000 (13:45 -0500)
committerJean Privat <jean@pryen.org>
Wed, 17 Dec 2014 20:29:28 +0000 (15:29 -0500)
Signed-off-by: Jean Privat <jean@pryen.org>

src/semantize/typing.nit

index accfe11..1dfaec6 100644 (file)
@@ -633,6 +633,12 @@ redef class AExpr
        do
                v.error(self, "no implemented accept_typing for {self.class_name}")
        end
+
+       # Is non-null if `self` is a leaf of a comprehension array construction.
+       # In this case, the enclosing literal array node is designated.
+       # The result of the evaluation of `self` must be
+       # stored inside the designated array (there is an implicit `push`)
+       var comprehension: nullable AArrayExpr = null
 end
 
 redef class ABlockExpr
@@ -857,7 +863,12 @@ redef class AIfExpr
 
                v.visit_stmt(n_then)
                v.visit_stmt(n_else)
+
                self.is_typed = true
+
+               if n_then != null and n_else == null then
+                       self.mtype = n_then.mtype
+               end
        end
 end
 
@@ -1043,6 +1054,7 @@ redef class AForExpr
                self.do_type_iterator(v, mtype)
 
                v.visit_stmt(n_block)
+               self.mtype = n_block.mtype
                self.is_typed = true
        end
 end
@@ -1189,6 +1201,22 @@ redef class AArrayExpr
        # The element of each type
        var element_mtype: nullable MType
 
+       # Set that `self` is a part of comprehension array `na`
+       # If `self` is a `for`, or a `if`, then `set_comprehension` is recursively applied.
+       private fun set_comprehension(n: nullable AExpr)
+       do
+               if n == null then
+                       return
+               else if n isa AForExpr then
+                       set_comprehension(n.n_block)
+               else if n isa AIfExpr then
+                       set_comprehension(n.n_then)
+                       set_comprehension(n.n_else)
+               else
+                       # is a leave
+                       n.comprehension = self
+               end
+       end
        redef fun accept_typing(v)
        do
                var mtype: nullable MType = null
@@ -1204,6 +1232,7 @@ redef class AArrayExpr
                        if t == null then
                                return # Skip error
                        end
+                       set_comprehension(e)
                        if mtype != null then
                                if v.check_subtype(e, t, mtype) == null then return # Skip error
                                if t == mtype then useless = true