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