GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
cdef-method.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2012-2024 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-idx.h"
48 #include "pt-misc.h"
49 #include "pt-stmt.h"
50 #include "pt-walk.h"
51 
53 
54 OCTAVE_NORETURN static
55 void
56 err_method_access (const std::string& from, const cdef_method& meth)
57 {
58  octave_value acc = meth.get ("Access");
59  std::string acc_s;
60 
61  if (acc.is_string ())
62  acc_s = acc.string_value ();
63  else
64  acc_s = "class-restricted";
65 
66  error ("%s: method '%s' has %s access and cannot be run in this context",
67  from.c_str (), meth.get_name ().c_str (), acc_s.c_str ());
68 }
69 
70 void
71 cdef_method::cdef_method_rep::check_method ()
72 {
73  if (is_external ())
74  {
75  if (is_dummy_method (m_function))
76  {
78 
79  std::string name = get_name ();
80  std::string cls_name = m_dispatch_type;
81  std::string pack_name;
82 
83  std::size_t pos = cls_name.rfind ('.');
84 
85  if (pos != std::string::npos)
86  {
87  pack_name = cls_name.substr (0, pos);
88  cls_name = cls_name.substr (pos + 1);
89  }
90 
91  std::string dir_name;
92  std::string file_name = lp.find_method (cls_name, name,
93  dir_name, pack_name);
94 
95  if (! file_name.empty ())
96  {
97  octave_value ov_fcn
98  = load_fcn_from_file (file_name, dir_name,
99  m_dispatch_type, pack_name);
100 
101  if (ov_fcn.is_defined ())
102  {
103  m_function = ov_fcn;
104 
105  make_function_of_class (m_dispatch_type, m_function);
106  }
107  }
108  }
109  else
110  {
111  // FIXME: check out-of-date status
112  }
113 
114  if (is_dummy_method (m_function))
115  error ("no definition found for method '%s' of class '%s'",
116  get_name ().c_str (), m_dispatch_type.c_str ());
117  }
118 }
119 
121 cdef_method::cdef_method_rep::execute (const octave_value_list& args,
122  int nargout, bool do_check_access,
123  const std::string& who)
124 {
125  octave_value_list retval;
126 
127  if (do_check_access && ! check_access ())
128  err_method_access (who, wrap ());
129 
130  if (get ("Abstract").bool_value ())
131  error ("%s: cannot execute abstract method",
132  get ("Name").string_value ().c_str ());
133 
134  check_method ();
135 
136  if (m_function.is_defined ())
137  {
138  interpreter& interp = __get_interpreter__ ();
139 
140  retval = interp.feval (m_function, args, nargout);
141  }
142 
143  return retval;
144 }
145 
147 cdef_method::cdef_method_rep::execute (const cdef_object& obj,
148  const octave_value_list& args,
149  int nargout, bool do_check_access,
150  const std::string& who)
151 {
152  octave_value_list retval;
153 
154  if (do_check_access && ! check_access ())
155  err_method_access (who, wrap ());
156 
157  if (get ("Abstract").bool_value ())
158  error ("%s: cannot execute abstract method",
159  get ("Name").string_value ().c_str ());
160 
161  check_method ();
162 
163  if (m_function.is_defined ())
164  {
165  octave_value_list new_args;
166 
167  new_args.resize (args.length () + 1);
168 
169  new_args(0) = to_ov (obj);
170  for (int i = 0; i < args.length (); i++)
171  new_args(i+1) = args(i);
172 
173  interpreter& interp = __get_interpreter__ ();
174 
175  retval = interp.feval (m_function, new_args, nargout);
176  }
177 
178  return retval;
179 }
180 
181 bool
182 cdef_method::cdef_method_rep::is_constructor () const
183 {
184  if (m_function.is_function())
185  return m_function.function_value ()->is_classdef_constructor ();
186 
187  return false;
188 }
189 
190 bool
191 cdef_method::cdef_method_rep::is_defined_in_class (const std::string& cname) const
192 {
193  return (m_function.is_function ()
194  ? m_function.function_value ()->dispatch_class () == cname
195  : false);
196 }
197 
198 std::string
199 cdef_method::cdef_method_rep::get_doc_string ()
200 {
201  check_method ();
202 
203  octave_function *fcn = m_function.function_value ();
204 
205  return fcn ? fcn->doc_string () : "";
206 }
207 
208 bool
210 {
211  cdef_class cls (to_cdef (get ("DefiningClass")));
212 
213  return octave::check_access (cls, get ("Access"), get_name ());
214 }
215 
217 cdef_method::cdef_method_rep::meta_subsref
218 (const std::string& type, const std::list<octave_value_list>& idx,
219  int nargout)
220 {
221  octave_value_list retval;
222 
223  switch (type[0])
224  {
225  case '(':
226  retval = (execute (idx.front (),
227  type.length () > 1 ? 1 : nargout, true));
228  break;
229 
230  default:
231  error ("invalid meta.method indexing");
232  break;
233  }
234 
235  if (type.length () > 1 && idx.size () > 1 && ! retval.empty ())
236  retval = retval(0).next_subsref (nargout, type, idx, 1);
237 
238  return retval;
239 }
240 
241 OCTAVE_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)
Definition: cdef-utils.cc:294
bool is_dummy_method(const octave_value &fcn)
Definition: cdef-utils.cc:179
cdef_object to_cdef(const octave_value &val)
Definition: cdef-utils.cc:143
octave_value to_ov(const cdef_object &obj)
Definition: cdef-utils.cc:128
void make_function_of_class(const std::string &class_name, const octave_value &fcn)
Definition: cdef-utils.cc:55
std::string get_name() const
Definition: cdef-method.h:182
octave_value get(const std::string &pname) const
Definition: cdef-object.h:268
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.
std::string find_method(const std::string &class_name, const std::string &meth, std::string &dir_name, const std::string &pack_name="")
Definition: load-path.h:77
virtual octave_function * function_value(bool silent=false)
Definition: ov-base.cc:940
virtual std::string doc_string(const std::string &="") const
Definition: ov-fcn.h:219
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
Definition: ovl.h:117
bool empty() const
Definition: ovl.h:115
octave_idx_type length() const
Definition: ovl.h:113
bool is_string() const
Definition: ov.h:637
bool is_defined() const
Definition: ov.h:592
std::string string_value(bool force=false) const
Definition: ov.h:974
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void() error(const char *fmt,...)
Definition: error.cc:988
interpreter & __get_interpreter__()
load_path & __get_load_path__()
octave_value load_fcn_from_file(const std::string &file_name, const std::string &dir_name="", const std::string &dispatch_type="", const std::string &package_name="", const std::string &fcn_name="", bool autoload=false)