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