GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
cdef-property.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 2012-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 (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include <algorithm>
31#include <iomanip>
32
33#include "cdef-class.h"
34#include "cdef-manager.h"
35#include "cdef-utils.h"
36#include "errwarn.h"
37#include "interpreter-private.h"
38#include "interpreter.h"
39#include "load-path.h"
40#include "ov-builtin.h"
41#include "ov-classdef.h"
42#include "ov-fcn-handle.h"
43#include "ov-usr-fcn.h"
44#include "pt-assign.h"
45#include "pt-classdef.h"
46#include "pt-eval.h"
47#include "pt-idx.h"
48#include "pt-misc.h"
49#include "pt-stmt.h"
50#include "pt-walk.h"
51
53
54static bool
55is_method_executing (const octave_value& ov, const cdef_object& obj)
56{
58
59 octave_function *stack_fcn = tw.current_function ();
60
61 octave_function *method_fcn = ov.function_value (true);
62
63 // Does the top of the call stack match our target function?
64
65 if (stack_fcn && stack_fcn == method_fcn)
66 {
67 octave_user_function *uf = method_fcn->user_function_value (true);
68
69 // We can only check the context object for user-function (not builtin),
70 // where we have access to the parameters (arguments and return values).
71 // That's ok as there's no need to call this function for builtin
72 // methods.
73
74 if (uf)
75 {
76 // At this point, the method is executing, but we still need to
77 // check the context object for which the method is executing. For
78 // methods, it's the first argument of the function; for ctors, it
79 // is the first return value.
80
82 ? uf->return_list ()
83 : uf->parameter_list ();
84
85 if (pl && pl->size () > 0)
86 {
87 tree_decl_elt *elt = pl->front ();
88
89 octave_value arg0 = tw.evaluate (elt);
90
91 if (arg0.is_defined () && arg0.type_name () == "object")
92 {
93 cdef_object arg0_obj = to_cdef (arg0);
94
95 return obj.is (arg0_obj);
96 }
97 }
98 }
99 }
100
101 return false;
102}
103
105cdef_property::cdef_property_rep::get_value (const cdef_object& obj,
106 bool do_check_access,
107 const std::string& who) const
108{
109 octave_value retval;
110
111 if (do_check_access && ! check_get_access ())
112 err_property_access (who, false);
113
114 if (! obj.is_constructed ())
115 {
116 cdef_class cls (to_cdef (get ("DefiningClass")));
117
118 if (! obj.is_partially_constructed_for (cls))
119 error ("cannot reference properties of class '%s' for non-constructed object",
120 cls.get_name ().c_str ());
121 }
122
123 octave_value get_fcn = get ("GetMethod");
124
125 // FIXME: should check whether we're already in get accessor method
126
127 if (get_fcn.isempty () || is_method_executing (get_fcn, obj))
128 retval = obj.get (get ("Name").string_value ());
129 else
130 {
132
133 args(0) = to_ov (obj);
134
135 interpreter& interp = __get_interpreter__ ();
136
137 args = interp.feval (get_fcn, args, 1);
138
139 retval = args(0);
140 }
141
142 return retval;
143}
144
146cdef_property::cdef_property_rep::get_value (bool do_check_access,
147 const std::string& who) const
148{
149 if (do_check_access && ! check_get_access ())
150 err_property_access (who, false);
151
152 return get ("DefaultValue");
153}
154
155bool
156cdef_property::cdef_property_rep::is_recursive_set (const cdef_object& /* obj */) const
157{
158 // FIXME: implement
159 return false;
160}
161
162OCTAVE_NORETURN void
163cdef_property::cdef_property_rep::err_property_access
164(const std::string& from, bool is_set) const
165{
166 octave_value acc = get (is_set ? "SetAccess" : "GetAccess");
167 std::string acc_s;
168
169 if (acc.is_string ())
170 acc_s = acc.string_value ();
171 else
172 acc_s = "class-restricted";
173
174 if (is_set)
175 error ("%s: property '%s' has %s access and cannot be set in this context",
176 from.c_str (), get_name ().c_str (), acc_s.c_str ());
177 else
178 error ("%s: property '%s' has %s access and cannot be obtained in this context",
179 from.c_str (), get_name ().c_str (), acc_s.c_str ());
180}
181
182void
183cdef_property::cdef_property_rep::set_value (cdef_object& obj,
184 const octave_value& val,
185 bool do_check_access,
186 const std::string& who)
187{
188 if (do_check_access && ! check_set_access ())
189 err_property_access (who, true);
190
191 if (! obj.is_constructed ())
192 {
193 cdef_class cls (to_cdef (get ("DefiningClass")));
194
195 if (! obj.is_partially_constructed_for (cls))
196 error ("cannot reference properties of class '%s' for non-constructed object",
197 cls.get_name ().c_str ());
198 }
199
200 octave_value set_fcn = get ("SetMethod");
201
202 if (set_fcn.isempty () || is_method_executing (set_fcn, obj))
203 obj.put (get ("Name").string_value (), val);
204 else
205 {
207
208 args(0) = to_ov (obj);
209 args(1) = val;
210
211 interpreter& interp = __get_interpreter__ ();
212
213 if (obj.is_handle_object ())
214 interp.feval (set_fcn, args, 0);
215 else
216 {
217 args = interp.feval (set_fcn, args, 1);
218
219 if (args.length () > 0 && args(0).is_defined ())
220 {
221 if (args(0).is_classdef_object ())
222 {
223 cdef_object new_obj = to_cdef (args(0));
224
225 obj = new_obj;
226 }
227 else
228 ::warning ("set-method of property '%s' returned a non-classdef object",
229 get_name ().c_str ());
230 }
231 }
232 }
233}
234
235bool
236cdef_property::cdef_property_rep::check_get_access () const
237{
238 cdef_class cls (to_cdef (get ("DefiningClass")));
239
240 return check_access (cls, get ("GetAccess"), "", get_name (), false);
241
242 return false;
243}
244
245bool
246cdef_property::cdef_property_rep::check_set_access () const
247{
248 cdef_class cls (to_cdef (get ("DefiningClass")));
249
250 return check_access (cls, get ("SetAccess"), "", get_name (), true);
251
252 return false;
253}
254
255OCTAVE_END_NAMESPACE(octave)
bool check_access(const cdef_class &cls, const octave_value &acc, const std::string &meth_name, const std::string &prop_name, bool is_prop_set)
cdef_object to_cdef(const octave_value &val)
octave_value to_ov(const cdef_object &obj)
bool is_constructed() const
bool is_partially_constructed_for(const cdef_class &cls) const
bool is_handle_object() const
void put(const std::string &pname, const octave_value &val)
bool is(const cdef_object &obj) const
octave_value get(const std::string &pname) const
octave_value_list feval(const char *name, const octave_value_list &args=octave_value_list(), int nargout=0)
Evaluate an Octave function (built-in or interpreted) and return the list of result values.
virtual octave_user_function * user_function_value(bool silent=false)
Definition ov-base.cc:944
octave::tree_parameter_list * parameter_list()
Definition ov-usr-fcn.h:387
bool is_classdef_constructor(const std::string &cname="") const
Definition ov-usr-fcn.h:352
octave::tree_parameter_list * return_list()
Definition ov-usr-fcn.h:389
octave_idx_type length() const
Definition ovl.h:111
octave_function * function_value(bool silent=false) const
bool is_string() const
Definition ov.h:637
bool is_defined() const
Definition ov.h:592
bool isempty() const
Definition ov.h:601
std::string string_value(bool force=false) const
Definition ov.h:983
std::string type_name() const
Definition ov.h:1360
octave_value evaluate(tree_decl_elt *)
Definition pt-eval.cc:1871
octave_function * current_function(bool skip_first=false) const
Definition pt-eval.cc:2613
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void error(const char *fmt,...)
Definition error.cc:1003
tree_evaluator & __get_evaluator__()
interpreter & __get_interpreter__()