GNU Octave  6.2.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-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 (octave_ov_usr_fcn_h)
27 #define octave_ov_usr_fcn_h 1
28 
29 #include "octave-config.h"
30 
31 #include <ctime>
32 
33 #include <string>
34 
35 #include "comment-list.h"
36 #include "ovl.h"
37 #include "ov-fcn.h"
38 #include "ov-typeinfo.h"
39 #include "symscope.h"
40 #include "unwind-prot.h"
41 
42 class string_vector;
43 
44 class octave_value;
45 
46 namespace octave
47 {
48  class file_info;
49  class stack_frame;
50  class tree_parameter_list;
51  class tree_statement_list;
52  class tree_evaluator;
53  class tree_expression;
54  class tree_walker;
55 #if defined (HAVE_LLVM)
56  class jit_function_info;
57 #endif
58 
59 }
60 
61 class
63 {
64 protected:
65 
66  octave_user_code (const std::string& fnm = "", const std::string& nm = "",
68  octave::tree_statement_list *cmds = nullptr,
69  const std::string& ds = "")
70  : octave_function (nm, ds), m_scope (scope), file_name (fnm),
71  t_parsed (static_cast<time_t> (0)),
72  t_checked (static_cast<time_t> (0)),
73  m_file_info (nullptr), cmd_list (cmds)
74  {
75  if (m_scope)
76  m_scope.set_user_code (this);
77  }
78 
79 public:
80 
81  // No copying!
82 
83  octave_user_code (const octave_user_code& f) = delete;
84 
85  octave_user_code& operator = (const octave_user_code& f) = delete;
86 
87  ~octave_user_code (void);
88 
89  bool is_user_code (void) const { return true; }
90 
91  std::string get_code_line (size_t line);
92 
93  std::deque<std::string> get_code_lines (size_t line, size_t num_lines);
94 
95  void cache_function_text (const std::string& text,
96  const octave::sys::time& timestamp);
97 
98  octave::symbol_scope scope (void) { return m_scope; }
99 
100  void stash_fcn_file_name (const std::string& nm) { file_name = nm; }
101 
102  void mark_fcn_file_up_to_date (const octave::sys::time& t) { t_checked = t; }
103 
105  {
106  t_parsed = t;
107  mark_fcn_file_up_to_date (t);
108  }
109 
110  std::string fcn_file_name (void) const { return file_name; }
111 
112  octave::sys::time time_parsed (void) const { return t_parsed; }
113 
114  octave::sys::time time_checked (void) const { return t_checked; }
115 
116  virtual octave_value find_subfunction (const std::string&) const
117  {
118  return octave_value ();
119  }
120 
121  virtual std::map<std::string, octave_value> subfunctions (void) const;
122 
123  octave::tree_statement_list * body (void) { return cmd_list; }
124 
125  octave_value dump (void) const;
126 
127 protected:
128 
129  void get_file_info (void);
130 
131  // Our symbol table scope.
133 
134  // The name of the file we parsed.
135  std::string file_name;
136 
137  // The time the file was parsed.
139 
140  // The time the file was last checked to see if it needs to be
141  // parsed again.
143 
144  // Cached text of function or script code with line offsets
145  // calculated.
147 
148  // The list of commands that make up the body of this function.
150 };
151 
152 // Scripts.
153 
154 class
156 {
157 public:
158 
159  octave_user_script (void);
160 
161  octave_user_script (const std::string& fnm, const std::string& nm,
162  const octave::symbol_scope& scope = octave::symbol_scope (),
163  octave::tree_statement_list *cmds = nullptr,
164  const std::string& ds = "");
165 
166  octave_user_script (const std::string& fnm, const std::string& nm,
167  const octave::symbol_scope& scope = octave::symbol_scope (),
168  const std::string& ds = "");
169 
170  // No copying!
171 
173 
174  octave_user_script& operator = (const octave_user_script& f) = delete;
175 
176  ~octave_user_script (void) = default;
177 
178  octave_function * function_value (bool = false) { return this; }
179 
180  octave_user_script * user_script_value (bool = false) { return this; }
181 
182  octave_user_code * user_code_value (bool = false) { return this; }
183 
184  // Scripts and user functions are both considered "scripts" because
185  // they are written in Octave's scripting language.
186 
187  bool is_user_script (void) const { return true; }
188 
189  // We must overload the call method so that we call the proper
190  // push_stack_frame method, which is overloaded for pointers to
191  // octave_function, octave_user_function, and octave_user_script
192  // objects.
193 
195  call (octave::tree_evaluator& tw, int nargout = 0,
196  const octave_value_list& args = octave_value_list ());
197 
199  execute (octave::tree_evaluator& tw, int nargout = 0,
200  const octave_value_list& args = octave_value_list ());
201 
202  void accept (octave::tree_walker& tw);
203 
204 private:
205 
207 };
208 
209 // User-defined functions.
210 
211 class
213 {
214 public:
215 
217  octave::tree_parameter_list *pl = nullptr,
218  octave::tree_parameter_list *rl = nullptr,
219  octave::tree_statement_list *cl = nullptr);
220 
221  // No copying!
222 
224 
225  octave_user_function& operator = (const octave_user_function& fn) = delete;
226 
227  ~octave_user_function (void);
228 
229  octave_function * function_value (bool = false) { return this; }
230 
231  octave_user_function * user_function_value (bool = false) { return this; }
232 
233  octave_user_code * user_code_value (bool = false) { return this; }
234 
236 
237  octave_user_function * define_ret_list (octave::tree_parameter_list *t);
238 
239  void stash_fcn_location (int line, int col)
240  {
241  location_line = line;
242  location_column = col;
243  }
244 
245  int beginning_line (void) const { return location_line; }
246  int beginning_column (void) const { return location_column; }
247 
248  void stash_fcn_end_location (int line, int col)
249  {
250  end_location_line = line;
251  end_location_column = col;
252  }
253 
254  int ending_line (void) const { return end_location_line; }
255  int ending_column (void) const { return end_location_column; }
256 
257  void maybe_relocate_end (void);
258 
259  void stash_parent_fcn_name (const std::string& p) { parent_name = p; }
260 
261  void stash_parent_fcn_scope (const octave::symbol_scope& ps);
262 
263  void stash_leading_comment (octave::comment_list *lc) { lead_comm = lc; }
264 
265  void stash_trailing_comment (octave::comment_list *tc) { trail_comm = tc; }
266 
267  std::string profiler_name (void) const;
268 
269  std::string parent_fcn_name (void) const { return parent_name; }
270 
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 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) { my_name = s; }
312 
313  void mark_as_subfunction (void) { subfunction = true; }
314 
315  bool is_subfunction (void) const { return subfunction; }
316 
317  void mark_as_inline_function (void) { inline_function = true; }
318 
319  bool is_inline_function (void) const { return inline_function; }
320 
321  void mark_as_anonymous_function (void) { anonymous_function = true; }
322 
323  bool is_anonymous_function (void) const { return anonymous_function; }
324 
326  (const std::string& cname = "") const
327  {
328  return 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) { nested_function = true; }
344 
345  bool is_nested_function (void) const { return nested_function; }
346 
347  bool is_parent_function (void) const { return m_scope.is_parent (); }
348 
349  void mark_as_legacy_constructor (void) { class_constructor = legacy; }
350 
351  bool is_legacy_constructor (const std::string& cname = "") const
352  {
353  return (class_constructor == legacy
354  ? (cname.empty () ? true : cname == dispatch_class ()) : false);
355  }
356 
357  void mark_as_classdef_constructor (void) { class_constructor = classdef; }
358 
359  bool is_classdef_constructor (const std::string& cname = "") const
360  {
361  return (class_constructor == classdef
362  ? (cname.empty () ? true : cname == dispatch_class ()) : false);
363  }
364 
365  void mark_as_legacy_method (void) { class_method = legacy; }
366 
367  bool is_legacy_method (const std::string& cname = "") const
368  {
369  return (class_method == legacy
370  ? (cname.empty () ? true : cname == dispatch_class ()) : false);
371  }
372 
373  void mark_as_classdef_method (void) { class_method = classdef; }
374 
375  bool is_classdef_method (const std::string& cname = "") const
376  {
377  return (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 param_list; }
395 
396  octave::tree_parameter_list * return_list (void) { return ret_list; }
397 
398  octave::comment_list * leading_comment (void) { return lead_comm; }
399 
400  octave::comment_list * trailing_comment (void) { return 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 #if defined (HAVE_LLVM)
411  octave::jit_function_info * get_info (void) { return jit_info; }
412 
413  void stash_info (octave::jit_function_info *info) { jit_info = info; }
414 #endif
415 
416  octave_value dump (void) const;
417 
418 private:
419 
420  enum class_method_type
421  {
424  classdef
425  };
426 
427  std::string ctor_type_str (void) const;
428  std::string method_type_str (void) const;
429 
430  // List of arguments for this function. These are local variables.
432 
433  // List of parameters we return. These are also local variables in
434  // this function.
436 
437  // The comments preceding the FUNCTION token.
439 
440  // The comments preceding the ENDFUNCTION token.
442 
443  // Location where this function was defined.
448 
449  // The name of the parent function, if any.
450  std::string parent_name;
451 
452  // True if this function came from a file that is considered to be a
453  // system function. This affects whether we check the time stamp
454  // on the file to see if it has changed.
456 
457  // The number of arguments that have names.
459 
460  // TRUE means this is a subfunction of a primary function.
462 
463  // TRUE means this is an inline function.
465 
466  // TRUE means this is an anonymous function.
468 
469  // TRUE means this is a nested function.
471 
472  // TRUE means this function contains a nested function.
474 
475  // Enum describing whether this function is the constructor for class object.
477 
478  // Enum describing whether this function is a method for a class.
480 
481 #if defined (HAVE_LLVM)
483 #endif
484 
485  void maybe_relocate_end_internal (void);
486 
487  void print_code_function_header (const std::string& prefix);
488 
489  void print_code_function_trailer (const std::string& prefix);
490 
491  // XXX FIXME (public)
492 public:
493 
494  void restore_warning_states (void);
495 
497 };
498 
499 #endif
std::shared_ptr< symbol_scope_rep > parent_scope(void) const
Definition: symscope.h:455
void stash_fcn_file_name(const std::string &nm)
Definition: ov-usr-fcn.h:100
std::string fcn_file_name(void) const
Definition: ov-usr-fcn.h:110
octave_user_code(const octave_user_code &f)=delete
octave::tree_statement_list * body(void)
Definition: ov-usr-fcn.h:123
void mark_fcn_file_up_to_date(const octave::sys::time &t)
Definition: ov-usr-fcn.h:102
octave::sys::time time_checked(void) const
Definition: ov-usr-fcn.h:114
std::string file_name
Definition: ov-usr-fcn.h:135
virtual octave_value find_subfunction(const std::string &) const
Definition: ov-usr-fcn.h:116
octave::file_info * m_file_info
Definition: ov-usr-fcn.h:146
octave::sys::time time_parsed(void) const
Definition: ov-usr-fcn.h:112
void stash_fcn_file_time(const octave::sys::time &t)
Definition: ov-usr-fcn.h:104
octave::symbol_scope scope(void)
Definition: ov-usr-fcn.h:98
bool is_user_code(void) const
Definition: ov-usr-fcn.h:89
octave::sys::time t_parsed
Definition: ov-usr-fcn.h:138
octave::symbol_scope m_scope
Definition: ov-usr-fcn.h:132
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:66
octave::sys::time t_checked
Definition: ov-usr-fcn.h:142
octave::tree_statement_list * cmd_list
Definition: ov-usr-fcn.h:149
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:269
std::string parent_name
Definition: ov-usr-fcn.h:450
octave::jit_function_info * get_info(void)
Definition: ov-usr-fcn.h:411
octave::tree_parameter_list * ret_list
Definition: ov-usr-fcn.h:435
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:265
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
octave::comment_list * trail_comm
Definition: ov-usr-fcn.h:441
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_function * function_value(bool=false)
Definition: ov-usr-fcn.h:229
int ending_line(void) const
Definition: ov-usr-fcn.h:254
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
class_method_type class_constructor
Definition: ov-usr-fcn.h:476
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:231
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:255
int beginning_column(void) const
Definition: ov-usr-fcn.h:246
void mark_as_classdef_constructor(void)
Definition: ov-usr-fcn.h:357
octave::jit_function_info * jit_info
Definition: ov-usr-fcn.h:482
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:233
bool is_inline_function(void) const
Definition: ov-usr-fcn.h:319
void stash_parent_fcn_name(const std::string &p)
Definition: ov-usr-fcn.h:259
void stash_info(octave::jit_function_info *info)
Definition: ov-usr-fcn.h:413
octave::comment_list * lead_comm
Definition: ov-usr-fcn.h:438
std::list< std::string > parent_fcn_names(void) const
Definition: ov-usr-fcn.h:276
void stash_leading_comment(octave::comment_list *lc)
Definition: ov-usr-fcn.h:263
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:245
void stash_fcn_location(int line, int col)
Definition: ov-usr-fcn.h:239
void stash_fcn_end_location(int line, int col)
Definition: ov-usr-fcn.h:248
octave_user_function(const octave_user_function &fn)=delete
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 * trailing_comment(void)
Definition: ov-usr-fcn.h:400
octave::tree_parameter_list * param_list
Definition: ov-usr-fcn.h:431
bool is_anonymous_function(void) const
Definition: ov-usr-fcn.h:323
class_method_type class_method
Definition: ov-usr-fcn.h:479
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:187
octave_user_script(const octave_user_script &f)=delete
octave_user_code * user_code_value(bool=false)
Definition: ov-usr-fcn.h:182
octave_function * function_value(bool=false)
Definition: ov-usr-fcn.h:178
octave_user_script * user_script_value(bool=false)
Definition: ov-usr-fcn.h:180
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:158