changeset 15869:5e5705b3e505 classdef

Implement some embryonic handle-classdef semantic. * libinterp/octave-value/ov-classdef.h (cdef_object_rep::subsasgn, handle_cdef_object::subsasgn, octave_classdef::subsasgn): New method declarations. (handle_cdef_object::~handle_cdef_object): New destructor declaration. (cdef_class::cdef_class_rep::handle_class): New boolean field. (cdef_class::cdef_class_rep::cdef_class_rep): Initialize it. (cdef_class::cdef_class_rep::mark_as_handle_class, cdef_class::cdef_class_rep::is_handle_class, cdef_class::mark_as_handle_class, cdef_class::is_handle_class): Manipulate it. (cdef_class::cdef_class_rep::get_name): New method. (cdef_class::get_name): Use it. (cdef_class::cdef_class_rep::initialize_object, cdef_class::cdef_class_rep::subsref_meta, cdef_class::cdef_class_rep::run_constructor, cdef_class::cdef_class_rep::construct, cdef_class:initialize_object, cdef_class::subsref_meta, cdef_class::run_constructor, cdef_class::construct): New methods. (cdef_class::cdef_class_rep::find_method, cdef_class::find_method): Add "local" argument. (cdef_class::cdef_class_rep::find_names, cdef_class::find_names): Change signature to use std::set and a boolean flag. (cdef_class::cdef_class_rep::find_methods, cdef_class::find_methods): Change signature to use a boolean flag as second argument. (cdef_class::make_meta_class): New static method. (cdef_class::get_method_function, cdef_class::get_constructor_function): New methods. (cdef_property::cdef_property_rep::set_value, cdef_property::set_value): Make cdef_object argument non const. (cdef_property::cder_property_rep::is_relative_set): New method. (cdef_property::get_get_access, cdef_property::get_set_access): Delete methods. (cdef_property::check_get_access, cdef_property::check_set_access): Remove string argument. (cdef_method::get_access): Delete method. (cdef_method::check_access): Remove string argument. * libinterp/octave-value/ov-classdef.cc (gripe_method_access, gripe_property_access): Support access specified as cell array of classes. (make_function_of_class): New static function(s). (check_access (std::string, std::string), superclass_access): Remove static functions. (lookup_class): Use symbol_table when class hasn't been loaded yet. (lookup_classes): Returns std::list<cdef_class> instead of Cell. (class_get_superclasses, class_get_inferiorclasses): Use it. (to_ov (const std::list<cdef_class>&)): New static function. (get_class_context, check_access (const cdef_class&, const octave_value&)): Likewise. (handle_cdef_object::subsref): Use new signature of access check methods. (property_get_defaultvalue): New built-in property accessor. (make_class): Change signature to support multiple inheritance. Set "Sealed" to false by default. Determine value for HandleCompatible property and handle-class representation. (make_property): Take cdef_class as first argument. Add DefaultValue and HasDefault properties. Call make_function_of_class for property accessors. (make_attribute): Take cdef_class as first argument. (make_method): Likewise. Call make_function_of_class. (make_method (octave_builtin::fcn)): Do no construct a function handle object. (octave_classdef::subsasgn, handle_cdef_object::subsasgn): New method. (class octave_classdef_proxy): New class. (cdef_class::get_method_function): Use it, new method. (handle_cdef_object::~handle_cdef_object): New destructor. (cdef_class_rep::find_method): New boolean "local" argument. When true, only look into the current class, not in superclasses. (cdef_class_rep::find_methods): New signature. (cdef_class_rep::get_methods): Use it. (cdef_class_rep::find_properties): New signature. (cdef_class_rep::get_properties): Use it. (cdef_class_rep::find_names): New signature. (cdef_class_rep::get_names): Use it. (cdef_class_rep::subsref_meta, cdef_class_rep::initialize_object, cdef_class_rep::run_constructor, cdef_class_rep::construct): New methods. (compute_attribute_value, attribute_to_string): New static functions. (cdef_class::make_meta_class): Change signature, non const argument. Implement it. (cdef_property_rep::get_value): Do not check access here. (cdef_property_rep::set_value, cdef_property_rep::is_recursive_set): New method. (cdef_property_rep::check_get_access, cdef_property_rep::check_set_access, cdef_method_rep::check_access): Use static check_access utility function. (install_classdef): Adapt to change of signature of make_class. Mark meta classes as sealed. Add HandleCompatible property to meta.class. Add DefaultValue and HasDefault properties to meta.property. * libinterp/parse-tree/pt-classdef.h (tree_classdef::make_meta_class): Change return type to (octave_function *). * libinterp/parse-tree/pt-classdef.cc (tree_classdef::make_meta_class): Likewise. Call cdef_class::get_constructor_function. * libinterp/parse-tree/oct-parse.yy (parse_fcn_file): Adapt to new signature of tree_classdef::make_meta_class. * libinterp/octave-value/ov-fcn.h (octave_function::is_classdef_constructor): New virtual method. * libinterp/octave-value/ov-usr-fcn.h (octave_user_function::class_ctor_type): New private enum. (octave_user_function::mark_as_class_constructor, octave_user_function::is_class_constructor): Use it. (octave_user_function::mark_as_classdef_constructor, octave_user_function::is_classdef_constructor): New methods. (octave_user_function::class_constructor): Turn into class_ctor_type. * libinterp/octave-value/of-usr-fcn.cc (octave_user_function::octave_user_function): Initialize class_constructor. (octave_user_function::do_multi_index_op): When function is a classdef constructor, extract the first argument and use it to populate the first output argument.
author Michael Goffioul <michael.goffioul@gmail.com>
date Tue, 01 Jan 2013 19:42:17 -0500
parents 622f3f794162
children 2b6fe094e615
files libinterp/octave-value/ov-classdef.cc libinterp/octave-value/ov-classdef.h libinterp/octave-value/ov-fcn.h libinterp/octave-value/ov-usr-fcn.cc libinterp/octave-value/ov-usr-fcn.h libinterp/parse-tree/oct-parse.yy libinterp/parse-tree/pt-classdef.cc libinterp/parse-tree/pt-classdef.h
diffstat 8 files changed, 1075 insertions(+), 232 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/octave-value/ov-classdef.cc	Sun Dec 23 19:03:38 2012 -0500
+++ b/libinterp/octave-value/ov-classdef.cc	Tue Jan 01 19:42:17 2013 -0500
@@ -32,6 +32,9 @@
 #include "ov-fcn-handle.h"
 #include "ov-typeinfo.h"
 #include "pt-classdef.h"
+#include "pt-walk.h"
+#include "symtab.h"
+#include "toplev.h"
 
 static std::map<std::string, cdef_class> all_classes;
 static std::map<std::string, cdef_package> all_packages;
