return self.modelbuilder.force_get_primitive_method(current_node, name, recv.mclass, self.mainmodule)
end
- # Is a return executed?
- # Set this mark to skip the evaluation until the end of the specified method frame
- var returnmark: nullable FRAME = null
-
- # Is a break or a continue executed?
+ # Is a return, a break or a continue executed?
# Set this mark to skip the evaluation until a labeled statement catch it with `is_escape`
var escapemark: nullable EscapeMark = null
+ # Is an abort being executed ?
+ # Set this mark to return to the last `catch` bloc or effectively aborting if there isn't any
+ var catch_mark = new EscapeMark
+
+ # The count of `catch` blocs that have been encountered and can catch an abort
+ var catch_count = 0
+
# Is a return or a break or a continue executed?
# Use this function to know if you must skip the evaluation of statements
- fun is_escaping: Bool do return returnmark != null or escapemark != null
+ fun is_escaping: Bool do return escapemark != null
# The value associated with the current return/break/continue, if any.
# Set the value when you set a escapemark.
var f = v.new_frame(self, mpropdef, args)
var res = call_commons(v, mpropdef, args, f)
v.frames.shift
- if v.returnmark == f then
- v.returnmark = null
+ if v.is_escape(self.return_mark) then
res = v.escapevalue
- v.escapevalue = null
return res
end
return res
val = v.expr(nexpr)
else if nblock != null then
v.stmt(nblock)
- assert v.returnmark == f
+ assert v.escapemark == return_mark
val = v.escapevalue
- v.returnmark = null
- v.escapevalue = null
+ v.escapemark = null
else
abort
end
end
end
redef class AAbortExpr
redef fun stmt(v)
do
- fatal(v, "Aborted")
- exit(1)
+ # Abort as asked if there is no `catch` bloc
+ if v.catch_count <= 0 then
+ fatal(v, "Aborted")
+ exit(1)
+ else
+ # Abort mode, skipping everything until a `catch` bloc is reached
+ v.escapemark = v.catch_mark
+ end
end
end
redef class ADoExpr
redef fun stmt(v)
do
+ # If this bloc has a catch, register it in the counter
+ if self.n_catch != null then v.catch_count += 1
v.stmt(self.n_block)
v.is_escape(self.break_mark) # Clear the break (if any)
+ if self.n_catch != null then
+ v.catch_count -= 1
+ # Are we in abort mode? then this catch is executing
+ if v.is_escape(v.catch_mark) then v.stmt(self.n_catch)
+ end
end
end
super TokenKeyword
end
+ # The keyword `catch`
+ class TKwcatch
+ super TokenKeyword
+ end
+
# The keyword `var`
class TKwvar
super TokenKeyword
# A `return` statement. eg `return x`
class AReturnExpr
- super AExpr
+ super AEscapeExpr
# The `return` keyword
var n_kwreturn: nullable TKwreturn = null is writable
-
- # The return value, if any
- var n_expr: nullable AExpr = null is writable
end
# A `yield` statement. eg `yield x`
# The list of statements of the `do`.
var n_block: nullable AExpr = null is writable
+
+ # The `catch` keyword
+ var n_kwcatch: nullable TKwcatch = null is writable
+
+ # The do catch block
+ var n_catch: nullable AExpr = null is writable
end
# A `if` statement
# The tool context used to display errors
var toolcontext: ToolContext
+ # The analysed property
+ var propdef: APropdef
+
var selfvariable = new Variable("self")
init
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
do
self.break_mark = v.make_escape_mark(n_label, false)
v.enter_visit_block(n_block, self.break_mark)
+ v.enter_visit_block(n_catch)
end
end