comparison src/symtab.h @ 7336:745a8299c2b5

[project @ 2007-12-28 20:56:55 by jwe]
author jwe
date Fri, 28 Dec 2007 20:56:58 +0000
parents 88417316c1b0
children 40252ccfcb67
comparison
equal deleted inserted replaced
7335:58f5fab3ebe5 7336:745a8299c2b5
1 /* 1 /*
2 2
3 Copyright (C) 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2002, 2003, 3 Copyright (C) 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2002, 2003,
4 2004, 2005, 2006, 2007 John W. Eaton 4 2004, 2005, 2006, 2007 John W. Eaton
5 5
6 This file is part of Octave. 6 This file is part of Octave.
7 7
8 Octave is free software; you can redistribute it and/or modify it 8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the 9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your 10 Free Software Foundation; either version 3 of the License, or (at your
22 */ 22 */
23 23
24 #if !defined (octave_symtab_h) 24 #if !defined (octave_symtab_h)
25 #define octave_symtab_h 1 25 #define octave_symtab_h 1
26 26
27 #include <cassert> 27 #include <deque>
28 28 #include <list>
29 #include <map>
30 #include <set>
31 #include <stack>
29 #include <string> 32 #include <string>
30 #include <stack> 33
31 #include <sstream> 34 #include "glob-match.h"
32 35
33 #include "oct-alloc.h" 36 class tree_argument_list;
34 #include "str-vec.h" 37
35 38 #include "oct-obj.h"
36 #include "ov.h" 39 #include "ov.h"
37
38 class octave_lvalue;
39
40 class string_vector;
41
42 class symbol_record;
43 class symbol_table;
44
45 struct
46 whos_parameter
47 {
48 char command;
49 char modifier;
50 int parameter_length;
51 int first_parameter_length;
52 int dimensions;
53 int balance;
54 std::string text;
55 std::string line;
56 };
57
58 // Individual records in a symbol table.
59
60 class
61 OCTINTERP_API
62 symbol_record
63 {
64 public:
65
66 // If you add or delete an entry here, you'll also need to change
67 // the width parameter in the declaration for symbol_type below...
68
69 enum TYPE
70 {
71 UNKNOWN = 0,
72 USER_FUNCTION = 1,
73 USER_VARIABLE = 2,
74 DLD_FUNCTION = 4,
75 BUILTIN_FUNCTION = 8,
76 COMMAND = 16,
77 RAWCOMMAND = 32,
78 MAPPER_FUNCTION = 64,
79 MEX_FUNCTION = 128
80 };
81
82 private:
83
84 // Variables or functions.
85
86 class symbol_def
87 {
88 public:
89
90 symbol_def (const octave_value& val = octave_value (),
91 unsigned int sym_type = 0)
92 : symbol_type (sym_type), read_only (0), help_string (),
93 definition (val), count (1) { }
94
95 ~symbol_def (void) { }
96
97 bool is_variable (void) const
98 { return (symbol_type & symbol_record::USER_VARIABLE); }
99
100 // It's not necessary to check for COMMAND and MAPPER_FUNCTION
101 // here. Those tags are just used as additional qualifiers for
102 // the other types of functions.
103
104 bool is_function (void) const
105 {
106 return (symbol_type & symbol_record::USER_FUNCTION
107 || symbol_type & symbol_record::DLD_FUNCTION
108 || symbol_type & symbol_record::MEX_FUNCTION
109 || symbol_type & symbol_record::BUILTIN_FUNCTION);
110 }
111
112 bool is_user_variable (void) const
113 { return (symbol_type & symbol_record::USER_VARIABLE); }
114
115 // Don't use |= here to avoid error with AIX compiler.
116 void mark_as_command (void)
117 { symbol_type = symbol_type | symbol_record::COMMAND; }
118
119 void unmark_command (void)
120 { symbol_type &= ~symbol_record::COMMAND; }
121
122 bool is_command (void) const
123 { return (symbol_type & symbol_record::COMMAND); }
124
125 void mark_as_rawcommand (void)
126 { symbol_type |= (symbol_record::COMMAND
127 | symbol_record::RAWCOMMAND); }
128
129 void unmark_rawcommand (void)
130 { symbol_type &= ~symbol_record::RAWCOMMAND; }
131
132 bool is_rawcommand (void) const
133 { return (symbol_type & symbol_record::RAWCOMMAND); }
134
135 bool is_mapper_function (void) const
136 { return (symbol_type & symbol_record::MAPPER_FUNCTION); }
137
138 bool is_user_function (void) const
139 { return (symbol_type & symbol_record::USER_FUNCTION); }
140
141 bool is_builtin_function (void) const
142 { return (symbol_type & symbol_record::BUILTIN_FUNCTION); }
143
144 bool is_dld_function (void) const
145 { return (symbol_type & symbol_record::DLD_FUNCTION); }
146
147 bool is_mex_function (void) const
148 { return (symbol_type & symbol_record::MEX_FUNCTION); }
149
150 // FIXME
151 bool is_map_element (const std::string& /* elts */) const
152 { return false; }
153
154 bool is_defined (void) const
155 { return definition.is_defined (); }
156
157 bool is_read_only (void) const
158 { return read_only; }
159
160 bool is_matrix_type (void) const
161 { return definition.is_matrix_type (); }
162
163 bool is_sparse_type (void) const
164 { return definition.is_sparse_type (); }
165
166 bool is_complex_type (void) const
167 { return definition.is_complex_type (); }
168
169 std::string class_name (void) const
170 { return definition.class_name (); }
171
172 Matrix size (void) const
173 { return definition.size (); }
174
175 size_t byte_size (void) const
176 { return definition.byte_size (); };
177
178 octave_idx_type numel (void) const
179 { return definition.numel (); };
180
181 octave_idx_type capacity (void) const
182 { return definition.capacity (); };
183
184 dim_vector dims (void) const
185 { return definition.dims (); }
186
187 octave_idx_type rows (void) const { return definition.rows (); }
188 octave_idx_type columns (void) const { return definition.columns (); }
189
190 std::string type_name (void) const { return definition.type_name (); }
191
192 std::string type_as_string (void) const;
193
194 void type (std::ostream& os, const std::string& name, bool pr_type_info,
195 bool quiet, bool pr_orig_txt);
196
197 std::string which (const std::string& name);
198
199 void which (std::ostream& os, const std::string& name);
200
201 void define (const octave_value& val, unsigned int sym_type)
202 {
203 definition = val;
204 symbol_type = sym_type;
205 }
206
207 void protect (void) { read_only = 1; }
208
209 void unprotect (void) { read_only = 0; }
210
211 octave_value& def (void) { return definition; }
212
213 std::string help (void) const { return help_string; }
214
215 void document (const std::string& h);
216
217 unsigned int type (void) { return symbol_type; }
218
219 void *operator new (size_t size)
220 { return allocator.alloc (size); }
221
222 void operator delete (void *p, size_t size)
223 { allocator.free (p, size); }
224
225 static octave_allocator allocator;
226
227 // The type of this symbol (see the enum above).
228 unsigned int symbol_type : 9;
229
230 // Nonzero means this variable cannot be given a new value.
231 unsigned int read_only : 1;
232
233 // The doc string associated with this variable.
234 std::string help_string;
235
236 // The value of this definition. See ov.h and related files.
237 octave_value definition;
238
239 // Reference count.
240 int count;
241
242 void print_info (std::ostream& os,
243 const std::string& prefix = std::string ()) const;
244
245 // No copying!
246
247 symbol_def (const symbol_def& sd);
248
249 symbol_def& operator = (const symbol_def& sd);
250 };
251
252 public:
253
254 typedef int (*change_function) (void);
255
256 symbol_record (void)
257 : formal_param (false), automatic_variable (false),
258 linked_to_global (false), tagged_static (false),
259 can_hide_function (true), visible (true), eternal (false),
260 nm (), chg_fcn (0), definition (new symbol_def ()), next_elem (0) { }
261
262 // FIXME -- kluge alert! We obviously need a better way of
263 // handling allow_shadow!
264
265 symbol_record (const std::string& n, symbol_record *nxt)
266 : formal_param (false), automatic_variable (false),
267 linked_to_global (false), tagged_static (false),
268 can_hide_function (n != "__end__"), visible (true),
269 eternal (false), nm (n), chg_fcn (0),
270 definition (new symbol_def ()), next_elem (nxt) { }
271
272 ~symbol_record (void)
273 {
274 if (--definition->count <= 0)
275 delete definition;
276 }
277
278 std::string name (void) const { return nm; }
279
280 std::string help (void) const { return definition->help (); }
281
282 octave_value& def (void) { return definition->def (); }
283
284 void rename (const std::string& new_name);
285
286 bool is_function (void) const
287 { return definition->is_function (); }
288
289 void mark_as_command (void)
290 { definition->mark_as_command (); }
291
292 void unmark_command (void)
293 { definition->unmark_command (); }
294
295 bool is_command (void) const
296 { return definition->is_command (); }
297
298 void mark_as_rawcommand (void)
299 { definition->mark_as_rawcommand (); }
300
301 void unmark_rawcommand (void)
302 { definition->unmark_rawcommand (); }
303
304 bool is_rawcommand (void) const
305 { return definition->is_rawcommand (); }
306
307 bool is_mapper_function (void) const
308 { return definition->is_mapper_function (); }
309
310 bool is_user_function (void) const
311 { return definition->is_user_function (); }
312
313 bool is_builtin_function (void) const
314 { return definition->is_builtin_function (); }
315
316 bool is_dld_function (void) const
317 { return definition->is_dld_function (); }
318
319 bool is_mex_function (void) const
320 { return definition->is_mex_function (); }
321
322 bool is_variable (void) const
323 { return definition->is_variable (); }
324
325 bool is_user_variable (void) const
326 { return definition->is_user_variable (); }
327
328 bool is_map_element (const std::string& elts) const
329 { return definition->is_map_element (elts); }
330
331 unsigned int type (void) const { return definition->type (); }
332
333 bool is_defined (void) const { return definition->is_defined (); }
334
335 bool is_read_only (void) const { return definition->is_read_only (); }
336
337 bool is_eternal (void) const { return eternal; }
338
339 void protect (void) { definition->protect (); }
340
341 void unprotect (void) { definition->unprotect (); }
342
343 void make_eternal (void) { eternal = 1; }
344
345 void hide (void) { visible = false; }
346 void show (void) { visible = true; }
347 bool is_visible (void) const { return visible; }
348
349 void set_change_function (change_function f) { chg_fcn = f; }
350
351 void define (const octave_value& v, unsigned int sym_type = USER_VARIABLE);
352
353 bool define (octave_function *f, unsigned int sym_type);
354
355 void document (const std::string& h) { definition->document (h); }
356
357 void clear (void);
358
359 void alias (symbol_record *s, bool mark_to_clear = false);
360
361 void mark_as_formal_parameter (void);
362 bool is_formal_parameter (void) const { return formal_param; }
363
364 void mark_as_automatic_variable (void);
365 bool is_automatic_variable (void) const { return automatic_variable; }
366
367 void mark_as_linked_to_global (void);
368 bool is_linked_to_global (void) const { return linked_to_global; }
369
370 void mark_as_static (void);
371 bool is_static (void) const { return tagged_static; }
372 void unmark_static (void) { tagged_static = false; }
373
374 bool is_matrix_type (void) const
375 { return definition->is_matrix_type (); }
376
377 bool is_sparse_type (void) const
378 { return definition->is_sparse_type (); }
379
380 bool is_complex_type (void) const
381 { return definition->is_complex_type (); }
382
383 std::string class_name (void) const
384 { return definition->class_name (); }
385
386 Matrix size (void) const
387 { return definition->size (); }
388
389 size_t byte_size (void) const
390 { return definition->byte_size (); };
391
392 octave_idx_type numel (void) const
393 { return definition->numel (); };
394
395 octave_idx_type capacity (void) const
396 { return definition->capacity (); };
397
398 dim_vector dims (void) const { return definition->dims (); }
399
400 int dimensions_string_req_first_space (int print_dims) const;
401
402 int dimensions_string_req_total_space (int print_dims) const;
403
404 std::string make_dimensions_string (int print_dims) const;
405
406 octave_idx_type rows (void) const { return definition->rows (); }
407 octave_idx_type columns (void) const { return definition->columns (); }
408
409 std::string type_name (void) const { return definition->type_name (); }
410
411 std::string type_as_string (void) const
412 { return definition->type_as_string (); }
413
414 void type (std::ostream& os, bool pr_type_info, bool quiet, bool pr_orig_txt)
415 { definition->type (os, name (), pr_type_info, quiet, pr_orig_txt); }
416
417 std::string which (void) { return definition->which (name ()); }
418
419 void which (std::ostream& os) { definition->which (os, name ()); }
420
421 octave_value& variable_value (void);
422 octave_lvalue variable_reference (void);
423
424 symbol_record *next (void) const { return next_elem; }
425
426 void chain (symbol_record *s) { next_elem = s; }
427
428 void push_context (void);
429
430 void pop_context (void);
431
432 void print_symbol_info_line (std::ostream& os,
433 std::list<whos_parameter>& params) const;
434
435 void print_info (std::ostream& os,
436 const std::string& prefix = std::string ()) const;
437
438 private:
439
440 unsigned int formal_param : 1;
441 unsigned int automatic_variable : 1;
442 unsigned int linked_to_global : 1;
443 unsigned int tagged_static : 1;
444 unsigned int can_hide_function : 1;
445 unsigned int visible : 1;
446 unsigned int eternal : 1;
447
448 std::string nm;
449 change_function chg_fcn;
450 symbol_def *definition;
451 symbol_record *next_elem;
452
453 // This should maybe be one stack with a structure containing all the
454 // items we need to save for recursive calls...
455 std::stack <symbol_def *> context;
456 std::stack <unsigned int> global_link_context;
457
458 std::stack <symbol_record *> aliases_to_clear;
459
460 void push_alias_to_clear (symbol_record *s)
461 { aliases_to_clear.push (s); }
462
463 bool read_only_error (const char *action);
464
465 void maybe_delete_def (void)
466 {
467 if (--definition->count <= 0)
468 delete definition;
469 }
470
471 // No copying!
472
473 symbol_record (const symbol_record& s);
474
475 symbol_record& operator = (const symbol_record& s);
476 };
477
478 // A symbol table.
479
480 #define SYMTAB_LOCAL_SCOPE 1
481 #define SYMTAB_GLOBAL_SCOPE 2
482
483 #define SYMTAB_ALL_SCOPES (SYMTAB_LOCAL_SCOPE | SYMTAB_GLOBAL_SCOPE)
484
485 #define SYMTAB_ALL_TYPES (symbol_record::USER_FUNCTION \
486 | symbol_record::USER_VARIABLE \
487 | symbol_record::DLD_FUNCTION \
488 | symbol_record::BUILTIN_FUNCTION \
489 | symbol_record::COMMAND \
490 | symbol_record::RAWCOMMAND \
491 | symbol_record::MAPPER_FUNCTION \
492 | symbol_record::MEX_FUNCTION)
493
494 #define SYMTAB_VARIABLES (symbol_record::USER_VARIABLE)
495 40
496 class 41 class
497 OCTINTERP_API 42 OCTINTERP_API
498 symbol_table 43 symbol_table
499 { 44 {
500 public: 45 public:
501 46
502 symbol_table (unsigned int tab_size = 64, 47 typedef int scope_id;
503 const std::string& nm = std::string ()) 48
504 : table_size (tab_size), table (new symbol_record [table_size]), 49 class
505 table_name (nm) 50 symbol_record
506 { 51 {
507 assert ((tab_size % 2) == 0); 52 public:
508 53
509 if (table_name.empty ()) 54 // generic variable
55 static const unsigned int local = 1;
56
57 // varargin, argn, .nargin., .nargout.
58 // (FIXME -- is this really used now?)
59 static const unsigned int automatic = 2;
60
61 // formal parameter
62 static const unsigned int formal = 4;
63
64 // not listed or cleared (.nargin., .nargout.)
65 static const unsigned int hidden = 8;
66
67 // inherited from parent scope; not cleared at function exit
68 static const unsigned int inherited = 16;
69
70 // global (redirects to global scope)
71 static const unsigned int global = 32;
72
73 // not cleared at function exit
74 static const unsigned int persistent = 64;
75
76 private:
77
78 class
79 symbol_record_rep
80 {
81 public:
82
83 symbol_record_rep (const std::string& nm, const octave_value& v,
84 unsigned int sc)
85 : name (nm), value_stack (), storage_class (sc), count (1)
86 {
87 value_stack.push (v);
88 }
89
90 octave_value& varref (void) { return value_stack.top (); }
91
92 octave_value varval (void) const { return value_stack.top (); }
93
94 void push_context (void) { value_stack.push (octave_value ()); }
95
96 void pop_context (void) { value_stack.pop (); }
97
98 void clear (void)
99 {
100 if (! (is_hidden () || is_inherited ()))
101 {
102 if (is_global ())
103 unmark_global ();
104
105 if (is_persistent ())
106 {
107 symbol_table::persistent_varref (name) = varval ();
108 unmark_persistent ();
109 }
110
111 varref () = octave_value ();
112 }
113 }
114
115 bool is_defined (void) const { return varval ().is_defined (); }
116
117 bool is_variable (void) const
118 {
119 return (storage_class != local || is_defined ());
120 }
121
122 bool is_local (void) const { return storage_class & local; }
123 bool is_automatic (void) const { return storage_class & automatic; }
124 bool is_formal (void) const { return storage_class & formal; }
125 bool is_hidden (void) const { return storage_class & hidden; }
126 bool is_inherited (void) const { return storage_class & inherited; }
127 bool is_global (void) const { return storage_class & global; }
128 bool is_persistent (void) const { return storage_class & persistent; }
129
130 void mark_local (void) { storage_class |= local; }
131 void mark_automatic (void) { storage_class |= automatic; }
132 void mark_formal (void) { storage_class |= formal; }
133 void mark_hidden (void) { storage_class |= hidden; }
134 void mark_inherited (void) { storage_class |= inherited; }
135 void mark_global (void)
136 {
137 if (is_persistent ())
138 error ("can't make persistent variable %s global", name.c_str ());
139 else
140 storage_class |= global;
141 }
142 void mark_persistent (void)
143 {
144 if (is_global ())
145 error ("can't make global variable %s persistent", name.c_str ());
146 else
147 storage_class |= persistent;
148 }
149
150 void unmark_local (void) { storage_class &= ~local; }
151 void unmark_automatic (void) { storage_class &= ~automatic; }
152 void unmark_formal (void) { storage_class &= ~formal; }
153 void unmark_hidden (void) { storage_class &= ~hidden; }
154 void unmark_inherited (void) { storage_class &= ~inherited; }
155 void unmark_global (void) { storage_class &= ~global; }
156 void unmark_persistent (void) { storage_class &= ~persistent; }
157
158 void init_persistent (void)
159 {
160 if (! is_defined ())
161 {
162 mark_persistent ();
163
164 varref () = symbol_table::persistent_varval (name);
165 }
166 // FIXME -- this causes trouble with recursive calls.
167 // else
168 // error ("unable to declare existing variable persistent");
169 }
170
171 void erase_persistent (void)
172 {
173 unmark_persistent ();
174 symbol_table::erase_persistent (name);
175 }
176
177 symbol_record_rep *dup (void)
178 {
179 return new symbol_record_rep (name, varval (), storage_class);
180 }
181
182 std::string name;
183
184 std::stack<octave_value> value_stack;
185
186 unsigned int storage_class;
187
188 size_t count;
189
190 private:
191
192 // No copying!
193
194 symbol_record_rep (const symbol_record_rep& ov);
195
196 symbol_record_rep& operator = (const symbol_record_rep&);
197 };
198
199 public:
200
201 symbol_record (const std::string& nm = std::string (),
202 const octave_value& v = octave_value (),
203 unsigned int sc = local)
204 : rep (new symbol_record_rep (nm, v, sc)) { }
205
206 symbol_record (const symbol_record& sr)
207 : rep (sr.rep)
208 {
209 rep->count++;
210 }
211
212 symbol_record& operator = (const symbol_record& sr)
213 {
214 if (this != &sr)
510 { 215 {
511 std::ostringstream buf; 216 rep = sr.rep;
512 buf << symtab_count++; 217 rep->count++;
513 table_name = buf.str ();
514 } 218 }
515 } 219
516 220 return *this;
517 ~symbol_table (void); 221 }
518 222
519 symbol_record *lookup (const std::string& nm, bool insert = false, 223 ~symbol_record (void)
520 bool warn = false); 224 {
521 225 if (--rep->count == 0)
522 void rename (const std::string& old_name, const std::string& new_name); 226 delete rep;
523 227 }
524 void clear (void); 228
525 229 symbol_record dup (void) const { return symbol_record (rep->dup ()); }
526 void clear_variables (void); 230
527 void clear_functions (void); 231 std::string name (void) const { return rep->name; }
528 void clear_mex_functions (void); 232
529 void clear_globals (void); 233 octave_value
530 234 find (tree_argument_list *args, const string_vector& arg_names,
531 bool clear (const std::string& nm); 235 octave_value_list& evaluated_args, bool& args_evaluated) const;
532 236
533 bool clear_variable (const std::string& nm); 237 octave_value& varref (void)
534 bool clear_function (const std::string& nm); 238 {
535 bool clear_global (const std::string& nm); 239 return is_global ()
536 240 ? symbol_table::varref (name (), symbol_table::global_scope ())
537 bool clear_variable_pattern (const std::string& pat); 241 : rep->varref ();
538 bool clear_function_pattern (const std::string& pat); 242 }
539 bool clear_global_pattern (const std::string& pat); 243
540 244 octave_value varval (void) const
541 int size (void) const; 245 {
542 246 return is_global ()
543 Array<symbol_record *> 247 ? symbol_table::varval (name (), symbol_table::global_scope ())
544 subsymbol_list (const string_vector& pats = string_vector (), 248 : rep->varval ();
545 unsigned int type = SYMTAB_ALL_TYPES, 249 }
546 unsigned int scope = SYMTAB_ALL_SCOPES) const; 250
547 251 void push_context (void)
548 Array<symbol_record *> 252 {
549 symbol_list (const string_vector& pats = string_vector (), 253 if (! (is_persistent () || is_global ()))
550 unsigned int type = SYMTAB_ALL_TYPES, 254 rep->push_context ();
551 unsigned int scope = SYMTAB_ALL_SCOPES) const; 255 }
552 256
553 257 void pop_context (void)
554 string_vector 258 {
555 name_list (const string_vector& pats = string_vector (), 259 if (! (is_persistent () || is_global ()))
556 bool sort = false, unsigned int type = SYMTAB_ALL_TYPES, 260 rep->pop_context ();
557 unsigned int scope = SYMTAB_ALL_SCOPES) const; 261 }
558 262
559 string_vector 263 void clear (void) { rep->clear (); }
560 user_function_name_list (void) const 264
561 { 265 bool is_defined (void) const { return rep->is_defined (); }
562 return name_list 266 bool is_variable (void) const { return rep->is_variable (); }
563 (string_vector (), false, 267
564 symbol_record::USER_FUNCTION|symbol_record::DLD_FUNCTION|symbol_record::MEX_FUNCTION, 268 bool is_local (void) const { return rep->is_local (); }
565 SYMTAB_ALL_SCOPES); 269 bool is_automatic (void) const { return rep->is_automatic (); }
566 } 270 bool is_formal (void) const { return rep->is_formal (); }
567 271 bool is_global (void) const { return rep->is_global (); }
568 string_vector 272 bool is_hidden (void) const { return rep->is_hidden (); }
569 global_variable_name_list (void) const 273 bool is_inherited (void) const { return rep->is_inherited (); }
570 { 274 bool is_persistent (void) const { return rep->is_persistent (); }
571 return name_list 275
572 (string_vector (), false, SYMTAB_VARIABLES, SYMTAB_GLOBAL_SCOPE); 276 void mark_local (void) { rep->mark_local (); }
573 } 277 void mark_automatic (void) { rep->mark_automatic (); }
574 278 void mark_formal (void) { rep->mark_formal (); }
575 string_vector 279 void mark_hidden (void) { rep->mark_hidden (); }
576 variable_name_list (void) const 280 void mark_inherited (void) { rep->mark_inherited (); }
577 { 281 void mark_global (void) { rep->mark_global (); }
578 return name_list 282 void mark_persistent (void) { rep->mark_persistent (); }
579 (string_vector (), false, SYMTAB_VARIABLES, SYMTAB_LOCAL_SCOPE); 283
580 } 284 void unmark_local (void) { rep->unmark_local (); }
581 285 void unmark_automatic (void) { rep->unmark_automatic (); }
582 int maybe_list (const char *header, const string_vector& argv, 286 void unmark_formal (void) { rep->unmark_formal (); }
583 std::ostream& os, bool show_verbose, 287 void unmark_hidden (void) { rep->unmark_hidden (); }
584 unsigned type, unsigned scope); 288 void unmark_inherited (void) { rep->unmark_inherited (); }
585 289 void unmark_global (void) { rep->unmark_global (); }
586 Array<symbol_record *> glob (const std::string& pat = std::string ("*"), 290 void unmark_persistent (void) { rep->unmark_persistent (); }
587 unsigned int type = SYMTAB_ALL_TYPES, 291
588 unsigned int scope = SYMTAB_ALL_SCOPES) const; 292 void init_persistent (void) { rep->init_persistent (); }
589 293
590 void push_context (void); 294 void erase_persistent (void) { rep->erase_persistent (); }
591 295
592 void pop_context (void); 296 unsigned int xstorage_class (void) const { return rep->storage_class; }
593 297
594 // Create a new symbol table with the same entries. Only the symbol 298 private:
595 // names and some attributes are copied, not values. 299
596 symbol_table *dup (void); 300 symbol_record_rep *rep;
597 301
598 // Inherit some values from the parent_sym_tab. 302 symbol_record (symbol_record_rep *new_rep) : rep (new_rep) { }
599 void inherit (symbol_table *parent_sym_tab); 303 };
600 304
601 void print_info (std::ostream& os) const; 305 class
306 fcn_info
307 {
308 public:
309
310 typedef std::map<std::string, std::string> dispatch_map_type;
311
312 typedef std::map<scope_id, octave_value>::const_iterator const_scope_val_iterator;
313 typedef std::map<scope_id, octave_value>::iterator scope_val_iterator;
314
315 typedef std::map<std::string, octave_value>::const_iterator const_str_val_iterator;
316 typedef std::map<std::string, octave_value>::iterator str_val_iterator;
317
318 typedef dispatch_map_type::const_iterator const_dispatch_map_iterator;
319 typedef dispatch_map_type::iterator dispatch_map_iterator;
320
321 private:
322
323 class
324 fcn_info_rep
325 {
326 public:
327
328 fcn_info_rep (const std::string& nm)
329 : name (nm), subfunctions (), private_functions (),
330 class_constructors (), class_methods (), cmdline_function (),
331 autoload_function (), function_on_path (), built_in_function (),
332 count (1) { }
333
334 octave_value load_private_function (const std::string& dir_name);
335
336 octave_value load_class_constructor (void);
337
338 octave_value load_class_method (const std::string& dispatch_type);
339
340 octave_value
341 find (tree_argument_list *args, const string_vector& arg_names,
342 octave_value_list& evaluated_args, bool& args_evaluated,
343 scope_id scope);
344
345 octave_value find_method (const std::string& dispatch_type);
346
347 octave_value find_autoload (void);
348
349 octave_value find_user_function (void);
350
351 bool is_user_function_defined (void) const
352 {
353 return function_on_path.is_defined ();
354 }
355
356 octave_value find_function (scope_id scope)
357 {
358 octave_value_list args;
359
360 return find_function (args, scope);
361 }
362
363 octave_value find_function (const octave_value_list& args,
364 scope_id scope)
365 {
366 string_vector arg_names;
367 octave_value_list evaluated_args = args;
368 bool args_evaluated;
369
370 return find (0, arg_names, evaluated_args, args_evaluated, scope);
371 }
372
373 void install_cmdline_function (const octave_value& f)
374 {
375 cmdline_function = f;
376 }
377
378 void install_subfunction (const octave_value& f, scope_id scope)
379 {
380 subfunctions[scope] = f;
381 }
382
383 void install_user_function (const octave_value& f)
384 {
385 function_on_path = f;
386 }
387
388 void install_built_in_function (const octave_value& f)
389 {
390 built_in_function = f;
391 }
392
393 void clear (void)
394 {
395 subfunctions.clear ();
396 private_functions.clear ();
397 class_constructors.clear ();
398 class_methods.clear ();
399 cmdline_function = octave_value ();
400 autoload_function = octave_value ();
401 function_on_path = octave_value ();
402 }
403
404 // FIXME -- should this also clear the cmdline and other "user
405 // defined" functions?
406 void clear_user_function (void)
407 {
408 function_on_path = octave_value ();
409 }
410
411 void clear_mex_function (void)
412 {
413 if (function_on_path.is_mex_function ())
414 function_on_path = octave_value ();
415 }
416
417 void add_dispatch (const std::string& type, const std::string& fname)
418 {
419 dispatch_map[type] = fname;
420 }
421
422 void clear_dispatch (const std::string& type)
423 {
424 dispatch_map_iterator p = dispatch_map.find (type);
425
426 if (p != dispatch_map.end ())
427 dispatch_map.erase (p);
428 }
429
430 void print_dispatch (std::ostream& os) const;
431
432 std::string help_for_dispatch (void) const;
433
434 dispatch_map_type get_dispatch (void) const { return dispatch_map; }
435
436 std::string name;
437
438 // Scope id to function object.
439 std::map<scope_id, octave_value> subfunctions;
440
441 // Directory name to function object.
442 std::map<std::string, octave_value> private_functions;
443
444 // Class name to function object.
445 std::map<std::string, octave_value> class_constructors;
446
447 // Dispatch type to function object.
448 std::map<std::string, octave_value> class_methods;
449
450 // Legacy dispatch map (dispatch type name to function name).
451 dispatch_map_type dispatch_map;
452
453 octave_value cmdline_function;
454
455 octave_value autoload_function;
456
457 octave_value function_on_path;
458
459 octave_value built_in_function;
460
461 size_t count;
462
463 private:
464
465 // No copying!
466
467 fcn_info_rep (const fcn_info_rep&);
468
469 fcn_info_rep& operator = (const fcn_info_rep&);
470 };
471
472 public:
473
474 fcn_info (const std::string& nm = std::string ())
475 : rep (new fcn_info_rep (nm)) { }
476
477 fcn_info (const fcn_info& ov) : rep (ov.rep)
478 {
479 rep->count++;
480 }
481
482 fcn_info& operator = (const fcn_info& ov)
483 {
484 if (this != &ov)
485 {
486 rep = ov.rep;
487 rep->count++;
488 }
489
490 return *this;
491 }
492
493 ~fcn_info (void)
494 {
495 if (--rep->count == 0)
496 delete rep;
497 }
498
499 octave_value
500 find (tree_argument_list *args, const string_vector& arg_names,
501 octave_value_list& evaluated_args, bool& args_evaluated,
502 scope_id scope);
503
504 octave_value find_method (const std::string& dispatch_type) const
505 {
506 return rep->find_method (dispatch_type);
507 }
508
509 octave_value find_built_in_function (void) const
510 {
511 return rep->built_in_function;
512 }
513
514 octave_value find_autoload (void)
515 {
516 return rep->find_autoload ();
517 }
518
519 octave_value find_user_function (void)
520 {
521 return rep->find_user_function ();
522 }
523
524 bool is_user_function_defined (void) const
525 {
526 return rep->is_user_function_defined ();
527 }
528
529 octave_value find_function (scope_id scope)
530 {
531 return rep->find_function (scope);
532 }
533
534 octave_value find_function (const octave_value_list& args,
535 scope_id scope)
536 {
537 return rep->find_function (args, scope);
538 }
539
540 void install_cmdline_function (const octave_value& f)
541 {
542 rep->install_cmdline_function (f);
543 }
544
545 void install_subfunction (const octave_value& f, scope_id scope)
546 {
547 rep->install_subfunction (f, scope);
548 }
549
550 void install_user_function (const octave_value& f)
551 {
552 rep->install_user_function (f);
553 }
554
555 void install_built_in_function (const octave_value& f)
556 {
557 rep->install_built_in_function (f);
558 }
559
560 void clear (void) { rep->clear (); }
561
562 void clear_user_function (void) { rep->clear_user_function (); }
563
564 void clear_mex_function (void) { rep->clear_mex_function (); }
565
566 void add_dispatch (const std::string& type, const std::string& fname)
567 {
568 rep->add_dispatch (type, fname);
569 }
570
571 void clear_dispatch (const std::string& type)
572 {
573 rep->clear_dispatch (type);
574 }
575
576 void print_dispatch (std::ostream& os) const
577 {
578 rep->print_dispatch (os);
579 }
580
581 std::string help_for_dispatch (void) const { return rep->help_for_dispatch (); }
582
583 dispatch_map_type get_dispatch (void) const
584 {
585 return rep->get_dispatch ();
586 }
587
588 private:
589
590 fcn_info_rep *rep;
591 };
592
593 static scope_id global_scope (void) { return xglobal_scope; }
594 static scope_id top_scope (void) { return xtop_scope; }
595
596 static scope_id current_scope (void) { return xcurrent_scope; }
597 static scope_id current_caller_scope (void) { return xcurrent_caller_scope; }
598
599 // We use parent_scope to handle parsing subfunctions.
600 static scope_id parent_scope (void) { return xparent_scope; }
601
602 static scope_id alloc_scope (void)
603 {
604 scope_id retval;
605
606 scope_ids_free_list_iterator p = scope_ids_free_list.begin ();
607
608 if (p != scope_ids_free_list.end ())
609 {
610 retval = *p;
611 scope_ids_free_list.erase (p);
612 }
613 else
614 retval = next_available_scope++;
615
616 scope_ids_in_use.insert (retval);
617
618 return retval;
619 }
620
621 static void set_scope (scope_id scope)
622 {
623 if (scope == xglobal_scope)
624 error ("can't set scope to global");
625 else if (scope != xcurrent_scope)
626 {
627 all_instances_iterator p = all_instances.find (scope);
628
629 if (p == all_instances.end ())
630 {
631 instance = new symbol_table ();
632
633 all_instances[scope] = instance;
634 }
635 else
636 instance = p->second;
637
638 xcurrent_scope = scope;
639 }
640 }
641
642 static void push_scope (scope_id scope)
643 {
644 if (scope_stack.empty ())
645 scope_stack.push_front (xtop_scope);
646
647 xcurrent_caller_scope = xcurrent_scope;
648
649 set_scope (scope);
650
651 scope_stack.push_front (scope);
652 }
653
654 static void pop_scope (void)
655 {
656 scope_stack.pop_front ();
657
658 set_scope (scope_stack[0]);
659
660 xcurrent_caller_scope = scope_stack[1];
661 }
662
663 static void pop_scope (void *) { pop_scope (); }
664
665 static void reset_scope (void)
666 {
667 scope_stack.clear ();
668
669 scope_stack.push_front (xtop_scope);
670
671 set_scope (xtop_scope);
672
673 xcurrent_caller_scope = -1;
674 }
675
676 static void set_parent_scope (scope_id scope)
677 {
678 xparent_scope = scope;
679 }
680
681 static void reset_parent_scope (void)
682 {
683 set_parent_scope (-1);
684 }
685
686 static void erase_scope (scope_id scope = xcurrent_scope)
687 {
688 all_instances_iterator p = all_instances.find (scope);
689
690 if (p != all_instances.end ())
691 all_instances.erase (p);
692
693 // free_scope (scope);
694 }
695
696 static scope_id dup_scope (scope_id scope = xcurrent_scope)
697 {
698 scope_id retval = -1;
699
700 symbol_table *inst = get_instance (scope);
701
702 if (inst)
703 {
704 scope_id new_scope = alloc_scope ();
705
706 symbol_table *new_symbol_table = new symbol_table ();
707
708 if (new_symbol_table)
709 {
710 all_instances[new_scope] = new_symbol_table;
711
712 inst->do_dup_scope (*new_symbol_table);
713
714 retval = new_scope;
715 }
716 }
717
718 return retval;
719 }
720
721 #if 0
722 static void print_scope (const std::string& tag, scope_id scope)
723 {
724 symbol_table *inst = get_instance (scope);
725
726 if (inst)
727 {
728 std::cerr << "printing " << tag << ", scope: " << scope
729 << ", inst: " << inst << std::endl;
730
731 inst->do_print_scope (std::cerr);
732 }
733 }
734
735 void do_print_scope (std::ostream& os) const
736 {
737 for (const_table_iterator p = table.begin (); p != table.end (); p++)
738 {
739 symbol_record sr = p->second;
740
741 octave_value val = sr.varval ();
742
743 if (val.is_defined ())
744 sr.varval ().print_with_name (os, sr.name ());
745 else
746 os << sr.name () << " is not defined" << std::endl;
747 }
748 }
749 #endif
750
751 static symbol_record find_symbol (const std::string& name,
752 scope_id scope = xcurrent_scope)
753 {
754 symbol_table *inst = get_instance (scope);
755
756 return inst ? inst->do_find_symbol (name) : symbol_record ();
757 }
758
759 static void inherit (scope_id scope, scope_id donor_scope)
760 {
761 symbol_table *inst = get_instance (scope);
762
763 if (inst)
764 inst->do_inherit (donor_scope);
765 }
766
767 static bool at_top_level (void) { return xcurrent_scope == xtop_scope; }
768
769 // Find a value corresponding to the given name in the table.
770 static octave_value
771 find (const std::string& name, tree_argument_list *args,
772 const string_vector& arg_names,
773 octave_value_list& evaluated_args, bool& args_evaluated,
774 scope_id scope = xcurrent_scope, bool skip_variables = false);
775
776 // Insert a new name in the table.
777 static symbol_record&
778 insert (const std::string& name, scope_id scope = xcurrent_scope)
779 {
780 static symbol_record foobar;
781
782 symbol_table *inst = get_instance (scope);
783
784 return inst ? inst->do_insert (name) : foobar;
785 }
786
787 static octave_value&
788 varref (const std::string& name, scope_id scope = xcurrent_scope)
789 {
790 static octave_value foobar;
791
792 symbol_table *inst = get_instance (scope);
793
794 return inst ? inst->do_varref (name) : foobar;
795 }
796
797 static octave_value
798 varval (const std::string& name, scope_id scope = xcurrent_scope)
799 {
800 symbol_table *inst = get_instance (scope);
801
802 return inst ? inst->do_varval (name) : octave_value ();
803 }
804
805 static octave_value&
806 persistent_varref (const std::string& name, scope_id scope = xcurrent_scope)
807 {
808 static octave_value foobar;
809
810 symbol_table *inst = get_instance (scope);
811
812 return inst ? inst->do_persistent_varref (name) : foobar;
813 }
814
815 static octave_value
816 persistent_varval (const std::string& name, scope_id scope = xcurrent_scope)
817 {
818 symbol_table *inst = get_instance (scope);
819
820 return inst ? inst->do_persistent_varval (name) : octave_value ();
821 }
822
823 static void
824 erase_persistent (const std::string& name, scope_id scope = xcurrent_scope)
825 {
826 symbol_table *inst = get_instance (scope);
827
828 if (inst)
829 inst->do_erase_persistent (name);
830 }
831
832 static bool
833 is_variable (const std::string& name, scope_id scope = xcurrent_scope)
834 {
835 symbol_table *inst = get_instance (scope);
836
837 return inst ? inst->do_is_variable (name) : false;
838 }
839
840 static bool
841 is_built_in_function_name (const std::string& name)
842 {
843 octave_value val = find_built_in_function (name);
844
845 return val.is_defined ();
846 }
847
848 static octave_value
849 find_method (const std::string& name, const std::string& dispatch_type)
850 {
851 const_fcn_table_iterator p = fcn_table.find (name);
852
853 if (p != fcn_table.end ())
854 return p->second.find_method (dispatch_type);
855 else
856 {
857 fcn_info finfo (name);
858
859 octave_value fcn = finfo.find_method (dispatch_type);
860
861 if (fcn.is_defined ())
862 fcn_table[name] = finfo;
863
864 return fcn;
865 }
866 }
867
868 static octave_value
869 find_built_in_function (const std::string& name)
870 {
871 const_fcn_table_iterator p = fcn_table.find (name);
872
873 return (p != fcn_table.end ())
874 ? p->second.find_built_in_function () : octave_value ();
875 }
876
877 static octave_value
878 find_autoload (const std::string& name)
879 {
880 fcn_table_iterator p = fcn_table.find (name);
881
882 return (p != fcn_table.end ())
883 ? p->second.find_autoload () : octave_value ();
884 }
885
886 static octave_value
887 find_function (const std::string& name, tree_argument_list *args,
888 const string_vector& arg_names,
889 octave_value_list& evaluated_args, bool& args_evaluated,
890 scope_id scope = xcurrent_scope);
891
892 static octave_value
893 find_user_function (const std::string& name)
894 {
895 fcn_table_iterator p = fcn_table.find (name);
896
897 return (p != fcn_table.end ())
898 ? p->second.find_user_function () : octave_value ();
899 }
900
901 static octave_value
902 find_function (const std::string& name, scope_id scope = xcurrent_scope)
903 {
904 octave_value_list evaluated_args;
905
906 return find_function (name, evaluated_args, scope);
907 }
908
909 static octave_value
910 find_function (const std::string& name, const octave_value_list& args,
911 scope_id scope = xcurrent_scope)
912 {
913 string_vector arg_names;
914 octave_value_list evaluated_args = args;
915 bool args_evaluated = ! args.empty ();
916
917 return find_function (name, 0, arg_names, evaluated_args,
918 args_evaluated, scope);
919 }
920
921 static void install_cmdline_function (const std::string& name,
922 const octave_value& fcn)
923 {
924 fcn_table_iterator p = fcn_table.find (name);
925
926 if (p != fcn_table.end ())
927 {
928 fcn_info& finfo = p->second;
929
930 finfo.install_cmdline_function (fcn);
931 }
932 else
933 {
934 fcn_info finfo (name);
935
936 finfo.install_cmdline_function (fcn);
937
938 fcn_table[name] = finfo;
939 }
940 }
941
942 static void install_subfunction (const std::string& name,
943 const octave_value& fcn,
944 scope_id scope = xparent_scope)
945 {
946 fcn_table_iterator p = fcn_table.find (name);
947
948 if (p != fcn_table.end ())
949 {
950 fcn_info& finfo = p->second;
951
952 finfo.install_subfunction (fcn, scope);
953 }
954 else
955 {
956 fcn_info finfo (name);
957
958 finfo.install_subfunction (fcn, scope);
959
960 fcn_table[name] = finfo;
961 }
962 }
963
964 static void install_user_function (const std::string& name,
965 const octave_value& fcn)
966 {
967 fcn_table_iterator p = fcn_table.find (name);
968
969 if (p != fcn_table.end ())
970 {
971 fcn_info& finfo = p->second;
972
973 finfo.install_user_function (fcn);
974 }
975 else
976 {
977 fcn_info finfo (name);
978
979 finfo.install_user_function (fcn);
980
981 fcn_table[name] = finfo;
982 }
983 }
984
985 static void install_built_in_function (const std::string& name,
986 const octave_value& fcn)
987 {
988 fcn_table_iterator p = fcn_table.find (name);
989
990 if (p != fcn_table.end ())
991 {
992 fcn_info& finfo = p->second;
993
994 finfo.install_built_in_function (fcn);
995 }
996 else
997 {
998 fcn_info finfo (name);
999
1000 finfo.install_built_in_function (fcn);
1001
1002 fcn_table[name] = finfo;
1003 }
1004 }
1005
1006 static void clear (const std::string& name, scope_id scope = xcurrent_scope)
1007 {
1008 clear_variable (name, scope);
1009 }
1010
1011 static void clear_all (void)
1012 {
1013 clear_variables ();
1014
1015 clear_functions ();
1016 }
1017
1018 static void clear_variables (scope_id scope = xcurrent_scope)
1019 {
1020 symbol_table *inst = get_instance (scope);
1021
1022 if (inst)
1023 inst->do_clear_variables ();
1024 }
1025
1026 // For unwind_protect.
1027 static void clear_variables (void *) { clear_variables (); }
1028
1029 static void clear_functions (void)
1030 {
1031 for (fcn_table_iterator p = fcn_table.begin (); p != fcn_table.end (); p++)
1032 p->second.clear ();
1033 }
1034
1035 static void clear_function (const std::string& name)
1036 {
1037 clear_user_function (name);
1038 }
1039
1040 static void clear_global (const std::string& name,
1041 scope_id scope = xcurrent_scope)
1042 {
1043 symbol_table *inst = get_instance (scope);
1044
1045 if (inst)
1046 inst->do_clear_global (name);
1047 }
1048
1049 static void clear_variable (const std::string& name,
1050 scope_id scope = xcurrent_scope)
1051 {
1052 symbol_table *inst = get_instance (scope);
1053
1054 if (inst)
1055 inst->do_clear_variable (name);
1056 }
1057
1058 static void clear_symbol (const std::string& name)
1059 {
1060 // FIXME -- are we supposed to do both here?
1061
1062 clear_variable (name);
1063 clear_function (name);
1064 }
1065
1066 static void clear_function_pattern (const std::string& pat)
1067 {
1068 glob_match pattern (pat);
1069
1070 for (fcn_table_iterator p = fcn_table.begin (); p != fcn_table.end (); p++)
1071 {
1072 if (pattern.match (p->first))
1073 p->second.clear_user_function ();
1074 }
1075 }
1076
1077 static void clear_global_pattern (const std::string& pat,
1078 scope_id scope = xcurrent_scope)
1079 {
1080 symbol_table *inst = get_instance (scope);
1081
1082 if (inst)
1083 inst->do_clear_global_pattern (pat);
1084 }
1085
1086 static void clear_variable_pattern (const std::string& pat,
1087 scope_id scope = xcurrent_scope)
1088 {
1089 symbol_table *inst = get_instance (scope);
1090
1091 if (inst)
1092 inst->do_clear_variable_pattern (pat);
1093 }
1094
1095 static void clear_symbol_pattern (const std::string& pat)
1096 {
1097 // FIXME -- are we supposed to do both here?
1098
1099 clear_variable_pattern (pat);
1100 clear_function_pattern (pat);
1101 }
1102
1103 static void clear_user_function (const std::string& name)
1104 {
1105 fcn_table_iterator p = fcn_table.find (name);
1106
1107 if (p != fcn_table.end ())
1108 {
1109 fcn_info& finfo = p->second;
1110
1111 finfo.clear_user_function ();
1112 }
1113 // FIXME -- is this necessary, or even useful?
1114 // else
1115 // error ("clear: no such function `%s'", name.c_str ());
1116 }
1117
1118 static void clear_mex_functions (void)
1119 {
1120 for (fcn_table_iterator p = fcn_table.begin (); p != fcn_table.end (); p++)
1121 {
1122 fcn_info& finfo = p->second;
1123
1124 finfo.clear_mex_function ();
1125 }
1126 }
1127
1128 static void alias_built_in_function (const std::string& alias,
1129 const std::string& name)
1130 {
1131 octave_value fcn = find_built_in_function (name);
1132
1133 if (fcn.is_defined ())
1134 {
1135 fcn_info finfo (alias);
1136
1137 finfo.install_built_in_function (fcn);
1138
1139 fcn_table[alias] = finfo;
1140 }
1141 else
1142 panic ("alias: `%s' is undefined", name.c_str ());
1143 }
1144
1145 static void add_dispatch (const std::string& name, const std::string& type,
1146 const std::string& fname)
1147 {
1148 fcn_table_iterator p = fcn_table.find (name);
1149
1150 if (p != fcn_table.end ())
1151 {
1152 fcn_info& finfo = p->second;
1153
1154 finfo.add_dispatch (type, fname);
1155 }
1156 else
1157 {
1158 fcn_info finfo (name);
1159
1160 finfo.add_dispatch (type, fname);
1161
1162 fcn_table[name] = finfo;
1163 }
1164 }
1165
1166 static void clear_dispatch (const std::string& name, const std::string& type)
1167 {
1168 fcn_table_iterator p = fcn_table.find (name);
1169
1170 if (p != fcn_table.end ())
1171 {
1172 fcn_info& finfo = p->second;
1173
1174 finfo.clear_dispatch (type);
1175 }
1176 }
1177
1178 static void print_dispatch (std::ostream& os, const std::string& name)
1179 {
1180 fcn_table_iterator p = fcn_table.find (name);
1181
1182 if (p != fcn_table.end ())
1183 {
1184 fcn_info& finfo = p->second;
1185
1186 finfo.print_dispatch (os);
1187 }
1188 }
1189
1190 static fcn_info::dispatch_map_type get_dispatch (const std::string& name)
1191 {
1192 fcn_info::dispatch_map_type retval;
1193
1194 fcn_table_iterator p = fcn_table.find (name);
1195
1196 if (p != fcn_table.end ())
1197 {
1198 fcn_info& finfo = p->second;
1199
1200 retval = finfo.get_dispatch ();
1201 }
1202
1203 return retval;
1204 }
1205
1206 static std::string help_for_dispatch (const std::string& name)
1207 {
1208 std::string retval;
1209
1210 fcn_table_iterator p = fcn_table.find (name);
1211
1212 if (p != fcn_table.end ())
1213 {
1214 fcn_info& finfo = p->second;
1215
1216 retval = finfo.help_for_dispatch ();
1217 }
1218
1219 return retval;
1220 }
1221
1222 static void push_context (scope_id scope = xcurrent_scope)
1223 {
1224 if (scope == xglobal_scope || scope == xtop_scope)
1225 error ("invalid call to xymtab::push_context");
1226 else
1227 {
1228 symbol_table *inst = get_instance (scope);
1229
1230 if (inst)
1231 inst->do_push_context ();
1232 }
1233 }
1234
1235 static void pop_context (scope_id scope = xcurrent_scope)
1236 {
1237 if (scope == xglobal_scope || scope == xtop_scope)
1238 error ("invalid call to xymtab::push_context");
1239 else
1240 {
1241 symbol_table *inst = get_instance (scope);
1242
1243 if (inst)
1244 inst->do_pop_context ();
1245 }
1246 }
1247
1248 // For unwind_protect.
1249 static void pop_context (void *) { pop_context (); }
1250
1251 static void mark_hidden (const std::string& name,
1252 scope_id scope = xcurrent_scope)
1253 {
1254 symbol_table *inst = get_instance (scope);
1255
1256 if (inst)
1257 inst->do_mark_hidden (name);
1258 }
1259
1260 static void mark_global (const std::string& name,
1261 scope_id scope = xcurrent_scope)
1262 {
1263 symbol_table *inst = get_instance (scope);
1264
1265 if (inst)
1266 inst->do_mark_global (name);
1267 }
1268
1269 static std::list<symbol_record>
1270 all_variables (scope_id scope = xcurrent_scope, bool defined_only = true)
1271 {
1272 symbol_table *inst = get_instance (scope);
1273
1274 return inst
1275 ? inst->do_all_variables (defined_only) : std::list<symbol_record> ();
1276 }
1277
1278 static std::list<symbol_record>
1279 glob (const std::string& pattern, scope_id scope = xcurrent_scope)
1280 {
1281 symbol_table *inst = get_instance (scope);
1282
1283 return inst ? inst->do_glob (pattern) : std::list<symbol_record> ();
1284 }
1285
1286 static std::list<symbol_record>
1287 glob_variables (const std::string& pattern, scope_id scope = xcurrent_scope)
1288 {
1289 symbol_table *inst = get_instance (scope);
1290
1291 return inst ? inst->do_glob (pattern, true) : std::list<symbol_record> ();
1292 }
1293
1294 static std::list<symbol_record>
1295 glob_variables (const string_vector& patterns,
1296 scope_id scope = xcurrent_scope)
1297 {
1298 std::list<symbol_record> retval;
1299
1300 size_t len = patterns.length ();
1301
1302 for (size_t i = 0; i < len; i++)
1303 {
1304 std::list<symbol_record> tmp = glob_variables (patterns[i], scope);
1305
1306 retval.insert (retval.begin (), tmp.begin (), tmp.end ());
1307 }
1308
1309 return retval;
1310 }
1311
1312 static std::list<std::string> user_function_names (void)
1313 {
1314 std::list<std::string> retval;
1315
1316 for (fcn_table_iterator p = fcn_table.begin ();
1317 p != fcn_table.end (); p++)
1318 {
1319 if (p->second.is_user_function_defined ())
1320 retval.push_back (p->first);
1321 }
1322
1323 if (! retval.empty ())
1324 retval.sort ();
1325
1326 return retval;
1327 }
1328
1329 static std::list<std::string>
1330 variable_names (scope_id scope = xcurrent_scope)
1331 {
1332 symbol_table *inst = get_instance (scope);
1333
1334 return inst ? inst->do_variable_names () : std::list<std::string> ();
1335 }
1336
1337 static std::list<std::string> built_in_function_names (void)
1338 {
1339 std::list<std::string> retval;
1340
1341 for (const_fcn_table_iterator p = fcn_table.begin ();
1342 p != fcn_table.end (); p++)
1343 {
1344 octave_value fcn = p->second.find_built_in_function ();
1345
1346 if (fcn.is_defined ())
1347 retval.push_back (p->first);
1348 }
1349
1350 if (! retval.empty ())
1351 retval.sort ();
1352
1353 return retval;
1354 }
1355
1356 static bool is_local_variable (const std::string& name,
1357 scope_id scope = xcurrent_scope)
1358 {
1359 if (scope == xglobal_scope)
1360 return false;
1361 else
1362 {
1363 symbol_table *inst = get_instance (scope);
1364
1365 return inst ? inst->do_is_local_variable (name) : false;
1366 }
1367 }
1368
1369 static bool is_global (const std::string& name,
1370 scope_id scope = xcurrent_scope)
1371 {
1372 if (scope == xglobal_scope)
1373 return true;
1374 else
1375 {
1376 symbol_table *inst = get_instance (scope);
1377
1378 return inst ? inst->do_is_global (name) : false;
1379 }
1380 }
602 1381
603 private: 1382 private:
604 1383
605 unsigned int table_size; 1384 typedef std::map<std::string, symbol_record>::const_iterator const_table_iterator;
606 1385 typedef std::map<std::string, symbol_record>::iterator table_iterator;
607 symbol_record *table; 1386
608 1387 typedef std::map<std::string, octave_value>::const_iterator const_persistent_table_iterator;
609 std::string table_name; 1388 typedef std::map<std::string, octave_value>::iterator persistent_table_iterator;
610 1389
611 static unsigned long int symtab_count; 1390 typedef std::map<scope_id, symbol_table*>::const_iterator all_instances_const_iterator;
1391 typedef std::map<scope_id, symbol_table*>::iterator all_instances_iterator;
1392
1393 typedef std::map<std::string, fcn_info>::const_iterator const_fcn_table_iterator;
1394 typedef std::map<std::string, fcn_info>::iterator fcn_table_iterator;
1395
1396 typedef std::set<scope_id>::const_iterator scope_ids_free_list_const_iterator;
1397 typedef std::set<scope_id>::iterator scope_ids_free_list_iterator;
1398
1399 typedef std::set<scope_id>::const_iterator scope_ids_in_use_const_iterator;
1400 typedef std::set<scope_id>::iterator scope_ids_in_use_iterator;
1401
1402 // Map from symbol names to symbol info.
1403 std::map<std::string, symbol_record> table;
1404
1405 // Map from names of persistent variables to values.
1406 std::map<std::string, octave_value> persistent_table;
1407
1408 // Pointer to symbol table for current scope (variables only).
1409 static symbol_table *instance;
1410
1411 // Map from scope id to symbol table instances.
1412 static std::map<scope_id, symbol_table*> all_instances;
1413
1414 // Map from function names to function info (subfunctions, private
1415 // functions, class constructors, class methods, etc.)
1416 static std::map<std::string, fcn_info> fcn_table;
1417
1418 static const scope_id xglobal_scope;
1419 static const scope_id xtop_scope;
1420
1421 static scope_id xcurrent_scope;
1422 static scope_id xcurrent_caller_scope;
1423
1424 // We use parent_scope to handle parsing subfunctions.
1425 static scope_id xparent_scope;
1426
1427 static std::deque<scope_id> scope_stack;
1428
1429 // The next available scope ID.
1430 static scope_id next_available_scope;
1431
1432 // The set of scope IDs that are currently allocated.
1433 static std::set<scope_id> scope_ids_in_use;
1434
1435 // The set of scope IDs that are currently available.
1436 static std::set<scope_id> scope_ids_free_list;
1437
1438 symbol_table (void) : table () { }
1439
1440 ~symbol_table (void) { }
1441
1442 static void free_scope (scope_id scope)
1443 {
1444 if (scope == xglobal_scope || scope == xtop_scope)
1445 error ("can't free global or top-level scopes!");
1446 else
1447 {
1448 scope_ids_in_use_iterator p = scope_ids_in_use.find (scope);
1449
1450 if (p != scope_ids_in_use.end ())
1451 {
1452 scope_ids_in_use.erase (p);
1453 scope_ids_free_list.insert (*p);
1454 }
1455 else
1456 error ("scope id = %ld not found!", scope);
1457 }
1458 }
1459
1460 static symbol_table *get_instance (scope_id scope)
1461 {
1462 symbol_table *retval = 0;
1463
1464 if (scope == xcurrent_scope)
1465 {
1466 if (! instance)
1467 {
1468 instance = new symbol_table ();
1469
1470 all_instances[scope] = instance;
1471 }
1472
1473 if (! instance)
1474 error ("unable to create symbol_table object!");
1475
1476 retval = instance;
1477 }
1478 else
1479 {
1480 all_instances_iterator p = all_instances.find (scope);
1481
1482 if (p == all_instances.end ())
1483 {
1484 retval = new symbol_table ();
1485
1486 all_instances[scope] = retval;
1487 }
1488 else
1489 retval = p->second;
1490 }
1491
1492 return retval;
1493 }
1494
1495 void insert_symbol_record (const symbol_record& sr)
1496 {
1497 table[sr.name ()] = sr;
1498 }
612 1499
613 void 1500 void
614 print_descriptor (std::ostream& os, 1501 do_dup_scope (symbol_table& new_symbol_table) const
615 std::list<whos_parameter> params) const; 1502 {
616 1503 for (const_table_iterator p = table.begin (); p != table.end (); p++)
617 std::list<whos_parameter> 1504 new_symbol_table.insert_symbol_record (p->second.dup ());
618 parse_whos_line_format (Array<symbol_record *>& symbols) const; 1505 }
619 1506
620 unsigned int hash (const std::string& s); 1507 symbol_record do_find_symbol (const std::string& name)
621 1508 {
622 // No copying! 1509 table_iterator p = table.find (name);
623 1510
624 symbol_table (const symbol_table&); 1511 if (p == table.end ())
625 1512 return do_insert (name);
626 symbol_table& operator = (const symbol_table&); 1513 else
1514 return p->second;
1515 }
1516
1517 void do_inherit (scope_id donor_scope)
1518 {
1519 for (table_iterator p = table.begin (); p != table.end (); p++)
1520 {
1521 symbol_record& sr = p->second;
1522
1523 std::string nm = sr.name ();
1524
1525 if (! (sr.is_automatic () || sr.is_formal () || nm == "__retval__"))
1526 {
1527 octave_value val = symbol_table::varval (nm, donor_scope);
1528
1529 if (val.is_defined ())
1530 {
1531 sr.varref () = val;
1532
1533 sr.mark_inherited ();
1534 }
1535 }
1536 }
1537 }
1538
1539 octave_value
1540 do_find (const std::string& name, tree_argument_list *args,
1541 const string_vector& arg_names,
1542 octave_value_list& evaluated_args, bool& args_evaluated,
1543 scope_id scope, bool skip_variables);
1544
1545 symbol_record& do_insert (const std::string& name)
1546 {
1547 table_iterator p = table.find (name);
1548
1549 return p == table.end ()
1550 ? (table[name] = symbol_record (name)) : p->second;
1551 }
1552
1553 octave_value& do_varref (const std::string& name)
1554 {
1555 table_iterator p = table.find (name);
1556
1557 if (p == table.end ())
1558 {
1559 symbol_record& sr = do_insert (name);
1560
1561 return sr.varref ();
1562 }
1563 else
1564 return p->second.varref ();
1565 }
1566
1567 octave_value do_varval (const std::string& name) const
1568 {
1569 const_table_iterator p = table.find (name);
1570
1571 return (p != table.end ()) ? p->second.varval () : octave_value ();
1572 }
1573
1574 octave_value& do_persistent_varref (const std::string& name)
1575 {
1576 persistent_table_iterator p = persistent_table.find (name);
1577
1578 return (p == persistent_table.end ())
1579 ? persistent_table[name] : p->second;
1580 }
1581
1582 octave_value do_persistent_varval (const std::string& name)
1583 {
1584 const_persistent_table_iterator p = persistent_table.find (name);
1585
1586 return (p != persistent_table.end ()) ? p->second : octave_value ();
1587 }
1588
1589 void do_erase_persistent (const std::string& name)
1590 {
1591 persistent_table_iterator p = persistent_table.find (name);
1592
1593 if (p != persistent_table.end ())
1594 persistent_table.erase (p);
1595 }
1596
1597 bool do_is_variable (const std::string& name) const
1598 {
1599 bool retval = false;
1600
1601 const_table_iterator p = table.find (name);
1602
1603 if (p != table.end ())
1604 {
1605 const symbol_record& sr = p->second;
1606
1607 retval = sr.is_variable ();
1608 }
1609
1610 return retval;
1611 }
1612
1613 void do_push_context (void)
1614 {
1615 for (table_iterator p = table.begin (); p != table.end (); p++)
1616 p->second.push_context ();
1617 }
1618
1619 void do_pop_context (void)
1620 {
1621 for (table_iterator p = table.begin (); p != table.end (); p++)
1622 p->second.pop_context ();
1623 }
1624
1625 void do_clear_variables (void)
1626 {
1627 for (table_iterator p = table.begin (); p != table.end (); p++)
1628 p->second.clear ();
1629 }
1630
1631 void do_clear_global (const std::string& name)
1632 {
1633 table_iterator p = table.find (name);
1634
1635 if (p != table.end ())
1636 {
1637 symbol_record& sr = p->second;
1638
1639 if (sr.is_global ())
1640 {
1641 symbol_table::clear_variable (p->first, xglobal_scope);
1642
1643 sr.unmark_global ();
1644 }
1645 }
1646 }
1647
1648 void do_clear_variable (const std::string& name)
1649 {
1650 table_iterator p = table.find (name);
1651
1652 if (p != table.end ())
1653 p->second.clear ();
1654 }
1655
1656 void do_clear_global_pattern (const std::string& pat)
1657 {
1658 glob_match pattern (pat);
1659
1660 for (table_iterator p = table.begin (); p != table.end (); p++)
1661 {
1662 symbol_record& sr = p->second;
1663
1664 if (sr.is_global ())
1665 {
1666 if (pattern.match (sr.name ()))
1667 {
1668 symbol_table::clear_variable (p->first, xglobal_scope);
1669
1670 sr.unmark_global ();
1671 }
1672 }
1673 }
1674 }
1675
1676 void do_clear_variable_pattern (const std::string& pat)
1677 {
1678 glob_match pattern (pat);
1679
1680 for (table_iterator p = table.begin (); p != table.end (); p++)
1681 {
1682 symbol_record& sr = p->second;
1683
1684 if (sr.is_defined () || sr.is_global ())
1685 {
1686 if (pattern.match (sr.name ()))
1687 sr.clear ();
1688 }
1689 }
1690 }
1691
1692 void do_mark_hidden (const std::string& name)
1693 {
1694 table_iterator p = table.find (name);
1695
1696 if (p != table.end ())
1697 p->second.mark_hidden ();
1698 }
1699
1700 void do_mark_global (const std::string& name)
1701 {
1702 table_iterator p = table.find (name);
1703
1704 if (p != table.end ())
1705 p->second.mark_global ();
1706 }
1707
1708 std::list<symbol_record> do_all_variables (bool defined_only) const
1709 {
1710 std::list<symbol_record> retval;
1711
1712 for (const_table_iterator p = table.begin (); p != table.end (); p++)
1713 {
1714 const symbol_record& sr = p->second;
1715
1716 if (defined_only && ! sr.is_defined ())
1717 continue;
1718
1719 retval.push_back (sr);
1720 }
1721
1722 return retval;
1723 }
1724
1725 std::list<symbol_record> do_glob (const std::string& pattern,
1726 bool vars_only = false) const
1727 {
1728 std::list<symbol_record> retval;
1729
1730 glob_match pat (pattern);
1731
1732 for (const_table_iterator p = table.begin (); p != table.end (); p++)
1733 {
1734 if (pat.match (p->first))
1735 {
1736 const symbol_record& sr = p->second;
1737
1738 if (vars_only && ! sr.is_variable ())
1739 continue;
1740
1741 retval.push_back (sr);
1742 }
1743 }
1744
1745 return retval;
1746 }
1747
1748 std::list<std::string> do_variable_names (void)
1749 {
1750 std::list<std::string> retval;
1751
1752 for (const_table_iterator p = table.begin (); p != table.end (); p++)
1753 retval.push_back (p->first);
1754
1755 retval.sort ();
1756
1757 return retval;
1758 }
1759
1760 bool do_is_local_variable (const std::string& name) const
1761 {
1762 const_table_iterator p = table.find (name);
1763
1764 return (p != table.end ()
1765 && ! p->second.is_global ()
1766 && p->second.is_defined ());
1767 }
1768
1769 bool do_is_global (const std::string& name) const
1770 {
1771 const_table_iterator p = table.find (name);
1772
1773 return p != table.end () && p->second.is_global ();
1774 }
627 }; 1775 };
628 1776
629 // Defines layout for the whos/who -long command. 1777 extern bool out_of_date_check (octave_value& function);
630 extern std::string Vwhos_line_format;
631 1778
632 #endif 1779 #endif
633 1780
634 /* 1781 /*
635 ;;; Local Variables: *** 1782 ;;; Local Variables: ***