@@ -39,23 +42,78 @@
 static void
 gripe_method_access (const std::string& from, const cdef_method& meth)
 {
+  octave_value acc = meth.get ("Access");
+  std::string acc_s;
+
+  if (acc.is_string ())
+    acc_s = acc.string_value ();
+  else
+    acc_s = "class-restricted";
+
   error ("%s: method `%s' has %s access and cannot be run in this context",
-	 from.c_str (), meth.get_name ().c_str (),
-	 meth.get_access ().c_str ());
+	 from.c_str (), meth.get_name ().c_str (), acc_s.c_str ());
 }
 
 static void
 gripe_property_access (const std::string& from, const cdef_property& prop,
 		       bool is_set = false)
 {
+  octave_value acc = prop.get (is_set ? "SetAccess" : "GetAccess");
+  std::string acc_s;
+
+  if (acc.is_string ())
+    acc_s = acc.string_value ();
+  else
+    acc_s = "class-restricted";
+
   if (is_set)
     error ("%s: property `%s' has %s access and cannot be set in this context",
-	   from.c_str (), prop.get_name ().c_str (),
-	   prop.get_set_access ().c_str ());
+	   from.c_str (), prop.get_name ().c_str (), acc_s.c_str ());
   else
     error ("%s: property `%s' has %s access and cannot be obtained in this context",
-	   from.c_str (), prop.get_name ().c_str (),
-	   prop.get_get_access ().c_str ());
+	   from.c_str (), prop.get_name ().c_str (), acc_s.c_str ());
+}
+
+static std::string
+get_base_name (const std::string& nm)
+{
+  std::string::size_type pos = nm.find_last_of ('.');
+
+  if (pos != std::string::npos)
+    return nm.substr (pos + 1);
+
+  return nm;
+}
+
+static void
+make_function_of_class (const std::string& class_name,
+                        const octave_value& fcn)
+{
+  octave_function *of = fcn.function_value ();
+
+  if (! error_state)
+    {
+      of->stash_dispatch_class (class_name);
+
+      octave_user_function *uf = of->user_function_value (true);
+
+      if (! error_state && uf)
+        {
+          if (get_base_name (class_name) == uf->name ())
+            {
+              uf->mark_as_class_constructor ();
+              uf->mark_as_classdef_constructor ();
+            }
+          else
+            uf->mark_as_class_method ();
+        }
+    }
+}
+
+static void
+make_function_of_class (const cdef_class& cls, const octave_value& fcn)
+{
+  make_function_of_class (cls.get_name (), fcn);
 }
 
 static octave_value
@@ -78,37 +136,6 @@
   return val.subsref (type, idx, nargout);
 }
 
-static bool
-check_access (const std::string& req, const std::string& acc)
-{
-  if (req == "private")
-    return true;
-  else if (req == "protected")
-    return (acc != "private");
-  else
-    return (acc == "public");
-}
-
-static std::string
-get_base_name (const std::string& nm)
-{
-  std::string::size_type pos = nm.find_last_of ('.');
-
-  if (pos != std::string::npos)
-    return nm.substr (pos + 1);
-
-  return nm;
-}
-
-static std::string
-superclass_access (const std::string& acc)
-{
-  if (acc == "public")
-    return acc;
-  else
-    return "protected";
-}
-
 static cdef_class
 lookup_class (const std::string& name, bool error_if_not_found = true)
 {
@@ -116,7 +143,16 @@
 
   if (it == all_classes.end ())
     {
-      // FIXME: should look into load-path
+      // FIXME: implement this properly
+
+      octave_value ov_cls = symbol_table::find (name);
+
+      if (ov_cls.is_defined ())
+        it = all_classes.find (name);
+    }
+
+  if (it == all_classes.end ())
+    {
       if (error_if_not_found)
 	error ("class not found: %s", name.c_str ());
     }
@@ -138,22 +174,38 @@
   return cdef_class ();
 }
 
-static Cell
+static std::list<cdef_class>
 lookup_classes (const Cell& cls_names)
 {
-  Cell cls (cls_names.numel (), 1);
+  std::list<cdef_class> retval;
 
   for (int i = 0; i < cls_names.numel (); i++)
     {
       cdef_class c = lookup_class (cls_names(i).string_value ());
 
       if (! error_state)
-	cls(i) = to_ov (c);
+        retval.push_back (c);
       else
-	return Cell ();
+        {
+          retval.clear ();
+          break;
+        }
     }
 
-  return cls;
+  return retval;
+}
+
+static octave_value
+to_ov (const std::list<cdef_class>& class_list)
+{
+  Cell cls (class_list.size (), 1);
+  int i = 0;
+
+  for (std::list<cdef_class>::const_iterator it = class_list.begin ();
+       it != class_list.end (); ++it, ++i)
+    cls(i) = to_ov (*it);
+
+  return octave_value (cls);
 }
 
 static bool
@@ -199,6 +251,72 @@
   return retval;
 }
 
+static cdef_class
+get_class_context (void)
+{
+  cdef_class cls;
+
+  octave_function* fcn = octave_call_stack::current ();
+
+  if (fcn &&
+      (fcn->is_class_method ()
+       || fcn->is_class_constructor ()
+       || fcn->is_anonymous_function_of_class ()
+       || (fcn->is_private_function ()
+           && ! fcn->dispatch_class ().empty ())))
+    cls = lookup_class (fcn->dispatch_class ());
+
+  return cls;
+}
+
+static bool
+check_access (const cdef_class& cls, const octave_value& acc)
+{
+  if (acc.is_string ())
+    {
+      std::string acc_s = acc.string_value ();
+
+      if (acc_s == "public")
+        return true;
+
+      cdef_class ctx = get_class_context ();
+
+      if (acc_s == "private")
+        return (ctx == cls);
+      else if (acc_s == "protected")
+        return is_superclass (cls, ctx);
+      else
+        panic_impossible ();
+    }
+  else if (acc.is_cell ())
+    {
+      Cell acc_c = acc.cell_value ();
+
+      cdef_class ctx = get_class_context ();
+
+      if (ctx == cls)
+        return true;
+
+      for (int i = 0; ! error_state && i < acc.numel (); i++)
+        {
+          cdef_class acc_cls (to_cdef (acc_c(i)));
+
+          if (! error_state)
+            {
+              if (is_superclass (acc_cls, ctx))
+                return true;
+            }
+        }
+
+      return false;
+    }
+  else
+    error ("invalid property/method access in class `%s'",
+           cls.get_name ().c_str ());
+  
+  return false;
+}
+
 static octave_value_list
 class_get_methods (const octave_value_list& args, int /* nargout */)
 {
@@ -226,7 +344,7 @@
 
       Cell classes = cls.get ("SuperClasses").cell_value ();
 
-      retval(0) = lookup_classes (classes);
+      retval(0) = to_ov (lookup_classes (classes));
     }
 
   return retval;
@@ -244,7 +362,7 @@
 
       Cell classes = cls.get ("InferiorClasses").cell_value ();
 
-      retval(0) = lookup_classes (classes);
+      retval(0) = to_ov (lookup_classes (classes));
     }
 
   return retval;
