comparison src/pt-eval.cc @ 10066:2cd940306a06

make unwind_protect frames local
author Jaroslav Hajek <highegg@gmail.com>
date Wed, 06 Jan 2010 13:18:41 +0100
parents ca95d991a65a
children 829e69ec3110
comparison
equal deleted inserted replaced
10065:64a06079cae4 10066:2cd940306a06
277 return; 277 return;
278 278
279 if (debug_mode) 279 if (debug_mode)
280 do_breakpoint (cmd.is_breakpoint ()); 280 do_breakpoint (cmd.is_breakpoint ());
281 281
282 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); 282 unwind_protect frame;
283 283
284 unwind_protect::protect_var (in_loop_command); 284 frame.protect_var (in_loop_command);
285 285
286 in_loop_command = true; 286 in_loop_command = true;
287 287
288 tree_expression *expr = cmd.control_expr (); 288 tree_expression *expr = cmd.control_expr ();
289 289
290 octave_value rhs = expr->rvalue1 (); 290 octave_value rhs = expr->rvalue1 ();
291 291
292 if (error_state || rhs.is_undefined ()) 292 if (error_state || rhs.is_undefined ())
293 goto cleanup; 293 return;
294 294
295 { 295 {
296 tree_expression *lhs = cmd.left_hand_side (); 296 tree_expression *lhs = cmd.left_hand_side ();
297 297
298 octave_lvalue ult = lhs->lvalue (); 298 octave_lvalue ult = lhs->lvalue ();
299 299
300 if (error_state) 300 if (error_state)
301 goto cleanup; 301 return;
302 302
303 tree_statement_list *loop_body = cmd.body (); 303 tree_statement_list *loop_body = cmd.body ();
304 304
305 if (rhs.is_range ()) 305 if (rhs.is_range ())
306 { 306 {
385 { 385 {
386 ::error ("invalid type in for loop expression near line %d, column %d", 386 ::error ("invalid type in for loop expression near line %d, column %d",
387 cmd.line (), cmd.column ()); 387 cmd.line (), cmd.column ());
388 } 388 }
389 } 389 }
390
391 cleanup:
392 unwind_protect::run_frame (uwp_frame);
393 } 390 }
394 391
395 void 392 void
396 tree_evaluator::visit_complex_for_command (tree_complex_for_command& cmd) 393 tree_evaluator::visit_complex_for_command (tree_complex_for_command& cmd)
397 { 394 {
399 return; 396 return;
400 397
401 if (debug_mode) 398 if (debug_mode)
402 do_breakpoint (cmd.is_breakpoint ()); 399 do_breakpoint (cmd.is_breakpoint ());
403 400
404 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); 401 unwind_protect frame;
405 402
406 unwind_protect::protect_var (in_loop_command); 403 frame.protect_var (in_loop_command);
407 404
408 in_loop_command = true; 405 in_loop_command = true;
409 406
410 tree_expression *expr = cmd.control_expr (); 407 tree_expression *expr = cmd.control_expr ();
411 408
412 octave_value rhs = expr->rvalue1 (); 409 octave_value rhs = expr->rvalue1 ();
413 410
414 if (error_state || rhs.is_undefined ()) 411 if (error_state || rhs.is_undefined ())
415 goto cleanup; 412 return;
416 413
417 if (rhs.is_map ()) 414 if (rhs.is_map ())
418 { 415 {
419 // Cycle through structure elements. First element of id_list 416 // Cycle through structure elements. First element of id_list
420 // is set to value and the second is set to the name of the 417 // is set to value and the second is set to the name of the
460 break; 457 break;
461 } 458 }
462 } 459 }
463 else 460 else
464 error ("in statement `for [X, Y] = VAL', VAL must be a structure"); 461 error ("in statement `for [X, Y] = VAL', VAL must be a structure");
465
466 cleanup:
467 unwind_protect::run_frame (uwp_frame);
468 } 462 }
469 463
470 void 464 void
471 tree_evaluator::visit_octave_user_script (octave_user_script&) 465 tree_evaluator::visit_octave_user_script (octave_user_script&)
472 { 466 {
817 else 811 else
818 ::error ("missing value in switch command near line %d, column %d", 812 ::error ("missing value in switch command near line %d, column %d",
819 cmd.line (), cmd.column ()); 813 cmd.line (), cmd.column ());
820 } 814 }
821 815
822 static void
823 do_catch_code (tree_statement_list *list)
824 {
825 // Is it safe to call OCTAVE_QUIT here? We are already running
826 // something on the unwind_protect stack, but the element for this
827 // action would have already been popped from the top of the stack,
828 // so we should not be attempting to run it again.
829
830 OCTAVE_QUIT;
831
832 // If we are interrupting immediately, or if an interrupt is in
833 // progress (octave_interrupt_state < 0), then we don't want to run
834 // the catch code (it should only run on errors, not interrupts).
835
836 // If octave_interrupt_state is positive, an interrupt is pending.
837 // The only way that could happen would be for the interrupt to
838 // come in after the OCTAVE_QUIT above and before the if statement
839 // below -- it's possible, but unlikely. In any case, we should
840 // probably let the catch code throw the exception because we don't
841 // want to skip that and potentially run some other code. For
842 // example, an error may have originally brought us here for some
843 // cleanup operation and we shouldn't skip that.
844
845 if (octave_interrupt_immediately || octave_interrupt_state < 0)
846 return;
847
848 // Set up for letting the user print any messages from errors that
849 // occurred in the body of the try_catch statement.
850
851 buffer_error_messages--;
852
853 if (list)
854 list->accept (*current_evaluator);
855 }
856
857 void 816 void
858 tree_evaluator::visit_try_catch_command (tree_try_catch_command& cmd) 817 tree_evaluator::visit_try_catch_command (tree_try_catch_command& cmd)
859 { 818 {
860 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); 819 unwind_protect frame;
861 820
862 unwind_protect::protect_var (buffer_error_messages); 821 frame.protect_var (buffer_error_messages);
863 unwind_protect::protect_var (Vdebug_on_error); 822 frame.protect_var (Vdebug_on_error);
864 unwind_protect::protect_var (Vdebug_on_warning); 823 frame.protect_var (Vdebug_on_warning);
865 824
866 buffer_error_messages++; 825 buffer_error_messages++;
867 Vdebug_on_error = false; 826 Vdebug_on_error = false;
868 Vdebug_on_warning = false; 827 Vdebug_on_warning = false;
869 828
870 tree_statement_list *catch_code = cmd.cleanup (); 829 tree_statement_list *catch_code = cmd.cleanup ();
871 830
872 unwind_protect::add_fcn (do_catch_code, catch_code); 831 // The catch code is *not* added to unwind_protect stack; it doesn't need
832 // to be run on interrupts.
873 833
874 tree_statement_list *try_code = cmd.body (); 834 tree_statement_list *try_code = cmd.body ();
875 835
876 if (try_code) 836 if (try_code)
877 try_code->accept (*this); 837 {
878 838 try_code->accept (*this);
879 if (catch_code && error_state) 839 // FIXME: should std::bad_alloc be handled here?
840 }
841
842 if (error_state)
880 { 843 {
881 error_state = 0; 844 error_state = 0;
882 unwind_protect::run_frame (uwp_frame); 845
883 } 846 if (catch_code)
884 else 847 {
885 { 848 // Set up for letting the user print any messages from errors that
886 error_state = 0; 849 // occurred in the body of the try_catch statement.
887 850
888 // Unwind stack elements must be cleared or run in the reverse 851 buffer_error_messages--;
889 // order in which they were added to the stack. 852
890 853 if (catch_code)
891 // For clearing the do_catch_code cleanup function. 854 catch_code->accept (*this);
892 unwind_protect::discard (); 855 }
893 856 }
894 // Run the rest of the frame. 857 }
895 unwind_protect::run_frame (uwp_frame); 858
896 } 859 void
897 } 860 tree_evaluator::do_unwind_protect_cleanup_code (tree_statement_list *list)
898 861 {
899 static void 862 unwind_protect frame;
900 do_unwind_protect_cleanup_code (tree_statement_list *list) 863
901 { 864 frame.protect_var (octave_interrupt_state);
902 unwind_protect::protect_var (octave_interrupt_state);
903 octave_interrupt_state = 0; 865 octave_interrupt_state = 0;
904 866
905 // We want to run the cleanup code without error_state being set, 867 // We want to run the cleanup code without error_state being set,
906 // but we need to restore its value, so that any errors encountered 868 // but we need to restore its value, so that any errors encountered
907 // in the first part of the unwind_protect are not completely 869 // in the first part of the unwind_protect are not completely
908 // ignored. 870 // ignored.
909 871
910 unwind_protect::protect_var (error_state); 872 frame.protect_var (error_state);
911 error_state = 0; 873 error_state = 0;
912 874
913 // Similarly, if we have seen a return or break statement, allow all 875 // Similarly, if we have seen a return or break statement, allow all
914 // the cleanup code to run before returning or handling the break. 876 // the cleanup code to run before returning or handling the break.
915 // We don't have to worry about continue statements because they can 877 // We don't have to worry about continue statements because they can
916 // only occur in loops. 878 // only occur in loops.
917 879
918 unwind_protect::protect_var (tree_return_command::returning); 880 frame.protect_var (tree_return_command::returning);
919 tree_return_command::returning = 0; 881 tree_return_command::returning = 0;
920 882
921 unwind_protect::protect_var (tree_break_command::breaking); 883 frame.protect_var (tree_break_command::breaking);
922 tree_break_command::breaking = 0; 884 tree_break_command::breaking = 0;
923 885
924 if (list) 886 if (list)
925 list->accept (*current_evaluator); 887 list->accept (*this);
926 888
927 // The unwind_protects are popped off the stack in the reverse of 889 // The unwind_protects are popped off the stack in the reverse of
928 // the order they are pushed on. 890 // the order they are pushed on.
929 891
930 // FIXME -- these statements say that if we see a break or 892 // FIXME -- these statements say that if we see a break or
951 // break in the cleanup block, the values should be reset to 913 // break in the cleanup block, the values should be reset to
952 // whatever they were when the cleanup block was entered. 914 // whatever they were when the cleanup block was entered.
953 915
954 if (tree_break_command::breaking || tree_return_command::returning) 916 if (tree_break_command::breaking || tree_return_command::returning)
955 { 917 {
956 unwind_protect::discard (); 918 frame.discard_top (2);
957 unwind_protect::discard ();
958 } 919 }
959 else 920 else
960 { 921 {
961 unwind_protect::run (); 922 frame.run_top (2);
962 unwind_protect::run ();
963 } 923 }
964 924
965 // We don't want to ignore errors that occur in the cleanup code, so 925 // We don't want to ignore errors that occur in the cleanup code, so
966 // if an error is encountered there, leave error_state alone. 926 // if an error is encountered there, leave error_state alone.
967 // Otherwise, set it back to what it was before. 927 // Otherwise, set it back to what it was before.
968 928
969 if (error_state) 929 if (error_state)
970 unwind_protect::discard (); 930 frame.discard_top ();
971 else 931 else
972 unwind_protect::run (); 932 frame.run_top ();
973 933
974 unwind_protect::run (); 934 frame.run ();
975 } 935 }
976 936
977 void 937 void
978 tree_evaluator::visit_unwind_protect_command (tree_unwind_protect_command& cmd) 938 tree_evaluator::visit_unwind_protect_command (tree_unwind_protect_command& cmd)
979 { 939 {
980 tree_statement_list *cleanup_code = cmd.cleanup (); 940 tree_statement_list *cleanup_code = cmd.cleanup ();
981 941
982 unwind_protect::add_fcn (do_unwind_protect_cleanup_code, cleanup_code);
983
984 tree_statement_list *unwind_protect_code = cmd.body (); 942 tree_statement_list *unwind_protect_code = cmd.body ();
985 943
986 if (unwind_protect_code) 944 if (unwind_protect_code)
987 unwind_protect_code->accept (*this); 945 {
988 946 try
989 unwind_protect::run (); 947 {
948 unwind_protect_code->accept (*this);
949 }
950 catch (...)
951 {
952 // Run the cleanup code on exceptions, so that it is run even in case
953 // of interrupt or out-of-memory.
954 do_unwind_protect_cleanup_code (cleanup_code);
955 // FIXME: should error_state be checked here?
956 // We want to rethrow the exception, even if error_state is set, so
957 // that interrupts continue.
958 throw;
959 }
960
961 do_unwind_protect_cleanup_code (cleanup_code);
962 }
990 } 963 }
991 964
992 void 965 void
993 tree_evaluator::visit_while_command (tree_while_command& cmd) 966 tree_evaluator::visit_while_command (tree_while_command& cmd)
994 { 967 {
995 if (error_state) 968 if (error_state)
996 return; 969 return;
997 970
998 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); 971 unwind_protect frame;
999 972
1000 unwind_protect::protect_var (in_loop_command); 973 frame.protect_var (in_loop_command);
1001 974
1002 in_loop_command = true; 975 in_loop_command = true;
1003 976
1004 tree_expression *expr = cmd.condition (); 977 tree_expression *expr = cmd.condition ();
1005 978
1018 if (loop_body) 991 if (loop_body)
1019 { 992 {
1020 loop_body->accept (*this); 993 loop_body->accept (*this);
1021 994
1022 if (error_state) 995 if (error_state)
1023 goto cleanup; 996 return;
1024 } 997 }
1025 998
1026 if (quit_loop_now ()) 999 if (quit_loop_now ())
1027 break; 1000 break;
1028 } 1001 }
1029 else 1002 else
1030 break; 1003 break;
1031 } 1004 }
1032
1033 cleanup:
1034 unwind_protect::run_frame (uwp_frame);
1035 } 1005 }
1036 1006
1037 void 1007 void
1038 tree_evaluator::visit_do_until_command (tree_do_until_command& cmd) 1008 tree_evaluator::visit_do_until_command (tree_do_until_command& cmd)
1039 { 1009 {
1040 if (error_state) 1010 if (error_state)
1041 return; 1011 return;
1042 1012
1043 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); 1013 unwind_protect frame;
1044 1014
1045 unwind_protect::protect_var (in_loop_command); 1015 frame.protect_var (in_loop_command);
1046 1016
1047 in_loop_command = true; 1017 in_loop_command = true;
1048 1018
1049 tree_expression *expr = cmd.condition (); 1019 tree_expression *expr = cmd.condition ();
1050 1020
1058 if (loop_body) 1028 if (loop_body)
1059 { 1029 {
1060 loop_body->accept (*this); 1030 loop_body->accept (*this);
1061 1031
1062 if (error_state) 1032 if (error_state)
1063 goto cleanup; 1033 return;
1064 } 1034 }
1065 1035
1066 if (quit_loop_now ()) 1036 if (quit_loop_now ())
1067 break; 1037 break;
1068 1038
1070 do_breakpoint (cmd.is_breakpoint ()); 1040 do_breakpoint (cmd.is_breakpoint ());
1071 1041
1072 if (expr->is_logically_true ("do-until")) 1042 if (expr->is_logically_true ("do-until"))
1073 break; 1043 break;
1074 } 1044 }
1075
1076 cleanup:
1077 unwind_protect::run_frame (uwp_frame);
1078 } 1045 }
1079 1046
1080 void 1047 void
1081 tree_evaluator::do_breakpoint (tree_statement& stmt) const 1048 tree_evaluator::do_breakpoint (tree_statement& stmt) const
1082 { 1049 {