changeset 15913:8521321604df classdef

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.
author Michael Goffioul <michael.goffioul@gmail.com>
date Tue, 08 Jan 2013 12:34:30 -0500
parents b18b7e560236
children f97a746e4544
files libinterp/octave-value/ov-classdef.cc libinterp/octave-value/ov-classdef.h
diffstat 2 files changed, 486 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- 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<std::string, cdef_class> all_classes;
 static std::map<std::string, cdef_package> 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<cdef_class> (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<octave_value_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<octave_value_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<idx_vector> 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<cdef_object> 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<octave_value_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<idx_vector> 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<cdef_object> rhs_mat;
+
+                      if (! rhs_obj.is_array ())
+                        {
+                          rhs_mat = Array<cdef_object> (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<cdef_class>& 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<cdef_class> ());
+              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<cdef_class> ());
+              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<cdef_class> ());
+              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"));
--- 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<cdef_object> array_value (void) const
+    {
+      gripe_invalid_object ("array_value");
+      return Array<cdef_object> ();
+    }
+
   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<cdef_object> 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<octave_value_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<cdef_object>& 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<cdef_object> array_value (void) const { return array; }
+
+  octave_value_list
+  subsref (const std::string& type, const std::list<octave_value_list>& idx,
+           int nargout, size_t& skip, const cdef_class& context);
+
+  octave_value
+  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
+            const octave_value& rhs);
+
+private:
+  Array<cdef_object> 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<cdef_class>& 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<octave_idx_type> object_count;
 
+    // TRUE if this class is a built-in meta class.
+    bool meta;
+
     // Utility iterator typedef's.
     typedef std::map<std::string,cdef_method>::iterator method_iterator;
     typedef std::map<std::string,cdef_method>::const_iterator method_const_iterator;
     typedef std::map<std::string,cdef_property>::iterator property_iterator;
     typedef std::map<std::string,cdef_property>::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<std::string, octave_value>::const_iterator function_const_iterator;
     typedef std::map<std::string, cdef_package>::iterator package_iterator;
     typedef std::map<std::string, cdef_package>::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<octave_value_list>& idx,
                          const octave_value& rhs);
 
+  octave_value
+  undef_subsasgn (const std::string& type,
+                  const std::list<octave_value_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); }