@@ -289,8 +407,7 @@
 
 	      if (meth.ok ())
 		{
-		  // FIXME: can the context be something else?
-		  if (meth.check_access ("public"))
+		  if (meth.check_access ())
 		    {
 		      if (meth.is_static ())
 			retval = meth.execute (args.splice (0, 2), nargout);
@@ -336,8 +453,7 @@
 
 	      if (prop.ok ())
 		{
-		  // FIXME: can the context be something else?
-		  if (prop.check_get_access ("public"))
+		  if (prop.check_get_access ())
 		    {
 		      if (prop.is_constant ())
 			retval(0) = prop.get_value ();
@@ -396,6 +512,26 @@
 META_CLASS_CMP (eq, clsa, clsb, operator==)
 META_CLASS_CMP (ne, clsa, clsb, operator!=)
 
+octave_value_list
+property_get_defaultvalue (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1 && args(0).type_name () == "object")
+    {
+      cdef_property prop (to_cdef (args(0)));
+
+      retval(0) = prop.get ("DefaultValue");
+
+      if (! retval(0).is_defined ())
+        error_with_id ("Octave:class:NotDefaultDefined",
+                       "no default value for property `%s'",
+                       prop.get_name ().c_str ());
+    }
+
+  return retval;
+}
+
 static octave_value_list
 handle_delete (const octave_value_list& /* args */, int /* nargout */)
 {
@@ -407,11 +543,12 @@
 }
 
 static cdef_class
-make_class (const std::string& name, const std::string& super = std::string())
+make_class (const std::string& name,
+            const std::list<cdef_class>& super_list = std::list<cdef_class> (),
+            const std::list<std::string>& super_name_list = std::list<std::string> ())
 {
   cdef_class cls ("meta.class");
 
-  all_classes[name] = cls;
   cls.put ("ConstructOnLoad", false);
   cls.put ("ContainingPackage", Matrix ());
   cls.put ("Description", std::string ());
@@ -422,17 +559,68 @@
   cls.put ("Methods", Cell ());
   cls.put ("Name", name);
   cls.put ("Properties", Cell ());
-  cls.put ("Sealed", true);
-  if (super.empty ())
-    cls.put ("SuperClasses", Cell ());
+  cls.put ("Sealed", false);
+  if (super_name_list.size () == super_list.size ())
+    cls.put ("SuperClasses", Cell (super_name_list));
+  else
+    {
+      std::list<std::string> snamelist;
+
+      for (std::list<cdef_class>::const_iterator it = super_list.begin ();
+           it != super_list.end (); ++it)
+        snamelist.push_back (it->get_name ());
+
+      cls.put ("SuperClasses", Cell (snamelist));
+    }
+
+  if (name == "handle")
+    {
+      cls.put ("HandleCompatible", true);
+      cls.mark_as_handle_class ();
+    }
+  else if (super_list.empty ())
+    {
+      cls.put ("HandleCompatible", false);
+    }
   else
-    cls.put ("SuperClasses", Cell (octave_value (super)));
+    {
+      bool all_handle_compatible = true;
+      bool has_handle_class = false;
+
+      for (std::list<cdef_class>::const_iterator it = super_list.begin ();
+           it != super_list.end (); ++it)
+        {
+          all_handle_compatible = all_handle_compatible && it->get ("HandleCompatible").bool_value ();
+          has_handle_class = has_handle_class || it->is_handle_class ();
+        }
+
+      if (has_handle_class && ! all_handle_compatible)
+        ::error ("%s: cannot mix handle and non-HandleCompatible classes",
+                 name.c_str ());
+      else
+        {
+          cls.put ("HandleCompatible", all_handle_compatible);
+          if (has_handle_class)
+            cls.mark_as_handle_class ();
+        }
+    }
+
+  if (error_state)
+    return cdef_class ();
+
+  all_classes[name] = cls;
 
   return cls;
 }
 
+static cdef_class
+make_class (const std::string& name, const cdef_class& super)
+{
+  return make_class (name, std::list<cdef_class> (1, super));
+}
+
 static cdef_property
-make_property (const cdef_object& cls, const std::string& name,
+make_property (const cdef_class& cls, const std::string& name,
 	       const octave_value& get_method = Matrix (),
 	       const std::string& get_access = "public",
 	       const octave_value& set_method = Matrix (),
@@ -457,19 +645,29 @@
   prop.put ("GetMethod", get_method);
   prop.put ("SetMethod", set_method);
   prop.put ("DefiningClass", to_ov (cls));
+  prop.put ("DefaultValue", octave_value ());
+  prop.put ("HasDefault", false);
+
+  std::string class_name = cls.get_name ();
+
+  if (! get_method.is_empty ())
+    make_function_of_class (class_name, get_method);
+  if (! set_method.is_empty ())
+    make_function_of_class (class_name, set_method);
 
   return prop;
 }
 
 inline cdef_property
-make_attribute (const cdef_object& cls, const std::string& name)
+make_attribute (const cdef_class& cls, const std::string& name)
 {
   return make_property (cls, name, Matrix (), "public", Matrix (), "private");
 }
 
 static cdef_method
-make_method (const cdef_object& cls, const std::string& name, const octave_value& fcn,
-	     const std::string& m_access = "public", bool is_static = false)
+make_method (const cdef_class& cls, const std::string& name,
+             const octave_value& fcn,const std::string& m_access = "public",
+             bool is_static = false)
 {
   cdef_method meth ("meta.method");
 
@@ -483,20 +681,21 @@
   meth.put ("Sealed", true);
   meth.put ("Static", is_static);
 
+  make_function_of_class (cls, fcn);
+
   meth.set_function (fcn);
 
   return meth;
 }
 
 inline cdef_method
-make_method (const cdef_object& cls, const std::string& name, octave_builtin::fcn ff,
-	     const std::string& m_access = "public", bool is_static = false)
+make_method (const cdef_class& cls, const std::string& name,
+             octave_builtin::fcn ff, const std::string& m_access = "public",
+             bool is_static = false)
 {
   octave_value fcn (new octave_builtin (ff, name));
 
-  octave_value fcn_handle (new octave_fcn_handle (fcn, name));
-
-  return make_method (cls, name, fcn_handle, m_access, is_static);
+  return make_method (cls, name, fcn, m_access, is_static);
 }
 
 static cdef_package
@@ -512,6 +711,8 @@
   return pack;
 }
 
+//----------------------------------------------------------------------------
+
 DEFINE_OCTAVE_ALLOCATOR (octave_classdef);
 
 int octave_classdef::t_id (-1);
@@ -525,6 +726,72 @@
     (octave_classdef::t_name, "<unknown>", octave_value (new octave_classdef ()));
 }
 
+octave_value_list
+octave_classdef::subsref (const std::string& type,
+                          const std::list<octave_value_list>& idx,
+                          int nargout)
+{
+  int skip = 0;
+  octave_value_list retval;
+
+  // FIXME: should check "subsref" method first
+
+  retval = object.subsref (type, idx, nargout, skip);
+
+  if (! error_state)
+    {
+      if (type.length () > skip && idx.size () > skip)
+	retval = retval(0).next_subsref (nargout, type, idx, skip);
+    }
+
+  return retval;
+}
+
+octave_value
+octave_classdef::subsasgn (const std::string& type,
+                           const std::list<octave_value_list>& idx,
+                           const octave_value& rhs)
+{
+  return object.subsasgn (type, idx, rhs);
+}
+
+//----------------------------------------------------------------------------
+
+class octave_classdef_proxy : public octave_function
+{
+public:
+  octave_classdef_proxy (const cdef_class& _klass)
+    : klass (_klass) { }
+
+  ~octave_classdef_proxy (void) { }
+
+  octave_value_list
+  subsref (const std::string& type,
+           const std::list<octave_value_list>& idx,
+           int nargout)
+    { return klass.subsref_meta (type, idx, nargout); }
+
+  octave_value
+  subsref (const std::string& type,
+           const std::list<octave_value_list>& idx)
+    {
+      octave_value_list retval;
+
+      retval = subsref (type, idx, 1);
+
+      return (retval.length () > 0 ? retval(0) : octave_value ());
+    }
+
+  octave_value_list
+  do_multi_index_op (int /* nargout */, const octave_value_list& /* idx */)
+    { return to_ov (klass); }
+
+private:
+  cdef_class klass;
+};
+
+//----------------------------------------------------------------------------
+
 cdef_class
 cdef_object_rep::get_class (void) const
 {
@@ -544,6 +811,11 @@
   return string_vector ();
 }
 
+handle_cdef_object::~handle_cdef_object (void)
+{
+  printf ("deleting %s object (handle)\n", cname.c_str ());
+}
+
 octave_value_list
 handle_cdef_object::subsref (const std::string& type,
 			     const std::list<octave_value_list>& idx,
@@ -564,17 +836,11 @@
 	{
 	  std::string name = (idx.front ())(0).string_value ();
 
-	  // FIXME: get the right context; context should also
-	  // be linked to the current executing class (if any)
-	  // such that protected/private methods found in inherited
-	  // classes are correctly resolved.
-	  std::string context = "public";
-
 	  cdef_method meth = cls.find_method (name);
 
 	  if (meth.ok ())
 	    {
-	      if (meth.check_access (context))
+	      if (meth.check_access ())
 		{
 		  int _nargout = (type.length () > 2 ? 1 : nargout);
 
@@ -609,7 +875,7 @@
 
 	      if (prop.ok ())
 		{
-		  if (prop.check_get_access (context))
+		  if (prop.check_get_access ())
 		    {
 		      refcount++;
 		      retval(0) = prop.get_value (cdef_object (this));
@@ -632,8 +898,67 @@
   return retval;
 }
 
+octave_value
+handle_cdef_object::subsasgn (const std::string& type,
+                              const std::list<octave_value_list>& idx,
+                              const octave_value& rhs)
+{
+  octave_value retval;
+
+  cdef_class cls = get_class ();
+
+  switch (type[0])
+    {
+    case '.':
+        {
+          std::string name = (idx.front ())(0).string_value ();
+
+          if (! error_state)
+            {
+              cdef_property prop = cls.find_property (name);
+
+              if (prop.ok ())
+                {
+                  if (type.length () == 1)
+                    {
+                      if (prop.check_set_access ())
+                        {
+                          refcount++;
+
+                          cdef_object obj (this);
+
+                          prop.set_value (obj, rhs);
+
+                          if (! error_state)
+                            retval = to_ov (obj);
+                        }
+                      else
+                        gripe_property_access ("subsasgn", prop, true);
+                    }
+                  else
+                    {
+                    }
+
+                  if (! error_state)
+                    {
+                    }
+                }
+              else
+                error ("subsasgn: unknown property: %s", name.c_str ());
+            }
+        }
+      break;
+
+    default:
+      panic_impossible ();
+      break;
+    }
+
+  return retval;
+}
+
 cdef_method
-cdef_class::cdef_class_rep::find_method (const std::string& nm)
+cdef_class::cdef_class_rep::find_method (const std::string& nm, bool local)
 {
   method_iterator it = method_map.find (nm);
 
@@ -651,21 +976,24 @@
 	return meth;
     }
 
-  // Look into superclasses
-
-  Cell super_classes = get ("SuperClasses").cell_value ();
+  if (! local)
+    {
+      // Look into superclasses
 
-  for (int i = 0; i < super_classes.numel (); i++)
-    {
-      cdef_class cls = lookup_class (super_classes(i).string_value ());
+      Cell super_classes = get ("SuperClasses").cell_value ();
 
-      if (! error_state)
-	{
-	  cdef_method meth = cls.find_method (nm);
+      for (int i = 0; i < super_classes.numel (); i++)
+        {
+          cdef_class cls = lookup_class (super_classes(i).string_value ());
 
-	  if (meth.ok ())
-	    return meth;
-	}
+          if (! error_state)
+            {
+              cdef_method meth = cls.find_method (nm);
+
+              if (meth.ok ())
+                return meth;
+            }
+        }
     }
 
   return cdef_method ();
@@ -688,22 +1016,17 @@
 {
   std::map<std::string,cdef_method> meths;
 
-  std::map<std::string,int> count;
-
-  count["public"] = count["protected"] = count["private"] = 0;
-
-  find_methods (meths, count);
+  find_methods (meths, false);
 
   if (! error_state)
     {
-      Cell c (count["public"] + count["protected"], 1);
+      Cell c (meths.size (), 1);
 
       int idx = 0;
 
       for (std::map<std::string,cdef_method>::const_iterator it = meths.begin ();
-	   it != meths.end (); ++it)
-	if (::check_access ("protected", it->second.get_access ()))
-	  c (idx++, 0) = to_ov (it->second);
+	   it != meths.end (); ++it, ++idx)
+        c (idx, 0) = to_ov (it->second);
 
       return c;
     }
@@ -712,24 +1035,35 @@
 }
 
 void
-cdef_class::cdef_class_rep::find_methods (std::map<std::string,cdef_method>& meths,
-					  std::map<std::string,int>& count)
+cdef_class::cdef_class_rep::find_methods (std::map<std::string, cdef_method>& meths,
+                                          bool only_inherited)
 {
   load_all_methods ();
 
   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 (meths.find (nm) == meths.end ())
-	{
-	  std::string acc = it->second.get_access ();
+      if (nm != cls_name)
+        {
+          if (meths.find (nm) == meths.end ())
+            {
+              if (only_inherited)
+                {
+                  octave_value acc = it->second.get ("Access");
 
-	  meths[nm] = it->second;
-	  count[acc]++;
-	}
+                  if (! acc.is_string ()
+                      || acc.string_value () == "private")
+                    continue;
+                }
+
+              meths[nm] = it->second;
+            }
+        }
     }
 
   // Look into superclasses
@@ -741,7 +1075,7 @@
       cdef_class cls = lookup_class (super_classes(i).string_value ());
 
       if (! error_state)
-	cls.get_rep ()->find_methods (meths, count);
+	cls.get_rep ()->find_methods (meths, true);
       else
 	break;
     }
@@ -791,22 +1125,17 @@
 {
   std::map<std::string,cdef_property> props;
 
-  std::map<std::string,int> count;
-
-  count["public"] = count["protected"] = count["private"] = 0;
-
-  find_properties (props, count);
+  find_properties (props, false);
 
   if (! error_state)
     {
-      Cell c (count["public"] + count["protected"], 1);
+      Cell c (props.size (), 1);
 
       int idx = 0;
 
       for (std::map<std::string,cdef_property>::const_iterator it = props.begin ();
-	   it != props.end (); ++it)
-	if (::check_access ("protected", it->second.get_get_access ()))
-	  c (idx++, 0) = to_ov (it->second);
+	   it != props.end (); ++it, ++idx)
+        c (idx, 0) = to_ov (it->second);
 
       return c;
     }
@@ -816,20 +1145,27 @@
 
 void
 cdef_class::cdef_class_rep::find_properties (std::map<std::string,cdef_property>& props,
-					     std::map<std::string,int>& count)
+                                             bool only_inherited)
 {
   property_const_iterator it;
 
-  for (it = property_map.begin (); it != property_map.end (); ++it)
+  for (it = property_map.begin (); ! error_state && it != property_map.end ();
+       ++it)
     {
       std::string nm = it->second.get_name ();
 
       if (props.find (nm) == props.end ())
 	{
-	  std::string acc = it->second.get_get_access ();
+          if (only_inherited)
+            {
+              octave_value acc = it->second.get ("GetAccess");
+
+              if (! acc.is_string ()
+                  || acc.string_value () == "private")
+                continue;
+            }
 
 	  props[nm] = it->second;
-	  count[acc]++;
 	}
     }
 
@@ -837,61 +1173,72 @@
 
   Cell super_classes = get ("SuperClasses").cell_value ();
 
-  for (int i = 0; i < super_classes.numel (); i++)
+  for (int i = 0; ! error_state && i < super_classes.numel (); i++)
     {
       cdef_class cls = lookup_class (super_classes(i).string_value ());
 
       if (! error_state)
-	cls.get_rep ()->find_properties (props, count);
+	cls.get_rep ()->find_properties (props, true);
       else
 	break;
     }
 }
 
 void
-cdef_class::cdef_class_rep::find_names (std::map<std::string,std::string>& names,
-					std::map<std::string,int>& count)
+cdef_class::cdef_class_rep::find_names (std::set<std::string>& names,
+                                        bool all)
 {
   load_all_methods ();
 
+  std::string cls_name = get_base_name (get_name ());
+
   for (method_const_iterator it = method_map.begin ();
-       it != method_map.end(); ++it)
+       ! error_state && it != method_map.end(); ++it)
     {
       std::string nm = it->second.get_name ();
 
-      if (names.find (nm) == names.end ())
-	{
-	  std::string acc = it->second.get_access ();
+      if (nm != cls_name)
+        {
+          if (! all)
+            {
+              octave_value acc = it->second.get ("Access");
 
-	  names[nm] = acc;
-	  count[acc]++;
-	}
+              if (! acc.is_string()
+                  || acc.string_value () != "public")
+                continue;
+            }
+
+          names.insert (nm);
+        }
     }
 
   for (property_const_iterator it = property_map.begin ();
-       it != property_map.end (); ++it)
+       ! error_state && it != property_map.end (); ++it)
     {
       std::string nm = it->second.get_name ();
 
-      if (names.find (nm) == names.end ())
-	{
-	  std::string acc = it->second.get_get_access ();
+      if (! all)
+        {
+          octave_value acc = it->second.get ("GetAccess");
 
-	  names[nm] = acc;
-	  count[acc]++;
-	}
+          if (! acc.is_string()
+              || acc.string_value () != "public")
+            continue;
+        }
+
+      names.insert (nm);
     }
 
   // Look into superclasses
 
   Cell super_classes = get ("SuperClasses").cell_value ();
 
-  for (int i = 0; i < super_classes.numel (); i++)
+  for (int i = 0; ! error_state && i < super_classes.numel (); i++)
     {
       cdef_class cls = lookup_class (super_classes(i).string_value ());
 
       if (! error_state)
-	cls.get_rep ()->find_names (names, count);
+	cls.get_rep ()->find_names (names, all);
       else
 	break;
     }
@@ -900,25 +1247,18 @@
 string_vector
 cdef_class::cdef_class_rep::get_names (void)
 {
-  std::map<std::string,std::string> names;
-
-  std::map<std::string,int> count;
+  std::set<std::string> names;
 
-  count["public"] = count["protected"] = count["private"] = 0;
-
-  find_names (names, count);
+  find_names (names, false);
 
   if (! error_state)
     {
-      string_vector v (count["public"]);
+      string_vector v (names.size ());
 
       int idx = 0;
-      for (std::map<std::string,std::string>::const_iterator it = names.begin ();
-	   it != names.end (); ++it)
-	{
-	  if (it->second == "public")
-	      v[idx++] = it->first;
-	}
+      for (std::set<std::string>::const_iterator it = names.begin ();
+	   it != names.end (); ++it, ++idx)
+        v[idx] = *it;
 
       return v.sort (true);
     }
@@ -957,14 +1297,352 @@
     }
 }
 
+octave_value_list
+cdef_class::cdef_class_rep::subsref_meta (const std::string& type,
+                                          const std::list<octave_value_list>& idx,
+                                          int nargout)
+{
+  octave_value_list retval;
+
+  switch (type[0])
+    {
+    case '(':
+      // Constructor call
+      printf ("constructor\n");
+      retval(0) = construct (idx.front ());
+      break;
+    case '.':
+      // Static method, constant (or property?)
+      printf ("static method\n");
+      break;
+    }
+
+  if (! error_state)
+    {
+      if (type.length () > 1 && idx.size () > 1 && ! retval.empty ())
+	retval = retval(0).next_subsref (nargout, type, idx);
+    }
+
+  return retval;
+}
+
+void
+cdef_class::cdef_class_rep::initialize_object (cdef_object& obj)
+{
+  // Populate the object with default property values
+
+  std::list<cdef_class> super_classes = lookup_classes (get ("SuperClasses").cell_value ());
+
+  if (! error_state)
+    {
+      for (std::list<cdef_class>::iterator it = super_classes.begin ();
+           ! error_state && it != super_classes.end (); ++it)
+        it->initialize_object (obj);
+
+      if (! error_state)
+        {
+          for (property_const_iterator it = property_map.begin ();
+               ! error_state && it != property_map.end (); ++it)
+            {
+              if (! it->second.get ("Dependent").bool_value ())
+                {
+                  octave_value pvalue = it->second.get ("DefaultValue");
+
+                  if (pvalue.is_defined ())
+                    obj.put (it->first, pvalue);
+                  else
+                    obj.put (it->first, octave_value (Matrix ()));
+                }
+            }
+        }
+    }
+}
+
+void
+cdef_class::cdef_class_rep::run_constructor (cdef_object& obj,
+                                             const octave_value_list& args)
+{
+  // FIXME: Run constructors from superclasses if needed.
+  //        One must analyze the class constructor to detect
+  //        whether it explicitly calls them or not.
+
+  std::string ctor_name = get_base_name (get_name ());
+  cdef_method ctor = find_method (ctor_name);
+
+  if (ctor.ok ())
+    {
+      octave_value_list ctor_args (args);
+      octave_value_list ctor_retval;
+
+      ctor_args.prepend (to_ov (obj));
+      ctor_retval = ctor.execute (ctor_args, 1);
+
+      if (ctor_retval.length () == 1)
+        obj = to_cdef (ctor_retval(0));
+      else
+        ::error ("%s: invalid number of output arguments for classdef constructor",
+                 ctor_name.c_str ());
+    }
+}
+
+octave_value
+cdef_class::cdef_class_rep::construct (const octave_value_list& args)
+{
+  // FIXME: determine whether to use value or handle rep object
+  cdef_object obj (new handle_cdef_object (get ("Name").string_value ()));
+
+  initialize_object (obj);
+
+  if (! error_state)
+    {
+      run_constructor (obj, args);
+
+      if (! error_state)
+        return to_ov (obj);
+    }
+
+  return octave_value();
+}
+
+static octave_value
+compute_attribute_value (tree_classdef_attribute* t)
+{
+  if (t->expression ())
+    {
+      if (t->expression ()->is_identifier ())
+        {
+          std::string s = t->expression ()->name ();
+
+          if (s == "public")
+            return std::string ("public");
+          else if (s == "protected")
+            return std::string ("protected");
+          else if (s == "private")
+            return std::string ("private");
+        }
+
+      return t->expression ()->rvalue1 ();
+    }
+  else
+    return octave_value (true);
+}
+
+template<class T>
+static std::string
+attribute_value_to_string (T* t, octave_value v)
+{
+  if (v.is_string ())
+    return v.string_value ();
+  else if (t->expression ())
+    return t->expression ()->original_text ();
+  else
+    return std::string ("true");
+}
+
 cdef_class
-cdef_class::make_meta_class (const tree_classdef* t)
+cdef_class::make_meta_class (tree_classdef* t)
 {
   cdef_class retval;
+  std::string class_name;
+
+  // Class creation
+
+  class_name = t->ident ()->name ();
+  printf ("class: %s\n", class_name.c_str ());
+
+  std::list<std::string> snamelist;
+  std::list<cdef_class> slist;
+
+  if (t->superclass_list ())
+    {
+      for (tree_classdef_superclass_list::iterator it = t->superclass_list ()->begin ();
+           ! error_state && it != t->superclass_list ()->end (); ++it)
+        {
+          std::string sclass_name =
+            ((*it)->package () ? (*it)->package ()->name () + "." : std::string ())
+            + (*it)->ident ()->name ();
+
+          printf ("superclass: %s\n", sclass_name.c_str ());
+
+          cdef_class sclass = lookup_class (sclass_name);
+
+          if (! error_state)
+            {
+              if (! sclass.get ("Sealed").bool_value ())
+                {
+                  slist.push_back (sclass);
+                  snamelist.push_back (sclass_name);
+                }
+              else
+                {
+                  ::error ("`%s' cannot inherit from `%s', because it is sealed",
+                           class_name.c_str (), sclass_name.c_str ());
+                  return retval;
+                }
+            }
+          else
+            return retval;
+
+        }
+    }
+
+  retval = ::make_class (class_name, slist);
+
+  if (error_state)
+    return cdef_class ();
+
+  // FIXME: remove this...
+  if (! retval.is_handle_class ())
+    {
+      ::error ("%s: value classes not supported yet",
+               class_name.c_str ());
+      return cdef_class ();
+    }
+
+  // Class attributes
+
+  if (t->attribute_list ())
+    {
+      for (tree_classdef_attribute_list::iterator it = t->attribute_list ()->begin ();
+           it != t->attribute_list ()->end (); ++it)
+        {
+          std::string aname = (*it)->ident ()->name ();
+          octave_value avalue = compute_attribute_value (*it);
+
+          printf ("class attribute: %s = %s\n", aname.c_str (),
+                  attribute_value_to_string (*it, avalue).c_str ());
+          retval.put (aname, avalue);
+        }
+    }
+
+  tree_classdef_body* b = t->body ();
+
+  if (b)
+    {
+      // Method blocks
+
+      std::list<tree_classdef_methods_block *> mb_list = b->methods_list ();
+
+      for (tree_classdef_body::methods_list_iterator it = mb_list.begin ();
+           it != mb_list.end (); ++it)
+        {
+          std::map<std::string, octave_value> amap;
+          printf ("method block\n");
+
+          // Method attributes
+
+          if ((*it)->attribute_list ())
+            {
+              for (tree_classdef_attribute_list::iterator ait = (*it)->attribute_list ()->begin ();
+                   ait != (*it)->attribute_list ()->end (); ++ait)
+                {
+                  std::string aname = (*ait)->ident ()->name ();
+                  octave_value avalue = compute_attribute_value (*ait);
+
+                  printf ("method attribute: %s = %s\n", aname.c_str (),
+                          attribute_value_to_string (*ait, avalue).c_str ());
+                  amap[aname] = avalue;
+                }
+            }
+
+          // Methods
+
+          if ((*it)->element_list ())
+            {
+              for (tree_classdef_methods_list::iterator mit = (*it)->element_list ()->begin ();
+                   mit != (*it)->element_list ()->end (); ++mit)
+                {
+                  std::string mname = mit->function_value ()->name ();
+                  cdef_method meth = make_method (retval, mname, *mit);
+
+                  printf ("%s: %s\n", (mname == class_name ? "constructor" : "method"),
+                          mname.c_str ());
+                  for (std::map<std::string, octave_value>::iterator ait = amap.begin ();
+                       ait != amap.end (); ++ait)
+                    meth.put (ait->first, ait->second);
+
+                  retval.install_method (meth);
+                }
+            }
+        }
+
+      // Property blocks
+
+      // FIXME: default property expression should be able to call static
+      //        methods of the class being constructed. A restricted CLASSNAME
+      //        symbol should be added to the scope before evaluating default
+      //        value expressions.
+
+      std::list<tree_classdef_properties_block *> pb_list = b->properties_list ();
+
+      for (tree_classdef_body::properties_list_iterator it = pb_list.begin ();
+           it != pb_list.end (); ++it)
+        {
+          std::map<std::string, octave_value> amap;
+          printf ("property block\n");
+
+          // Property attributes
+
+          if ((*it)->attribute_list ())
+            {
+              for (tree_classdef_attribute_list::iterator ait = (*it)->attribute_list ()->begin ();
+                   ait != (*it)->attribute_list ()->end (); ++ait)
+                {
+                  std::string aname = (*ait)->ident ()->name ();
+                  octave_value avalue = compute_attribute_value (*ait);
+
+                  printf ("property attribute: %s = %s\n", aname.c_str (),
+                          attribute_value_to_string (*ait, avalue).c_str ());
+                  if (aname == "Access")
+                    {
+                      amap["GetAccess"] = avalue;
+                      amap["SetAccess"] = avalue;
+                    }
+                  else
+                    amap[aname] = avalue;
+                }
+            }
+
+          // Properties
+
+          if ((*it)->element_list ())
+            {
+              for (tree_classdef_property_list::iterator pit = (*it)->element_list ()->begin ();
+                   pit != (*it)->element_list ()->end (); ++pit)
+                {
+                  cdef_property prop = ::make_property (retval, (*pit)->ident ()->name ());
+
+                  printf ("property: %s\n", (*pit)->ident ()->name ().c_str ());
+                  if ((*pit)->expression ())
+                    {
+                      octave_value pvalue = (*pit)->expression ()->rvalue1 ();
+
+                      printf ("property default: %s\n",
+                              attribute_value_to_string (*pit, pvalue).c_str ());
+                      prop.put ("DefaultValue", pvalue);
+                    }
+
+                  for (std::map<std::string, octave_value>::iterator ait = amap.begin ();
+                       ait != amap.end (); ++ait)
+                    prop.put (ait->first, ait->second);
+
+                  retval.install_property (prop);
+                }
+            }
+        }
+    }
 
   return retval;
 }
 
+octave_function*
+cdef_class::get_method_function (const std::string& /* nm */)
+{
+  octave_classdef_proxy* p = new octave_classdef_proxy (*this);
+
+  return p;
+}
+
 octave_value
 cdef_property::cdef_property_rep::get_value (const cdef_object& obj)
 {
@@ -974,13 +1652,6 @@
  
   octave_value get_fcn = get ("GetMethod");
 
-  std::string get_access = get ("GetAccess").string_value ();
-
-  if (get_access != "public")
-    {
-      // FIXME: should check the current call stack
-    }
-
   if (get_fcn.is_empty ())
     retval = obj.get (get ("Name").string_value ());
   else
@@ -999,15 +1670,64 @@
 }
 
 bool
-cdef_property::check_get_access (const std::string& req) const
+cdef_property::cdef_property_rep::is_recursive_set (const cdef_object& /* obj */) const
+{
+  // FIXME: implement
+  return false;
+}
+
+void
+cdef_property::cdef_property_rep::set_value (cdef_object& obj,
+                                             const octave_value& val)
 {
-  return ::check_access (req, get_get_access ());
+  octave_value set_fcn = get ("SetMethod");
+
+  if (set_fcn.is_empty () || is_recursive_set (obj))
+    {
+      obj.put (get ("Name").string_value (), val);
+    }
+  else
+    {
+      octave_value_list args;
+
+      args(0) = to_ov (obj);
+      args(1) = val;
+
+      args = execute_ov (set_fcn, args, 1);
+
+      if (! error_state)
+        {
+          if (args.length() > 0)
+            {
+              cdef_object new_obj = to_cdef (args(0));
+
+              if (! error_state)
+                obj = new_obj;
+            }
+        }
+    }
 }
 
 bool
-cdef_property::check_set_access (const std::string& req) const
+cdef_property::check_get_access (void) const
 {
-  return ::check_access (req, get_set_access ());
+  cdef_class cls (to_cdef (get ("DefiningClass")));
+
+  if (! error_state)
+    return ::check_access (cls, get ("GetAccess"));
+
+  return false;
+}
+
+bool
+cdef_property::check_set_access (void) const
+{
+  cdef_class cls (to_cdef (get ("DefiningClass")));
+
+  if (! error_state)
+    return ::check_access (cls, get ("SetAccess"));
+
+  return false;
 }
 
 void
@@ -1070,9 +1790,14 @@
 }
 
 bool
-cdef_method::check_access (const std::string& req) const
+cdef_method::check_access (void) const
 {
-  return ::check_access (req, get_access ());
+  cdef_class cls (to_cdef (get ("DefiningClass")));
+
+  if (! error_state)
+    return ::check_access (cls, get ("Access"));
+
+  return false;
 }
 
 static cdef_package
@@ -1220,27 +1945,6 @@
 cdef_package::cdef_package_rep::get_packages (void) const
 { return map2Cell (package_map); }
 
-octave_value_list
-octave_classdef::subsref (const std::string& type,
-			const std::list<octave_value_list>& idx,
-			int nargout)
-{
-  int skip = 0;
-  octave_value_list retval;
-
-  // FIXME: should check "subsref" method first
-
-  retval = object.subsref (type, idx, nargout, skip);
-
-  if (! error_state)
-    {
-      if (type.length () > skip && idx.size () > skip)
-	retval = retval(0).next_subsref (nargout, type, idx, skip);
-    }
-
-  return retval;
-}
-
 void
 install_classdef (void)
 {
@@ -1248,12 +1952,20 @@
 
   /* meta classes */
   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_event = make_class ("meta.event", "handle");
-  cdef_class meta_package = make_class ("meta.package", "handle");
-  cdef_class meta_dynproperty = make_class ("meta.dynamicproperty", "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_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_event.put ("Sealed", true);
+  meta_package.put ("Sealed", true);
+  meta_dynproperty.put ("Sealed", true);
 
   /* meta.class properties */
   meta_class.install_property (make_attribute (meta_class, "ConstructOnLoad"));
@@ -1261,6 +1973,7 @@
   meta_class.install_property (make_property  (meta_class, "Description"));
   meta_class.install_property (make_property  (meta_class, "DetailedDescription"));
   meta_class.install_property (make_property  (meta_class, "Events"));
+  meta_class.install_property (make_attribute (meta_class, "HandleCompatible"));
   meta_class.install_property (make_attribute (meta_class, "Hidden"));
   meta_class.install_property
       (make_property (meta_class, "InferiorClasses",
@@ -1333,6 +2046,11 @@
   meta_property.install_property (make_attribute (meta_property, "GetMethod"));
   meta_property.install_property (make_attribute (meta_property, "SetMethod"));
   meta_property.install_property (make_attribute (meta_property, "DefiningClass"));
+  meta_property.install_property
+      (make_property (meta_property, "DefaultValue",
+		      make_fcn_handle (property_get_defaultvalue, "meta.property>get.DefaultValue"),
+		      "public", Matrix (), "private"));
+  meta_property.install_property (make_attribute (meta_property, "HasDefault"));
   /* meta.property events */
   // FIXME: add events
 
--- a/libinterp/octave-value/ov-classdef.h	Sun Dec 23 19:03:38 2012 -0500
+++ b/libinterp/octave-value/ov-classdef.h	Tue Jan 01 19:42:17 2013 -0500
@@ -23,6 +23,7 @@
 #if !defined (octave_classdef_h)
 #define octave_classdef_h 1
 
+#include <set>
 #include <string>
 
 #include "oct-map.h"
@@ -80,6 +81,14 @@
       return octave_value_list ();
     }
 
+  virtual octave_value subsasgn (const std::string&,
+                                 const std::list<octave_value_list>&,
+                                 const octave_value&)
+    {
+      error ("subsasgn: invalid object");
+      return octave_value ();
+    }
+
   virtual string_vector map_keys(void) const;
 
   virtual bool is_valid (void) const { return false; }
@@ -156,6 +165,11 @@
 			     int nargout, int& skip)
     { return rep->subsref (type, idx, nargout, skip); }
 
+  octave_value subsasgn (const std::string& type,
+                         const std::list<octave_value_list>& idx,
+                         const octave_value& rhs)
+    { return rep->subsasgn (type, idx, rhs); }
+
   string_vector map_keys (void) const { return rep->map_keys (); }
 
   const cdef_object_rep* get_rep (void) const { return rep; }
@@ -179,6 +193,8 @@
   handle_cdef_object (const std::string& nm)
       : cdef_object_rep (nm) { }
 
+  ~handle_cdef_object (void);
+
   cdef_object_rep* clone (void) const
     {
       handle_cdef_object *obj = const_cast<handle_cdef_object *> (this);
@@ -206,6 +222,10 @@
 			     const std::list<octave_value_list>& idx,
 			     int nargout, int& skip);
 
+  octave_value subsasgn (const std::string& type,
+                         const std::list<octave_value_list>& idx,
+                         const octave_value& rhs);
+
   bool is_valid (void) const { return true; }
 
 protected:
@@ -222,9 +242,12 @@
   {
   public:
     cdef_class_rep (const std::string& nm)
-	: handle_cdef_object (nm) { }
+	: handle_cdef_object (nm), handle_class (false) { }
 
-    cdef_method find_method (const std::string& nm);
+    std::string get_name (void) const
+      { return get ("Name").string_value (); }
+
+    cdef_method find_method (const std::string& nm, bool local = false);
 
     void install_method (const cdef_method& meth);
 
@@ -244,25 +267,47 @@
 
     void delete_object (cdef_object obj);
 
+    octave_value_list subsref_meta (const std::string& type,
+                                    const std::list<octave_value_list>& idx,
+                                    int nargout);
+
+    octave_value construct (const octave_value_list& args);
+
+    void initialize_object (cdef_object& obj);
+
+    void run_constructor (cdef_object& obj, const octave_value_list& args);
+
+    void mark_as_handle_class (void) { handle_class = true; }
+
+    bool is_handle_class (void) const { return handle_class; }
+
   private:
     void load_all_methods (void);
 
-    void find_names (std::map<std::string,std::string>& names,
-		     std::map<std::string,int>& count);
+    void find_names (std::set<std::string>& names, bool all);
     
     void find_properties (std::map<std::string,cdef_property>& props,
-			  std::map<std::string,int>& count);
-    
-    void find_methods (std::map<std::string,cdef_method>& meths,
-		       std::map<std::string,int>& count);
+                          bool only_inherited);
+
+    void find_methods (std::map<std::string, cdef_method>& meths,
+                       bool only_inherited);
 
   private:
+    // The @-directory were this class is loaded from.
+    // (not used yet)
     std::string directory;
 
+    // The methods defined by this class.
     std::map<std::string,cdef_method> method_map;
 
+    // The properties defined by this class.
     std::map<std::string,cdef_property> property_map;
 
+    // TRUE if this class is a handle class. A class is a handle
+    // class when the abstract "handle" class is one of its superclasses.
+    bool handle_class;
+
+    // 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;
@@ -307,7 +352,7 @@
       return *this;
     }
 
-  cdef_method find_method (const std::string& nm);
+  cdef_method find_method (const std::string& nm, bool local = false);
 
   void install_method (const cdef_method& meth)
     { get_rep ()->install_method (meth); }
@@ -330,7 +375,7 @@
     { return get_rep ()->get_directory (); }
 
   std::string get_name (void) const
-    { return get ("Name").string_value (); }
+    { return get_rep ()->get_name (); }
 
   bool is_builtin (void) const
     { return get_directory ().empty (); }
@@ -338,7 +383,32 @@
   void delete_object (cdef_object obj)
     { get_rep ()->delete_object (obj); }
 
-  static cdef_class make_meta_class (const tree_classdef* t);
+  octave_value_list subsref_meta (const std::string& type,
+                                  const std::list<octave_value_list>& idx,
+                                  int nargout)
+    { return get_rep ()->subsref_meta (type, idx, nargout); }
+
+  static cdef_class make_meta_class (tree_classdef* t);
+
+  octave_function* get_method_function (const std::string& nm);
+
+  octave_function* get_constructor_function (void)
+    { return get_method_function (get_name ()); }
+
+  octave_value construct (const octave_value_list& args)
+    { return get_rep ()->construct (args); }
+
+  void initialize_object (cdef_object& obj)
+    { get_rep ()->initialize_object (obj); }
+
+  void run_constructor (cdef_object& obj, const octave_value_list& args)
+    { get_rep ()->run_constructor (obj, args); }
+
+  void mark_as_handle_class (void)
+    { get_rep ()->mark_as_handle_class (); }
+
+  bool is_handle_class (void) const
+    { return get_rep ()->is_handle_class (); }
 
 private:
   cdef_class_rep* get_rep (void)
@@ -378,7 +448,10 @@
 
     void set_value (const octave_value& val) { default_value = val; }
 
-    void set_value (const cdef_object& obj, const octave_value& val);
+    void set_value (cdef_object& obj, const octave_value& val);
+
+  private:
+    bool is_recursive_set (const cdef_object& obj) const;
 
   private:
     octave_value default_value;
@@ -414,20 +487,14 @@
 
   octave_value get_value (void) { return get_rep ()->get_value (); }
 
-  void set_value (const cdef_object& obj, const octave_value& val)
+  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); }
  
-  std::string get_get_access (void) const
-    { return get ("GetAccess").string_value (); }
+  bool check_get_access (void) const;
   
-  std::string get_set_access (void) const
-    { return get ("SetAccess").string_value (); }
-
-  bool check_get_access (const std::string& acc) const;
-  
-  bool check_set_access (const std::string& acc) const;
+  bool check_set_access (void) const;
 
   std::string get_name (void) const
     { return get ("Name").string_value (); }
@@ -506,10 +573,7 @@
 			     const octave_value_list& args, int nargout)
     { return get_rep ()->execute (obj, args, nargout); }
 
