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
# 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
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.
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
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
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
# 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
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]
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