nitc/niti: unify returnmark and escapemark
[nit.git] / src / interpreter / naive_interpreter.nit
index d417d9e..7fc2355 100644 (file)
@@ -113,17 +113,13 @@ 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
 
        # 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 +844,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
@@ -1012,9 +1006,6 @@ redef class AMethPropdef
                                return v.int32_instance(recvval.to_i32)
                        else if pname == "to_u32" then
                                return v.uint32_instance(recvval.to_u32)
-                       else if pname == "rand" then
-                               var res = recvval.rand
-                               return v.int_instance(res)
                        end
                else if cname == "Byte" then
                        var recvval = args[0].to_b
@@ -1140,8 +1131,6 @@ redef class AMethPropdef
                                return v.float_instance(args[0].to_f.log)
                        else if pname == "pow" then
                                return v.float_instance(args[0].to_f.pow(args[1].to_f))
-                       else if pname == "rand" then
-                               return v.float_instance(args[0].to_f.rand)
                        else if pname == "abs" then
                                return v.float_instance(args[0].to_f.abs)
                        else if pname == "hypot_with" then
@@ -1550,10 +1539,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
@@ -1698,19 +1686,6 @@ 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
@@ -1848,7 +1823,13 @@ redef class AWithExpr
                v.callsite(method_start, [expr])
                v.stmt(self.n_block)
                v.is_escape(self.break_mark) # Clear the break
+
+               # Execute the finally without an escape
+               var old_mark = v.escapemark
+               v.escapemark = null
                v.callsite(method_finish, [expr])
+               # Restore the escape unless another escape was provided
+               if v.escapemark == null then v.escapemark = old_mark
        end
 end