GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
ov-usr-fcn.h
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2024 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 (octave_ov_usr_fcn_h)
27 #define octave_ov_usr_fcn_h 1
28 
29 #include "octave-config.h"
30 
31 #include <string>
32 
33 #include "comment-list.h"
34 #include "ovl.h"
35 #include "ov-fcn.h"
36 #include "ov-typeinfo.h"
37 #include "symscope.h"
38 #include "unwind-prot.h"
39 
40 class string_vector;
41 
42 class octave_value;
43 
45 
46 class file_info;
47 class stack_frame;
50 class tree_evaluator;
51 class tree_expression;
52 class tree_walker;
53 
54 OCTAVE_END_NAMESPACE(octave)
55 
56 class
58 {
59 protected:
60 
61  octave_user_code (const std::string& fnm = "", const std::string& nm = "",
62  const octave::symbol_scope& scope = octave::symbol_scope::anonymous (),
63  octave::tree_statement_list *cmds = nullptr,
64  const std::string& ds = "")
65  : octave_function (nm, ds), m_scope (scope), m_file_name (fnm),
66  m_t_parsed (static_cast<OCTAVE_TIME_T> (0)),
67  m_t_checked (static_cast<OCTAVE_TIME_T> (0)),
68  m_file_info (nullptr), m_cmd_list (cmds)
69  {
70  if (m_scope)
71  m_scope.set_user_code (this);
72  }
73 
74 public:
75 
76  OCTAVE_DISABLE_COPY_MOVE (octave_user_code)
77 
78  ~octave_user_code ();
79 
80  bool is_user_code () const { return true; }
81 
82  std::string get_code_line (std::size_t line);
83 
84  std::deque<std::string> get_code_lines (std::size_t line,
85  std::size_t num_lines);
86 
87  void cache_function_text (const std::string& text,
88  const octave::sys::time& timestamp);
89 
90  octave::symbol_scope scope () { return m_scope; }
91 
92  std::size_t scope_num_symbols () { return m_scope.num_symbols (); }
93 
94  void stash_fcn_file_name (const std::string& nm) { m_file_name = nm; }
95 
96  void mark_fcn_file_up_to_date (const octave::sys::time& t)
97  { m_t_checked = t; }
98 
99  void stash_fcn_file_time (const octave::sys::time& t)
100  {
101  m_t_parsed = t;
102  mark_fcn_file_up_to_date (t);
103  }
104 
105  std::string fcn_file_name () const { return m_file_name; }
106 
107  octave::sys::time time_parsed () const { return m_t_parsed; }
108 
109  octave::sys::time time_checked () const { return m_t_checked; }
110 
111  virtual octave_value find_subfunction (const std::string&) const
112  {
113  return octave_value ();
114  }
115 
116  virtual std::map<std::string, octave_value> subfunctions () const;
117 
118  octave::tree_statement_list * body () { return m_cmd_list; }
119 
120  octave_value dump () const;
121 
122 protected:
123 
124  void get_file_info ();
125 
126  // Our symbol table scope.
127  octave::symbol_scope m_scope;
128 
129  // The name of the file we parsed.
130  std::string m_file_name;
131 
132  // The time the file was parsed.
133  octave::sys::time m_t_parsed;
134 
135  // The time the file was last checked to see if it needs to be
136  // parsed again.
137  octave::sys::time m_t_checked;
138 
139  // Cached text of function or script code with line offsets
140  // calculated.
141  octave::file_info *m_file_info;
142 
143  // The list of commands that make up the body of this function.
144  octave::tree_statement_list *m_cmd_list;
145 };
146 
147 // Scripts.
148 
149 class
151 {
152 public:
153 
155 
156  octave_user_script (const std::string& fnm, const std::string& nm,
157  const octave::symbol_scope& scope = octave::symbol_scope::anonymous (),
158  octave::tree_statement_list *cmds = nullptr,
159  const std::string& ds = "");
160 
161  octave_user_script (const std::string& fnm, const std::string& nm,
162  const octave::symbol_scope& scope = octave::symbol_scope::anonymous (),
163  const std::string& ds = "");
164 
165  OCTAVE_DISABLE_COPY_MOVE (octave_user_script)
166 
167  ~octave_user_script () = default;
168 
169  octave_function * function_value (bool = false) { return this; }
170 
171  octave_user_script * user_script_value (bool = false) { return this; }
172 
173  octave_user_code * user_code_value (bool = false) { return this; }
174 
175  // Scripts and user functions are both considered "scripts" because
176  // they are written in Octave's scripting language.
177 
178  bool is_user_script () const { return true; }
179 
180  // We must overload the call method so that we call the proper
181  // push_stack_frame method, which is overloaded for pointers to
182  // octave_function, octave_user_function, and octave_user_script
183  // objects.
184 
186  call (octave::tree_evaluator& tw, int nargout = 0,
187  const octave_value_list& args = octave_value_list ());
188 
190  execute (octave::tree_evaluator& tw, int nargout = 0,
191  const octave_value_list& args = octave_value_list ());
192 
193  void accept (octave::tree_walker& tw);
194 
195 private:
196 
198 };
199 
200 // User-defined functions.
201 
202 class
204 {
205 public:
206 
207  octave_user_function (const octave::symbol_scope& scope = octave::symbol_scope::anonymous (),
208  octave::tree_parameter_list *pl = nullptr,
209  octave::tree_parameter_list *rl = nullptr,
210  octave::tree_statement_list *cl = nullptr);
211 
212  OCTAVE_DISABLE_COPY_MOVE (octave_user_function)
213 
215 
216  octave_function * function_value (bool = false) { return this; }
217 
218  octave_user_function * user_function_value (bool = false) { return this; }
219 
220  octave_user_code * user_code_value (bool = false) { return this; }
221 
222  octave_user_function * define_param_list (octave::tree_parameter_list *t);
223 
224  octave_user_function * define_ret_list (octave::tree_parameter_list *t);
225 
226  void stash_fcn_location (int line, int col)
227  {
228  m_location_line = line;
229  m_location_column = col;
230  }
231 
232  int beginning_line () const { return m_location_line; }
233  int beginning_column () const { return m_location_column; }
234 
235  void stash_fcn_end_location (int line, int col)
236  {
237  m_end_location_line = line;
238  m_end_location_column = col;
239  }
240 
241  int ending_line () const { return m_end_location_line; }
242  int ending_column () const { return m_end_location_column; }
243 
244  void maybe_relocate_end ();
245 
246  void stash_parent_fcn_scope (const octave::symbol_scope& ps);
247 
248  void stash_leading_comment (octave::comment_list *lc) { m_lead_comm = lc; }
249 
250  void stash_trailing_comment (octave::comment_list *tc) { m_trail_comm = tc; }
251 
252  std::string profiler_name () const;
253 
254  std::string parent_fcn_name () const
255  {
256  octave::symbol_scope pscope = parent_fcn_scope ();
257 
258  return pscope.fcn_name ();
259  }
260 
261  octave::symbol_scope parent_fcn_scope () const
262  {
263  return m_scope.parent_scope ();
264  }
265 
266  std::list<std::string> parent_fcn_names () const
267  {
268  return m_scope.parent_fcn_names ();
269  }
270 
271  void mark_as_system_fcn_file ();
272 
273  bool is_system_fcn_file () const { return m_system_fcn_file; }
274 
275  bool is_user_function () const { return true; }
276 
277  void erase_subfunctions ();
278 
279  bool takes_varargs () const;
280 
281  bool takes_var_return () const;
282 
283  void mark_as_private_function (const std::string& cname = "");
284 
285  void lock_subfunctions ();
286 
287  void unlock_subfunctions ();
288 
289  std::map<std::string, octave_value> subfunctions () const;
290 
291  octave_value find_subfunction (const std::string& subfuns) const;
292 
293  bool has_subfunctions () const;
294 
295  void stash_subfunction_names (const std::list<std::string>& names);
296 
297  std::list<std::string> subfunction_names () const;
298 
299  octave_value_list all_va_args (const octave_value_list& args);
300 
301  void stash_function_name (const std::string& s) { m_name = s; }
302 
303  void mark_as_subfunction () { m_subfunction = true; }
304 
305  bool is_subfunction () const { return m_subfunction; }
306 
307  void mark_as_inline_function () { m_inline_function = true; }
308 
309  bool is_inline_function () const { return m_inline_function; }
310 
311  void mark_as_anonymous_function () { m_anonymous_function = true; }
312 
313  bool is_anonymous_function () const { return m_anonymous_function; }
314 
316  (const std::string& cname = "") const
317  {
318  return m_anonymous_function
319  ? (cname.empty ()
320  ? (! dispatch_class ().empty ())
321  : cname == dispatch_class ())
322  : false;
323  }
324 
325  // If we are a special expression, then the function body consists of exactly
326  // one expression. The expression's result is the return value of the
327  // function.
328  bool is_special_expr () const
329  {
330  return is_inline_function () || is_anonymous_function ();
331  }
332 
333  void mark_as_nested_function () { m_nested_function = true; }
334 
335  bool is_nested_function () const { return m_nested_function; }
336 
337  bool is_parent_function () const { return m_scope.is_parent (); }
338 
339  void mark_as_legacy_constructor () { m_class_constructor = legacy; }
340 
341  bool is_legacy_constructor (const std::string& cname = "") const
342  {
343  return (m_class_constructor == legacy
344  ? (cname.empty () ? true : cname == dispatch_class ()) : false);
345  }
346 
347  void mark_as_classdef_constructor () { m_class_constructor = classdef; }
348 
349  bool is_classdef_constructor (const std::string& cname = "") const
350  {
351  return (m_class_constructor == classdef
352  ? (cname.empty () ? true : cname == dispatch_class ()) : false);
353  }
354 
355  void mark_as_legacy_method () { m_class_method = legacy; }
356 
357  bool is_legacy_method (const std::string& cname = "") const
358  {
359  return (m_class_method == legacy
360  ? (cname.empty () ? true : cname == dispatch_class ()) : false);
361  }
362 
363  void mark_as_classdef_method () { m_class_method = classdef; }
364 
365  bool is_classdef_method (const std::string& cname = "") const
366  {
367  return (m_class_method == classdef
368  ? (cname.empty () ? true : cname == dispatch_class ()) : false);
369  }
370 
371  // We must overload the call method so that we call the proper
372  // push_stack_frame method, which is overloaded for pointers to
373  // octave_function, octave_user_function, and octave_user_script
374  // objects.
375 
377  call (octave::tree_evaluator& tw, int nargout = 0,
378  const octave_value_list& args = octave_value_list ());
379 
381  execute (octave::tree_evaluator& tw, int nargout = 0,
382  const octave_value_list& args = octave_value_list ());
383 
384  octave::tree_parameter_list * parameter_list () { return m_param_list; }
385 
386  octave::tree_parameter_list * return_list () { return m_ret_list; }
387 
388  octave::comment_list * leading_comment () { return m_lead_comm; }
389 
390  octave::comment_list * trailing_comment () { return m_trail_comm; }
391 
392  // If is_special_expr is true, retrieve the sigular expression that forms the
393  // body. May be null (even if is_special_expr is true).
394  octave::tree_expression * special_expr ();
395 
396  bool subsasgn_optimization_ok ();
397 
398  void accept (octave::tree_walker& tw);
399 
400  octave_value dump () const;
401 
402 private:
403 
404  enum class_method_type
405  {
406  none,
407  legacy,
408  classdef
409  };
410 
411  std::string ctor_type_str () const;
412  std::string method_type_str () const;
413 
414  // List of arguments for this function. These are local variables.
415  octave::tree_parameter_list *m_param_list;
416 
417  // List of parameters we return. These are also local variables in
418  // this function.
419  octave::tree_parameter_list *m_ret_list;
420 
421  // The comments preceding the FUNCTION token.
422  octave::comment_list *m_lead_comm;
423 
424  // The comments preceding the ENDFUNCTION token.
425  octave::comment_list *m_trail_comm;
426 
427  // Location where this function was defined.
428  int m_location_line;
429  int m_location_column;
430  int m_end_location_line;
431  int m_end_location_column;
432 
433  // True if this function came from a file that is considered to be a
434  // system function. This affects whether we check the time stamp
435  // on the file to see if it has changed.
436  bool m_system_fcn_file;
437 
438  // The number of arguments that have names.
439  int m_num_named_args;
440 
441  // TRUE means this is a m_subfunction of a primary function.
442  bool m_subfunction;
443 
444  // TRUE means this is an inline function.
445  bool m_inline_function;
446 
447  // TRUE means this is an anonymous function.
448  bool m_anonymous_function;
449 
450  // TRUE means this is a nested function.
451  bool m_nested_function;
452 
453  // Enum describing whether this function is the constructor for class object.
454  class_method_type m_class_constructor;
455 
456  // Enum describing whether this function is a method for a class.
457  class_method_type m_class_method;
458 
459  void maybe_relocate_end_internal ();
460 
461  void print_code_function_header (const std::string& prefix);
462 
463  void print_code_function_trailer (const std::string& prefix);
464 
465  // XXX FIXME (public)
466 public:
467 
468  void restore_warning_states ();
469 
471 };
472 
473 #endif
void stash_fcn_file_name(const std::string &nm)
Definition: ov-usr-fcn.h:94
octave_user_code(const std::string &fnm="", const std::string &nm="", const octave::symbol_scope &scope=octave::symbol_scope::anonymous(), octave::tree_statement_list *cmds=nullptr, const std::string &ds="")
Definition: ov-usr-fcn.h:61
bool is_user_code() const
Definition: ov-usr-fcn.h:80
octave::symbol_scope scope()
Definition: ov-usr-fcn.h:90
std::string m_file_name
Definition: ov-usr-fcn.h:130
void mark_fcn_file_up_to_date(const octave::sys::time &t)
Definition: ov-usr-fcn.h:96
octave::sys::time m_t_checked
Definition: ov-usr-fcn.h:137
std::string fcn_file_name() const
Definition: ov-usr-fcn.h:105
octave::tree_statement_list * m_cmd_list
Definition: ov-usr-fcn.h:144
virtual octave_value find_subfunction(const std::string &) const
Definition: ov-usr-fcn.h:111
octave::sys::time m_t_parsed
Definition: ov-usr-fcn.h:133
octave::file_info * m_file_info
Definition: ov-usr-fcn.h:141
octave::tree_statement_list * body()
Definition: ov-usr-fcn.h:118
void stash_fcn_file_time(const octave::sys::time &t)
Definition: ov-usr-fcn.h:99
octave::symbol_scope m_scope
Definition: ov-usr-fcn.h:127
std::size_t scope_num_symbols()
Definition: ov-usr-fcn.h:92
octave::sys::time time_parsed() const
Definition: ov-usr-fcn.h:107
octave::sys::time time_checked() const
Definition: ov-usr-fcn.h:109
void mark_as_inline_function()
Definition: ov-usr-fcn.h:307
bool is_legacy_method(const std::string &cname="") const
Definition: ov-usr-fcn.h:357
void stash_trailing_comment(octave::comment_list *tc)
Definition: ov-usr-fcn.h:250
void stash_function_name(const std::string &s)
Definition: ov-usr-fcn.h:301
bool is_nested_function() const
Definition: ov-usr-fcn.h:335
bool is_inline_function() const
Definition: ov-usr-fcn.h:309
bool is_special_expr() const
Definition: ov-usr-fcn.h:328
octave::comment_list * trailing_comment()
Definition: ov-usr-fcn.h:390
octave_function * function_value(bool=false)
Definition: ov-usr-fcn.h:216
bool is_classdef_constructor(const std::string &cname="") const
Definition: ov-usr-fcn.h:349
bool is_system_fcn_file() const
Definition: ov-usr-fcn.h:273
int ending_column() const
Definition: ov-usr-fcn.h:242
octave::comment_list * leading_comment()
Definition: ov-usr-fcn.h:388
octave::symbol_scope parent_fcn_scope() const
Definition: ov-usr-fcn.h:261
octave::tree_parameter_list * parameter_list()
Definition: ov-usr-fcn.h:384
octave_user_function * define_param_list(octave::tree_parameter_list *t)
void mark_as_classdef_method()
Definition: ov-usr-fcn.h:363
octave_user_function * user_function_value(bool=false)
Definition: ov-usr-fcn.h:218
bool is_legacy_constructor(const std::string &cname="") const
Definition: ov-usr-fcn.h:341
int beginning_column() const
Definition: ov-usr-fcn.h:233
bool is_classdef_method(const std::string &cname="") const
Definition: ov-usr-fcn.h:365
std::string parent_fcn_name() const
Definition: ov-usr-fcn.h:254
bool is_anonymous_function() const
Definition: ov-usr-fcn.h:313
bool is_anonymous_function_of_class(const std::string &cname="") const
Definition: ov-usr-fcn.h:316
void mark_as_legacy_constructor()
Definition: ov-usr-fcn.h:339
octave_user_code * user_code_value(bool=false)
Definition: ov-usr-fcn.h:220
void mark_as_legacy_method()
Definition: ov-usr-fcn.h:355
int beginning_line() const
Definition: ov-usr-fcn.h:232
void stash_leading_comment(octave::comment_list *lc)
Definition: ov-usr-fcn.h:248
int ending_line() const
Definition: ov-usr-fcn.h:241
bool is_subfunction() const
Definition: ov-usr-fcn.h:305
void stash_fcn_location(int line, int col)
Definition: ov-usr-fcn.h:226
std::list< std::string > parent_fcn_names() const
Definition: ov-usr-fcn.h:266
void mark_as_subfunction()
Definition: ov-usr-fcn.h:303
void stash_fcn_end_location(int line, int col)
Definition: ov-usr-fcn.h:235
octave::tree_parameter_list * return_list()
Definition: ov-usr-fcn.h:386
void mark_as_anonymous_function()
Definition: ov-usr-fcn.h:311
bool is_parent_function() const
Definition: ov-usr-fcn.h:337
void mark_as_classdef_constructor()
Definition: ov-usr-fcn.h:347
bool is_user_function() const
Definition: ov-usr-fcn.h:275
void mark_as_nested_function()
Definition: ov-usr-fcn.h:333
~octave_user_script()=default
bool is_user_script() const
Definition: ov-usr-fcn.h:178
octave_user_code * user_code_value(bool=false)
Definition: ov-usr-fcn.h:173
octave_function * function_value(bool=false)
Definition: ov-usr-fcn.h:169
octave_user_script * user_script_value(bool=false)
Definition: ov-usr-fcn.h:171
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
#define DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
Definition: ov-base.h:181