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