# HG changeset patch # User Michael Goffioul # Date 1357666470 18000 # Node ID 8521321604df33d1cb03eadbb5cc113e9415d2b0 # Parent b18b7e560236e6cab20b2764e2bdb8bcaf266736 Initial support for object array semantic. * libinterp/octave-value/ov-classdef.h (class cdef_object_array): New class. (cdef_object_rep::empty_clone, cdef_object_rep::copy, cdef_object_rep::make_array, cdef_object_rep::is_array, cdef_object_rep::array_value): New methods. (cdef_object::empty_clone, cdef_object::make_array, cdef_object::copy, cdef_object::is_array, cdef_object::array_value): Likewise. (cdef_object_base::empty_clone, cdef_object_base::make_array): Likewise. (handle_cdef_object::copy): Likewise. (value_cdef_object::copy): Likewise. (cdef_class::cdef_class_rep::copy, cdef_property::cdef_property_rep::copy, cdef_method::cdef_method_rep::copy, cdef_package::cdef_package_rep::copy): Likewise. (handle_cdef_object::handle_cdef_object): New copy constructor. (cdef_object::make_unique): New method. (cdef_object::subsasgn): Use it. (cdef_class::cdef_class_rep::meta): New member. (cdef_class::cdef_class_rep::cdef_class_rep): Initialize it. (cdef_class::cdef_class_rep::mark_as_meta_class, cdef_class::cdef_class_rep::is_meta): Use and manipulate it. (cdef_class::mark_as_meta_class, cdef_class::is_meta): Likewise. (cdef_class::cdef_class_rep::construct_object, cdef_class::cdef_class_rep::is_abstract, cdef_class::cdef_class_rep::is_sealed): New methods. (cdef_class::construct_object, cdef_class::is_abstract, cdef_class::is_sealed): Likewise. (cdef_class::cdef_class_rep::cdef_class_rep): New copy constructor. (cdef_property::cdef_property_rep::default_value): Remove member. (cdef_property::cdef_property_rep::get_value ()): Use "DefaultValue" slot. (cdef_property::cdef_property_rep::set_value (octave_value)): Remove method. (cdef_property::set_value (octave_value)): Likewise. (cdef_property::cdef_property_rep::cdef_property_rep): New copy constructor. (cdef_method::cdef_method_rep::cdef_method_rep): Likewise. (cdef_package::cdef_package_rep::cdef_package_rep): Likewise. (octave_classdef::empty_clone): Call cdef_object::empty_clone. (octave_classdef::undef_subsasgn): New method. (class cdef_property, class cdef_method, class cdef_package): Mark cdef_class as friend. * libinterp/octave-value/ov-classdef.cc: Include Array.cc. (make_class): Initialize "Abstract" property. Do not register classes with empty name. (make_meta_class): New static function. (make_method): Check whether function object is valid. (make_package): Do not register packages with empty name. (octave_classdef::undef_subsasgn): New method. (class cdef_object_array): New class. (cdef_class::cdef_class_rep::cdef_class_rep): Initialize meta. (cdef_class::cdef_class_rep::find_methods, cdef_class::cdef_class_rep::find_names): Use cdef_method::is_constructor instead of relying on the method name. (cdef_class::cdef_class_rep::construct_object): New method. (cdef_class::cdef_class_rep::construct): Use it. (install_classdef): Use make_meta_class. Create "Abstract" property for class meta.class. diff -r b18b7e560236 -r 8521321604df libinterp/octave-value/ov-classdef.cc --- a/libinterp/octave-value/ov-classdef.cc Sun Jan 06 22:22:13 2013 -0500 +++ b/libinterp/octave-value/ov-classdef.cc Tue Jan 08 12:34:30 2013 -0500 @@ -41,6 +41,8 @@ #include "symtab.h" #include "toplev.h" +#include "Array.cc" + static std::map all_classes; static std::map all_packages; @@ -611,6 +613,7 @@ cdef_class cls (name, super_list); cls.set_class (cdef_class::meta_class ()); + cls.put ("Abstract", false); cls.put ("ConstructOnLoad", false); cls.put ("ContainingPackage", Matrix ()); cls.put ("Description", std::string ()); @@ -657,7 +660,8 @@ if (error_state) return cdef_class (); - all_classes[name] = cls; + if (! name.empty ()) + all_classes[name] = cls; return cls; } @@ -668,6 +672,17 @@ return make_class (name, std::list (1, super)); } +static cdef_class +make_meta_class (const std::string& name, const cdef_class& super) +{ + cdef_class cls = make_class (name, super); + + cls.put ("Sealed", true); + cls.mark_as_meta_class (); + + return cls; +} + static cdef_property make_property (const cdef_class& cls, const std::string& name, const octave_value& get_method = Matrix (), @@ -675,8 +690,6 @@ const octave_value& set_method = Matrix (), const std::string& set_access = "public") { - // FIXME: what about default value? - cdef_property prop (name); prop.set_class (cdef_class::meta_property ()); @@ -730,7 +743,8 @@ meth.put ("Sealed", true); meth.put ("Static", is_static); - make_function_of_class (cls, fcn); + if (fcn.is_defined ()) + make_function_of_class (cls, fcn); meth.set_function (fcn); @@ -757,7 +771,8 @@ pack.put ("Name", nm); pack.put ("ContainingPackage", to_ov (all_packages[parent])); - all_packages[nm] = pack; + if (! nm.empty ()) + all_packages[nm] = pack; return pack; } @@ -806,6 +821,24 @@ return object.subsasgn (type, idx, rhs); } +octave_value +octave_classdef::undef_subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs) +{ + if (type.length () == 1 && type[0] == '(') + { + object = object.make_array (); + + if (! error_state) + return subsasgn (type, idx, rhs); + } + else + return octave_base_value::undef_subsasgn (type, idx, rhs); + + return octave_value (); +} + //---------------------------------------------------------------------------- class octave_classdef_proxy : public octave_function @@ -1180,6 +1213,171 @@ ctor_list[cls] = supcls_list; } } + +octave_value_list +cdef_object_array::subsref (const std::string& type, + const std::list& idx, + int /* nargout */, size_t& skip, + const cdef_class& /* context */) +{ + octave_value_list retval; + + skip = 1; + + switch (type[0]) + { + case '(': + { + const octave_value_list& ival = idx.front (); + bool is_scalar = true; + Array iv (dim_vector (1, ival.length ())); + + for (int i = 0; ! error_state && i < ival.length (); i++) + { + iv(i) = ival(i).index_vector (); + if (! error_state) + is_scalar = is_scalar && iv(i).is_scalar (); + } + + if (! error_state) + { + Array ires = array.index (iv); + + if (! error_state) + { + if (is_scalar) + retval(0) = to_ov (ires(0)); + else + { + cdef_object array_obj (new cdef_object_array (ires)); + + array_obj.set_class (get_class ()); + + retval(0) = to_ov (array_obj); + } + } + } + } + break; + + default: + ::error ("can't perform indexing operation on array of %s objects", + class_name ().c_str ()); + break; + } + + return retval; +} + +octave_value +cdef_object_array::subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs) +{ + octave_value retval; + + switch (type[0]) + { + case '(': + if (type.length () == 1) + { + cdef_object rhs_obj = to_cdef (rhs); + + if (! error_state) + { + if (rhs_obj.get_class () == get_class ()) + { + const octave_value_list& ival = idx.front (); + bool is_scalar = true; + Array iv (dim_vector (1, ival.length ())); + + for (int i = 0; ! error_state && i < ival.length (); i++) + { + iv(i) = ival(i).index_vector (); + if (! error_state) + is_scalar = is_scalar && iv(i).is_scalar (); + } + + if (! error_state) + { + Array rhs_mat; + + if (! rhs_obj.is_array ()) + { + rhs_mat = Array (dim_vector (1, 1)); + rhs_mat(0) = rhs_obj; + } + else + rhs_mat = rhs_obj.array_value (); + + if (! error_state) + { + octave_idx_type n = array.numel (); + + array.assign (iv, rhs_mat, cdef_object ()); + + if (! error_state) + { + if (array.numel () > n) + fill_empty_values (); + + if (! error_state) + { + refcount++; + retval = to_ov (cdef_object (this)); + } + } + } + } + } + else + ::error ("can't assign %s object into array of %s objects.", + rhs_obj.class_name ().c_str (), + class_name ().c_str ()); + } + } + else + ::error ("can't perform indexing operation on array of %s objects", + class_name ().c_str ()); + break; + + default: + ::error ("can't perform indexing operation on array of %s objects", + class_name ().c_str ()); + break; + } + + return retval; +} + +void +cdef_object_array::fill_empty_values (void) +{ + cdef_class cls = get_class (); + + if (! error_state) + { + cdef_object obj; + + int n = array.numel (); + + for (int i = 0; ! error_state && i < n; i++) + { + if (! array.xelem (i).ok ()) + { + if (! obj.ok ()) + { + obj = cls.construct_object (octave_value_list ()); + + if (! error_state) + array.xelem (i) = obj; + } + else + array.xelem (i) = obj.copy (); + } + } + } +} bool cdef_object_scalar::is_constructed_for (const cdef_class& cls) const { @@ -1219,7 +1417,7 @@ cdef_class::cdef_class_rep::cdef_class_rep (const std::list& superclasses) : handle_cdef_object (), member_count (0), handle_class (false), - object_count (0) + object_count (0), meta (false) { put ("SuperClasses", to_ov (superclasses)); implicit_ctor_list = superclasses; @@ -1474,14 +1672,12 @@ method_const_iterator it; - std::string cls_name = get_base_name (get_name ()); - for (it = method_map.begin (); it != method_map.end (); ++it) { - std::string nm = it->second.get_name (); - - if (nm != cls_name) + if (! it->second.is_constructor ()) { + std::string nm = it->second.get_name (); + if (meths.find (nm) == meths.end ()) { if (only_inherited) @@ -1624,15 +1820,13 @@ { load_all_methods (); - std::string cls_name = get_base_name (get_name ()); - for (method_const_iterator it = method_map.begin (); ! error_state && it != method_map.end(); ++it) { - std::string nm = it->second.get_name (); - - if (nm != cls_name) + if (! it->second.is_constructor ()) { + std::string nm = it->second.get_name (); + if (! all) { octave_value acc = it->second.get ("Access"); @@ -1848,27 +2042,93 @@ octave_value cdef_class::cdef_class_rep::construct (const octave_value_list& args) { - cdef_object_rep *r; - - if (is_handle_class ()) - r = new handle_cdef_object (); + cdef_object obj = construct_object (args); + + if (! error_state && obj.ok ()) + return to_ov (obj); + + return octave_value (); +} + +cdef_object +cdef_class::cdef_class_rep::construct_object (const octave_value_list& args) +{ + if (! is_abstract ()) + { + cdef_object obj; + + if (is_meta_class ()) + { + // This code path is only used to create empty meta objects + // as filler for the empty values within a meta object array. + + cdef_class this_cls = wrap (); + + static cdef_object empty_class; + + if (this_cls == cdef_class::meta_class ()) + { + if (! empty_class.ok ()) + empty_class = make_class ("", std::list ()); + obj = empty_class; + } + else if (this_cls == cdef_class::meta_property ()) + { + static cdef_property empty_property; + + if (! empty_class.ok ()) + empty_class = make_class ("", std::list ()); + if (! empty_property.ok ()) + empty_property = make_property (empty_class, ""); + obj = empty_property; + } + else if (this_cls == cdef_class::meta_method ()) + { + static cdef_method empty_method; + + if (! empty_class.ok ()) + empty_class = make_class ("", std::list ()); + if (! empty_method.ok ()) + empty_method = make_method (empty_class, "", octave_value ()); + obj = empty_method; + } + else if (this_cls == cdef_class::meta_package ()) + { + static cdef_package empty_package; + + if (! empty_package.ok ()) + empty_package = make_package (""); + obj = empty_package; + } + else + panic_impossible (); + + return obj; + } + else + { + if (is_handle_class ()) + obj = cdef_object (new handle_cdef_object ()); + else + obj = cdef_object (new value_cdef_object ()); + obj.set_class (wrap ()); + + initialize_object (obj); + + if (! error_state) + { + run_constructor (obj, args); + + if (! error_state) + return obj; + } + } + } else - r = new value_cdef_object (); - r->set_class (wrap ()); - - cdef_object obj (r); - - initialize_object (obj); - - if (! error_state) - { - run_constructor (obj, args); - - if (! error_state) - return to_ov (obj); - } - - return octave_value(); + error ("cannot instantiate object for abstract class `%s'", + get_name ().c_str ()); + + return cdef_object (); } static octave_value @@ -2443,27 +2703,20 @@ /* bootstrap */ cdef_class handle = make_class ("handle"); - cdef_class meta_class = cdef_class::_meta_class = make_class ("meta.class", handle); + cdef_class meta_class = cdef_class::_meta_class = make_meta_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_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_dynproperty.put ("Sealed", true); + cdef_class meta_property = cdef_class::_meta_property = make_meta_class ("meta.property", handle); + cdef_class meta_method = cdef_class::_meta_method = make_meta_class ("meta.method", handle); + cdef_class meta_package = cdef_class::_meta_package = make_meta_class ("meta.package", handle); + + cdef_class meta_event = make_meta_class ("meta.event", handle); + cdef_class meta_dynproperty = make_meta_class ("meta.dynamicproperty", handle); /* meta.class properties */ + meta_class.install_property (make_attribute (meta_class, "Abstract")); meta_class.install_property (make_attribute (meta_class, "ConstructOnLoad")); meta_class.install_property (make_property (meta_class, "ContainingPackage")); meta_class.install_property (make_property (meta_class, "Description")); diff -r b18b7e560236 -r 8521321604df libinterp/octave-value/ov-classdef.h --- a/libinterp/octave-value/ov-classdef.h Sun Jan 06 22:22:13 2013 -0500 +++ b/libinterp/octave-value/ov-classdef.h Tue Jan 08 12:34:30 2013 -0500 @@ -63,6 +63,26 @@ return new cdef_object_rep (); } + virtual cdef_object_rep* empty_clone (void) const + { + gripe_invalid_object ("empty_clone"); + return new cdef_object_rep (); + } + + virtual cdef_object_rep* copy (void) const + { + gripe_invalid_object ("copy"); + return new cdef_object_rep (); + } + + virtual cdef_object_rep* make_array (void) const + { + gripe_invalid_object ("make_array"); + return new cdef_object_rep (); + } + + virtual bool is_array (void) const { return false; } + virtual bool is_class (void) const { return false; } virtual bool is_property (void) const { return false; } @@ -71,6 +91,12 @@ virtual bool is_package (void) const { return false; } + virtual Array array_value (void) const + { + gripe_invalid_object ("array_value"); + return Array (); + } + virtual void put (const std::string&, const octave_value&) { gripe_invalid_object ("put"); } @@ -199,6 +225,17 @@ cdef_object clone (void) const { return cdef_object (rep->clone ()); } + cdef_object empty_clone (void) const + { return cdef_object (rep->empty_clone ()); } + + cdef_object make_array (void) const + { return cdef_object (rep->make_array ()); } + + cdef_object copy (void) const + { return cdef_object (rep->copy ()); } + + bool is_array (void) const { return rep->is_array (); } + bool is_class (void) const { return rep->is_class (); } bool is_property (void) const { return rep->is_property (); } @@ -207,6 +244,8 @@ bool is_package (void) const { return rep->is_package (); } + Array array_value (void) const { return rep->array_value (); } + void put (const std::string& pname, const octave_value& val) { rep->put (pname, val); } @@ -221,7 +260,10 @@ octave_value subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs) - { return rep->subsasgn (type, idx, rhs); } + { + make_unique (); + return rep->subsasgn (type, idx, rhs); + } string_vector map_keys (void) const { return rep->map_keys (); } @@ -248,6 +290,12 @@ protected: cdef_object_rep* get_rep (void) { return rep; } + void make_unique (void) + { + if (rep->refcount > 1) + *this = clone (); + } + private: cdef_object_rep *rep; }; @@ -268,6 +316,11 @@ void set_class (const cdef_class& cls); + cdef_object_rep* empty_clone (void) const + { return new cdef_object_base (*this); } + + cdef_object_rep* make_array (void) const; + protected: // Restricted copying! cdef_object_base (const cdef_object_base& obj) @@ -291,6 +344,46 @@ }; class +cdef_object_array : public cdef_object_base +{ +public: + cdef_object_array (void) : cdef_object_base () { } + + cdef_object_array (const Array& a) + : cdef_object_base (), array (a) { } + + cdef_object_rep* clone (void) const + { return new cdef_object_array (*this); } + + bool is_valid (void) const { return true; } + + bool is_array (void) const { return true; } + + Array array_value (void) const { return array; } + + 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); + +private: + Array array; + +private: + void fill_empty_values (void); + + // Private copying! + cdef_object_array (const cdef_object_array& obj) + : cdef_object_base (obj), array (obj.array) { } + + // No assignment! + cdef_object_array& operator = (const cdef_object_array&); +}; + +class cdef_object_scalar : public cdef_object_base { public: @@ -367,11 +460,18 @@ return obj; } + cdef_object_rep* copy (void) const + { return new handle_cdef_object (*this); } + bool is_valid (void) const { return true; } +protected: + // Restricted copying! + handle_cdef_object (const handle_cdef_object& obj) + : cdef_object_scalar (obj) { } + private: - // No copying - handle_cdef_object (const handle_cdef_object&); + // No assignment handle_cdef_object& operator = (const handle_cdef_object&); }; @@ -385,10 +485,9 @@ ~value_cdef_object (void); cdef_object_rep* clone (void) const - { - value_cdef_object* obj = new value_cdef_object (*this); - return obj; - } + { return new value_cdef_object (*this); } + + cdef_object_rep* copy (void) const { return clone (); } bool is_valid (void) const { return true; } @@ -412,10 +511,12 @@ public: cdef_class_rep (void) : handle_cdef_object (), member_count (0), handle_class (false), - object_count (0) { } + object_count (0), meta (false) { } cdef_class_rep (const std::list& superclasses); + cdef_object_rep* copy (void) const { return new cdef_class_rep (*this); } + bool is_class (void) const { return true; } std::string get_name (void) const @@ -423,6 +524,10 @@ void set_name (const std::string& nm) { put ("Name", nm); } + bool is_abstract (void) const { return get ("Abstract").bool_value (); } + + bool is_sealed (void) const { return get ("Sealed").bool_value (); } + cdef_method find_method (const std::string& nm, bool local = false); void install_method (const cdef_method& meth); @@ -449,6 +554,8 @@ octave_value construct (const octave_value_list& args); + cdef_object construct_object (const octave_value_list& args); + void initialize_object (cdef_object& obj); void run_constructor (cdef_object& obj, const octave_value_list& args); @@ -478,6 +585,10 @@ delete this; } + void mark_as_meta_class (void) { meta = true; } + + bool is_meta_class (void) const { return meta; } + private: void load_all_methods (void); @@ -521,11 +632,22 @@ // The number of objects of this class. octave_refcount object_count; + // TRUE if this class is a built-in meta class. + bool meta; + // Utility iterator typedef's. typedef std::map::iterator method_iterator; typedef std::map::const_iterator method_const_iterator; typedef std::map::iterator property_iterator; typedef std::map::const_iterator property_const_iterator; + + private: + cdef_class_rep (const cdef_class_rep& c) + : handle_cdef_object (c), directory (c.directory), + method_map (c.method_map), property_map (c.property_map), + member_count (c.member_count), handle_class (c.handle_class), + implicit_ctor_list (c.implicit_ctor_list), + object_count (c.object_count), meta (c.meta) { } }; public: @@ -584,6 +706,10 @@ string_vector get_names (void) { return get_rep ()->get_names (); } + bool is_abstract (void) const { return get_rep ()->is_abstract (); } + + bool is_sealed (void) const { return get_rep ()->is_sealed (); } + void set_directory (const std::string& dir) { get_rep ()->set_directory (dir); } @@ -614,6 +740,9 @@ octave_value construct (const octave_value_list& args) { return get_rep ()->construct (args); } + cdef_object construct_object (const octave_value_list& args) + { return get_rep ()->construct_object (args); } + void initialize_object (cdef_object& obj) { get_rep ()->initialize_object (obj); } @@ -626,6 +755,10 @@ bool is_handle_class (void) const { return get_rep ()->is_handle_class (); } + void mark_as_meta_class (void) { get_rep ()->mark_as_meta_class (); } + + bool is_meta_class (void) const { return get_rep ()->is_meta_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; } @@ -672,6 +805,8 @@ class cdef_property : public cdef_object { + friend cdef_class; + private: class @@ -681,6 +816,8 @@ cdef_property_rep (void) : handle_cdef_object () { } + cdef_object_rep* copy (void) const { return new cdef_property_rep (*this); } + bool is_property (void) const { return true; } std::string get_name (void) const { return get("Name").string_value (); } @@ -689,19 +826,17 @@ bool is_constant (void) const { return get("Constant").bool_value (); } - octave_value get_value (void) const { return default_value; } + octave_value get_value (void) const { return get ("DefaultValue"); } octave_value get_value (const cdef_object& obj); - void set_value (const octave_value& val) { default_value = val; } - void set_value (cdef_object& obj, const octave_value& val); private: - bool is_recursive_set (const cdef_object& obj) const; + cdef_property_rep (const cdef_property_rep& p) + : handle_cdef_object (p) { } - private: - octave_value default_value; + bool is_recursive_set (const cdef_object& obj) const; }; public: @@ -738,8 +873,6 @@ void set_value (cdef_object& obj, const octave_value& val) { get_rep ()->set_value (obj, val); } - void set_value (const octave_value& val) { get_rep ()->set_value (val); } - bool check_get_access (void) const; bool check_set_access (void) const; @@ -759,6 +892,8 @@ class cdef_method : public cdef_object { + friend cdef_class; + private: class @@ -767,6 +902,8 @@ public: cdef_method_rep (void) : handle_cdef_object () { } + cdef_object_rep* copy (void) const { return new cdef_method_rep(*this); } + bool is_method (void) const { return true; } std::string get_name (void) const { return get("Name").string_value (); } @@ -787,6 +924,9 @@ bool is_constructor (void) const; private: + cdef_method_rep (const cdef_method_rep& m) + : handle_cdef_object (m), function (m.function) { } + void check_method (void); private: @@ -907,6 +1047,16 @@ } } +inline cdef_object_rep* +cdef_object_base::make_array (void) const +{ + cdef_object_rep* r = new cdef_object_array (); + + r->set_class (get_class ()); + + return r; +} + inline cdef_method cdef_class::find_method (const std::string& nm, bool local) { return get_rep ()->find_method (nm, local); } @@ -918,6 +1068,8 @@ class cdef_package : public cdef_object { + friend cdef_class; + private: class @@ -926,6 +1078,8 @@ public: cdef_package_rep (void) : handle_cdef_object (), member_count (0) { } + cdef_object_rep* copy (void) const { return new cdef_package_rep (*this); } + bool is_package (void) const { return true; } std::string get_name (void) const { return get("Name").string_value (); } @@ -976,6 +1130,12 @@ typedef std::map::const_iterator function_const_iterator; typedef std::map::iterator package_iterator; typedef std::map::const_iterator package_const_iterator; + + private: + cdef_package_rep (const cdef_package_rep& p) + : handle_cdef_object (p), class_map (p.class_map), + function_map (p.function_map), package_map (p.package_map), + member_count (p.member_count) { } }; public: @@ -1053,7 +1213,7 @@ { return new octave_classdef (object.clone ()); } octave_base_value* empty_clone (void) const - { return new octave_classdef (); } + { return new octave_classdef (object.empty_clone ()); } cdef_object get_object (void) const { return object; } @@ -1091,6 +1251,11 @@ const std::list& idx, const octave_value& rhs); + octave_value + undef_subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs); + string_vector map_keys (void) const { return object.map_keys (); } dim_vector dims (void) const { return dim_vector (1, 1); }