Mercurial > hg > octave-lyh
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 } |