-  std::string get_access (void) const
-    { return get ("Access").string_value (); }
-
-  bool check_access (const std::string& req) const;
+  bool check_access (void) const;
   
   std::string get_name (void) const
     { return get ("Name").string_value (); }
@@ -533,8 +597,8 @@
 { return rep->get_class (); }
 
 inline cdef_method
-cdef_class::find_method (const std::string& nm)
-{ return get_rep ()->find_method (nm); }
+cdef_class::find_method (const std::string& nm, bool local)
+{ return get_rep ()->find_method (nm, local); }
 
 inline cdef_property
 cdef_class::find_property (const std::string& nm)
@@ -679,6 +743,10 @@
       return (retval.length () > 0 ? retval(0) : octave_value ());
     }
 
+  octave_value 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); }
--- a/libinterp/octave-value/ov-fcn.h	Sun Dec 23 19:03:38 2012 -0500
+++ b/libinterp/octave-value/ov-fcn.h	Tue Jan 01 19:42:17 2013 -0500
@@ -85,6 +85,10 @@
   virtual bool is_class_constructor (const std::string& = std::string ()) const
     { return false; }
 
+  virtual bool
+  is_classdef_constructor (const std::string& = std::string ()) const
+    { return false; }
+
   virtual bool is_class_method (const std::string& = std::string ()) const
     { return false; }
 
