Mercurial > hg > octave-lyh
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 |