GNU Octave 11.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-2026 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 octave::comment_list leading_comments () const;
89 OCTINTERP_API octave::comment_list trailing_comments () const;
90
91 OCTINTERP_API std::string get_code_line (std::size_t line);
92
93 OCTINTERP_API std::deque<std::string>
94 get_code_lines (std::size_t line, std::size_t num_lines);
95
96 OCTINTERP_API void
97 cache_function_text (const std::string& text,
98 const octave::sys::time& timestamp);
99
100 octave::symbol_scope scope () { return m_scope; }
101
102 std::size_t scope_num_symbols () { return m_scope.num_symbols (); }
103
104 void stash_fcn_file_name (const std::string& nm) { m_file_name = nm; }
105
106 void mark_fcn_file_up_to_date (const octave::sys::time& t)
107 { m_t_checked = t; }
108
109 void stash_fcn_file_time (const octave::sys::time& t)
110 {
111 m_t_parsed = t;
112 mark_fcn_file_up_to_date (t);
113 }
114
115 std::string fcn_file_name () const { return m_file_name; }
116
117 octave::sys::time time_parsed () const { return m_t_parsed; }
118
119 octave::sys::time time_checked () const { return m_t_checked; }
120
121 virtual octave_value find_subfunction (const std::string&) const
122 {
123 return octave_value ();
124 }
125
126 virtual std::map<std::string, octave_value> subfunctions () const;
127
128 octave::tree_statement_list * body () { return m_cmd_list; }
129
130 OCTINTERP_API octave_value dump () const;
131
132protected:
133
134 OCTINTERP_API void get_file_info ();
135
136 // Our symbol table scope.
137 octave::symbol_scope m_scope;
138
139 // The name of the file we parsed.
140 std::string m_file_name;
141
142 // The time the file was parsed.
143 octave::sys::time m_t_parsed;
144
145 // The time the file was last checked to see if it needs to be
146 // parsed again.
147 octave::sys::time m_t_checked;
148
149 // Cached text of function or script code with line offsets
150 // calculated.
151 octave::file_info *m_file_info;
152
153 // The list of commands that make up the body of this function.
154 octave::tree_statement_list *m_cmd_list;
155};
156
157// Scripts.
158
159class OCTINTERP_API octave_user_script : public octave_user_code
160{
161public:
162
163 OCTINTERP_API octave_user_script ();
164
165 OCTINTERP_API
166 octave_user_script (const std::string& fnm, const std::string& nm,
167 const octave::symbol_scope& scope = octave::symbol_scope::anonymous (),
168 octave::tree_statement_list *cmds = nullptr,
169 const std::string& ds = "");
170
171 OCTINTERP_API
172 octave_user_script (const std::string& fnm, const std::string& nm,
173 const octave::symbol_scope& scope = octave::symbol_scope::anonymous (),
174 const std::string& ds = "");
175
176 OCTAVE_DISABLE_COPY_MOVE (octave_user_script)
177
179
180 octave_function * function_value (bool = false) { return this; }
181
182 octave_user_script * user_script_value (bool = false) { return this; }
183
184 octave_user_code * user_code_value (bool = false) { return this; }
185
186 // Scripts and user functions are both considered "scripts" because
187 // they are written in Octave's scripting language.
188
189 bool is_user_script () const { return true; }
190
191 // We must overload the call method so that we call the proper
192 // push_stack_frame method, which is overloaded for pointers to
193 // octave_function, octave_user_function, and octave_user_script
194 // objects.
195
196 OCTINTERP_API octave_value_list
197 call (octave::tree_evaluator& tw, int nargout = 0,
198 const octave_value_list& args = octave_value_list ());
199
200 OCTINTERP_API octave_value_list
201 execute (octave::tree_evaluator& tw, int nargout = 0,
202 const octave_value_list& args = octave_value_list ());
203
204 OCTINTERP_API void accept (octave::tree_walker& tw);
205
206private:
207
209};
210
211// User-defined functions.
212
213class OCTINTERP_API octave_user_function : public octave_user_code
214{
215public:
216
217 OCTINTERP_API
218 octave_user_function (const octave::symbol_scope& scope = octave::symbol_scope::anonymous (),
219 octave::tree_identifier *id = nullptr,
220 octave::tree_parameter_list *pl = nullptr,
221 octave::tree_parameter_list *rl = nullptr,
222 octave::tree_statement_list *cl = nullptr);
223
224 OCTAVE_DISABLE_COPY_MOVE (octave_user_function)
225
226 OCTINTERP_API ~octave_user_function ();
227
228 // Declared calling form, generated from the parse tree.
229 OCTINTERP_API std::string signature () const;
230
231 octave_function * function_value (bool = false) { return this; }
232
233 octave_user_function * user_function_value (bool = false) { return this; }
234
235 octave_user_code * user_code_value (bool = false) { return this; }
236
237 OCTINTERP_API octave_user_function *
238 define_param_list (octave::tree_parameter_list *t);
239
240 OCTINTERP_API octave_user_function *
241 define_ret_list (octave::tree_parameter_list *t);
242
243 void set_fcn_tok (const octave::token& fcn_tok) { m_fcn_tok = fcn_tok; }
244 void set_eq_tok (const octave::token& eq_tok) { m_eq_tok = eq_tok; }
245
246 OCTINTERP_API void
247 attach_trailing_comments (const octave::comment_list& lst);
248
249 octave::filepos beg_pos () const { return m_fcn_tok.beg_pos(); }
250 // The end_pos function is defined in the octave_user_code class.
251
252 octave::comment_list leading_comments () const
253 { return m_fcn_tok.leading_comments (); }
254 // The trailing_comments function is defined in the octave_user_code class.
255
256 OCTINTERP_API void maybe_relocate_end ();
257
258 OCTINTERP_API void stash_parent_fcn_scope (const octave::symbol_scope& ps);
259
260 OCTINTERP_API std::string profiler_name () const;
261
262 std::string parent_fcn_name () const
263 {
264 octave::symbol_scope pscope = parent_fcn_scope ();
265
266 return pscope.fcn_name ();
267 }
268
269 octave::symbol_scope parent_fcn_scope () const
270 {
271 return m_scope.parent_scope ();
272 }
273
274 std::list<std::string> parent_fcn_names () const
275 {
276 return m_scope.parent_fcn_names ();
277 }
278
279 OCTINTERP_API void mark_as_system_fcn_file ();
280
281 bool is_system_fcn_file () const { return m_system_fcn_file; }
282
283 bool is_user_function () const { return true; }
284
285 OCTINTERP_API void erase_subfunctions ();
286
287 OCTINTERP_API bool takes_varargs () const;
288
289 OCTINTERP_API bool takes_var_return () const;
290
291 OCTINTERP_API void mark_as_private_function (const std::string& cname = "");
292
293 OCTINTERP_API void lock_subfunctions ();
294
295 OCTINTERP_API void unlock_subfunctions ();
296
297 OCTINTERP_API std::map<std::string, octave_value> subfunctions () const;
298
299 OCTINTERP_API octave_value
300 find_subfunction (const std::string& subfuns) const;
301
302 OCTINTERP_API bool has_subfunctions () const;
303
304 OCTINTERP_API void
305 stash_subfunction_names (const std::list<std::string>& names);
306
307 OCTINTERP_API std::list<std::string> subfunction_names () const;
308
309 OCTINTERP_API 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 () { m_subfunction = true; }
314
315 bool is_subfunction () const { return m_subfunction; }
316
317 void mark_as_inline_function () { m_inline_function = true; }
318
319 bool is_inline_function () const { return m_inline_function; }
320
321 void mark_as_anonymous_function () { m_anonymous_function = true; }
322
323 bool is_anonymous_function () 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 () const
339 {
340 return is_inline_function () || is_anonymous_function ();
341 }
342
343 void mark_as_nested_function () { m_nested_function = true; }
344
345 bool is_nested_function () const { return m_nested_function; }
346
347 bool is_parent_function () const { return m_scope.is_parent (); }
348
349 void mark_as_legacy_constructor () { 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 () { 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 () { 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 () { 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
386 OCTINTERP_API octave_value_list
387 call (octave::tree_evaluator& tw, int nargout = 0,
388 const octave_value_list& args = octave_value_list ());
389
390 OCTINTERP_API octave_value_list
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 () { return m_param_list; }
395
396 octave::tree_parameter_list * return_list () { return m_ret_list; }
397
398 // If is_special_expr is true, retrieve the sigular expression that forms the
399 // body. May be null (even if is_special_expr is true).
400 OCTINTERP_API octave::tree_expression * special_expr ();
401
402 OCTINTERP_API bool subsasgn_optimization_ok ();
403
404 OCTINTERP_API void accept (octave::tree_walker& tw);
405
406 OCTINTERP_API octave_value dump () const;
407
408private:
409
410 enum class_method_type
411 {
412 none,
413 legacy,
414 classdef
415 };
416
417 OCTINTERP_API std::string ctor_type_str () const;
418 OCTINTERP_API std::string method_type_str () const;
419
420 // Name of this function.
421 octave::tree_identifier *m_id;
422
423 // List of arguments for this function. These are local variables.
424 octave::tree_parameter_list *m_param_list;
425
426 // List of parameters we return. These are also local variables in
427 // this function.
428 octave::tree_parameter_list *m_ret_list;
429
430 // We don't keep track of an end token separately because functions
431 // may still be defined without an explicit END. If there is an
432 // explicit END, the final statement will contain it.
433
434 octave::token m_fcn_tok;
435 octave::token m_eq_tok;
436
437 // True if this function came from a file that is considered to be a
438 // system function. This affects whether we check the time stamp
439 // on the file to see if it has changed.
440 bool m_system_fcn_file {false};
441
442 // The number of arguments that have names.
443 int m_num_named_args;
444
445 // TRUE means this is a m_subfunction of a primary function.
446 bool m_subfunction {false};
447
448 // TRUE means this is an inline function.
449 bool m_inline_function {false};
450
451 // TRUE means this is an anonymous function.
452 bool m_anonymous_function {false};
453
454 // TRUE means this is a nested function.
455 bool m_nested_function {false};
456
457 // Enum describing whether this function is the constructor for class object.
458 class_method_type m_class_constructor {none};
459
460 // Enum describing whether this function is a method for a class.
461 class_method_type m_class_method {none};
462
463 OCTINTERP_API void maybe_relocate_end_internal ();
464
465 OCTINTERP_API void print_code_function_header (const std::string& prefix);
466
467 OCTINTERP_API void print_code_function_trailer (const std::string& prefix);
468
469 // XXX FIXME (public)
470public:
471
472 OCTINTERP_API void restore_warning_states ();
473
475};
476
477#endif
void stash_fcn_file_name(const std::string &nm)
Definition ov-usr-fcn.h:104
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:100
std::string m_file_name
Definition ov-usr-fcn.h:140
void mark_fcn_file_up_to_date(const octave::sys::time &t)
Definition ov-usr-fcn.h:106
octave::sys::time m_t_checked
Definition ov-usr-fcn.h:147
std::string fcn_file_name() const
Definition ov-usr-fcn.h:115
octave::tree_statement_list * m_cmd_list
Definition ov-usr-fcn.h:154
virtual octave_value find_subfunction(const std::string &) const
Definition ov-usr-fcn.h:121
octave::sys::time m_t_parsed
Definition ov-usr-fcn.h:143
octave::file_info * m_file_info
Definition ov-usr-fcn.h:151
void stash_fcn_file_time(const octave::sys::time &t)
Definition ov-usr-fcn.h:109
octave::symbol_scope m_scope
Definition ov-usr-fcn.h:137
std::size_t scope_num_symbols()
Definition ov-usr-fcn.h:102
octave::sys::time time_parsed() const
Definition ov-usr-fcn.h:117
octave::sys::time time_checked() const
Definition ov-usr-fcn.h:119
octave::tree_statement_list * body()
Definition ov-usr-fcn.h:128
void mark_as_inline_function()
Definition ov-usr-fcn.h:317
bool is_legacy_method(const std::string &cname="") const
Definition ov-usr-fcn.h:367
std::list< std::string > parent_fcn_names() const
Definition ov-usr-fcn.h:274
void stash_function_name(const std::string &s)
Definition ov-usr-fcn.h:311
void set_fcn_tok(const octave::token &fcn_tok)
Definition ov-usr-fcn.h:243
bool is_nested_function() const
Definition ov-usr-fcn.h:345
octave_user_code * user_code_value(bool=false)
Definition ov-usr-fcn.h:235
bool is_inline_function() const
Definition ov-usr-fcn.h:319
octave::tree_parameter_list * parameter_list()
Definition ov-usr-fcn.h:394
bool is_special_expr() const
Definition ov-usr-fcn.h:338
octave::comment_list leading_comments() const
Definition ov-usr-fcn.h:252
bool is_classdef_constructor(const std::string &cname="") const
Definition ov-usr-fcn.h:359
bool is_system_fcn_file() const
Definition ov-usr-fcn.h:281
octave::symbol_scope parent_fcn_scope() const
Definition ov-usr-fcn.h:269
void mark_as_classdef_method()
Definition ov-usr-fcn.h:373
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
octave::tree_parameter_list * return_list()
Definition ov-usr-fcn.h:396
void set_eq_tok(const octave::token &eq_tok)
Definition ov-usr-fcn.h:244
std::string parent_fcn_name() const
Definition ov-usr-fcn.h:262
octave_user_function * user_function_value(bool=false)
Definition ov-usr-fcn.h:233
bool is_anonymous_function() const
Definition ov-usr-fcn.h:323
octave_function * function_value(bool=false)
Definition ov-usr-fcn.h:231
bool is_anonymous_function_of_class(const std::string &cname="") const
Definition ov-usr-fcn.h:326
void mark_as_legacy_constructor()
Definition ov-usr-fcn.h:349
bool is_subfunction() const
Definition ov-usr-fcn.h:315
octave_user_function * define_param_list(octave::tree_parameter_list *t)
void mark_as_anonymous_function()
Definition ov-usr-fcn.h:321
bool is_parent_function() const
Definition ov-usr-fcn.h:347
octave::filepos beg_pos() const
Definition ov-usr-fcn.h:249
void mark_as_classdef_constructor()
Definition ov-usr-fcn.h:357
bool is_user_function() const
Definition ov-usr-fcn.h:283
void mark_as_nested_function()
Definition ov-usr-fcn.h:343
octave_user_code * user_code_value(bool=false)
Definition ov-usr-fcn.h:184
~octave_user_script()=default
bool is_user_script() const
Definition ov-usr-fcn.h:189
octave_user_script * user_script_value(bool=false)
Definition ov-usr-fcn.h:182
octave_function * function_value(bool=false)
Definition ov-usr-fcn.h:180
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
#define DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API(API)
Definition ov-base.h:185