# HG changeset patch # User Michael Goffioul # Date 1357492756 18000 # Node ID b8bff84022d6ae102ac60dfc262ccf9357f3bdfe # Parent a413c6fe1726bcdac03cc71ec2e8558c3bd4da04 Use strong reference between objects and their class. * libinterp/octave-value/ov-classdef.h (cdef_object_rep::cname): Remove member. (cdef_object_rep::cdef_object_rep (void), cdef_object_rep::cdef_object_rep (cdef_object_rep)): Do not initialize it. (cdef_object_rep::cdef_object_rep (std::string)): Remove constructor. (cdef_object_rep::set_class_name): Remove method. (cdef_object_rep::grip_invalid_object): New private method. (cdef_object_rep::set_class, cdef_object_rep::is_class, cdef_object_rep::is_property, cdef_object_rep::is_method, cdef_object_rep::is_package): New methods. (cdef_object_rep::map, cdef_object_rep::ctor_list): Move members to cdef_object_scalar. (cdef_object_rep::put, cdef_object_rep::get, cdef_object_rep::subsref, cdef_object_rep::subsasgn, cdef_object_rep::mark_for_construction, cdef_object_rep::is_constructed_for, cdef_object_rep::mark_as_constructed, cdef_object_rep::is_partially_constructed_for, cdef_object_rep::is_constructed): Move implementation to cdef_object_scalar. (cdef_object_rep::is_constructed_for, cdef_object_rep::mark_as_constructed, cdef_object_rep::is_partially_constructed_for): Change signature, use cdef_class argument instead of std::string. (cdef_object_rep::class_name): Use get_class () and move inline definition after cdef_class declaration. (cdef_object::set_class_name): Remove method. (cdef_object::is_class, cdef_object::is_property, cdef_object::is_method, cdef_object::is_package): New methods. (cdef_object::is_constructed_for, cdef_object::mark_as_constructed, cdef_object::is_partially_constructed_for): Change signature, use cdef_class instead of std::string. (class cdef_object_base, class cdef_object_scalar): New classes. (class handle_cdef_object, class value_cdef_object): Inherits from cdef_object_scalar. (handle_cdef_object::handle_cdef_object (std::string)): Remove constructor. (value_cdef_object::value_cdef_object (std::string)): Likewise. (value_cdef_object::value_cdef_object (value_cdef_object)): Implement copy constructor. (value_cdef_object::clone): Use it. (cdef_class::cdef_class_rep::cdef_class_rep): Remove first string argument. (cdef_class::cdef_class_rep::is_class, cdef_class::cdef_class_rep::set_name, cdef_class::cdef_class_rep::wrap): New methods. (cdef_class::cdef_class_rep::implicit_ctor_list): Change type to std::list. (cdef_class::cdef_class (std::string): Remove constructor. (cdef_class::cdef_class (std::list)): Use string argument as the class name. (cdef_class::cdef_class (cdef_object), cdef_class::operator= (cdef_object)): Use is_class method. (cdef_class::_meta_class, cdef_class::_meta_property, cdef_class::_meta_method, cdef_class::_meta_package): New static members. (cdef_class::meta_class, cdef_class::meta_property, cdef_class::meta_method, cdef_class::meta_package): New static methods. (operator< (cdef_cass, cdef_class)): New function. (cdef_property::cdef_property_rep::cdef_property_rep): Remove first argument string. (cdef_property::cdef_property_rep::is_property, cdef_property::cdef_property_rep::get_name, cdef_property::cdef_property_rep::set_name, cdef_property::cdef_property_rep::is_constant): New methods. (cdef_property::get_name, cdef_property::is_constant): Use them. (cdef_property::cdef_property (std::string)): Use string argument as property name. (cdef_property::cdef_property (cdef_object)): Use is_property method. (cdef_method::cdef_method_rep::cdef_method_rep): Remove first argument string. (cdef_method::cdef_method_rep::is_method, cdef_method::cdef_method_rep::get_name, cdef_method::cdef_method_rep::set_name, cdef_method::cdef_method_rep::is_static): New methods. (cdef_method::get_name, cdef_method::is_static): Use them. (cdef_method::cdef_method (std::string)): Use string argument as method name. (cdef_method::cdef_method (cdef_object)): Use is_method method. (cdef_package::cdef_package_rep::cdef_package_rep): Remove first argument string. (cdef_package::cdef_package_rep::is_package, cdef_package::cdef_package_rep::get_name, cdef_package::cdef_package_rep::set_name): New methods. (cdef_package::get_name): Likewise. (cdef_package::cdef_package (std::string)): Use string argument as package name. (cdef_package::cdef_package (cdef_object)): Use is_package method. (cdef_package::_meta): New static member. (cdef_package::meta): New static method. * libinterp/octave-value/ov-classdef.cc (lookup_class (cdef_class), lookup_class (octave_value)): New static function overloads. (lookup_classes): Change argument name to reflect the fact we're using now a list of cdef_class objects, not a list of names. (make_class, make_property, make_method, make_package): Use name as constructor argument. Set object class. (cdef_object_rep::get_class): Move implementation to header. (cdef_object_rep::subsref, cdef_object_rep::subsasgn, cdef_object_rep::mark_for_construction): Move implementation to cdef_object_scalar. (cdef_object_scalar::is_constructed_for, cdef_object_scalar::is_partially_constructed_for): Moved from cdef_object_rep. (handle_cdef_object::~handle_cdef_object, value_cdef_object::~value_cdef_object): Do not use cname. (cdef_class::cdef_class_rep::cdef_class_rep (std::list)): Remove first string argument. Keep strong references to cdef_class superclass objects. (cdef_class::cdef_class_rep::find_method, cdef_class::cdef_class_rep::find_methods, cdef_class::cdef_class_rep::find_property, cdef_class::cdef_class_rep::find_properties, cdef_class::cdef_class_rep::find_names, cdef_class::cdef_class_rep::delete_object): Superclasses are now strong references for cdef_class objects. (ctor_analyzer::available_ctor_list): Remove member. (ctor_analyzer::ctor_analyzer): Do not use it. (ctor_analyzer::ctor_list): Change type to std::list. (ctor_analyzer::visit_funcall): Use it. Do not produce any error. (cdef_class::cdef_class_rep::install_method): Use strong references to cdef_class superclass objects. (cdef_class::cdef_class_rep::run_constructor): Likewise. (cdef_class::cdef_class_rep::construct): Use strong reference to cdef_class object. (cdef_property::cdef_property_rep::get_value, cdef_property::cdef_property_rep::set_value): Likewise. (cdef_class::_meta_class, cdef_class::_meta_property, cdef_class::_meta_method, cdef_class::_meta_package): Initialize static members. (cdef_package::_meta): Likewise. (install_classdef): Bootstrap meta classes with strong references to cdef_class. Assign cdef_class and cdef_package static members. diff -r a413c6fe1726 -r b8bff84022d6 libinterp/octave-value/ov-classdef.cc --- a/libinterp/octave-value/ov-classdef.cc Fri Jan 04 14:29:13 2013 -0500 +++ b/libinterp/octave-value/ov-classdef.cc Sun Jan 06 12:19:16 2013 -0500 @@ -179,14 +179,39 @@ return cdef_class (); } +static cdef_class +lookup_class (const cdef_class& cls) +{ + // FIXME: placeholder for the time being, the purpose + // is to centralized any class update activity here. + + return cls; +} + +static cdef_class +lookup_class (const octave_value& ov) +{ + if (ov.is_string()) + return lookup_class (ov.string_value ()); + else + { + cdef_class cls (to_cdef (ov)); + + if (! error_state) + return lookup_class (cls); + } + + return cdef_class (); +} + static std::list -lookup_classes (const Cell& cls_names) +lookup_classes (const Cell& cls_list) { std::list retval; - for (int i = 0; i < cls_names.numel (); i++) + for (int i = 0; i < cls_list.numel (); i++) { - cdef_class c = lookup_class (cls_names(i).string_value ()); + cdef_class c = lookup_class (cls_list(i)); if (! error_state) retval.push_back (c); @@ -227,7 +252,7 @@ for (int i = 0; ! error_state && ! retval && i < c.numel (); i++) { - cdef_class cls = lookup_class (c(i).string_value ()); + cdef_class cls = lookup_class (c(i)); if (! error_state) retval = is_superclass (clsa, cls, true, @@ -583,8 +608,9 @@ make_class (const std::string& name, const std::list& super_list = std::list ()) { - cdef_class cls ("meta.class", super_list); - + cdef_class cls (name, super_list); + + cls.set_class (cdef_class::meta_class ()); cls.put ("ConstructOnLoad", false); cls.put ("ContainingPackage", Matrix ()); cls.put ("Description", std::string ()); @@ -593,7 +619,6 @@ cls.put ("Hidden", false); cls.put ("InferiorClasses", Cell ()); cls.put ("Methods", Cell ()); - cls.put ("Name", name); cls.put ("Properties", Cell ()); cls.put ("Sealed", false); @@ -652,9 +677,9 @@ { // FIXME: what about default value? - cdef_property prop ("meta.property"); - - prop.put ("Name", name); + cdef_property prop (name); + + prop.set_class (cdef_class::meta_property ()); prop.put ("Description", std::string ()); prop.put ("DetailedDescription", std::string ()); prop.put ("Abstract", false); @@ -693,15 +718,15 @@ const octave_value& fcn,const std::string& m_access = "public", bool is_static = false) { - cdef_method meth ("meta.method"); - + cdef_method meth (name); + + meth.set_class (cdef_class::meta_method ()); meth.put ("Abstract", false); meth.put ("Access", m_access); meth.put ("DefiningClass", to_ov (cls)); meth.put ("Description", std::string ()); meth.put ("DetailedDescription", std::string ()); meth.put ("Hidden", false); - meth.put ("Name", name); meth.put ("Sealed", true); meth.put ("Static", is_static); @@ -728,10 +753,12 @@ { cdef_package pack ("meta.package"); - all_packages[nm] = pack; + pack.set_class (cdef_class::meta_package ()); pack.put ("Name", nm); pack.put ("ContainingPackage", to_ov (all_packages[parent])); + all_packages[nm] = pack; + return pack; } @@ -981,14 +1008,6 @@ //---------------------------------------------------------------------------- -cdef_class -cdef_object_rep::get_class (void) const -{ - cdef_class cls = lookup_class (class_name ()); - - return cls; -} - string_vector cdef_object_rep::map_keys (void) const { @@ -1001,10 +1020,10 @@ } octave_value_list -cdef_object_rep::subsref (const std::string& type, - const std::list& idx, - int nargout, size_t& skip, - const cdef_class& context) +cdef_object_scalar::subsref (const std::string& type, + const std::list& idx, + int nargout, size_t& skip, + const cdef_class& context) { skip = 0; @@ -1084,9 +1103,9 @@ } octave_value -cdef_object_rep::subsasgn (const std::string& type, - const std::list& idx, - const octave_value& rhs) +cdef_object_scalar::subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs) { octave_value retval; @@ -1143,7 +1162,7 @@ } void -cdef_object_rep::mark_for_construction (const cdef_class& cls) +cdef_object_scalar::mark_for_construction (const cdef_class& cls) { std::string cls_name = cls.get_name (); @@ -1151,35 +1170,54 @@ if (! error_state) { - std::list supcls_names; - - for (int i = 0; ! error_state && i < supcls.numel (); i++) - supcls_names.push_back (supcls(i).string_value ()); + std::list supcls_list = lookup_classes (supcls); if (! error_state) - ctor_list[cls_name] = supcls_names; + ctor_list[cls] = supcls_list; } } + +bool cdef_object_scalar::is_constructed_for (const cdef_class& cls) const +{ + return (is_constructed () + || ctor_list.find (cls) == ctor_list.end ()); +} + +bool cdef_object_scalar::is_partially_constructed_for (const cdef_class& cls) const +{ + std::map< cdef_class, std::list >::const_iterator it; + + if (is_constructed ()) + return true; + else if ((it = ctor_list.find (cls)) == ctor_list.end () + || it->second.empty ()) + return true; + + for (std::list::const_iterator lit = it->second.begin (); + lit != it->second.end (); ++lit) + if (! is_constructed_for (*lit)) + return false; + + return true; +} handle_cdef_object::~handle_cdef_object (void) { - gnulib::printf ("deleting %s object (handle)\n", cname.c_str ()); + gnulib::printf ("deleting %s object (handle)\n", + get_class ().get_name ().c_str ()); } value_cdef_object::~value_cdef_object (void) { - gnulib::printf ("deleting %s object (value)\n", cname.c_str ()); + gnulib::printf ("deleting %s object (value)\n", + get_class ().get_name ().c_str ()); } -cdef_class::cdef_class_rep::cdef_class_rep (const std::string& nm, - const std::list& superclasses) - : handle_cdef_object (nm), handle_class (false) +cdef_class::cdef_class_rep::cdef_class_rep (const std::list& superclasses) + : handle_cdef_object (), handle_class (false) { - for (std::list::const_iterator it = superclasses.begin (); - it != superclasses.end (); ++it) - implicit_ctor_list.push_back (it->get_name ()); - - put ("SuperClasses", Cell (implicit_ctor_list)); + put ("SuperClasses", to_ov (superclasses)); + implicit_ctor_list = superclasses; } cdef_method @@ -1209,7 +1247,7 @@ for (int i = 0; i < super_classes.numel (); i++) { - cdef_class cls = lookup_class (super_classes(i).string_value ()); + cdef_class cls = lookup_class (super_classes(i)); if (! error_state) { @@ -1227,9 +1265,8 @@ class ctor_analyzer : public tree_walker { public: - ctor_analyzer (const std::string& ctor, const std::string& obj, - const std::list& l) - : tree_walker (), who (ctor), obj_name (obj), available_ctor_list (l) { } + ctor_analyzer (const std::string& ctor, const std::string& obj) + : tree_walker (), who (ctor), obj_name (obj) { } void visit_statement_list (tree_statement_list& t) { @@ -1282,24 +1319,17 @@ ? class_name : package_name + "." + class_name); - if (std::find (available_ctor_list.begin (), - available_ctor_list.end (), ctor_name) - == available_ctor_list.end ()) - ::error ("`%s' is not a direct superclass of `%s'", - ctor_name.c_str (), who.c_str ()); - else if (std::find (ctor_list.begin (), ctor_list.end (), - ctor_name) != ctor_list.end ()) - ::error ("calling constructor `%s' more than once", - ctor_name.c_str ()); - - ctor_list.push_back (ctor_name); + cdef_class cls = lookup_class (ctor_name, false); + + if (cls.ok ()) + ctor_list.push_back (cls); } } } } } - std::list get_constructor_list (void) const + std::list get_constructor_list (void) const { return ctor_list; } // NO-OP @@ -1348,10 +1378,7 @@ std::string obj_name; /* The list of superclass constructors that are explicitly called */ - std::list ctor_list; - - /* The list of possible superclass constructors */ - std::list available_ctor_list; + std::list ctor_list; }; void @@ -1378,20 +1405,19 @@ if (ret_list && ret_list->size () == 1) { std::string obj_name = ret_list->front ()->name (); - ctor_analyzer a (meth.get_name (), obj_name, - implicit_ctor_list); + ctor_analyzer a (meth.get_name (), obj_name); body->accept (a); if (! error_state) { - std::list explicit_ctor_list + std::list explicit_ctor_list = a.get_constructor_list (); - for (std::list::const_iterator it = explicit_ctor_list.begin (); + for (std::list::const_iterator it = explicit_ctor_list.begin (); ! error_state && it != explicit_ctor_list.end (); ++it) { gnulib::printf ("explicit superclass constructor: %s\n", - it->c_str ()); + it->get_name ().c_str ()); implicit_ctor_list.remove (*it); } } @@ -1471,7 +1497,7 @@ for (int i = 0; i < super_classes.numel (); i++) { - cdef_class cls = lookup_class (super_classes(i).string_value ()); + cdef_class cls = lookup_class (super_classes(i)); if (! error_state) cls.get_rep ()->find_methods (meths, true); @@ -1499,7 +1525,7 @@ for (int i = 0; i < super_classes.numel (); i++) { - cdef_class cls = lookup_class (super_classes(i).string_value ()); + cdef_class cls = lookup_class (super_classes(i)); if (! error_state) { @@ -1574,7 +1600,7 @@ for (int i = 0; ! error_state && i < super_classes.numel (); i++) { - cdef_class cls = lookup_class (super_classes(i).string_value ()); + cdef_class cls = lookup_class (super_classes(i)); if (! error_state) cls.get_rep ()->find_properties (props, true); @@ -1634,7 +1660,7 @@ for (int i = 0; ! error_state && i < super_classes.numel (); i++) { - cdef_class cls = lookup_class (super_classes(i).string_value ()); + cdef_class cls = lookup_class (super_classes(i)); if (! error_state) cls.get_rep ()->find_names (names, all); @@ -1672,13 +1698,13 @@ if (it != method_map.end ()) { - std::string cls_name = obj.class_name (); - - obj.set_class_name (get ("Name").string_value ()); + cdef_class cls = obj.get_class (); + + obj.set_class (wrap ()); it->second.execute (obj, octave_value_list (), 0); - obj.set_class_name (cls_name); + obj.set_class (cls); } // FIXME: should we destroy corresponding properties here? @@ -1689,7 +1715,7 @@ for (int i = 0; i < super_classes.numel (); i++) { - cdef_class cls = lookup_class (super_classes(i).string_value ()); + cdef_class cls = lookup_class (super_classes(i)); if (!error_state) cls.delete_object (obj); @@ -1769,7 +1795,7 @@ { octave_value_list empty_args; - for (std::list::const_iterator it = implicit_ctor_list.begin (); + for (std::list::const_iterator it = implicit_ctor_list.begin (); ! error_state && it != implicit_ctor_list.end (); ++it) { cdef_class supcls = lookup_class (*it); @@ -1807,7 +1833,7 @@ } } - obj.mark_as_constructed (cls_name); + obj.mark_as_constructed (wrap ()); } octave_value @@ -1816,9 +1842,10 @@ cdef_object_rep *r; if (is_handle_class ()) - r = new handle_cdef_object (get_name ()); + r = new handle_cdef_object (); else - r = new value_cdef_object (get_name ()); + r = new value_cdef_object (); + r->set_class (wrap ()); cdef_object obj (r); @@ -2071,7 +2098,7 @@ { cdef_class cls (to_cdef (get ("DefiningClass"))); - if (! obj.is_partially_constructed_for (cls.get_name ())) + if (! obj.is_partially_constructed_for (cls)) { ::error ("cannot reference properties of class `%s' for non-constructed object", cls.get_name ().c_str ()); @@ -2115,7 +2142,7 @@ { cdef_class cls (to_cdef (get ("DefiningClass"))); - if (! obj.is_partially_constructed_for (cls.get_name ())) + if (! obj.is_partially_constructed_for (cls)) { ::error ("cannot reference properties of class `%s' for non-constructed object", cls.get_name ().c_str ()); @@ -2389,26 +2416,38 @@ cdef_package::cdef_package_rep::get_packages (void) const { return map2Cell (package_map); } +cdef_class cdef_class::_meta_class = cdef_class (); +cdef_class cdef_class::_meta_property = cdef_class (); +cdef_class cdef_class::_meta_method = cdef_class (); +cdef_class cdef_class::_meta_package = cdef_class (); + +cdef_package cdef_package::_meta = cdef_package (); + void install_classdef (void) { octave_classdef::register_type (); - /* meta classes */ + /* bootstrap */ cdef_class handle = make_class ("handle"); - cdef_class meta_class = make_class ("meta.class", handle); - cdef_class meta_property = make_class ("meta.property", handle); - cdef_class meta_method = make_class ("meta.method", handle); + cdef_class meta_class = cdef_class::_meta_class = make_class ("meta.class", handle); + handle.set_class (meta_class); + meta_class.set_class (meta_class); + + /* meta classes */ + cdef_class meta_property = cdef_class::_meta_property = make_class ("meta.property", handle); + cdef_class meta_method = cdef_class::_meta_method = make_class ("meta.method", handle); + cdef_class meta_package = cdef_class::_meta_package = make_class ("meta.package", handle); + cdef_class meta_event = make_class ("meta.event", handle); - cdef_class meta_package = make_class ("meta.package", handle); cdef_class meta_dynproperty = make_class ("meta.dynamicproperty", handle); /* meta classes are all sealed */ meta_class.put ("Sealed", true); meta_property.put ("Sealed", true); meta_method.put ("Sealed", true); + meta_package.put ("Sealed", true); meta_event.put ("Sealed", true); - meta_package.put ("Sealed", true); meta_dynproperty.put ("Sealed", true); /* meta.class properties */ @@ -2532,7 +2571,7 @@ "public", true)); /* create "meta" package */ - cdef_package package_meta = make_package ("meta"); + cdef_package package_meta = cdef_package::_meta = make_package ("meta"); package_meta.install_class (meta_class, "class"); package_meta.install_class (meta_property, "property"); package_meta.install_class (meta_method, "method"); diff -r a413c6fe1726 -r b8bff84022d6 libinterp/octave-value/ov-classdef.h --- a/libinterp/octave-value/ov-classdef.h Fri Jan 04 14:29:13 2013 -0500 +++ b/libinterp/octave-value/ov-classdef.h Sun Jan 06 12:19:16 2013 -0500 @@ -38,6 +38,9 @@ class tree_classdef; +// This is mainly a boostrap class to declare the expected interface. +// The actual base class is cdef_class_base, which is declared after +// cdef_object, such that it can contain cdef_object objects. class cdef_object_rep { @@ -45,110 +48,102 @@ friend class cdef_object; public: - cdef_object_rep (void) - : refcount (1), cname () { } - - cdef_object_rep (const std::string& nm) - : refcount (1), cname (nm) { } + cdef_object_rep (void) : refcount (1) { } virtual ~cdef_object_rep (void) { } virtual cdef_class get_class (void) const; + virtual void set_class (const cdef_class&) + { gripe_invalid_object ("set_class"); } + virtual cdef_object_rep* clone (void) const { - error ("clone: invalid object"); + gripe_invalid_object ("clone"); return new cdef_object_rep (); } - virtual void put (const std::string& pname, const octave_value& val) - { map.assign (pname, val); } + virtual bool is_class (void) const { return false; } + + virtual bool is_property (void) const { return false; } - virtual octave_value get (const std::string& pname) const - { - Cell val = map.contents (pname); + virtual bool is_method (void) const { return false; } + + virtual bool is_package (void) const { return false; } - if (val.numel () > 0) - return val(0, 0); - else - { - error ("get: unknown slot: %s", pname.c_str ()); - return octave_value (); - } + virtual void put (const std::string&, const octave_value&) + { gripe_invalid_object ("put"); } + + virtual octave_value get (const std::string&) const + { + gripe_invalid_object ("get"); + return octave_value (); } virtual octave_value_list - subsref (const std::string& type, const std::list& idx, - int nargout, size_t& skip, const cdef_class& context); + subsref (const std::string&, const std::list&, + int, size_t&, const cdef_class&) + { + gripe_invalid_object ("subsref"); + return octave_value_list (); + } virtual octave_value - subsasgn (const std::string& type, const std::list& idx, - const octave_value& rhs); + subsasgn (const std::string&, const std::list&, + const octave_value&) + { + gripe_invalid_object ("subsasgn"); + return octave_value (); + } virtual string_vector map_keys(void) const; virtual bool is_valid (void) const { return false; } - std::string class_name (void) const { return cname; } + std::string class_name (void) const; - void set_class_name (const std::string& nm) { cname = nm; } - - void mark_for_construction (const cdef_class&); + virtual void mark_for_construction (const cdef_class&) + { gripe_invalid_object ("mark_for_construction"); } - //bool is_constructed_for (const cdef_class&) const; - - bool is_constructed_for (const std::string& nm) const + virtual bool is_constructed_for (const cdef_class&) const { - return (is_constructed () - || ctor_list.find (nm) == ctor_list.end ()); + gripe_invalid_object ("is_constructed_for"); + return false; } - bool is_partially_constructed_for (const std::string& nm) const + virtual bool is_partially_constructed_for (const cdef_class&) const { - std::map< std::string, std::list >::const_iterator it; - - if (is_constructed ()) - return true; - else if ((it = ctor_list.find (nm)) == ctor_list.end () - || it->second.empty ()) - return true; - - for (std::list::const_iterator lit = it->second.begin (); - lit != it->second.end (); ++lit) - if (! is_constructed_for (*lit)) - return false; - - return true; + gripe_invalid_object ("is_partially_constructed_for"); + return false; } - void mark_as_constructed (void) { ctor_list.clear (); } + virtual void mark_as_constructed (void) + { gripe_invalid_object ("mark_as_constructed"); } + + virtual void mark_as_constructed (const cdef_class&) + { gripe_invalid_object ("mark_as_constructed"); } - void mark_as_constructed (const std::string& nm) { ctor_list.erase (nm); } - - bool is_constructed (void) const { return ctor_list.empty (); } + virtual bool is_constructed (void) const + { + gripe_invalid_object ("is_constructed"); + return false; + } protected: /* reference count */ octave_refcount refcount; - /* class name */ - std::string cname; - - /* object property values */ - Octave_map map; - - /* Internal/temporary structure used during object construction */ - std::map< std::string, std::list > ctor_list; - protected: /* Restricted copying */ - cdef_object_rep (const cdef_object_rep& r) - : refcount (1), cname (r.cname), map (r.map), - ctor_list (r.ctor_list) { } + cdef_object_rep (const cdef_object_rep&) + : refcount (1) { } private: /* No assignment */ cdef_object_rep& operator = (const cdef_object_rep& ); + + void gripe_invalid_object (const char *who) const + { error ("%s: invalid object", who); } }; class @@ -190,8 +185,7 @@ cdef_class get_class (void) const; - void set_class_name (const std::string& nm) - { rep->set_class_name (nm); } + void set_class (const cdef_class& cls) { rep->set_class (cls); } std::string class_name (void) const { return rep->class_name (); } @@ -199,6 +193,14 @@ cdef_object clone (void) const { return cdef_object (rep->clone ()); } + bool is_class (void) const { return rep->is_class (); } + + bool is_property (void) const { return rep->is_property (); } + + bool is_method (void) const { return rep->is_method (); } + + bool is_package (void) const { return rep->is_package (); } + void put (const std::string& pname, const octave_value& val) { rep->put (pname, val); } @@ -226,16 +228,16 @@ bool is_constructed (void) const { return rep->is_constructed (); } - bool is_constructed_for (const std::string& nm) const - { return rep->is_constructed_for (nm); } + bool is_constructed_for (const cdef_class& cls) const + { return rep->is_constructed_for (cls); } - bool is_partially_constructed_for (const std::string& nm) const - { return rep->is_partially_constructed_for (nm); } + bool is_partially_constructed_for (const cdef_class& cls) const + { return rep->is_partially_constructed_for (cls); } void mark_as_constructed (void) { rep->mark_as_constructed (); } - void mark_as_constructed (const std::string& nm) - { rep->mark_as_constructed (nm); } + void mark_as_constructed (const cdef_class& cls) + { rep->mark_as_constructed (cls); } protected: cdef_object_rep* get_rep (void) { return rep; } @@ -245,14 +247,110 @@ }; class -handle_cdef_object : public cdef_object_rep +cdef_object_base : public cdef_object_rep +{ +public: + cdef_object_base (void) + : cdef_object_rep (), klass () + { + register_object (); + } + + ~cdef_object_base (void) { unregister_object (); } + + cdef_class get_class (void) const; + + void set_class (const cdef_class& cls); + +protected: + // Restricted copying! + cdef_object_base (const cdef_object_base& obj) + : cdef_object_rep (obj), klass (obj.klass) + { + register_object (); + } + +private: + void register_object (void); + + void unregister_object (void); + +private: + // The class of the object + cdef_object klass; + +private: + // No assignment! + cdef_object_base& operator = (const cdef_object_base&); +}; + +class +cdef_object_scalar : public cdef_object_base +{ +public: + cdef_object_scalar (void) : cdef_object_base () { } + + ~cdef_object_scalar (void) { } + + void put (const std::string& pname, const octave_value& val) + { map.assign (pname, val); } + + octave_value get (const std::string& pname) const + { + Cell val = map.contents (pname); + + if (val.numel () > 0) + return val(0, 0); + else + { + error ("get: unknown slot: %s", pname.c_str ()); + return octave_value (); + } + } + + octave_value_list + subsref (const std::string& type, const std::list& idx, + int nargout, size_t& skip, const cdef_class& context); + + octave_value + subsasgn (const std::string& type, const std::list& idx, + const octave_value& rhs); + + void mark_for_construction (const cdef_class&); + + bool is_constructed_for (const cdef_class& cls) const; + + bool is_partially_constructed_for (const cdef_class& cls) const; + + void mark_as_constructed (void) { ctor_list.clear (); } + + void mark_as_constructed (const cdef_class& cls) { ctor_list.erase (cls); } + + bool is_constructed (void) const { return ctor_list.empty (); } + +protected: + // Object property values + Octave_map map; + + // Internal/temporary structure used during object construction + std::map< cdef_class, std::list > ctor_list; + +protected: + // Restricted object copying! + cdef_object_scalar (const cdef_object_scalar& obj) + : cdef_object_base (obj), map (obj.map), ctor_list (obj.ctor_list) { } + +private: + // No assignment! + cdef_object_scalar& operator = (const cdef_object_scalar&); +}; + +class +handle_cdef_object : public cdef_object_scalar { public: handle_cdef_object (void) - : cdef_object_rep () { } - - handle_cdef_object (const std::string& nm) - : cdef_object_rep (nm) { } + : cdef_object_scalar () { } ~handle_cdef_object (void); @@ -272,29 +370,28 @@ }; class -value_cdef_object : public cdef_object_rep +value_cdef_object : public cdef_object_scalar { public: value_cdef_object (void) - : cdef_object_rep () { } - - value_cdef_object (const std::string& nm) - : cdef_object_rep (nm) { } + : cdef_object_scalar () { } ~value_cdef_object (void); cdef_object_rep* clone (void) const { - value_cdef_object* obj = new value_cdef_object (cname); - obj->map = map; + value_cdef_object* obj = new value_cdef_object (*this); return obj; } bool is_valid (void) const { return true; } private: - // No copying - value_cdef_object (const value_cdef_object&); + // Private copying! + value_cdef_object (const value_cdef_object& obj) + : cdef_object_scalar (obj) { } + + // No assignment! value_cdef_object& operator = (const value_cdef_object&); }; @@ -307,15 +404,18 @@ cdef_class_rep : public handle_cdef_object { public: - cdef_class_rep (const std::string& nm) - : handle_cdef_object (nm), handle_class (false) { } + cdef_class_rep (void) + : handle_cdef_object (), handle_class (false) { } - cdef_class_rep (const std::string& nm, - const std::list& superclasses); + cdef_class_rep (const std::list& superclasses); + + bool is_class (void) const { return true; } std::string get_name (void) const { return get ("Name").string_value (); } + void set_name (const std::string& nm) { put ("Name", nm); } + cdef_method find_method (const std::string& nm, bool local = false); void install_method (const cdef_method& meth); @@ -361,6 +461,12 @@ void find_methods (std::map& meths, bool only_inherited); + cdef_class wrap (void) + { + refcount++; + return cdef_class (this); + } + private: // The @-directory were this class is loaded from. // (not used yet) @@ -379,7 +485,7 @@ // The list of super-class constructors that are called implicitly by the // the classdef engine when creating an object. These constructors are not // called explicitly by the class constructor. - std::list implicit_ctor_list; + std::list implicit_ctor_list; // Utility iterator typedef's. typedef std::map::iterator method_iterator; @@ -393,12 +499,10 @@ cdef_class (void) : cdef_object () { } - cdef_class (const std::string& nm) - : cdef_object (new cdef_class_rep (nm)) { } - cdef_class (const std::string& nm, const std::list& superclasses) - : cdef_object (new cdef_class_rep (nm, superclasses)) { } + : cdef_object (new cdef_class_rep (superclasses)) + { get_rep ()->set_name (nm); } cdef_class (const cdef_class& cls) : cdef_object (cls) { } @@ -407,7 +511,7 @@ : cdef_object (obj) { // This should never happen... - if (class_name () != "meta.class") + if (! is_class ()) error ("internal error: invalid assignment from %s to meta.class object", class_name ().c_str ()); } @@ -421,7 +525,7 @@ cdef_class& operator = (const cdef_object& obj) { - if (obj.class_name () == "meta.class") + if (obj.is_class ()) cdef_object::operator= (obj); else error ("internal error: invalid assignment from %s to meta.class object", @@ -488,6 +592,11 @@ bool is_handle_class (void) const { return get_rep ()->is_handle_class (); } + static const cdef_class& meta_class (void) { return _meta_class; } + static const cdef_class& meta_property (void) { return _meta_property; } + static const cdef_class& meta_method (void) { return _meta_method; } + static const cdef_class& meta_package (void) { return _meta_package; } + private: cdef_class_rep* get_rep (void) { return dynamic_cast (cdef_object::get_rep ()); } @@ -497,6 +606,15 @@ friend bool operator == (const cdef_class&, const cdef_class&); friend bool operator != (const cdef_class&, const cdef_class&); + friend bool operator < (const cdef_class&, const cdef_class&); + +private: + static cdef_class _meta_class; + static cdef_class _meta_property; + static cdef_class _meta_method; + static cdef_class _meta_package; + + friend void install_classdef (void); }; inline bool @@ -508,6 +626,11 @@ operator != (const cdef_class& clsa, const cdef_class& clsb) { return ! (clsa == clsb); } +// This is only to be able to use cdef_class as map keys. +inline bool +operator < (const cdef_class& clsa, const cdef_class& clsb) +{ return clsa.get_rep () < clsb.get_rep (); } + class cdef_property : public cdef_object { @@ -517,8 +640,16 @@ cdef_property_rep : public handle_cdef_object { public: - cdef_property_rep (const std::string& nm) - : handle_cdef_object (nm) { } + cdef_property_rep (void) + : handle_cdef_object () { } + + bool is_property (void) const { return true; } + + std::string get_name (void) const { return get("Name").string_value (); } + + void set_name (const std::string& nm) { put ("Name", nm); } + + bool is_constant (void) const { return get("Constant").bool_value (); } octave_value get_value (void) const { return default_value; } @@ -539,7 +670,8 @@ cdef_property (void) : cdef_object () { } cdef_property (const std::string& nm) - : cdef_object (new cdef_property_rep (nm)) { } + : cdef_object (new cdef_property_rep ()) + { get_rep ()->set_name (nm); } cdef_property (const cdef_property& prop) : cdef_object (prop) { } @@ -548,7 +680,7 @@ : cdef_object (obj) { // This should never happen... - if (class_name () != "meta.property") + if (! is_property ()) error ("internal error: invalid assignment from %s to meta.property object", class_name ().c_str ()); } @@ -574,11 +706,9 @@ bool check_set_access (void) const; - std::string get_name (void) const - { return get ("Name").string_value (); } + std::string get_name (void) const { return get_rep ()->get_name (); } - bool is_constant (void) const - { return get ("Constant").bool_value (); } + bool is_constant (void) const { return get_rep ()->is_constant (); } private: cdef_property_rep* get_rep (void) @@ -597,8 +727,15 @@ cdef_method_rep : public handle_cdef_object { public: - cdef_method_rep (const std::string& nm) - : handle_cdef_object (nm) { } + cdef_method_rep (void) : handle_cdef_object () { } + + bool is_method (void) const { return true; } + + std::string get_name (void) const { return get("Name").string_value (); } + + void set_name (const std::string& nm) { put ("Name", nm); } + + bool is_static (void) const { return get("Static").bool_value (); } octave_value get_function (void) const { return function; } @@ -622,7 +759,8 @@ cdef_method (void) : cdef_object () { } cdef_method (const std::string& nm) - : cdef_object (new cdef_method_rep (nm)) { } + : cdef_object (new cdef_method_rep ()) + { get_rep ()->set_name (nm); } cdef_method (const cdef_property& prop) : cdef_object (prop) { } @@ -631,7 +769,7 @@ : cdef_object (obj) { // This should never happen... - if (class_name () != "meta.method") + if (! is_method ()) error ("internal error: invalid assignment from %s to meta.method object", class_name ().c_str ()); } @@ -654,11 +792,9 @@ bool check_access (void) const; - std::string get_name (void) const - { return get ("Name").string_value (); } + std::string get_name (void) const { return get_rep ()->get_name (); } - bool is_static (void) const - { return get ("Static").bool_value (); } + bool is_static (void) const { return get_rep ()->is_static (); } void set_function (const octave_value& fcn) { get_rep ()->set_function (fcn); } @@ -678,9 +814,42 @@ }; inline cdef_class +cdef_object_rep::get_class (void) const +{ + gripe_invalid_object ("get_class"); + return cdef_class (); +} + +inline std::string +cdef_object_rep::class_name (void) const +{ return get_class ().get_name (); } + +inline cdef_class cdef_object::get_class (void) const { return rep->get_class (); } +inline cdef_class +cdef_object_base::get_class (void) const +{ return cdef_class (klass); } + +inline void +cdef_object_base::set_class (const cdef_class& cls) +{ + klass = cls; +} + +inline void +cdef_object_base::register_object (void) +{ + // FIXME: implement this +} + +inline void +cdef_object_base::unregister_object (void) +{ + // FIXME: implement this +} + inline cdef_method cdef_class::find_method (const std::string& nm, bool local) { return get_rep ()->find_method (nm, local); } @@ -698,8 +867,13 @@ cdef_package_rep : public handle_cdef_object { public: - cdef_package_rep (const std::string& nm) - : handle_cdef_object (nm) { } + cdef_package_rep (void) : handle_cdef_object () { } + + bool is_package (void) const { return true; } + + std::string get_name (void) const { return get("Name").string_value (); } + + void set_name (const std::string& nm) { put ("Name", nm); } void install_class (const cdef_class& cls, const std::string& nm); @@ -730,13 +904,14 @@ cdef_package (void) : cdef_object () { } cdef_package (const std::string& nm) - : cdef_object (new cdef_package_rep (nm)) { } + : cdef_object (new cdef_package_rep ()) + { get_rep ()->set_name (nm); } cdef_package (const cdef_object& obj) : cdef_object (obj) { // This should never happen... - if (class_name () != "meta.package") + if (! is_package ()) error ("internal error: invalid assignment from %s to meta.package object", class_name ().c_str ()); } @@ -766,12 +941,21 @@ Cell get_packages (void) const { return get_rep ()->get_packages (); } + std::string get_name (void) const { return get_rep ()->get_name (); } + + static const cdef_package& meta (void) { return _meta; } + private: cdef_package_rep* get_rep (void) { return dynamic_cast (cdef_object::get_rep ()); } const cdef_package_rep* get_rep (void) const { return dynamic_cast (cdef_object::get_rep ()); } + +private: + static cdef_package _meta; + + friend void install_classdef (void); }; class