GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
cdef-class.h
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 (octave_cdef_class_h)
27 #define octave_cdef_class_h 1
28 
29 #include "octave-config.h"
30 
31 #include <map>
32 #include <set>
33 #include <string>
34 
35 #include "oct-refcount.h"
36 
37 #include "cdef-fwd.h"
38 #include "cdef-method.h"
39 #include "cdef-object.h"
40 #include "cdef-package.h"
41 #include "cdef-property.h"
42 #include "error.h"
43 #include "ov.h"
44 #include "ovl.h"
45 
47 
48 class interpreter;
49 class tree_classdef;
50 
51 class
52 OCTINTERP_API
54 {
55 private:
56 
57  class
58  cdef_class_rep : public cdef_meta_object_rep
59  {
60  public:
61  cdef_class_rep ()
62  : cdef_meta_object_rep (), m_member_count (0), m_handle_class (false),
63  m_meta (false)
64  { }
65 
66  OCTINTERP_API cdef_class_rep (const std::list<cdef_class>& superclasses);
67 
68  cdef_class_rep& operator = (const cdef_class_rep&) = delete;
69 
70  ~cdef_class_rep () = default;
71 
72  cdef_object_rep * copy () const { return new cdef_class_rep (*this); }
73 
74  bool is_class () const { return true; }
75 
76  std::string get_name () const
77  { return get ("Name").string_value (); }
78 
79  void set_name (const std::string& nm) { put ("Name", nm); }
80 
81  bool is_abstract () const { return get ("Abstract").bool_value (); }
82 
83  bool is_sealed () const { return get ("Sealed").bool_value (); }
84 
85  OCTINTERP_API cdef_method
86  find_method (const std::string& nm, bool local = false);
87 
88  OCTINTERP_API void
89  install_method (const cdef_method& meth);
90 
91  OCTINTERP_API Cell
92  get_methods (bool include_ctor);
93 
94  OCTINTERP_API std::map<std::string, cdef_method>
95  get_method_map (bool only_inherited, bool include_ctor);
96 
97  OCTINTERP_API cdef_property find_property (const std::string& nm);
98 
99  OCTINTERP_API void install_property (const cdef_property& prop);
100 
101  OCTINTERP_API Cell get_properties (int mode);
102 
103  OCTINTERP_API std::map<std::string, cdef_property>
104  get_property_map (int mode);
105 
106  OCTINTERP_API string_vector get_names ();
107 
108  void set_directory (const std::string& dir) { m_directory = dir; }
109 
110  std::string get_directory () const { return m_directory; }
111 
112  OCTINTERP_API void delete_object (const cdef_object& obj);
113 
114  OCTINTERP_API octave_value_list
115  meta_subsref (const std::string& type,
116  const std::list<octave_value_list>& idx, int nargout);
117 
118  OCTINTERP_API void meta_release ();
119 
120  bool meta_accepts_postfix_index (char type) const
121  {
122  return (type == '(' || type == '.');
123  }
124 
125  OCTINTERP_API octave_value get_method (const std::string& name) const;
126 
127  OCTINTERP_API octave_value get_method (int line) const;
128 
129  OCTINTERP_API octave_value construct (const octave_value_list& args);
130 
131  OCTINTERP_API cdef_object
132  construct_object (const octave_value_list& args);
133 
134  OCTINTERP_API void initialize_object (cdef_object& obj);
135 
136  OCTINTERP_API void
137  run_constructor (cdef_object& obj, const octave_value_list& args);
138 
139  void mark_as_handle_class () { m_handle_class = true; }
140 
141  bool is_handle_class () const { return m_handle_class; }
142 
143  octave_idx_type static_count () const { return m_member_count; }
144 
145  void destroy ()
146  {
147  if (m_member_count)
148  {
149  m_count++;
150  cdef_class lock (this);
151 
152  m_member_count = 0;
153  m_method_map.clear ();
154  m_property_map.clear ();
155  }
156  else
157  delete this;
158  }
159 
160  void mark_as_meta_class () { m_meta = true; }
161 
162  bool is_meta_class () const { return m_meta; }
163 
164  void file_name (const std::string& nm) { m_file_name = nm; }
165 
166  std::string file_name () const { return m_file_name; }
167 
168  private:
169 
170  OCTINTERP_API void load_all_methods ();
171 
172  OCTINTERP_API void find_names (std::set<std::string>& names, bool all);
173 
174  OCTINTERP_API void
175  find_properties (std::map<std::string, cdef_property>& props,
176  int mode = 0);
177 
178  OCTINTERP_API void
179  find_methods (std::map<std::string, cdef_method>& meths,
180  bool only_inherited, bool include_ctor = false);
181 
182  cdef_class wrap ()
183  {
184  m_count++;
185  return cdef_class (this);
186  }
187 
188  // The @-directory were this class is loaded from.
189  // (not used yet)
190 
191  std::string m_directory;
192 
193  std::string m_file_name;
194 
195  // The methods defined by this class.
196 
197  std::map<std::string, cdef_method> m_method_map;
198 
199  // The properties defined by this class.
200 
201  std::map<std::string, cdef_property> m_property_map;
202 
203  // The number of members in this class (methods, properties...)
204 
205  octave_idx_type m_member_count;
206 
207  // TRUE if this class is a handle class. A class is a handle
208  // class when the abstract "handle" class is one of its superclasses.
209 
210  bool m_handle_class;
211 
212  // The list of super-class constructors that are called implicitly by the
213  // classdef engine when creating an object. These constructors are not
214  // called explicitly by the class constructor.
215 
216  std::list<cdef_class> m_implicit_ctor_list;
217 
218  // TRUE if this class is a built-in meta class.
219 
220  bool m_meta;
221 
222  // Utility iterator typedefs.
223 
224  typedef std::map<std::string, cdef_method>::iterator method_iterator;
225  typedef std::map<std::string, cdef_method>::const_iterator method_const_iterator;
226  typedef std::map<std::string, cdef_property>::iterator property_iterator;
227  typedef std::map<std::string, cdef_property>::const_iterator property_const_iterator;
228 
229  cdef_class_rep (const cdef_class_rep& c) = default;
230  };
231 
232 public:
233 
234  // Create an invalid class object.
235 
237 
238  cdef_class (const std::string& nm,
239  const std::list<cdef_class>& superclasses)
240  : cdef_meta_object (new cdef_class_rep (superclasses))
241  {
242  get_rep ()->set_name (nm);
243  }
244 
245  cdef_class (const cdef_class& cls) : cdef_meta_object (cls) { }
246 
247  cdef_class (const cdef_object& obj)
248  : cdef_meta_object (obj)
249  {
250  // This should never happen...
251  if (! is_class ())
252  error ("internal error: invalid assignment from %s to meta.class object",
253  class_name ().c_str ());
254  }
255 
256  cdef_class& operator = (const cdef_class& cls)
257  {
259 
260  return *this;
261  }
262 
263  ~cdef_class () = default;
264 
265  OCTINTERP_API cdef_method
266  find_method (const std::string& nm, bool local = false);
267 
268  void install_method (const cdef_method& meth)
269  {
270  get_rep ()->install_method (meth);
271  }
272 
273  Cell get_methods (bool include_ctor = false)
274  {
275  return get_rep ()->get_methods (include_ctor);
276  }
277 
278  std::map<std::string, cdef_method>
279  get_method_map (bool only_inherited = false, bool include_ctor = false)
280  {
281  return get_rep ()->get_method_map (only_inherited, include_ctor);
282  }
283 
284  OCTINTERP_API cdef_property find_property (const std::string& nm);
285 
286  void install_property (const cdef_property& prop)
287  {
288  get_rep ()->install_property (prop);
289  }
290 
291  Cell get_properties (int mode = property_normal)
292  {
293  return get_rep ()->get_properties (mode);
294  }
295 
296  std::map<std::string, cdef_property>
297  get_property_map (int mode = property_normal)
298  {
299  return get_rep ()->get_property_map (mode);
300  }
301 
302  string_vector get_names () { return get_rep ()->get_names (); }
303 
304  bool is_abstract () const { return get_rep ()->is_abstract (); }
305 
306  bool is_sealed () const { return get_rep ()->is_sealed (); }
307 
308  void set_directory (const std::string& dir)
309  {
310  get_rep ()->set_directory (dir);
311  }
312 
313  std::string get_directory () const
314  {
315  return get_rep ()->get_directory ();
316  }
317 
318  std::string get_name () const { return get_rep ()->get_name (); }
319 
320  bool is_builtin () const { return get_directory ().empty (); }
321 
322  void delete_object (const cdef_object& obj)
323  {
324  get_rep ()->delete_object (obj);
325  }
326 
327  //! Analyze the tree_classdef tree and transform it to a cdef_class
328  //!
329  //! <b>All attribute validation should occur here.</b>
330  //!
331  //! Classdef attribute values can be given in the form of
332  //! expressions. These expressions must be evaluated before
333  //! assigning them as attribute values. Evaluating them as they are
334  //! parsed causes trouble with possible recursion in the parser so we
335  //! do it here. For example
336  //!
337  //! @code
338  //! classdef recursion_class
339  //! methods (Access = ?recursion_class)
340  //! endmethods
341  //! endclassdef
342  //! @endcode
343  //!
344  //! will fail because each attempt to compute the metaclass of
345  //! recursion_class will cause recursion_class to be parsed again.
346 
347  static OCTINTERP_API cdef_class
349  bool is_at_folder = false);
350 
351  octave_value get_method (const std::string& nm) const
352  {
353  return get_rep ()->get_method (nm);
354  }
355 
356  octave_value get_method (int ln) const
357  {
358  return get_rep ()->get_method (ln);
359  }
360 
361  OCTINTERP_API octave_value get_method_function (const std::string& nm);
362 
364  {
365  return get_method_function (get_name ());
366  }
367 
369  {
370  return get_rep ()->construct (args);
371  }
372 
374  {
375  return get_rep ()->construct_object (args);
376  }
377 
379  {
380  get_rep ()->initialize_object (obj);
381  }
382 
384  {
385  get_rep ()->run_constructor (obj, args);
386  }
387 
389  {
390  get_rep ()->mark_as_handle_class ();
391  }
392 
393  bool is_handle_class () const
394  {
395  return get_rep ()->is_handle_class ();
396  }
397 
398  void mark_as_meta_class () { get_rep ()->mark_as_meta_class (); }
399 
400  bool is_meta_class () const { return get_rep ()->is_meta_class (); }
401 
402  void file_name (const std::string& nm) { get_rep ()->file_name (nm); }
403 
404  std::string file_name () const { return get_rep ()->file_name (); }
405 
406 public:
407 
408  enum
409  {
412  property_all
413  };
414 
415 private:
416 
417  cdef_class_rep * get_rep ()
418  {
419  return dynamic_cast<cdef_class_rep *> (cdef_object::get_rep ());
420  }
421 
422  const cdef_class_rep * get_rep () const
423  {
424  return dynamic_cast<const cdef_class_rep *> (cdef_object::get_rep ());
425  }
426 
427  friend OCTINTERP_API bool operator == (const cdef_class&, const cdef_class&);
428  friend OCTINTERP_API bool operator != (const cdef_class&, const cdef_class&);
429  friend OCTINTERP_API bool operator < (const cdef_class&, const cdef_class&);
430 
431  friend void install_classdef (octave::interpreter& interp);
432 };
433 
434 inline bool
435 operator == (const cdef_class& clsa, const cdef_class& clsb)
436 {
437  // FIXME: is this really the right way to check class equality?
438 
439  return (clsa.get_rep () == clsb.get_rep ());
440 }
441 
442 inline bool
443 operator != (const cdef_class& clsa, const cdef_class& clsb)
444 {
445  return ! (clsa == clsb);
446 }
447 
448 // This is only to be able to use cdef_class as map keys.
449 
450 inline bool
451 operator < (const cdef_class& clsa, const cdef_class& clsb)
452 {
453  return clsa.get_rep () < clsb.get_rep ();
454 }
455 
456 inline cdef_method
457 cdef_class::find_method (const std::string& nm, bool local)
458 {
459  return get_rep ()->find_method (nm, local);
460 }
461 
462 inline cdef_property
463 cdef_class::find_property (const std::string& nm)
464 {
465  return get_rep ()->find_property (nm);
466 }
467 
468 OCTAVE_END_NAMESPACE(octave)
469 
470 #endif
bool operator==(const cdef_class &clsa, const cdef_class &clsb)
Definition: cdef-class.h:435
bool operator!=(const cdef_class &clsa, const cdef_class &clsb)
Definition: cdef-class.h:443
bool operator<(const cdef_class &clsa, const cdef_class &clsb)
Definition: cdef-class.h:451
Definition: Cell.h:43
cdef_method find_method(const std::string &nm, bool local=false)
Definition: cdef-class.h:457
void mark_as_meta_class()
Definition: cdef-class.h:398
octave_value construct(const octave_value_list &args)
Definition: cdef-class.h:368
void install_property(const cdef_property &prop)
Definition: cdef-class.h:286
cdef_class(const std::string &nm, const std::list< cdef_class > &superclasses)
Definition: cdef-class.h:238
void mark_as_handle_class()
Definition: cdef-class.h:388
void install_method(const cdef_method &meth)
Definition: cdef-class.h:268
bool is_abstract() const
Definition: cdef-class.h:304
void run_constructor(cdef_object &obj, const octave_value_list &args)
Definition: cdef-class.h:383
octave_value get_method(int ln) const
Definition: cdef-class.h:356
octave_value get_method(const std::string &nm) const
Definition: cdef-class.h:351
bool is_builtin() const
Definition: cdef-class.h:320
string_vector get_names()
Definition: cdef-class.h:302
std::map< std::string, cdef_property > get_property_map(int mode=property_normal)
Definition: cdef-class.h:297
std::map< std::string, cdef_method > get_method_map(bool only_inherited=false, bool include_ctor=false)
Definition: cdef-class.h:279
octave_value get_constructor_function()
Definition: cdef-class.h:363
std::string get_directory() const
Definition: cdef-class.h:313
cdef_class(const cdef_class &cls)
Definition: cdef-class.h:245
bool is_sealed() const
Definition: cdef-class.h:306
std::string get_name() const
Definition: cdef-class.h:318
void file_name(const std::string &nm)
Definition: cdef-class.h:402
std::string file_name() const
Definition: cdef-class.h:404
void initialize_object(cdef_object &obj)
Definition: cdef-class.h:378
void delete_object(const cdef_object &obj)
Definition: cdef-class.h:322
~cdef_class()=default
bool is_handle_class() const
Definition: cdef-class.h:393
bool is_meta_class() const
Definition: cdef-class.h:400
cdef_property find_property(const std::string &nm)
Definition: cdef-class.h:463
friend void install_classdef(octave::interpreter &interp)
Cell get_properties(int mode=property_normal)
Definition: cdef-class.h:291
@ property_inherited
Definition: cdef-class.h:411
@ property_normal
Definition: cdef-class.h:410
cdef_object construct_object(const octave_value_list &args)
Definition: cdef-class.h:373
cdef_class(const cdef_object &obj)
Definition: cdef-class.h:247
Cell get_methods(bool include_ctor=false)
Definition: cdef-class.h:273
void set_directory(const std::string &dir)
Definition: cdef-class.h:308
const cdef_object_rep * get_rep() const
Definition: cdef-object.h:310
cdef_object & operator=(const cdef_object &obj)
Definition: cdef-object.h:217
octave_value make_meta_class(interpreter &interp, bool is_at_folder=false)
Definition: pt-classdef.cc:314
std::string file_name() const
Definition: pt-classdef.h:723
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void() error(const char *fmt,...)
Definition: error.cc:988