module scope
import phase
+import modelbuilder
redef class ToolContext
# Run `APropdef::do_scope` on each propdef.
# A local variable (including parameters, automatic variables and self)
class Variable
# The name of the variable (as used in the program)
- var name: String
+ var name: String is writable
# Alias of `name`
redef fun to_s do return self.name
# The declaration of the variable, if any
- var location: nullable Location = null
+ var location: nullable Location = null is writable
# Is the local variable not read and need a warning?
var warn_unread = false is writable
# The tool context used to display errors
var toolcontext: ToolContext
+ # The analysed property
+ var propdef: APropdef
+
var selfvariable = new Variable("self")
init
var res = search_label("")
if res == null then
self.error(nlabel, "Syntax Error: invalid anonymous label.")
+ node.is_broken = true
return null
end
return res
var res = search_label(name)
if res == null then
self.error(nlabel, "Syntax Error: invalid label `{name}`.")
+ node.is_broken = true
return null
end
return res
fun error(node: ANode, message: String)
do
self.toolcontext.error(node.hot_location, message)
+ node.is_broken = true
end
end
end
redef class APropdef
+ # The break escape mark associated with the return
+ var return_mark: nullable EscapeMark
+
# Entry point of the scope analysis
fun do_scope(toolcontext: ToolContext)
do
- var v = new ScopeVisitor(toolcontext)
+ var v = new ScopeVisitor(toolcontext, self)
v.enter_visit(self)
v.shift_scope
end
end
end
+redef class AReturnExpr
+ redef fun accept_scope_visitor(v)
+ do
+ super
+
+ var escapemark = v.propdef.return_mark
+ if escapemark == null then
+ escapemark = new EscapeMark
+ v.propdef.return_mark = escapemark
+ end
+
+ escapemark.escapes.add(self)
+ self.escapemark = escapemark
+ end
+end
redef class ADoExpr
# The break escape mark associated with the 'do' block
end
redef class AForExpr
- # The automatic variables in order
- var variables: nullable Array[Variable]
-
# The break escape mark associated with the 'for'
var break_mark: nullable EscapeMark
redef fun accept_scope_visitor(v)
do
- v.enter_visit(n_expr)
+ for g in n_groups do
+ v.enter_visit(g.n_expr)
+ end
# Protect automatic variables
v.scopes.unshift(new Scope)
- # Create the automatic variables
- var variables = new Array[Variable]
- self.variables = variables
- for nid in n_ids do
- var va = new Variable(nid.text)
- v.register_variable(nid, va)
- variables.add(va)
+ for g in n_groups do
+ # Create the automatic variables
+ var variables = new Array[Variable]
+ g.variables = variables
+ for nid in g.n_ids do
+ var va = new Variable(nid.text)
+ v.register_variable(nid, va)
+ variables.add(va)
+ end
end
var escapemark = v.make_escape_mark(n_label, true)
end
end
+redef class AForGroup
+ # The automatic variables in order
+ var variables: nullable Array[Variable]
+end
+
redef class AWithExpr
# The break escape mark associated with the 'with'
var break_mark: nullable EscapeMark
redef class AVarFormExpr
# The associated variable
- var variable: nullable Variable
+ var variable: nullable Variable is writable
end
redef class ACallFormExpr
redef fun accept_scope_visitor(v)
do
if n_expr isa AImplicitSelfExpr then
- var name = n_id.text
+ var name = n_qid.n_id.text
var variable = v.search_variable(name)
if variable != null then
var n: AExpr
redef fun variable_create(variable)
do
variable.warn_unread = false
- return new AVarExpr.init_avarexpr(n_id)
+ return new AVarExpr.init_avarexpr(n_qid.n_id)
end
end
redef class ACallAssignExpr
redef fun variable_create(variable)
do
- return new AVarAssignExpr.init_avarassignexpr(n_id, n_assign, n_value)
+ return new AVarAssignExpr.init_avarassignexpr(n_qid.n_id, n_assign, n_value)
end
end
redef fun variable_create(variable)
do
variable.warn_unread = false
- return new AVarReassignExpr.init_avarreassignexpr(n_id, n_assign_op, n_value)
+ return new AVarReassignExpr.init_avarreassignexpr(n_qid.n_id, n_assign_op, n_value)
end
end