GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
symscope.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1993-2025 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include <sstream>
31
32#include "file-ops.h"
33
34#include "fcn-info.h"
35#include "interpreter-private.h"
36#include "interpreter.h"
37#include "ov-fcn.h"
38#include "ov-usr-fcn.h"
39#include "symrec.h"
40#include "symscope.h"
41#include "utils.h"
42
44
45symbol_record symbol_scope::symbol_scope_rep::insert_local (const std::string& name)
46{
47 symbol_record sym (name);
48
49 insert_symbol_record (sym);
50
51 return sym;
52}
53
54void
55symbol_scope::symbol_scope_rep::insert_symbol_record (symbol_record& sr)
56{
57 std::size_t data_offset = num_symbols ();
58 std::string name = sr.name ();
59
60 sr.set_data_offset (data_offset);
61
62 m_symbols[name] = sr;
63}
64
66symbol_scope::symbol_scope_rep::insert (const std::string& name)
67{
68 table_iterator p = m_symbols.find (name);
69
70 if (p == m_symbols.end ())
71 {
72 symbol_record ret (name);
73
74 std::size_t data_offset = num_symbols ();
75
76 ret.set_data_offset (data_offset);
77
78 auto t_parent = m_parent.lock ();
79
80 std::size_t offset = 0;
81
82 if (is_nested () && t_parent
83 && t_parent->look_nonlocal (name, offset, ret))
84 return m_symbols[name] = ret;
85 else
86 {
87 if (m_is_static)
88 ret.mark_added_static ();
89
90 return m_symbols[name] = ret;
91 }
92 }
93 else
94 return p->second;
95}
96
97std::list<octave_value>
98symbol_scope::symbol_scope_rep::localfunctions () const
99{
100 std::list<octave_value> retval;
101
102 // Find the subfunctions of this function (which should be the
103 // primary parent function for this scope).
104
105 // 1) m_subfunction_names contains only valid subfunctions
106 // 2) m_subfunctions contains both nested functions and subfunctions
107
108 // loop over them.
109
110 for (const auto& nm : m_subfunction_names)
111 {
112 auto nm_fcn_iter = m_subfunctions.find (nm);
113
114 if (nm_fcn_iter != m_subfunctions.end ())
115 {
116 octave_value ov_fcn = nm_fcn_iter->second;
117 octave_user_code *fcn = ov_fcn.user_code_value ();
118
119 if (! fcn)
120 continue;
121
122 symbol_scope scope = fcn->scope ();
123
124 std::list<std::string> plst = scope.parent_fcn_names ();
125
126 octave_fcn_handle *fh = new octave_fcn_handle (ov_fcn, nm, plst);
127
128 retval.push_back (octave_value (fh));
129 }
130 }
131
132 return retval;
133}
134
136symbol_scope::symbol_scope_rep::dump () const
137{
138 std::map<std::string, octave_value> m
139 = {{ "name", m_name },
140 { "nesting_depth", m_nesting_depth },
141 { "is_static", m_is_static },
142 { "symbols", dump_symbols_map () },
143 { "subfunction_names", string_vector (m_subfunction_names) },
144 { "subfunctions", dump_function_map (m_subfunctions) }
145 };
146
147 return octave_value (m);
148}
149
151symbol_scope::symbol_scope_rep::dump_symbols_map () const
152{
153 std::map<std::string, octave_value> info_map;
154
155 for (const auto& nm_sr : m_symbols)
156 {
157 std::string nm = nm_sr.first;
158 symbol_record sr = nm_sr.second;
159 info_map[nm] = sr.dump ();
160 }
161
162 return octave_value (info_map);
163}
164
165std::list<symbol_record>
166symbol_scope::symbol_scope_rep::symbol_list () const
167{
168 std::list<symbol_record> retval;
169
170 for (const auto& nm_sr : m_symbols)
171 retval.push_back (nm_sr.second);
172
173 return retval;
174}
175
177symbol_scope::symbol_scope_rep::find_subfunction (const std::string& name) const
178{
179 subfunctions_const_iterator p = m_subfunctions.find (name);
180
181 if (p != m_subfunctions.end ())
182 return p->second;
183
184 auto t_parent = m_parent.lock ();
185
186 if (t_parent)
187 return t_parent->find_subfunction (name);
188
189 return octave_value ();
190}
191
192void
193symbol_scope::symbol_scope_rep::mark_subfunctions_in_scope_as_private (const std::string& class_name)
194{
195 for (auto& nm_sf : m_subfunctions)
196 {
197 octave_function *fcn = nm_sf.second.function_value ();
198
199 if (fcn)
200 fcn->mark_as_private_function (class_name);
201 }
202}
203
204std::list<std::string>
205symbol_scope::symbol_scope_rep::parent_fcn_names () const
206{
207 std::list<std::string> retval;
208
209 auto pscope = parent_scope_rep ();
210
211 while (pscope)
212 {
213 retval.push_back (pscope->fcn_name ());
214
215 pscope = pscope->parent_scope_rep ();
216 }
217
218 return retval;
219}
220
221void
222symbol_scope::symbol_scope_rep::set_parent (const std::shared_ptr<symbol_scope::symbol_scope_rep>& parent)
223{
224 m_parent = std::weak_ptr<symbol_scope::symbol_scope_rep> (parent);
225}
226
227void
228symbol_scope::symbol_scope_rep::set_primary_parent (const std::shared_ptr<symbol_scope::symbol_scope_rep>& parent)
229{
230 m_primary_parent = std::weak_ptr<symbol_scope::symbol_scope_rep> (parent);
231}
232
233void
234symbol_scope::symbol_scope_rep::cache_dir_name (const std::string& name)
235{
236 m_dir_name = sys::canonicalize_file_name (name);
237}
238
239bool
240symbol_scope::symbol_scope_rep::is_relative (const std::shared_ptr<symbol_scope::symbol_scope_rep>& scope) const
241{
242 if (is_nested ())
243 {
244 // Since is_nested is true, the following should always return a
245 // valid scope.
246
247 auto t_parent = m_parent.lock ();
248
249 if (t_parent)
250 {
251 // SCOPE is the parent of this scope: this scope is a child
252 // of SCOPE.
253
254 if (t_parent == scope)
255 return true;
256 }
257
258 auto t_primary_parent = m_primary_parent.lock ();
259
260 if (t_primary_parent)
261 {
262 // SCOPE is the primary parent of this scope: this scope is a
263 // child (or grandchild) of SCOPE.
264 if (t_primary_parent == scope)
265 return true;
266
267 // SCOPE and this scope share the same primary parent: they are
268 // siblings (or cousins)
269 auto scope_primary_parent = scope->primary_parent_scope_rep ();
270 if (t_primary_parent == scope_primary_parent)
271 return true;
272 }
273 }
274
275 return false;
276}
277
278void
279symbol_scope::symbol_scope_rep::mark_as_variable (const std::string& nm)
280{
281 table_iterator p = m_symbols.find (nm);
282
283 if (p != m_symbols.end ())
284 p->second.mark_variable ();
285}
286
287void
288symbol_scope::symbol_scope_rep::mark_as_variables (const std::list<std::string>& lst)
289{
290 for (const auto& nm : lst)
291 mark_as_variable (nm);
292}
293
294bool
295symbol_scope::symbol_scope_rep::is_variable (const std::string& nm) const
296{
297 table_const_iterator p = m_symbols.find (nm);
298
299 // FIXME: maybe we should also mark formal parameters as variables?
300
301 if (p != m_symbols.end () && p->second.is_variable ())
302 return true;
303
304 if (is_nested ())
305 {
306 auto t_parent = m_parent.lock ();
307
308 return t_parent ? t_parent->is_variable (nm) : false;
309 }
310
311 return false;
312}
313
314void
315symbol_scope::symbol_scope_rep::update_nest ()
316{
317 auto t_parent = m_parent.lock ();
318
319 if (t_parent)
320 {
321 // fix bad symbol_records
322 for (auto& nm_sr : m_symbols)
323 {
324 symbol_record& ours = nm_sr.second;
325
326 std::size_t offset = 0;
327
328 if (! ours.is_formal () && is_nested ())
329 t_parent->look_nonlocal (nm_sr.first, offset, ours);
330 }
331
332 // The scopes of nested functions are static.
333 if (is_nested ())
334 m_is_static = true;
335 }
336 else if (m_children.size ())
337 {
338 // Parents of nested functions have static scopes.
339 m_is_static = true;
340 }
341
342 for (auto& scope_obj : m_children)
343 scope_obj.update_nest ();
344}
345
346bool
347symbol_scope::symbol_scope_rep::look_nonlocal (const std::string& name,
348 std::size_t offset,
349 symbol_record& result)
350{
351 offset++;
352
353 table_iterator p = m_symbols.find (name);
354
355 if (p == m_symbols.end ())
356 {
357 auto t_parent = m_parent.lock ();
358
359 if (is_nested () && t_parent)
360 return t_parent->look_nonlocal (name, offset, result);
361 }
362 else
363 {
364 // Add scope offsets because the one we found may be used in
365 // this scope but initially from another parent scope beyond
366 // that. The parent offset will already point to the first
367 // occurrence because we do the overall nesting update from the
368 // parent function down through the lists of all children.
369
370 std::size_t t_frame_offset = offset + p->second.frame_offset ();
371 std::size_t t_data_offset = p->second.data_offset ();
372
373 result.set_frame_offset (t_frame_offset);
374 result.set_data_offset (t_data_offset);
375
376 return true;
377 }
378
379 return false;
380}
381
382std::list<octave_value>
384{
385 if (! m_rep)
386 return std::list<octave_value> ();
387
389 return m_rep->localfunctions ();
390
391 std::shared_ptr<symbol_scope::symbol_scope_rep> ppsr
392 = m_rep->primary_parent_scope_rep ();
393
394 if (! ppsr)
395 return std::list<octave_value> ();
396
397 return ppsr->localfunctions ();
398}
399
400OCTAVE_END_NAMESPACE(octave)
virtual octave_function * function_value(bool silent=false)
Definition ov-base.cc:935
virtual void mark_as_private_function(const std::string &cname="")
Definition ov-fcn.h:157
octave::symbol_scope scope()
Definition ov-usr-fcn.h:97
void lock()
Definition ov.h:1446
octave_user_code * user_code_value(bool silent=false) const
void set_data_offset(std::size_t offset)
Definition symrec.h:211
std::string name() const
Definition symrec.h:218
void set_frame_offset(std::size_t offset)
Definition symrec.h:206
std::size_t frame_offset() const
Definition symrec.h:209
bool is_formal() const
Definition symrec.h:223
octave_value dump() const
Definition symrec.h:243
bool is_primary_fcn_scope() const
Definition symscope.h:664
std::list< octave_value > localfunctions() const
Definition symscope.cc:383
std::list< std::string > parent_fcn_names() const
Definition symscope.h:608
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
octave_value dump_function_map(const std::map< std::string, octave_value > &fcn_map)
Definition fcn-info.cc:1126