diff --git a/libinterp/parse-tree/pt-arg-list.cc b/libinterp/parse-tree/pt-arg-list.cc --- a/libinterp/parse-tree/pt-arg-list.cc +++ b/libinterp/parse-tree/pt-arg-list.cc @@ -252,7 +252,12 @@ namespace octave if (tmp.is_cs_list ()) args.push_back (tmp.list_value ()); else if (tmp.is_defined ()) - args.push_back (tmp); + { + args.push_back (tmp); + + // if (tmp.is_handle_object ()) + tw->defer_deletion (tmp); + } } else { diff --git a/libinterp/parse-tree/pt-eval.cc b/libinterp/parse-tree/pt-eval.cc --- a/libinterp/parse-tree/pt-eval.cc +++ b/libinterp/parse-tree/pt-eval.cc @@ -81,6 +81,7 @@ namespace octave m_result_type = RT_UNDEFINED; m_expr_result_value = octave_value (); m_expr_result_value_list = octave_value_list (); + m_deferred_delete_stack.clear (); m_lvalue_list_stack.clear (); m_nargout_stack.clear (); } @@ -2270,6 +2271,13 @@ namespace octave cmd->accept (*this); else { + unwind_protect frame; + + frame.add_method (m_deferred_delete_stack, + &deferred_delete_stack::pop_frame); + + m_deferred_delete_stack.mark (); + if (m_echo_state) { size_t line = stmt.line (); diff --git a/libinterp/parse-tree/pt-eval.h b/libinterp/parse-tree/pt-eval.h --- a/libinterp/parse-tree/pt-eval.h +++ b/libinterp/parse-tree/pt-eval.h @@ -67,6 +67,54 @@ namespace octave ECHO_ALL = 4 }; + class deferred_delete_stack + { + public: + + deferred_delete_stack (void) = default; + + deferred_delete_stack (const deferred_delete_stack&) = default; + + deferred_delete_stack& operator = (const deferred_delete_stack&) = default; + + ~deferred_delete_stack (void) = default; + + // An undefined value on the stack marks the boundary of the + // current frame. + + void mark (void) { push (octave_value ()); } + + void push (const octave_value& val) { m_stack.push (val); } + + void pop_frame (void) + { + while (! m_stack.empty ()) + { + octave_value val = val_pop (); + + if (val.is_undefined ()) + break; + } + } + + void clear (void) + { + while (! m_stack.empty ()) + m_stack.pop (); + } + + private: + + std::stack m_stack; + + octave_value val_pop (void) + { + octave_value retval = m_stack.top (); + m_stack.pop (); + return retval; + } + }; + template class value_stack { @@ -125,8 +173,8 @@ namespace octave tree_evaluator (interpreter& interp) : m_interpreter (interp), m_result_type (RT_UNDEFINED), m_expr_result_value (), m_expr_result_value_list (), - m_lvalue_list_stack (), m_nargout_stack (), - m_call_stack (interp), m_profiler (), + m_deferred_delete_stack (), m_lvalue_list_stack (), + m_nargout_stack (), m_call_stack (interp), m_profiler (), m_max_recursion_depth (256), m_silent_functions (false), m_string_fill_char (' '), m_PS4 ("+ "), m_echo (ECHO_OFF), m_echo_state (false), m_echo_file_name (), m_echo_file_pos (1), @@ -267,6 +315,11 @@ namespace octave // TRUE means we are evaluating some kind of looping construct. static bool in_loop_command; + void defer_deletion (const octave_value& val) + { + m_deferred_delete_stack.push (val); + } + Matrix ignored_fcn_outputs (void) const; bool isargout (int nargout, int iout) const; @@ -487,6 +540,8 @@ namespace octave octave_value m_expr_result_value; octave_value_list m_expr_result_value_list; + deferred_delete_stack m_deferred_delete_stack; + value_stack*> m_lvalue_list_stack; value_stack m_nargout_stack;