X-Git-Url: http://nitlanguage.org diff --git a/src/interpreter/naive_interpreter.nit b/src/interpreter/naive_interpreter.nit index 9236d99..539fb89 100644 --- a/src/interpreter/naive_interpreter.nit +++ b/src/interpreter/naive_interpreter.nit @@ -113,17 +113,16 @@ class NaiveInterpreter 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 + # 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. @@ -848,10 +847,8 @@ redef class AMethPropdef 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 @@ -1517,7 +1514,7 @@ redef class AAttrPropdef # Evaluate and set the default value of the attribute in `recv` private fun init_expr(v: NaiveInterpreter, recv: Instance) do - if is_lazy then return + if is_lazy or is_optional then return if has_value then var f = v.new_frame(self, mreadpropdef.as(not null), [recv]) evaluate_expr(v, recv, f) @@ -1545,10 +1542,9 @@ redef class AAttrPropdef 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 @@ -1693,24 +1689,16 @@ redef class AEscapeExpr end end -redef class AReturnExpr - redef fun stmt(v) - do - var ne = self.n_expr - if ne != null then - var i = v.expr(ne) - if i == null then return - v.escapevalue = i - end - v.returnmark = v.frame - 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 + end end end @@ -1754,8 +1742,24 @@ end redef class ADoExpr redef fun stmt(v) do - v.stmt(self.n_block) - v.is_escape(self.break_mark) # Clear the break (if any) + # If this bloc has a catch, handle it with a do ... catch ... end + if self.n_catch != null then + var frame = v.frame + v.catch_count += 1 + do + v.stmt(self.n_block) + v.is_escape(self.break_mark) # Clear the break (if any) + v.catch_count -= 1 + catch + # Restore the current frame if needed + while v.frame != frame do v.frames.shift + v.catch_count -= 1 + v.stmt(self.n_catch) + end + else + v.stmt(self.n_block) + v.is_escape(self.break_mark) + end end end