26#if defined (HAVE_CONFIG_H)
57#define OCTAVE_CDEF_CLASS_DEBUG 0
58#if OCTAVE_CDEF_CLASS_DEBUG
65make_fcn_handle (
const octave_value& fcn,
const std::string& meth_name,
66 const std::string& class_name)
82cdef_class::cdef_class_rep::cdef_class_rep (
const std::list<cdef_class>& superclasses)
86 put (
"SuperClasses",
to_ov (superclasses));
87 m_implicit_ctor_list = superclasses;
91cdef_class::cdef_class_rep::find_method (
const std::string& nm,
bool local)
93 auto it = m_method_map.find (nm);
95 if (it == m_method_map.end ())
113 Cell super_classes = get (
"SuperClasses").cell_value ();
117 for (
int i = 0; i < super_classes.
numel (); i++)
132 error (
"method %s: conflicting definitions in classes '%s' and '%s'",
133 nm.c_str (), cls1.
get_name ().c_str (),
149 ctor_analyzer () =
delete;
151 ctor_analyzer (
const std::string& ctor,
const std::string& obj)
152 :
tree_walker (), m_who (ctor), m_obj_name (obj) { }
154 OCTAVE_DISABLE_COPY_MOVE (ctor_analyzer)
156 ~ctor_analyzer () =
default;
179 std::list<cdef_class> get_constructor_list ()
const
180 {
return m_ctor_list; }
228 m_ctor_list.push_back (cls);
238 std::string m_obj_name;
241 std::list<cdef_class> m_ctor_list;
245cdef_class::cdef_class_rep::install_method (
const cdef_method& meth)
247 std::string method_name = meth.
get_name ();
248 auto it = m_method_map.find (method_name);
251 if (it != m_method_map.end ())
253 std::string class_file = file_name ();
254 error (
"duplicate method '%s' in class '%s' in file '%s'",
255 method_name.c_str (), get_name ().c_str (), class_file.c_str ());
259 m_method_map[method_name] = meth;
279 if (! ret_list || ret_list->size () != 1)
280 error (
"%s: invalid constructor output arguments",
283 std::string m_obj_name = ret_list->front ()->name ();
284 ctor_analyzer a (meth.
get_name (), m_obj_name);
288 std::list<cdef_class> explicit_ctor_list
289 = a.get_constructor_list ();
291 for (
const auto& cdef_cls : explicit_ctor_list)
293#if OCTAVE_CDEF_CLASS_DEBUG
294 std::cerr <<
"explicit superclass constructor: "
295 << cdef_cls.get_name () << std::endl;
298 m_implicit_ctor_list.remove (cdef_cls);
306cdef_class::cdef_class_rep::load_all_methods ()
312cdef_class::cdef_class_rep::get_methods (
bool include_ctor)
314 std::map<std::string, cdef_method> meths;
316 find_methods (meths,
false, include_ctor);
318 Cell c (meths.size (), 1);
322 for (
const auto& nm_mthd : meths)
323 c(idx++, 0) =
to_ov (nm_mthd.second);
328std::map<std::string, cdef_method>
329cdef_class::cdef_class_rep::get_method_map (
bool only_inherited,
332 std::map<std::string, cdef_method> methods;
334 find_methods (methods, only_inherited, include_ctor);
340cdef_class::cdef_class_rep::find_methods (std::map<std::string,
347 for (
const auto& it : m_method_map)
349 if (include_ctor || ! it.second.is_constructor ())
351 std::string nm = it.second.get_name ();
353 if (meths.find (nm) == meths.end ())
364 meths[nm] = it.second;
371 Cell super_classes = get (
"SuperClasses").cell_value ();
373 for (
int i = 0; i < super_classes.
numel (); i++)
377 cls.get_rep ()->find_methods (meths,
true,
false);
382cdef_class::cdef_class_rep::find_property (
const std::string& nm)
384 auto it = m_property_map.find (nm);
386 if (it != m_property_map.end ())
396 Cell super_classes = get (
"SuperClasses").cell_value ();
400 for (
int i = 0; i < super_classes.
numel (); i++)
415 error (
"property %s: conflicting definitions in classes '%s' and '%s'",
416 nm.c_str (), cls1.
get_name ().c_str (),
428cdef_class::cdef_class_rep::install_property (
const cdef_property& prop)
430 std::string prop_name = prop.
get_name ();
431 auto it = m_property_map.find (prop_name);
434 if (it != m_property_map.end ())
436 std::string class_file = file_name ();
437 error (
"duplicate property '%s' in class '%s' in file '%s'",
438 prop_name.c_str (), get_name ().c_str (), class_file.c_str ());
441 m_property_map[prop_name] = prop;
444 m_property_rank_map[prop.
get_name ()] = m_member_count;
450cdef_class::cdef_class_rep::get_properties (
int mode)
452 std::map<property_key, cdef_property> props;
454 props = get_property_map (mode);
456 Cell c (props.size (), 1);
460 for (
const auto& pname_prop : props)
461 c(idx++, 0) =
to_ov (pname_prop.second);
466std::map<property_key, cdef_property>
467cdef_class::cdef_class_rep::get_property_map (
int mode)
469 std::map<property_key, cdef_property> props;
471 find_properties (props, mode);
477cdef_class::cdef_class_rep::find_properties
478 (std::map<property_key, cdef_property>& props,
int mode)
480 std::set<std::string> prop_names;
486 find_properties_aux (props, prop_names, mode);
490cdef_class::cdef_class_rep::find_properties_aux
491 (std::map<property_key, cdef_property>& props,
492 std::set<std::string>& prop_names,
int mode)
496 static unsigned int property_offset {0};
498 for (
const auto& it : m_property_map)
500 std::string nm = it.second.get_name ();
502 if (prop_names.find (nm) == prop_names.end ())
504 if (mode == property_inherited)
514 std::make_pair (property_offset + m_property_rank_map[nm], nm);
515 props[pk] = it.second;
516 prop_names.insert (nm);
520 property_offset += m_member_count;
524 Cell super_classes = get (
"SuperClasses").cell_value ();
526 for (
int i = 0; i < super_classes.
numel (); i++)
530 cls.get_rep ()->find_properties_aux (props, prop_names,
531 (mode == property_all
533 : property_inherited));
540cdef_class::cdef_class_rep::find_names (std::set<std::string>& names,
545 for (
const auto& cls_fnmap : m_method_map)
547 if (! cls_fnmap.second.is_constructor ())
549 std::string nm = cls_fnmap.second.get_name ();
564 for (
const auto& pname_prop : m_property_map)
566 std::string nm = pname_prop.second.get_name ();
582 Cell super_classes = get (
"SuperClasses").cell_value ();
584 for (
int i = 0; i < super_classes.
numel (); i++)
588 cls.get_rep ()->find_names (names, all);
593cdef_class::cdef_class_rep::get_names ()
595 std::set<std::string> names;
597 find_names (names,
false);
601 return v.sort (
true);
605cdef_class::cdef_class_rep::delete_object (
const cdef_object& obj)
619 Cell super_classes = get (
"SuperClasses").cell_value ();
621 for (
int i = 0; i < super_classes.
numel (); i++)
631cdef_class::cdef_class_rep::meta_subsref (
const std::string& type,
632 const std::list<octave_value_list>& idx,
635 std::size_t skip = 1;
644#if OCTAVE_CDEF_CLASS_DEBUG
645 std::cerr <<
"constructor" << std::endl;
648 retval(0) = construct (idx.front ());
655#if OCTAVE_CDEF_CLASS_DEBUG
656 std::cerr <<
"static method/property" << std::endl;
659 if (idx.front ().length () != 1)
660 error (
"invalid meta.class indexing");
662 std::string nm = idx.front ()(0).xstring_value (
"invalid meta.class indexing, expected a method or property name");
669 error (
"method '%s' is not static", nm.c_str ());
673 if (type.length () > 1 && idx.size () > 1 && type[1] ==
'(')
675 args = *(++(idx.begin ()));
679 retval = meth.
execute (args, (type.length () > skip
680 ? 1 : nargout),
true,
688 error (
"no such method or property '%s'", nm.c_str ());
691 error (
"property '%s' is not constant", nm.c_str ());
693 retval(0) = prop.
get_value (
true,
"meta.class");
699 error (
"invalid meta.class indexing");
703 if (type.length () > skip && idx.size () > skip && ! retval.
empty ())
704 retval = retval(0).next_subsref (nargout, type, idx, skip);
710cdef_class::cdef_class_rep::meta_release ()
718cdef_class::cdef_class_rep::initialize_object (
cdef_object& obj)
722 std::list<cdef_class> super_classes
725 for (
auto& cls : super_classes)
726 cls.initialize_object (obj);
728 for (
const auto& pname_prop : m_property_map)
730 if (! pname_prop.second.get (
"Dependent").bool_value ())
732 octave_value pvalue = pname_prop.second.get (
"DefaultValue");
735 obj.
put (pname_prop.first, pvalue);
746cdef_class::cdef_class_rep::run_constructor (
cdef_object& obj,
751 for (
const auto& cls : m_implicit_ctor_list)
758 std::string cls_name = get_name ();
769 ctor_retval = ctor.
execute (ctor_args, 1,
true,
"constructor");
771 if (ctor_retval.
length () != 1)
772 error (
"%s: invalid number of output arguments for classdef constructor",
775 obj =
to_cdef (ctor_retval(0));
782cdef_class::cdef_class_rep::get_method (
const std::string& name)
const
784 auto p = m_method_map.find (name);
786 if (p == m_method_map.end ())
789 return p->second.get_function ();
793cdef_class::cdef_class_rep::get_method (
int line)
const
796 int closest_match_end_line = std::numeric_limits<int>::max ();
800 for (
auto i = m_method_map.cbegin (); i != m_method_map.cend (); ++i)
814 octave::filepos end_pos = pfcn->
end_pos ();
816 int end_line = end_pos.line ();
818 if (line <= end_line && end_line <= closest_match_end_line
822 closest_match_end_line = end_line;
827 for (
auto i = m_property_map.cbegin (); i != m_property_map.cend (); ++i)
829 const octave_value& get_meth = i->second.get (
"GetMethod");
838 octave::filepos end_pos = pfcn->
end_pos ();
840 int end_line = end_pos.line ();
842 if (line <= end_line && end_line <= closest_match_end_line
845 closest_match = get_meth;
846 closest_match_end_line = end_line;
850 const octave_value& set_meth = i->second.get (
"SetMethod");
859 octave::filepos end_pos = pfcn->
end_pos ();
861 int end_line = end_pos.line ();
863 if (line <= end_line && end_line <= closest_match_end_line
866 closest_match = set_meth;
867 closest_match_end_line = end_line;
872 return closest_match;
877 const bool default_initialize)
879 cdef_object obj = construct_object (args, default_initialize);
889 const bool default_initialize)
892 error (
"cannot instantiate object for abstract class '%s'",
893 get_name ().c_str ());
897 if (is_meta_class ())
910 if (! empty_class.
ok ())
911 empty_class = cdm.
make_class (
"", std::list<cdef_class> ());
918 if (! empty_class.
ok ())
919 empty_class = cdm.
make_class (
"", std::list<cdef_class> ());
920 if (! empty_property.
ok ())
922 obj = empty_property;
928 if (! empty_class.
ok ())
929 empty_class = cdm.
make_class (
"", std::list<cdef_class> ());
930 if (! empty_method.
ok ())
938 if (! empty_package.
ok ())
943 error (
"expecting meta class, property, method, or package in cdef_class::cdef_class_rep::construct_object - please report this bug");
949 if (is_handle_class ())
955 initialize_object (obj);
957 if (! default_initialize)
958 run_constructor (obj, args);
976 std::string s = expr->
name ();
979 return std::string (
"public");
980 else if (s ==
"protected")
981 return std::string (
"protected");
982 else if (s ==
"private")
983 return std::string (
"private");
998 else if (t->expression ())
999 return t->expression ()->original_text ();
1015 full_class_name = t->
package_name () +
'.' + full_class_name;
1017#if OCTAVE_CDEF_CLASS_DEBUG
1018 std::cerr <<
"class: " << full_class_name << std::endl;
1031 std::list<cdef_class> slist;
1037 std::string sclass_name = (scls)->
class_name ();
1039#if OCTAVE_CDEF_CLASS_DEBUG
1040 std::cerr <<
"superclass: " << sclass_name << std::endl;
1046 error (
"'%s' cannot inherit from '%s', because it is sealed",
1047 full_class_name.c_str (), sclass_name.c_str ());
1049 slist.push_back (sclass);
1055 retval = cdm.
make_class (full_class_name, slist);
1067 retval.
put (
"ContainingPackage",
to_ov (pack));
1081 std::string aname = attr->ident ()->name ();
1082 octave_value avalue = compute_attribute_value (tw, attr);
1084#if OCTAVE_CDEF_CLASS_DEBUG
1085 std::cerr <<
"class attribute: " << aname <<
" = "
1086 << attribute_value_to_string (attr, avalue) << std::endl;
1089 retval.
put (aname, avalue);
1101 std::map<std::string, octave_value> set_methods;
1105 std::list<tree_classdef_methods_block *> mb_list = b->
method_list ();
1109 for (
auto& mb_p : mb_list)
1111 std::map<std::string, octave_value> amap;
1113#if OCTAVE_CDEF_CLASS_DEBUG
1114 std::cerr <<
"method block" << std::endl;
1119 if (mb_p->attribute_list ())
1121 for (
auto& attr_p : *mb_p->attribute_list ())
1123 std::string aname = attr_p->ident ()->name ();
1124 octave_value avalue = compute_attribute_value (tw, attr_p);
1126#if OCTAVE_CDEF_CLASS_DEBUG
1127 std::cerr <<
"method attribute: " << aname <<
" = "
1128 << attribute_value_to_string (attr_p, avalue)
1132 amap[aname] = avalue;
1138 if (mb_p->element_list ())
1140 for (
auto& mtd : *mb_p->element_list ())
1143 std::string mprefix = mname.substr (0, 4);
1145 if (mprefix ==
"get.")
1147 = make_fcn_handle (mtd, mname, full_class_name);
1148 else if (mprefix ==
"set.")
1149 set_methods[mname.substr (4)]
1150 = make_fcn_handle (mtd, mname, full_class_name);
1155#if OCTAVE_CDEF_CLASS_DEBUG
1156 std::cerr << (mname ==
class_name ?
"constructor"
1158 <<
": " << mname << std::endl;
1168 for (
auto& attrnm_val : amap)
1169 meth.
put (attrnm_val.first, attrnm_val.second);
1186 std::list<std::string> external_methods
1187 = lp.
methods (full_class_name);
1189 for (
const auto& mtdnm : external_methods)
1218 std::list<tree_classdef_properties_block *> pb_list
1221 for (
auto& pb_p : pb_list)
1223 std::map<std::string, octave_value> amap;
1225#if OCTAVE_CDEF_CLASS_DEBUG
1226 std::cerr <<
"property block" << std::endl;
1231 if (pb_p->attribute_list ())
1233 for (
auto& attr_p : *pb_p->attribute_list ())
1235 std::string aname = attr_p->ident ()->name ();
1236 octave_value avalue = compute_attribute_value (tw, attr_p);
1238#if OCTAVE_CDEF_CLASS_DEBUG
1239 std::cerr <<
"property attribute: " << aname <<
" = "
1240 << attribute_value_to_string (attr_p, avalue)
1244 if (aname ==
"Access")
1246 amap[
"GetAccess"] = avalue;
1247 amap[
"SetAccess"] = avalue;
1250 amap[aname] = avalue;
1256 if (pb_p->element_list ())
1258 for (
auto& prop_p : *pb_p->element_list ())
1260 std::string prop_name = prop_p->ident ()->name ();
1266#if OCTAVE_CDEF_CLASS_DEBUG
1267 std::cerr <<
"property: " << prop_p->ident ()->name ()
1276#if OCTAVE_CDEF_CLASS_DEBUG
1277 std::cerr <<
"property default: "
1278 << attribute_value_to_string (prop_p, pvalue)
1282 prop.
put (
"DefaultValue", pvalue);
1295 for (
auto& attrnm_val : amap)
1296 prop.
put (attrnm_val.first, attrnm_val.second);
1308 prop.
put (
"GetMethod", git->second);
1312 auto sit = set_methods.
find (prop_name);
1314 if (sit != set_methods.end ())
1317 prop.
put (
"SetMethod", sit->second);
1318 set_methods.erase (sit);
1336OCTAVE_END_NAMESPACE(octave)
std::pair< unsigned int, std::string > property_key
cdef_object to_cdef(const octave_value &val)
cdef_class lookup_class(const std::string &name, bool error_if_not_found, bool load_if_not_found)
std::string get_base_name(const std::string &nm)
octave_value to_ov(const cdef_object &obj)
void make_function_of_class(const std::string &class_name, const octave_value &fcn)
std::list< cdef_class > lookup_classes(const Cell &cls_list)
Array< octave_idx_type > find(octave_idx_type n=-1, bool backward=false) const
Find indices of (at most n) nonzero elements.
octave_idx_type numel() const
Number of elements in the array.
cdef_method find_method(const std::string &nm, bool local=false)
void install_property(const cdef_property &prop)
void install_method(const cdef_method &meth)
void run_constructor(cdef_object &obj, const octave_value_list &args)
std::string get_name() const
void file_name(const std::string &nm)
void delete_object(const cdef_object &obj)
octave_value get_method_function(const std::string &nm)
cdef_property find_property(const std::string &nm)
Cell get_methods(bool include_ctor=false)
static cdef_class make_meta_class(interpreter &interp, tree_classdef *t, bool is_at_folder=false)
Analyze the tree_classdef tree and transform it to a cdef_class.
cdef_class make_class(const std::string &name, const std::list< cdef_class > &super_list=std::list< cdef_class >())
cdef_property make_property(const cdef_class &cls, const std::string &name, const octave_value &get_method=Matrix(), const std::string &get_access="public", const octave_value &set_method=Matrix(), const std::string &set_access="public")
const cdef_class & meta_package() const
cdef_package make_package(const std::string &nm, const std::string &parent="")
const cdef_class & meta_property() const
cdef_package find_package(const std::string &name, bool error_if_not_found=true, bool load_if_not_found=true)
const cdef_class & meta_method() const
void unregister_class(const cdef_class &cls)
const cdef_class & meta_class() const
cdef_method make_method(const cdef_class &cls, const std::string &name, const octave_value &fcn, const std::string &m_access="public", bool is_static=false)
bool is_constructor() const
octave_value_list execute(const octave_value_list &args, int nargout, bool do_check_access=true, const std::string &who="")
bool is_defined_in_class(const std::string &cname) const
octave_value get_function() const
std::string get_name() const
void mark_for_construction(const cdef_class &cls)
void put(const std::string &pname, const octave_value &val)
void mark_as_constructed()
void set_class(const cdef_class &cls)
std::string class_name() const
octave_value get(const std::string &pname) const
std::string get_name() const
octave_value get_value(const cdef_object &obj, bool do_check_access=true, const std::string &who="") const
load_path & get_load_path()
tree_evaluator & get_evaluator()
std::list< std::string > methods(const std::string &class_name, const std::string &pack_name="")
octave::filepos end_pos() const
bool is_user_code() const
octave::tree_statement_list * body()
void stash_function_name(const std::string &s)
octave::tree_parameter_list * return_list()
octave_idx_type length() const
octave_value_list & prepend(const octave_value &val)
bool is_function_handle() const
bool bool_value(bool warn=false) const
octave_function * function_value(bool silent=false) const
std::string string_value(bool force=false) const
octave_user_function * user_function_value(bool silent=false) const
octave_user_code * user_code_value(bool silent=false) const
tree_expression * expression()
std::list< tree_classdef_properties_block * > property_list()
std::list< tree_classdef_methods_block * > method_list()
std::string package_name() const
tree_classdef_body * body()
tree_identifier * ident()
tree_classdef_superclass_list * superclass_list()
tree_classdef_attribute_list * attribute_list()
std::string doc_string() const
std::string file_name() const
void push_dummy_scope(const std::string &name)
virtual octave_value evaluate(tree_evaluator &tw, int nargout=1)=0
virtual bool is_identifier() const
virtual std::string name() const
tree_expression * expression()
tree_expression * right_hand_side()
tree_expression * right_hand_side()
void accept(tree_walker &tw)
tree_expression * expression()
bool is_expression() const
std::string method_name() const
std::string class_name() const
virtual void visit_unwind_protect_command(tree_unwind_protect_command &)
virtual void visit_try_catch_command(tree_try_catch_command &)
virtual void visit_if_command_list(tree_if_command_list &)
virtual void visit_multi_assignment(tree_multi_assignment &)
virtual void visit_return_command(tree_return_command &)
virtual void visit_continue_command(tree_continue_command &)
virtual void visit_switch_case_list(tree_switch_case_list &)
virtual void visit_complex_for_command(tree_complex_for_command &)
virtual void visit_break_command(tree_break_command &)
virtual void visit_matrix(tree_matrix &)
virtual void visit_fcn_handle(tree_fcn_handle &)
virtual void visit_colon_expression(tree_colon_expression &)
virtual void visit_do_until_command(tree_do_until_command &)
virtual void visit_no_op_command(tree_no_op_command &)
virtual void visit_binary_expression(tree_binary_expression &)
virtual void visit_simple_for_command(tree_simple_for_command &)
virtual void visit_postfix_expression(tree_postfix_expression &)
virtual void visit_prefix_expression(tree_prefix_expression &)
virtual void visit_anon_fcn_handle(tree_anon_fcn_handle &)
virtual void visit_parameter_list(tree_parameter_list &)
virtual void visit_statement(tree_statement &)
virtual void visit_index_expression(tree_index_expression &)
virtual void visit_decl_command(tree_decl_command &)
virtual void visit_switch_case(tree_switch_case &)
virtual void visit_cell(tree_cell &)
virtual void visit_identifier(tree_identifier &)
virtual void visit_decl_init_list(tree_decl_init_list &)
virtual void visit_if_clause(tree_if_clause &)
virtual void visit_if_command(tree_if_command &)
virtual void visit_argument_list(tree_argument_list &)
virtual void visit_decl_elt(tree_decl_elt &)
virtual void visit_constant(tree_constant &)
virtual void visit_simple_assignment(tree_simple_assignment &)
virtual void visit_superclass_ref(tree_superclass_ref &)
virtual void visit_octave_user_script(octave_user_script &)
virtual void visit_octave_user_function(octave_user_function &)
virtual void visit_function_def(tree_function_def &)
virtual void visit_while_command(tree_while_command &)
virtual void visit_switch_command(tree_switch_command &)
virtual void accept(tree_walker &tw)=0
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void error(const char *fmt,...)
cdef_manager & __get_cdef_manager__()