GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
symscope.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1993-2021 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 
43 namespace octave
44 {
46  {
47  symbol_record sym (name);
48 
50 
51  return sym;
52  }
53 
55  {
56  size_t data_offset = num_symbols ();
57  std::string name = sr.name ();
58 
59  sr.set_data_offset (data_offset);
60 
61  m_symbols[name] = sr;
62  }
63 
65  {
66  table_iterator p = m_symbols.find (name);
67 
68  if (p == m_symbols.end ())
69  {
70  symbol_record ret (name);
71 
72  size_t data_offset = num_symbols ();
73 
74  ret.set_data_offset (data_offset);
75 
76  auto t_parent = m_parent.lock ();
77 
78  size_t offset = 0;
79 
80  if (is_nested () && t_parent
81  && t_parent->look_nonlocal (name, offset, ret))
82  return m_symbols[name] = ret;
83  else
84  {
85  if (m_is_static)
86  ret.mark_added_static ();
87 
88  return m_symbols[name] = ret;
89  }
90  }
91  else
92  return p->second;
93  }
94 
95  std::list<octave_value> symbol_scope_rep::localfunctions (void) const
96  {
97  std::list<octave_value> retval;
98 
99  // Find the subfunctions of this function (which should be the
100  // primary parent function for this scope).
101 
102  // 1) m_subfunction_names contains only valid subfunctions
103  // 2) m_subfunctions contains both nested functions and subfunctions
104 
105  // loop over them.
106 
107  for (const auto& nm : m_subfunction_names)
108  {
109  auto nm_fcn_iter = m_subfunctions.find (nm);
110 
111  if (nm_fcn_iter != m_subfunctions.end ())
112  {
113  octave_value ov_fcn = nm_fcn_iter->second;
114  octave_user_code *fcn = ov_fcn.user_code_value ();
115 
116  if (! fcn)
117  continue;
118 
119  octave::symbol_scope scope = fcn->scope ();
120 
121  std::list<std::string> plst = scope.parent_fcn_names ();
122 
123  octave_fcn_handle *fh = new octave_fcn_handle (ov_fcn, nm, plst);
124 
125  retval.push_back (octave_value (fh));
126  }
127  }
128 
129  return retval;
130  }
131 
134  {
135  std::map<std::string, octave_value> m
136  = {{ "name", m_name },
137  { "nesting_depth", m_nesting_depth },
138  { "is_static", m_is_static },
139  { "symbols", dump_symbols_map () },
140  { "subfunction_names", string_vector (m_subfunction_names) },
141  { "subfunctions", dump_function_map (m_subfunctions) }};
142 
143  return octave_value (m);
144  }
145 
148  {
149  std::map<std::string, octave_value> info_map;
150 
151  for (const auto& nm_sr : m_symbols)
152  {
153  std::string nm = nm_sr.first;
154  symbol_record sr = nm_sr.second;
155  info_map[nm] = sr.dump ();
156  }
157 
158  return octave_value (info_map);
159  }
160 
161  std::list<symbol_record> symbol_scope_rep::symbol_list (void) const
162  {
163  std::list<symbol_record> retval;
164 
165  for (const auto& nm_sr : m_symbols)
166  retval.push_back (nm_sr.second);
167 
168  return retval;
169  }
170 
172  symbol_scope_rep::find_subfunction (const std::string& name) const
173  {
175 
176  if (p != m_subfunctions.end ())
177  return p->second;
178 
179  auto t_parent = m_parent.lock ();
180 
181  if (t_parent)
182  return t_parent->find_subfunction (name);
183 
184  return octave_value ();
185  }
186 
187  void
189  {
190  for (auto& nm_sf : m_subfunctions)
191  {
192  octave_function *fcn = nm_sf.second.function_value ();
193 
194  if (fcn)
195  fcn->mark_as_private_function (class_name);
196  }
197  }
198 
199  void
200  symbol_scope_rep::set_parent (const std::shared_ptr<symbol_scope_rep>& parent)
201  {
202  m_parent = std::weak_ptr<symbol_scope_rep> (parent);
203  }
204 
205  void
206  symbol_scope_rep::set_primary_parent (const std::shared_ptr<symbol_scope_rep>& parent)
207  {
208  m_primary_parent = std::weak_ptr<symbol_scope_rep> (parent);
209  }
210 
211  void
213  {
215  }
216 
217  bool
218  symbol_scope_rep::is_relative (const std::shared_ptr<symbol_scope_rep>& scope) const
219  {
220  if (is_nested ())
221  {
222  // Since is_nested is true, the following should always return a
223  // valid scope.
224 
225  auto t_parent = m_parent.lock ();
226 
227  if (t_parent)
228  {
229  // SCOPE is the parent of this scope: this scope is a child
230  // of SCOPE.
231 
232  if (t_parent == scope)
233  return true;
234  }
235 
236  auto t_primary_parent = m_primary_parent.lock ();
237 
238  if (t_primary_parent)
239  {
240  // SCOPE is the primary parent of this scope: this scope is a
241  // child (or grandchild) of SCOPE.
242  if (t_primary_parent == scope)
243  return true;
244 
245  // SCOPE and this scope share the same primary parent: they are
246  // siblings (or cousins)
247  auto scope_primary_parent = scope->primary_parent_scope_rep ();
248  if (t_primary_parent == scope_primary_parent)
249  return true;
250  }
251  }
252 
253  return false;
254  }
255 
257  {
258  auto t_parent = m_parent.lock ();
259 
260  if (t_parent)
261  {
262  // fix bad symbol_records
263  for (auto& nm_sr : m_symbols)
264  {
265  symbol_record& ours = nm_sr.second;
266 
267  size_t offset = 0;
268 
269  if (! ours.is_formal () && is_nested ())
270  t_parent->look_nonlocal (nm_sr.first, offset, ours);
271  }
272 
273  // The scopes of nested functions are static.
274  if (is_nested ())
275  m_is_static = true;
276  }
277  else if (m_children.size ())
278  {
279  // Parents of nested functions have static scopes.
280  m_is_static = true;
281  }
282 
283  std::list<std::string> plst = parent_fcn_names ();
284  plst.push_front (m_fcn_name);
285 
286  for (auto& scope_obj : m_children)
287  {
288  scope_obj.cache_parent_fcn_names (plst);
289  scope_obj.update_nest ();
290  }
291  }
292 
293  bool symbol_scope_rep::look_nonlocal (const std::string& name,
294  size_t offset, symbol_record& result)
295  {
296  offset++;
297 
298  table_iterator p = m_symbols.find (name);
299 
300  if (p == m_symbols.end ())
301  {
302  auto t_parent = m_parent.lock ();
303 
304  if (is_nested () && t_parent)
305  return t_parent->look_nonlocal (name, offset, result);
306  }
307  else
308  {
309  // Add scope offsets because the one we found may be used in
310  // this scope but initially from another parent scope beyond
311  // that. The parent offset will already point to the first
312  // occurrence because we do the overall nesting update from the
313  // parent function down through the lists of all children.
314 
315  size_t t_frame_offset = offset + p->second.frame_offset ();
316  size_t t_data_offset = p->second.data_offset ();
317 
318  result.set_frame_offset (t_frame_offset);
319  result.set_data_offset (t_data_offset);
320 
321  return true;
322  }
323 
324  return false;
325  }
326 
327  std::list<octave_value> symbol_scope::localfunctions (void) const
328  {
329  if (! m_rep)
330  return std::list<octave_value> ();
331 
332  if (is_primary_fcn_scope ())
333  return m_rep->localfunctions ();
334 
335  std::shared_ptr<symbol_scope_rep> ppsr
336  = m_rep->primary_parent_scope_rep ();
337 
338  if (! ppsr)
339  return std::list<octave_value> ();
340 
341  return ppsr->localfunctions ();
342  }
343 }
void set_data_offset(size_t offset)
Definition: symrec.h:179
void mark_added_static(void)
Definition: symrec.h:195
void set_frame_offset(size_t offset)
Definition: symrec.h:175
bool is_formal(void) const
Definition: symrec.h:190
octave_value dump(void) const
Definition: symrec.h:203
std::string name(void) const
Definition: symrec.h:185
std::weak_ptr< symbol_scope_rep > m_primary_parent
Primary (top) parent of nested function (may be null).
Definition: symscope.h:364
std::string m_name
Name for this scope (usually the corresponding filename of the function corresponding to the scope).
Definition: symscope.h:319
std::vector< symbol_scope > m_children
Child nested functions.
Definition: symscope.h:368
std::string name(void) const
Definition: symscope.h:252
std::map< std::string, symbol_record >::iterator table_iterator
Definition: symscope.h:61
std::string m_dir_name
The directory associated with m_code.
Definition: symscope.h:355
std::map< std::string, octave_value >::const_iterator subfunctions_const_iterator
Definition: symscope.h:64
std::map< std::string, octave_value > m_subfunctions
Map from symbol names to subfunctions.
Definition: symscope.h:327
bool is_relative(const std::shared_ptr< symbol_scope_rep > &scope) const
Definition: symscope.cc:218
octave_value dump(void) const
Definition: symscope.cc:133
size_t m_nesting_depth
If true, then this scope belongs to a nested function.
Definition: symscope.h:372
void set_parent(const std::shared_ptr< symbol_scope_rep > &parent)
Definition: symscope.cc:200
std::map< std::string, symbol_record > m_symbols
Map from symbol names to symbol info.
Definition: symscope.h:323
symbol_record insert_local(const std::string &name)
Definition: symscope.cc:45
void mark_subfunctions_in_scope_as_private(const std::string &class_name)
Definition: symscope.cc:188
std::string m_fcn_name
Simple name of the function corresponding to this scope.
Definition: symscope.h:343
bool look_nonlocal(const std::string &name, size_t offset, symbol_record &result)
Definition: symscope.cc:293
octave_value dump_symbols_map(void) const
Definition: symscope.cc:147
size_t num_symbols(void) const
Definition: symscope.h:88
std::list< std::string > m_subfunction_names
The list of subfunctions (if any) in the order they appear in the function file.
Definition: symscope.h:335
symbol_record insert(const std::string &name)
Definition: symscope.cc:64
octave_value find_subfunction(const std::string &name) const
Definition: symscope.cc:172
std::list< octave_value > localfunctions(void) const
Definition: symscope.cc:95
bool m_is_static
If true then no variables can be added.
Definition: symscope.h:376
std::weak_ptr< symbol_scope_rep > m_parent
Parent of nested function (may be null).
Definition: symscope.h:359
bool is_nested(void) const
Definition: symscope.h:96
void set_primary_parent(const std::shared_ptr< symbol_scope_rep > &parent)
Definition: symscope.cc:206
void insert_symbol_record(symbol_record &sr)
Definition: symscope.cc:54
std::list< std::string > parent_fcn_names(void) const
Definition: symscope.h:260
void cache_dir_name(const std::string &name)
Definition: symscope.cc:212
std::list< symbol_record > symbol_list(void) const
Definition: symscope.cc:161
std::shared_ptr< symbol_scope_rep > m_rep
Definition: symscope.h:723
std::list< std::string > parent_fcn_names(void) const
Definition: symscope.h:601
bool is_primary_fcn_scope(void) const
Definition: symscope.h:663
std::list< octave_value > localfunctions(void) const
Definition: symscope.cc:327
virtual octave_function * function_value(bool silent=false)
Definition: ov-base.cc:873
virtual void mark_as_private_function(const std::string &cname="")
Definition: ov-fcn.h:158
octave::symbol_scope scope(void)
Definition: ov-usr-fcn.h:98
octave_user_code * user_code_value(bool silent=false) const
QString name
T octave_idx_type m
Definition: mx-inlines.cc:773
std::string canonicalize_file_name(const std::string &name)
Definition: file-ops.cc:693
octave_value dump_function_map(const std::map< std::string, octave_value > &fcn_map)
Definition: fcn-info.cc:1093
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811