comparison libinterp/corefcn/symtab.h @ 16892:68fc671a9339

maint: Collapse interpfcn and interpfcn-core directories into corefcn directory. * libgui/src/module.mk: Remove -I references to interp-core, interpfcn, add reference to corefcn. * libinterp/Makefile.am: Remove -I references to interp-core, interpfcn, add reference to corefcn. * libinterp/corefcn/module.mk: Add files from interp-core, interpfcn to build system. Copy over special rules from module.mk files in interp-core andd interpfcn. * src/Makefile.am: Replace references to interp-core, interpfcn with those to corefcn. * libinterp/corefcn/Cell.cc, libinterp/corefcn/Cell.h, libinterp/corefcn/action-container.h, libinterp/corefcn/c-file-ptr-stream.cc, libinterp/corefcn/c-file-ptr-stream.h, libinterp/corefcn/comment-list.cc, libinterp/corefcn/comment-list.h, libinterp/corefcn/cutils.c, libinterp/corefcn/cutils.h, libinterp/corefcn/data.cc, libinterp/corefcn/data.h, libinterp/corefcn/debug.cc, libinterp/corefcn/debug.h, libinterp/corefcn/defaults.cc, libinterp/corefcn/defaults.in.h, libinterp/corefcn/defun-dld.h, libinterp/corefcn/defun-int.h, libinterp/corefcn/defun.cc, libinterp/corefcn/defun.h, libinterp/corefcn/dirfns.cc, libinterp/corefcn/dirfns.h, libinterp/corefcn/display.cc, libinterp/corefcn/display.h, libinterp/corefcn/dynamic-ld.cc, libinterp/corefcn/dynamic-ld.h, libinterp/corefcn/error.cc, libinterp/corefcn/error.h, libinterp/corefcn/event-queue.h, libinterp/corefcn/file-io.cc, libinterp/corefcn/file-io.h, libinterp/corefcn/gl-render.cc, libinterp/corefcn/gl-render.h, libinterp/corefcn/gl2ps-renderer.cc, libinterp/corefcn/gl2ps-renderer.h, libinterp/corefcn/gl2ps.c, libinterp/corefcn/gl2ps.h, libinterp/corefcn/graphics.cc, libinterp/corefcn/graphics.in.h, libinterp/corefcn/gripes.cc, libinterp/corefcn/gripes.h, libinterp/corefcn/help.cc, libinterp/corefcn/help.h, libinterp/corefcn/hook-fcn.cc, libinterp/corefcn/hook-fcn.h, libinterp/corefcn/input.cc, libinterp/corefcn/input.h, libinterp/corefcn/jit-ir.cc, libinterp/corefcn/jit-ir.h, libinterp/corefcn/jit-typeinfo.cc, libinterp/corefcn/jit-typeinfo.h, libinterp/corefcn/jit-util.cc, libinterp/corefcn/jit-util.h, libinterp/corefcn/load-path.cc, libinterp/corefcn/load-path.h, libinterp/corefcn/load-save.cc, libinterp/corefcn/load-save.h, libinterp/corefcn/ls-ascii-helper.cc, libinterp/corefcn/ls-ascii-helper.h, libinterp/corefcn/ls-hdf5.cc, libinterp/corefcn/ls-hdf5.h, libinterp/corefcn/ls-mat-ascii.cc, libinterp/corefcn/ls-mat-ascii.h, libinterp/corefcn/ls-mat4.cc, libinterp/corefcn/ls-mat4.h, libinterp/corefcn/ls-mat5.cc, libinterp/corefcn/ls-mat5.h, libinterp/corefcn/ls-oct-ascii.cc, libinterp/corefcn/ls-oct-ascii.h, libinterp/corefcn/ls-oct-binary.cc, libinterp/corefcn/ls-oct-binary.h, libinterp/corefcn/ls-utils.cc, libinterp/corefcn/ls-utils.h, libinterp/corefcn/matherr.c, libinterp/corefcn/mex.cc, libinterp/corefcn/mex.h, libinterp/corefcn/mexproto.h, libinterp/corefcn/mxarray.in.h, libinterp/corefcn/oct-errno.h, libinterp/corefcn/oct-errno.in.cc, libinterp/corefcn/oct-fstrm.cc, libinterp/corefcn/oct-fstrm.h, libinterp/corefcn/oct-hdf5.h, libinterp/corefcn/oct-hist.cc, libinterp/corefcn/oct-hist.h, libinterp/corefcn/oct-iostrm.cc, libinterp/corefcn/oct-iostrm.h, libinterp/corefcn/oct-lvalue.cc, libinterp/corefcn/oct-lvalue.h, libinterp/corefcn/oct-map.cc, libinterp/corefcn/oct-map.h, libinterp/corefcn/oct-obj.cc, libinterp/corefcn/oct-obj.h, libinterp/corefcn/oct-prcstrm.cc, libinterp/corefcn/oct-prcstrm.h, libinterp/corefcn/oct-procbuf.cc, libinterp/corefcn/oct-procbuf.h, libinterp/corefcn/oct-stdstrm.h, libinterp/corefcn/oct-stream.cc, libinterp/corefcn/oct-stream.h, libinterp/corefcn/oct-strstrm.cc, libinterp/corefcn/oct-strstrm.h, libinterp/corefcn/oct.h, libinterp/corefcn/octave-link.cc, libinterp/corefcn/octave-link.h, libinterp/corefcn/pager.cc, libinterp/corefcn/pager.h, libinterp/corefcn/pr-output.cc, libinterp/corefcn/pr-output.h, libinterp/corefcn/procstream.cc, libinterp/corefcn/procstream.h, libinterp/corefcn/profiler.cc, libinterp/corefcn/profiler.h, libinterp/corefcn/pt-jit.cc, libinterp/corefcn/pt-jit.h, libinterp/corefcn/sighandlers.cc, libinterp/corefcn/sighandlers.h, libinterp/corefcn/siglist.c, libinterp/corefcn/siglist.h, libinterp/corefcn/sparse-xdiv.cc, libinterp/corefcn/sparse-xdiv.h, libinterp/corefcn/sparse-xpow.cc, libinterp/corefcn/sparse-xpow.h, libinterp/corefcn/symtab.cc, libinterp/corefcn/symtab.h, libinterp/corefcn/sysdep.cc, libinterp/corefcn/sysdep.h, libinterp/corefcn/toplev.cc, libinterp/corefcn/toplev.h, libinterp/corefcn/txt-eng-ft.cc, libinterp/corefcn/txt-eng-ft.h, libinterp/corefcn/txt-eng.h, libinterp/corefcn/unwind-prot.cc, libinterp/corefcn/unwind-prot.h, libinterp/corefcn/utils.cc, libinterp/corefcn/utils.h, libinterp/corefcn/variables.cc, libinterp/corefcn/variables.h, libinterp/corefcn/workspace-element.h, libinterp/corefcn/xdiv.cc, libinterp/corefcn/xdiv.h, libinterp/corefcn/xgl2ps.c, libinterp/corefcn/xnorm.cc, libinterp/corefcn/xnorm.h, libinterp/corefcn/xpow.cc, libinterp/corefcn/xpow.h, libinterp/corefcn/zfstream.cc, libinterp/corefcn/zfstream.h: Files moved from interp-core and interpfcn directories. * libinterp/interp-core/Cell.cc, libinterp/interp-core/Cell.h, libinterp/interp-core/action-container.h, libinterp/interp-core/c-file-ptr-stream.cc, libinterp/interp-core/c-file-ptr-stream.h, libinterp/interp-core/comment-list.cc, libinterp/interp-core/comment-list.h, libinterp/interp-core/cutils.c, libinterp/interp-core/cutils.h, libinterp/interp-core/defun-dld.h, libinterp/interp-core/defun-int.h, libinterp/interp-core/display.cc, libinterp/interp-core/display.h, libinterp/interp-core/dynamic-ld.cc, libinterp/interp-core/dynamic-ld.h, libinterp/interp-core/event-queue.h, libinterp/interp-core/gl-render.cc, libinterp/interp-core/gl-render.h, libinterp/interp-core/gl2ps-renderer.cc, libinterp/interp-core/gl2ps-renderer.h, libinterp/interp-core/gl2ps.c, libinterp/interp-core/gl2ps.h, libinterp/interp-core/gripes.cc, libinterp/interp-core/gripes.h, libinterp/interp-core/jit-ir.cc, libinterp/interp-core/jit-ir.h, libinterp/interp-core/jit-typeinfo.cc, libinterp/interp-core/jit-typeinfo.h, libinterp/interp-core/jit-util.cc, libinterp/interp-core/jit-util.h, libinterp/interp-core/ls-ascii-helper.cc, libinterp/interp-core/ls-ascii-helper.h, libinterp/interp-core/ls-hdf5.cc, libinterp/interp-core/ls-hdf5.h, libinterp/interp-core/ls-mat-ascii.cc, libinterp/interp-core/ls-mat-ascii.h, libinterp/interp-core/ls-mat4.cc, libinterp/interp-core/ls-mat4.h, libinterp/interp-core/ls-mat5.cc, libinterp/interp-core/ls-mat5.h, libinterp/interp-core/ls-oct-binary.cc, libinterp/interp-core/ls-oct-binary.h, libinterp/interp-core/ls-utils.cc, libinterp/interp-core/ls-utils.h, libinterp/interp-core/matherr.c, libinterp/interp-core/mex.cc, libinterp/interp-core/mex.h, libinterp/interp-core/mexproto.h, libinterp/interp-core/module.mk, libinterp/interp-core/mxarray.in.h, libinterp/interp-core/oct-errno.h, libinterp/interp-core/oct-errno.in.cc, libinterp/interp-core/oct-fstrm.cc, libinterp/interp-core/oct-fstrm.h, libinterp/interp-core/oct-hdf5.h, libinterp/interp-core/oct-iostrm.cc, libinterp/interp-core/oct-iostrm.h, libinterp/interp-core/oct-lvalue.cc, libinterp/interp-core/oct-lvalue.h, libinterp/interp-core/oct-map.cc, libinterp/interp-core/oct-map.h, libinterp/interp-core/oct-obj.cc, libinterp/interp-core/oct-obj.h, libinterp/interp-core/oct-prcstrm.cc, libinterp/interp-core/oct-prcstrm.h, libinterp/interp-core/oct-procbuf.cc, libinterp/interp-core/oct-procbuf.h, libinterp/interp-core/oct-stdstrm.h, libinterp/interp-core/oct-stream.cc, libinterp/interp-core/oct-stream.h, libinterp/interp-core/oct-strstrm.cc, libinterp/interp-core/oct-strstrm.h, libinterp/interp-core/oct.h, libinterp/interp-core/procstream.cc, libinterp/interp-core/procstream.h, libinterp/interp-core/pt-jit.cc, libinterp/interp-core/pt-jit.h, libinterp/interp-core/siglist.c, libinterp/interp-core/siglist.h, libinterp/interp-core/sparse-xdiv.cc, libinterp/interp-core/sparse-xdiv.h, libinterp/interp-core/sparse-xpow.cc, libinterp/interp-core/sparse-xpow.h, libinterp/interp-core/txt-eng-ft.cc, libinterp/interp-core/txt-eng-ft.h, libinterp/interp-core/txt-eng.h, libinterp/interp-core/unwind-prot.cc, libinterp/interp-core/unwind-prot.h, libinterp/interp-core/xdiv.cc, libinterp/interp-core/xdiv.h, libinterp/interp-core/xgl2ps.c, libinterp/interp-core/xnorm.cc, libinterp/interp-core/xnorm.h, libinterp/interp-core/xpow.cc, libinterp/interp-core/xpow.h, libinterp/interp-core/zfstream.cc, libinterp/interp-core/zfstream.h, libinterp/interpfcn/data.cc, libinterp/interpfcn/data.h, libinterp/interpfcn/debug.cc, libinterp/interpfcn/debug.h, libinterp/interpfcn/defaults.cc, libinterp/interpfcn/defaults.in.h, libinterp/interpfcn/defun.cc, libinterp/interpfcn/defun.h, libinterp/interpfcn/dirfns.cc, libinterp/interpfcn/dirfns.h, libinterp/interpfcn/error.cc, libinterp/interpfcn/error.h, libinterp/interpfcn/file-io.cc, libinterp/interpfcn/file-io.h, libinterp/interpfcn/graphics.cc, libinterp/interpfcn/graphics.in.h, libinterp/interpfcn/help.cc, libinterp/interpfcn/help.h, libinterp/interpfcn/hook-fcn.cc, libinterp/interpfcn/hook-fcn.h, libinterp/interpfcn/input.cc, libinterp/interpfcn/input.h, libinterp/interpfcn/load-path.cc, libinterp/interpfcn/load-path.h, libinterp/interpfcn/load-save.cc, libinterp/interpfcn/load-save.h, libinterp/interpfcn/ls-oct-ascii.cc, libinterp/interpfcn/ls-oct-ascii.h, libinterp/interpfcn/module.mk, libinterp/interpfcn/oct-hist.cc, libinterp/interpfcn/oct-hist.h, libinterp/interpfcn/octave-link.cc, libinterp/interpfcn/octave-link.h, libinterp/interpfcn/pager.cc, libinterp/interpfcn/pager.h, libinterp/interpfcn/pr-output.cc, libinterp/interpfcn/pr-output.h, libinterp/interpfcn/profiler.cc, libinterp/interpfcn/profiler.h, libinterp/interpfcn/sighandlers.cc, libinterp/interpfcn/sighandlers.h, libinterp/interpfcn/symtab.cc, libinterp/interpfcn/symtab.h, libinterp/interpfcn/sysdep.cc, libinterp/interpfcn/sysdep.h, libinterp/interpfcn/toplev.cc, libinterp/interpfcn/toplev.h, libinterp/interpfcn/utils.cc, libinterp/interpfcn/utils.h, libinterp/interpfcn/variables.cc, libinterp/interpfcn/variables.h, libinterp/interpfcn/workspace-element.h: deleted files.
author Rik <rik@octave.org>
date Wed, 03 Jul 2013 17:43:48 -0700
parents libinterp/interpfcn/symtab.h@2f8fb02a6c31
children 498b2dd1bd56 99122191d3dd
comparison
equal deleted inserted replaced
16891:486c3e2731ff 16892:68fc671a9339
1 /*
2
3 Copyright (C) 1993-2012 John W. Eaton
4 Copyright (C) 2009 VZLU Prague
5
6 This file is part of Octave.
7
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
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21
22 */
23
24 #if !defined (octave_symtab_h)
25 #define octave_symtab_h 1
26
27 #include <deque>
28 #include <list>
29 #include <map>
30 #include <set>
31 #include <string>
32
33 #include "glob-match.h"
34 #include "regexp.h"
35
36 class tree_argument_list;
37 class octave_user_function;
38
39 #include "oct-obj.h"
40 #include "workspace-element.h"
41 #include "oct-refcount.h"
42 #include "ov.h"
43
44 class
45 OCTINTERP_API
46 symbol_table
47 {
48 public:
49
50 typedef int scope_id;
51 typedef size_t context_id;
52
53 class
54 scope_id_cache
55 {
56 protected:
57
58 typedef std::set<scope_id>::iterator set_iterator;
59 typedef std::set<scope_id>::const_iterator set_const_iterator;
60
61 // We start with 2 because we allocate 0 for the global symbols
62 // and 1 for the top-level workspace.
63
64 scope_id_cache (void) : next_available (2), in_use (), free_list () { }
65
66 public:
67
68 ~scope_id_cache (void) { }
69
70 static scope_id alloc (void)
71 {
72 return instance_ok () ? instance->do_alloc () : -1;
73 }
74
75 static void free (scope_id scope)
76 {
77 if (instance_ok ())
78 return instance->do_free (scope);
79 }
80
81 static std::list<scope_id> scopes (void)
82 {
83 return instance_ok () ? instance->do_scopes () : std::list<scope_id> ();
84 }
85
86 static void create_instance (void);
87
88 static bool instance_ok (void)
89 {
90 bool retval = true;
91
92 if (! instance)
93 create_instance ();
94
95 if (! instance)
96 {
97 ::error ("unable to create scope_id_cache object!");
98
99 retval = false;
100 }
101
102 return retval;
103 }
104
105 private:
106
107 // No copying!
108
109 scope_id_cache (const scope_id_cache&);
110
111 scope_id_cache& operator = (const scope_id_cache&);
112
113 static scope_id_cache *instance;
114
115 static void cleanup_instance (void) { delete instance; instance = 0; }
116
117 // The next available scope not in the free list.
118 scope_id next_available;
119
120 // The set of scope IDs that are currently allocated.
121 std::set<scope_id> in_use;
122
123 // The set of scope IDs that are currently available.
124 std::set<scope_id> free_list;
125
126 scope_id do_alloc (void)
127 {
128 scope_id retval;
129
130 set_iterator p = free_list.begin ();
131
132 if (p != free_list.end ())
133 {
134 retval = *p;
135 free_list.erase (p);
136 }
137 else
138 retval = next_available++;
139
140 in_use.insert (retval);
141
142 return retval;
143 }
144
145 void do_free (scope_id scope)
146 {
147 set_iterator p = in_use.find (scope);
148
149 if (p != in_use.end ())
150 {
151 in_use.erase (p);
152 free_list.insert (scope);
153 }
154 else
155 error ("free_scope: scope %d not found!", scope);
156 }
157
158 std::list<scope_id> do_scopes (void) const
159 {
160 std::list<scope_id> retval;
161
162 for (set_const_iterator p = in_use.begin (); p != in_use.end (); p++)
163 retval.push_back (*p);
164
165 retval.sort ();
166
167 return retval;
168 }
169 };
170
171 class fcn_info;
172
173 class
174 symbol_record
175 {
176 public:
177
178 // generic variable
179 static const unsigned int local = 1;
180
181 // varargin, argn, .nargin., .nargout.
182 // (FIXME -- is this really used now?)
183 static const unsigned int automatic = 2;
184
185 // formal parameter
186 static const unsigned int formal = 4;
187
188 // not listed or cleared (.nargin., .nargout.)
189 static const unsigned int hidden = 8;
190
191 // inherited from parent scope; not cleared at function exit
192 static const unsigned int inherited = 16;
193
194 // global (redirects to global scope)
195 static const unsigned int global = 32;
196
197 // not cleared at function exit
198 static const unsigned int persistent = 64;
199
200 // this symbol may NOT become a variable.
201 // (symbol added to a static workspace)
202 static const unsigned int added_static = 128;
203
204 private:
205
206 class
207 symbol_record_rep
208 {
209 public:
210
211 symbol_record_rep (scope_id s, const std::string& nm,
212 const octave_value& v, unsigned int sc)
213 : decl_scope (s), curr_fcn (0), name (nm), value_stack (),
214 storage_class (sc), finfo (), valid (true), count (1)
215 {
216 value_stack.push_back (v);
217 }
218
219 void assign (const octave_value& value,
220 context_id context = xdefault_context)
221 {
222 varref (context) = value;
223 }
224
225 void assign (octave_value::assign_op op,
226 const std::string& type,
227 const std::list<octave_value_list>& idx,
228 const octave_value& value,
229 context_id context = xdefault_context)
230 {
231 varref(context).assign (op, type, idx, value);
232 }
233
234 void assign (octave_value::assign_op op, const octave_value& value,
235 context_id context = xdefault_context)
236 {
237 varref(context).assign (op, value);
238 }
239
240 void do_non_const_unary_op (octave_value::unary_op op,
241 context_id context = xdefault_context)
242 {
243 varref(context).do_non_const_unary_op (op);
244 }
245
246 void do_non_const_unary_op (octave_value::unary_op op,
247 const std::string& type,
248 const std::list<octave_value_list>& idx,
249 context_id context = xdefault_context)
250 {
251 varref(context).do_non_const_unary_op (op, type, idx);
252 }
253
254 octave_value& varref (context_id context = xdefault_context)
255 {
256 // We duplicate global_varref and persistent_varref here to
257 // avoid calling deprecated functions.
258
259 if (is_global ())
260 {
261 symbol_table::global_table_iterator p
262 = symbol_table::global_table.find (name);
263
264 return (p == symbol_table::global_table.end ())
265 ? symbol_table::global_table[name] : p->second;
266 }
267 else if (is_persistent ())
268 {
269 static octave_value foobar;
270
271 symbol_table *inst
272 = symbol_table::get_instance (symbol_table::current_scope ());
273
274 return inst ? inst->do_persistent_varref (name) : foobar;
275 }
276 else
277 {
278 if (context == xdefault_context)
279 context = active_context ();
280
281 context_id n = value_stack.size ();
282 while (n++ <= context)
283 value_stack.push_back (octave_value ());
284
285 return value_stack[context];
286 }
287 }
288
289 octave_value varval (context_id context = xdefault_context) const
290 {
291 if (is_global ())
292 return symbol_table::global_varval (name);
293 else if (is_persistent ())
294 return symbol_table::persistent_varval (name);
295 else
296 {
297 if (context == xdefault_context)
298 context = active_context ();
299
300 if (context < value_stack.size ())
301 return value_stack[context];
302 else
303 return octave_value ();
304 }
305 }
306
307 void push_context (scope_id s)
308 {
309 if (! (is_persistent () || is_global ())
310 && s == scope ())
311 value_stack.push_back (octave_value ());
312 }
313
314 // If pop_context returns 0, we are out of values and this element
315 // of the symbol table should be deleted. This can happen for
316 // functions like
317 //
318 // function foo (n)
319 // if (n > 0)
320 // foo (n-1);
321 // else
322 // eval ("x = 1");
323 // endif
324 // endfunction
325 //
326 // Here, X should only exist in the final stack frame.
327
328 size_t pop_context (scope_id s)
329 {
330 size_t retval = 1;
331
332 if (! (is_persistent () || is_global ())
333 && s == scope ())
334 {
335 value_stack.pop_back ();
336 retval = value_stack.size ();
337 }
338
339 return retval;
340 }
341
342 void clear (void) { clear (scope ()); }
343
344 void clear (scope_id s)
345 {
346 if (! (is_hidden () || is_inherited ())
347 && s == scope ())
348 {
349 if (is_global ())
350 unmark_global ();
351
352 if (is_persistent ())
353 {
354 symbol_table::persistent_assign (name, varval ());
355
356 unmark_persistent ();
357 }
358
359 assign (octave_value ());
360 }
361 }
362
363 bool is_defined (context_id context = xdefault_context) const
364 {
365 if (context == xdefault_context)
366 context = active_context ();
367
368 return varval (context).is_defined ();
369 }
370
371 bool is_valid (void) const
372 {
373 return valid;
374 }
375
376 bool is_variable (context_id context) const
377 {
378 if (context == xdefault_context)
379 context = active_context ();
380
381 return (! is_local () || is_defined (context));
382 }
383
384 bool is_local (void) const { return storage_class & local; }
385 bool is_automatic (void) const { return storage_class & automatic; }
386 bool is_formal (void) const { return storage_class & formal; }
387 bool is_hidden (void) const { return storage_class & hidden; }
388 bool is_inherited (void) const { return storage_class & inherited; }
389 bool is_global (void) const { return storage_class & global; }
390 bool is_persistent (void) const { return storage_class & persistent; }
391 bool is_added_static (void) const {return storage_class & added_static; }
392
393 void mark_local (void) { storage_class |= local; }
394 void mark_automatic (void) { storage_class |= automatic; }
395 void mark_formal (void) { storage_class |= formal; }
396 void mark_hidden (void) { storage_class |= hidden; }
397 void mark_inherited (void) { storage_class |= inherited; }
398 void mark_global (void)
399 {
400 if (is_persistent ())
401 error ("can't make persistent variable %s global", name.c_str ());
402 else
403 storage_class |= global;
404 }
405 void mark_persistent (void)
406 {
407 if (is_global ())
408 error ("can't make global variable %s persistent", name.c_str ());
409 else
410 storage_class |= persistent;
411 }
412 void mark_added_static (void) { storage_class |= added_static; }
413
414 void unmark_local (void) { storage_class &= ~local; }
415 void unmark_automatic (void) { storage_class &= ~automatic; }
416 void unmark_formal (void) { storage_class &= ~formal; }
417 void unmark_hidden (void) { storage_class &= ~hidden; }
418 void unmark_inherited (void) { storage_class &= ~inherited; }
419 void unmark_global (void) { storage_class &= ~global; }
420 void unmark_persistent (void) { storage_class &= ~persistent; }
421 void unmark_added_static (void) { storage_class &= ~added_static; }
422
423 void init_persistent (void)
424 {
425 if (! is_defined ())
426 {
427 mark_persistent ();
428
429 assign (symbol_table::persistent_varval (name));
430 }
431 // FIXME -- this causes trouble with recursive calls.
432 // else
433 // error ("unable to declare existing variable persistent");
434 }
435
436 void invalidate (void)
437 {
438 valid = false;
439 }
440
441 void erase_persistent (void)
442 {
443 unmark_persistent ();
444 symbol_table::erase_persistent (name);
445 }
446
447 OCTINTERP_API context_id active_context (void) const;
448
449 scope_id scope (void) const { return decl_scope; }
450
451 void set_curr_fcn (octave_user_function *fcn)
452 {
453 curr_fcn = fcn;
454 }
455
456 symbol_record_rep *dup (scope_id new_scope) const
457 {
458 return new symbol_record_rep (new_scope, name, varval (),
459 storage_class);
460 }
461
462 void dump (std::ostream& os, const std::string& prefix) const;
463
464 scope_id decl_scope;
465
466 octave_user_function* curr_fcn;
467
468 std::string name;
469
470 std::deque<octave_value> value_stack;
471
472 unsigned int storage_class;
473
474 fcn_info *finfo;
475
476 bool valid;
477
478 octave_refcount<size_t> count;
479
480 private:
481
482 // No copying!
483
484 symbol_record_rep (const symbol_record_rep& ov);
485
486 symbol_record_rep& operator = (const symbol_record_rep&);
487 };
488
489 public:
490
491 symbol_record (scope_id s = xcurrent_scope,
492 const std::string& nm = std::string (),
493 const octave_value& v = octave_value (),
494 unsigned int sc = local)
495 : rep (new symbol_record_rep (s, nm, v, sc)) { }
496
497 symbol_record (const symbol_record& sr)
498 : rep (sr.rep)
499 {
500 rep->count++;
501 }
502
503 symbol_record& operator = (const symbol_record& sr)
504 {
505 if (this != &sr)
506 {
507 if (--rep->count == 0)
508 delete rep;
509
510 rep = sr.rep;
511 rep->count++;
512 }
513
514 return *this;
515 }
516
517 ~symbol_record (void)
518 {
519 if (--rep->count == 0)
520 delete rep;
521 }
522
523 symbol_record dup (scope_id new_scope) const
524 {
525 return symbol_record (rep->dup (new_scope));
526 }
527
528 const std::string& name (void) const { return rep->name; }
529
530 void rename (const std::string& new_name) { rep->name = new_name; }
531
532 octave_value
533 find (const octave_value_list& args = octave_value_list ()) const;
534
535 void assign (const octave_value& value,
536 context_id context = xdefault_context)
537 {
538 rep->assign (value, context);
539 }
540
541 void assign (octave_value::assign_op op,
542 const std::string& type,
543 const std::list<octave_value_list>& idx,
544 const octave_value& value,
545 context_id context = xdefault_context)
546 {
547 rep->assign (op, type, idx, value, context);
548 }
549
550 void assign (octave_value::assign_op op, const octave_value& value,
551 context_id context = xdefault_context)
552 {
553 rep->assign (op, value, context);
554 }
555
556 void do_non_const_unary_op (octave_value::unary_op op)
557 {
558 rep->do_non_const_unary_op (op);
559 }
560
561 void do_non_const_unary_op (octave_value::unary_op op,
562 const std::string& type,
563 const std::list<octave_value_list>& idx)
564 {
565 rep->do_non_const_unary_op (op, type, idx);
566 }
567
568 // Delete when deprecated varref functions are removed.
569 octave_value& varref (context_id context = xdefault_context)
570 {
571 return rep->varref (context);
572 }
573
574 octave_value varval (context_id context = xdefault_context) const
575 {
576 return rep->varval (context);
577 }
578
579 void push_context (scope_id s) { rep->push_context (s); }
580
581 size_t pop_context (scope_id s) { return rep->pop_context (s); }
582
583 void clear (void) { rep->clear (); }
584
585 void clear (scope_id s) { rep->clear (s); }
586
587 bool is_defined (context_id context = xdefault_context) const
588 {
589 return rep->is_defined (context);
590 }
591
592 bool is_undefined (context_id context = xdefault_context) const
593 {
594 return ! rep->is_defined (context);
595 }
596
597 bool is_valid (void) const
598 {
599 return rep->is_valid ();
600 }
601
602 bool is_variable (context_id context = xdefault_context) const
603 {
604 return rep->is_variable (context);
605 }
606
607 bool is_local (void) const { return rep->is_local (); }
608 bool is_automatic (void) const { return rep->is_automatic (); }
609 bool is_formal (void) const { return rep->is_formal (); }
610 bool is_global (void) const { return rep->is_global (); }
611 bool is_hidden (void) const { return rep->is_hidden (); }
612 bool is_inherited (void) const { return rep->is_inherited (); }
613 bool is_persistent (void) const { return rep->is_persistent (); }
614 bool is_added_static (void) const { return rep->is_added_static (); }
615
616 void mark_local (void) { rep->mark_local (); }
617 void mark_automatic (void) { rep->mark_automatic (); }
618 void mark_formal (void) { rep->mark_formal (); }
619 void mark_hidden (void) { rep->mark_hidden (); }
620 void mark_inherited (void) { rep->mark_inherited (); }
621 void mark_global (void) { rep->mark_global (); }
622 void mark_persistent (void) { rep->mark_persistent (); }
623 void mark_added_static (void) { rep->mark_added_static (); }
624
625 void unmark_local (void) { rep->unmark_local (); }
626 void unmark_automatic (void) { rep->unmark_automatic (); }
627 void unmark_formal (void) { rep->unmark_formal (); }
628 void unmark_hidden (void) { rep->unmark_hidden (); }
629 void unmark_inherited (void) { rep->unmark_inherited (); }
630 void unmark_global (void) { rep->unmark_global (); }
631 void unmark_persistent (void) { rep->unmark_persistent (); }
632 void unmark_added_static (void) { rep->unmark_added_static (); }
633
634 void init_persistent (void) { rep->init_persistent (); }
635
636 void erase_persistent (void) { rep->erase_persistent (); }
637
638 void invalidate (void) { rep->invalidate (); }
639
640 context_id active_context (void) const { return rep->active_context (); }
641
642 scope_id scope (void) const { return rep->scope (); }
643
644 unsigned int xstorage_class (void) const { return rep->storage_class; }
645
646 void set_curr_fcn (octave_user_function *fcn) { rep->set_curr_fcn (fcn); }
647
648 void
649 dump (std::ostream& os, const std::string& prefix = std::string ()) const
650 {
651 rep->dump (os, prefix);
652 }
653
654 private:
655
656 symbol_record_rep *rep;
657
658 symbol_record (symbol_record_rep *new_rep) : rep (new_rep) { }
659 };
660
661 // Always access a symbol from the current scope.
662 // Useful for scripts, as they may be executed in more than one scope.
663 class
664 symbol_reference
665 {
666 public:
667
668 symbol_reference (void) : scope (-1) { }
669
670 symbol_reference (const symbol_record& record,
671 scope_id curr_scope = symbol_table::current_scope ())
672 : scope (curr_scope), sym (record)
673 { }
674
675 symbol_reference (const symbol_reference& ref)
676 : scope (ref.scope), sym (ref.sym)
677 { }
678
679 symbol_reference& operator = (const symbol_reference& ref)
680 {
681 if (this != &ref)
682 {
683 scope = ref.scope;
684 sym = ref.sym;
685 }
686 return *this;
687 }
688
689 bool is_black_hole (void) const { return scope < 0; }
690
691 // The name is the same regardless of scope.
692 const std::string& name (void) const { return sym.name (); }
693
694 symbol_record *operator-> (void)
695 {
696 update ();
697 return &sym;
698 }
699
700 symbol_record *operator-> (void) const
701 {
702 update ();
703 return &sym;
704 }
705
706 // can be used to place symbol_reference in maps, we don't overload < as
707 // it doesn't make any sense for symbol_reference
708 struct comparator
709 {
710 bool operator ()(const symbol_reference& lhs,
711 const symbol_reference& rhs) const
712 {
713 return lhs.name () < rhs.name ();
714 }
715 };
716 private:
717
718 void update (void) const
719 {
720 scope_id curr_scope = symbol_table::current_scope ();
721
722 if (scope != curr_scope || ! sym.is_valid ())
723 {
724 scope = curr_scope;
725 sym = symbol_table::insert (sym.name ());
726 }
727 }
728
729 mutable scope_id scope;
730 mutable symbol_record sym;
731 };
732
733 class
734 fcn_info
735 {
736 public:
737
738 typedef std::map<std::string, std::string> dispatch_map_type;
739
740 typedef std::map<scope_id, octave_value>::const_iterator scope_val_const_iterator;
741 typedef std::map<scope_id, octave_value>::iterator scope_val_iterator;
742
743 typedef std::map<std::string, octave_value>::const_iterator str_val_const_iterator;
744 typedef std::map<std::string, octave_value>::iterator str_val_iterator;
745
746 typedef dispatch_map_type::const_iterator dispatch_map_const_iterator;
747 typedef dispatch_map_type::iterator dispatch_map_iterator;
748
749 private:
750
751 class
752 fcn_info_rep
753 {
754 public:
755
756 fcn_info_rep (const std::string& nm)
757 : name (nm), subfunctions (), private_functions (),
758 class_constructors (), class_methods (), dispatch_map (),
759 cmdline_function (), autoload_function (), function_on_path (),
760 built_in_function (), count (1) { }
761
762 octave_value load_private_function (const std::string& dir_name);
763
764 octave_value load_class_constructor (void);
765
766 octave_value load_class_method (const std::string& dispatch_type);
767
768 octave_value find (const octave_value_list& args, bool local_funcs);
769
770 octave_value builtin_find (void);
771
772 octave_value find_method (const std::string& dispatch_type);
773
774 octave_value find_autoload (void);
775
776 octave_value find_user_function (void);
777
778 bool is_user_function_defined (void) const
779 {
780 return function_on_path.is_defined ();
781 }
782
783 octave_value find_function (const octave_value_list& args, bool local_funcs)
784 {
785 return find (args, local_funcs);
786 }
787
788 void lock_subfunction (scope_id scope)
789 {
790 scope_val_iterator p = subfunctions.find (scope);
791
792 if (p != subfunctions.end ())
793 p->second.lock ();
794 }
795
796 void unlock_subfunction (scope_id scope)
797 {
798 scope_val_iterator p = subfunctions.find (scope);
799
800 if (p != subfunctions.end ())
801 p->second.unlock ();
802 }
803
804 std::pair<std::string, octave_value>
805 subfunction_defined_in_scope (scope_id scope) const
806 {
807 scope_val_const_iterator p = subfunctions.find (scope);
808
809 return p == subfunctions.end ()
810 ? std::pair<std::string, octave_value> ()
811 : std::pair<std::string, octave_value> (name, p->second);
812 }
813
814 void erase_subfunction (scope_id scope)
815 {
816 scope_val_iterator p = subfunctions.find (scope);
817
818 if (p != subfunctions.end ())
819 subfunctions.erase (p);
820 }
821
822 void mark_subfunction_in_scope_as_private (scope_id scope,
823 const std::string& class_name);
824
825 void install_cmdline_function (const octave_value& f)
826 {
827 cmdline_function = f;
828 }
829
830 void install_subfunction (const octave_value& f, scope_id scope)
831 {
832 subfunctions[scope] = f;
833 }
834
835 void install_user_function (const octave_value& f)
836 {
837 function_on_path = f;
838 }
839
840 void install_built_in_function (const octave_value& f)
841 {
842 built_in_function = f;
843 }
844
845 template <class T>
846 void
847 clear_map (std::map<T, octave_value>& map, bool force = false)
848 {
849 typename std::map<T, octave_value>::iterator p = map.begin ();
850
851 while (p != map.end ())
852 {
853 if (force || ! p->second.islocked ())
854 map.erase (p++);
855 else
856 p++;
857 }
858 }
859
860 void clear_autoload_function (bool force = false)
861 {
862 if (force || ! autoload_function.islocked ())
863 autoload_function = octave_value ();
864 }
865
866 // We also clear command line functions here, as these are both
867 // "user defined"
868 void clear_user_function (bool force = false)
869 {
870 if (force || ! function_on_path.islocked ())
871 function_on_path = octave_value ();
872
873 if (force || ! cmdline_function.islocked ())
874 cmdline_function = octave_value ();
875 }
876
877 void clear_mex_function (void)
878 {
879 if (function_on_path.is_mex_function ())
880 clear_user_function ();
881 }
882
883 void clear (bool force = false)
884 {
885 clear_map (subfunctions, force);
886 clear_map (private_functions, force);
887 clear_map (class_constructors, force);
888 clear_map (class_methods, force);
889
890 clear_autoload_function (force);
891 clear_user_function (force);
892 }
893
894 void add_dispatch (const std::string& type, const std::string& fname)
895 {
896 dispatch_map[type] = fname;
897 }
898
899 void clear_dispatch (const std::string& type)
900 {
901 dispatch_map_iterator p = dispatch_map.find (type);
902
903 if (p != dispatch_map.end ())
904 dispatch_map.erase (p);
905 }
906
907 void print_dispatch (std::ostream& os) const;
908
909 std::string help_for_dispatch (void) const;
910
911 dispatch_map_type get_dispatch (void) const { return dispatch_map; }
912
913 void dump (std::ostream& os, const std::string& prefix) const;
914
915 std::string name;
916
917 // Scope id to function object.
918 std::map<scope_id, octave_value> subfunctions;
919
920 // Directory name to function object.
921 std::map<std::string, octave_value> private_functions;
922
923 // Class name to function object.
924 std::map<std::string, octave_value> class_constructors;
925
926 // Dispatch type to function object.
927 std::map<std::string, octave_value> class_methods;
928
929 // Legacy dispatch map (dispatch type name to function name).
930 dispatch_map_type dispatch_map;
931
932 octave_value cmdline_function;
933
934 octave_value autoload_function;
935
936 octave_value function_on_path;
937
938 octave_value built_in_function;
939
940 octave_refcount<size_t> count;
941
942 private:
943
944 octave_value xfind (const octave_value_list& args, bool local_funcs);
945
946 octave_value x_builtin_find (void);
947
948 // No copying!
949
950 fcn_info_rep (const fcn_info_rep&);
951
952 fcn_info_rep& operator = (const fcn_info_rep&);
953 };
954
955 public:
956
957 fcn_info (const std::string& nm = std::string ())
958 : rep (new fcn_info_rep (nm)) { }
959
960 fcn_info (const fcn_info& fi) : rep (fi.rep)
961 {
962 rep->count++;
963 }
964
965 fcn_info& operator = (const fcn_info& fi)
966 {
967 if (this != &fi)
968 {
969 if (--rep->count == 0)
970 delete rep;
971
972 rep = fi.rep;
973 rep->count++;
974 }
975
976 return *this;
977 }
978
979 ~fcn_info (void)
980 {
981 if (--rep->count == 0)
982 delete rep;
983 }
984
985 octave_value find (const octave_value_list& args = octave_value_list (),
986 bool local_funcs = true)
987 {
988 return rep->find (args, local_funcs);
989 }
990
991 octave_value builtin_find (void)
992 {
993 return rep->builtin_find ();
994 }
995
996 octave_value find_method (const std::string& dispatch_type) const
997 {
998 return rep->find_method (dispatch_type);
999 }
1000
1001 octave_value find_built_in_function (void) const
1002 {
1003 return rep->built_in_function;
1004 }
1005
1006 octave_value find_cmdline_function (void) const
1007 {
1008 return rep->cmdline_function;
1009 }
1010
1011 octave_value find_autoload (void)
1012 {
1013 return rep->find_autoload ();
1014 }
1015
1016 octave_value find_user_function (void)
1017 {
1018 return rep->find_user_function ();
1019 }
1020
1021 bool is_user_function_defined (void) const
1022 {
1023 return rep->is_user_function_defined ();
1024 }
1025
1026 octave_value find_function (const octave_value_list& args = octave_value_list (),
1027 bool local_funcs = true)
1028 {
1029 return rep->find_function (args, local_funcs);
1030 }
1031
1032 void lock_subfunction (scope_id scope)
1033 {
1034 rep->lock_subfunction (scope);
1035 }
1036
1037 void unlock_subfunction (scope_id scope)
1038 {
1039 rep->unlock_subfunction (scope);
1040 }
1041
1042 std::pair<std::string, octave_value>
1043 subfunction_defined_in_scope (scope_id scope = xcurrent_scope) const
1044 {
1045 return rep->subfunction_defined_in_scope (scope);
1046 }
1047
1048 void erase_subfunction (scope_id scope)
1049 {
1050 rep->erase_subfunction (scope);
1051 }
1052
1053 void mark_subfunction_in_scope_as_private (scope_id scope,
1054 const std::string& class_name)
1055 {
1056 rep->mark_subfunction_in_scope_as_private (scope, class_name);
1057 }
1058
1059 void install_cmdline_function (const octave_value& f)
1060 {
1061 rep->install_cmdline_function (f);
1062 }
1063
1064 void install_subfunction (const octave_value& f, scope_id scope)
1065 {
1066 rep->install_subfunction (f, scope);
1067 }
1068
1069 void install_user_function (const octave_value& f)
1070 {
1071 rep->install_user_function (f);
1072 }
1073
1074 void install_built_in_function (const octave_value& f)
1075 {
1076 rep->install_built_in_function (f);
1077 }
1078
1079 void clear (bool force = false) { rep->clear (force); }
1080
1081 void clear_user_function (bool force = false)
1082 {
1083 rep->clear_user_function (force);
1084 }
1085
1086 void clear_autoload_function (bool force = false)
1087 {
1088 rep->clear_autoload_function (force);
1089 }
1090
1091 void clear_mex_function (void) { rep->clear_mex_function (); }
1092
1093 void add_dispatch (const std::string& type, const std::string& fname)
1094 {
1095 rep->add_dispatch (type, fname);
1096 }
1097
1098 void clear_dispatch (const std::string& type)
1099 {
1100 rep->clear_dispatch (type);
1101 }
1102
1103 void print_dispatch (std::ostream& os) const
1104 {
1105 rep->print_dispatch (os);
1106 }
1107
1108 std::string help_for_dispatch (void) const { return rep->help_for_dispatch (); }
1109
1110 dispatch_map_type get_dispatch (void) const
1111 {
1112 return rep->get_dispatch ();
1113 }
1114
1115 void
1116 dump (std::ostream& os, const std::string& prefix = std::string ()) const
1117 {
1118 rep->dump (os, prefix);
1119 }
1120
1121 private:
1122
1123 fcn_info_rep *rep;
1124 };
1125
1126 static scope_id global_scope (void) { return xglobal_scope; }
1127 static scope_id top_scope (void) { return xtop_scope; }
1128
1129 static scope_id current_scope (void) { return xcurrent_scope; }
1130
1131 static context_id current_context (void) { return xcurrent_context; }
1132
1133 static scope_id alloc_scope (void) { return scope_id_cache::alloc (); }
1134
1135 static void set_scope (scope_id scope)
1136 {
1137 if (scope == xglobal_scope)
1138 error ("can't set scope to global");
1139 else if (scope != xcurrent_scope)
1140 {
1141 all_instances_iterator p = all_instances.find (scope);
1142
1143 if (p == all_instances.end ())
1144 {
1145 symbol_table *inst = new symbol_table (scope);
1146
1147 if (inst)
1148 all_instances[scope] = instance = inst;
1149 }
1150 else
1151 instance = p->second;
1152
1153 xcurrent_scope = scope;
1154 xcurrent_context = 0;
1155 }
1156 }
1157
1158 static void set_scope_and_context (scope_id scope, context_id context)
1159 {
1160 if (scope == xglobal_scope)
1161 error ("can't set scope to global");
1162 else
1163 {
1164 if (scope != xcurrent_scope)
1165 {
1166 all_instances_iterator p = all_instances.find (scope);
1167
1168 if (p == all_instances.end ())
1169 error ("scope not found!");
1170 else
1171 {
1172 instance = p->second;
1173
1174 xcurrent_scope = scope;
1175
1176 xcurrent_context = context;
1177 }
1178 }
1179 else
1180 xcurrent_context = context;
1181 }
1182 }
1183
1184 static void erase_scope (scope_id scope)
1185 {
1186 assert (scope != xglobal_scope);
1187
1188 erase_subfunctions_in_scope (scope);
1189
1190 all_instances_iterator p = all_instances.find (scope);
1191
1192 if (p != all_instances.end ())
1193 {
1194 delete p->second;
1195
1196 all_instances.erase (p);
1197
1198 free_scope (scope);
1199 }
1200 }
1201
1202 static void erase_subfunctions_in_scope (scope_id scope)
1203 {
1204 for (fcn_table_iterator q = fcn_table.begin ();
1205 q != fcn_table.end (); q++)
1206 q->second.erase_subfunction (scope);
1207 }
1208
1209 static void
1210 mark_subfunctions_in_scope_as_private (scope_id scope,
1211 const std::string& class_name)
1212 {
1213 for (fcn_table_iterator q = fcn_table.begin ();
1214 q != fcn_table.end (); q++)
1215 q->second.mark_subfunction_in_scope_as_private (scope, class_name);
1216 }
1217
1218 static scope_id dup_scope (scope_id scope)
1219 {
1220 scope_id retval = -1;
1221
1222 symbol_table *inst = get_instance (scope);
1223
1224 if (inst)
1225 {
1226 scope_id new_scope = alloc_scope ();
1227
1228 symbol_table *new_symbol_table = new symbol_table (scope);
1229
1230 if (new_symbol_table)
1231 {
1232 all_instances[new_scope] = new_symbol_table;
1233
1234 inst->do_dup_scope (*new_symbol_table);
1235
1236 retval = new_scope;
1237 }
1238 }
1239
1240 return retval;
1241 }
1242
1243 static std::list<scope_id> scopes (void)
1244 {
1245 return scope_id_cache::scopes ();
1246 }
1247
1248 static symbol_record
1249 find_symbol (const std::string& name, scope_id scope = xcurrent_scope)
1250 {
1251 symbol_table *inst = get_instance (scope);
1252
1253 return inst ? inst->do_find_symbol (name) :
1254 symbol_record (scope);
1255 }
1256
1257 static void
1258 inherit (scope_id scope, scope_id donor_scope, context_id donor_context)
1259 {
1260 symbol_table *inst = get_instance (scope);
1261
1262 if (inst)
1263 {
1264 symbol_table *donor_symbol_table = get_instance (donor_scope);
1265
1266 if (donor_symbol_table)
1267 inst->do_inherit (*donor_symbol_table, donor_context);
1268 }
1269 }
1270
1271 static bool at_top_level (void) { return xcurrent_scope == xtop_scope; }
1272
1273 // Find a value corresponding to the given name in the table.
1274 static octave_value
1275 find (const std::string& name,
1276 const octave_value_list& args = octave_value_list (),
1277 bool skip_variables = false,
1278 bool local_funcs = true);
1279
1280 static octave_value builtin_find (const std::string& name);
1281
1282 // Insert a new name in the table.
1283 static symbol_record& insert (const std::string& name,
1284 scope_id scope = xcurrent_scope)
1285 {
1286 static symbol_record foobar;
1287
1288 symbol_table *inst = get_instance (scope);
1289
1290 return inst ? inst->do_insert (name) : foobar;
1291 }
1292
1293 static void rename (const std::string& old_name,
1294 const std::string& new_name,
1295 scope_id scope = xcurrent_scope)
1296 {
1297 symbol_table *inst = get_instance (scope);
1298
1299 if (inst)
1300 inst->do_rename (old_name, new_name);
1301 }
1302
1303 static void assign (const std::string& name,
1304 const octave_value& value = octave_value (),
1305 scope_id scope = xcurrent_scope,
1306 context_id context = xdefault_context,
1307 bool force_add = false)
1308 {
1309 static octave_value foobar;
1310
1311 symbol_table *inst = get_instance (scope);
1312
1313 if (inst)
1314 inst->do_assign (name, value, context, force_add);
1315 }
1316
1317 // Use assign (name, value, scope, context, force_add) instead.
1318 static octave_value&
1319 varref (const std::string& name, scope_id scope = xcurrent_scope,
1320 context_id context = xdefault_context, bool force_add = false)
1321 GCC_ATTR_DEPRECATED
1322 {
1323 static octave_value foobar;
1324
1325 symbol_table *inst = get_instance (scope);
1326
1327 return inst ? inst->do_varref (name, context, force_add) : foobar;
1328 }
1329
1330 // Convenience function to simplify
1331 // octave_user_function::bind_automatic_vars
1332
1333 static void force_assign (const std::string& name,
1334 const octave_value& value = octave_value (),
1335 scope_id scope = xcurrent_scope,
1336 context_id context = xdefault_context)
1337 {
1338 assign (name, value, scope, context, true);
1339 }
1340
1341 // Use force_assign (name, value, scope, context) instead.
1342 static octave_value&
1343 force_varref (const std::string& name, scope_id scope = xcurrent_scope,
1344 context_id context = xdefault_context) GCC_ATTR_DEPRECATED
1345 {
1346 static octave_value foobar;
1347
1348 symbol_table *inst = get_instance (scope);
1349
1350 return inst ? inst->do_varref (name, context, true) : foobar;
1351 }
1352
1353 static octave_value varval (const std::string& name,
1354 scope_id scope = xcurrent_scope,
1355 context_id context = xdefault_context)
1356 {
1357 symbol_table *inst = get_instance (scope);
1358
1359 return inst ? inst->do_varval (name, context) : octave_value ();
1360 }
1361
1362 static void
1363 global_assign (const std::string& name,
1364 const octave_value& value = octave_value ())
1365
1366 {
1367 global_table_iterator p = global_table.find (name);
1368
1369 if (p == global_table.end ())
1370 global_table[name] = value;
1371 else
1372 p->second = value;
1373 }
1374
1375 // Use global_assign (name, value) instead.
1376 static octave_value&
1377 global_varref (const std::string& name) GCC_ATTR_DEPRECATED
1378
1379 {
1380 global_table_iterator p = global_table.find (name);
1381
1382 return (p == global_table.end ()) ? global_table[name] : p->second;
1383 }
1384
1385 static octave_value
1386 global_varval (const std::string& name)
1387 {
1388 global_table_const_iterator p = global_table.find (name);
1389
1390 return (p != global_table.end ()) ? p->second : octave_value ();
1391 }
1392
1393 static void
1394 top_level_assign (const std::string& name,
1395 const octave_value& value = octave_value ())
1396 {
1397 assign (name, value, top_scope (), 0);
1398 }
1399
1400 // Use top_level_assign (name, value) instead.
1401 static octave_value&
1402 top_level_varref (const std::string& name) GCC_ATTR_DEPRECATED
1403 {
1404 static octave_value foobar;
1405
1406 symbol_table *inst = get_instance (top_scope ());
1407
1408 return inst ? inst->do_varref (name, 0, true) : foobar;
1409 }
1410
1411 static octave_value
1412 top_level_varval (const std::string& name)
1413 {
1414 return varval (name, top_scope (), 0);
1415 }
1416
1417 static void
1418 persistent_assign (const std::string& name,
1419 const octave_value& value = octave_value ())
1420 {
1421 symbol_table *inst = get_instance (xcurrent_scope);
1422
1423 if (inst)
1424 inst->do_persistent_assign (name, value);
1425 }
1426
1427 // Use persistent_assign (name, value) instead.
1428 static octave_value& persistent_varref (const std::string& name)
1429 GCC_ATTR_DEPRECATED
1430 {
1431 static octave_value foobar;
1432
1433 symbol_table *inst = get_instance (xcurrent_scope);
1434
1435 return inst ? inst->do_persistent_varref (name) : foobar;
1436 }
1437
1438 static octave_value persistent_varval (const std::string& name)
1439 {
1440 symbol_table *inst = get_instance (xcurrent_scope);
1441
1442 return inst ? inst->do_persistent_varval (name) : octave_value ();
1443 }
1444
1445 static void erase_persistent (const std::string& name)
1446 {
1447 symbol_table *inst = get_instance (xcurrent_scope);
1448
1449 if (inst)
1450 inst->do_erase_persistent (name);
1451 }
1452
1453 static bool is_variable (const std::string& name)
1454 {
1455 symbol_table *inst = get_instance (xcurrent_scope);
1456
1457 return inst ? inst->do_is_variable (name) : false;
1458 }
1459
1460 static bool
1461 is_built_in_function_name (const std::string& name)
1462 {
1463 octave_value val = find_built_in_function (name);
1464
1465 return val.is_defined ();
1466 }
1467
1468 static octave_value
1469 find_method (const std::string& name, const std::string& dispatch_type)
1470 {
1471 fcn_table_const_iterator p = fcn_table.find (name);
1472
1473 if (p != fcn_table.end ())
1474 return p->second.find_method (dispatch_type);
1475 else
1476 {
1477 fcn_info finfo (name);
1478
1479 octave_value fcn = finfo.find_method (dispatch_type);
1480
1481 if (fcn.is_defined ())
1482 fcn_table[name] = finfo;
1483
1484 return fcn;
1485 }
1486 }
1487
1488 static octave_value
1489 find_built_in_function (const std::string& name)
1490 {
1491 fcn_table_const_iterator p = fcn_table.find (name);
1492
1493 return (p != fcn_table.end ())
1494 ? p->second.find_built_in_function () : octave_value ();
1495 }
1496
1497 static octave_value
1498 find_autoload (const std::string& name)
1499 {
1500 fcn_table_iterator p = fcn_table.find (name);
1501
1502 return (p != fcn_table.end ())
1503 ? p->second.find_autoload () : octave_value ();
1504 }
1505
1506 static octave_value
1507 find_function (const std::string& name,
1508 const octave_value_list& args = octave_value_list (),
1509 bool local_funcs = true);
1510
1511 static octave_value find_user_function (const std::string& name)
1512 {
1513 fcn_table_iterator p = fcn_table.find (name);
1514
1515 return (p != fcn_table.end ())
1516 ? p->second.find_user_function () : octave_value ();
1517 }
1518
1519 static void install_cmdline_function (const std::string& name,
1520 const octave_value& fcn)
1521 {
1522 fcn_table_iterator p = fcn_table.find (name);
1523
1524 if (p != fcn_table.end ())
1525 {
1526 fcn_info& finfo = p->second;
1527
1528 finfo.install_cmdline_function (fcn);
1529 }
1530 else
1531 {
1532 fcn_info finfo (name);
1533
1534 finfo.install_cmdline_function (fcn);
1535
1536 fcn_table[name] = finfo;
1537 }
1538 }
1539
1540 // Install subfunction FCN named NAME. SCOPE is the scope of the
1541 // primary function corresponding to this subfunction.
1542
1543 static void install_subfunction (const std::string& name,
1544 const octave_value& fcn,
1545 scope_id scope)
1546 {
1547 fcn_table_iterator p = fcn_table.find (name);
1548
1549 if (p != fcn_table.end ())
1550 {
1551 fcn_info& finfo = p->second;
1552
1553 finfo.install_subfunction (fcn, scope);
1554 }
1555 else
1556 {
1557 fcn_info finfo (name);
1558
1559 finfo.install_subfunction (fcn, scope);
1560
1561 fcn_table[name] = finfo;
1562 }
1563 }
1564
1565 static void install_nestfunction (const std::string& name,
1566 const octave_value& fcn,
1567 scope_id parent_scope);
1568
1569 static void update_nest (scope_id scope)
1570 {
1571 symbol_table *inst = get_instance (scope);
1572 if (inst)
1573 inst->do_update_nest ();
1574 }
1575
1576 static void install_user_function (const std::string& name,
1577 const octave_value& fcn)
1578 {
1579 fcn_table_iterator p = fcn_table.find (name);
1580
1581 if (p != fcn_table.end ())
1582 {
1583 fcn_info& finfo = p->second;
1584
1585 finfo.install_user_function (fcn);
1586 }
1587 else
1588 {
1589 fcn_info finfo (name);
1590
1591 finfo.install_user_function (fcn);
1592
1593 fcn_table[name] = finfo;
1594 }
1595 }
1596
1597 static void install_built_in_function (const std::string& name,
1598 const octave_value& fcn)
1599 {
1600 fcn_table_iterator p = fcn_table.find (name);
1601
1602 if (p != fcn_table.end ())
1603 {
1604 fcn_info& finfo = p->second;
1605
1606 finfo.install_built_in_function (fcn);
1607 }
1608 else
1609 {
1610 fcn_info finfo (name);
1611
1612 finfo.install_built_in_function (fcn);
1613
1614 fcn_table[name] = finfo;
1615 }
1616 }
1617
1618 static void clear (const std::string& name)
1619 {
1620 clear_variable (name);
1621 }
1622
1623 static void clear_all (bool force = false)
1624 {
1625 clear_variables ();
1626
1627 clear_global_pattern ("*");
1628
1629 clear_functions (force);
1630 }
1631
1632 static void clear_variables (scope_id scope)
1633 {
1634 symbol_table *inst = get_instance (scope);
1635
1636 if (inst)
1637 inst->do_clear_variables ();
1638 }
1639
1640 // This is split for unwind_protect.
1641 static void clear_variables (void)
1642 {
1643 clear_variables (xcurrent_scope);
1644 }
1645
1646 static void clear_objects (scope_id scope = xcurrent_scope)
1647 {
1648 symbol_table *inst = get_instance (scope);
1649
1650 if (inst)
1651 inst->do_clear_objects ();
1652 }
1653
1654 static void clear_functions (bool force = false)
1655 {
1656 for (fcn_table_iterator p = fcn_table.begin (); p != fcn_table.end (); p++)
1657 p->second.clear (force);
1658 }
1659
1660 static void clear_function (const std::string& name)
1661 {
1662 clear_user_function (name);
1663 }
1664
1665 static void clear_global (const std::string& name)
1666 {
1667 symbol_table *inst = get_instance (xcurrent_scope);
1668
1669 if (inst)
1670 inst->do_clear_global (name);
1671 }
1672
1673 static void clear_variable (const std::string& name)
1674 {
1675 symbol_table *inst = get_instance (xcurrent_scope);
1676
1677 if (inst)
1678 inst->do_clear_variable (name);
1679 }
1680
1681 static void clear_symbol (const std::string& name)
1682 {
1683 // FIXME -- are we supposed to do both here?
1684
1685 clear_variable (name);
1686 clear_function (name);
1687 }
1688
1689 static void clear_function_pattern (const std::string& pat)
1690 {
1691 glob_match pattern (pat);
1692
1693 for (fcn_table_iterator p = fcn_table.begin (); p != fcn_table.end (); p++)
1694 {
1695 if (pattern.match (p->first))
1696 p->second.clear_user_function ();
1697 }
1698 }
1699
1700 static void clear_global_pattern (const std::string& pat)
1701 {
1702 symbol_table *inst = get_instance (xcurrent_scope);
1703
1704 if (inst)
1705 inst->do_clear_global_pattern (pat);
1706 }
1707
1708 static void clear_variable_pattern (const std::string& pat)
1709 {
1710 symbol_table *inst = get_instance (xcurrent_scope);
1711
1712 if (inst)
1713 inst->do_clear_variable_pattern (pat);
1714 }
1715
1716 static void clear_variable_regexp (const std::string& pat)
1717 {
1718 symbol_table *inst = get_instance (xcurrent_scope);
1719
1720 if (inst)
1721 inst->do_clear_variable_regexp (pat);
1722 }
1723
1724 static void clear_symbol_pattern (const std::string& pat)
1725 {
1726 // FIXME -- are we supposed to do both here?
1727
1728 clear_variable_pattern (pat);
1729 clear_function_pattern (pat);
1730 }
1731
1732 static void clear_user_function (const std::string& name)
1733 {
1734 fcn_table_iterator p = fcn_table.find (name);
1735
1736 if (p != fcn_table.end ())
1737 {
1738 fcn_info& finfo = p->second;
1739
1740 finfo.clear_user_function ();
1741 }
1742 // FIXME -- is this necessary, or even useful?
1743 // else
1744 // error ("clear: no such function '%s'", name.c_str ());
1745 }
1746
1747 // This clears oct and mex files, incl. autoloads.
1748 static void clear_dld_function (const std::string& name)
1749 {
1750 fcn_table_iterator p = fcn_table.find (name);
1751
1752 if (p != fcn_table.end ())
1753 {
1754 fcn_info& finfo = p->second;
1755
1756 finfo.clear_autoload_function ();
1757 finfo.clear_user_function ();
1758 }
1759 }
1760
1761 static void clear_mex_functions (void)
1762 {
1763 for (fcn_table_iterator p = fcn_table.begin (); p != fcn_table.end (); p++)
1764 {
1765 fcn_info& finfo = p->second;
1766
1767 finfo.clear_mex_function ();
1768 }
1769 }
1770
1771 static bool set_class_relationship (const std::string& sup_class,
1772 const std::string& inf_class);
1773
1774 static bool is_superiorto (const std::string& a, const std::string& b);
1775
1776 static void alias_built_in_function (const std::string& alias,
1777 const std::string& name)
1778 {
1779 octave_value fcn = find_built_in_function (name);
1780
1781 if (fcn.is_defined ())
1782 {
1783 fcn_info finfo (alias);
1784
1785 finfo.install_built_in_function (fcn);
1786
1787 fcn_table[alias] = finfo;
1788 }
1789 else
1790 panic ("alias: '%s' is undefined", name.c_str ());
1791 }
1792
1793 static void add_dispatch (const std::string& name, const std::string& type,
1794 const std::string& fname)
1795 {
1796 fcn_table_iterator p = fcn_table.find (name);
1797
1798 if (p != fcn_table.end ())
1799 {
1800 fcn_info& finfo = p->second;
1801
1802 finfo.add_dispatch (type, fname);
1803 }
1804 else
1805 {
1806 fcn_info finfo (name);
1807
1808 finfo.add_dispatch (type, fname);
1809
1810 fcn_table[name] = finfo;
1811 }
1812 }
1813
1814 static void clear_dispatch (const std::string& name, const std::string& type)
1815 {
1816 fcn_table_iterator p = fcn_table.find (name);
1817
1818 if (p != fcn_table.end ())
1819 {
1820 fcn_info& finfo = p->second;
1821
1822 finfo.clear_dispatch (type);
1823 }
1824 }
1825
1826 static void print_dispatch (std::ostream& os, const std::string& name)
1827 {
1828 fcn_table_iterator p = fcn_table.find (name);
1829
1830 if (p != fcn_table.end ())
1831 {
1832 fcn_info& finfo = p->second;
1833
1834 finfo.print_dispatch (os);
1835 }
1836 }
1837
1838 static fcn_info::dispatch_map_type get_dispatch (const std::string& name)
1839 {
1840 fcn_info::dispatch_map_type retval;
1841
1842 fcn_table_iterator p = fcn_table.find (name);
1843
1844 if (p != fcn_table.end ())
1845 {
1846 fcn_info& finfo = p->second;
1847
1848 retval = finfo.get_dispatch ();
1849 }
1850
1851 return retval;
1852 }
1853
1854 static std::string help_for_dispatch (const std::string& name)
1855 {
1856 std::string retval;
1857
1858 fcn_table_iterator p = fcn_table.find (name);
1859
1860 if (p != fcn_table.end ())
1861 {
1862 fcn_info& finfo = p->second;
1863
1864 retval = finfo.help_for_dispatch ();
1865 }
1866
1867 return retval;
1868 }
1869
1870 static void push_context (void)
1871 {
1872 if (xcurrent_scope == xglobal_scope || xcurrent_scope == xtop_scope)
1873 error ("invalid call to xymtab::push_context");
1874 else
1875 {
1876 symbol_table *inst = get_instance (xcurrent_scope);
1877
1878 if (inst)
1879 inst->do_push_context ();
1880 }
1881 }
1882
1883 static void pop_context (void)
1884 {
1885 if (xcurrent_scope == xglobal_scope || xcurrent_scope == xtop_scope)
1886 error ("invalid call to xymtab::pop_context");
1887 else
1888 {
1889 symbol_table *inst = get_instance (xcurrent_scope);
1890
1891 if (inst)
1892 inst->do_pop_context ();
1893 }
1894 }
1895
1896 // For unwind_protect.
1897 static void pop_context (void *) { pop_context (); }
1898
1899 static void mark_automatic (const std::string& name)
1900 {
1901 symbol_table *inst = get_instance (xcurrent_scope);
1902
1903 if (inst)
1904 inst->do_mark_automatic (name);
1905 }
1906
1907 static void mark_hidden (const std::string& name)
1908 {
1909 symbol_table *inst = get_instance (xcurrent_scope);
1910
1911 if (inst)
1912 inst->do_mark_hidden (name);
1913 }
1914
1915 static void mark_global (const std::string& name)
1916 {
1917 symbol_table *inst = get_instance (xcurrent_scope);
1918
1919 if (inst)
1920 inst->do_mark_global (name);
1921 }
1922
1923 // exclude: Storage classes to exclude, you can OR them together
1924 static std::list<symbol_record>
1925 all_variables (scope_id scope = xcurrent_scope,
1926 context_id context = xdefault_context,
1927 bool defined_only = true,
1928 unsigned int exclude = symbol_record::hidden)
1929 {
1930 symbol_table *inst = get_instance (scope);
1931
1932 return inst
1933 ? inst->do_all_variables (context, defined_only, exclude)
1934 : std::list<symbol_record> ();
1935 }
1936
1937 static std::list<symbol_record> glob (const std::string& pattern)
1938 {
1939 symbol_table *inst = get_instance (xcurrent_scope);
1940
1941 return inst ? inst->do_glob (pattern) : std::list<symbol_record> ();
1942 }
1943
1944 static std::list<symbol_record> regexp (const std::string& pattern)
1945 {
1946 symbol_table *inst = get_instance (xcurrent_scope);
1947
1948 return inst ? inst->do_regexp (pattern) : std::list<symbol_record> ();
1949 }
1950
1951 static std::list<symbol_record> glob_variables (const std::string& pattern)
1952 {
1953 symbol_table *inst = get_instance (xcurrent_scope);
1954
1955 return inst ? inst->do_glob (pattern, true) : std::list<symbol_record> ();
1956 }
1957
1958 static std::list<symbol_record> regexp_variables (const std::string& pattern)
1959 {
1960 symbol_table *inst = get_instance (xcurrent_scope);
1961
1962 return inst ? inst->do_regexp (pattern, true) : std::list<symbol_record> ();
1963 }
1964
1965 static std::list<symbol_record>
1966 glob_global_variables (const std::string& pattern)
1967 {
1968 std::list<symbol_record> retval;
1969
1970 glob_match pat (pattern);
1971
1972 for (global_table_const_iterator p = global_table.begin ();
1973 p != global_table.end (); p++)
1974 {
1975 // We generate a list of symbol_record objects so that
1976 // the results from glob_variables and glob_global_variables
1977 // may be handled the same way.
1978
1979 if (pat.match (p->first))
1980 retval.push_back (symbol_record (xglobal_scope,
1981 p->first, p->second,
1982 symbol_record::global));
1983 }
1984
1985 return retval;
1986 }
1987
1988 static std::list<symbol_record>
1989 regexp_global_variables (const std::string& pattern)
1990 {
1991 std::list<symbol_record> retval;
1992
1993 ::regexp pat (pattern);
1994
1995 for (global_table_const_iterator p = global_table.begin ();
1996 p != global_table.end (); p++)
1997 {
1998 // We generate a list of symbol_record objects so that
1999 // the results from regexp_variables and regexp_global_variables
2000 // may be handled the same way.
2001
2002 if (pat.is_match (p->first))
2003 retval.push_back (symbol_record (xglobal_scope,
2004 p->first, p->second,
2005 symbol_record::global));
2006 }
2007
2008 return retval;
2009 }
2010
2011 static std::list<symbol_record> glob_variables (const string_vector& patterns)
2012 {
2013 std::list<symbol_record> retval;
2014
2015 size_t len = patterns.length ();
2016
2017 for (size_t i = 0; i < len; i++)
2018 {
2019 std::list<symbol_record> tmp = glob_variables (patterns[i]);
2020
2021 retval.insert (retval.begin (), tmp.begin (), tmp.end ());
2022 }
2023
2024 return retval;
2025 }
2026
2027 static std::list<symbol_record> regexp_variables
2028 (const string_vector& patterns)
2029 {
2030 std::list<symbol_record> retval;
2031
2032 size_t len = patterns.length ();
2033
2034 for (size_t i = 0; i < len; i++)
2035 {
2036 std::list<symbol_record> tmp = regexp_variables (patterns[i]);
2037
2038 retval.insert (retval.begin (), tmp.begin (), tmp.end ());
2039 }
2040
2041 return retval;
2042 }
2043
2044 static std::list<std::string> user_function_names (void)
2045 {
2046 std::list<std::string> retval;
2047
2048 for (fcn_table_iterator p = fcn_table.begin ();
2049 p != fcn_table.end (); p++)
2050 {
2051 if (p->second.is_user_function_defined ())
2052 retval.push_back (p->first);
2053 }
2054
2055 if (! retval.empty ())
2056 retval.sort ();
2057
2058 return retval;
2059 }
2060
2061 static std::list<std::string> global_variable_names (void)
2062 {
2063 std::list<std::string> retval;
2064
2065 for (global_table_const_iterator p = global_table.begin ();
2066 p != global_table.end (); p++)
2067 retval.push_back (p->first);
2068
2069 retval.sort ();
2070
2071 return retval;
2072 }
2073
2074 static std::list<std::string> top_level_variable_names (void)
2075 {
2076 symbol_table *inst = get_instance (xtop_scope);
2077
2078 return inst ? inst->do_variable_names () : std::list<std::string> ();
2079 }
2080
2081 static std::list<std::string> variable_names (void)
2082 {
2083 symbol_table *inst = get_instance (xcurrent_scope);
2084
2085 return inst ? inst->do_variable_names () : std::list<std::string> ();
2086 }
2087
2088 static std::list<std::string> built_in_function_names (void)
2089 {
2090 std::list<std::string> retval;
2091
2092 for (fcn_table_const_iterator p = fcn_table.begin ();
2093 p != fcn_table.end (); p++)
2094 {
2095 octave_value fcn = p->second.find_built_in_function ();
2096
2097 if (fcn.is_defined ())
2098 retval.push_back (p->first);
2099 }
2100
2101 if (! retval.empty ())
2102 retval.sort ();
2103
2104 return retval;
2105 }
2106
2107 static std::list<std::string> cmdline_function_names (void)
2108 {
2109 std::list<std::string> retval;
2110
2111 for (fcn_table_const_iterator p = fcn_table.begin ();
2112 p != fcn_table.end (); p++)
2113 {
2114 octave_value fcn = p->second.find_cmdline_function ();
2115
2116 if (fcn.is_defined ())
2117 retval.push_back (p->first);
2118 }
2119
2120 if (! retval.empty ())
2121 retval.sort ();
2122
2123 return retval;
2124 }
2125
2126 static bool is_local_variable (const std::string& name)
2127 {
2128 if (xcurrent_scope == xglobal_scope)
2129 return false;
2130 else
2131 {
2132 symbol_table *inst = get_instance (xcurrent_scope);
2133
2134 return inst ? inst->do_is_local_variable (name) : false;
2135 }
2136 }
2137
2138 static bool is_global (const std::string& name)
2139 {
2140 if (xcurrent_scope == xglobal_scope)
2141 return true;
2142 else
2143 {
2144 symbol_table *inst = get_instance (xcurrent_scope);
2145
2146 return inst ? inst->do_is_global (name) : false;
2147 }
2148 }
2149
2150 static std::list<workspace_element> workspace_info (void)
2151 {
2152 symbol_table *inst = get_instance (xcurrent_scope);
2153
2154 return inst
2155 ? inst->do_workspace_info () : std::list<workspace_element> ();
2156 }
2157
2158 static void dump (std::ostream& os, scope_id scope = xcurrent_scope);
2159
2160 static void dump_global (std::ostream& os);
2161
2162 static void dump_functions (std::ostream& os);
2163
2164 static void cache_name (scope_id scope, const std::string& name)
2165 {
2166 symbol_table *inst = get_instance (scope, false);
2167
2168 if (inst)
2169 inst->do_cache_name (name);
2170 }
2171
2172 static void lock_subfunctions (scope_id scope = xcurrent_scope)
2173 {
2174 for (fcn_table_iterator p = fcn_table.begin ();
2175 p != fcn_table.end (); p++)
2176 p->second.lock_subfunction (scope);
2177 }
2178
2179 static void unlock_subfunctions (scope_id scope = xcurrent_scope)
2180 {
2181 for (fcn_table_iterator p = fcn_table.begin ();
2182 p != fcn_table.end (); p++)
2183 p->second.unlock_subfunction (scope);
2184 }
2185
2186 static std::map<std::string, octave_value>
2187 subfunctions_defined_in_scope (scope_id scope = xcurrent_scope)
2188 {
2189 std::map<std::string, octave_value> retval;
2190
2191 for (fcn_table_const_iterator p = fcn_table.begin ();
2192 p != fcn_table.end (); p++)
2193 {
2194 std::pair<std::string, octave_value> tmp
2195 = p->second.subfunction_defined_in_scope (scope);
2196
2197 std::string nm = tmp.first;
2198
2199 if (! nm.empty ())
2200 retval[nm] = tmp.second;
2201 }
2202
2203 return retval;
2204 }
2205
2206 static void free_scope (scope_id scope)
2207 {
2208 if (scope == xglobal_scope || scope == xtop_scope)
2209 error ("can't free global or top-level scopes!");
2210 else
2211 symbol_table::scope_id_cache::free (scope);
2212 }
2213
2214 static void stash_dir_name_for_subfunctions (scope_id scope,
2215 const std::string& dir_name);
2216
2217 static void add_to_parent_map (const std::string& classname,
2218 const std::list<std::string>& parent_list)
2219 {
2220 parent_map[classname] = parent_list;
2221 }
2222
2223 static std::list<std::string>
2224 parent_classes (const std::string& dispatch_type)
2225 {
2226 std::list<std::string> retval;
2227
2228 const_parent_map_iterator it = parent_map.find (dispatch_type);
2229
2230 if (it != parent_map.end ())
2231 retval = it->second;
2232
2233 for (std::list<std::string>::const_iterator lit = retval.begin ();
2234 lit != retval.end (); lit++)
2235 {
2236 // Search for parents of parents and append them to the list.
2237
2238 // FIXME -- should we worry about a circular inheritance graph?
2239
2240 std::list<std::string> parents = parent_classes (*lit);
2241
2242 if (! parents.empty ())
2243 retval.insert (retval.end (), parents.begin (), parents.end ());
2244 }
2245
2246 return retval;
2247 }
2248
2249 static octave_user_function *get_curr_fcn (scope_id scope = xcurrent_scope)
2250 {
2251 symbol_table *inst = get_instance (scope);
2252 return inst->curr_fcn;
2253 }
2254
2255 static void set_curr_fcn (octave_user_function *curr_fcn,
2256 scope_id scope = xcurrent_scope)
2257 {
2258 assert (scope != xtop_scope && scope != xglobal_scope);
2259 symbol_table *inst = get_instance (scope);
2260 // FIXME: normally, functions should not usurp each other's scope.
2261 // If for any incredible reason this is needed, call
2262 // set_user_function (0, scope) first. This may cause problems with
2263 // nested functions, as the curr_fcn of symbol_records must be updated.
2264 assert (inst->curr_fcn == 0 || curr_fcn == 0);
2265 inst->curr_fcn = curr_fcn;
2266 }
2267
2268 static void cleanup (void);
2269
2270 private:
2271
2272 // No copying!
2273
2274 symbol_table (const symbol_table&);
2275
2276 symbol_table& operator = (const symbol_table&);
2277
2278 typedef std::map<std::string, symbol_record>::const_iterator table_const_iterator;
2279 typedef std::map<std::string, symbol_record>::iterator table_iterator;
2280
2281 typedef std::map<std::string, octave_value>::const_iterator global_table_const_iterator;
2282 typedef std::map<std::string, octave_value>::iterator global_table_iterator;
2283
2284 typedef std::map<std::string, octave_value>::const_iterator persistent_table_const_iterator;
2285 typedef std::map<std::string, octave_value>::iterator persistent_table_iterator;
2286
2287 typedef std::map<scope_id, symbol_table*>::const_iterator all_instances_const_iterator;
2288 typedef std::map<scope_id, symbol_table*>::iterator all_instances_iterator;
2289
2290 typedef std::map<std::string, fcn_info>::const_iterator fcn_table_const_iterator;
2291 typedef std::map<std::string, fcn_info>::iterator fcn_table_iterator;
2292
2293 // The scope of this symbol table.
2294 scope_id my_scope;
2295
2296 // Name for this table (usually the file name of the function
2297 // corresponding to the scope);
2298 std::string table_name;
2299
2300 // Map from symbol names to symbol info.
2301 std::map<std::string, symbol_record> table;
2302
2303 // Child nested functions.
2304 std::vector<symbol_table*> nest_children;
2305
2306 // Parent nested function (may be null).
2307 symbol_table *nest_parent;
2308
2309 // The associated user code (may be null).
2310 octave_user_function *curr_fcn;
2311
2312 // If true then no variables can be added.
2313 bool static_workspace;
2314
2315 // Map from names of global variables to values.
2316 static std::map<std::string, octave_value> global_table;
2317
2318 // Map from names of persistent variables to values.
2319 std::map<std::string, octave_value> persistent_table;
2320
2321 // Pointer to symbol table for current scope (variables only).
2322 static symbol_table *instance;
2323
2324 // Map from scope id to symbol table instances.
2325 static std::map<scope_id, symbol_table*> all_instances;
2326
2327 // Map from function names to function info (subfunctions, private
2328 // functions, class constructors, class methods, etc.)
2329 static std::map<std::string, fcn_info> fcn_table;
2330
2331 // Mape from class names to set of classes that have lower
2332 // precedence.
2333 static std::map<std::string, std::set<std::string> > class_precedence_table;
2334
2335 typedef std::map<std::string, std::set<std::string> >::const_iterator class_precedence_table_const_iterator;
2336 typedef std::map<std::string, std::set<std::string> >::iterator class_precedence_table_iterator;
2337
2338 // Map from class names to parent class names.
2339 static std::map<std::string, std::list<std::string> > parent_map;
2340
2341 typedef std::map<std::string, std::list<std::string> >::const_iterator const_parent_map_iterator;
2342 typedef std::map<std::string, std::list<std::string> >::iterator parent_map_iterator;
2343
2344 static const scope_id xglobal_scope;
2345 static const scope_id xtop_scope;
2346
2347 static scope_id xcurrent_scope;
2348
2349 static context_id xcurrent_context;
2350
2351 static const context_id xdefault_context = static_cast<context_id> (-1);
2352
2353 symbol_table (scope_id scope)
2354 : my_scope (scope), table_name (), table (), nest_children (), nest_parent (0),
2355 curr_fcn (0), static_workspace (false), persistent_table () { }
2356
2357 ~symbol_table (void) { }
2358
2359 static symbol_table *get_instance (scope_id scope, bool create = true)
2360 {
2361 symbol_table *retval = 0;
2362
2363 bool ok = true;
2364
2365 if (scope != xglobal_scope)
2366 {
2367 if (scope == xcurrent_scope)
2368 {
2369 if (! instance && create)
2370 {
2371 symbol_table *inst = new symbol_table (scope);
2372
2373 if (inst)
2374 {
2375 all_instances[scope] = instance = inst;
2376
2377 if (scope == xtop_scope)
2378 instance->do_cache_name ("top-level");
2379 }
2380 }
2381
2382 if (! instance)
2383 ok = false;
2384
2385 retval = instance;
2386 }
2387 else
2388 {
2389 all_instances_iterator p = all_instances.find (scope);
2390
2391 if (p == all_instances.end ())
2392 {
2393 if (create)
2394 {
2395 retval = new symbol_table (scope);
2396
2397 if (retval)
2398 all_instances[scope] = retval;
2399 else
2400 ok = false;
2401 }
2402 else
2403 ok = false;
2404 }
2405 else
2406 retval = p->second;
2407 }
2408 }
2409
2410 if (! ok)
2411 error ("unable to %s symbol_table object for scope %d!",
2412 create ? "create" : "find", scope);
2413
2414 return retval;
2415 }
2416
2417 void add_nest_child (symbol_table& st)
2418 {
2419 assert (!st.nest_parent);
2420 nest_children.push_back (&st);
2421 st.nest_parent = this;
2422 }
2423
2424 void insert_symbol_record (const symbol_record& sr)
2425 {
2426 table[sr.name ()] = sr;
2427 }
2428
2429 void
2430 do_dup_scope (symbol_table& new_symbol_table) const
2431 {
2432 for (table_const_iterator p = table.begin (); p != table.end (); p++)
2433 new_symbol_table.insert_symbol_record (p->second.dup (new_symbol_table.my_scope));
2434 }
2435
2436 symbol_record do_find_symbol (const std::string& name)
2437 {
2438 table_iterator p = table.find (name);
2439
2440 if (p == table.end ())
2441 return do_insert (name);
2442 else
2443 return p->second;
2444 }
2445
2446 void do_inherit (symbol_table& donor_table, context_id donor_context)
2447 {
2448 for (table_iterator p = table.begin (); p != table.end (); p++)
2449 {
2450 symbol_record& sr = p->second;
2451
2452 if (! (sr.is_automatic () || sr.is_formal ()))
2453 {
2454 std::string nm = sr.name ();
2455
2456 if (nm != "__retval__")
2457 {
2458 octave_value val = donor_table.do_varval (nm, donor_context);
2459
2460 if (val.is_defined ())
2461 {
2462 sr.assign (val, 0);
2463
2464 sr.mark_inherited ();
2465 }
2466 }
2467 }
2468 }
2469 }
2470
2471 static fcn_info *get_fcn_info (const std::string& name)
2472 {
2473 fcn_table_iterator p = fcn_table.find (name);
2474 return p != fcn_table.end () ? &p->second : 0;
2475 }
2476
2477 octave_value
2478 do_find (const std::string& name, const octave_value_list& args,
2479 bool skip_variables, bool local_funcs);
2480
2481 octave_value do_builtin_find (const std::string& name);
2482
2483 symbol_record& do_insert (const std::string& name, bool force_add = false)
2484 {
2485 table_iterator p = table.find (name);
2486
2487 if (p == table.end ())
2488 {
2489 symbol_record ret (my_scope, name);
2490
2491 if (nest_parent && nest_parent->look_nonlocal (name, ret))
2492 return table[name] = ret;
2493 else
2494 {
2495 if (static_workspace && ! force_add)
2496 ret.mark_added_static ();
2497
2498 return table[name] = ret;
2499 }
2500 }
2501 else
2502 return p->second;
2503 }
2504
2505 void do_rename (const std::string& old_name, const std::string& new_name)
2506 {
2507 table_iterator p = table.find (old_name);
2508
2509 if (p != table.end ())
2510 {
2511 symbol_record sr = p->second;
2512
2513 sr.rename (new_name);
2514
2515 table.erase (p);
2516
2517 table[new_name] = sr;
2518 }
2519 }
2520
2521 void do_assign (const std::string& name, const octave_value& value,
2522 context_id context, bool force_add)
2523 {
2524 table_iterator p = table.find (name);
2525
2526 if (p == table.end ())
2527 {
2528 symbol_record& sr = do_insert (name, force_add);
2529
2530 sr.assign (value, context);
2531 }
2532 else
2533 p->second.assign (value, context);
2534 }
2535
2536 // Use do_assign (name, value, context, force_add) instead.
2537 // Delete when deprecated varref functions are removed.
2538 octave_value& do_varref (const std::string& name, context_id context,
2539 bool force_add)
2540 {
2541 table_iterator p = table.find (name);
2542
2543 if (p == table.end ())
2544 {
2545 symbol_record& sr = do_insert (name, force_add);
2546
2547 return sr.varref (context);
2548 }
2549 else
2550 return p->second.varref (context);
2551 }
2552
2553 octave_value do_varval (const std::string& name, context_id context) const
2554 {
2555 table_const_iterator p = table.find (name);
2556
2557 return (p != table.end ()) ? p->second.varval (context) : octave_value ();
2558 }
2559
2560 void do_persistent_assign (const std::string& name,
2561 const octave_value& value)
2562 {
2563 persistent_table_iterator p = persistent_table.find (name);
2564
2565 if (p == persistent_table.end ())
2566 persistent_table[name] = value;
2567 else
2568 p->second = value;
2569 }
2570
2571 // Use do_persistent_assign (name, value) instead.
2572 // Delete when deprecated varref functions are removed.
2573 octave_value& do_persistent_varref (const std::string& name)
2574 {
2575 persistent_table_iterator p = persistent_table.find (name);
2576
2577 return (p == persistent_table.end ())
2578 ? persistent_table[name] : p->second;
2579 }
2580
2581 octave_value do_persistent_varval (const std::string& name)
2582 {
2583 persistent_table_const_iterator p = persistent_table.find (name);
2584
2585 return (p != persistent_table.end ()) ? p->second : octave_value ();
2586 }
2587
2588 void do_erase_persistent (const std::string& name)
2589 {
2590 persistent_table_iterator p = persistent_table.find (name);
2591
2592 if (p != persistent_table.end ())
2593 persistent_table.erase (p);
2594 }
2595
2596 bool do_is_variable (const std::string& name) const
2597 {
2598 bool retval = false;
2599
2600 table_const_iterator p = table.find (name);
2601
2602 if (p != table.end ())
2603 {
2604 const symbol_record& sr = p->second;
2605
2606 retval = sr.is_variable ();
2607 }
2608
2609 return retval;
2610 }
2611
2612 void do_push_context (void)
2613 {
2614 for (table_iterator p = table.begin (); p != table.end (); p++)
2615 p->second.push_context (my_scope);
2616 }
2617
2618 void do_pop_context (void)
2619 {
2620 table_iterator p = table.begin ();
2621
2622 while (p != table.end ())
2623 {
2624 if (p->second.pop_context (my_scope) == 0)
2625 table.erase (p++);
2626 else
2627 p++;
2628 }
2629 }
2630
2631 void do_clear_variables (void)
2632 {
2633 for (table_iterator p = table.begin (); p != table.end (); p++)
2634 p->second.clear (my_scope);
2635 }
2636
2637 void do_clear_objects (void)
2638 {
2639 for (table_iterator p = table.begin (); p != table.end (); p++)
2640 {
2641 symbol_record& sr = p->second;
2642 octave_value val = sr.varval ();
2643 if (val.is_object ())
2644 p->second.clear (my_scope);
2645 }
2646 }
2647
2648 void do_clear_global (const std::string& name)
2649 {
2650 table_iterator p = table.find (name);
2651
2652 if (p != table.end ())
2653 {
2654 symbol_record& sr = p->second;
2655
2656 if (sr.is_global ())
2657 sr.unmark_global ();
2658 }
2659
2660 global_table_iterator q = global_table.find (name);
2661
2662 if (q != global_table.end ())
2663 global_table.erase (q);
2664
2665 }
2666
2667 void do_clear_variable (const std::string& name)
2668 {
2669 table_iterator p = table.find (name);
2670
2671 if (p != table.end ())
2672 p->second.clear (my_scope);
2673 }
2674
2675 void do_clear_global_pattern (const std::string& pat)
2676 {
2677 glob_match pattern (pat);
2678
2679 for (table_iterator p = table.begin (); p != table.end (); p++)
2680 {
2681 symbol_record& sr = p->second;
2682
2683 if (sr.is_global () && pattern.match (sr.name ()))
2684 sr.unmark_global ();
2685 }
2686
2687 global_table_iterator q = global_table.begin ();
2688
2689 while (q != global_table.end ())
2690 {
2691 if (pattern.match (q->first))
2692 global_table.erase (q++);
2693 else
2694 q++;
2695 }
2696
2697
2698 }
2699
2700 void do_clear_variable_pattern (const std::string& pat)
2701 {
2702 glob_match pattern (pat);
2703
2704 for (table_iterator p = table.begin (); p != table.end (); p++)
2705 {
2706 symbol_record& sr = p->second;
2707
2708 if (sr.is_defined () || sr.is_global ())
2709 {
2710 if (pattern.match (sr.name ()))
2711 sr.clear (my_scope);
2712 }
2713 }
2714 }
2715
2716 void do_clear_variable_regexp (const std::string& pat)
2717 {
2718 ::regexp pattern (pat);
2719
2720 for (table_iterator p = table.begin (); p != table.end (); p++)
2721 {
2722 symbol_record& sr = p->second;
2723
2724 if (sr.is_defined () || sr.is_global ())
2725 {
2726 if (pattern.is_match (sr.name ()))
2727 sr.clear (my_scope);
2728 }
2729 }
2730 }
2731
2732 void do_mark_automatic (const std::string& name)
2733 {
2734 do_insert (name).mark_automatic ();
2735 }
2736
2737 void do_mark_hidden (const std::string& name)
2738 {
2739 do_insert (name).mark_hidden ();
2740 }
2741
2742 void do_mark_global (const std::string& name)
2743 {
2744 do_insert (name).mark_global ();
2745 }
2746
2747 std::list<symbol_record>
2748 do_all_variables (context_id context, bool defined_only,
2749 unsigned int exclude) const
2750 {
2751 std::list<symbol_record> retval;
2752
2753 for (table_const_iterator p = table.begin (); p != table.end (); p++)
2754 {
2755 const symbol_record& sr = p->second;
2756
2757 if ((defined_only && ! sr.is_defined (context))
2758 || (sr.xstorage_class () & exclude))
2759 continue;
2760
2761 retval.push_back (sr);
2762 }
2763
2764 return retval;
2765 }
2766
2767 std::list<symbol_record> do_glob (const std::string& pattern,
2768 bool vars_only = false) const
2769 {
2770 std::list<symbol_record> retval;
2771
2772 glob_match pat (pattern);
2773
2774 for (table_const_iterator p = table.begin (); p != table.end (); p++)
2775 {
2776 if (pat.match (p->first))
2777 {
2778 const symbol_record& sr = p->second;
2779
2780 if (vars_only && ! sr.is_variable ())
2781 continue;
2782
2783 retval.push_back (sr);
2784 }
2785 }
2786
2787 return retval;
2788 }
2789
2790 std::list<symbol_record> do_regexp (const std::string& pattern,
2791 bool vars_only = false) const
2792 {
2793 std::list<symbol_record> retval;
2794
2795 ::regexp pat (pattern);
2796
2797 for (table_const_iterator p = table.begin (); p != table.end (); p++)
2798 {
2799 if (pat.is_match (p->first))
2800 {
2801 const symbol_record& sr = p->second;
2802
2803 if (vars_only && ! sr.is_variable ())
2804 continue;
2805
2806 retval.push_back (sr);
2807 }
2808 }
2809
2810 return retval;
2811 }
2812
2813 std::list<std::string> do_variable_names (void)
2814 {
2815 std::list<std::string> retval;
2816
2817 for (table_const_iterator p = table.begin (); p != table.end (); p++)
2818 {
2819 if (p->second.is_variable ())
2820 retval.push_back (p->first);
2821 }
2822
2823 retval.sort ();
2824
2825 return retval;
2826 }
2827
2828 bool do_is_local_variable (const std::string& name) const
2829 {
2830 table_const_iterator p = table.find (name);
2831
2832 return (p != table.end ()
2833 && ! p->second.is_global ()
2834 && p->second.is_defined ());
2835 }
2836
2837 bool do_is_global (const std::string& name) const
2838 {
2839 table_const_iterator p = table.find (name);
2840
2841 return p != table.end () && p->second.is_global ();
2842 }
2843
2844 std::list<workspace_element> do_workspace_info (void) const;
2845
2846 void do_dump (std::ostream& os);
2847
2848 void do_cache_name (const std::string& name) { table_name = name; }
2849
2850 void do_update_nest (void);
2851
2852 bool look_nonlocal (const std::string& name, symbol_record& result)
2853 {
2854 table_iterator p = table.find (name);
2855 if (p == table.end ())
2856 {
2857 if (nest_parent)
2858 return nest_parent->look_nonlocal (name, result);
2859 }
2860 else if (! p->second.is_automatic ())
2861 {
2862 result = p->second;
2863 return true;
2864 }
2865
2866 return false;
2867 }
2868 };
2869
2870 extern bool out_of_date_check (octave_value& function,
2871 const std::string& dispatch_type = std::string (),
2872 bool check_relative = true);
2873
2874 extern OCTINTERP_API std::string
2875 get_dispatch_type (const octave_value_list& args);
2876 extern OCTINTERP_API std::string
2877 get_dispatch_type (const octave_value_list& args, builtin_type_t& builtin_type);
2878
2879 #endif