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