--- a/libinterp/octave-value/ov-usr-fcn.cc	Sun Dec 23 19:03:38 2012 -0500
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Tue Jan 01 19:42:17 2013 -0500
@@ -191,7 +191,7 @@
     num_named_args (param_list ? param_list->length () : 0),
     subfunction (false), inline_function (false),
     anonymous_function (false), nested_function (false),
-    class_constructor (false), class_method (false),
+    class_constructor (none), class_method (false),
     parent_scope (-1), local_scope (sid),
     curr_unwind_protect_frame (0)
 #ifdef HAVE_LLVM
@@ -370,7 +370,7 @@
 
 octave_value_list
 octave_user_function::do_multi_index_op (int nargout,
-                                         const octave_value_list& args,
+                                         const octave_value_list& _args,
                                          const std::list<octave_lvalue>* lvalue_list)
 {
   octave_value_list retval;
@@ -381,6 +381,23 @@
   if (! cmd_list)
     return retval;
 
+  // If this function is a classdef constructor, extract the first input
+  // argument, which must be the partially constructed object instance.
+
+  octave_value_list args (_args);
+  octave_value_list ret_args;
+
+  if (is_classdef_constructor ())
+    {
+      if (args.length () > 0)
+        {
+          ret_args = args.slice (0, 1, true);
+          args = args.slice (1, args.length () - 1, true);
+        }
+      else
+        panic_impossible ();
+    }
+
 #ifdef HAVE_LLVM
   if (is_special_expr ()
       && tree_jit::execute (*this, args, retval))
@@ -424,6 +441,25 @@
         return retval;
     }
 
