00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #if !defined (octave_symtab_h)
00025 #define octave_symtab_h 1
00026
00027 #include <deque>
00028 #include <list>
00029 #include <map>
00030 #include <set>
00031 #include <string>
00032
00033 #include "glob-match.h"
00034 #include "regexp.h"
00035
00036 class tree_argument_list;
00037 class octave_user_function;
00038
00039 #include "oct-obj.h"
00040 #include "oct-refcount.h"
00041 #include "ov.h"
00042
00043 class
00044 OCTINTERP_API
00045 symbol_table
00046 {
00047 public:
00048
00049 typedef int scope_id;
00050 typedef size_t context_id;
00051
00052 class
00053 scope_id_cache
00054 {
00055 protected:
00056
00057 typedef std::set<scope_id>::iterator set_iterator;
00058 typedef std::set<scope_id>::const_iterator set_const_iterator;
00059
00060
00061
00062
00063 scope_id_cache (void) : next_available (2), in_use (), free_list () { }
00064
00065 public:
00066
00067 ~scope_id_cache (void) { }
00068
00069 static scope_id alloc (void)
00070 {
00071 return instance_ok () ? instance->do_alloc () : -1;
00072 }
00073
00074 static void free (scope_id scope)
00075 {
00076 if (instance_ok ())
00077 return instance->do_free (scope);
00078 }
00079
00080 static std::list<scope_id> scopes (void)
00081 {
00082 return instance_ok () ? instance->do_scopes () : std::list<scope_id> ();
00083 }
00084
00085 static void create_instance (void);
00086
00087 static bool instance_ok (void)
00088 {
00089 bool retval = true;
00090
00091 if (! instance)
00092 create_instance ();
00093
00094 if (! instance)
00095 {
00096 ::error ("unable to create scope_id_cache object!");
00097
00098 retval = false;
00099 }
00100
00101 return retval;
00102 }
00103
00104 private:
00105
00106
00107
00108 scope_id_cache (const scope_id_cache&);
00109
00110 scope_id_cache& operator = (const scope_id_cache&);
00111
00112 static scope_id_cache *instance;
00113
00114 static void cleanup_instance (void) { delete instance; instance = 0; }
00115
00116
00117 scope_id next_available;
00118
00119
00120 std::set<scope_id> in_use;
00121
00122
00123 std::set<scope_id> free_list;
00124
00125 scope_id do_alloc (void)
00126 {
00127 scope_id retval;
00128
00129 set_iterator p = free_list.begin ();
00130
00131 if (p != free_list.end ())
00132 {
00133 retval = *p;
00134 free_list.erase (p);
00135 }
00136 else
00137 retval = next_available++;
00138
00139 in_use.insert (retval);
00140
00141 return retval;
00142 }
00143
00144 void do_free (scope_id scope)
00145 {
00146 set_iterator p = in_use.find (scope);
00147
00148 if (p != in_use.end ())
00149 {
00150 in_use.erase (p);
00151 free_list.insert (scope);
00152 }
00153 else
00154 error ("free_scope: scope %d not found!", scope);
00155 }
00156
00157 std::list<scope_id> do_scopes (void) const
00158 {
00159 std::list<scope_id> retval;
00160
00161 for (set_const_iterator p = in_use.begin (); p != in_use.end (); p++)
00162 retval.push_back (*p);
00163
00164 retval.sort ();
00165
00166 return retval;
00167 }
00168 };
00169
00170 class fcn_info;
00171
00172 class
00173 symbol_record
00174 {
00175 public:
00176
00177
00178 static const unsigned int local = 1;
00179
00180
00181
00182 static const unsigned int automatic = 2;
00183
00184
00185 static const unsigned int formal = 4;
00186
00187
00188 static const unsigned int hidden = 8;
00189
00190
00191 static const unsigned int inherited = 16;
00192
00193
00194 static const unsigned int global = 32;
00195
00196
00197 static const unsigned int persistent = 64;
00198
00199
00200 static const unsigned int forced = 128;
00201
00202 private:
00203
00204 class
00205 symbol_record_rep
00206 {
00207 public:
00208
00209 symbol_record_rep (const std::string& nm, const octave_value& v,
00210 unsigned int sc)
00211 : name (nm), value_stack (), storage_class (sc), finfo (), count (1)
00212 {
00213 value_stack.push_back (v);
00214 }
00215
00216 void force_variable (context_id context)
00217 {
00218 octave_value& val = varref (context);
00219
00220 if (! val.is_defined ())
00221 mark_forced ();
00222 }
00223
00224 octave_value& varref (context_id context)
00225 {
00226 if (is_global ())
00227 return symbol_table::global_varref (name);
00228 else if (is_persistent ())
00229 return symbol_table::persistent_varref (name);
00230 else
00231 {
00232 context_id n = value_stack.size ();
00233 while (n++ <= context)
00234 value_stack.push_back (octave_value ());
00235
00236 return value_stack[context];
00237 }
00238 }
00239
00240 octave_value varval (context_id context) const
00241 {
00242 if (is_global ())
00243 return symbol_table::global_varval (name);
00244 else if (is_persistent ())
00245 return symbol_table::persistent_varval (name);
00246 else
00247 {
00248 if (context < value_stack.size ())
00249 return value_stack[context];
00250 else
00251 return octave_value ();
00252 }
00253 }
00254
00255 void push_context (void)
00256 {
00257 if (! (is_persistent () || is_global ()))
00258 value_stack.push_back (octave_value ());
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 size_t pop_context (void)
00276 {
00277 size_t retval = 1;
00278
00279 if (! (is_persistent () || is_global ()))
00280 {
00281 value_stack.pop_back ();
00282 retval = value_stack.size ();
00283 }
00284
00285 return retval;
00286 }
00287
00288 void clear (void)
00289 {
00290 if (! (is_hidden () || is_inherited ()))
00291 {
00292 if (is_global ())
00293 unmark_global ();
00294
00295 if (is_persistent ())
00296 {
00297 symbol_table::persistent_varref (name)
00298 = varval (xcurrent_context);
00299
00300 unmark_persistent ();
00301 }
00302
00303 varref (xcurrent_context) = octave_value ();
00304 }
00305 }
00306
00307 bool is_defined (context_id context) const
00308 {
00309 return varval (context).is_defined ();
00310 }
00311
00312 bool is_variable (context_id context) const
00313 {
00314 return (! is_local () || is_defined (context) || is_forced ());
00315 }
00316
00317 bool is_local (void) const { return storage_class & local; }
00318 bool is_automatic (void) const { return storage_class & automatic; }
00319 bool is_formal (void) const { return storage_class & formal; }
00320 bool is_hidden (void) const { return storage_class & hidden; }
00321 bool is_inherited (void) const { return storage_class & inherited; }
00322 bool is_global (void) const { return storage_class & global; }
00323 bool is_persistent (void) const { return storage_class & persistent; }
00324 bool is_forced (void) const { return storage_class & forced; }
00325
00326 void mark_local (void) { storage_class |= local; }
00327 void mark_automatic (void) { storage_class |= automatic; }
00328 void mark_formal (void) { storage_class |= formal; }
00329 void mark_hidden (void) { storage_class |= hidden; }
00330 void mark_inherited (void) { storage_class |= inherited; }
00331 void mark_global (void)
00332 {
00333 if (is_persistent ())
00334 error ("can't make persistent variable %s global", name.c_str ());
00335 else
00336 storage_class |= global;
00337 }
00338 void mark_persistent (void)
00339 {
00340 if (is_global ())
00341 error ("can't make global variable %s persistent", name.c_str ());
00342 else
00343 storage_class |= persistent;
00344 }
00345 void mark_forced (void) { storage_class |= forced; }
00346
00347 void unmark_local (void) { storage_class &= ~local; }
00348 void unmark_automatic (void) { storage_class &= ~automatic; }
00349 void unmark_formal (void) { storage_class &= ~formal; }
00350 void unmark_hidden (void) { storage_class &= ~hidden; }
00351 void unmark_inherited (void) { storage_class &= ~inherited; }
00352 void unmark_global (void) { storage_class &= ~global; }
00353 void unmark_persistent (void) { storage_class &= ~persistent; }
00354 void unmark_forced (void) { storage_class &= ~forced; }
00355
00356 void init_persistent (void)
00357 {
00358 if (! is_defined (xcurrent_context))
00359 {
00360 mark_persistent ();
00361
00362 varref (xcurrent_context) = symbol_table::persistent_varval (name);
00363 }
00364
00365
00366
00367 }
00368
00369 void erase_persistent (void)
00370 {
00371 unmark_persistent ();
00372 symbol_table::erase_persistent (name);
00373 }
00374
00375 symbol_record_rep *dup (void) const
00376 {
00377 return new symbol_record_rep (name, varval (xcurrent_context),
00378 storage_class);
00379 }
00380
00381 void dump (std::ostream& os, const std::string& prefix) const;
00382
00383 std::string name;
00384
00385 std::deque<octave_value> value_stack;
00386
00387 unsigned int storage_class;
00388
00389 fcn_info *finfo;
00390
00391 octave_refcount<size_t> count;
00392
00393 private:
00394
00395
00396
00397 symbol_record_rep (const symbol_record_rep& ov);
00398
00399 symbol_record_rep& operator = (const symbol_record_rep&);
00400 };
00401
00402 public:
00403
00404 symbol_record (const std::string& nm = std::string (),
00405 const octave_value& v = octave_value (),
00406 unsigned int sc = local)
00407 : rep (new symbol_record_rep (nm, v, sc)) { }
00408
00409 symbol_record (const symbol_record& sr)
00410 : rep (sr.rep)
00411 {
00412 rep->count++;
00413 }
00414
00415 symbol_record& operator = (const symbol_record& sr)
00416 {
00417 if (this != &sr)
00418 {
00419 if (--rep->count == 0)
00420 delete rep;
00421
00422 rep = sr.rep;
00423 rep->count++;
00424 }
00425
00426 return *this;
00427 }
00428
00429 ~symbol_record (void)
00430 {
00431 if (--rep->count == 0)
00432 delete rep;
00433 }
00434
00435 symbol_record dup (void) const { return symbol_record (rep->dup ()); }
00436
00437 std::string name (void) const { return rep->name; }
00438
00439 octave_value find (const octave_value_list& args = octave_value_list ()) const;
00440
00441 void force_variable (context_id context = xcurrent_context)
00442 {
00443 rep->force_variable (context);
00444 }
00445
00446 octave_value& varref (context_id context = xcurrent_context)
00447 {
00448 return rep->varref (context);
00449 }
00450
00451 octave_value varval (context_id context = xcurrent_context) const
00452 {
00453 return rep->varval (context);
00454 }
00455
00456 void push_context (void) { rep->push_context (); }
00457
00458 size_t pop_context (void) { return rep->pop_context (); }
00459
00460 void clear (void) { rep->clear (); }
00461
00462 bool is_defined (context_id context = xcurrent_context) const
00463 {
00464 return rep->is_defined (context);
00465 }
00466
00467 bool is_variable (context_id context = xcurrent_context) const
00468 {
00469 return rep->is_variable (context);
00470 }
00471
00472 bool is_local (void) const { return rep->is_local (); }
00473 bool is_automatic (void) const { return rep->is_automatic (); }
00474 bool is_formal (void) const { return rep->is_formal (); }
00475 bool is_global (void) const { return rep->is_global (); }
00476 bool is_hidden (void) const { return rep->is_hidden (); }
00477 bool is_inherited (void) const { return rep->is_inherited (); }
00478 bool is_persistent (void) const { return rep->is_persistent (); }
00479 bool is_forced (void) const { return rep->is_forced (); }
00480
00481 void mark_local (void) { rep->mark_local (); }
00482 void mark_automatic (void) { rep->mark_automatic (); }
00483 void mark_formal (void) { rep->mark_formal (); }
00484 void mark_hidden (void) { rep->mark_hidden (); }
00485 void mark_inherited (void) { rep->mark_inherited (); }
00486 void mark_global (void) { rep->mark_global (); }
00487 void mark_persistent (void) { rep->mark_persistent (); }
00488 void mark_forced (void) { rep->mark_forced (); }
00489
00490 void unmark_local (void) { rep->unmark_local (); }
00491 void unmark_automatic (void) { rep->unmark_automatic (); }
00492 void unmark_formal (void) { rep->unmark_formal (); }
00493 void unmark_hidden (void) { rep->unmark_hidden (); }
00494 void unmark_inherited (void) { rep->unmark_inherited (); }
00495 void unmark_global (void) { rep->unmark_global (); }
00496 void unmark_persistent (void) { rep->unmark_persistent (); }
00497 void unmark_forced (void) { rep->unmark_forced (); }
00498
00499 void init_persistent (void) { rep->init_persistent (); }
00500
00501 void erase_persistent (void) { rep->erase_persistent (); }
00502
00503 unsigned int xstorage_class (void) const { return rep->storage_class; }
00504
00505 void
00506 dump (std::ostream& os, const std::string& prefix = std::string ()) const
00507 {
00508 rep->dump (os, prefix);
00509 }
00510
00511 private:
00512
00513 symbol_record_rep *rep;
00514
00515 symbol_record (symbol_record_rep *new_rep) : rep (new_rep) { }
00516 };
00517
00518 class
00519 fcn_info
00520 {
00521 public:
00522
00523 typedef std::map<std::string, std::string> dispatch_map_type;
00524
00525 typedef std::map<scope_id, octave_value>::const_iterator scope_val_const_iterator;
00526 typedef std::map<scope_id, octave_value>::iterator scope_val_iterator;
00527
00528 typedef std::map<std::string, octave_value>::const_iterator str_val_const_iterator;
00529 typedef std::map<std::string, octave_value>::iterator str_val_iterator;
00530
00531 typedef dispatch_map_type::const_iterator dispatch_map_const_iterator;
00532 typedef dispatch_map_type::iterator dispatch_map_iterator;
00533
00534 private:
00535
00536 class
00537 fcn_info_rep
00538 {
00539 public:
00540
00541 fcn_info_rep (const std::string& nm)
00542 : name (nm), subfunctions (), private_functions (),
00543 class_constructors (), class_methods (), dispatch_map (),
00544 cmdline_function (), autoload_function (), function_on_path (),
00545 built_in_function (), count (1) { }
00546
00547 octave_value load_private_function (const std::string& dir_name);
00548
00549 octave_value load_class_constructor (void);
00550
00551 octave_value load_class_method (const std::string& dispatch_type);
00552
00553 octave_value find (const octave_value_list& args, bool local_funcs);
00554
00555 octave_value builtin_find (void);
00556
00557 octave_value find_method (const std::string& dispatch_type);
00558
00559 octave_value find_autoload (void);
00560
00561 octave_value find_user_function (void);
00562
00563 bool is_user_function_defined (void) const
00564 {
00565 return function_on_path.is_defined ();
00566 }
00567
00568 octave_value find_function (const octave_value_list& args, bool local_funcs)
00569 {
00570 return find (args, local_funcs);
00571 }
00572
00573 void lock_subfunction (scope_id scope)
00574 {
00575 scope_val_iterator p = subfunctions.find (scope);
00576
00577 if (p != subfunctions.end ())
00578 p->second.lock ();
00579 }
00580
00581 void unlock_subfunction (scope_id scope)
00582 {
00583 scope_val_iterator p = subfunctions.find (scope);
00584
00585 if (p != subfunctions.end ())
00586 p->second.unlock ();
00587 }
00588
00589 std::pair<std::string, octave_value>
00590 subfunction_defined_in_scope (scope_id scope) const
00591 {
00592 scope_val_const_iterator p = subfunctions.find (scope);
00593
00594 return p == subfunctions.end ()
00595 ? std::pair<std::string, octave_value> ()
00596 : std::pair<std::string, octave_value> (name, p->second);
00597 }
00598
00599 void erase_subfunction (scope_id scope)
00600 {
00601 scope_val_iterator p = subfunctions.find (scope);
00602
00603 if (p != subfunctions.end ())
00604 subfunctions.erase (p);
00605 }
00606
00607 void mark_subfunction_in_scope_as_private (scope_id scope,
00608 const std::string& class_name);
00609
00610 void install_cmdline_function (const octave_value& f)
00611 {
00612 cmdline_function = f;
00613 }
00614
00615 void install_subfunction (const octave_value& f, scope_id scope)
00616 {
00617 subfunctions[scope] = f;
00618 }
00619
00620 void install_user_function (const octave_value& f)
00621 {
00622 function_on_path = f;
00623 }
00624
00625 void install_built_in_function (const octave_value& f)
00626 {
00627 built_in_function = f;
00628 }
00629
00630 template <class T>
00631 void
00632 clear_unlocked (std::map<T, octave_value>& map)
00633 {
00634 typename std::map<T, octave_value>::iterator p = map.begin ();
00635
00636 while (p != map.end ())
00637 {
00638 if (p->second.islocked ())
00639 p++;
00640 else
00641 map.erase (p++);
00642 }
00643 }
00644
00645 void clear_cmdline_function (void)
00646 {
00647 if (! cmdline_function.islocked ())
00648 cmdline_function = octave_value ();
00649 }
00650
00651 void clear_autoload_function (void)
00652 {
00653 if (! autoload_function.islocked ())
00654 autoload_function = octave_value ();
00655 }
00656
00657
00658
00659 void clear_user_function (void)
00660 {
00661 if (! function_on_path.islocked ())
00662 {
00663 function_on_path.erase_subfunctions ();
00664
00665 function_on_path = octave_value ();
00666 }
00667 }
00668
00669 void clear_mex_function (void)
00670 {
00671 if (function_on_path.is_mex_function ())
00672 clear_user_function ();
00673 }
00674
00675 void clear (void)
00676 {
00677 clear_unlocked (subfunctions);
00678 clear_unlocked (private_functions);
00679 clear_unlocked (class_constructors);
00680 clear_unlocked (class_methods);
00681 clear_cmdline_function ();
00682 clear_autoload_function ();
00683 clear_user_function ();
00684 }
00685
00686 void add_dispatch (const std::string& type, const std::string& fname)
00687 {
00688 dispatch_map[type] = fname;
00689 }
00690
00691 void clear_dispatch (const std::string& type)
00692 {
00693 dispatch_map_iterator p = dispatch_map.find (type);
00694
00695 if (p != dispatch_map.end ())
00696 dispatch_map.erase (p);
00697 }
00698
00699 void print_dispatch (std::ostream& os) const;
00700
00701 std::string help_for_dispatch (void) const;
00702
00703 dispatch_map_type get_dispatch (void) const { return dispatch_map; }
00704
00705 void dump (std::ostream& os, const std::string& prefix) const;
00706
00707 std::string name;
00708
00709
00710 std::map<scope_id, octave_value> subfunctions;
00711
00712
00713 std::map<std::string, octave_value> private_functions;
00714
00715
00716 std::map<std::string, octave_value> class_constructors;
00717
00718
00719 std::map<std::string, octave_value> class_methods;
00720
00721
00722 dispatch_map_type dispatch_map;
00723
00724 octave_value cmdline_function;
00725
00726 octave_value autoload_function;
00727
00728 octave_value function_on_path;
00729
00730 octave_value built_in_function;
00731
00732 octave_refcount<size_t> count;
00733
00734 private:
00735
00736 octave_value xfind (const octave_value_list& args, bool local_funcs);
00737
00738 octave_value x_builtin_find (void);
00739
00740
00741
00742 fcn_info_rep (const fcn_info_rep&);
00743
00744 fcn_info_rep& operator = (const fcn_info_rep&);
00745 };
00746
00747 public:
00748
00749 fcn_info (const std::string& nm = std::string ())
00750 : rep (new fcn_info_rep (nm)) { }
00751
00752 fcn_info (const fcn_info& fi) : rep (fi.rep)
00753 {
00754 rep->count++;
00755 }
00756
00757 fcn_info& operator = (const fcn_info& fi)
00758 {
00759 if (this != &fi)
00760 {
00761 if (--rep->count == 0)
00762 delete rep;
00763
00764 rep = fi.rep;
00765 rep->count++;
00766 }
00767
00768 return *this;
00769 }
00770
00771 ~fcn_info (void)
00772 {
00773 if (--rep->count == 0)
00774 delete rep;
00775 }
00776
00777 octave_value find (const octave_value_list& args = octave_value_list (),
00778 bool local_funcs = true)
00779 {
00780 return rep->find (args, local_funcs);
00781 }
00782
00783 octave_value builtin_find (void)
00784 {
00785 return rep->builtin_find ();
00786 }
00787
00788 octave_value find_method (const std::string& dispatch_type) const
00789 {
00790 return rep->find_method (dispatch_type);
00791 }
00792
00793 octave_value find_built_in_function (void) const
00794 {
00795 return rep->built_in_function;
00796 }
00797
00798 octave_value find_cmdline_function (void) const
00799 {
00800 return rep->cmdline_function;
00801 }
00802
00803 octave_value find_autoload (void)
00804 {
00805 return rep->find_autoload ();
00806 }
00807
00808 octave_value find_user_function (void)
00809 {
00810 return rep->find_user_function ();
00811 }
00812
00813 bool is_user_function_defined (void) const
00814 {
00815 return rep->is_user_function_defined ();
00816 }
00817
00818 octave_value find_function (const octave_value_list& args = octave_value_list (),
00819 bool local_funcs = true)
00820 {
00821 return rep->find_function (args, local_funcs);
00822 }
00823
00824 void lock_subfunction (scope_id scope)
00825 {
00826 rep->lock_subfunction (scope);
00827 }
00828
00829 void unlock_subfunction (scope_id scope)
00830 {
00831 rep->unlock_subfunction (scope);
00832 }
00833
00834 std::pair<std::string, octave_value>
00835 subfunction_defined_in_scope (scope_id scope = xcurrent_scope) const
00836 {
00837 return rep->subfunction_defined_in_scope (scope);
00838 }
00839
00840 void erase_subfunction (scope_id scope)
00841 {
00842 rep->erase_subfunction (scope);
00843 }
00844
00845 void mark_subfunction_in_scope_as_private (scope_id scope,
00846 const std::string& class_name)
00847 {
00848 rep->mark_subfunction_in_scope_as_private (scope, class_name);
00849 }
00850
00851 void install_cmdline_function (const octave_value& f)
00852 {
00853 rep->install_cmdline_function (f);
00854 }
00855
00856 void install_subfunction (const octave_value& f, scope_id scope)
00857 {
00858 rep->install_subfunction (f, scope);
00859 }
00860
00861 void install_user_function (const octave_value& f)
00862 {
00863 rep->install_user_function (f);
00864 }
00865
00866 void install_built_in_function (const octave_value& f)
00867 {
00868 rep->install_built_in_function (f);
00869 }
00870
00871 void clear (void) { rep->clear (); }
00872
00873 void clear_user_function (void) { rep->clear_user_function (); }
00874
00875 void clear_autoload_function (void) { rep->clear_autoload_function (); }
00876
00877 void clear_mex_function (void) { rep->clear_mex_function (); }
00878
00879 void add_dispatch (const std::string& type, const std::string& fname)
00880 {
00881 rep->add_dispatch (type, fname);
00882 }
00883
00884 void clear_dispatch (const std::string& type)
00885 {
00886 rep->clear_dispatch (type);
00887 }
00888
00889 void print_dispatch (std::ostream& os) const
00890 {
00891 rep->print_dispatch (os);
00892 }
00893
00894 std::string help_for_dispatch (void) const { return rep->help_for_dispatch (); }
00895
00896 dispatch_map_type get_dispatch (void) const
00897 {
00898 return rep->get_dispatch ();
00899 }
00900
00901 void
00902 dump (std::ostream& os, const std::string& prefix = std::string ()) const
00903 {
00904 rep->dump (os, prefix);
00905 }
00906
00907 private:
00908
00909 fcn_info_rep *rep;
00910 };
00911
00912 static scope_id global_scope (void) { return xglobal_scope; }
00913 static scope_id top_scope (void) { return xtop_scope; }
00914
00915 static scope_id current_scope (void) { return xcurrent_scope; }
00916
00917 static context_id current_context (void) { return xcurrent_context; }
00918
00919 static scope_id alloc_scope (void) { return scope_id_cache::alloc (); }
00920
00921 static void set_scope (scope_id scope)
00922 {
00923 if (scope == xglobal_scope)
00924 error ("can't set scope to global");
00925 else if (scope != xcurrent_scope)
00926 {
00927 all_instances_iterator p = all_instances.find (scope);
00928
00929 if (p == all_instances.end ())
00930 {
00931 symbol_table *inst = new symbol_table ();
00932
00933 if (inst)
00934 all_instances[scope] = instance = inst;
00935 }
00936 else
00937 instance = p->second;
00938
00939 xcurrent_scope = scope;
00940 xcurrent_context = 0;
00941 }
00942 }
00943
00944 static void set_scope_and_context (scope_id scope, context_id context)
00945 {
00946 if (scope == xglobal_scope)
00947 error ("can't set scope to global");
00948 else
00949 {
00950 if (scope != xcurrent_scope)
00951 {
00952 all_instances_iterator p = all_instances.find (scope);
00953
00954 if (p == all_instances.end ())
00955 error ("scope not found!");
00956 else
00957 {
00958 instance = p->second;
00959
00960 xcurrent_scope = scope;
00961
00962 xcurrent_context = context;
00963 }
00964 }
00965 else
00966 xcurrent_context = context;
00967 }
00968 }
00969
00970 static void erase_scope (scope_id scope)
00971 {
00972 assert (scope != xglobal_scope);
00973
00974 all_instances_iterator p = all_instances.find (scope);
00975
00976 if (p != all_instances.end ())
00977 {
00978 delete p->second;
00979
00980 all_instances.erase (p);
00981
00982 free_scope (scope);
00983 }
00984 }
00985
00986 static void erase_subfunctions_in_scope (scope_id scope)
00987 {
00988 for (fcn_table_iterator q = fcn_table.begin ();
00989 q != fcn_table.end (); q++)
00990 q->second.erase_subfunction (scope);
00991 }
00992
00993 static void
00994 mark_subfunctions_in_scope_as_private (scope_id scope,
00995 const std::string& class_name)
00996 {
00997 for (fcn_table_iterator q = fcn_table.begin ();
00998 q != fcn_table.end (); q++)
00999 q->second.mark_subfunction_in_scope_as_private (scope, class_name);
01000 }
01001
01002 static scope_id dup_scope (scope_id scope)
01003 {
01004 scope_id retval = -1;
01005
01006 symbol_table *inst = get_instance (scope);
01007
01008 if (inst)
01009 {
01010 scope_id new_scope = alloc_scope ();
01011
01012 symbol_table *new_symbol_table = new symbol_table ();
01013
01014 if (new_symbol_table)
01015 {
01016 all_instances[new_scope] = new_symbol_table;
01017
01018 inst->do_dup_scope (*new_symbol_table);
01019
01020 retval = new_scope;
01021 }
01022 }
01023
01024 return retval;
01025 }
01026
01027 static std::list<scope_id> scopes (void)
01028 {
01029 return scope_id_cache::scopes ();
01030 }
01031
01032 static symbol_record
01033 find_symbol (const std::string& name, scope_id scope = xcurrent_scope)
01034 {
01035 symbol_table *inst = get_instance (scope);
01036
01037 return inst ? inst->do_find_symbol (name) : symbol_record ();
01038 }
01039
01040 static void
01041 inherit (scope_id scope, scope_id donor_scope, context_id donor_context)
01042 {
01043 symbol_table *inst = get_instance (scope);
01044
01045 if (inst)
01046 {
01047 symbol_table *donor_symbol_table = get_instance (donor_scope);
01048
01049 if (donor_symbol_table)
01050 inst->do_inherit (*donor_symbol_table, donor_context);
01051 }
01052 }
01053
01054 static bool at_top_level (void) { return xcurrent_scope == xtop_scope; }
01055
01056
01057 static octave_value
01058 find (const std::string& name,
01059 const octave_value_list& args = octave_value_list (),
01060 bool skip_variables = false,
01061 bool local_funcs = true);
01062
01063 static octave_value builtin_find (const std::string& name);
01064
01065
01066 static symbol_record& insert (const std::string& name)
01067 {
01068 static symbol_record foobar;
01069
01070 symbol_table *inst = get_instance (xcurrent_scope);
01071
01072 return inst ? inst->do_insert (name) : foobar;
01073 }
01074
01075 static void force_variable (const std::string& name,
01076 scope_id scope = xcurrent_scope,
01077 context_id context = xcurrent_context)
01078 {
01079 symbol_table *inst = get_instance (scope);
01080
01081 if (inst)
01082 inst->do_force_variable (name, context);
01083 }
01084
01085 static octave_value& varref (const std::string& name,
01086 scope_id scope = xcurrent_scope,
01087 context_id context = xcurrent_context)
01088 {
01089 static octave_value foobar;
01090
01091 symbol_table *inst = get_instance (scope);
01092
01093 return inst ? inst->do_varref (name, context) : foobar;
01094 }
01095
01096 static octave_value varval (const std::string& name,
01097 scope_id scope = xcurrent_scope,
01098 context_id context = xcurrent_context)
01099 {
01100 symbol_table *inst = get_instance (scope);
01101
01102 return inst ? inst->do_varval (name, context) : octave_value ();
01103 }
01104
01105 static octave_value&
01106 global_varref (const std::string& name)
01107 {
01108 global_table_iterator p = global_table.find (name);
01109
01110 return (p == global_table.end ()) ? global_table[name] : p->second;
01111 }
01112
01113 static octave_value
01114 global_varval (const std::string& name)
01115 {
01116 global_table_const_iterator p = global_table.find (name);
01117
01118 return (p != global_table.end ()) ? p->second : octave_value ();
01119 }
01120
01121 static octave_value&
01122 top_level_varref (const std::string& name)
01123 {
01124 return varref (name, top_scope (), 0);
01125 }
01126
01127 static octave_value
01128 top_level_varval (const std::string& name)
01129 {
01130 return varval (name, top_scope (), 0);
01131 }
01132
01133 static octave_value& persistent_varref (const std::string& name)
01134 {
01135 static octave_value foobar;
01136
01137 symbol_table *inst = get_instance (xcurrent_scope);
01138
01139 return inst ? inst->do_persistent_varref (name) : foobar;
01140 }
01141
01142 static octave_value persistent_varval (const std::string& name)
01143 {
01144 symbol_table *inst = get_instance (xcurrent_scope);
01145
01146 return inst ? inst->do_persistent_varval (name) : octave_value ();
01147 }
01148
01149 static void erase_persistent (const std::string& name)
01150 {
01151 symbol_table *inst = get_instance (xcurrent_scope);
01152
01153 if (inst)
01154 inst->do_erase_persistent (name);
01155 }
01156
01157 static bool is_variable (const std::string& name)
01158 {
01159 symbol_table *inst = get_instance (xcurrent_scope);
01160
01161 return inst ? inst->do_is_variable (name) : false;
01162 }
01163
01164 static bool
01165 is_built_in_function_name (const std::string& name)
01166 {
01167 octave_value val = find_built_in_function (name);
01168
01169 return val.is_defined ();
01170 }
01171
01172 static octave_value
01173 find_method (const std::string& name, const std::string& dispatch_type)
01174 {
01175 fcn_table_const_iterator p = fcn_table.find (name);
01176
01177 if (p != fcn_table.end ())
01178 return p->second.find_method (dispatch_type);
01179 else
01180 {
01181 fcn_info finfo (name);
01182
01183 octave_value fcn = finfo.find_method (dispatch_type);
01184
01185 if (fcn.is_defined ())
01186 fcn_table[name] = finfo;
01187
01188 return fcn;
01189 }
01190 }
01191
01192 static octave_value
01193 find_built_in_function (const std::string& name)
01194 {
01195 fcn_table_const_iterator p = fcn_table.find (name);
01196
01197 return (p != fcn_table.end ())
01198 ? p->second.find_built_in_function () : octave_value ();
01199 }
01200
01201 static octave_value
01202 find_autoload (const std::string& name)
01203 {
01204 fcn_table_iterator p = fcn_table.find (name);
01205
01206 return (p != fcn_table.end ())
01207 ? p->second.find_autoload () : octave_value ();
01208 }
01209
01210 static octave_value
01211 find_function (const std::string& name,
01212 const octave_value_list& args = octave_value_list (),
01213 bool local_funcs = true);
01214
01215 static octave_value find_user_function (const std::string& name)
01216 {
01217 fcn_table_iterator p = fcn_table.find (name);
01218
01219 return (p != fcn_table.end ())
01220 ? p->second.find_user_function () : octave_value ();
01221 }
01222
01223 static void install_cmdline_function (const std::string& name,
01224 const octave_value& fcn)
01225 {
01226 fcn_table_iterator p = fcn_table.find (name);
01227
01228 if (p != fcn_table.end ())
01229 {
01230 fcn_info& finfo = p->second;
01231
01232 finfo.install_cmdline_function (fcn);
01233 }
01234 else
01235 {
01236 fcn_info finfo (name);
01237
01238 finfo.install_cmdline_function (fcn);
01239
01240 fcn_table[name] = finfo;
01241 }
01242 }
01243
01244 static void install_subfunction (const std::string& name,
01245 const octave_value& fcn,
01246 scope_id scope)
01247 {
01248 fcn_table_iterator p = fcn_table.find (name);
01249
01250 if (p != fcn_table.end ())
01251 {
01252 fcn_info& finfo = p->second;
01253
01254 finfo.install_subfunction (fcn, scope);
01255 }
01256 else
01257 {
01258 fcn_info finfo (name);
01259
01260 finfo.install_subfunction (fcn, scope);
01261
01262 fcn_table[name] = finfo;
01263 }
01264 }
01265
01266 static void install_user_function (const std::string& name,
01267 const octave_value& fcn)
01268 {
01269 fcn_table_iterator p = fcn_table.find (name);
01270
01271 if (p != fcn_table.end ())
01272 {
01273 fcn_info& finfo = p->second;
01274
01275 finfo.install_user_function (fcn);
01276 }
01277 else
01278 {
01279 fcn_info finfo (name);
01280
01281 finfo.install_user_function (fcn);
01282
01283 fcn_table[name] = finfo;
01284 }
01285 }
01286
01287 static void install_built_in_function (const std::string& name,
01288 const octave_value& fcn)
01289 {
01290 fcn_table_iterator p = fcn_table.find (name);
01291
01292 if (p != fcn_table.end ())
01293 {
01294 fcn_info& finfo = p->second;
01295
01296 finfo.install_built_in_function (fcn);
01297 }
01298 else
01299 {
01300 fcn_info finfo (name);
01301
01302 finfo.install_built_in_function (fcn);
01303
01304 fcn_table[name] = finfo;
01305 }
01306 }
01307
01308 static void clear (const std::string& name)
01309 {
01310 clear_variable (name);
01311 }
01312
01313 static void clear_all (void)
01314 {
01315 clear_variables ();
01316
01317 clear_global_pattern ("*");
01318
01319 clear_functions ();
01320 }
01321
01322 static void clear_variables (scope_id scope)
01323 {
01324 symbol_table *inst = get_instance (scope);
01325
01326 if (inst)
01327 inst->do_clear_variables ();
01328 }
01329
01330
01331 static void clear_variables (void)
01332 {
01333 clear_variables (xcurrent_scope);
01334 }
01335
01336 static void clear_objects (scope_id scope = xcurrent_scope)
01337 {
01338 symbol_table *inst = get_instance (scope);
01339
01340 if (inst)
01341 inst->do_clear_objects ();
01342 }
01343
01344 static void unmark_forced_variables (scope_id scope = xcurrent_scope)
01345 {
01346 symbol_table *inst = get_instance (scope);
01347
01348 if (inst)
01349 inst->do_unmark_forced_variables ();
01350 }
01351
01352 static void clear_functions (void)
01353 {
01354 for (fcn_table_iterator p = fcn_table.begin (); p != fcn_table.end (); p++)
01355 p->second.clear ();
01356 }
01357
01358 static void clear_function (const std::string& name)
01359 {
01360 clear_user_function (name);
01361 }
01362
01363 static void clear_global (const std::string& name)
01364 {
01365 symbol_table *inst = get_instance (xcurrent_scope);
01366
01367 if (inst)
01368 inst->do_clear_global (name);
01369 }
01370
01371 static void clear_variable (const std::string& name)
01372 {
01373 symbol_table *inst = get_instance (xcurrent_scope);
01374
01375 if (inst)
01376 inst->do_clear_variable (name);
01377 }
01378
01379 static void clear_symbol (const std::string& name)
01380 {
01381
01382
01383 clear_variable (name);
01384 clear_function (name);
01385 }
01386
01387 static void clear_function_pattern (const std::string& pat)
01388 {
01389 glob_match pattern (pat);
01390
01391 for (fcn_table_iterator p = fcn_table.begin (); p != fcn_table.end (); p++)
01392 {
01393 if (pattern.match (p->first))
01394 p->second.clear_user_function ();
01395 }
01396 }
01397
01398 static void clear_global_pattern (const std::string& pat)
01399 {
01400 symbol_table *inst = get_instance (xcurrent_scope);
01401
01402 if (inst)
01403 inst->do_clear_global_pattern (pat);
01404 }
01405
01406 static void clear_variable_pattern (const std::string& pat)
01407 {
01408 symbol_table *inst = get_instance (xcurrent_scope);
01409
01410 if (inst)
01411 inst->do_clear_variable_pattern (pat);
01412 }
01413
01414 static void clear_variable_regexp (const std::string& pat)
01415 {
01416 symbol_table *inst = get_instance (xcurrent_scope);
01417
01418 if (inst)
01419 inst->do_clear_variable_regexp (pat);
01420 }
01421
01422 static void clear_symbol_pattern (const std::string& pat)
01423 {
01424
01425
01426 clear_variable_pattern (pat);
01427 clear_function_pattern (pat);
01428 }
01429
01430 static void clear_user_function (const std::string& name)
01431 {
01432 fcn_table_iterator p = fcn_table.find (name);
01433
01434 if (p != fcn_table.end ())
01435 {
01436 fcn_info& finfo = p->second;
01437
01438 finfo.clear_user_function ();
01439 }
01440
01441
01442
01443 }
01444
01445
01446 static void clear_dld_function (const std::string& name)
01447 {
01448 fcn_table_iterator p = fcn_table.find (name);
01449
01450 if (p != fcn_table.end ())
01451 {
01452 fcn_info& finfo = p->second;
01453
01454 finfo.clear_autoload_function ();
01455 finfo.clear_user_function ();
01456 }
01457 }
01458
01459 static void clear_mex_functions (void)
01460 {
01461 for (fcn_table_iterator p = fcn_table.begin (); p != fcn_table.end (); p++)
01462 {
01463 fcn_info& finfo = p->second;
01464
01465 finfo.clear_mex_function ();
01466 }
01467 }
01468
01469 static bool set_class_relationship (const std::string& sup_class,
01470 const std::string& inf_class);
01471
01472 static bool is_superiorto (const std::string& a, const std::string& b);
01473
01474 static void alias_built_in_function (const std::string& alias,
01475 const std::string& name)
01476 {
01477 octave_value fcn = find_built_in_function (name);
01478
01479 if (fcn.is_defined ())
01480 {
01481 fcn_info finfo (alias);
01482
01483 finfo.install_built_in_function (fcn);
01484
01485 fcn_table[alias] = finfo;
01486 }
01487 else
01488 panic ("alias: '%s' is undefined", name.c_str ());
01489 }
01490
01491 static void add_dispatch (const std::string& name, const std::string& type,
01492 const std::string& fname)
01493 {
01494 fcn_table_iterator p = fcn_table.find (name);
01495
01496 if (p != fcn_table.end ())
01497 {
01498 fcn_info& finfo = p->second;
01499
01500 finfo.add_dispatch (type, fname);
01501 }
01502 else
01503 {
01504 fcn_info finfo (name);
01505
01506 finfo.add_dispatch (type, fname);
01507
01508 fcn_table[name] = finfo;
01509 }
01510 }
01511
01512 static void clear_dispatch (const std::string& name, const std::string& type)
01513 {
01514 fcn_table_iterator p = fcn_table.find (name);
01515
01516 if (p != fcn_table.end ())
01517 {
01518 fcn_info& finfo = p->second;
01519
01520 finfo.clear_dispatch (type);
01521 }
01522 }
01523
01524 static void print_dispatch (std::ostream& os, const std::string& name)
01525 {
01526 fcn_table_iterator p = fcn_table.find (name);
01527
01528 if (p != fcn_table.end ())
01529 {
01530 fcn_info& finfo = p->second;
01531
01532 finfo.print_dispatch (os);
01533 }
01534 }
01535
01536 static fcn_info::dispatch_map_type get_dispatch (const std::string& name)
01537 {
01538 fcn_info::dispatch_map_type retval;
01539
01540 fcn_table_iterator p = fcn_table.find (name);
01541
01542 if (p != fcn_table.end ())
01543 {
01544 fcn_info& finfo = p->second;
01545
01546 retval = finfo.get_dispatch ();
01547 }
01548
01549 return retval;
01550 }
01551
01552 static std::string help_for_dispatch (const std::string& name)
01553 {
01554 std::string retval;
01555
01556 fcn_table_iterator p = fcn_table.find (name);
01557
01558 if (p != fcn_table.end ())
01559 {
01560 fcn_info& finfo = p->second;
01561
01562 retval = finfo.help_for_dispatch ();
01563 }
01564
01565 return retval;
01566 }
01567
01568 static void push_context (void)
01569 {
01570 if (xcurrent_scope == xglobal_scope || xcurrent_scope == xtop_scope)
01571 error ("invalid call to xymtab::push_context");
01572 else
01573 {
01574 symbol_table *inst = get_instance (xcurrent_scope);
01575
01576 if (inst)
01577 inst->do_push_context ();
01578 }
01579 }
01580
01581 static void pop_context (void)
01582 {
01583 if (xcurrent_scope == xglobal_scope || xcurrent_scope == xtop_scope)
01584 error ("invalid call to xymtab::pop_context");
01585 else
01586 {
01587 symbol_table *inst = get_instance (xcurrent_scope);
01588
01589 if (inst)
01590 inst->do_pop_context ();
01591 }
01592 }
01593
01594
01595 static void pop_context (void *) { pop_context (); }
01596
01597 static void mark_automatic (const std::string& name)
01598 {
01599 symbol_table *inst = get_instance (xcurrent_scope);
01600
01601 if (inst)
01602 inst->do_mark_automatic (name);
01603 }
01604
01605 static void mark_hidden (const std::string& name)
01606 {
01607 symbol_table *inst = get_instance (xcurrent_scope);
01608
01609 if (inst)
01610 inst->do_mark_hidden (name);
01611 }
01612
01613 static void mark_global (const std::string& name)
01614 {
01615 symbol_table *inst = get_instance (xcurrent_scope);
01616
01617 if (inst)
01618 inst->do_mark_global (name);
01619 }
01620
01621 static std::list<symbol_record>
01622 all_variables (scope_id scope = xcurrent_scope,
01623 context_id context = xcurrent_context,
01624 bool defined_only = true)
01625 {
01626 symbol_table *inst = get_instance (scope);
01627
01628 return inst
01629 ? inst->do_all_variables (context, defined_only) : std::list<symbol_record> ();
01630 }
01631
01632 static std::list<symbol_record> glob (const std::string& pattern)
01633 {
01634 symbol_table *inst = get_instance (xcurrent_scope);
01635
01636 return inst ? inst->do_glob (pattern) : std::list<symbol_record> ();
01637 }
01638
01639 static std::list<symbol_record> regexp (const std::string& pattern)
01640 {
01641 symbol_table *inst = get_instance (xcurrent_scope);
01642
01643 return inst ? inst->do_regexp (pattern) : std::list<symbol_record> ();
01644 }
01645
01646 static std::list<symbol_record> glob_variables (const std::string& pattern)
01647 {
01648 symbol_table *inst = get_instance (xcurrent_scope);
01649
01650 return inst ? inst->do_glob (pattern, true) : std::list<symbol_record> ();
01651 }
01652
01653 static std::list<symbol_record> regexp_variables (const std::string& pattern)
01654 {
01655 symbol_table *inst = get_instance (xcurrent_scope);
01656
01657 return inst ? inst->do_regexp (pattern, true) : std::list<symbol_record> ();
01658 }
01659
01660 static std::list<symbol_record>
01661 glob_global_variables (const std::string& pattern)
01662 {
01663 std::list<symbol_record> retval;
01664
01665 glob_match pat (pattern);
01666
01667 for (global_table_const_iterator p = global_table.begin ();
01668 p != global_table.end (); p++)
01669 {
01670
01671
01672
01673
01674 if (pat.match (p->first))
01675 retval.push_back (symbol_record (p->first, p->second,
01676 symbol_record::global));
01677 }
01678
01679 return retval;
01680 }
01681
01682 static std::list<symbol_record>
01683 regexp_global_variables (const std::string& pattern)
01684 {
01685 std::list<symbol_record> retval;
01686
01687 ::regexp pat (pattern);
01688
01689 for (global_table_const_iterator p = global_table.begin ();
01690 p != global_table.end (); p++)
01691 {
01692
01693
01694
01695
01696 if (pat.is_match (p->first))
01697 retval.push_back (symbol_record (p->first, p->second,
01698 symbol_record::global));
01699 }
01700
01701 return retval;
01702 }
01703
01704 static std::list<symbol_record> glob_variables (const string_vector& patterns)
01705 {
01706 std::list<symbol_record> retval;
01707
01708 size_t len = patterns.length ();
01709
01710 for (size_t i = 0; i < len; i++)
01711 {
01712 std::list<symbol_record> tmp = glob_variables (patterns[i]);
01713
01714 retval.insert (retval.begin (), tmp.begin (), tmp.end ());
01715 }
01716
01717 return retval;
01718 }
01719
01720 static std::list<symbol_record> regexp_variables
01721 (const string_vector& patterns)
01722 {
01723 std::list<symbol_record> retval;
01724
01725 size_t len = patterns.length ();
01726
01727 for (size_t i = 0; i < len; i++)
01728 {
01729 std::list<symbol_record> tmp = regexp_variables (patterns[i]);
01730
01731 retval.insert (retval.begin (), tmp.begin (), tmp.end ());
01732 }
01733
01734 return retval;
01735 }
01736
01737 static std::list<std::string> user_function_names (void)
01738 {
01739 std::list<std::string> retval;
01740
01741 for (fcn_table_iterator p = fcn_table.begin ();
01742 p != fcn_table.end (); p++)
01743 {
01744 if (p->second.is_user_function_defined ())
01745 retval.push_back (p->first);
01746 }
01747
01748 if (! retval.empty ())
01749 retval.sort ();
01750
01751 return retval;
01752 }
01753
01754 static std::list<std::string> global_variable_names (void)
01755 {
01756 std::list<std::string> retval;
01757
01758 for (global_table_const_iterator p = global_table.begin ();
01759 p != global_table.end (); p++)
01760 retval.push_back (p->first);
01761
01762 retval.sort ();
01763
01764 return retval;
01765 }
01766
01767 static std::list<std::string> top_level_variable_names (void)
01768 {
01769 symbol_table *inst = get_instance (xtop_scope);
01770
01771 return inst ? inst->do_variable_names () : std::list<std::string> ();
01772 }
01773
01774 static std::list<std::string> variable_names (void)
01775 {
01776 symbol_table *inst = get_instance (xcurrent_scope);
01777
01778 return inst ? inst->do_variable_names () : std::list<std::string> ();
01779 }
01780
01781 static std::list<std::string> built_in_function_names (void)
01782 {
01783 std::list<std::string> retval;
01784
01785 for (fcn_table_const_iterator p = fcn_table.begin ();
01786 p != fcn_table.end (); p++)
01787 {
01788 octave_value fcn = p->second.find_built_in_function ();
01789
01790 if (fcn.is_defined ())
01791 retval.push_back (p->first);
01792 }
01793
01794 if (! retval.empty ())
01795 retval.sort ();
01796
01797 return retval;
01798 }
01799
01800 static std::list<std::string> cmdline_function_names (void)
01801 {
01802 std::list<std::string> retval;
01803
01804 for (fcn_table_const_iterator p = fcn_table.begin ();
01805 p != fcn_table.end (); p++)
01806 {
01807 octave_value fcn = p->second.find_cmdline_function ();
01808
01809 if (fcn.is_defined ())
01810 retval.push_back (p->first);
01811 }
01812
01813 if (! retval.empty ())
01814 retval.sort ();
01815
01816 return retval;
01817 }
01818
01819 static bool is_local_variable (const std::string& name)
01820 {
01821 if (xcurrent_scope == xglobal_scope)
01822 return false;
01823 else
01824 {
01825 symbol_table *inst = get_instance (xcurrent_scope);
01826
01827 return inst ? inst->do_is_local_variable (name) : false;
01828 }
01829 }
01830
01831 static bool is_global (const std::string& name)
01832 {
01833 if (xcurrent_scope == xglobal_scope)
01834 return true;
01835 else
01836 {
01837 symbol_table *inst = get_instance (xcurrent_scope);
01838
01839 return inst ? inst->do_is_global (name) : false;
01840 }
01841 }
01842
01843 static void dump (std::ostream& os, scope_id scope = xcurrent_scope);
01844
01845 static void dump_global (std::ostream& os);
01846
01847 static void dump_functions (std::ostream& os);
01848
01849 static void cache_name (scope_id scope, const std::string& name)
01850 {
01851 symbol_table *inst = get_instance (scope, false);
01852
01853 if (inst)
01854 inst->do_cache_name (name);
01855 }
01856
01857 static void lock_subfunctions (scope_id scope = xcurrent_scope)
01858 {
01859 for (fcn_table_iterator p = fcn_table.begin ();
01860 p != fcn_table.end (); p++)
01861 p->second.lock_subfunction (scope);
01862 }
01863
01864 static void unlock_subfunctions (scope_id scope = xcurrent_scope)
01865 {
01866 for (fcn_table_iterator p = fcn_table.begin ();
01867 p != fcn_table.end (); p++)
01868 p->second.unlock_subfunction (scope);
01869 }
01870
01871 static void free_scope (scope_id scope)
01872 {
01873 if (scope == xglobal_scope || scope == xtop_scope)
01874 error ("can't free global or top-level scopes!");
01875 else
01876 symbol_table::scope_id_cache::free (scope);
01877 }
01878
01879 static void stash_dir_name_for_subfunctions (scope_id scope,
01880 const std::string& dir_name);
01881
01882 static void add_to_parent_map (const std::string& classname,
01883 const std::list<std::string>& parent_list)
01884 {
01885 parent_map[classname] = parent_list;
01886 }
01887
01888 static std::list<std::string>
01889 parent_classes (const std::string& dispatch_type)
01890 {
01891 std::list<std::string> retval;
01892
01893 const_parent_map_iterator it = parent_map.find (dispatch_type);
01894
01895 if (it != parent_map.end ())
01896 retval = it->second;
01897
01898 for (std::list<std::string>::const_iterator lit = retval.begin ();
01899 lit != retval.end (); lit++)
01900 {
01901
01902
01903
01904
01905 std::list<std::string> parents = parent_classes (*lit);
01906
01907 if (! parents.empty ())
01908 retval.insert (retval.end (), parents.begin (), parents.end ());
01909 }
01910
01911 return retval;
01912 }
01913
01914 static octave_user_function *get_curr_fcn (scope_id scope = xcurrent_scope)
01915 {
01916 symbol_table *inst = get_instance (scope);
01917 return inst->curr_fcn;
01918 }
01919
01920 static void set_curr_fcn (octave_user_function *curr_fcn,
01921 scope_id scope = xcurrent_scope)
01922 {
01923 assert (scope != xtop_scope && scope != xglobal_scope);
01924 symbol_table *inst = get_instance (scope);
01925
01926
01927
01928 assert (inst->curr_fcn == 0 || curr_fcn == 0);
01929 inst->curr_fcn = curr_fcn;
01930 }
01931
01932 static void cleanup (void);
01933
01934 private:
01935
01936
01937
01938 symbol_table (const symbol_table&);
01939
01940 symbol_table& operator = (const symbol_table&);
01941
01942 typedef std::map<std::string, symbol_record>::const_iterator table_const_iterator;
01943 typedef std::map<std::string, symbol_record>::iterator table_iterator;
01944
01945 typedef std::map<std::string, octave_value>::const_iterator global_table_const_iterator;
01946 typedef std::map<std::string, octave_value>::iterator global_table_iterator;
01947
01948 typedef std::map<std::string, octave_value>::const_iterator persistent_table_const_iterator;
01949 typedef std::map<std::string, octave_value>::iterator persistent_table_iterator;
01950
01951 typedef std::map<scope_id, symbol_table*>::const_iterator all_instances_const_iterator;
01952 typedef std::map<scope_id, symbol_table*>::iterator all_instances_iterator;
01953
01954 typedef std::map<std::string, fcn_info>::const_iterator fcn_table_const_iterator;
01955 typedef std::map<std::string, fcn_info>::iterator fcn_table_iterator;
01956
01957
01958
01959 std::string table_name;
01960
01961
01962 std::map<std::string, symbol_record> table;
01963
01964
01965 octave_user_function *curr_fcn;
01966
01967
01968 static std::map<std::string, octave_value> global_table;
01969
01970
01971 std::map<std::string, octave_value> persistent_table;
01972
01973
01974 static symbol_table *instance;
01975
01976
01977 static std::map<scope_id, symbol_table*> all_instances;
01978
01979
01980
01981 static std::map<std::string, fcn_info> fcn_table;
01982
01983
01984
01985 static std::map<std::string, std::set<std::string> > class_precedence_table;
01986
01987 typedef std::map<std::string, std::set<std::string> >::const_iterator class_precedence_table_const_iterator;
01988 typedef std::map<std::string, std::set<std::string> >::iterator class_precedence_table_iterator;
01989
01990
01991 static std::map<std::string, std::list<std::string> > parent_map;
01992
01993 typedef std::map<std::string, std::list<std::string> >::const_iterator const_parent_map_iterator;
01994 typedef std::map<std::string, std::list<std::string> >::iterator parent_map_iterator;
01995
01996 static const scope_id xglobal_scope;
01997 static const scope_id xtop_scope;
01998
01999 static scope_id xcurrent_scope;
02000
02001 static context_id xcurrent_context;
02002
02003 symbol_table (void)
02004 : table_name (), table (), curr_fcn (0), persistent_table () { }
02005
02006 ~symbol_table (void) { }
02007
02008 static symbol_table *get_instance (scope_id scope, bool create = true)
02009 {
02010 symbol_table *retval = 0;
02011
02012 bool ok = true;
02013
02014 if (scope != xglobal_scope)
02015 {
02016 if (scope == xcurrent_scope)
02017 {
02018 if (! instance && create)
02019 {
02020 symbol_table *inst = new symbol_table ();
02021
02022 if (inst)
02023 {
02024 all_instances[scope] = instance = inst;
02025
02026 if (scope == xtop_scope)
02027 instance->do_cache_name ("top-level");
02028 }
02029 }
02030
02031 if (! instance)
02032 ok = false;
02033
02034 retval = instance;
02035 }
02036 else
02037 {
02038 all_instances_iterator p = all_instances.find (scope);
02039
02040 if (p == all_instances.end ())
02041 {
02042 if (create)
02043 {
02044 retval = new symbol_table ();
02045
02046 if (retval)
02047 all_instances[scope] = retval;
02048 else
02049 ok = false;
02050 }
02051 else
02052 ok = false;
02053 }
02054 else
02055 retval = p->second;
02056 }
02057 }
02058
02059 if (! ok)
02060 error ("unable to %s symbol_table object for scope %d!",
02061 create ? "create" : "find", scope);
02062
02063 return retval;
02064 }
02065
02066 void insert_symbol_record (const symbol_record& sr)
02067 {
02068 table[sr.name ()] = sr;
02069 }
02070
02071 void
02072 do_dup_scope (symbol_table& new_symbol_table) const
02073 {
02074 for (table_const_iterator p = table.begin (); p != table.end (); p++)
02075 new_symbol_table.insert_symbol_record (p->second.dup ());
02076 }
02077
02078 symbol_record do_find_symbol (const std::string& name)
02079 {
02080 table_iterator p = table.find (name);
02081
02082 if (p == table.end ())
02083 return do_insert (name);
02084 else
02085 return p->second;
02086 }
02087
02088 void do_inherit (symbol_table& donor_table, context_id donor_context)
02089 {
02090 for (table_iterator p = table.begin (); p != table.end (); p++)
02091 {
02092 symbol_record& sr = p->second;
02093
02094 if (! (sr.is_automatic () || sr.is_formal ()))
02095 {
02096 std::string nm = sr.name ();
02097
02098 if (nm != "__retval__")
02099 {
02100 octave_value val = donor_table.do_varval (nm, donor_context);
02101
02102 if (val.is_defined ())
02103 {
02104 sr.varref (0) = val;
02105
02106 sr.mark_inherited ();
02107 }
02108 }
02109 }
02110 }
02111 }
02112
02113 static fcn_info *get_fcn_info (const std::string& name)
02114 {
02115 fcn_table_iterator p = fcn_table.find (name);
02116 return p != fcn_table.end () ? &p->second : 0;
02117 }
02118
02119 octave_value
02120 do_find (const std::string& name, const octave_value_list& args,
02121 bool skip_variables, bool local_funcs);
02122
02123 octave_value do_builtin_find (const std::string& name);
02124
02125 symbol_record& do_insert (const std::string& name)
02126 {
02127 table_iterator p = table.find (name);
02128
02129 return p == table.end ()
02130 ? (table[name] = symbol_record (name)) : p->second;
02131 }
02132
02133 void do_force_variable (const std::string& name, context_id context)
02134 {
02135 table_iterator p = table.find (name);
02136
02137 if (p == table.end ())
02138 {
02139 symbol_record& sr = do_insert (name);
02140
02141 sr.force_variable (context);
02142 }
02143 else
02144 p->second.force_variable (context);
02145 }
02146
02147 octave_value& do_varref (const std::string& name, context_id context)
02148 {
02149 table_iterator p = table.find (name);
02150
02151 if (p == table.end ())
02152 {
02153 symbol_record& sr = do_insert (name);
02154
02155 return sr.varref (context);
02156 }
02157 else
02158 return p->second.varref (context);
02159 }
02160
02161 octave_value do_varval (const std::string& name, context_id context) const
02162 {
02163 table_const_iterator p = table.find (name);
02164
02165 return (p != table.end ()) ? p->second.varval (context) : octave_value ();
02166 }
02167
02168 octave_value& do_persistent_varref (const std::string& name)
02169 {
02170 persistent_table_iterator p = persistent_table.find (name);
02171
02172 return (p == persistent_table.end ())
02173 ? persistent_table[name] : p->second;
02174 }
02175
02176 octave_value do_persistent_varval (const std::string& name)
02177 {
02178 persistent_table_const_iterator p = persistent_table.find (name);
02179
02180 return (p != persistent_table.end ()) ? p->second : octave_value ();
02181 }
02182
02183 void do_erase_persistent (const std::string& name)
02184 {
02185 persistent_table_iterator p = persistent_table.find (name);
02186
02187 if (p != persistent_table.end ())
02188 persistent_table.erase (p);
02189 }
02190
02191 bool do_is_variable (const std::string& name) const
02192 {
02193 bool retval = false;
02194
02195 table_const_iterator p = table.find (name);
02196
02197 if (p != table.end ())
02198 {
02199 const symbol_record& sr = p->second;
02200
02201 retval = sr.is_variable ();
02202 }
02203
02204 return retval;
02205 }
02206
02207 void do_push_context (void)
02208 {
02209 for (table_iterator p = table.begin (); p != table.end (); p++)
02210 p->second.push_context ();
02211 }
02212
02213 void do_pop_context (void)
02214 {
02215 for (table_iterator p = table.begin (); p != table.end (); )
02216 {
02217 if (p->second.pop_context () == 0)
02218 table.erase (p++);
02219 else
02220 p++;
02221 }
02222 }
02223
02224 void do_clear_variables (void)
02225 {
02226 for (table_iterator p = table.begin (); p != table.end (); p++)
02227 p->second.clear ();
02228 }
02229
02230 void do_clear_objects (void)
02231 {
02232 for (table_iterator p = table.begin (); p != table.end (); p++)
02233 {
02234 symbol_record& sr = p->second;
02235 octave_value& val = sr.varref ();
02236 if (val.is_object())
02237 p->second.clear ();
02238 }
02239 }
02240
02241 void do_unmark_forced_variables (void)
02242 {
02243 for (table_iterator p = table.begin (); p != table.end (); p++)
02244 p->second.unmark_forced ();
02245 }
02246
02247 void do_clear_global (const std::string& name)
02248 {
02249 table_iterator p = table.find (name);
02250
02251 if (p != table.end ())
02252 {
02253 symbol_record& sr = p->second;
02254
02255 if (sr.is_global ())
02256 sr.unmark_global ();
02257 }
02258
02259 global_table_iterator q = global_table.find (name);
02260
02261 if (q != global_table.end ())
02262 global_table.erase (q);
02263
02264 }
02265
02266 void do_clear_variable (const std::string& name)
02267 {
02268 table_iterator p = table.find (name);
02269
02270 if (p != table.end ())
02271 p->second.clear ();
02272 }
02273
02274 void do_clear_global_pattern (const std::string& pat)
02275 {
02276 glob_match pattern (pat);
02277
02278 for (table_iterator p = table.begin (); p != table.end (); p++)
02279 {
02280 symbol_record& sr = p->second;
02281
02282 if (sr.is_global () && pattern.match (sr.name ()))
02283 sr.unmark_global ();
02284 }
02285
02286
02287 for (global_table_iterator q = global_table.begin ();
02288 q != global_table.end ();)
02289 {
02290 if (pattern.match (q->first))
02291 global_table.erase (q++);
02292
02293 else
02294 q++;
02295 }
02296
02297
02298 }
02299
02300 void do_clear_variable_pattern (const std::string& pat)
02301 {
02302 glob_match pattern (pat);
02303
02304 for (table_iterator p = table.begin (); p != table.end (); p++)
02305 {
02306 symbol_record& sr = p->second;
02307
02308 if (sr.is_defined () || sr.is_global ())
02309 {
02310 if (pattern.match (sr.name ()))
02311 sr.clear ();
02312 }
02313 }
02314 }
02315
02316 void do_clear_variable_regexp (const std::string& pat)
02317 {
02318 ::regexp pattern (pat);
02319
02320 for (table_iterator p = table.begin (); p != table.end (); p++)
02321 {
02322 symbol_record& sr = p->second;
02323
02324 if (sr.is_defined () || sr.is_global ())
02325 {
02326 if (pattern.is_match (sr.name ()))
02327 sr.clear ();
02328 }
02329 }
02330 }
02331
02332 void do_mark_automatic (const std::string& name)
02333 {
02334 do_insert (name).mark_automatic ();
02335 }
02336
02337 void do_mark_hidden (const std::string& name)
02338 {
02339 do_insert (name).mark_hidden ();
02340 }
02341
02342 void do_mark_global (const std::string& name)
02343 {
02344 do_insert (name).mark_global ();
02345 }
02346
02347 std::list<symbol_record>
02348 do_all_variables (context_id context, bool defined_only) const
02349 {
02350 std::list<symbol_record> retval;
02351
02352 for (table_const_iterator p = table.begin (); p != table.end (); p++)
02353 {
02354 const symbol_record& sr = p->second;
02355
02356 if (defined_only && ! sr.is_defined (context))
02357 continue;
02358
02359 retval.push_back (sr);
02360 }
02361
02362 return retval;
02363 }
02364
02365 std::list<symbol_record> do_glob (const std::string& pattern,
02366 bool vars_only = false) const
02367 {
02368 std::list<symbol_record> retval;
02369
02370 glob_match pat (pattern);
02371
02372 for (table_const_iterator p = table.begin (); p != table.end (); p++)
02373 {
02374 if (pat.match (p->first))
02375 {
02376 const symbol_record& sr = p->second;
02377
02378 if (vars_only && ! sr.is_variable ())
02379 continue;
02380
02381 retval.push_back (sr);
02382 }
02383 }
02384
02385 return retval;
02386 }
02387
02388 std::list<symbol_record> do_regexp (const std::string& pattern,
02389 bool vars_only = false) const
02390 {
02391 std::list<symbol_record> retval;
02392
02393 ::regexp pat (pattern);
02394
02395 for (table_const_iterator p = table.begin (); p != table.end (); p++)
02396 {
02397 if (pat.is_match (p->first))
02398 {
02399 const symbol_record& sr = p->second;
02400
02401 if (vars_only && ! sr.is_variable ())
02402 continue;
02403
02404 retval.push_back (sr);
02405 }
02406 }
02407
02408 return retval;
02409 }
02410
02411 std::list<std::string> do_variable_names (void)
02412 {
02413 std::list<std::string> retval;
02414
02415 for (table_const_iterator p = table.begin (); p != table.end (); p++)
02416 {
02417 if (p->second.is_variable ())
02418 retval.push_back (p->first);
02419 }
02420
02421 retval.sort ();
02422
02423 return retval;
02424 }
02425
02426 static std::map<std::string, octave_value>
02427 subfunctions_defined_in_scope (scope_id scope = xcurrent_scope)
02428 {
02429 std::map<std::string, octave_value> retval;
02430
02431 for (fcn_table_const_iterator p = fcn_table.begin ();
02432 p != fcn_table.end (); p++)
02433 {
02434 std::pair<std::string, octave_value> tmp
02435 = p->second.subfunction_defined_in_scope (scope);
02436
02437 std::string nm = tmp.first;
02438
02439 if (! nm.empty ())
02440 retval[nm] = tmp.second;
02441 }
02442
02443 return retval;
02444 }
02445
02446 bool do_is_local_variable (const std::string& name) const
02447 {
02448 table_const_iterator p = table.find (name);
02449
02450 return (p != table.end ()
02451 && ! p->second.is_global ()
02452 && p->second.is_defined ());
02453 }
02454
02455 bool do_is_global (const std::string& name) const
02456 {
02457 table_const_iterator p = table.find (name);
02458
02459 return p != table.end () && p->second.is_global ();
02460 }
02461
02462 void do_dump (std::ostream& os);
02463
02464 void do_cache_name (const std::string& name) { table_name = name; }
02465 };
02466
02467 extern bool out_of_date_check (octave_value& function,
02468 const std::string& dispatch_type = std::string (),
02469 bool check_relative = true);
02470
02471 extern OCTINTERP_API std::string
02472 get_dispatch_type (const octave_value_list& args);
02473 extern OCTINTERP_API std::string
02474 get_dispatch_type (const octave_value_list& args, builtin_type_t& builtin_type);
02475
02476 #endif