comparison src/symtab.h @ 7752:40c428ea3408

initial implementation of dbup and dbdown
author John W. Eaton <jwe@octave.org>
date Sun, 04 May 2008 03:42:19 -0400
parents 8e4592e49fa7
children e76a4a6e3c47
comparison
equal deleted inserted replaced
7751:7c020c067a60 7752:40c428ea3408
26 26
27 #include <deque> 27 #include <deque>
28 #include <list> 28 #include <list>
29 #include <map> 29 #include <map>
30 #include <set> 30 #include <set>
31 #include <stack>
32 #include <string> 31 #include <string>
33 32
34 #include "glob-match.h" 33 #include "glob-match.h"
35 34
36 class tree_argument_list; 35 class tree_argument_list;
43 symbol_table 42 symbol_table
44 { 43 {
45 public: 44 public:
46 45
47 typedef int scope_id; 46 typedef int scope_id;
47 typedef size_t context_id;
48 48
49 class 49 class
50 symbol_record 50 symbol_record
51 { 51 {
52 public: 52 public:
82 82
83 symbol_record_rep (const std::string& nm, const octave_value& v, 83 symbol_record_rep (const std::string& nm, const octave_value& v,
84 unsigned int sc) 84 unsigned int sc)
85 : name (nm), value_stack (), storage_class (sc), count (1) 85 : name (nm), value_stack (), storage_class (sc), count (1)
86 { 86 {
87 value_stack.push (v); 87 value_stack.push_back (v);
88 } 88 }
89 89
90 octave_value& varref (void) { return value_stack.top (); } 90 octave_value& varref (void)
91 91 {
92 octave_value varval (void) const { return value_stack.top (); } 92 if (is_global ())
93 93 return symbol_table::global_varref (name);
94 void push_context (void) { value_stack.push (octave_value ()); } 94 else if (is_persistent ())
95 return symbol_table::persistent_varref (name);
96 else
97 {
98 context_id n = value_stack.size ();
99 while (n++ <= symbol_table::xcurrent_context)
100 value_stack.push_back (octave_value ());
101
102 return value_stack[symbol_table::xcurrent_context];
103 }
104 }
105
106 octave_value varval (void) const
107 {
108 if (is_global ())
109 return symbol_table::global_varval (name);
110 else if (is_persistent ())
111 return symbol_table::persistent_varval (name);
112 else
113 {
114 if (symbol_table::xcurrent_context < value_stack.size ())
115 return value_stack[symbol_table::xcurrent_context];
116 else
117 return octave_value ();
118 }
119 }
120
121 void push_context (void)
122 {
123 if (! (is_persistent () || is_global ()))
124 value_stack.push_back (octave_value ());
125 }
126
127 // If pop_context returns 0, we are out of values and this element
128 // of the symbol table should be deleted. This can happen for
129 // functions like
130 //
131 // function foo (n)
132 // if (n > 0)
133 // foo (n-1);
134 // else
135 // eval ("x = 1");
136 // endif
137 // endfunction
138 //
139 // Here, X should only exist in the final stack frame.
95 140
96 size_t pop_context (void) 141 size_t pop_context (void)
97 { 142 {
98 value_stack.pop (); 143 size_t retval = 1;
99 return value_stack.size (); 144
145 if (! (is_persistent () || is_global ()))
146 {
147 value_stack.pop_back ();
148 retval = value_stack.size ();
149 }
150
151 return retval;
100 } 152 }
101 153
102 void clear (void) 154 void clear (void)
103 { 155 {
104 if (! (is_hidden () || is_inherited ())) 156 if (! (is_hidden () || is_inherited ()))
183 return new symbol_record_rep (name, varval (), storage_class); 235 return new symbol_record_rep (name, varval (), storage_class);
184 } 236 }
185 237
186 std::string name; 238 std::string name;
187 239
188 std::stack<octave_value> value_stack; 240 std::deque<octave_value> value_stack;
189 241
190 unsigned int storage_class; 242 unsigned int storage_class;
191 243
192 size_t count; 244 size_t count;
193 245
236 288
237 octave_value 289 octave_value
238 find (tree_argument_list *args, const string_vector& arg_names, 290 find (tree_argument_list *args, const string_vector& arg_names,
239 octave_value_list& evaluated_args, bool& args_evaluated) const; 291 octave_value_list& evaluated_args, bool& args_evaluated) const;
240 292
241 octave_value& varref (void) 293 octave_value& varref (void) { return rep->varref (); }
242 { 294
243 return is_global () 295 octave_value varval (void) const { return rep->varval (); }
244 ? symbol_table::varref (name (), symbol_table::global_scope ()) 296
245 : rep->varref (); 297 void push_context (void) { rep->push_context (); }
246 } 298
247 299 size_t pop_context (void) { return rep->pop_context (); }
248 octave_value varval (void) const
249 {
250 return is_global ()
251 ? symbol_table::varval (name (), symbol_table::global_scope ())
252 : rep->varval ();
253 }
254
255 void push_context (void)
256 {
257 if (! (is_persistent () || is_global ()))
258 rep->push_context ();
259 }
260
261 // If pop_context returns 0, we are out of values and this element
262 // of the symbol table should be deleted. This can happen for
263 // functions like
264 //
265 // function foo (n)
266 // if (n > 0)
267 // foo (n-1);
268 // else
269 // eval ("x = 1");
270 // endif
271 // endfunction
272 //
273 // Here, X should only exist in the final stack frame.
274
275 size_t pop_context (void)
276 {
277 return (is_persistent () || is_global ()) ? 1 : rep->pop_context ();
278 }
279 300
280 void clear (void) { rep->clear (); } 301 void clear (void) { rep->clear (); }
281 302
282 bool is_defined (void) const { return rep->is_defined (); } 303 bool is_defined (void) const { return rep->is_defined (); }
283 bool is_variable (void) const { return rep->is_variable (); } 304 bool is_variable (void) const { return rep->is_variable (); }
354 375
355 octave_value load_class_method (const std::string& dispatch_type); 376 octave_value load_class_method (const std::string& dispatch_type);
356 377
357 octave_value 378 octave_value
358 find (tree_argument_list *args, const string_vector& arg_names, 379 find (tree_argument_list *args, const string_vector& arg_names,
359 octave_value_list& evaluated_args, bool& args_evaluated, 380 octave_value_list& evaluated_args, bool& args_evaluated);
360 scope_id scope);
361 381
362 octave_value find_method (const std::string& dispatch_type); 382 octave_value find_method (const std::string& dispatch_type);
363 383
364 octave_value find_autoload (void); 384 octave_value find_autoload (void);
365 385
368 bool is_user_function_defined (void) const 388 bool is_user_function_defined (void) const
369 { 389 {
370 return function_on_path.is_defined (); 390 return function_on_path.is_defined ();
371 } 391 }
372 392
373 octave_value find_function (scope_id scope) 393 octave_value find_function (void)
374 { 394 {
375 octave_value_list args; 395 octave_value_list args;
376 396
377 return find_function (args, scope); 397 return find_function (args);
378 } 398 }
379 399
380 octave_value find_function (const octave_value_list& args, 400 octave_value find_function (const octave_value_list& args)
381 scope_id scope)
382 { 401 {
383 string_vector arg_names; 402 string_vector arg_names;
384 octave_value_list evaluated_args = args; 403 octave_value_list evaluated_args = args;
385 bool args_evaluated; 404 bool args_evaluated;
386 405
387 return find (0, arg_names, evaluated_args, args_evaluated, scope); 406 return find (0, arg_names, evaluated_args, args_evaluated);
388 } 407 }
389 408
390 void install_cmdline_function (const octave_value& f) 409 void install_cmdline_function (const octave_value& f)
391 { 410 {
392 cmdline_function = f; 411 cmdline_function = f;
541 delete rep; 560 delete rep;
542 } 561 }
543 562
544 octave_value 563 octave_value
545 find (tree_argument_list *args, const string_vector& arg_names, 564 find (tree_argument_list *args, const string_vector& arg_names,
546 octave_value_list& evaluated_args, bool& args_evaluated, 565 octave_value_list& evaluated_args, bool& args_evaluated);
547 scope_id scope);
548 566
549 octave_value find_method (const std::string& dispatch_type) const 567 octave_value find_method (const std::string& dispatch_type) const
550 { 568 {
551 return rep->find_method (dispatch_type); 569 return rep->find_method (dispatch_type);
552 } 570 }
569 bool is_user_function_defined (void) const 587 bool is_user_function_defined (void) const
570 { 588 {
571 return rep->is_user_function_defined (); 589 return rep->is_user_function_defined ();
572 } 590 }
573 591
574 octave_value find_function (scope_id scope) 592 octave_value find_function (void)
575 { 593 {
576 return rep->find_function (scope); 594 return rep->find_function ();
577 } 595 }
578 596
579 octave_value find_function (const octave_value_list& args, 597 octave_value find_function (const octave_value_list& args)
580 scope_id scope) 598 {
581 { 599 return rep->find_function (args);
582 return rep->find_function (args, scope);
583 } 600 }
584 601
585 void install_cmdline_function (const octave_value& f) 602 void install_cmdline_function (const octave_value& f)
586 { 603 {
587 rep->install_cmdline_function (f); 604 rep->install_cmdline_function (f);
639 static scope_id top_scope (void) { return xtop_scope; } 656 static scope_id top_scope (void) { return xtop_scope; }
640 657
641 static scope_id current_scope (void) { return xcurrent_scope; } 658 static scope_id current_scope (void) { return xcurrent_scope; }
642 static scope_id current_caller_scope (void) { return xcurrent_caller_scope; } 659 static scope_id current_caller_scope (void) { return xcurrent_caller_scope; }
643 660
661 static context_id current_context (void) { return xcurrent_context; }
662
644 // We use parent_scope to handle parsing subfunctions. 663 // We use parent_scope to handle parsing subfunctions.
645 static scope_id parent_scope (void) { return xparent_scope; } 664 static scope_id parent_scope (void) { return xparent_scope; }
646 665
647 static scope_id alloc_scope (void) 666 static scope_id alloc_scope (void)
648 { 667 {
679 } 698 }
680 else 699 else
681 instance = p->second; 700 instance = p->second;
682 701
683 xcurrent_scope = scope; 702 xcurrent_scope = scope;
703 xcurrent_context = instance->xcurrent_context_this_table;
704 }
705 }
706
707 static void set_scope_and_context (scope_id scope, context_id context)
708 {
709 if (scope == xglobal_scope)
710 error ("can't set scope to global");
711 else
712 {
713 if (scope != xcurrent_scope)
714 {
715 all_instances_iterator p = all_instances.find (scope);
716
717 if (p == all_instances.end ())
718 error ("scope not found!");
719 else
720 {
721 instance = p->second;
722
723 xcurrent_scope = scope;
724 }
725 }
726
727 if (! error_state)
728 xcurrent_context = context;
684 } 729 }
685 } 730 }
686 731
687 static void push_scope (scope_id scope) 732 static void push_scope (scope_id scope)
688 { 733 {
726 static void reset_parent_scope (void) 771 static void reset_parent_scope (void)
727 { 772 {
728 set_parent_scope (-1); 773 set_parent_scope (-1);
729 } 774 }
730 775
731 static void erase_scope (scope_id scope = xcurrent_scope) 776 static void erase_scope (scope_id scope)
732 { 777 {
778 assert (scope != xglobal_scope);
779
733 all_instances_iterator p = all_instances.find (scope); 780 all_instances_iterator p = all_instances.find (scope);
734 781
735 if (p != all_instances.end ()) 782 if (p != all_instances.end ())
736 all_instances.erase (p); 783 all_instances.erase (p);
737 784
738 // free_scope (scope); 785 // free_scope (scope);
739 } 786 }
740 787
741 static scope_id dup_scope (scope_id scope = xcurrent_scope) 788 static scope_id dup_scope (scope_id scope)
742 { 789 {
743 scope_id retval = -1; 790 scope_id retval = -1;
744 791
745 symbol_table *inst = get_instance (scope); 792 symbol_table *inst = get_instance (scope);
746 793
762 809
763 return retval; 810 return retval;
764 } 811 }
765 812
766 #if 0 813 #if 0
767 static void print_scope (const std::string& tag, scope_id scope) 814 static void print_scope (const std::string& tag)
768 { 815 {
769 symbol_table *inst = get_instance (scope); 816 symbol_table *inst = get_instance (xcurrent_scope);
770 817
771 if (inst) 818 if (inst)
772 { 819 inst->do_print_scope (std::cerr);
773 std::cerr << "printing " << tag << ", scope: " << scope
774 << ", inst: " << inst << std::endl;
775
776 inst->do_print_scope (std::cerr);
777 }
778 } 820 }
779 821
780 void do_print_scope (std::ostream& os) const 822 void do_print_scope (std::ostream& os) const
781 { 823 {
782 for (const_table_iterator p = table.begin (); p != table.end (); p++) 824 for (const_table_iterator p = table.begin (); p != table.end (); p++)
791 os << sr.name () << " is not defined" << std::endl; 833 os << sr.name () << " is not defined" << std::endl;
792 } 834 }
793 } 835 }
794 #endif 836 #endif
795 837
796 static symbol_record find_symbol (const std::string& name, 838 static symbol_record
797 scope_id scope = xcurrent_scope) 839 find_symbol (const std::string& name, scope_id scope = xcurrent_scope)
798 { 840 {
799 symbol_table *inst = get_instance (scope); 841 symbol_table *inst = get_instance (scope);
800 842
801 return inst ? inst->do_find_symbol (name) : symbol_record (); 843 return inst ? inst->do_find_symbol (name) : symbol_record ();
802 } 844 }
814 // Find a value corresponding to the given name in the table. 856 // Find a value corresponding to the given name in the table.
815 static octave_value 857 static octave_value
816 find (const std::string& name, tree_argument_list *args, 858 find (const std::string& name, tree_argument_list *args,
817 const string_vector& arg_names, 859 const string_vector& arg_names,
818 octave_value_list& evaluated_args, bool& args_evaluated, 860 octave_value_list& evaluated_args, bool& args_evaluated,
819 scope_id scope = xcurrent_scope, bool skip_variables = false); 861 bool skip_variables = false);
820 862
821 // Insert a new name in the table. 863 // Insert a new name in the table.
822 static symbol_record& 864 static symbol_record& insert (const std::string& name)
823 insert (const std::string& name, scope_id scope = xcurrent_scope)
824 { 865 {
825 static symbol_record foobar; 866 static symbol_record foobar;
826 867
868 symbol_table *inst = get_instance (xcurrent_scope);
869
870 return inst ? inst->do_insert (name) : foobar;
871 }
872
873 static octave_value& varref (const std::string& name,
874 scope_id scope = xcurrent_scope)
875 {
876 static octave_value foobar;
877
827 symbol_table *inst = get_instance (scope); 878 symbol_table *inst = get_instance (scope);
828 879
829 return inst ? inst->do_insert (name) : foobar; 880 return inst ? inst->do_varref (name) : foobar;
881 }
882
883 static octave_value varval (const std::string& name,
884 scope_id scope = xcurrent_scope)
885 {
886 symbol_table *inst = get_instance (scope);
887
888 return inst ? inst->do_varval (name) : octave_value ();
830 } 889 }
831 890
832 static octave_value& 891 static octave_value&
833 varref (const std::string& name, scope_id scope = xcurrent_scope) 892 global_varref (const std::string& name)
893 {
894 global_table_iterator p = global_table.find (name);
895
896 return (p == global_table.end ()) ? global_table[name] : p->second;
897 }
898
899 static octave_value
900 global_varval (const std::string& name)
901 {
902 const_global_table_iterator p = global_table.find (name);
903
904 return (p != global_table.end ()) ? p->second : octave_value ();
905 }
906
907 static octave_value& persistent_varref (const std::string& name)
834 { 908 {
835 static octave_value foobar; 909 static octave_value foobar;
836 910
837 symbol_table *inst = get_instance (scope); 911 symbol_table *inst = get_instance (xcurrent_scope);
838
839 return inst ? inst->do_varref (name) : foobar;
840 }
841
842 static octave_value
843 varval (const std::string& name, scope_id scope = xcurrent_scope)
844 {
845 symbol_table *inst = get_instance (scope);
846
847 return inst ? inst->do_varval (name) : octave_value ();
848 }
849
850 static octave_value&
851 persistent_varref (const std::string& name, scope_id scope = xcurrent_scope)
852 {
853 static octave_value foobar;
854
855 symbol_table *inst = get_instance (scope);
856 912
857 return inst ? inst->do_persistent_varref (name) : foobar; 913 return inst ? inst->do_persistent_varref (name) : foobar;
858 } 914 }
859 915
860 static octave_value 916 static octave_value persistent_varval (const std::string& name)
861 persistent_varval (const std::string& name, scope_id scope = xcurrent_scope) 917 {
862 { 918 symbol_table *inst = get_instance (xcurrent_scope);
863 symbol_table *inst = get_instance (scope);
864 919
865 return inst ? inst->do_persistent_varval (name) : octave_value (); 920 return inst ? inst->do_persistent_varval (name) : octave_value ();
866 } 921 }
867 922
868 static void 923 static void erase_persistent (const std::string& name)
869 erase_persistent (const std::string& name, scope_id scope = xcurrent_scope) 924 {
870 { 925 symbol_table *inst = get_instance (xcurrent_scope);
871 symbol_table *inst = get_instance (scope);
872 926
873 if (inst) 927 if (inst)
874 inst->do_erase_persistent (name); 928 inst->do_erase_persistent (name);
875 } 929 }
876 930
877 static bool 931 static bool is_variable (const std::string& name)
878 is_variable (const std::string& name, scope_id scope = xcurrent_scope) 932 {
879 { 933 symbol_table *inst = get_instance (xcurrent_scope);
880 symbol_table *inst = get_instance (scope);
881 934
882 return inst ? inst->do_is_variable (name) : false; 935 return inst ? inst->do_is_variable (name) : false;
883 } 936 }
884 937
885 static bool 938 static bool
929 } 982 }
930 983
931 static octave_value 984 static octave_value
932 find_function (const std::string& name, tree_argument_list *args, 985 find_function (const std::string& name, tree_argument_list *args,
933 const string_vector& arg_names, 986 const string_vector& arg_names,
934 octave_value_list& evaluated_args, bool& args_evaluated, 987 octave_value_list& evaluated_args, bool& args_evaluated);
935 scope_id scope = xcurrent_scope); 988
936 989 static octave_value find_user_function (const std::string& name)
937 static octave_value
938 find_user_function (const std::string& name)
939 { 990 {
940 fcn_table_iterator p = fcn_table.find (name); 991 fcn_table_iterator p = fcn_table.find (name);
941 992
942 return (p != fcn_table.end ()) 993 return (p != fcn_table.end ())
943 ? p->second.find_user_function () : octave_value (); 994 ? p->second.find_user_function () : octave_value ();
944 } 995 }
945 996
997 static octave_value find_function (const std::string& name)
998 {
999 octave_value_list evaluated_args;
1000
1001 return find_function (name, evaluated_args);
1002 }
1003
946 static octave_value 1004 static octave_value
947 find_function (const std::string& name, scope_id scope = xcurrent_scope) 1005 find_function (const std::string& name, const octave_value_list& args)
948 {
949 octave_value_list evaluated_args;
950
951 return find_function (name, evaluated_args, scope);
952 }
953
954 static octave_value
955 find_function (const std::string& name, const octave_value_list& args,
956 scope_id scope = xcurrent_scope)
957 { 1006 {
958 string_vector arg_names; 1007 string_vector arg_names;
959 octave_value_list evaluated_args = args; 1008 octave_value_list evaluated_args = args;
960 bool args_evaluated = ! args.empty (); 1009 bool args_evaluated = ! args.empty ();
961 1010
962 return find_function (name, 0, arg_names, evaluated_args, 1011 return find_function (name, 0, arg_names, evaluated_args, args_evaluated);
963 args_evaluated, scope);
964 } 1012 }
965 1013
966 static void install_cmdline_function (const std::string& name, 1014 static void install_cmdline_function (const std::string& name,
967 const octave_value& fcn) 1015 const octave_value& fcn)
968 { 1016 {
1046 1094
1047 fcn_table[name] = finfo; 1095 fcn_table[name] = finfo;
1048 } 1096 }
1049 } 1097 }
1050 1098
1051 static void clear (const std::string& name, scope_id scope = xcurrent_scope) 1099 static void clear (const std::string& name)
1052 { 1100 {
1053 clear_variable (name, scope); 1101 clear_variable (name);
1054 } 1102 }
1055 1103
1056 static void clear_all (void) 1104 static void clear_all (void)
1057 { 1105 {
1058 clear_variables (); 1106 clear_variables ();
1059 1107
1060 clear_functions (); 1108 clear_functions ();
1061 } 1109 }
1062 1110
1063 static void clear_variables (scope_id scope = xcurrent_scope) 1111 static void clear_variables (void)
1064 { 1112 {
1065 symbol_table *inst = get_instance (scope); 1113 symbol_table *inst = get_instance (xcurrent_scope);
1066 1114
1067 if (inst) 1115 if (inst)
1068 inst->do_clear_variables (); 1116 inst->do_clear_variables ();
1069 } 1117 }
1070 1118
1080 static void clear_function (const std::string& name) 1128 static void clear_function (const std::string& name)
1081 { 1129 {
1082 clear_user_function (name); 1130 clear_user_function (name);
1083 } 1131 }
1084 1132
1085 static void clear_global (const std::string& name, 1133 static void clear_global (const std::string& name)
1086 scope_id scope = xcurrent_scope) 1134 {
1087 { 1135 symbol_table *inst = get_instance (xcurrent_scope);
1088 symbol_table *inst = get_instance (scope);
1089 1136
1090 if (inst) 1137 if (inst)
1091 inst->do_clear_global (name); 1138 inst->do_clear_global (name);
1092 } 1139 }
1093 1140
1094 static void clear_variable (const std::string& name, 1141 static void clear_variable (const std::string& name)
1095 scope_id scope = xcurrent_scope) 1142 {
1096 { 1143 symbol_table *inst = get_instance (xcurrent_scope);
1097 symbol_table *inst = get_instance (scope);
1098 1144
1099 if (inst) 1145 if (inst)
1100 inst->do_clear_variable (name); 1146 inst->do_clear_variable (name);
1101 } 1147 }
1102 1148
1117 if (pattern.match (p->first)) 1163 if (pattern.match (p->first))
1118 p->second.clear_user_function (); 1164 p->second.clear_user_function ();
1119 } 1165 }
1120 } 1166 }
1121 1167
1122 static void clear_global_pattern (const std::string& pat, 1168 static void clear_global_pattern (const std::string& pat)
1123 scope_id scope = xcurrent_scope) 1169 {
1124 { 1170 symbol_table *inst = get_instance (xcurrent_scope);
1125 symbol_table *inst = get_instance (scope);
1126 1171
1127 if (inst) 1172 if (inst)
1128 inst->do_clear_global_pattern (pat); 1173 inst->do_clear_global_pattern (pat);
1129 } 1174 }
1130 1175
1131 static void clear_variable_pattern (const std::string& pat, 1176 static void clear_variable_pattern (const std::string& pat)
1132 scope_id scope = xcurrent_scope) 1177 {
1133 { 1178 symbol_table *inst = get_instance (xcurrent_scope);
1134 symbol_table *inst = get_instance (scope);
1135 1179
1136 if (inst) 1180 if (inst)
1137 inst->do_clear_variable_pattern (pat); 1181 inst->do_clear_variable_pattern (pat);
1138 } 1182 }
1139 1183
1262 } 1306 }
1263 1307
1264 return retval; 1308 return retval;
1265 } 1309 }
1266 1310
1267 static void push_context (scope_id scope = xcurrent_scope) 1311 static void push_context (void)
1268 { 1312 {
1269 if (scope == xglobal_scope || scope == xtop_scope) 1313 if (xcurrent_scope == xglobal_scope || xcurrent_scope == xtop_scope)
1270 error ("invalid call to xymtab::push_context"); 1314 error ("invalid call to xymtab::push_context");
1271 else 1315 else
1272 { 1316 {
1273 symbol_table *inst = get_instance (scope); 1317 symbol_table *inst = get_instance (xcurrent_scope);
1274 1318
1275 if (inst) 1319 if (inst)
1276 inst->do_push_context (); 1320 inst->do_push_context ();
1277 } 1321 }
1278 } 1322 }
1279 1323
1280 static void pop_context (scope_id scope = xcurrent_scope) 1324 static void pop_context (void)
1281 { 1325 {
1282 if (scope == xglobal_scope || scope == xtop_scope) 1326 if (xcurrent_scope == xglobal_scope || xcurrent_scope == xtop_scope)
1283 error ("invalid call to xymtab::push_context"); 1327 error ("invalid call to xymtab::pop_context");
1284 else 1328 else
1285 { 1329 {
1286 symbol_table *inst = get_instance (scope); 1330 symbol_table *inst = get_instance (xcurrent_scope);
1287 1331
1288 if (inst) 1332 if (inst)
1289 inst->do_pop_context (); 1333 inst->do_pop_context ();
1290 } 1334 }
1291 } 1335 }
1292 1336
1293 // For unwind_protect. 1337 // For unwind_protect.
1294 static void pop_context (void *) { pop_context (); } 1338 static void pop_context (void *) { pop_context (); }
1295 1339
1296 static void mark_hidden (const std::string& name, 1340 static void mark_hidden (const std::string& name)
1297 scope_id scope = xcurrent_scope) 1341 {
1298 { 1342 symbol_table *inst = get_instance (xcurrent_scope);
1299 symbol_table *inst = get_instance (scope);
1300 1343
1301 if (inst) 1344 if (inst)
1302 inst->do_mark_hidden (name); 1345 inst->do_mark_hidden (name);
1303 } 1346 }
1304 1347
1305 static void mark_global (const std::string& name, 1348 static void mark_global (const std::string& name)
1306 scope_id scope = xcurrent_scope) 1349 {
1307 { 1350 symbol_table *inst = get_instance (xcurrent_scope);
1308 symbol_table *inst = get_instance (scope);
1309 1351
1310 if (inst) 1352 if (inst)
1311 inst->do_mark_global (name); 1353 inst->do_mark_global (name);
1312 } 1354 }
1313 1355
1318 1360
1319 return inst 1361 return inst
1320 ? inst->do_all_variables (defined_only) : std::list<symbol_record> (); 1362 ? inst->do_all_variables (defined_only) : std::list<symbol_record> ();
1321 } 1363 }
1322 1364
1365 static std::list<symbol_record> glob (const std::string& pattern)
1366 {
1367 symbol_table *inst = get_instance (xcurrent_scope);
1368
1369 return inst ? inst->do_glob (pattern) : std::list<symbol_record> ();
1370 }
1371
1372 static std::list<symbol_record> glob_variables (const std::string& pattern)
1373 {
1374 symbol_table *inst = get_instance (xcurrent_scope);
1375
1376 return inst ? inst->do_glob (pattern, true) : std::list<symbol_record> ();
1377 }
1378
1323 static std::list<symbol_record> 1379 static std::list<symbol_record>
1324 glob (const std::string& pattern, scope_id scope = xcurrent_scope) 1380 glob_global_variables (const std::string& pattern)
1325 {
1326 symbol_table *inst = get_instance (scope);
1327
1328 return inst ? inst->do_glob (pattern) : std::list<symbol_record> ();
1329 }
1330
1331 static std::list<symbol_record>
1332 glob_variables (const std::string& pattern, scope_id scope = xcurrent_scope)
1333 {
1334 symbol_table *inst = get_instance (scope);
1335
1336 return inst ? inst->do_glob (pattern, true) : std::list<symbol_record> ();
1337 }
1338
1339 static std::list<symbol_record>
1340 glob_variables (const string_vector& patterns,
1341 scope_id scope = xcurrent_scope)
1342 { 1381 {
1343 std::list<symbol_record> retval; 1382 std::list<symbol_record> retval;
1344 1383
1384 glob_match pat (pattern);
1385
1386 for (const_global_table_iterator p = global_table.begin ();
1387 p != global_table.end (); p++)
1388 {
1389 // We generate a list of symbol_record objects so that
1390 // the results from glob_variables and glob_global_variables
1391 // may be handled the same way.
1392
1393 if (pat.match (p->first))
1394 retval.push_back (symbol_record (p->first, p->second,
1395 symbol_record::global));
1396 }
1397
1398 return retval;
1399 }
1400
1401 static std::list<symbol_record> glob_variables (const string_vector& patterns)
1402 {
1403 std::list<symbol_record> retval;
1404
1345 size_t len = patterns.length (); 1405 size_t len = patterns.length ();
1346 1406
1347 for (size_t i = 0; i < len; i++) 1407 for (size_t i = 0; i < len; i++)
1348 { 1408 {
1349 std::list<symbol_record> tmp = glob_variables (patterns[i], scope); 1409 std::list<symbol_record> tmp = glob_variables (patterns[i]);
1350 1410
1351 retval.insert (retval.begin (), tmp.begin (), tmp.end ()); 1411 retval.insert (retval.begin (), tmp.begin (), tmp.end ());
1352 } 1412 }
1353 1413
1354 return retval; 1414 return retval;
1369 retval.sort (); 1429 retval.sort ();
1370 1430
1371 return retval; 1431 return retval;
1372 } 1432 }
1373 1433
1374 static std::list<std::string> 1434 static std::list<std::string> global_variable_names (void)
1375 variable_names (scope_id scope = xcurrent_scope) 1435 {
1376 { 1436 std::list<std::string> retval;
1377 symbol_table *inst = get_instance (scope); 1437
1438 for (const_global_table_iterator p = global_table.begin ();
1439 p != global_table.end (); p++)
1440 retval.push_back (p->first);
1441
1442 retval.sort ();
1443
1444 return retval;
1445 }
1446
1447 static std::list<std::string> top_level_variable_names (void)
1448 {
1449 symbol_table *inst = get_instance (xtop_scope);
1450
1451 return inst ? inst->do_variable_names () : std::list<std::string> ();
1452 }
1453
1454 static std::list<std::string> variable_names (void)
1455 {
1456 symbol_table *inst = get_instance (xcurrent_scope);
1378 1457
1379 return inst ? inst->do_variable_names () : std::list<std::string> (); 1458 return inst ? inst->do_variable_names () : std::list<std::string> ();
1380 } 1459 }
1381 1460
1382 static std::list<std::string> built_in_function_names (void) 1461 static std::list<std::string> built_in_function_names (void)
1396 retval.sort (); 1475 retval.sort ();
1397 1476
1398 return retval; 1477 return retval;
1399 } 1478 }
1400 1479
1401 static bool is_local_variable (const std::string& name, 1480 static bool is_local_variable (const std::string& name)
1402 scope_id scope = xcurrent_scope) 1481 {
1403 { 1482 if (xcurrent_scope == xglobal_scope)
1404 if (scope == xglobal_scope)
1405 return false; 1483 return false;
1406 else 1484 else
1407 { 1485 {
1408 symbol_table *inst = get_instance (scope); 1486 symbol_table *inst = get_instance (xcurrent_scope);
1409 1487
1410 return inst ? inst->do_is_local_variable (name) : false; 1488 return inst ? inst->do_is_local_variable (name) : false;
1411 } 1489 }
1412 } 1490 }
1413 1491
1414 static bool is_global (const std::string& name, 1492 static bool is_global (const std::string& name)
1415 scope_id scope = xcurrent_scope) 1493 {
1416 { 1494 if (xcurrent_scope == xglobal_scope)
1417 if (scope == xglobal_scope)
1418 return true; 1495 return true;
1419 else 1496 else
1420 { 1497 {
1421 symbol_table *inst = get_instance (scope); 1498 symbol_table *inst = get_instance (xcurrent_scope);
1422 1499
1423 return inst ? inst->do_is_global (name) : false; 1500 return inst ? inst->do_is_global (name) : false;
1424 } 1501 }
1425 } 1502 }
1426 1503
1427 private: 1504 private:
1428 1505
1429 typedef std::map<std::string, symbol_record>::const_iterator const_table_iterator; 1506 typedef std::map<std::string, symbol_record>::const_iterator const_table_iterator;
1430 typedef std::map<std::string, symbol_record>::iterator table_iterator; 1507 typedef std::map<std::string, symbol_record>::iterator table_iterator;
1431 1508
1509 typedef std::map<std::string, octave_value>::const_iterator const_global_table_iterator;
1510 typedef std::map<std::string, octave_value>::iterator global_table_iterator;
1511
1432 typedef std::map<std::string, octave_value>::const_iterator const_persistent_table_iterator; 1512 typedef std::map<std::string, octave_value>::const_iterator const_persistent_table_iterator;
1433 typedef std::map<std::string, octave_value>::iterator persistent_table_iterator; 1513 typedef std::map<std::string, octave_value>::iterator persistent_table_iterator;
1434 1514
1435 typedef std::map<scope_id, symbol_table*>::const_iterator all_instances_const_iterator; 1515 typedef std::map<scope_id, symbol_table*>::const_iterator all_instances_const_iterator;
1436 typedef std::map<scope_id, symbol_table*>::iterator all_instances_iterator; 1516 typedef std::map<scope_id, symbol_table*>::iterator all_instances_iterator;
1444 typedef std::set<scope_id>::const_iterator scope_ids_in_use_const_iterator; 1524 typedef std::set<scope_id>::const_iterator scope_ids_in_use_const_iterator;
1445 typedef std::set<scope_id>::iterator scope_ids_in_use_iterator; 1525 typedef std::set<scope_id>::iterator scope_ids_in_use_iterator;
1446 1526
1447 // Map from symbol names to symbol info. 1527 // Map from symbol names to symbol info.
1448 std::map<std::string, symbol_record> table; 1528 std::map<std::string, symbol_record> table;
1529
1530 // Map from names of global variables to values.
1531 static std::map<std::string, octave_value> global_table;
1449 1532
1450 // Map from names of persistent variables to values. 1533 // Map from names of persistent variables to values.
1451 std::map<std::string, octave_value> persistent_table; 1534 std::map<std::string, octave_value> persistent_table;
1452 1535
1453 // Pointer to symbol table for current scope (variables only). 1536 // Pointer to symbol table for current scope (variables only).
1467 static scope_id xcurrent_caller_scope; 1550 static scope_id xcurrent_caller_scope;
1468 1551
1469 // We use parent_scope to handle parsing subfunctions. 1552 // We use parent_scope to handle parsing subfunctions.
1470 static scope_id xparent_scope; 1553 static scope_id xparent_scope;
1471 1554
1555 // Used to handle recursive calls.
1556 context_id xcurrent_context_this_table;
1557 static context_id xcurrent_context;
1558
1472 static std::deque<scope_id> scope_stack; 1559 static std::deque<scope_id> scope_stack;
1473 1560
1474 // The next available scope ID. 1561 // The next available scope ID.
1475 static scope_id next_available_scope; 1562 static scope_id next_available_scope;
1476 1563
1478 static std::set<scope_id> scope_ids_in_use; 1565 static std::set<scope_id> scope_ids_in_use;
1479 1566
1480 // The set of scope IDs that are currently available. 1567 // The set of scope IDs that are currently available.
1481 static std::set<scope_id> scope_ids_free_list; 1568 static std::set<scope_id> scope_ids_free_list;
1482 1569
1483 symbol_table (void) : table () { } 1570 symbol_table (void) : table (), xcurrent_context_this_table () { }
1484 1571
1485 ~symbol_table (void) { } 1572 ~symbol_table (void) { }
1486 1573
1487 static void free_scope (scope_id scope) 1574 static void free_scope (scope_id scope)
1488 { 1575 {
1504 1591
1505 static symbol_table *get_instance (scope_id scope) 1592 static symbol_table *get_instance (scope_id scope)
1506 { 1593 {
1507 symbol_table *retval = 0; 1594 symbol_table *retval = 0;
1508 1595
1509 if (scope == xcurrent_scope) 1596 if (scope != xglobal_scope)
1510 { 1597 {
1511 if (! instance) 1598 if (scope == xcurrent_scope)
1512 { 1599 {
1513 instance = new symbol_table (); 1600 if (! instance)
1514 1601 {
1515 all_instances[scope] = instance; 1602 instance = new symbol_table ();
1516 } 1603
1517 1604 all_instances[scope] = instance;
1518 if (! instance) 1605 }
1519 error ("unable to create symbol_table object!"); 1606
1520 1607 if (! instance)
1521 retval = instance; 1608 error ("unable to create symbol_table object!");
1522 } 1609
1523 else 1610 retval = instance;
1524 {
1525 all_instances_iterator p = all_instances.find (scope);
1526
1527 if (p == all_instances.end ())
1528 {
1529 retval = new symbol_table ();
1530
1531 all_instances[scope] = retval;
1532 } 1611 }
1533 else 1612 else
1534 retval = p->second; 1613 {
1614 all_instances_iterator p = all_instances.find (scope);
1615
1616 if (p == all_instances.end ())
1617 {
1618 retval = new symbol_table ();
1619
1620 all_instances[scope] = retval;
1621 }
1622 else
1623 retval = p->second;
1624 }
1535 } 1625 }
1536 1626
1537 return retval; 1627 return retval;
1538 } 1628 }
1539 1629
1583 1673
1584 octave_value 1674 octave_value
1585 do_find (const std::string& name, tree_argument_list *args, 1675 do_find (const std::string& name, tree_argument_list *args,
1586 const string_vector& arg_names, 1676 const string_vector& arg_names,
1587 octave_value_list& evaluated_args, bool& args_evaluated, 1677 octave_value_list& evaluated_args, bool& args_evaluated,
1588 scope_id scope, bool skip_variables); 1678 bool skip_variables);
1589 1679
1590 symbol_record& do_insert (const std::string& name) 1680 symbol_record& do_insert (const std::string& name)
1591 { 1681 {
1592 table_iterator p = table.find (name); 1682 table_iterator p = table.find (name);
1593 1683
1655 return retval; 1745 return retval;
1656 } 1746 }
1657 1747
1658 void do_push_context (void) 1748 void do_push_context (void)
1659 { 1749 {
1750 xcurrent_context = ++xcurrent_context_this_table;
1751
1660 for (table_iterator p = table.begin (); p != table.end (); p++) 1752 for (table_iterator p = table.begin (); p != table.end (); p++)
1661 p->second.push_context (); 1753 p->second.push_context ();
1662 } 1754 }
1663 1755
1664 void do_pop_context (void) 1756 void do_pop_context (void)
1665 { 1757 {
1758 xcurrent_context = --xcurrent_context_this_table;
1759
1666 for (table_iterator p = table.begin (); p != table.end (); ) 1760 for (table_iterator p = table.begin (); p != table.end (); )
1667 { 1761 {
1668 if (p->second.pop_context () == 0) 1762 if (p->second.pop_context () == 0)
1669 table.erase (p++); 1763 table.erase (p++);
1670 else 1764 else
1686 { 1780 {
1687 symbol_record& sr = p->second; 1781 symbol_record& sr = p->second;
1688 1782
1689 if (sr.is_global ()) 1783 if (sr.is_global ())
1690 { 1784 {
1691 symbol_table::clear_variable (p->first, xglobal_scope); 1785 global_table_iterator q = global_table.find (name);
1786
1787 if (q != global_table.end ())
1788 global_table.erase (q);
1692 1789
1693 sr.unmark_global (); 1790 sr.unmark_global ();
1694 } 1791 }
1695 } 1792 }
1696 } 1793 }
1713 1810
1714 if (sr.is_global ()) 1811 if (sr.is_global ())
1715 { 1812 {
1716 if (pattern.match (sr.name ())) 1813 if (pattern.match (sr.name ()))
1717 { 1814 {
1718 symbol_table::clear_variable (p->first, xglobal_scope); 1815 global_table_iterator q = global_table.find (sr.name ());
1816
1817 if (q != global_table.end ())
1818 global_table.erase (q);
1719 1819
1720 sr.unmark_global (); 1820 sr.unmark_global ();
1721 } 1821 }
1722 } 1822 }
1723 } 1823 }