+  // For classdef constructor, pre-populate the output arguments
+  // with the pre-initialized object instance, extracted above.
+
+  if (is_classdef_constructor ())
+    {
+      if (ret_list)
+        {
+          ret_list->define_from_arg_vector (ret_args);
+          if (error_state)
+            return retval;
+        }
+      else
+        {
+          ::error ("%s: invalid classdef constructor, no output argument defined",
+                   dispatch_class ().c_str ());
+          return retval;
+        }
+    }
+
   // Force parameter list to be undefined when this function exits.
   // Doing so decrements the reference counts on the values of local
   // variables that are also named function parameters.
--- a/libinterp/octave-value/ov-usr-fcn.h	Sun Dec 23 19:03:38 2012 -0500
+++ b/libinterp/octave-value/ov-usr-fcn.h	Tue Jan 01 19:42:17 2013 -0500
@@ -300,11 +300,19 @@
 
   void mark_as_nested_function (void) { nested_function = true; }
 
-  void mark_as_class_constructor (void) { class_constructor = true; }
+  void mark_as_class_constructor (void) { class_constructor = legacy; }
+
+  void mark_as_classdef_constructor (void) { class_constructor = classdef; }
 
   bool is_class_constructor (const std::string& cname = std::string ()) const
     {
-      return class_constructor
+      return class_constructor == legacy
+        ? (cname.empty () ? true : cname == dispatch_class ()) : false;
+    }
+
+  bool is_classdef_constructor (const std::string& cname = std::string ()) const
+    {
+      return class_constructor == classdef
         ? (cname.empty () ? true : cname == dispatch_class ()) : false;
     }
 
