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