GNU Octave 7.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
pt-fcn-handle.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 2003-2022 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 (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include <ostream>
31
32#include "interpreter-private.h"
33#include "pt-anon-scopes.h"
34#include "pt-fcn-handle.h"
35#include "stack-frame.h"
36
37namespace octave
38{
39 void
40 tree_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax,
41 bool pr_orig_text)
42 {
43 print_raw (os, pr_as_read_syntax, pr_orig_text);
44 }
45
46 void
47 tree_fcn_handle::print_raw (std::ostream& os, bool pr_as_read_syntax,
48 bool pr_orig_text)
49 {
50 os << ((pr_as_read_syntax || pr_orig_text) ? "@" : "") << m_name;
51 }
52
55 {
56 tree_fcn_handle *new_fh = new tree_fcn_handle (m_name, line (), column ());
57
58 new_fh->copy_base (*this);
59
60 return new_fh;
61 }
62
65 {
66 return tw.make_fcn_handle (m_name);
67 }
68
70 {
71 delete m_parameter_list;
72 delete m_expression;
73 }
74
77 {
78 tree_parameter_list *param_list = parameter_list ();
79 tree_expression *expr = expression ();
80
81 symbol_scope af_scope = m_scope;
82 symbol_scope af_parent_scope = m_parent_scope;
83
84 symbol_scope new_scope;
85
86 if (af_scope)
87 new_scope = af_scope.dup ();
88
89 // FIXME: if new scope is nullptr, then we are in big trouble here...
90
91 tree_anon_fcn_handle *new_afh = new
92 tree_anon_fcn_handle (param_list ? param_list->dup (new_scope) : nullptr,
93 expr ? expr->dup (new_scope) : nullptr,
94 new_scope, af_parent_scope, line (), column ());
95
96 new_afh->copy_base (*this);
97
98 return new_afh;
99 }
100
103 {
104 // FIXME: should CMD_LIST be limited to a single expression?
105 // I think that is what Matlab does.
106
107 symbol_scope new_scope;
108 if (m_scope)
109 new_scope = m_scope.dup ();
110
111 tree_parameter_list *param_list_dup
112 = m_parameter_list ? m_parameter_list->dup (new_scope) : nullptr;
113
114 tree_parameter_list *ret_list = nullptr;
115
116 tree_statement_list *stmt_list = nullptr;
117
119
120 new_scope.set_parent (parent_scope);
122
123 if (m_expression)
124 {
125 tree_expression *expr_dup = m_expression->dup (new_scope);
126 tree_statement *stmt = new tree_statement (expr_dup, nullptr);
127 stmt_list = new tree_statement_list (stmt);
128 }
129
130 tree_anon_scopes anon_fcn_ctx (*this);
131
132 std::set<std::string> free_vars = anon_fcn_ctx.free_variables ();
133
135
136 call_stack& cs = tw.get_call_stack ();
137
138 std::shared_ptr<stack_frame> frame = cs.get_current_stack_frame ();
139
140 for (auto& name : free_vars)
141 {
142 octave_value val = frame->varval (name);
143
144 if (val.is_defined ())
145 local_vars[name] = val;
146 }
147
149 = new octave_user_function (new_scope, param_list_dup, ret_list,
150 stmt_list);
151
152 octave_function *curr_fcn = cs.current_function ();
153
154 bool is_nested = false;
155
156 if (curr_fcn)
157 {
158 // FIXME: maybe it would be better to just stash curr_fcn
159 // instead of individual bits of info about it?
160
161 // An anonymous function defined inside another nested function
162 // or parent of a nested function also behaves like a nested
163 // function.
164
165 if (curr_fcn->is_parent_function () || curr_fcn->is_nested_function ())
166 {
167 is_nested = true;
170 }
171
172 af->stash_dir_name (curr_fcn->dir_name ());
173
174 new_scope.cache_fcn_file_name (curr_fcn->fcn_file_name ());
175 new_scope.cache_dir_name (curr_fcn->dir_name ());
176
177 // The following is needed so that class method dispatch works
178 // properly for anonymous functions that wrap class methods.
179
180 if (curr_fcn->is_class_method () || curr_fcn->is_class_constructor ())
181 af->stash_dispatch_class (curr_fcn->dispatch_class ());
182
183 af->stash_fcn_file_name (curr_fcn->fcn_file_name ());
184 }
185
187
188 octave_value ov_fcn (af);
189
190 return (is_nested
191 ? octave_value (new octave_fcn_handle (ov_fcn, local_vars, frame))
192 : octave_value (new octave_fcn_handle (ov_fcn, local_vars)));
193 }
194}
195
196/*
197%!function r = __f2 (f, x)
198%! r = f (x);
199%!endfunction
200%!function f = __f1 (k)
201%! f = @(x) __f2 (@(y) y-k, x);
202%!endfunction
203
204%!assert ((__f1 (3)) (10) == 7)
205
206%!test
207%! g = @(t) feval (@(x) t*x, 2);
208%! assert (g(0.5) == 1);
209
210%!test
211%! h = @(x) sin (x);
212%! g = @(f, x) h (x);
213%! f = @() g (@(x) h, pi);
214%! assert (f () == sin (pi));
215
216The next two tests are intended to test parsing of a character string
217vs. hermitian operator at the beginning of an anonymous function
218expression. The use of ' for the character string and the spacing is
219intentional, so don't change it.
220
221%!test
222%! f = @() 'foo';
223%! assert (f (), 'foo');
224
225%!test
226%! f = @()'foo';
227%! assert (f (), 'foo');
228*/
octave_function * current_function(bool skip_first=false) const
Definition: call-stack.cc:66
std::shared_ptr< stack_frame > get_current_stack_frame(void) const
Definition: call-stack.h:91
std::map< std::string, octave_value > local_vars_map
Definition: stack-frame.h:112
void set_primary_parent(const symbol_scope &p)
Definition: symscope.h:615
symbol_scope dup(void) const
Definition: symscope.h:457
void set_nesting_depth(std::size_t depth)
Definition: symscope.h:425
void set_parent(const symbol_scope &p)
Definition: symscope.h:609
void cache_dir_name(const std::string &name)
Definition: symscope.h:627
void cache_fcn_file_name(const std::string &name)
Definition: symscope.h:621
std::size_t nesting_depth(void) const
Definition: symscope.h:431
tree_parameter_list * parameter_list(void) const
tree_expression * dup(symbol_scope &scope) const
tree_parameter_list * m_parameter_list
octave_value evaluate(tree_evaluator &tw, int nargout=1)
tree_anon_fcn_handle(int l=-1, int c=-1)
tree_expression * m_expression
symbol_scope parent_scope(void) const
tree_expression * expression(void) const
std::set< std::string > free_variables(void) const
virtual void copy_base(const tree_expression &e)
Definition: pt-exp.h:133
virtual std::string name(void) const
Definition: pt-exp.h:105
virtual tree_expression * dup(symbol_scope &scope) const =0
tree_fcn_handle(int l=-1, int c=-1)
Definition: pt-fcn-handle.h:52
tree_expression * dup(symbol_scope &scope) const
void print_raw(std::ostream &os, bool pr_as_read_syntax=false, bool pr_orig_txt=true)
octave_value evaluate(tree_evaluator &tw, int nargout=1)
void print(std::ostream &os, bool pr_as_read_syntax=false, bool pr_orig_txt=true)
tree_parameter_list * dup(symbol_scope &scope) const
Definition: pt-misc.cc:69
virtual int column(void) const
Definition: pt.h:62
virtual int line(void) const
Definition: pt.h:60
std::string dispatch_class(void) const
Definition: ov-fcn.h:149
virtual std::string fcn_file_name(void) const
Definition: ov-fcn.h:78
std::string dir_name(void) const
Definition: ov-fcn.h:171
bool is_class_method(const std::string &cname="") const
Definition: ov-fcn.h:116
virtual bool is_parent_function(void) const
Definition: ov-fcn.h:107
bool is_class_constructor(const std::string &cname="") const
Definition: ov-fcn.h:111
void stash_dir_name(const std::string &dir)
Definition: ov-fcn.h:173
void stash_dispatch_class(const std::string &nm)
Definition: ov-fcn.h:147
virtual bool is_nested_function(void) const
Definition: ov-fcn.h:105
void stash_fcn_file_name(const std::string &nm)
Definition: ov-usr-fcn.h:95
void mark_as_anonymous_function(void)
Definition: ov-usr-fcn.h:320
void mark_as_nested_function(void)
Definition: ov-usr-fcn.h:342
bool is_defined(void) const
Definition: ov.h:637
symbol_scope get_current_scope(void) const
Definition: pt-eval.cc:2656
call_stack & get_call_stack(void)
Definition: pt-eval.h:420
octave_value make_fcn_handle(const std::string &nm)
Definition: pt-eval.cc:1604