GNU Octave  6.2.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-2021 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 
53 namespace 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  {
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  {
132  octave_value_list args;
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  {
205  octave_value_list args;
206 
207  args(0) = to_ov (obj);
208  args(1) = val;
209 
210  args = feval (set_fcn, args, 1);
211 
212  if (args.length () > 0 && args(0).is_defined ())
213  {
214  if (args (0).is_classdef_object ())
215  {
216  cdef_object new_obj = to_cdef (args(0));
217 
218  obj = new_obj;
219  }
220  else
221  ::warning ("set-method of property '%s' returned a non-classdef object",
222  get_name ().c_str ());
223  }
224  }
225  }
226 
227  bool
229  {
230  cdef_class cls (to_cdef (get ("DefiningClass")));
231 
232  return check_access (cls, get ("GetAccess"), "", get_name (), false);
233 
234  return false;
235  }
236 
237  bool
239  {
240  cdef_class cls (to_cdef (get ("DefiningClass")));
241 
242  return check_access (cls, get ("SetAccess"), "", get_name (), true);
243 
244  return false;
245  }
246 }
elt_type & front(void)
Definition: base-list.h:79
size_t size(void) const
Definition: base-list.h:52
std::string get_name(void) const
Definition: cdef-class.h:304
octave_value get(const std::string &pname) const
Definition: cdef-object.h:463
bool is(const cdef_object &obj) const
Definition: cdef-object.h:324
bool is_constructed(void) const
Definition: cdef-object.h:307
void put(const std::string &pname, const octave_value &val)
Definition: cdef-object.h:256
bool is_partially_constructed_for(const cdef_class &cls) const
Definition: cdef-object.h:314
octave_value get(const std::string &pname) const
Definition: cdef-object.h:261
OCTAVE_NORETURN void err_property_access(const std::string &from, bool is_set=false) const
void set_value(cdef_object &obj, const octave_value &val, bool do_check_access=true, const std::string &who="")
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
octave_value evaluate(tree_decl_elt *)
Definition: pt-eval.cc:1245
octave_function * current_function(bool skip_first=false) const
Definition: pt-eval.cc:1907
virtual octave_user_function * user_function_value(bool silent=false)
Definition: ov-base.cc:882
octave::tree_parameter_list * return_list(void)
Definition: ov-usr-fcn.h:396
bool is_classdef_constructor(const std::string &cname="") const
Definition: ov-usr-fcn.h:359
octave::tree_parameter_list * parameter_list(void)
Definition: ov-usr-fcn.h:394
octave_idx_type length(void) const
Definition: ovl.h:113
bool is_string(void) const
Definition: ov.h:593
bool is_defined(void) const
Definition: ov.h:551
octave_function * function_value(bool silent=false) const
std::string string_value(bool force=false) const
Definition: ov.h:927
bool isempty(void) const
Definition: ov.h:557
std::string type_name(void) const
Definition: ov.h:1254
void warning(const char *fmt,...)
Definition: error.cc:1050
void error(const char *fmt,...)
Definition: error.cc:968
static bool is_method_executing(const octave_value &ov, const cdef_object &obj)
octave_value to_ov(const cdef_object &obj)
Definition: cdef-utils.cc:128
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)
octave_value_list feval(const char *name, const octave_value_list &args, int nargout)
Evaluate an Octave function (built-in or interpreted) and return the list of result values.
Definition: oct-parse.cc:9580
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811