Mercurial > hg > octave-nkf
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 { |