comparison libinterp/parse-tree/pt-eval.cc @ 20744:b70cc4bd8109

begin removal of global error_state variable * gripes.h, gripes.cc (gripe_library_execution_error): Delete. * error.cc (warning_state): Delete unused variable. (reset_error_handler): Don't set warning_state or error_state. (debug_or_throw_exception): New static function. (verror): Don't check error_state. (vmessage): Call debug_or_throw_exception instead of setting error_state. (error_1, error_2): Combine into single function, error_1 that prints error message and ultimately calls debug_or_throw_exception. (verror, verror_with_cfn, verror_with_id_cfn): Call error_1. Don't check or set warning_state. (error): Don't check error_state. (Flasterror, Flasterr): Adapt to not using error_state. (interpreter_try): Don't unwind_protect error_state. * NEWS: Update. * doc/interpreter/external.txi: Explain octave_execution_exception instead of error_state for matrix addition example. * jit-typeinfo.cc (octave_jit_gripe_nan_to_logical_conversion, octave_jit_ginvalid_index, octave_jit_gindex_range, octave_jit_paren_scalar, octave_jit_paren_scalar_subsasgn): Don't catch octave_execution_exception. * cellfun.cc (Fcellfun): Use exceptions instead of error_state. * ls-mat-ascii.cc (save_mat_ascii_data): Likewise. * mex.cc (mexCallMATLAB, mexEvalString): Likewise. * variables.cc (safe_symbol_lookup): Likewise. * svd.cc (Fsvd): Eliminate use of error_state. * __magick_read__.cc (read_file, write_file): Likewise. * variables.cc (generate_struct_completions): Eliminate use of obsolete warning_state variable. * ov-builtin.cc (octave_builtin::do_multi_index_op): Don't catch octave_execution_exception and call gripe_library_execution_error. * ov-class.cc (octave_class::reconstruct_exemplar): Eliminate use of error_state. Catch possible octave_execution_exception in do_multi_index_op. * ov-mex-fcn.cc (octave_mex_function::do_multi_index_op): Eliminate use of error_state. Catch possible octave_execution_exception in call_mex. * ov-fcn-handle.cc (octave_fcn_binder::maybe_binder): Eliminate use of error_state. * ov-oncleanup.cc (octave_oncleanup::~octave_oncleanup): Eliminate use of error_state. Propagate possible octave_execution_exception from do_multi_index_op. * ov.cc (octave_value::assign, do_binary_op, do_unary_op, octave_value::do_non_const_unary_op): Don't catch octave_execution_exception here. * oct-parse.in.yy (octave_base_parser::finish_colon_expression, octave_base_parser::finish_array_list): Eliminate use of warning_state and error_state. (Feval, Fevalin): Use exceptions instead of error_state. * pt-eval.cc, pt-eval.h (tree_evaluator::unwind_protect_exception): New static variable. * (tree_evaluator::visit_statement): Don't catch octave_execution_exception here. (tree_evaluator::visit_try_catch_command, tree_evaluator::do_unwind_protect_cleanup): Eliminate use of error_state. (tree_evaluator::visit_unwind_protect_command): Use unwind_protect_exception to track whether an exception has occurred in the try block.
author John W. Eaton <jwe@octave.org>
date Thu, 01 Oct 2015 16:18:19 -0400
parents 7ac907da9fba
children 56fee8f84fe7
comparison
equal deleted inserted replaced
20743:fcb792acab9b 20744:b70cc4bd8109
56 size_t tree_evaluator::current_frame = 0; 56 size_t tree_evaluator::current_frame = 0;
57 57
58 bool tree_evaluator::debug_mode = false; 58 bool tree_evaluator::debug_mode = false;
59 59
60 bool tree_evaluator::quiet_breakpoint_flag = false; 60 bool tree_evaluator::quiet_breakpoint_flag = false;
61
62 bool tree_evaluator::unwind_protect_exception = false;
61 63
62 tree_evaluator::stmt_list_type tree_evaluator::statement_context 64 tree_evaluator::stmt_list_type tree_evaluator::statement_context
63 = tree_evaluator::other; 65 = tree_evaluator::other;
64 66
65 bool tree_evaluator::in_loop_command = false; 67 bool tree_evaluator::in_loop_command = false;
749 751
750 // if (tmp_result.is_defined ()) 752 // if (tmp_result.is_defined ())
751 // result_values(0) = tmp_result; 753 // result_values(0) = tmp_result;
752 } 754 }
753 } 755 }
754 catch (octave_execution_exception) 756 catch (const std::bad_alloc&)
755 {
756 gripe_library_execution_error ();
757 }
758 catch (std::bad_alloc)
759 { 757 {
760 // FIXME: We want to use error_with_id here so that we set 758 // FIXME: We want to use error_with_id here so that we set
761 // the error state, give users control over this error 759 // the error state, give users control over this error
762 // message, and so that we set the error_state appropriately 760 // message, and so that we set the error_state appropriately
763 // so we'll get stack trace info when appropriate. But 761 // so we'll get stack trace info when appropriate. But
900 // The catch code is *not* added to unwind_protect stack; it doesn't need 898 // The catch code is *not* added to unwind_protect stack; it doesn't need
901 // to be run on interrupts. 899 // to be run on interrupts.
902 900
903 tree_statement_list *try_code = cmd.body (); 901 tree_statement_list *try_code = cmd.body ();
904 902
903 bool execution_error = false;
904
905 if (try_code) 905 if (try_code)
906 { 906 {
907 try_code->accept (*this); 907 try
908 } 908 {
909 909 try_code->accept (*this);
910 if (error_state) 910 }
911 { 911 catch (const octave_execution_exception&)
912 error_state = 0; 912 {
913 913 execution_error = true;
914 }
915 }
916
917 if (execution_error)
918 {
914 if (catch_code) 919 if (catch_code)
915 { 920 {
916 // Set up for letting the user print any messages from errors that 921 // Set up for letting the user print any messages from errors that
917 // occurred in the body of the try_catch statement. 922 // occurred in the body of the try_catch statement.
918 923
921 tree_identifier *expr_id = cmd.identifier (); 926 tree_identifier *expr_id = cmd.identifier ();
922 octave_lvalue ult; 927 octave_lvalue ult;
923 928
924 if (expr_id) 929 if (expr_id)
925 { 930 {
931 ult = expr_id->lvalue ();
926 932
927 octave_scalar_map err; 933 octave_scalar_map err;
928
929 ult = expr_id->lvalue ();
930
931 if (error_state)
932 return;
933 934
934 err.assign ("message", last_error_message ()); 935 err.assign ("message", last_error_message ());
935 err.assign ("identifier", last_error_id ()); 936 err.assign ("identifier", last_error_id ());
936 err.assign ("stack", last_error_stack ()); 937 err.assign ("stack", last_error_stack ());
937 938
938 if (! error_state) 939 ult.assign (octave_value::op_asn_eq, err);
939 ult.assign (octave_value::op_asn_eq, err);
940
941 } 940 }
942 941
943 if (catch_code) 942 if (catch_code)
944 catch_code->accept (*this); 943 catch_code->accept (*this);
945 } 944 }
951 { 950 {
952 unwind_protect frame; 951 unwind_protect frame;
953 952
954 frame.protect_var (octave_interrupt_state); 953 frame.protect_var (octave_interrupt_state);
955 octave_interrupt_state = 0; 954 octave_interrupt_state = 0;
956
957 // We want to run the cleanup code without error_state being set,
958 // but we need to restore its value, so that any errors encountered
959 // in the first part of the unwind_protect are not completely
960 // ignored.
961
962 frame.protect_var (error_state);
963 error_state = 0;
964 955
965 // We want to preserve the last location info for possible 956 // We want to preserve the last location info for possible
966 // backtracking. 957 // backtracking.
967 frame.add_fcn (octave_call_stack::set_line, 958 frame.add_fcn (octave_call_stack::set_line,
968 octave_call_stack::current_line ()); 959 octave_call_stack::current_line ());
978 tree_return_command::returning = 0; 969 tree_return_command::returning = 0;
979 970
980 frame.protect_var (tree_break_command::breaking); 971 frame.protect_var (tree_break_command::breaking);
981 tree_break_command::breaking = 0; 972 tree_break_command::breaking = 0;
982 973
983 if (list) 974 bool execution_error_in_cleanup = false;
984 list->accept (*this); 975
976 try
977 {
978 if (list)
979 list->accept (*this);
980 }
981 catch (const octave_execution_exception&)
982 {
983 execution_error_in_cleanup = true;
984 }
985 985
986 // The unwind_protects are popped off the stack in the reverse of 986 // The unwind_protects are popped off the stack in the reverse of
987 // the order they are pushed on. 987 // the order they are pushed on.
988 988
989 // FIXME: these statements say that if we see a break or 989 // FIXME: these statements say that if we see a break or
1009 // both. So, use the most recent one. If there is no return or 1009 // both. So, use the most recent one. If there is no return or
1010 // break in the cleanup block, the values should be reset to 1010 // break in the cleanup block, the values should be reset to
1011 // whatever they were when the cleanup block was entered. 1011 // whatever they were when the cleanup block was entered.
1012 1012
1013 if (tree_break_command::breaking || tree_return_command::returning) 1013 if (tree_break_command::breaking || tree_return_command::returning)
1014 {
1015 frame.discard (2);
1016 }
1017 else
1018 {
1019 frame.run (2);
1020 }
1021
1022 // We don't want to ignore errors that occur in the cleanup code, so
1023 // if an error is encountered there, leave error_state alone.
1024 // Otherwise, set it back to what it was before.
1025
1026 if (error_state)
1027 frame.discard (2); 1014 frame.discard (2);
1028 else 1015 else
1029 frame.run (2); 1016 frame.run (2);
1030 1017
1018 // We don't want to ignore errors that occur in the cleanup code,
1019 // so if an error is encountered there, rethrow the exception.
1020 // Otherwise, rethrow any exception that might have occurred in the
1021 // unwind_protect block.
1022
1023 if (execution_error_in_cleanup)
1024 frame.discard (2);
1025 else
1026 frame.run (2);
1027
1031 frame.run (); 1028 frame.run ();
1029
1030 // FIXME: we should really be rethrowing whatever exception occurred,
1031 // not just throwing an execution exception.
1032 if (unwind_protect_exception || execution_error_in_cleanup)
1033 {
1034 unwind_protect_exception = false;
1035
1036 octave_throw_execution_exception ();
1037 }
1032 } 1038 }
1033 1039
1034 void 1040 void
1035 tree_evaluator::visit_unwind_protect_command (tree_unwind_protect_command& cmd) 1041 tree_evaluator::visit_unwind_protect_command (tree_unwind_protect_command& cmd)
1036 { 1042 {
1038 1044
1039 tree_statement_list *unwind_protect_code = cmd.body (); 1045 tree_statement_list *unwind_protect_code = cmd.body ();
1040 1046
1041 if (unwind_protect_code) 1047 if (unwind_protect_code)
1042 { 1048 {
1049 unwind_protect_exception = false;
1050
1043 try 1051 try
1044 { 1052 {
1045 unwind_protect_code->accept (*this); 1053 unwind_protect_code->accept (*this);
1046 } 1054 }
1047 catch (...) 1055 catch (const octave_execution_exception&)
1048 { 1056 {
1057 unwind_protect_exception = true;
1058
1049 // Run the cleanup code on exceptions, so that it is run even in case 1059 // Run the cleanup code on exceptions, so that it is run even in case
1050 // of interrupt or out-of-memory. 1060 // of interrupt or out-of-memory.
1051 do_unwind_protect_cleanup_code (cleanup_code); 1061 do_unwind_protect_cleanup_code (cleanup_code);
1062
1052 // FIXME: should error_state be checked here? 1063 // FIXME: should error_state be checked here?
1053 // We want to rethrow the exception, even if error_state is set, so 1064 // We want to rethrow the exception, even if error_state is set, so
1054 // that interrupts continue. 1065 // that interrupts continue.
1055 throw; 1066 throw;
1056 } 1067 }