@@ -380,6 +388,13 @@
 
 private:
 
+  enum class_ctor_type
+    {
+      none,
+      legacy,
+      classdef
+    };
+
   // List of arguments for this function.  These are local variables.
   tree_parameter_list *param_list;
 
@@ -436,8 +451,8 @@
   // TRUE means this is a nested function. (either a child or parent)
   bool nested_function;
 
-  // TRUE means this function is the constructor for class object.
-  bool class_constructor;
+  // Enum describing whether this function is the constructor for class object.
+  class_ctor_type class_constructor;
 
   // TRUE means this function is a method for a class.
   bool class_method;
--- a/libinterp/parse-tree/oct-parse.yy	Sun Dec 23 19:03:38 2012 -0500
+++ b/libinterp/parse-tree/oct-parse.yy	Tue Jan 01 19:42:17 2013 -0500
@@ -3893,8 +3893,11 @@
                   // Convert parse tree for classdef object to
                   // meta.class info (and stash it in the symbol
                   // table?).  Return pointer to constructor?
-                  
-                  octave_value meta_class = classdef_object->make_meta_class ();
+
+                  if (fcn_ptr)
+                    panic_impossible ();
+
+                  fcn_ptr = classdef_object->make_meta_class ();
                 }
             }
           else
--- a/libinterp/parse-tree/pt-classdef.cc	Sun Dec 23 19:03:38 2012 -0500
+++ b/libinterp/parse-tree/pt-classdef.cc	Tue Jan 01 19:42:17 2013 -0500
@@ -232,16 +232,16 @@
 
 // Classdef
 
-octave_value
-tree_classdef::make_meta_class (void) const
+octave_function*
+tree_classdef::make_meta_class (void)
 {
   octave_value retval;
   cdef_class cls = cdef_class::make_meta_class (this);
 
   if (cls.ok ())
-    retval = to_ov (cls);
+    return cls.get_constructor_function ();
 
-  return retval;
+  return 0;
 }
 
 tree_classdef *
@@ -255,6 +255,5 @@
 void
 tree_classdef::accept (tree_walker& tw)
 {
-  std::cerr << "I am super accepting" << std::endl;
-  // tw.visit_classdef (*this);
+  tw.visit_classdef (*this);
 }
--- a/libinterp/parse-tree/pt-classdef.h	Sun Dec 23 19:03:38 2012 -0500
+++ b/libinterp/parse-tree/pt-classdef.h	Tue Jan 01 19:42:17 2013 -0500
@@ -623,7 +623,7 @@
   octave_comment_list *leading_comment (void) { return lead_comm; }
   octave_comment_list *trailing_comment (void) { return trail_comm; }
 
-  octave_value make_meta_class (void) const;
+  octave_function* make_meta_class (void);
 
   tree_classdef *dup (symbol_table::scope_id scope,
                       symbol_table::context_id context) const;