tool: new program nitunit.nit
[nit.git] / src / scope.nit
index 95e4d4a..2805556 100644 (file)
@@ -19,13 +19,26 @@ module scope
 
 import parser
 import toolcontext
+import phase
+
+import modelbuilder #FIXME useless
+
+redef class ToolContext
+       var scope_phase: Phase = new ScopePhase(self, null)
+end
+
+private class ScopePhase
+       super Phase
+       redef fun process_npropdef(npropdef) do npropdef.do_scope(toolcontext)
+end
+
 
 # A local variable (including parameters, automatic variables and self)
 class Variable
        # The name of the variable (as used in the program)
        var name: String
 
-       # Alias of `name'
+       # Alias of `name`
        redef fun to_s do return self.name
 end
 
@@ -54,8 +67,8 @@ end
 # Visit a npropdef and:
 #  * Identify variables, closures and labels
 #  * Associate each break and continue to its escapemark
-#  * Transform ACallFormExpr that access a variable into AVarFormExpr
-#  * Transform ACallFormExpr that call a closure into AClosureCallExpr
+#  * Transform `ACallFormExpr` that access a variable into `AVarFormExpr`
+#  * Transform `ACallFormExpr` that call a closure into `AClosureCallExpr`
 # FIXME: Should the class be private?
 private class ScopeVisitor
        super Visitor
@@ -71,7 +84,7 @@ private class ScopeVisitor
                scopes.add(new Scope)
        end
 
-       # All stacked scope. `scopes.first' is the current scope
+       # All stacked scope. `scopes.first` is the current scope
        private var scopes: List[Scope] = new List[Scope]
 
        # Regiter a local variable.
@@ -88,7 +101,7 @@ private class ScopeVisitor
                return true
        end
 
-       # Look for a variable named `name'.
+       # Look for a variable named `name`.
        # Return null if no such a variable is found.
        fun search_variable(name: String): nullable Variable
        do
@@ -101,13 +114,13 @@ private class ScopeVisitor
                return null
        end
 
-       redef fun visit(n: nullable ANode)
+       redef fun visit(n)
        do
                n.accept_scope_visitor(self)
        end
 
-       # Enter in a statement block `node' as inside a new scope.
-       # The block can be optionally attached to an `escapemark'.
+       # Enter in a statement block `node` as inside a new scope.
+       # The block can be optionally attached to an `escapemark`.
        private fun enter_visit_block(node: nullable AExpr, escapemark: nullable EscapeMark)
        do
                if node == null then return
@@ -118,7 +131,7 @@ private class ScopeVisitor
                scopes.shift
        end
 
-       # Look for a label `name'.
+       # Look for a label `name`.
        # Return nulll if no such a label is found.
        private fun search_label(name: String): nullable EscapeMark
        do
@@ -152,7 +165,7 @@ private class ScopeVisitor
 
        # Look for an escape mark optionally associated with a label.
        # If a label is given, the the escapemark of this label is returned.
-       # If there is no label, the nearest escapemark that is `for loop' ir returned.
+       # If there is no label, the nearest escapemark that is `for loop` is returned.
        # If there is no valid escapemark, then an error is displayed ans null is returned.
        # Return nulll if no such a label is found.
        private fun get_escapemark(node: ANode, nlabel: nullable ALabel): nullable EscapeMark
@@ -431,6 +444,20 @@ redef class AClosureCallExpr
        var variable: nullable ClosureVariable
 end
 
+redef class ASendExpr
+       # The escape mark used with the closures if any
+       var escapemark: nullable EscapeMark
+
+       redef fun accept_scope_visitor(v)
+       do
+               if self.n_closure_defs.length > 0 then
+                       var escapemark = v.make_escape_mark(self.n_closure_defs.last.n_label, true)
+                       self.escapemark = escapemark
+               end
+               super
+       end
+end
+
 redef class AClosureDef
        # The automatic variables in order
        var variables: nullable Array[Variable]
@@ -451,8 +478,7 @@ redef class AClosureDef
                        variables.add(va)
                end
 
-               var escapemark = v.make_escape_mark(n_label, true)
-               self.escapemark = escapemark
+               self.escapemark = self.parent.as(ASendExpr).escapemark
                v.enter_visit_block(self.n_expr, escapemark)
 
                v.scopes.shift