changeset 16050:fc3cb570ac46 classdef

periodic merge of default to classdef.
author Michael Goffioul <michael.goffioul@gmail.com>
date Mon, 11 Feb 2013 15:45:26 -0500
parents ebd2259c5df1 (diff) a1e67cf915ba (current diff)
children 0259254a3ccc
files libgui/languages/generic.qm libgui/languages/generic.ts libinterp/Makefile.am test/Makefile.am test/bc_overloads_expected test/bug-35448/test_bug_35448.m test/bug-36025/test_bug_36025.m test/build_bc_overload_tests.sh test/build_sparse_tests.sh test/class-concat/test_class_concat.m test/classdef/classdef.tst test/classdef/module.mk test/classdef/test_classdef.m test/classes/classes.tst test/classes/module.mk test/classes/test_classes.m test/ctor-vs-method/test_ctor_vs_method.m test/fcn-handle-derived-resolution/test_fcn_handle_derived_resolution.m test/nest/test_nest.m test/test_args.m test/test_bug_31371.m test/test_diag_perm.m test/test_error.m test/test_eval-catch.m test/test_for.m test/test_func.m test/test_global.m test/test_if.m test/test_index.m test/test_io.m test/test_line_continue.m test/test_logical_index.m test/test_null_assign.m test/test_parser.m test/test_prefer.m test/test_range.m test/test_recursion.m test/test_return.m test/test_slice.m test/test_struct.m test/test_switch.m test/test_system.m test/test_transpose.m test/test_try.m test/test_unwind.m test/test_while.m
diffstat 41 files changed, 6805 insertions(+), 243 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/interp-core/pt-jit.cc	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/interp-core/pt-jit.cc	Mon Feb 11 15:45:26 2013 -0500
@@ -655,6 +655,12 @@
 }
 
 void
+jit_convert::visit_funcall (tree_funcall&)
+{
+  throw jit_fail_exception ();
+}
+
+void
 jit_convert::visit_parameter_list (tree_parameter_list&)
 {
   throw jit_fail_exception ();
--- a/libinterp/interp-core/pt-jit.h	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/interp-core/pt-jit.h	Mon Feb 11 15:45:26 2013 -0500
@@ -127,6 +127,8 @@
 
   void visit_fcn_handle (tree_fcn_handle&);
 
+  void visit_funcall (tree_funcall&);
+
   void visit_parameter_list (tree_parameter_list&);
 
   void visit_postfix_expression (tree_postfix_expression&);
--- a/libinterp/interpfcn/symtab.cc	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/interpfcn/symtab.cc	Mon Feb 11 15:45:26 2013 -0500
@@ -36,6 +36,7 @@
 #include "dirfns.h"
 #include "input.h"
 #include "load-path.h"
+#include "ov-classdef.h"
 #include "ov-fcn.h"
 #include "ov-usr-fcn.h"
 #include "pager.h"
@@ -392,6 +393,31 @@
           class_constructors[name] = retval;
         }
     }
+  else
+    {
+      // Classdef constructors can be defined anywhere in the path, not
+      // necessarily in @-folders. Look for a normal function and load it.
+      // If the loaded function is a classdef constructor, store it as such
+      // and restore function_on_path to its previous value.
+
+      octave_value old_function_on_path = function_on_path;
+
+      octave_value maybe_cdef_ctor = find_user_function ();
+
+      if (maybe_cdef_ctor.is_defined ())
+        {
+          octave_function *fcn = maybe_cdef_ctor.function_value (true);
+
+          if (fcn && fcn->is_classdef_constructor ())
+            {
+              retval = maybe_cdef_ctor;
+
+              class_constructors[name] = retval;
+
+              function_on_path = old_function_on_path;
+            }
+        }
+    }
 
   return retval;
 }
@@ -406,43 +432,53 @@
     retval = load_class_constructor ();
   else
     {
-      std::string dir_name;
+      octave_function *cm = cdef_manager::find_method_symbol (name,
+                                                              dispatch_type);
 
-      std::string file_name = load_path::find_method (dispatch_type, name,
-                                                      dir_name);
+      if (cm)
+        retval = octave_value (cm);
 
-      if (! file_name.empty ())
+      if (! retval.is_defined ())
         {
-          octave_function *fcn = load_fcn_from_file (file_name, dir_name,
-                                                     dispatch_type);
+          std::string dir_name;
 
-          if (fcn)
+          std::string file_name = load_path::find_method (dispatch_type, name,
+                                                          dir_name);
+
+          if (! file_name.empty ())
             {
-              retval = octave_value (fcn);
+              octave_function *fcn = load_fcn_from_file (file_name, dir_name,
+                                                         dispatch_type);
 
-              class_methods[dispatch_type] = retval;
-            }
-        }
+              if (fcn)
+                {
+                  retval = octave_value (fcn);
 
-      if (retval.is_undefined ())
-        {
-          // Search parent classes
+                  class_methods[dispatch_type] = retval;
+                }
+            }
 
-          const std::list<std::string>& plist = parent_classes (dispatch_type);
-
-          std::list<std::string>::const_iterator it = plist.begin ();
-
-          while (it != plist.end ())
+          if (retval.is_undefined ())
             {
-              retval = find_method (*it);
+              // Search parent classes
 
-              if (retval.is_defined ())
+              const std::list<std::string>& plist =
+                parent_classes (dispatch_type);
+
+              std::list<std::string>::const_iterator it = plist.begin ();
+
+              while (it != plist.end ())
                 {
-                  class_methods[dispatch_type] = retval;
-                  break;
+                  retval = find_method (*it);
+
+                  if (retval.is_defined ())
+                    {
+                      class_methods[dispatch_type] = retval;
+                      break;
+                    }
+
+                  it++;
                 }
-
-              it++;
             }
         }
     }
--- a/libinterp/octave-value/module.mk	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/octave-value/module.mk	Mon Feb 11 15:45:26 2013 -0500
@@ -36,6 +36,7 @@
   octave-value/ov-cell.h \
   octave-value/ov-ch-mat.h \
   octave-value/ov-class.h \
+  octave-value/ov-classdef.h \
   octave-value/ov-colon.h \
   octave-value/ov-complex.h \
   octave-value/ov-cs-list.h \
@@ -94,6 +95,7 @@
   octave-value/ov-cell.cc \
   octave-value/ov-ch-mat.cc \
   octave-value/ov-class.cc \
+  octave-value/ov-classdef.cc \
   octave-value/ov-colon.cc \
   octave-value/ov-complex.cc \
   octave-value/ov-cs-list.cc \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/ov-classdef.cc	Mon Feb 11 15:45:26 2013 -0500
@@ -0,0 +1,3113 @@
+/*
+
+Copyright (C) 2012 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <algorithm>
+
+#include "defun.h"
+#include "ov-builtin.h"
+#include "ov-classdef.h"
+#include "ov-fcn-handle.h"
+#include "ov-typeinfo.h"
+#include "pt-assign.h"
+#include "pt-classdef.h"
+#include "pt-funcall.h"
+#include "pt-misc.h"
+#include "pt-stmt.h"
+#include "pt-walk.h"
+#include "singleton-cleanup.h"
+#include "symtab.h"
+#include "toplev.h"
+
+#include "Array.cc"
+
+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 (), 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 (), 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 (), 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
+make_fcn_handle (octave_builtin::fcn ff, const std::string& nm)
+{
+  octave_value fcn (new octave_builtin (ff, nm));
+
+  octave_value fcn_handle (new octave_fcn_handle (fcn, nm));
+
+  return fcn_handle;
+}
+
+inline octave_value_list
+execute_ov (octave_value val, const octave_value_list& args, int nargout)
+{
+  std::list<octave_value_list> idx (1, args);
+
+  std::string type ("(");
+
+  return val.subsref (type, idx, nargout);
+}
+
+static cdef_class
+lookup_class (const std::string& name, bool error_if_not_found = true,
+              bool load_if_not_found = true)
+{
+  return cdef_manager::find_class (name, error_if_not_found,
+                                   load_if_not_found);
+}
+
+static cdef_class
+lookup_class (const cdef_class& cls)
+{
+  // FIXME: placeholder for the time being, the purpose
+  //        is to centralized any class update activity here.
+
+  return cls;
+}
+
+static cdef_class
+lookup_class (const octave_value& ov)
+{
+  if (ov.is_string())
+    return lookup_class (ov.string_value ());
+  else
+    {
+      cdef_class cls (to_cdef (ov));
+
+      if (! error_state)
+        return lookup_class (cls);
+    }
+
+  return cdef_class ();
+}
+
+static std::list<cdef_class>
+lookup_classes (const Cell& cls_list)
+{
+  std::list<cdef_class> retval;
+
+  for (int i = 0; i < cls_list.numel (); i++)
+    {
+      cdef_class c = lookup_class (cls_list(i));
+
+      if (! error_state)
+        retval.push_back (c);
+      else
+        {
+          retval.clear ();
+          break;
+        }
+    }
+
+  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
+is_superclass (const cdef_class& clsa, const cdef_class& clsb,
+	       bool allow_equal = true, int max_depth = -1)
+{
+  bool retval = false;
+
+  if (allow_equal && clsa == clsb)
+    retval = true;
+  else if (max_depth != 0)
+    {
+      Cell c = clsb.get ("SuperClasses").cell_value ();
+
+      for (int i = 0; ! error_state && ! retval && i < c.numel (); i++)
+	{
+	  cdef_class cls = lookup_class (c(i));
+
+	  if (! error_state)
+	    retval = is_superclass (clsa, cls, true,
+                                    max_depth < 0 ? max_depth : max_depth-1);
+	}
+    }
+
+  return retval;
+}
+
+inline bool
+is_strict_superclass (const cdef_class& clsa, const cdef_class& clsb)
+{ return is_superclass (clsa, clsb, false); }
+
+inline bool
+is_direct_superclass (const cdef_class& clsa, const cdef_class& clsb)
+{ return is_superclass (clsa, clsb, false, 1); }
+
+static octave_value_list
+class_get_properties (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1 && args(0).type_name () == "object")
+    {
+      cdef_class cls (to_cdef (args(0)));
+
+      retval(0) = cls.get_properties ();
+    }
+
+  return retval;
+}
+
+static cdef_class
+get_class_context (std::string& name, bool& in_constructor)
+{
+  cdef_class cls;
+
+  octave_function* fcn = octave_call_stack::current ();
+
+  in_constructor = false;
+
+  if (fcn &&
+      (fcn->is_class_method ()
+       || fcn->is_classdef_constructor ()
+       || fcn->is_anonymous_function_of_class ()
+       || (fcn->is_private_function ()
+           && ! fcn->dispatch_class ().empty ())))
+    {
+      cls = lookup_class (fcn->dispatch_class ());
+      if (! error_state)
+        {
+          name = fcn->name ();
+          in_constructor = fcn->is_classdef_constructor ();
+        }
+    }
+
+  return cls;
+}
+
+inline cdef_class
+get_class_context (void)
+{
+  std::string dummy_string;
+  bool dummy_bool;
+
+  return get_class_context (dummy_string, dummy_bool);
+}
+
+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 ();
+
+      // The access is private or protected, this requires a
+      // valid class context.
+
+      if (! error_state && ctx.ok ())
+        {
+          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 ();
+
+      // At this point, a class context is always required.
+
+      if (! error_state && ctx.ok ())
+        {
+          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;
+                }
+            }
+        }
+    }
+  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 */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1 && args(0).type_name () == "object")
+    {
+      cdef_class cls (to_cdef (args(0)));
+
+      retval(0) = cls.get_methods ();
+    }
+
+  return retval;
+}
+
+static octave_value_list
+class_get_superclasses (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.class")
+    {
+      cdef_class cls (to_cdef (args(0)));
+
+      Cell classes = cls.get ("SuperClasses").cell_value ();
+
+      retval(0) = to_ov (lookup_classes (classes));
+    }
+
+  return retval;
+}
+
+static octave_value_list
+class_get_inferiorclasses (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.class")
+    {
+      cdef_class cls (to_cdef (args(0)));
+
+      Cell classes = cls.get ("InferiorClasses").cell_value ();
+
+      retval(0) = to_ov (lookup_classes (classes));
+    }
+
+  return retval;
+}
+
+static octave_value_list
+class_fromName (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1)
+    {
+      std::string name = args(0).string_value ();
+
+      if (! error_state)
+	retval(0) = to_ov (lookup_class (name));
+      else
+	error ("fromName: invalid class name, expected a string value");
+    }
+  else
+    error ("fromName: invalid number of parameters");
+
+  return retval;
+}
+
+static octave_value_list
+class_fevalStatic (const octave_value_list& args, int nargout)
+{
+  octave_value_list retval;
+
+  if (args.length () > 1 && args(0).type_name () == "object")
+    {
+      cdef_class cls (to_cdef (args(0)));
+
+      if (! error_state)
+	{
+	  std::string meth_name = args(1).string_value ();
+
+	  if (! error_state)
+	    {
+	      cdef_method meth = cls.find_method (meth_name);
+
+	      if (meth.ok ())
+		{
+                    if (meth.is_static ())
+                      retval = meth.execute (args.splice (0, 2), nargout,
+                                             true, "fevalStatic");
+                    else
+                      error ("fevalStatic: method `%s' is not static",
+                             meth_name.c_str ());
+		}
+	      else
+		error ("fevalStatic: method not found: %s",
+		       meth_name.c_str ());
+	    }
+	  else
+	    error ("fevalStatic: invalid method name, expected a string value");
+	}
+      error ("fevalStatic: invalid object, expected a meta.class object");
+    }
+  else
+    error ("fevalStatic: invalid arguments");
+
+  return retval;
+}
+
+static octave_value_list
+class_getConstant (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 2 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.class")
+    {
+      cdef_class cls = to_cdef (args(0));
+
+      if (! error_state)
+	{
+	  std::string prop_name = args(1).string_value ();
+
+	  if (! error_state)
+	    {
+	      cdef_property prop = cls.find_property (prop_name);
+
+	      if (prop.ok ())
+		{
+                  if (prop.is_constant ())
+                    retval(0) = prop.get_value (true, "getConstant");
+                  else
+                    error ("getConstant: property `%s' is not constant",
+                           prop_name.c_str ());
+		}
+	      else
+		error ("getConstant: property not found: %s",
+		       prop_name.c_str ());
+	    }
+	  else
+	    error ("getConstant: invalid property name, expected a string value");
+	}
+      else
+	error ("getConstant: invalid object, expected a meta.class object");
+    }
+  else
+    error ("getConstant: invalid arguments");
+
+  return retval;
+}
+
+#define META_CLASS_CMP(OP, CLSA, CLSB, FUN) \
+static octave_value_list \
+class_ ## OP (const octave_value_list& args, int /* nargout */) \
+{ \
+  octave_value_list retval; \
+\
+  if (args.length () == 2 \
+      && args(0).type_name () == "object" && args(1).type_name () == "object" \
+      && args(0).class_name () == "meta.class" && args(1).class_name () == "meta.class") \
+    { \
+      cdef_class clsa = to_cdef (args(0)); \
+\
+      cdef_class clsb = to_cdef (args(1)); \
+\
+      if (! error_state) \
+	retval(0) = FUN (CLSA, CLSB); \
+      else \
+	error (#OP ": invalid objects, expected meta.class objects"); \
+    } \
+  else \
+    error (#OP ": invalid arguments"); \
+\
+  return retval; \
+}
+
+META_CLASS_CMP (lt, clsb, clsa, is_strict_superclass)
+META_CLASS_CMP (le, clsb, clsa, is_superclass)
+META_CLASS_CMP (gt, clsa, clsb, is_strict_superclass)
+META_CLASS_CMP (ge, clsa, clsb, is_superclass)
+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 */)
+{
+  octave_value_list retval;
+
+  // FIXME: implement this
+
+  return retval;
+}
+
+static cdef_class
+make_class (const std::string& name,
+            const std::list<cdef_class>& super_list = std::list<cdef_class> ())
+{
+  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 ());
+  cls.put ("DetailedDescription", std::string ());
+  cls.put ("Events", Cell ());
+  cls.put ("Hidden", false);
+  cls.put ("InferiorClasses", Cell ());
+  cls.put ("Methods", Cell ());
+  cls.put ("Properties", Cell ());
+  cls.put ("Sealed", false);
+
+  if (name == "handle")
+    {
+      cls.put ("HandleCompatible", true);
+      cls.mark_as_handle_class ();
+    }
+  else if (super_list.empty ())
+    {
+      cls.put ("HandleCompatible", false);
+    }
+  else
+    {
+      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 ();
+
+  if (! name.empty ())
+    cdef_manager::register_class (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_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 (),
+	       const std::string& get_access = "public",
+	       const octave_value& set_method = Matrix (),
+	       const std::string& set_access = "public")
+{
+  cdef_property prop (name);
+
+  prop.set_class (cdef_class::meta_property ());
+  prop.put ("Description", std::string ());
+  prop.put ("DetailedDescription", std::string ());
+  prop.put ("Abstract", false);
+  prop.put ("Constant", false);
+  prop.put ("GetAccess", get_access);
+  prop.put ("SetAccess", set_access);
+  prop.put ("Dependent", false);
+  prop.put ("Transient", false);
+  prop.put ("Hidden", false);
+  prop.put ("GetObservable", false);
+  prop.put ("SetObservable", false);
+  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_class& cls, const std::string& name)
+{
+  return make_property (cls, name, Matrix (), "public", Matrix (), "private");
+}
+
+static cdef_method
+make_method (const cdef_class& cls, const std::string& name,
+             const octave_value& fcn,const std::string& m_access = "public",
+             bool is_static = false)
+{
+  cdef_method meth (name);
+
+  meth.set_class (cdef_class::meta_method ());
+  meth.put ("Abstract", false);
+  meth.put ("Access", m_access);
+  meth.put ("DefiningClass", to_ov (cls));
+  meth.put ("Description", std::string ());
+  meth.put ("DetailedDescription", std::string ());
+  meth.put ("Hidden", false);
+  meth.put ("Sealed", true);
+  meth.put ("Static", is_static);
+
+  if (fcn.is_defined ())
+    make_function_of_class (cls, fcn);
+
+  meth.set_function (fcn);
+
+  return meth;
+}
+
+inline cdef_method
+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));
+
+  return make_method (cls, name, fcn, m_access, is_static);
+}
+
+static cdef_package
+make_package (const std::string& nm,
+              const std::string& parent = std::string ())
+{
+  cdef_package pack ("meta.package");
+
+  pack.set_class (cdef_class::meta_package ());
+  pack.put ("Name", nm);
+  if (parent.empty ())
+    pack.put ("ContainingPackage", Matrix ());
+  else
+    pack.put ("ContainingPackage", to_ov (cdef_manager::find_package (parent)));
+
+  if (! nm.empty ())
+    cdef_manager::register_package (pack);
+
+  return pack;
+}
+
+//----------------------------------------------------------------------------
+
+DEFINE_OCTAVE_ALLOCATOR (octave_classdef);
+
+int octave_classdef::t_id (-1);
+
+const std::string octave_classdef::t_name ("object");
+
+void
+octave_classdef::register_type (void)
+{
+  t_id = octave_value_typeinfo::register_type
+    (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)
+{
+  size_t skip = 0;
+  octave_value_list retval;
+
+  // FIXME: should check "subsref" method first
+
+  retval = object.subsref (type, idx, nargout, skip, cdef_class ());
+
+  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);
+}
+
+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_meta : public octave_function
+{
+public:
+  octave_classdef_meta (const cdef_meta_object& obj)
+    : object (obj) { }
+
+  ~octave_classdef_meta (void)
+    { object.meta_release (); }
+
+  octave_function* function_value (bool = false) { return this; }
+
+  octave_value_list
+  subsref (const std::string& type,
+           const std::list<octave_value_list>& idx,
+           int nargout)
+    { return object.meta_subsref (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)
+    {
+      // Emulate ()-type meta subsref
+
+      std::list<octave_value_list> l (1, idx);
+      std::string type ("(");
+
+      return subsref (type, l, nargout);
+    }
+
+  bool is_postfix_index_handled (char type) const
+    { return object.meta_is_postfix_index_handled (type); }
+
+private:
+  cdef_meta_object object;
+};
+
+//----------------------------------------------------------------------------
+
+class octave_classdef_superclass_ref : public octave_function
+{
+public:
+  octave_classdef_superclass_ref (const octave_value_list& a)
+    : octave_function (), args (a) { }
+
+  ~octave_classdef_superclass_ref (void) { }
+
+  octave_value_list
+  subsref (const std::string& type,
+           const std::list<octave_value_list>& idx,
+           int nargout)
+    {
+      size_t skip = 0;
+      octave_value_list retval;
+
+      switch (type[0])
+        {
+        case '(':
+          skip = 1;
+          retval = do_multi_index_op (type.length () > 1 ? 1 : nargout,
+                                      idx.front ());
+          break;
+        default:
+          retval = do_multi_index_op (1, octave_value_list ());
+          break;
+        }
+
+      if (! error_state)
+        {
+          if (type.length () > skip && idx.size () > skip
+              && retval.length () > 0)
+            retval = retval(0).next_subsref (nargout, type, idx, skip);
+        }
+
+      return retval;
+    }
+
+  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)
+    {
+      octave_value_list retval;
+
+      std::string meth_name;
+      bool in_constructor;
+      cdef_class ctx;
+
+      ctx = get_class_context (meth_name, in_constructor);
+
+      if (! error_state && ctx.ok ())
+        {
+          std::string mname = args(0).string_value ();
+          std::string pname = args(1).string_value ();
+          std::string cname = args(2).string_value ();
+
+          std::string cls_name = (pname.empty () ?
+                                  cname : pname + "." + cname);
+          cdef_class cls = lookup_class (cls_name);
+
+          if (! error_state)
+            {
+              if (in_constructor)
+                {
+                  if (is_direct_superclass (cls, ctx))
+                    {
+                      if (is_constructed_object (mname))
+                        {
+                          octave_value& sym = symbol_table::varref (mname);
+
+                          cls.run_constructor (to_cdef_ref (sym), idx);
+
+                          retval(0) = sym;
+                        }
+                      else
+                        ::error ("cannot call superclass constructor with "
+                                 "variable `%s'", mname.c_str ());
+                    }
+                  else
+                    ::error ("`%s' is not a direct superclass of `%s'",
+                             cls_name.c_str (), ctx.get_name ().c_str ());
+                }
+              else
+                {
+                  if (mname == meth_name)
+                    {
+                      if (is_strict_superclass (cls, ctx))
+                        {
+                          // I see 2 possible implementations here:
+                          // 1) use cdef_object::subsref with a different class
+                          //    context; this avoids duplicating codem but
+                          //    assumes the object is always the first argument
+                          // 2) lookup the method manually and call
+                          //    cdef_method::execute; this duplicates part of
+                          //    logic in cdef_object::subsref, but avoid the
+                          //    assumption of 1)
+                          // Not being sure about the assumption of 1), I
+                          // go with option 2) for the time being.
+
+                          cdef_method meth = cls.find_method (meth_name, false);
+
+                          if (meth.ok ())
+                            retval = meth.execute (idx, nargout, true,
+                                                   meth_name);
+                          else
+                            ::error ("no method `%s' found in superclass `%s'",
+                                     meth_name.c_str (), cls_name.c_str ());
+                        }
+                      else
+                        ::error ("`%s' is not a superclass of `%s'",
+                                 cls_name.c_str (), ctx.get_name ().c_str ());
+                    }
+                  else
+                    ::error ("method name mismatch (`%s' != `%s')",
+                             mname.c_str (), meth_name.c_str ());
+                }
+            }
+        }
+      else if (! error_state)
+        ::error ("superclass calls can only occur in methods or constructors");
+
+      return retval;
+    }
+
+private:
+  bool is_constructed_object (const std::string nm)
+    {
+      octave_function *of = octave_call_stack::current ();
+
+      if (of->is_classdef_constructor ())
+        {
+          octave_user_function *uf = of->user_function_value (true);
+
+          if (uf)
+            {
+              tree_parameter_list *ret_list = uf->return_list ();
+
+              if (ret_list && ret_list->length () == 1)
+                return (ret_list->front ()->name () == nm);
+            }
+        }
+
+      return false;
+    }
+
+private:
+  octave_value_list args;
+};
+
+//----------------------------------------------------------------------------
+
+string_vector
+cdef_object_rep::map_keys (void) const
+{
+  cdef_class cls = get_class ();
+
+  if (cls.ok ())
+    return cls.get_names ();
+  
+  return string_vector ();
+}
+
+octave_value_list
+cdef_object_scalar::subsref (const std::string& type,
+                             const std::list<octave_value_list>& idx,
+                             int nargout, size_t& skip,
+                             const cdef_class& context)
+{
+  skip = 0;
+
+  cdef_class cls = (context.ok () ? context : get_class ());
+
+  octave_value_list retval;
+
+  if (! cls.ok ())
+    return retval;
+
+  switch (type[0])
+    {
+    case '.':
+	{
+	  std::string name = (idx.front ())(0).string_value ();
+
+	  cdef_method meth = cls.find_method (name);
+
+	  if (meth.ok ())
+	    {
+              int _nargout = (type.length () > 2 ? 1 : nargout);
+
+              octave_value_list args;
+
+              skip = 1;
+
+              if (type.length () > 1 && type[1] == '(')
+                {
+                  std::list<octave_value_list>::const_iterator it = idx.begin ();
+
+                  args = *++it;
+
+                  skip++;
+                }
+
+              if (meth.is_static ())
+                retval = meth.execute (args, _nargout, true, "subsref");
+              else
+                {
+                  refcount++;
+                  retval = meth.execute (cdef_object (this), args, _nargout,
+                                         true, "subsref");
+                }
+	    }
+
+	  if (skip == 0 && ! error_state)
+	    {
+	      cdef_property prop = cls.find_property (name);
+
+	      if (prop.ok ())
+		{
+                  if (prop.is_constant ())
+                    retval(0) = prop.get_value (true, "subsref");
+                  else
+                    {
+                      refcount++;
+                      retval(0) = prop.get_value (cdef_object (this),
+                                                  true, "subsref");
+                    }
+
+                  skip = 1;
+		}
+	      else
+		error ("subsref: unknown method or property: %s", name.c_str ());
+	    }
+	  break;
+	}
+    default:
+      error ("object cannot be indexed with `%c'", type[0]);
+      break;
+    }
+
+  return retval;
+}
+
+octave_value
+cdef_object_scalar::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)
+                    {
+                      refcount++;
+
+                      cdef_object obj (this);
+
+                      prop.set_value (obj, rhs, true, "subsasgn");
+
+                      if (! error_state)
+                        retval = to_ov (obj);
+                    }
+                  else
+                    {
+                    }
+
+                  if (! error_state)
+                    {
+                    }
+                }
+              else
+                error ("subsasgn: unknown property: %s", name.c_str ());
+            }
+        }
+      break;
+
+    default:
+      panic_impossible ();
+      break;
+    }
+
+  return retval;
+}
+
+void
+cdef_object_scalar::mark_for_construction (const cdef_class& cls)
+{
+  std::string cls_name = cls.get_name ();
+
+  Cell supcls = cls.get ("SuperClasses").cell_value ();
+
+  if (! error_state)
+    {
+      std::list<cdef_class> supcls_list = lookup_classes (supcls);
+
+      if (! error_state)
+        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
+{
+  return (is_constructed ()
+          || ctor_list.find (cls) == ctor_list.end ());
+}
+
+bool cdef_object_scalar::is_partially_constructed_for (const cdef_class& cls) const
+{
+  std::map< cdef_class, std::list<cdef_class> >::const_iterator it;
+
+  if (is_constructed ())
+    return true;
+  else if ((it = ctor_list.find (cls)) == ctor_list.end ()
+           || it->second.empty ())
+    return true;
+
+  for (std::list<cdef_class>::const_iterator lit = it->second.begin ();
+       lit != it->second.end (); ++lit)
+    if (! is_constructed_for (*lit))
+      return false;
+
+  return true;
+}
+
+handle_cdef_object::~handle_cdef_object (void)
+{
+  gnulib::printf ("deleting %s object (handle)\n",
+                  get_class ().get_name ().c_str ());
+}
+
+value_cdef_object::~value_cdef_object (void)
+{
+  gnulib::printf ("deleting %s object (value)\n",
+                  get_class ().get_name ().c_str ());
+}
+
+cdef_class::cdef_class_rep::cdef_class_rep (const std::list<cdef_class>& superclasses)
+     : cdef_meta_object_rep (), member_count (0), handle_class (false),
+       object_count (0), meta (false)
+{
+  put ("SuperClasses", to_ov (superclasses));
+  implicit_ctor_list = superclasses;
+}
+
+cdef_method
+cdef_class::cdef_class_rep::find_method (const std::string& nm, bool local)
+{
+  method_iterator it = method_map.find (nm);
+
+  if (it == method_map.end ())
+    {
+      // FIXME: look into class directory
+    }
+  else
+    {
+      cdef_method& meth = it->second;
+
+      // FIXME: check if method reload needed
+
+      if (meth.ok ())
+	return meth;
+    }
+
+  if (! local)
+    {
+      // Look into superclasses
+
+      Cell super_classes = get ("SuperClasses").cell_value ();
+
+      for (int i = 0; i < super_classes.numel (); i++)
+        {
+          cdef_class cls = lookup_class (super_classes(i));
+
+          if (! error_state)
+            {
+              cdef_method meth = cls.find_method (nm);
+
+              if (meth.ok ())
+                return meth;
+            }
+        }
+    }
+
+  return cdef_method ();
+}
+
+class ctor_analyzer : public tree_walker
+{
+public:
+  ctor_analyzer (const std::string& ctor, const std::string& obj)
+    : tree_walker (), who (ctor), obj_name (obj) { }
+
+  void visit_statement_list (tree_statement_list& t)
+    {
+      for (tree_statement_list::const_iterator it = t.begin ();
+           ! error_state && it != t.end (); ++it)
+        (*it)->accept (*this);
+    }
+
+  void visit_statement (tree_statement& t)
+    {
+      if (t.is_expression ())
+        t.expression ()->accept (*this);
+    }
+
+  void visit_simple_assignment (tree_simple_assignment& t)
+    {
+      t.right_hand_side ()->accept (*this);
+    }
+
+  void visit_multi_assignment (tree_multi_assignment& t)
+    {
+      t.right_hand_side ()->accept (*this);
+    }
+
+  void visit_index_expression (tree_index_expression& t)
+    {
+      t.expression ()->accept (*this);
+    }
+
+  void visit_funcall (tree_funcall& t)
+    {
+      octave_value fcn = t.function ();
+
+      if (fcn.is_function ())
+        {
+          octave_function *of = fcn.function_value (true);
+
+          if (of)
+            {
+              if (of->name () == "__superclass_reference__")
+                {
+                  octave_value_list args = t.arguments ();
+
+                  if (args(0).string_value () == obj_name)
+                    {
+                      std::string package_name = args(1).string_value ();
+                      std::string class_name = args(2).string_value ();
+
+                      std::string ctor_name = (package_name.empty ()
+                                               ? class_name
+                                               : package_name + "." + class_name);
+
+                      cdef_class cls = lookup_class (ctor_name, false);
+
+                      if (cls.ok ())
+                        ctor_list.push_back (cls);
+                    }
+                }
+            }
+        }
+    }
+
+  std::list<cdef_class> get_constructor_list (void) const
+    { return ctor_list; }
+
+  // NO-OP
+  void visit_anon_fcn_handle (tree_anon_fcn_handle&) { }
+  void visit_argument_list (tree_argument_list&) { }
+  void visit_binary_expression (tree_binary_expression&) { }
+  void visit_break_command (tree_break_command&) { }
+  void visit_colon_expression (tree_colon_expression&) { }
+  void visit_continue_command (tree_continue_command&) { }
+  void visit_global_command (tree_global_command&) { }
+  void visit_persistent_command (tree_persistent_command&) { }
+  void visit_decl_elt (tree_decl_elt&) { }
+  void visit_decl_init_list (tree_decl_init_list&) { }
+  void visit_simple_for_command (tree_simple_for_command&) { }
+  void visit_complex_for_command (tree_complex_for_command&) { }
+  void visit_octave_user_script (octave_user_script&) { }
+  void visit_octave_user_function (octave_user_function&) { }
+  void visit_function_def (tree_function_def&) { }
+  void visit_identifier (tree_identifier&) { }
+  void visit_if_clause (tree_if_clause&) { }
+  void visit_if_command (tree_if_command&) { }
+  void visit_if_command_list (tree_if_command_list&) { }
+  void visit_switch_case (tree_switch_case&) { }
+  void visit_switch_case_list (tree_switch_case_list&) { }
+  void visit_switch_command (tree_switch_command&) { }
+  void visit_matrix (tree_matrix&) { }
+  void visit_cell (tree_cell&) { }
+  void visit_no_op_command (tree_no_op_command&) { }
+  void visit_constant (tree_constant&) { }
+  void visit_fcn_handle (tree_fcn_handle&) { }
+  void visit_parameter_list (tree_parameter_list&) { }
+  void visit_postfix_expression (tree_postfix_expression&) { }
+  void visit_prefix_expression (tree_prefix_expression&) { }
+  void visit_return_command (tree_return_command&) { }
+  void visit_return_list (tree_return_list&) { }
+  void visit_try_catch_command (tree_try_catch_command&) { }
+  void visit_unwind_protect_command (tree_unwind_protect_command&) { }
+  void visit_while_command (tree_while_command&) { }
+  void visit_do_until_command (tree_do_until_command&) { }
+
+private:
+  /* The name of the constructor being analyzed */
+  std::string who;
+
+  /* The name of the first output argument of the constructor */
+  std::string obj_name;
+
+  /* The list of superclass constructors that are explicitly called */
+  std::list<cdef_class> ctor_list;
+};
+
+void
+cdef_class::cdef_class_rep::install_method (const cdef_method& meth)
+{
+  method_map[meth.get_name ()] = meth;
+
+  member_count++;
+
+  if (meth.is_constructor ())
+    {
+      // Analyze the constructor code to determine what superclass
+      // constructors are called explicitly.
+
+      octave_function *of = meth.get_function ().function_value (true);
+
+      if (of)
+        {
+          octave_user_function *uf = of->user_function_value (true);
+
+          if (uf)
+            {
+              tree_parameter_list *ret_list = uf->return_list ();
+              tree_statement_list *body = uf->body ();
+
+              if (ret_list && ret_list->size () == 1)
+                {
+                  std::string obj_name = ret_list->front ()->name ();
+                  ctor_analyzer a (meth.get_name (), obj_name);
+
+                  body->accept (a);
+                  if (! error_state)
+                    {
+                      std::list<cdef_class> explicit_ctor_list
+                        = a.get_constructor_list ();
+
+                      for (std::list<cdef_class>::const_iterator it = explicit_ctor_list.begin ();
+                           ! error_state && it != explicit_ctor_list.end (); ++it)
+                        {
+                          gnulib::printf ("explicit superclass constructor: %s\n",
+                                          it->get_name ().c_str ());
+                          implicit_ctor_list.remove (*it);
+                        }
+                    }
+                }
+              else
+                ::error ("%s: invalid constructor output arguments",
+                         meth.get_name ().c_str ());
+            }
+        }
+    }
+}
+
+void
+cdef_class::cdef_class_rep::load_all_methods (void)
+{
+  // FIXME: re-scan class directory
+}
+
+Cell
+cdef_class::cdef_class_rep::get_methods (void)
+{
+  std::map<std::string,cdef_method> meths;
+
+  find_methods (meths, false);
+
+  if (! error_state)
+    {
+      Cell c (meths.size (), 1);
+
+      int idx = 0;
+
+      for (std::map<std::string,cdef_method>::const_iterator it = meths.begin ();
+	   it != meths.end (); ++it, ++idx)
+        c (idx, 0) = to_ov (it->second);
+
+      return c;
+    }
+
+  return Cell ();
+}
+
+void
+cdef_class::cdef_class_rep::find_methods (std::map<std::string, cdef_method>& meths,
+                                          bool only_inherited)
+{
+  load_all_methods ();
+
+  method_const_iterator it;
+
+  for (it = method_map.begin (); it != method_map.end (); ++it)
+    {
+      if (! it->second.is_constructor ())
+        {
+          std::string nm = it->second.get_name ();
+
+          if (meths.find (nm) == meths.end ())
+            {
+              if (only_inherited)
+                {
+                  octave_value acc = it->second.get ("Access");
+
+                  if (! acc.is_string ()
+                      || acc.string_value () == "private")
+                    continue;
+                }
+
+              meths[nm] = it->second;
+            }
+        }
+    }
+
+  // Look into superclasses
+
+  Cell super_classes = get ("SuperClasses").cell_value ();
+
+  for (int i = 0; i < super_classes.numel (); i++)
+    {
+      cdef_class cls = lookup_class (super_classes(i));
+
+      if (! error_state)
+	cls.get_rep ()->find_methods (meths, true);
+      else
+	break;
+    }
+}
+
+cdef_property
+cdef_class::cdef_class_rep::find_property (const std::string& nm)
+{
+  property_iterator it = property_map.find (nm);
+
+  if (it != property_map.end ())
+    {
+      cdef_property& prop = it->second;
+
+      if (prop.ok ())
+	return prop;
+    }
+
+  // Look into superclasses
+
+  Cell super_classes = get ("SuperClasses").cell_value ();
+
+  for (int i = 0; i < super_classes.numel (); i++)
+    {
+      cdef_class cls = lookup_class (super_classes(i));
+
+      if (! error_state)
+	{
+	  cdef_property prop = cls.find_property (nm);
+
+	  if (prop.ok ())
+	    return prop;
+	}
+    }
+
+  return cdef_property ();
+}
+
+void
+cdef_class::cdef_class_rep::install_property (const cdef_property& prop)
+{
+  property_map[prop.get_name ()] = prop;
+
+  member_count++;
+}
+
+Cell
+cdef_class::cdef_class_rep::get_properties (void)
+{
+  std::map<std::string,cdef_property> props;
+
+  find_properties (props, false);
+
+  if (! error_state)
+    {
+      Cell c (props.size (), 1);
+
+      int idx = 0;
+
+      for (std::map<std::string,cdef_property>::const_iterator it = props.begin ();
+	   it != props.end (); ++it, ++idx)
+        c (idx, 0) = to_ov (it->second);
+
+      return c;
+    }
+
+  return Cell ();
+}
+
+void
+cdef_class::cdef_class_rep::find_properties (std::map<std::string,cdef_property>& props,
+                                             bool only_inherited)
+{
+  property_const_iterator 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 ())
+	{
+          if (only_inherited)
+            {
+              octave_value acc = it->second.get ("GetAccess");
+
+              if (! acc.is_string ()
+                  || acc.string_value () == "private")
+                continue;
+            }
+
+	  props[nm] = it->second;
+	}
+    }
+
+  // Look into superclasses
+
+  Cell super_classes = get ("SuperClasses").cell_value ();
+
+  for (int i = 0; ! error_state && i < super_classes.numel (); i++)
+    {
+      cdef_class cls = lookup_class (super_classes(i));
+
+      if (! error_state)
+	cls.get_rep ()->find_properties (props, true);
+      else
+	break;
+    }
+}
+
+void
+cdef_class::cdef_class_rep::find_names (std::set<std::string>& names,
+                                        bool all)
+{
+  load_all_methods ();
+
+  for (method_const_iterator it = method_map.begin ();
+       ! error_state && it != method_map.end(); ++it)
+    {
+      if (! it->second.is_constructor ())
+        {
+          std::string nm = it->second.get_name ();
+
+          if (! all)
+            {
+              octave_value acc = it->second.get ("Access");
+
+              if (! acc.is_string()
+                  || acc.string_value () != "public")
+                continue;
+            }
+
+          names.insert (nm);
+        }
+    }
+
+  for (property_const_iterator it = property_map.begin ();
+       ! error_state && it != property_map.end (); ++it)
+    {
+      std::string nm = it->second.get_name ();
+
+      if (! all)
+        {
+          octave_value acc = it->second.get ("GetAccess");
+
+          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; ! error_state && i < super_classes.numel (); i++)
+    {
+      cdef_class cls = lookup_class (super_classes(i));
+
+      if (! error_state)
+	cls.get_rep ()->find_names (names, all);
+      else
+	break;
+    }
+}
+
+string_vector
+cdef_class::cdef_class_rep::get_names (void)
+{
+  std::set<std::string> names;
+
+  find_names (names, false);
+
+  if (! error_state)
+    {
+      string_vector v (names.size ());
+
+      int idx = 0;
+      for (std::set<std::string>::const_iterator it = names.begin ();
+	   it != names.end (); ++it, ++idx)
+        v[idx] = *it;
+
+      return v.sort (true);
+    }
+
+  return string_vector ();
+}
+
+void
+cdef_class::cdef_class_rep::delete_object (cdef_object obj)
+{
+  method_iterator it = method_map.find ("delete");
+
+  if (it != method_map.end ())
+    {
+      cdef_class cls = obj.get_class ();
+
+      obj.set_class (wrap ());
+
+      it->second.execute (obj, octave_value_list (), 0, false);
+
+      obj.set_class (cls);
+    }
+
+  // FIXME: should we destroy corresponding properties here?
+
+  // Call "delete" in super classes
+
+  Cell super_classes = get ("SuperClasses").cell_value ();
+
+  for (int i = 0; i < super_classes.numel (); i++)
+    {
+      cdef_class cls = lookup_class (super_classes(i));
+
+      if (!error_state)
+	cls.delete_object (obj);
+    }
+}
+
+octave_value_list
+cdef_class::cdef_class_rep::meta_subsref (const std::string& type,
+                                          const std::list<octave_value_list>& idx,
+                                          int nargout)
+{
+  size_t skip = 1;
+
+  octave_value_list retval;
+
+  switch (type[0])
+    {
+    case '(':
+      // Constructor call
+      gnulib::printf ("constructor\n");
+      retval(0) = construct (idx.front ());
+      break;
+
+    case '.':
+      // Static method, constant (or property?)
+      gnulib::printf ("static method/property\n");
+      if (idx.front ().length () == 1)
+        {
+          std::string nm = idx.front ()(0).string_value ();
+
+          if (! error_state)
+            {
+              cdef_method meth = find_method (nm);
+
+              if (meth.ok ())
+                {
+                  if (meth.is_static ())
+                    {
+                      octave_value_list args;
+
+                      if (type.length () > 1 && idx.size () > 1
+                          && type[1] == '(')
+                        {
+                          args = *(++(idx.begin ()));
+                          skip++;
+                        }
+
+                      retval = meth.execute (args, (type.length () > skip
+                                                    ? 1 : nargout), true,
+                                             "meta.class");
+                    }
+                  else
+                    ::error ("method `%s' is not static", nm.c_str ());
+                }
+              else
+                {
+                  cdef_property prop = find_property (nm);
+
+                  if (prop.ok ())
+                    {
+                      if (prop.is_constant ())
+                        retval(0) = prop.get_value (true, "meta.class");
+                      else
+                        ::error ("property `%s' is not constant",
+                                 nm.c_str ());
+                    }
+                  else
+                    ::error ("no such method or property `%s'", nm.c_str ());
+                }
+            }
+          else
+            ::error ("invalid meta.class indexing, expected a method or property name");
+        }
+      else
+        ::error ("invalid meta.class indexing");
+      break;
+
+    default:
+      ::error ("invalid meta.class indexing");
+      break;
+    }
+
+  if (! error_state)
+    {
+      if (type.length () > skip && idx.size () > skip && ! retval.empty ())
+	retval = retval(0).next_subsref (nargout, type, idx, skip);
+    }
+
+  return retval;
+}
+
+void
+cdef_class::cdef_class_rep::meta_release (void)
+{
+  cdef_manager::unregister_class (wrap ());
+}
+
+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 ()));
+                }
+            }
+
+          if (! error_state)
+            {
+              refcount++;
+              obj.mark_for_construction (cdef_class (this));
+            }
+        }
+    }
+}
+
+void
+cdef_class::cdef_class_rep::run_constructor (cdef_object& obj,
+                                             const octave_value_list& args)
+{
+  octave_value_list empty_args;
+
+  for (std::list<cdef_class>::const_iterator it = implicit_ctor_list.begin ();
+       ! error_state && it != implicit_ctor_list.end (); ++it)
+    {
+      cdef_class supcls = lookup_class (*it);
+
+      if (! error_state)
+        supcls.run_constructor (obj, empty_args);
+    }
+
+  if (error_state)
+    return;
+
+  std::string cls_name = get_name ();
+  std::string ctor_name = get_base_name (cls_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, true, "constructor");
+
+      if (! error_state)
+        {
+          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 ());
+              return;
+            }
+        }
+    }
+
+  obj.mark_as_constructed (wrap ());
+}
+
+octave_value
+cdef_class::cdef_class_rep::construct (const octave_value_list& args)
+{
+  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
+    error ("cannot instantiate object for abstract class `%s'",
+           get_name ().c_str ());
+
+  return cdef_object ();
+}
+
+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 (tree_classdef* t)
+{
+  cdef_class retval;
+  std::string class_name;
+
+  // Class creation
+
+  class_name = t->ident ()->name ();
+  gnulib::printf ("class: %s\n", class_name.c_str ());
+
+  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 ();
+
+          gnulib::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);
+              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 ();
+
+  // 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);
+
+          gnulib::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;
+          gnulib::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);
+
+                  gnulib::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);
+
+                  gnulib::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;
+          gnulib::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);
+
+                  gnulib::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 ());
+
+                  gnulib::printf ("property: %s\n", (*pit)->ident ()->name ().c_str ());
+                  if ((*pit)->expression ())
+                    {
+                      octave_value pvalue = (*pit)->expression ()->rvalue1 ();
+
+                      gnulib::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_meta* p = new octave_classdef_meta (*this);
+
+  return p;
+}
+
+octave_value
+cdef_property::cdef_property_rep::get_value (const cdef_object& obj,
+                                             bool do_check_access,
+                                             const std::string& who)
+{
+  octave_value retval;
+
+  if (do_check_access && ! check_get_access ())
+    {
+      gripe_property_access (who, wrap (), false);
+
+      return retval;
+    }
+
+  if (! obj.is_constructed ())
+    {
+      cdef_class cls (to_cdef (get ("DefiningClass")));
+
+      if (! obj.is_partially_constructed_for (cls))
+        {
+          ::error ("cannot reference properties of class `%s' for non-constructed object",
+                   cls.get_name ().c_str ());
+          return retval;
+        }
+    }
+ 
+  octave_value get_fcn = get ("GetMethod");
+
+  // FIXME: should check whether we're already in get accessor method
+
+  if (get_fcn.is_empty ())
+    retval = obj.get (get ("Name").string_value ());
+  else
+    {
+      octave_value_list args;
+
+      args(0) = to_ov (obj);
+      
+      args = execute_ov (get_fcn, args, 1);
+
+      if (! error_state)
+	retval = args(0);
+    }
+
+  return retval;
+}
+
+octave_value
+cdef_property::cdef_property_rep::get_value (bool do_check_access,
+                                             const std::string& who)
+{
+  if (do_check_access && ! check_get_access ())
+    {
+      gripe_property_access (who, wrap (), false);
+
+      return octave_value ();
+    }
+
+  return get ("DefaultValue");
+}
+
+bool
+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,
+                                             bool do_check_access,
+                                             const std::string& who)
+{
+  if (do_check_access && ! check_set_access ())
+    {
+      gripe_property_access (who, wrap (), true);
+
+      return;
+    }
+
+  if (! obj.is_constructed ())
+    {
+      cdef_class cls (to_cdef (get ("DefiningClass")));
+
+      if (! obj.is_partially_constructed_for (cls))
+        {
+          ::error ("cannot reference properties of class `%s' for non-constructed object",
+                   cls.get_name ().c_str ());
+          return;
+        }
+    }
+ 
+  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::cdef_property_rep::check_get_access (void) const
+{
+  cdef_class cls (to_cdef (get ("DefiningClass")));
+
+  if (! error_state)
+    return ::check_access (cls, get ("GetAccess"));
+
+  return false;
+}
+
+bool
+cdef_property::cdef_property_rep::check_set_access (void) const
+{
+  cdef_class cls (to_cdef (get ("DefiningClass")));
+
+  if (! error_state)
+    return ::check_access (cls, get ("SetAccess"));
+
+  return false;
+}
+
+void
+cdef_method::cdef_method_rep::check_method (void)
+{
+  // FIXME: check whether re-load is needed
+}
+
+octave_value_list
+cdef_method::cdef_method_rep::execute (const octave_value_list& args,
+				       int nargout, bool do_check_access,
+                                       const std::string& who)
+{
+  octave_value_list retval;
+
+  if (do_check_access && ! check_access ())
+    {
+      gripe_method_access (who, wrap ());
+
+      return retval;
+    }
+
+  if (! get ("Abstract").bool_value ())
+    {
+      check_method ();
+
+      if (function.is_defined ())
+	{
+	  retval = execute_ov (function, args, nargout);
+	}
+    }
+  else
+    error ("%s: cannot execute abstract method",
+	   get ("Name").string_value ().c_str ());
+
+  return retval;
+}
+
+octave_value_list
+cdef_method::cdef_method_rep::execute (const cdef_object& obj,
+				       const octave_value_list& args,
+				       int nargout, bool do_check_access,
+                                       const std::string& who)
+{
+  octave_value_list retval;
+
+  if (do_check_access && ! check_access ())
+    {
+      gripe_method_access (who, wrap ());
+
+      return retval;
+    }
+
+  if (! get ("Abstract").bool_value ())
+    {
+      check_method ();
+
+      octave_value_list new_args;
+
+      if (function.is_defined ())
+	{
+	  new_args.resize (args.length () + 1);
+
+	  new_args(0) = to_ov (obj);
+	  for (int i = 0; i < args.length (); i++)
+	    new_args(i+1) = args(i);
+
+	  retval = execute_ov (function, new_args, nargout);
+	}
+    }
+  else
+    error ("%s: cannot execute abstract method",
+	   get ("Name").string_value ().c_str ());
+
+  return retval;
+}
+
+bool
+cdef_method::cdef_method_rep::is_constructor (void) const
+{
+  if (function.is_function())
+    return function.function_value ()->is_classdef_constructor ();
+
+  return false;
+}
+
+bool
+cdef_method::cdef_method_rep::check_access (void) const
+{
+  cdef_class cls (to_cdef (get ("DefiningClass")));
+
+  if (! error_state)
+    return ::check_access (cls, get ("Access"));
+
+  return false;
+}
+
+octave_value_list
+cdef_method::cdef_method_rep::meta_subsref
+  (const std::string& type, const std::list<octave_value_list>& idx,
+   int nargout)
+{
+  octave_value_list retval;
+
+  switch (type[0])
+    {
+    case '(':
+      retval = execute (idx.front (), type.length () > 1 ? 1 : nargout, true);
+      break;
+
+    default:
+      error ("invalid meta.method indexing");
+      break;
+    }
+
+  if (! error_state)
+    {
+      if (type.length () > 1 && idx.size () > 1 && ! retval.empty ())
+	retval = retval(0).next_subsref (nargout, type, idx, 1);
+    }
+
+  return retval;
+}
+
+static cdef_package
+lookup_package (const std::string& name)
+{
+  return cdef_manager::find_package (name);
+}
+
+static octave_value_list
+package_fromName (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1)
+    {
+      std::string name = args(0).string_value ();
+
+      if (! error_state)
+	retval(0) = to_ov (lookup_package (name));
+      else
+	error ("fromName: invalid package name, expected a string value");
+    }
+  else
+    error ("fromName: invalid number of parameters");
+
+  return retval;
+}
+
+static octave_value_list
+package_get_classes (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval (1, Matrix ());
+
+  if (args.length () == 1 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.package")
+    {
+      cdef_package pack (to_cdef (args(0)));
+
+      retval(0) = pack.get_classes ();
+    }
+
+  return retval;
+}
+
+static octave_value_list
+package_get_functions (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval (1, Matrix ());
+
+  if (args.length () == 0 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.package")
+    {
+      cdef_package pack (to_cdef (args(0)));
+
+      retval(0) = pack.get_functions ();
+    }
+
+  return retval;
+}
+
+static octave_value_list
+package_get_packages (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval (1, Matrix ());
+
+  if (args.length () == 0 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.package")
+    {
+      cdef_package pack (to_cdef (args(0)));
+
+      retval(0) = pack.get_packages ();
+    }
+
+  return retval;
+}
+
+void
+cdef_package::cdef_package_rep::install_class (const cdef_class& cls,
+                                               const std::string& nm)
+{
+  class_map[nm] = cls;
+
+  member_count++;
+}
+
+void
+cdef_package::cdef_package_rep::install_function (const octave_value& fcn,
+                                                  const std::string& nm)
+{
+  function_map[nm] = fcn;
+}
+
+void
+cdef_package::cdef_package_rep::install_package (const cdef_package& pack,
+                                                 const std::string& nm)
+{
+  package_map[nm] = pack;
+
+  member_count++;
+}
+
+template<class T1, class T2>
+Cell
+map2Cell (const std::map<T1, T2>& m)
+{
+  Cell retval (1, m.size ());
+  int i = 0;
+
+  for (typename std::map<T1, T2>::const_iterator it = m.begin ();
+       it != m.end (); ++it, ++i)
+    {
+      retval(i) = to_ov (it->second);
+    }
+
+  return retval;
+}
+
+Cell
+cdef_package::cdef_package_rep::get_classes (void) const
+{ return map2Cell (class_map); }
+
+Cell
+cdef_package::cdef_package_rep::get_functions (void) const
+{ return map2Cell (function_map); }
+
+Cell
+cdef_package::cdef_package_rep::get_packages (void) const
+{ return map2Cell (package_map); }
+
+cdef_class cdef_class::_meta_class = cdef_class ();
+cdef_class cdef_class::_meta_property = cdef_class ();
+cdef_class cdef_class::_meta_method = cdef_class ();
+cdef_class cdef_class::_meta_package = cdef_class ();
+
+cdef_package cdef_package::_meta = cdef_package ();
+
+void
+install_classdef (void)
+{
+  octave_classdef::register_type ();
+
+  /* bootstrap */
+  cdef_class handle = make_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_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"));
+  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",
+		      make_fcn_handle (class_get_inferiorclasses, "meta.class>get.InferiorClasses"),
+		      "public", Matrix (), "private"));
+  meta_class.install_property
+      (make_property  (meta_class, "Methods",
+		       make_fcn_handle (class_get_methods, "meta.class>get.Methods"),
+		       "public", Matrix (), "private"));
+  meta_class.install_property
+      (make_property  (meta_class, "MethodList",
+		       make_fcn_handle (class_get_methods, "meta.class>get.MethodList"),
+		       "public", Matrix (), "private"));
+  meta_class.install_property (make_attribute (meta_class, "Name"));
+  meta_class.install_property
+      (make_property  (meta_class, "Properties",
+		       make_fcn_handle (class_get_properties, "meta.class>get.Properties"),
+		       "public", Matrix (), "private"));
+  meta_class.install_property
+      (make_property  (meta_class, "PropertyList",
+		       make_fcn_handle (class_get_properties, "meta.class>get.PropertyList"),
+		       "public", Matrix (), "private"));
+  meta_class.install_property (make_attribute (meta_class, "Sealed"));
+  meta_class.install_property
+      (make_property (meta_class, "SuperClasses",
+		      make_fcn_handle (class_get_superclasses, "meta.class>get.SuperClasses"),
+		      "public", Matrix (), "private"));
+  meta_class.install_property
+      (make_property (meta_class, "SuperClassList",
+		      make_fcn_handle (class_get_superclasses, "meta.class>get.SuperClassList"),
+		      "public", Matrix (), "private"));
+  /* meta.class methods */
+  meta_class.install_method (make_method (meta_class, "fromName", class_fromName,
+					  "public", true));
+  meta_class.install_method (make_method (meta_class, "fevalStatic", class_fevalStatic,
+					  "public", false));
+  meta_class.install_method (make_method (meta_class, "getConstant", class_getConstant,
+					  "public", false));
+  meta_class.install_method (make_method (meta_class, "eq", class_eq));
+  meta_class.install_method (make_method (meta_class, "ne", class_ne));
+  meta_class.install_method (make_method (meta_class, "lt", class_lt));
+  meta_class.install_method (make_method (meta_class, "le", class_le));
+  meta_class.install_method (make_method (meta_class, "gt", class_gt));
+  meta_class.install_method (make_method (meta_class, "ge", class_ge));
+
+  /* meta.method properties */
+  meta_method.install_property (make_attribute (meta_method, "Abstract"));
+  meta_method.install_property (make_attribute (meta_method, "Access"));
+  meta_method.install_property (make_attribute (meta_method, "DefiningClass"));
+  meta_method.install_property (make_attribute (meta_method, "Description"));
+  meta_method.install_property (make_attribute (meta_method, "DetailedDescription"));
+  meta_method.install_property (make_attribute (meta_method, "Hidden"));
+  meta_method.install_property (make_attribute (meta_method, "Name"));
+  meta_method.install_property (make_attribute (meta_method, "Sealed"));
+  meta_method.install_property (make_attribute (meta_method, "Static"));
+
+  /* meta.property properties */
+  meta_property.install_property (make_attribute (meta_property, "Name"));
+  meta_property.install_property (make_attribute (meta_property, "Description"));
+  meta_property.install_property (make_attribute (meta_property, "DetailedDescription"));
+  meta_property.install_property (make_attribute (meta_property, "Abstract"));
+  meta_property.install_property (make_attribute (meta_property, "Constant"));
+  meta_property.install_property (make_attribute (meta_property, "GetAccess"));
+  meta_property.install_property (make_attribute (meta_property, "SetAccess"));
+  meta_property.install_property (make_attribute (meta_property, "Dependent"));
+  meta_property.install_property (make_attribute (meta_property, "Transient"));
+  meta_property.install_property (make_attribute (meta_property, "Hidden"));
+  meta_property.install_property (make_attribute (meta_property, "GetObservable"));
+  meta_property.install_property (make_attribute (meta_property, "SetObservable"));
+  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
+
+  /* handle methods */
+  handle.install_method (make_method (handle, "delete", handle_delete));
+
+  /* meta.package properties */
+  meta_package.install_property (make_attribute (meta_package, "Name"));
+  meta_package.install_property (make_property  (meta_package, "ContainingPackage"));
+  meta_package.install_property
+      (make_property (meta_package, "ClassList",
+		      make_fcn_handle (package_get_classes, "meta.package>get.ClassList"),
+		      "public", Matrix (), "private"));
+  meta_package.install_property
+      (make_property (meta_package, "Classes",
+		      make_fcn_handle (package_get_classes, "meta.package>get.Classes"),
+		      "public", Matrix (), "private"));
+  meta_package.install_property
+      (make_property (meta_package, "FunctionList",
+		      make_fcn_handle (package_get_functions, "meta.package>get.FunctionList"),
+		      "public", Matrix (), "private"));
+  meta_package.install_property
+      (make_property (meta_package, "Functions",
+		      make_fcn_handle (package_get_functions, "meta.package>get.Functions"),
+		      "public", Matrix (), "private"));
+  meta_package.install_property
+      (make_property (meta_package, "PackageList",
+		      make_fcn_handle (package_get_packages, "meta.package>get.PackageList"),
+		      "public", Matrix (), "private"));
+  meta_package.install_property
+      (make_property (meta_package, "Packages",
+		      make_fcn_handle (package_get_packages, "meta.package>get.Packages"),
+		      "public", Matrix (), "private"));
+  meta_package.install_method (make_method (meta_package, "fromName", package_fromName,
+                                            "public", true));
+
+  /* create "meta" package */
+  cdef_package package_meta = cdef_package::_meta = make_package ("meta");
+  package_meta.install_class (meta_class,       "class");
+  package_meta.install_class (meta_property,    "property");
+  package_meta.install_class (meta_method,      "method");
+  package_meta.install_class (meta_package,     "package");
+  package_meta.install_class (meta_event,       "event");
+  package_meta.install_class (meta_dynproperty, "dynproperty");
+}
+
+//----------------------------------------------------------------------------
+
+cdef_manager* cdef_manager::instance = 0;
+
+void
+cdef_manager::create_instance (void)
+{
+  instance = new cdef_manager ();
+
+  if (instance)
+    singleton_cleanup_list::add (cleanup_instance);
+}
+
+cdef_class
+cdef_manager::do_find_class (const std::string& name,
+                             bool error_if_not_found, bool load_if_not_found)
+{
+  std::map<std::string, cdef_class>::iterator it = all_classes.find (name);
+
+  if (it == all_classes.end ())
+    {
+      // FIXME: implement this properly, take package prefix into account
+
+      if (load_if_not_found)
+        {
+          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 ());
+    }
+  else
+    {
+      cdef_class cls = it->second;
+
+      if (! cls.is_builtin ())
+        cls = lookup_class (cls);
+
+      if (cls.ok ())
+	return cls;
+      else
+	all_classes.erase (it);
+    }
+
+  return cdef_class ();
+}
+
+octave_function*
+cdef_manager::do_find_method_symbol (const std::string& method_name,
+                                     const std::string& class_name)
+{
+  octave_function *retval = 0;
+
+  cdef_class cls = find_class (class_name, false, false);
+
+  if (cls.ok ())
+    {
+      cdef_method meth = cls.find_method (method_name);
+
+      if (meth.ok ())
+        retval = new octave_classdef_meta (meth);
+    }
+
+  return retval;
+}
+
+cdef_package
+cdef_manager::do_find_package (const std::string& name,
+                               bool error_if_not_found)
+{
+  cdef_package retval;
+
+  std::map<std::string, cdef_package>::const_iterator it
+    = all_packages.find (name);
+
+  if (it != all_packages.end ())
+    {
+      retval = it->second;
+
+      if (! retval.ok ())
+        error ("invalid package `%s'", name.c_str ());
+    }
+  else if (error_if_not_found)
+    error ("unknown package `%s'", name.c_str ());
+
+  return retval;
+}
+
+//----------------------------------------------------------------------------
+
+DEFUN (__meta_get_package__, args, , "")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    {
+      std::string cname = args(0).string_value ();
+
+      if (! error_state)
+	retval = to_ov (lookup_package (cname));
+      else
+	error ("invalid package name, expected a string value");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+DEFUN (__superclass_reference__, args, /* nargout */,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __superclass_reference__ ()\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  return octave_value (new octave_classdef_superclass_ref (args));
+}
+
+DEFUN (__meta_class_query__, args, /* nargout */,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __meta_class_query__ ()\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  std::cerr << "__meta_class_query__ ("
+            << args(0).string_value () << ", "
+            << args(1).string_value () << ")"
+            << std::endl;
+
+  if (args.length () == 2)
+    {
+      std::string pkg = args(0).string_value ();
+      std::string cls = args(1).string_value ();
+
+      if (! pkg.empty ())
+        cls = pkg + "." + cls;
+
+      if (! error_state)
+	retval = to_ov (lookup_class (cls));
+      else
+	error ("invalid class name, expected a string value");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+DEFUN (metaclass, args, /* nargout */,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} metaclass (obj)\n\
+Returns the meta.class object corresponding to the class of @var{obj}.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    {
+      cdef_object obj = to_cdef (args(0));
+
+      if (! error_state)
+        retval = to_ov (obj.get_class ());
+      else
+        print_usage ();
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/ov-classdef.h	Mon Feb 11 15:45:26 2013 -0500
@@ -0,0 +1,1604 @@
+/*
+
+Copyright (C) 2012 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_classdef_h)
+#define octave_classdef_h 1
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "oct-map.h"
+#include "oct-refcount.h"
+#include "ov-base.h"
+
+class cdef_object;
+class cdef_class;
+class cdef_property;
+class cdef_method;
+class cdef_package;
+
+class tree_classdef;
+
+// This is mainly a boostrap class to declare the expected interface.
+// The actual base class is cdef_class_base, which is declared after
+// cdef_object, such that it can contain cdef_object objects.
+class
+cdef_object_rep
+{
+public:
+  friend class cdef_object;
+
+public:
+  cdef_object_rep (void) : refcount (1) { }
+
+  virtual ~cdef_object_rep (void) { }
+
+  virtual cdef_class get_class (void) const;
+
+  virtual void set_class (const cdef_class&)
+    { gripe_invalid_object ("set_class"); }
+
+  virtual cdef_object_rep* clone (void) const
+    {
+      gripe_invalid_object ("clone");
+      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_value_object (void) const { return false; }
+
+  virtual bool is_handle_object (void) const { return false; }
+
+  virtual bool is_meta_object (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"); }
+
+  virtual octave_value get (const std::string&) const
+    {
+      gripe_invalid_object ("get");
+      return octave_value ();
+    }
+
+  virtual octave_value_list
+  subsref (const std::string&, const std::list<octave_value_list>&,
+           int, size_t&, const cdef_class&)
+    {
+      gripe_invalid_object ("subsref");
+      return octave_value_list ();
+    }
+
+  virtual octave_value
+  subsasgn (const std::string&, const std::list<octave_value_list>&,
+            const octave_value&)
+    {
+      gripe_invalid_object ("subsasgn");
+      return octave_value ();
+    }
+
+  virtual string_vector map_keys(void) const;
+
+  virtual bool is_valid (void) const { return false; }
+
+  std::string class_name (void) const;
+
+  virtual void mark_for_construction (const cdef_class&)
+    { gripe_invalid_object ("mark_for_construction"); }
+
+  virtual bool is_constructed_for (const cdef_class&) const
+    {
+      gripe_invalid_object ("is_constructed_for");
+      return false;
+    }
+
+  virtual bool is_partially_constructed_for (const cdef_class&) const
+    {
+      gripe_invalid_object ("is_partially_constructed_for");
+      return false;
+    }
+
+  virtual void mark_as_constructed (void)
+    { gripe_invalid_object ("mark_as_constructed"); }
+
+  virtual void mark_as_constructed (const cdef_class&)
+    { gripe_invalid_object ("mark_as_constructed"); }
+
+  virtual bool is_constructed (void) const
+    {
+      gripe_invalid_object ("is_constructed");
+      return false;
+    }
+
+  virtual octave_idx_type static_count (void) const { return 0; }
+
+  virtual void destroy (void) { delete this; }
+
+  void release (void)
+    {
+      if (--refcount == static_count ())
+        destroy ();
+    }
+
+  virtual dim_vector dims (void) const { return dim_vector (); }
+
+protected:
+  /* reference count */
+  octave_refcount<octave_idx_type> refcount;
+
+protected:
+  /* Restricted copying */
+  cdef_object_rep (const cdef_object_rep&)
+    : refcount (1) { }
+
+private:
+  /* No assignment */
+  cdef_object_rep& operator = (const cdef_object_rep& );
+
+  void gripe_invalid_object (const char *who) const
+    { error ("%s: invalid object", who); }
+};
+
+class
+cdef_object
+{
+public:
+  /* FIXME: use a null object */
+  cdef_object (void)
+      : rep (new cdef_object_rep ()) { }
+
+  cdef_object (const cdef_object& obj)
+    : rep (obj.rep)
+    {
+      rep->refcount++;
+    }
+
+  cdef_object (cdef_object_rep *r)
+      : rep (r) { }
+
+  virtual ~cdef_object (void)
+    { rep->release (); }
+
+  cdef_object& operator = (const cdef_object& obj)
+    {
+      if (rep != obj.rep)
+	{
+          rep->release ();
+
+	  rep = obj.rep;
+	  rep->refcount++;
+	}
+
+      return *this;
+    }
+
+  cdef_class get_class (void) const;
+
+  void set_class (const cdef_class& cls) { rep->set_class (cls); }
+
+  std::string class_name (void) const
+    { return rep->class_name (); }
+
+  cdef_object clone (void) const
+    { return cdef_object (rep->clone ()); }
+
+  cdef_object empty_clone (void) const
+    { return cdef_object (rep->empty_clone ()); }
+
+  dim_vector dims (void) const { return rep->dims (); }
+
+  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_value_object (void) const { return rep->is_value_object (); }
+
+  bool is_handle_object (void) const { return rep->is_handle_object (); }
+
+  bool is_meta_object (void) const { return rep->is_meta_object (); }
+
+  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); }
+
+  octave_value get (const std::string& pname) const
+    { return rep->get (pname); }
+
+  octave_value_list
+  subsref (const std::string& type, const std::list<octave_value_list>& idx,
+           int nargout, size_t& skip, const cdef_class& context)
+    { return rep->subsref (type, idx, nargout, skip, context); }
+
+  octave_value
+  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
+            const octave_value& rhs)
+    {
+      make_unique ();
+      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; }
+
+  bool ok (void) const { return rep->is_valid (); }
+
+  void mark_for_construction (const cdef_class& cls)
+    { rep->mark_for_construction (cls); }
+
+  bool is_constructed (void) const { return rep->is_constructed (); }
+
+  bool is_constructed_for (const cdef_class& cls) const
+    { return rep->is_constructed_for (cls); }
+
+  bool is_partially_constructed_for (const cdef_class& cls) const
+    { return rep->is_partially_constructed_for (cls); }
+
+  void mark_as_constructed (void) { rep->mark_as_constructed (); }
+
+  void mark_as_constructed (const cdef_class& cls)
+    { rep->mark_as_constructed (cls); }
+
+protected:
+  cdef_object_rep* get_rep (void) { return rep; }
+
+  void make_unique (void)
+    {
+      if (rep->refcount > 1)
+        *this = clone ();
+    }
+
+private:
+  cdef_object_rep *rep;
+};
+
+class
+cdef_object_base : public cdef_object_rep
+{
+public:
+  cdef_object_base (void)
+    : cdef_object_rep (), klass ()
+    {
+      register_object ();
+    }
+
+  ~cdef_object_base (void) { unregister_object (); }
+
+  cdef_class get_class (void) const;
+
+  void set_class (const cdef_class& cls);
+
+  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)
+    : cdef_object_rep (obj), klass (obj.klass)
+    {
+      register_object ();
+    }
+
+private:
+  void register_object (void);
+
+  void unregister_object (void);
+
+private:
+  // The class of the object
+  cdef_object klass;
+
+private:
+  // No assignment!
+  cdef_object_base& operator = (const cdef_object_base&);
+};
+
+class
+cdef_object_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); }
+
+  dim_vector dims (void) const { return array.dims (); }
+
+  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:
+  cdef_object_scalar (void) : cdef_object_base () { }
+
+  ~cdef_object_scalar (void) { }
+
+  dim_vector dims (void) const { return dim_vector (1, 1); }
+
+  void put (const std::string& pname, const octave_value& val)
+    { map.assign (pname, val); }
+
+  octave_value get (const std::string& pname) const
+    {
+      Cell val = map.contents (pname);
+
+      if (val.numel () > 0)
+	return val(0, 0);
+      else
+	{
+	  error ("get: unknown slot: %s", pname.c_str ());
+	  return octave_value ();
+	}
+    }
+
+  octave_value_list
+  subsref (const std::string& type, const std::list<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);
+
+  void mark_for_construction (const cdef_class&);
+
+  bool is_constructed_for (const cdef_class& cls) const;
+
+  bool is_partially_constructed_for (const cdef_class& cls) const;
+
+  void mark_as_constructed (void) { ctor_list.clear (); }
+
+  void mark_as_constructed (const cdef_class& cls) { ctor_list.erase (cls); }
+
+  bool is_constructed (void) const { return ctor_list.empty (); }
+
+protected:
+  // Object property values
+  Octave_map map;
+
+  // Internal/temporary structure used during object construction
+  std::map< cdef_class, std::list<cdef_class> > ctor_list;
+
+protected:
+  // Restricted object copying!
+  cdef_object_scalar (const cdef_object_scalar& obj)
+    : cdef_object_base (obj), map (obj.map), ctor_list (obj.ctor_list) { }
+
+private:
+  // No assignment!
+  cdef_object_scalar& operator = (const cdef_object_scalar&);
+};
+
+class
+handle_cdef_object : public cdef_object_scalar
+{
+public:
+  handle_cdef_object (void)
+      : cdef_object_scalar () { }
+
+  ~handle_cdef_object (void);
+
+  cdef_object_rep* clone (void) const
+    {
+      handle_cdef_object *obj = const_cast<handle_cdef_object *> (this);
+      obj->refcount++;
+      return obj;
+    }
+
+  cdef_object_rep* copy (void) const
+    { return new handle_cdef_object (*this); }
+
+  bool is_valid (void) const { return true; }
+
+  bool is_handle_object (void) const { return true; }
+
+protected:
+  // Restricted copying!
+  handle_cdef_object (const handle_cdef_object& obj)
+    : cdef_object_scalar (obj) { }
+
+private:
+  // No assignment
+  handle_cdef_object& operator = (const handle_cdef_object&);
+};
+
+class
+value_cdef_object : public cdef_object_scalar
+{
+public:
+  value_cdef_object (void)
+      : cdef_object_scalar () { }
+
+  ~value_cdef_object (void);
+
+  cdef_object_rep* clone (void) const
+    { return new value_cdef_object (*this); }
+
+  cdef_object_rep* copy (void) const { return clone (); }
+
+  bool is_valid (void) const { return true; }
+
+  bool is_value_object (void) const { return true; }
+
+private:
+  // Private copying!
+  value_cdef_object (const value_cdef_object& obj)
+    : cdef_object_scalar (obj) { }
+
+  // No assignment!
+  value_cdef_object& operator = (const value_cdef_object&);
+};
+
+class
+cdef_meta_object_rep : public handle_cdef_object
+{
+public:
+  cdef_meta_object_rep (void)
+    : handle_cdef_object () { }
+
+  ~cdef_meta_object_rep (void) { }
+
+  cdef_object_rep* copy (void) const
+    { return new cdef_meta_object_rep (*this); }
+
+  bool is_meta_object (void) const { return true; }
+
+  virtual bool is_class (void) const { return false; }
+
+  virtual bool is_property (void) const { return false; }
+
+  virtual bool is_method (void) const { return false; }
+
+  virtual bool is_package (void) const { return false; }
+  
+  virtual octave_value_list
+  meta_subsref (const std::string& /* type */,
+                const std::list<octave_value_list>& /* idx */,
+                int /* nargout */)
+    {
+      ::error ("subsref: invalid meta object");
+      return octave_value_list ();
+    }
+
+  virtual void meta_release (void) { }
+
+  virtual bool meta_is_postfix_index_handled (char /* type */) const
+    { return false; }
+
+protected:
+  // Restricted copying!
+  cdef_meta_object_rep (const cdef_meta_object_rep& obj)
+    : handle_cdef_object (obj) { }
+
+private:
+  // No assignment!
+  cdef_meta_object_rep& operator = (const cdef_meta_object_rep&);
+};
+
+class
+cdef_meta_object : public cdef_object
+{
+public:
+  cdef_meta_object (void)
+    : cdef_object () { }
+
+  cdef_meta_object (const cdef_meta_object& obj)
+    : cdef_object (obj) { }
+
+  cdef_meta_object (cdef_meta_object_rep *r)
+    : cdef_object (r) { }
+
+  // Object consistency is checked in sub-classes.
+  cdef_meta_object (const cdef_object& obj)
+    : cdef_object (obj) { }
+
+  ~cdef_meta_object (void) { }
+
+  bool is_class (void) const { return get_rep ()->is_class (); }
+
+  bool is_property (void) const { return get_rep ()->is_property (); }
+
+  bool is_method (void) const { return get_rep ()->is_method (); }
+
+  bool is_package (void) const { return get_rep ()->is_package (); }
+
+  octave_value_list
+  meta_subsref (const std::string& type,
+                const std::list<octave_value_list>& idx, int nargout)
+    { return get_rep ()->meta_subsref (type, idx, nargout); }
+
+  void meta_release (void) { get_rep ()->meta_release (); }
+
+  bool meta_is_postfix_index_handled (char type) const
+    { return get_rep ()->meta_is_postfix_index_handled (type); }
+
+private:
+  cdef_meta_object_rep* get_rep (void)
+    { return dynamic_cast<cdef_meta_object_rep *> (cdef_object::get_rep ()); }
+  
+  const cdef_meta_object_rep* get_rep (void) const
+    { return dynamic_cast<const cdef_meta_object_rep *> (cdef_object::get_rep ()); }
+};
+
+class
+cdef_class : public cdef_meta_object
+{
+private:
+
+  class
+  cdef_class_rep : public cdef_meta_object_rep
+  {
+  public:
+    cdef_class_rep (void)
+	: cdef_meta_object_rep (), member_count (0), handle_class (false),
+          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
+      { return get ("Name").string_value (); }
+
+    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);
+
+    Cell get_methods (void);
+
+    cdef_property find_property (const std::string& nm);
+
+    void install_property (const cdef_property& prop);
+
+    Cell get_properties (void);
+
+    string_vector get_names (void);
+
+    void set_directory (const std::string& dir) { directory = dir; }
+
+    std::string get_directory (void) const { return directory; }
+
+    void delete_object (cdef_object obj);
+
+    octave_value_list
+    meta_subsref (const std::string& type,
+                  const std::list<octave_value_list>& idx, int nargout);
+
+    void meta_release (void);
+
+    bool meta_is_postfix_index_handled (char type) const
+      { return (type == '(' || type == '.'); }
+
+    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);
+
+    void mark_as_handle_class (void) { handle_class = true; }
+
+    bool is_handle_class (void) const { return handle_class; }
+
+    void register_object (void) { object_count++; }
+
+    void unregister_object (void) { object_count--; }
+
+    octave_idx_type static_count (void) const { return member_count; }
+
+    void destroy (void)
+      {
+        if (member_count)
+          {
+            refcount++;
+            cdef_class lock (this);
+
+            member_count = 0;
+            method_map.clear ();
+            property_map.clear ();
+          }
+        else
+          delete this;
+      }
+
+    void mark_as_meta_class (void) { meta = true; }
+
+    bool is_meta_class (void) const { return meta; }
+
+  private:
+    void load_all_methods (void);
+
+    void find_names (std::set<std::string>& names, bool all);
+    
+    void find_properties (std::map<std::string,cdef_property>& props,
+                          bool only_inherited);
+
+    void find_methods (std::map<std::string, cdef_method>& meths,
+                       bool only_inherited);
+
+    cdef_class wrap (void)
+      {
+        refcount++;
+        return cdef_class (this);
+      }
+
+  private:
+    // The @-directory were this class is loaded from.
+    // (not used yet)
+    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;
+
+    // The number of members in this class (methods, properties...)
+    octave_idx_type member_count;
+
+    // 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;
+
+    // The list of super-class constructors that are called implicitly by the
+    // the classdef engine when creating an object. These constructors are not
+    // called explicitly by the class constructor.
+    std::list<cdef_class> implicit_ctor_list;
+
+    // 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)
+      : cdef_meta_object_rep (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:
+  // Create and invalid class object
+  cdef_class (void)
+      : cdef_meta_object () { }
+
+  cdef_class (const std::string& nm,
+              const std::list<cdef_class>& superclasses)
+      : cdef_meta_object (new cdef_class_rep (superclasses))
+    { get_rep ()->set_name (nm); }
+
+  cdef_class (const cdef_class& cls)
+      : cdef_meta_object (cls) { }
+
+  cdef_class (const cdef_object& obj)
+      : cdef_meta_object (obj)
+    {
+      // This should never happen...
+      if (! is_class ())
+	error ("internal error: invalid assignment from %s to meta.class object",
+	       class_name ().c_str ());
+    }
+
+  cdef_class& operator = (const cdef_class& cls)
+    {
+      cdef_object::operator= (cls);
+
+      return *this;
+    }
+
+  cdef_method find_method (const std::string& nm, bool local = false);
+
+  void install_method (const cdef_method& meth)
+    { get_rep ()->install_method (meth); }
+
+  Cell get_methods (void) { return get_rep ()->get_methods (); }
+
+  cdef_property find_property (const std::string& nm);
+  
+  void install_property (const cdef_property& prop)
+    { get_rep ()->install_property (prop); }
+
+  Cell get_properties (void) { return get_rep ()->get_properties (); }
+
+  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); }
+
+  std::string get_directory (void) const
+    { return get_rep ()->get_directory (); }
+
+  std::string get_name (void) const
+    { return get_rep ()->get_name (); }
+
+  bool is_builtin (void) const
+    { return get_directory ().empty (); }
+
+  void delete_object (cdef_object obj)
+    { get_rep ()->delete_object (obj); }
+
+  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); }
+
+  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); }
+
+  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 (); }
+
+  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; }
+  static const cdef_class& meta_package (void) { return _meta_package; }
+
+  void register_object (void) { get_rep ()->register_object (); }
+
+  void unregister_object (void) { get_rep ()->unregister_object (); }
+
+private:
+  cdef_class_rep* get_rep (void)
+    { return dynamic_cast<cdef_class_rep *> (cdef_object::get_rep ()); }
+  
+  const cdef_class_rep* get_rep (void) const
+    { return dynamic_cast<const cdef_class_rep *> (cdef_object::get_rep ()); }
+
+  friend bool operator == (const cdef_class&, const cdef_class&);
+  friend bool operator != (const cdef_class&, const cdef_class&);
+  friend bool operator < (const cdef_class&, const cdef_class&);
+
+private:
+  static cdef_class _meta_class;
+  static cdef_class _meta_property;
+  static cdef_class _meta_method;
+  static cdef_class _meta_package;
+
+  friend void install_classdef (void);
+};
+
+inline bool
+operator == (const cdef_class& clsa, const cdef_class& clsb)
+// FIXME: is this really the right way to check class equality?
+{ return (clsa.get_rep () == clsb.get_rep ()); }
+
+inline bool
+operator != (const cdef_class& clsa, const cdef_class& clsb)
+{ return ! (clsa == clsb); }
+
+// This is only to be able to use cdef_class as map keys.
+inline bool
+operator < (const cdef_class& clsa, const cdef_class& clsb)
+{ return clsa.get_rep () < clsb.get_rep (); }
+
+class
+cdef_property : public cdef_meta_object
+{
+  friend class cdef_class;
+
+private:
+
+  class
+  cdef_property_rep : public cdef_meta_object_rep
+  {
+  public:
+    cdef_property_rep (void)
+	: cdef_meta_object_rep () { }
+
+    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 (); }
+
+    void set_name (const std::string& nm) { put ("Name", nm); }
+
+    bool is_constant (void) const { return get("Constant").bool_value (); }
+
+    octave_value get_value (bool do_check_access = true,
+                            const std::string& who = std::string ());
+
+    octave_value get_value (const cdef_object& obj,
+                            bool do_check_access = true,
+                            const std::string& who = std::string ());
+
+    void set_value (cdef_object& obj, const octave_value& val,
+                    bool do_check_access = true,
+                    const std::string& who = std::string ());
+
+    bool check_get_access (void) const;
+
+    bool check_set_access (void) const;
+
+  private:
+    cdef_property_rep (const cdef_property_rep& p)
+      : cdef_meta_object_rep (p) { }
+
+    bool is_recursive_set (const cdef_object& obj) const;
+
+    cdef_property wrap (void)
+      {
+        refcount++;
+        return cdef_property (this);
+      }
+  };
+
+public:
+  cdef_property (void) : cdef_meta_object () { }
+
+  cdef_property (const std::string& nm)
+      : cdef_meta_object (new cdef_property_rep ())
+    { get_rep ()->set_name (nm); }
+
+  cdef_property (const cdef_property& prop)
+      : cdef_meta_object (prop) { }
+
+  cdef_property (const cdef_object& obj)
+      : cdef_meta_object (obj)
+    {
+      // This should never happen...
+      if (! is_property ())
+	error ("internal error: invalid assignment from %s to meta.property object",
+	       class_name ().c_str ());
+    }
+
+  cdef_property& operator = (const cdef_property& prop)
+    {
+      cdef_object::operator= (prop);
+
+      return *this;
+    }
+
+  octave_value get_value (const cdef_object& obj, bool do_check_access = true,
+                          const std::string& who = std::string ())
+    { return get_rep ()->get_value (obj, do_check_access, who); }
+
+  octave_value get_value (bool do_check_access = true,
+                          const std::string& who = std::string ())
+    { return get_rep ()->get_value (do_check_access, who); }
+
+  void set_value (cdef_object& obj, const octave_value& val,
+                  bool do_check_access = true,
+                  const std::string& who = std::string ())
+    { get_rep ()->set_value (obj, val, do_check_access, who); }
+
+  bool check_get_access (void) const
+    { return get_rep ()->check_get_access (); }
+  
+  bool check_set_access (void) const
+    { return get_rep ()->check_set_access (); }
+
+  std::string get_name (void) const { return get_rep ()->get_name (); }
+
+  bool is_constant (void) const { return get_rep ()->is_constant (); }
+
+private:
+  cdef_property_rep* get_rep (void)
+    { return dynamic_cast<cdef_property_rep *> (cdef_object::get_rep ()); }
+  
+  const cdef_property_rep* get_rep (void) const
+    { return dynamic_cast<const cdef_property_rep *> (cdef_object::get_rep ()); }
+};
+
+class
+cdef_method : public cdef_meta_object
+{
+  friend class cdef_class;
+
+private:
+
+  class
+  cdef_method_rep : public cdef_meta_object_rep
+  {
+  public:
+    cdef_method_rep (void) : cdef_meta_object_rep () { }
+
+    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 (); }
+
+    void set_name (const std::string& nm) { put ("Name", nm); }
+
+    bool is_static (void) const { return get("Static").bool_value (); }
+
+    octave_value get_function (void) const { return function; }
+
+    void set_function (const octave_value& fcn) { function = fcn; }
+
+    bool check_access (void) const;
+
+    octave_value_list execute (const octave_value_list& args, int nargout,
+                               bool do_check_access = true,
+                               const std::string& who = std::string ());
+
+    octave_value_list execute (const cdef_object& obj,
+			       const octave_value_list& args, int nargout,
+                               bool do_check_access = true,
+                               const std::string& who = std::string ());
+
+    bool is_constructor (void) const;
+
+    octave_value_list
+    meta_subsref (const std::string& type,
+                  const std::list<octave_value_list>& idx, int nargout);
+
+    bool meta_is_postfix_index_handled (char type) const
+      { return (type == '(' || type == '.'); }
+
+  private:
+    cdef_method_rep (const cdef_method_rep& m)
+      : cdef_meta_object_rep (m), function (m.function) { }
+
+    void check_method (void);
+
+    cdef_method wrap (void)
+      {
+        refcount++;
+        return cdef_method (this);
+      }
+
+  private:
+    octave_value function;
+  };
+
+public:
+  cdef_method (void) : cdef_meta_object () { }
+
+  cdef_method (const std::string& nm)
+      : cdef_meta_object (new cdef_method_rep ())
+    { get_rep ()->set_name (nm); }
+
+  cdef_method (const cdef_method& meth)
+      : cdef_meta_object (meth) { }
+
+  cdef_method (const cdef_object& obj)
+      : cdef_meta_object (obj)
+    {
+      // This should never happen...
+      if (! is_method ())
+	error ("internal error: invalid assignment from %s to meta.method object",
+	       class_name ().c_str ());
+    }
+
+  cdef_method& operator = (const cdef_method& meth)
+    {
+      cdef_object::operator= (meth);
+
+      return *this;
+    }
+
+  /* normal invokation */
+  octave_value_list execute (const octave_value_list& args, int nargout,
+                             bool do_check_access = true,
+                             const std::string& who = std::string ())
+    { return get_rep ()->execute (args, nargout, do_check_access, who); }
+
+  /* dot-invokation: object is pushed as 1st argument */
+  octave_value_list execute (const cdef_object& obj,
+			     const octave_value_list& args, int nargout,
+                             bool do_check_access = true,
+                             const std::string& who = std::string ())
+    { return get_rep ()->execute (obj, args, nargout, do_check_access, who); }
+
+  bool check_access (void) const { return get_rep ()->check_access (); }
+  
+  std::string get_name (void) const { return get_rep ()->get_name (); }
+
+  bool is_static (void) const { return get_rep ()->is_static (); }
+
+  void set_function (const octave_value& fcn)
+    { get_rep ()->set_function (fcn); }
+
+  octave_value get_function (void) const
+    { return get_rep ()->get_function (); }
+
+  bool is_constructor (void) const
+    { return get_rep ()->is_constructor (); }
+
+private:
+  cdef_method_rep* get_rep (void)
+    { return dynamic_cast<cdef_method_rep *> (cdef_object::get_rep ()); }
+  
+  const cdef_method_rep* get_rep (void) const
+    { return dynamic_cast<const cdef_method_rep *> (cdef_object::get_rep ()); }
+};
+
+inline cdef_class
+cdef_object_rep::get_class (void) const
+{
+  gripe_invalid_object ("get_class");
+  return cdef_class ();
+}
+
+inline std::string
+cdef_object_rep::class_name (void) const
+{ return get_class ().get_name (); }
+
+inline cdef_class
+cdef_object::get_class (void) const
+{ return rep->get_class (); }
+
+inline cdef_class
+cdef_object_base::get_class (void) const
+{ return cdef_class (klass); }
+
+inline void
+cdef_object_base::set_class (const cdef_class& cls)
+{
+  if ((klass.ok () && cls.ok () && cls != get_class ())
+      || (klass.ok () && ! cls.ok ())
+      || (! klass.ok () && cls.ok ()))
+    {
+      unregister_object ();
+      klass = cls;
+      register_object ();
+    }
+}
+
+inline void
+cdef_object_base::register_object (void)
+{
+  if (klass.ok ())
+    {
+      cdef_class cls (get_class ());
+
+      if (! error_state && cls.ok ())
+        cls.register_object ();
+    }
+}
+
+inline void
+cdef_object_base::unregister_object (void)
+{
+  if (klass.ok ())
+    {
+      cdef_class cls (get_class ());
+
+      if (! error_state && cls.ok ())
+        cls.unregister_object ();
+    }
+}
+
+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); }
+
+inline cdef_property
+cdef_class::find_property (const std::string& nm)
+{ return get_rep ()->find_property (nm); }
+
+class
+cdef_package : public cdef_meta_object
+{
+  friend class cdef_class;
+
+private:
+
+  class
+  cdef_package_rep : public cdef_meta_object_rep
+  {
+  public:
+    cdef_package_rep (void) : cdef_meta_object_rep (), 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 (); }
+
+    void set_name (const std::string& nm) { put ("Name", nm); }
+
+    void install_class (const cdef_class& cls, const std::string& nm);
+
+    void install_function (const octave_value& fcn, const std::string& nm);
+
+    void install_package (const cdef_package& pack, const std::string& nm);
+
+    Cell get_classes (void) const;
+
+    Cell get_functions (void) const;
+
+    Cell get_packages (void) const;
+
+    octave_idx_type static_count (void) const { return member_count; }
+
+    void destroy (void)
+      {
+        if (member_count)
+          {
+            refcount++;
+            cdef_package lock (this);
+
+            member_count = 0;
+            class_map.clear ();
+            package_map.clear ();
+          }
+        else
+          delete this;
+      }
+
+  private:
+    std::map<std::string, cdef_class> class_map;
+    std::map<std::string, octave_value> function_map;
+    std::map<std::string, cdef_package> package_map;
+
+    // The number of registered members in this package (classes, packages).
+    // This only accounts for the members that back-reference to this package.
+    octave_idx_type member_count;
+
+    typedef std::map<std::string, cdef_class>::iterator class_iterator;
+    typedef std::map<std::string, cdef_class>::const_iterator class_const_iterator;
+    typedef std::map<std::string, octave_value>::iterator function_iterator;
+    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)
+      : cdef_meta_object_rep (p), class_map (p.class_map),
+        function_map (p.function_map), package_map (p.package_map),
+        member_count (p.member_count) { }
+  };
+
+public:
+  cdef_package (void) : cdef_meta_object () { }
+
+  cdef_package (const std::string& nm)
+      : cdef_meta_object (new cdef_package_rep ())
+    { get_rep ()->set_name (nm); }
+
+  cdef_package (const cdef_package& pack)
+    : cdef_meta_object (pack) { }
+
+  cdef_package (const cdef_object& obj)
+      : cdef_meta_object (obj)
+    {
+      // This should never happen...
+      if (! is_package ())
+	error ("internal error: invalid assignment from %s to meta.package object",
+	       class_name ().c_str ());
+    }
+
+  cdef_package& operator = (const cdef_package& pack)
+    {
+      cdef_object::operator= (pack);
+
+      return *this;
+    }
+
+  void install_class (const cdef_class& cls, const std::string& nm)
+    { get_rep ()->install_class (cls, nm); }
+
+  void install_function (const octave_value& fcn, const std::string& nm)
+    { get_rep ()->install_function (fcn, nm); }
+
+  void install_package (const cdef_package& pack, const std::string& nm)
+    { get_rep ()->install_package (pack, nm); }
+
+  Cell get_classes (void) const
+    { return get_rep ()->get_classes (); }
+
+  Cell get_functions (void) const
+    { return get_rep ()->get_functions (); }
+
+  Cell get_packages (void) const
+    { return get_rep ()->get_packages (); }
+
+  std::string get_name (void) const { return get_rep ()->get_name (); }
+
+  static const cdef_package& meta (void) { return _meta; }
+
+private:
+  cdef_package_rep* get_rep (void)
+    { return dynamic_cast<cdef_package_rep *> (cdef_object::get_rep ()); }
+  
+  const cdef_package_rep* get_rep (void) const
+    { return dynamic_cast<const cdef_package_rep *> (cdef_object::get_rep ()); }
+
+private:
+  static cdef_package _meta;
+
+  friend void install_classdef (void);
+};
+
+class
+octave_classdef : public octave_base_value
+{
+public:
+  octave_classdef (void)
+      : octave_base_value (), object () { }
+
+  octave_classdef (const cdef_object& obj)
+      : octave_base_value (), object (obj) { }
+
+  octave_classdef (const octave_classdef& obj)
+      : octave_base_value (obj), object (obj.object) { }
+
+  octave_base_value* clone (void) const
+    { return new octave_classdef (object.clone ()); }
+
+  octave_base_value* empty_clone (void) const
+    { return new octave_classdef (object.empty_clone ()); }
+
+  cdef_object get_object (void) const { return object; }
+
+  cdef_object& get_object_ref (void) { return object; }
+
+  bool is_defined (void) const { return true; }
+
+  bool is_map (void) const { return true; }
+
+  bool print_as_scalar (void) const { return true; }
+
+  void print(std::ostream& os, bool pr_as_read_syntax = false) const
+    {
+      // FIXME: should call "display" method
+      print_raw(os, pr_as_read_syntax);
+      newline(os);
+    }
+
+  void print_raw(std::ostream& os, bool /* pr_as_read_syntax */ = false) const
+    {
+      if (object.is_array ())
+        os << "array (" << object.dims ().str () << ") of "
+          << object.class_name () << " objects";
+      else
+        os << object.class_name () << " object";
+    }
+
+  octave_value_list subsref (const std::string& type,
+			     const std::list<octave_value_list>& idx, int nargout);
+
+  octave_value subsref (const std::string& type,
+			const std::list<octave_value_list>& idx)
+    {
+      octave_value_list retval = subsref (type, idx, 1);
+      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);
+
+  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 object.dims (); }
+
+private:
+  cdef_object object;
+
+private:
+  DECLARE_OCTAVE_ALLOCATOR
+
+public:
+  int type_id (void) const { return t_id; }
+  std::string type_name (void) const { return t_name; }
+  std::string class_name (void) const { return object.class_name (); }
+
+  static int static_type_id (void) { return t_id; }
+  static std::string static_type_name (void) { return t_name; }
+  static std::string static_class_name (void) { return "<unknown>"; }
+  static void register_type (void);
+
+private:
+  static int t_id;
+
+  static const std::string t_name;
+};
+
+inline octave_value
+to_ov (const cdef_object& obj)
+{
+  if (obj.ok ())
+    return octave_value (new octave_classdef (obj));
+  else
+    return octave_value (Matrix ());
+}
+
+inline octave_value
+to_ov (const octave_value& ov)
+{ return ov; }
+
+inline cdef_object
+to_cdef (const octave_value& val)
+{
+  if (val.type_name () == "object")
+    return dynamic_cast<octave_classdef *> (val.internal_rep ())->get_object ();
+  else
+    {
+      warning ("trying to cast non-object into object");
+      return cdef_object ();
+    }
+}
+
+inline cdef_object&
+to_cdef_ref (octave_value& val)
+{
+  static cdef_object empty;
+
+  if (val.type_name () == "object")
+    return dynamic_cast<octave_classdef *> (val.internal_rep ())->get_object_ref ();
+  else
+    {
+      warning ("trying to cast non-object into object");
+      return empty;
+    }
+}
+
+inline cdef_object
+to_cdef (const cdef_object& obj)
+{ return obj; }
+
+OCTINTERP_API void install_classdef (void);
+
+class
+cdef_manager
+{
+public:
+
+  static cdef_class find_class (const std::string& name,
+                                bool error_if_not_found = true,
+                                bool load_if_not_found = true)
+    {
+      if (instance_ok ())
+        return instance->do_find_class (name, error_if_not_found,
+                                        load_if_not_found);
+
+      return cdef_class ();
+    }
+
+  static octave_function* find_method_symbol (const std::string& method_name,
+                                              const std::string& class_name)
+    {
+      if (instance_ok ())
+        return instance->do_find_method_symbol (method_name, class_name);
+
+      return 0;
+    }
+
+  static cdef_package find_package (const std::string& name,
+                                    bool error_if_not_found = true)
+    {
+      if (instance_ok ())
+        return instance->do_find_package (name, error_if_not_found);
+
+      return cdef_package ();
+    }
+
+  static void register_class (const cdef_class& cls)
+    {
+      if (instance_ok ())
+        instance->do_register_class (cls);
+    }
+
+  static void unregister_class (const cdef_class& cls)
+    {
+      if (instance_ok ())
+        instance->do_unregister_class (cls);
+    }
+
+  static void register_package (const cdef_package& pkg)
+    {
+      if (instance_ok ())
+        instance->do_register_package (pkg);
+    }
+
+  static void unregister_package (const cdef_package& pkg)
+    {
+      if (instance_ok ())
+        instance->do_unregister_package (pkg);
+    }
+
+private:
+
+  cdef_manager (void) { }
+
+  cdef_manager (const cdef_manager&);
+
+  cdef_manager& operator = (const cdef_manager&);
+
+  ~cdef_manager (void) { }
+
+  static void create_instance (void);
+
+  static bool instance_ok (void)
+    {
+      bool retval = true;
+
+      if (! instance)
+        create_instance ();
+
+      if (! instance)
+        {
+          ::error ("unable to create cdef_manager!");
+
+          retval = false;
+        }
+
+      return retval;
+    }
+
+  static void cleanup_instance (void)
+    {
+      delete instance;
+
+      instance = 0;
+    }
+
+  cdef_class do_find_class (const std::string& name, bool error_if_not_found,
+                            bool load_if_not_found);
+
+  octave_function* do_find_method_symbol (const std::string& method_name,
+                                          const std::string& class_name);
+
+  cdef_package do_find_package (const std::string& name,
+                                bool error_if_not_found);
+
+  void do_register_class (const cdef_class& cls)
+    { all_classes[cls.get_name ()] = cls; }
+
+  void do_unregister_class (const cdef_class& cls)
+    { all_classes.erase(cls.get_name ()); }
+
+  void do_register_package (const cdef_package& pkg)
+    { all_packages[pkg.get_name ()] = pkg; }
+
+  void do_unregister_package (const cdef_package& pkg)
+    { all_packages.erase(pkg.get_name ()); }
+
+private:
+
+  // The single cdef_manager instance
+  static cdef_manager *instance;
+
+  // All registered/loaded classes
+  std::map<std::string, cdef_class> all_classes;
+
+  // All registered/loaded packages
+  std::map<std::string, cdef_package> all_packages;
+};
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
--- a/libinterp/octave-value/ov-fcn.h	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/octave-value/ov-fcn.h	Mon Feb 11 15:45:26 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; }
 
@@ -148,6 +152,9 @@
 
   virtual void accept (tree_walker&) { }
 
+  virtual bool is_postfix_index_handled (char type) const
+    { return (type == '(' || type == '{'); }
+
 protected:
 
   octave_function (const std::string& nm,
--- a/libinterp/octave-value/ov-usr-fcn.cc	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Mon Feb 11 15:45:26 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	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/octave-value/ov-usr-fcn.h	Mon Feb 11 15:45:26 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/octave-value/ov.cc	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/octave-value/ov.cc	Mon Feb 11 15:45:26 2013 -0500
@@ -65,6 +65,7 @@
 #include "ov-range.h"
 #include "ov-struct.h"
 #include "ov-class.h"
+#include "ov-classdef.h"
 #include "ov-oncleanup.h"
 #include "ov-cs-list.h"
 #include "ov-colon.h"
--- a/libinterp/octave.cc	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/octave.cc	Mon Feb 11 15:45:26 2013 -0500
@@ -64,6 +64,7 @@
 #include "oct-obj.h"
 #include "ops.h"
 #include "ov.h"
+#include "ov-classdef.h"
 #include "ov-range.h"
 #include "toplev.h"
 #include "parse.h"
@@ -890,6 +891,8 @@
 
   install_builtins ();
 
+  install_classdef ();
+
   for (std::list<std::string>::const_iterator it = command_line_path.begin ();
        it != command_line_path.end (); it++)
     load_path::set_command_line_path (*it);
--- a/libinterp/parse-tree/lex.h	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/lex.h	Mon Feb 11 15:45:26 2013 -0500
@@ -52,6 +52,7 @@
 
 extern void prep_lexer_for_script_file (void);
 extern void prep_lexer_for_function_file (void);
+extern void prep_lexer_for_classdef_file (void);
 
 // For communication between the lexer and parser.
 
@@ -72,7 +73,8 @@
       looking_for_object_index (false), do_comma_insert (false),
       looking_at_indirect_ref (false), parsed_function_name (),
       parsing_class_method (false), maybe_classdef_get_set_method (false),
-      parsing_classdef (false), quote_is_transpose (false),
+      parsing_classdef (false), parsing_classdef_get_method (false),
+      parsing_classdef_set_method (false), quote_is_transpose (false),
       pending_local_variables ()
 
     {
@@ -157,6 +159,12 @@
   // TRUE means we are parsing a classdef file
   bool parsing_classdef;
 
+  // TRUE means we are parsing a classdef get.method.
+  bool parsing_classdef_get_method;
+
+  // TRUE means we are parsing a classdef set.method.
+  bool parsing_classdef_set_method;
+
   // Return transpose or start a string?
   bool quote_is_transpose;
 
--- a/libinterp/parse-tree/lex.ll	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/lex.ll	Mon Feb 11 15:45:26 2013 -0500
@@ -34,6 +34,7 @@
 
 %x SCRIPT_FILE_BEGIN
 %x FUNCTION_FILE_BEGIN
+%x CLASSDEF_FILE_BEGIN
 
 %{
 
@@ -373,6 +374,14 @@
     COUNT_TOK_AND_RETURN (FUNCTION_FILE);
   }
 
+<CLASSDEF_FILE_BEGIN>. {
+    LEXER_DEBUG ("<CLASSDEF_FILE_BEGIN>.");
+
+    BEGIN (INITIAL);
+    xunput (yytext[0], yytext);
+    COUNT_TOK_AND_RETURN (CLASSDEF_FILE);
+  }
+
 %{
 // Help and other command-style functions.
 %}
@@ -756,7 +765,7 @@
       {
         lexer_flags.looking_for_object_index = true;
 
-        COUNT_TOK_AND_RETURN (SUPERCLASSREF);
+        COUNT_TOK_AND_RETURN (id_tok);
       }
   }
 
@@ -774,7 +783,7 @@
       {
         lexer_flags.looking_for_object_index = true;
 
-        COUNT_TOK_AND_RETURN (METAQUERY);
+        COUNT_TOK_AND_RETURN (id_tok);
       }
   }
 
@@ -3152,37 +3161,40 @@
 static int
 handle_superclass_identifier (void)
 {
-  eat_continuation ();
+  int c = yytext[yyleng-1];
+
+  std::string meth = strip_trailing_whitespace (yytext);
+
+  int cont_is_spc = eat_continuation ();
+
+  int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t');
+
+  size_t pos = meth.find ("@");
+  std::string cls = meth.substr (pos + 1);
+  meth = meth.substr (0, pos);
 
   std::string pkg;
-  std::string meth = strip_trailing_whitespace (yytext);
-  size_t pos = meth.find ("@");
-  std::string cls = meth.substr (pos).substr (1);
-  meth = meth.substr (0, pos - 1);
-
   pos = cls.find (".");
   if (pos != std::string::npos)
     {
-      pkg = cls.substr (pos).substr (1);
-      cls = cls.substr (0, pos - 1);
+      pkg = cls.substr (0, pos);
+      cls = cls.substr (pos + 1);
     }
 
   int kw_token = (is_keyword_token (meth) || is_keyword_token (cls)
                   || is_keyword_token (pkg));
   if (kw_token)
     {
-      error ("method, class and package names may not be keywords");
+      error ("method, class, and package names may not be keywords");
       return LEXICAL_ERROR;
     }
 
-  yylval.tok_val
-    = new token (meth.empty () ? 0 : &(symbol_table::insert (meth)),
-                 cls.empty () ? 0 : &(symbol_table::insert (cls)),
-                 pkg.empty () ? 0 : &(symbol_table::insert (pkg)),
-                 input_line_number, current_input_column);
+  yylval.tok_val = new token (meth, pkg, cls, input_line_number,
+                              current_input_column);
   token_stack.push (yylval.tok_val);
 
-  lexer_flags.convert_spaces_to_comma = true;
+  do_comma_insert_check ();
+  maybe_unput_comma (spc_gobbled);
   current_input_column += yyleng;
 
   return SUPERCLASSREF;
@@ -3191,33 +3203,35 @@
 static int
 handle_meta_identifier (void)
 {
-  eat_continuation ();
+  int c = yytext[yyleng-1];
+
+  std::string cls = strip_trailing_whitespace (yytext).substr (1);
+
+  int cont_is_spc = eat_continuation ();
+
+  int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t');
 
   std::string pkg;
-  std::string cls = strip_trailing_whitespace (yytext).substr (1);
   size_t pos = cls.find (".");
-
   if (pos != std::string::npos)
     {
-      pkg = cls.substr (pos).substr (1);
-      cls = cls.substr (0, pos - 1);
+      pkg = cls.substr (0, pos);
+      cls = cls.substr (pos + 1);
     }
 
   int kw_token = is_keyword_token (cls) || is_keyword_token (pkg);
   if (kw_token)
     {
-       error ("class and package names may not be keywords");
+      error ("class and package names may not be keywords");
       return LEXICAL_ERROR;
     }
 
-  yylval.tok_val
-    = new token (cls.empty () ? 0 : &(symbol_table::insert (cls)),
-                 pkg.empty () ? 0 : &(symbol_table::insert (pkg)),
-                 input_line_number, current_input_column);
-
+  yylval.tok_val = new token (pkg, cls, input_line_number,
+                              current_input_column);
   token_stack.push (yylval.tok_val);
 
-  lexer_flags.convert_spaces_to_comma = true;
+  do_comma_insert_check ();
+  maybe_unput_comma (spc_gobbled);
   current_input_column += yyleng;
 
   return METAQUERY;
@@ -3422,6 +3436,8 @@
   // Not initially defining a class with classdef.
   maybe_classdef_get_set_method = false;
   parsing_classdef = false;
+  parsing_classdef_get_method = false;
+  parsing_classdef_set_method = false;
 
   // Not initiallly looking at a function handle.
   looking_at_function_handle = 0;
@@ -3550,6 +3566,12 @@
   BEGIN (FUNCTION_FILE_BEGIN);
 }
 
+void
+prep_lexer_for_classdef_file (void)
+{
+  BEGIN (CLASSDEF_FILE_BEGIN);
+}
+
 static void
 maybe_warn_separator_insert (char sep)
 {
@@ -3722,6 +3744,7 @@
     case CLOSE_BRACE: std::cerr << "CLOSE_BRACE\n"; break;
     case SCRIPT_FILE: std::cerr << "SCRIPT_FILE\n"; break;
     case FUNCTION_FILE: std::cerr << "FUNCTION_FILE\n"; break;
+    case CLASSDEF_FILE: std::cerr << "CLASSDEF_FILE\n"; break;
     case SUPERCLASSREF: std::cerr << "SUPERCLASSREF\n"; break;
     case METAQUERY: std::cerr << "METAQUERY\n"; break;
     case GET: std::cerr << "GET\n"; break;
@@ -3771,6 +3794,10 @@
       std::cerr << "FUNCTION_FILE_BEGIN" << std::endl;
       break;
 
+    case CLASSDEF_FILE_BEGIN:
+      std::cerr << "CLASSDEF_FILE_BEGIN" << std::endl;
+      break;
+
     default:
       std::cerr << "UNKNOWN START STATE!" << std::endl;
       break;
--- a/libinterp/parse-tree/module.mk	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/module.mk	Mon Feb 11 15:45:26 2013 -0500
@@ -27,6 +27,7 @@
   parse-tree/pt-cbinop.h \
   parse-tree/pt-cell.h \
   parse-tree/pt-check.h \
+  parse-tree/pt-classdef.h \
   parse-tree/pt-cmd.h \
   parse-tree/pt-colon.h \
   parse-tree/pt-const.h \
@@ -35,6 +36,7 @@
   parse-tree/pt-except.h \
   parse-tree/pt-exp.h \
   parse-tree/pt-fcn-handle.h \
+  parse-tree/pt-funcall.h \
   parse-tree/pt-id.h \
   parse-tree/pt-idx.h \
   parse-tree/pt-jump.h \
@@ -58,6 +60,7 @@
   parse-tree/pt-cbinop.cc \
   parse-tree/pt-cell.cc \
   parse-tree/pt-check.cc \
+  parse-tree/pt-classdef.cc \
   parse-tree/pt-cmd.cc \
   parse-tree/pt-colon.cc \
   parse-tree/pt-const.cc \
@@ -66,6 +69,7 @@
   parse-tree/pt-except.cc \
   parse-tree/pt-exp.cc \
   parse-tree/pt-fcn-handle.cc \
+  parse-tree/pt-funcall.cc \
   parse-tree/pt-id.cc \
   parse-tree/pt-idx.cc \
   parse-tree/pt-jump.cc \
--- a/libinterp/parse-tree/oct-parse.yy	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/oct-parse.yy	Mon Feb 11 15:45:26 2013 -0500
@@ -62,6 +62,7 @@
 #include "load-path.h"
 #include "oct-hist.h"
 #include "oct-map.h"
+#include "ov-classdef.h"
 #include "ov-fcn-handle.h"
 #include "ov-usr-fcn.h"
 #include "ov-null-mat.h"
@@ -71,6 +72,7 @@
 #include "parse-private.h"
 #include "pt-all.h"
 #include "pt-eval.h"
+#include "pt-funcall.h"
 #include "symtab.h"
 #include "token.h"
 #include "unwind-prot.h"
@@ -152,6 +154,9 @@
 // used while reading function files.
 static symbol_table::scope_id primary_fcn_scope;
 
+// Pointer to the classdef object we just parsed, if any.
+static tree_classdef *classdef_object = 0;
+
 // List of autoloads (function -> file mapping).
 static std::map<std::string, std::string> autoload_map;
 
@@ -356,6 +361,47 @@
 append_statement_list (tree_statement_list *list, char sep,
                        tree_statement *stmt, bool warn_missing_semi);
 
+static tree_funcall *
+make_superclass_ref (const std::string& method_nm,
+                     const std::string& package_nm,
+                     const std::string& class_nm,
+                     int l, int c);
+
+static tree_funcall *
+make_meta_class_query (const std::string& package_nm,
+                       const std::string& class_nm,
+                       int l, int c);
+
+static tree_classdef *
+make_classdef (token *tok_val, tree_classdef_attribute_list *a,
+               tree_identifier *id, tree_classdef_superclass_list *sc,
+               tree_classdef_body *body, token *end_tok,
+               octave_comment_list *lc);
+
+static tree_classdef_properties_block *
+make_classdef_properties_block (token *tok_val,
+                                tree_classdef_attribute_list *a,
+                                tree_classdef_property_list *plist,
+                                token *end_tok, octave_comment_list *lc);
+
+static tree_classdef_methods_block *
+make_classdef_methods_block (token *tok_val,
+                             tree_classdef_attribute_list *a,
+                             tree_classdef_methods_list *mlist,
+                             token *end_tok, octave_comment_list *lc);
+
+static tree_classdef_events_block *
+make_classdef_events_block (token *tok_val,
+                            tree_classdef_attribute_list *a,
+                            tree_classdef_events_list *elist,
+                            token *end_tok, octave_comment_list *lc);
+
+static tree_classdef_enum_block *
+make_classdef_enum_block (token *tok_val,
+                          tree_classdef_attribute_list *a,
+                          tree_classdef_enum_list *elist,
+                          token *end_tok, octave_comment_list *lc);
+
 // Finish building a statement.
 template <class T>
 static tree_statement *
@@ -400,12 +446,15 @@
 
   // Types for the nonterminals we generate.
   char sep_type;
+  token *tok_type;
   tree *tree_type;
   tree_matrix *tree_matrix_type;
   tree_cell *tree_cell_type;
   tree_expression *tree_expression_type;
   tree_constant *tree_constant_type;
   tree_fcn_handle *tree_fcn_handle_type;
+  tree_funcall *tree_funcall_type;
+  tree_function_def *tree_function_def_type;
   tree_anon_fcn_handle *tree_anon_fcn_handle_type;
   tree_identifier *tree_identifier_type;
   tree_index_expression *tree_index_expression_type;
@@ -425,7 +474,24 @@
   tree_statement *tree_statement_type;
   tree_statement_list *tree_statement_list_type;
   octave_user_function *octave_user_function_type;
-  void *dummy_type;
+
+  tree_classdef *tree_classdef_type;
+  tree_classdef_attribute* tree_classdef_attribute_type;
+  tree_classdef_attribute_list* tree_classdef_attribute_list_type;
+  tree_classdef_superclass* tree_classdef_superclass_type;
+  tree_classdef_superclass_list* tree_classdef_superclass_list_type;
+  tree_classdef_body* tree_classdef_body_type;
+  tree_classdef_property* tree_classdef_property_type;
+  tree_classdef_property_list* tree_classdef_property_list_type;
+  tree_classdef_properties_block* tree_classdef_properties_block_type;
+  tree_classdef_methods_list* tree_classdef_methods_list_type;
+  tree_classdef_methods_block* tree_classdef_methods_block_type;
+  tree_classdef_event* tree_classdef_event_type;
+  tree_classdef_events_list* tree_classdef_events_list_type;
+  tree_classdef_events_block* tree_classdef_events_block_type;
+  tree_classdef_enum* tree_classdef_enum_type;
+  tree_classdef_enum_list* tree_classdef_enum_list_type;
+  tree_classdef_enum_block* tree_classdef_enum_block_type;
 }
 
 // Tokens with line and column information.
@@ -452,6 +518,7 @@
 %token <tok_val> TRY CATCH
 %token <tok_val> GLOBAL PERSISTENT
 %token <tok_val> FCN_HANDLE
+%token <tok_val> CLASSDEF
 %token <tok_val> PROPERTIES METHODS EVENTS ENUMERATION
 %token <tok_val> METAQUERY
 %token <tok_val> SUPERCLASSREF
@@ -459,13 +526,13 @@
 
 // Other tokens.
 %token END_OF_INPUT LEXICAL_ERROR
-%token FCN SCRIPT_FILE FUNCTION_FILE CLASSDEF
+%token FCN SCRIPT_FILE CLASSDEF_FILE FUNCTION_FILE
 // %token VARARGIN VARARGOUT
 %token CLOSE_BRACE
 
 // Nonterminals we construct.
-%type <comment_type> stash_comment function_beg classdef_beg
-%type <comment_type> properties_beg methods_beg events_beg enum_beg
+%type <comment_type> stash_comment function_beg
+%type <tok_type> classdef_beg
 %type <sep_type> sep_no_nl opt_sep_no_nl sep opt_sep opt_comma
 %type <tree_type> input
 %type <tree_constant_type> string constant magic_colon
@@ -477,18 +544,19 @@
 %type <tree_expression_type> primary_expr oper_expr
 %type <tree_expression_type> simple_expr colon_expr assign_expr expression
 %type <tree_identifier_type> identifier fcn_name magic_tilde
-%type <tree_identifier_type> superclass_identifier meta_identifier
-%type <octave_user_function_type> function1 function2 classdef1
+%type <tree_funcall_type> superclass_identifier meta_identifier
+%type <octave_user_function_type> function1 function2
 %type <tree_index_expression_type> word_list_cmd
 %type <tree_colon_expression_type> colon_expr1
 %type <tree_argument_list_type> arg_list word_list assign_lhs
 %type <tree_argument_list_type> cell_or_matrix_row
 %type <tree_parameter_list_type> param_list param_list1 param_list2
 %type <tree_parameter_list_type> return_list return_list1
-%type <tree_parameter_list_type> superclasses opt_superclasses
 %type <tree_command_type> command select_command loop_command
-%type <tree_command_type> jump_command except_command function
-%type <tree_command_type> script_file classdef
+%type <tree_command_type> jump_command except_command
+%type <tree_function_def_type> function
+%type <tree_classdef_type> classdef
+%type <tree_command_type> script_file classdef_file
 %type <tree_command_type> function_file function_list
 %type <tree_if_command_type> if_command
 %type <tree_if_clause_type> elseif_clause else_clause
@@ -499,25 +567,26 @@
 %type <tree_decl_elt_type> decl2
 %type <tree_decl_init_list_type> decl1
 %type <tree_decl_command_type> declaration
-%type <tree_statement_type> statement function_end classdef_end
+%type <tree_statement_type> statement function_end
 %type <tree_statement_list_type> simple_list simple_list1 list list1
 %type <tree_statement_list_type> opt_list input1
-// These types need to be specified.
-%type <dummy_type> attr
-%type <dummy_type> class_event
-%type <dummy_type> class_enum
-%type <dummy_type> class_property
-%type <dummy_type> properties_list
-%type <dummy_type> properties_block
-%type <dummy_type> methods_list
-%type <dummy_type> methods_block
-%type <dummy_type> opt_attr_list
-%type <dummy_type> attr_list
-%type <dummy_type> events_list
-%type <dummy_type> events_block
-%type <dummy_type> enum_list
-%type <dummy_type> enum_block
-%type <dummy_type> class_body
+
+%type <tree_classdef_attribute_type> attr
+%type <tree_classdef_attribute_list_type> attr_list opt_attr_list
+%type <tree_classdef_superclass_type> superclass
+%type <tree_classdef_superclass_list_type> superclass_list opt_superclass_list
+%type <tree_classdef_body_type> class_body
+%type <tree_classdef_property_type> class_property
+%type <tree_classdef_property_list_type> property_list
+%type <tree_classdef_properties_block_type> properties_block
+%type <tree_classdef_methods_list_type> methods_list
+%type <tree_classdef_methods_block_type> methods_block
+%type <tree_classdef_event_type> class_event
+%type <tree_classdef_events_list_type> events_list
+%type <tree_classdef_events_block_type> events_block
+%type <tree_classdef_enum_type> class_enum
+%type <tree_classdef_enum_list_type> enum_list
+%type <tree_classdef_enum_block_type> enum_block
 
 // Precedence and associativity.
 %right '=' ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ OR_EQ AND_EQ LSHIFT_EQ RSHIFT_EQ
@@ -552,6 +621,8 @@
                   }
                 | function_file
                   { YYACCEPT; }
+                | classdef_file
+                  { YYACCEPT; }
                 | simple_list parse_error
                   { ABORT_PARSE; }
                 | parse_error
@@ -641,11 +712,24 @@
 
 superclass_identifier
                 : SUPERCLASSREF
-                  { $$ = new tree_identifier ($1->line (), $1->column ()); }
+                  {
+                    std::string method_nm = $1->superclass_method_name ();
+                    std::string package_nm = $1->superclass_package_name ();
+                    std::string class_nm = $1->superclass_class_name ();
+
+                    $$ = make_superclass_ref (method_nm, package_nm, class_nm,
+                                              $1->line (), $1->column ());
+                  }
                 ;
 
 meta_identifier : METAQUERY
-                  { $$ = new tree_identifier ($1->line (), $1->column ()); }
+                  {
+                    std::string package_nm = $1->meta_package_name ();
+                    std::string class_nm = $1->meta_class_name ();
+
+                    $$ = make_meta_class_query (package_nm, class_nm,
+                                                $1->line (), $1->column ());
+                  }
                 ;
 
 string          : DQ_STRING
@@ -984,8 +1068,6 @@
                   { $$ = $1; }
                 | script_file
                   { $$ = $1; }
-                | classdef
-                  { $$ = $1; }
                 ;
 
 // =====================
@@ -1404,12 +1486,14 @@
                   {
                     lexer_flags.parsed_function_name.top () = true;
                     lexer_flags.maybe_classdef_get_set_method = false;
+                    lexer_flags.parsing_classdef_get_method = true;
                     $$ = $3;
                   }
                 | SET '.' identifier
                   {
                     lexer_flags.parsed_function_name.top () = true;
                     lexer_flags.maybe_classdef_get_set_method = false;
+                    lexer_flags.parsing_classdef_set_method = true;
                     $$ = $3;
                   }
                 ;
@@ -1474,161 +1558,212 @@
                   }
                 ;
 
+// =============
+// Classdef file
+// =============
+
+classdef_file   : CLASSDEF_FILE classdef opt_sep END_OF_INPUT
+                  {
+                    classdef_object = $2;
+                    $$ = 0;
+                  }
+                ;
+
 // ========
 // Classdef
 // ========
 
-classdef_beg    : CLASSDEF stash_comment
+classdef_beg    : CLASSDEF
                   {
-                    $$ = 0;
+                    if (! reading_classdef_file)
+                      {
+                        yyerror ("classdef must appear inside a file containing only a class definition");
+                        YYABORT;
+                      }
+
                     lexer_flags.parsing_classdef = true;
+                    $$ = $1;
                   }
                 ;
 
-classdef_end    : END
+classdef        : classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep class_body opt_sep END
                   {
                     lexer_flags.parsing_classdef = false;
-
-                    if (end_token_ok ($1, token::classdef_end))
-                      $$ = make_end ("endclassdef", $1->line (), $1->column ());
-                    else
+                    if (! ($$ = make_classdef ($1, $3, $4, $5, $7, $9, $2)))
                       ABORT_PARSE;
                   }
                 ;
 
-classdef1       : classdef_beg opt_attr_list identifier opt_superclasses
-                  { $$ = 0; }
-                ;
-
-classdef        : classdef1 opt_sep class_body opt_sep stash_comment classdef_end
-                  { $$ = 0; }
-                ;
-
 opt_attr_list   : // empty
                   { $$ = 0; }
                 | '(' attr_list ')'
-                  { $$ = 0; }
+                  { $$ = $2; }
                 ;
 
 attr_list       : attr
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_attribute_list ($1); }
                 | attr_list ',' attr
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 attr            : identifier
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_attribute ($1); }
                 | identifier '=' decl_param_init expression
-                  { $$ = 0; }
+                  {
+                    lexer_flags.looking_at_initializer_expression = false;
+                    $$ = new tree_classdef_attribute ($1, $4);
+                  }
                 | EXPR_NOT identifier
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_attribute ($2, false); }
                 ;
 
-opt_superclasses
+opt_superclass_list
                 : // empty
                   { $$ = 0; }
-                | superclasses
-                  { $$ = 0; }
+                | superclass_list
+                  { $$ = $1; }
                 ;
 
-superclasses    : EXPR_LT identifier '.' identifier
-                  { $$ = 0; }
-                | EXPR_LT identifier
-                  { $$ = 0; }
-                | superclasses EXPR_AND identifier '.' identifier
-                  { $$ = 0; }
-                | superclasses EXPR_AND identifier
-                  { $$ = 0; }
+superclass_list : EXPR_LT superclass
+                  { $$ = new tree_classdef_superclass_list ($2); }
+                | superclass_list EXPR_AND superclass
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+superclass      : identifier
+                  { $$ = new tree_classdef_superclass ($1); }
+                | identifier '.' identifier
+                  { $$ = new tree_classdef_superclass ($3, $1); }
                 ;
 
 class_body      : properties_block
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_body ($1); }
                 | methods_block
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_body ($1); }
                 | events_block
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_body ($1); }
                 | enum_block
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_body ($1); }
                 | class_body opt_sep properties_block
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 | class_body opt_sep methods_block
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 | class_body opt_sep events_block
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 | class_body opt_sep enum_block
-                  { $$ = 0; }
-                ;
-
-properties_beg  : PROPERTIES stash_comment
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 properties_block
-                : properties_beg opt_attr_list opt_sep properties_list opt_sep END
-                  { $$ = 0; }
+                : PROPERTIES stash_comment opt_attr_list opt_sep property_list opt_sep END
+                  {
+                    if (! ($$ = make_classdef_properties_block ($1, $3, $5, $7, $2)))
+                      ABORT_PARSE;
+                  }
                 ;
 
-properties_list
+property_list
                 : class_property
-                  { $$ = 0; }
-                | properties_list opt_sep class_property
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_property_list ($1); }
+                | property_list opt_sep class_property
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 class_property  : identifier
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_property ($1); }
                 | identifier '=' decl_param_init expression ';'
-                  { $$ = 0; }
+                  {
+                    lexer_flags.looking_at_initializer_expression = false;
+                    $$ = new tree_classdef_property ($1, $4);
+                  }
                 ;
 
-methods_beg     : METHODS stash_comment
-                  { $$ = 0; }
-                ;
-
-methods_block   : methods_beg opt_attr_list opt_sep methods_list opt_sep END
-                  { $$ = 0; }
+methods_block   : METHODS stash_comment opt_attr_list opt_sep methods_list opt_sep END
+                  {
+                    if (! ($$ = make_classdef_methods_block ($1, $3, $5, $7, $2)))
+                      ABORT_PARSE;
+                  }
                 ;
 
 methods_list    : function
-                  { $$ = 0; }
+                  {
+                    octave_value fcn;
+                    if ($1)
+                      fcn = $1->function ();
+                    delete $1;
+                    $$ = new tree_classdef_methods_list (fcn);
+                  }
                 | methods_list opt_sep function
-                  { $$ = 0; }
+                  {
+                    octave_value fcn;
+                    if ($3)
+                      fcn = $3->function ();
+                    delete $3;
+
+                    $1->append (fcn);
+                    $$ = $1;
+                  }
                 ;
 
-events_beg      : EVENTS stash_comment
-                  { $$ = 0; }
-                ;
-
-events_block    : events_beg opt_attr_list opt_sep events_list opt_sep END
-                  { $$ = 0; }
+events_block    : EVENTS stash_comment opt_attr_list opt_sep events_list opt_sep END
+                  {
+                    if (! ($$ = make_classdef_events_block ($1, $3, $5, $7, $2)))
+                      ABORT_PARSE;
+                  }
                 ;
 
 events_list     : class_event
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_events_list ($1); }
                 | events_list opt_sep class_event
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 class_event     : identifier
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_event ($1); }
                 ;
 
-enum_beg        : ENUMERATION stash_comment
-                  { $$ = 0; }
-                ;
-
-enum_block      : enum_beg opt_attr_list opt_sep enum_list opt_sep END
-                  { $$ = 0; }
+enum_block      : ENUMERATION stash_comment opt_attr_list opt_sep enum_list opt_sep END
+                  {
+                    if (! ($$ = make_classdef_enum_block ($1, $3, $5, $7, $2)))
+                      ABORT_PARSE;
+                  }
                 ;
 
 enum_list       : class_enum
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_enum_list ($1); }
                 | enum_list opt_sep class_enum
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 class_enum      : identifier '(' expression ')'
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_enum ($1, $3); }
                 ;
 
 // =============
@@ -3034,7 +3169,8 @@
   int l = expr->line ();
   int c = expr->column ();
 
-  expr->mark_postfix_indexed ();
+  if (! expr->is_postfix_indexed ()) 
+    expr->set_postfix_index (type);
 
   if (expr->is_index_expression ())
     {
@@ -3060,6 +3196,9 @@
   int l = expr->line ();
   int c = expr->column ();
 
+  if (! expr->is_postfix_indexed ()) 
+    expr->set_postfix_index ('.');
+
   if (expr->is_index_expression ())
     {
       tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
@@ -3086,6 +3225,9 @@
   int l = expr->line ();
   int c = expr->column ();
 
+  if (! expr->is_postfix_indexed ()) 
+    expr->set_postfix_index ('.');
+
   if (expr->is_index_expression ())
     {
       tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
@@ -3268,6 +3410,166 @@
   return list;
 }
 
+static tree_funcall *
+make_superclass_ref (const std::string& method_nm,
+                     const std::string& package_nm,
+                     const std::string& class_nm,
+                     int l, int c)
+{
+  octave_value_list args;
+
+  args(2) = class_nm;
+  args(1) = package_nm;
+  args(0) = method_nm;
+
+  octave_value fcn
+    = symbol_table::find_built_in_function ("__superclass_reference__");
+
+  return new tree_funcall (fcn, args);
+}
+
+static tree_funcall *
+make_meta_class_query (const std::string& package_nm,
+                       const std::string& class_nm,
+                       int l, int c)
+{
+  octave_value_list args;
+
+  args(1) = class_nm;
+  args(0) = package_nm;
+
+  octave_value fcn
+    = symbol_table::find_built_in_function ("__meta_class_query__");
+
+  return new tree_funcall (fcn, args);
+}
+
+// A CLASSDEF block defines a class that has a constructor and other
+// methods, but it is not an executable command.  Parsing the block
+// makes some changes in the symbol table (inserting the constructor
+// and methods, and adding to the list of known objects) and creates
+// a parse tree containing meta information about the class.
+
+static tree_classdef *
+make_classdef (token *tok_val, tree_classdef_attribute_list *a,
+               tree_identifier *id, tree_classdef_superclass_list *sc,
+               tree_classdef_body *body, token *end_tok,
+               octave_comment_list *lc)
+{
+  tree_classdef *retval = 0;
+
+  std::string cls_name = id->name ();
+
+  std::string nm = curr_fcn_file_name;
+
+  size_t pos = nm.find_last_of (file_ops::dir_sep_chars ());
+
+  if (pos != std::string::npos)
+    nm = curr_fcn_file_name.substr (pos+1);
+
+  if (nm != cls_name)
+    {
+      yyerror ("invalid classdef definition, the class name must match the file name");
+      return retval;
+    }
+
+  if (end_token_ok (end_tok, token::classdef_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      retval = new tree_classdef (a, id, sc, body, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
+static tree_classdef_properties_block *
+make_classdef_properties_block (token *tok_val,
+                                tree_classdef_attribute_list *a,
+                                tree_classdef_property_list *plist,
+                                token *end_tok, octave_comment_list *lc)
+{
+  tree_classdef_properties_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::properties_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
+static tree_classdef_methods_block *
+make_classdef_methods_block (token *tok_val,
+                             tree_classdef_attribute_list *a,
+                             tree_classdef_methods_list *mlist,
+                             token *end_tok, octave_comment_list *lc)
+{
+  tree_classdef_methods_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::methods_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      retval = new tree_classdef_methods_block (a, mlist, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
+static tree_classdef_events_block *
+make_classdef_events_block (token *tok_val,
+                            tree_classdef_attribute_list *a,
+                            tree_classdef_events_list *elist,
+                            token *end_tok, octave_comment_list *lc)
+{
+  tree_classdef_events_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::events_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      retval = new tree_classdef_events_block (a, elist, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
+static tree_classdef_enum_block *
+make_classdef_enum_block (token *tok_val,
+                          tree_classdef_attribute_list *a,
+                          tree_classdef_enum_list *elist,
+                          token *end_tok, octave_comment_list *lc)
+{
+  tree_classdef_enum_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::enumeration_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
 static void
 safe_fclose (FILE *f)
 {
@@ -3546,11 +3848,7 @@
 
               reading_classdef_file = true;
               reading_fcn_file = false;
-              // FIXME -- Should classdef files be handled as
-              // scripts or separately?  Currently, without setting up
-              // for reading script files, parsing classdef files
-              // fails.
-              reading_script_file = true;
+              reading_script_file = false;
             }
           else
             {
@@ -3574,6 +3872,9 @@
           frame.protect_var (primary_fcn_ptr);
           primary_fcn_ptr = 0;
 
+          frame.protect_var (classdef_object);
+          classdef_object = 0;
+
           reset_parser ();
 
           // Do this with an unwind-protect cleanup function so that
@@ -3587,6 +3888,8 @@
 
           if (reading_script_file)
             prep_lexer_for_script_file ();
+          else if (reading_classdef_file)
+            prep_lexer_for_classdef_file ();
           else
             prep_lexer_for_function_file ();
 
@@ -3606,9 +3909,25 @@
 
           fcn_ptr = primary_fcn_ptr;
 
-          if (status != 0)
-            error ("parse error while reading %s file %s",
-                   file_type.c_str (), ff.c_str ());
+          if (status == 0)
+            {
+              if (reading_classdef_file && classdef_object)
+                {
+                  // Convert parse tree for classdef object to
+                  // meta.class info (and stash it in the symbol
+                  // table?).  Return pointer to constructor?
+
+                  if (fcn_ptr)
+                    panic_impossible ();
+
+                  fcn_ptr = classdef_object->make_meta_class ();
+                }
+            }
+          else
+            {
+              error ("parse error while reading %s file %s",
+                     file_type.c_str(), ff.c_str ());
+            }
         }
       else
         {
--- a/libinterp/parse-tree/pt-all.h	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/pt-all.h	Mon Feb 11 15:45:26 2013 -0500
@@ -30,6 +30,7 @@
 #include "pt-binop.h"
 #include "pt-cbinop.h"
 #include "pt-check.h"
+#include "pt-classdef.h"
 #include "pt-cmd.h"
 #include "pt-colon.h"
 #include "pt-const.h"
@@ -37,6 +38,7 @@
 #include "pt-except.h"
 #include "pt-exp.h"
 #include "pt-fcn-handle.h"
+#include "pt-funcall.h"
 #include "pt-id.h"
 #include "pt-idx.h"
 #include "pt-jump.h"
--- a/libinterp/parse-tree/pt-bp.cc	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/pt-bp.cc	Mon Feb 11 15:45:26 2013 -0500
@@ -299,6 +299,12 @@
 }
 
 void
+tree_breakpoint::visit_funcall (tree_funcall&)
+{
+  panic_impossible ();
+}
+
+void
 tree_breakpoint::visit_parameter_list (tree_parameter_list&)
 {
   panic_impossible ();
--- a/libinterp/parse-tree/pt-bp.h	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/pt-bp.h	Mon Feb 11 15:45:26 2013 -0500
@@ -106,6 +106,8 @@
 
   void visit_fcn_handle (tree_fcn_handle&);
 
+  void visit_funcall (tree_funcall&);
+
   void visit_parameter_list (tree_parameter_list&);
 
   void visit_postfix_expression (tree_postfix_expression&);
--- a/libinterp/parse-tree/pt-check.cc	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/pt-check.cc	Mon Feb 11 15:45:26 2013 -0500
@@ -357,6 +357,11 @@
 }
 
 void
+tree_checker::visit_funcall (tree_funcall& /* fc */)
+{
+}
+
+void
 tree_checker::visit_parameter_list (tree_parameter_list& lst)
 {
   tree_parameter_list::iterator p = lst.begin ();
--- a/libinterp/parse-tree/pt-check.h	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/pt-check.h	Mon Feb 11 15:45:26 2013 -0500
@@ -91,6 +91,8 @@
 
   void visit_fcn_handle (tree_fcn_handle&);
 
+  void visit_funcall (tree_funcall&);
+
   void visit_parameter_list (tree_parameter_list&);
 
   void visit_postfix_expression (tree_postfix_expression&);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-classdef.cc	Mon Feb 11 15:45:26 2013 -0500
@@ -0,0 +1,259 @@
+/*
+
+Copyright (C) 2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ov-classdef.h"
+#include "pt-classdef.h"
+
+// Classdef attribute
+
+void
+tree_classdef_attribute::accept (tree_walker& tw)
+{
+  tw.visit_classdef_attribute (*this);
+}
+
+// Classdef attribute_list
+
+tree_classdef_attribute_list::~tree_classdef_attribute_list (void)
+{
+  while (! empty ())
+    {
+      iterator p = begin ();
+      delete *p;
+      erase (p);
+    }
+}
+
+void
+tree_classdef_attribute_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_attribute_list (*this);
+}
+
+// Classdef superclass
+
+void
+tree_classdef_superclass::accept (tree_walker& tw)
+{
+  tw.visit_classdef_superclass (*this);
+}
+
+// Classdef superclass_list
+
+tree_classdef_superclass_list::~tree_classdef_superclass_list (void)
+{
+  while (! empty ())
+    {
+      iterator p = begin ();
+      delete *p;
+      erase (p);
+    }
+}
+
+void
+tree_classdef_superclass_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_superclass_list (*this);
+}
+
+// Classdef property
+
+void
+tree_classdef_property::accept (tree_walker& tw)
+{
+  tw.visit_classdef_property (*this);
+}
+
+// Classdef property_list
+
+tree_classdef_property_list::~tree_classdef_property_list (void)
+{
+  while (! empty ())
+    {
+      iterator p = begin ();
+      delete *p;
+      erase (p);
+    }
+}
+
+void
+tree_classdef_property_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_property_list (*this);
+}
+
+// Classdef properties_block
+
+void
+tree_classdef_properties_block::accept (tree_walker& tw)
+{
+  tw.visit_classdef_properties_block (*this);
+}
+
+// Classdef methods_list
+
+void
+tree_classdef_methods_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_methods_list (*this);
+}
+
+// Classdef methods_block
+
+void
+tree_classdef_methods_block::accept (tree_walker& tw)
+{
+  tw.visit_classdef_methods_block (*this);
+}
+
+// Classdef event
+
+void
+tree_classdef_event::accept (tree_walker& tw)
+{
+  tw.visit_classdef_event (*this);
+}
+
+// Classdef events_list
+
+tree_classdef_events_list::~tree_classdef_events_list (void)
+{
+  while (! empty ())
+    {
+      iterator p = begin ();
+      delete *p;
+      erase (p);
+    }
+}
+
+void
+tree_classdef_events_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_events_list (*this);
+}
+
+// Classdef events_block
+
+void
+tree_classdef_events_block::accept (tree_walker& tw)
+{
+  tw.visit_classdef_events_block (*this);
+}
+
+// Classdef enum
+
+void
+tree_classdef_enum::accept (tree_walker& tw)
+{
+  tw.visit_classdef_enum (*this);
+}
+
+// Classdef enum_list
+
+tree_classdef_enum_list::~tree_classdef_enum_list (void)
+{
+  while (! empty ())
+    {
+      iterator p = begin ();
+      delete *p;
+      erase (p);
+    }
+}
+
+void
+tree_classdef_enum_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_enum_list (*this);
+}
+
+// Classdef enum_block
+
+void
+tree_classdef_enum_block::accept (tree_walker& tw)
+{
+  tw.visit_classdef_enum_block (*this);
+}
+
+// Classdef body
+
+tree_classdef_body::~tree_classdef_body (void)
+{
+  while (! properties_lst.empty ())
+    {
+      properties_list_iterator p = properties_lst.begin ();
+      delete *p;
+      properties_lst.erase (p);
+    }
+
+  while (! methods_lst.empty ())
+    {
+      methods_list_iterator p = methods_lst.begin ();
+      delete *p;
+      methods_lst.erase (p);
+    }
+
+  while (! events_lst.empty ())
+    {
+      events_list_iterator p = events_lst.begin ();
+      delete *p;
+      events_lst.erase (p);
+    }
+
+  while (! enum_lst.empty ())
+    {
+      enum_list_iterator p = enum_lst.begin ();
+      delete *p;
+      enum_lst.erase (p);
+    }
+}
+
+// Classdef
+
+octave_function*
+tree_classdef::make_meta_class (void)
+{
+  octave_value retval;
+  cdef_class cls = cdef_class::make_meta_class (this);
+
+  if (cls.ok ())
+    return cls.get_constructor_function ();
+
+  return 0;
+}
+
+tree_classdef *
+tree_classdef::dup (symbol_table::scope_id,
+                    symbol_table::context_id) const
+{
+  // FIXME
+  return 0;
+}
+
+void
+tree_classdef::accept (tree_walker& tw)
+{
+  tw.visit_classdef (*this);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-classdef.h	Mon Feb 11 15:45:26 2013 -0500
@@ -0,0 +1,653 @@
+/*
+
+Copyright (C) 2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_tree_classdef_h)
+#define octave_tree_classdef_h 1
+
+class octave_value;
+
+class tree_walker;
+
+#include "pt-cmd.h"
+#include "pt-exp.h"
+#include "pt-id.h"
+
+#include "base-list.h"
+
+#include <list>
+
+class tree_classdef_attribute
+{
+public:
+
+  tree_classdef_attribute (tree_identifier *i = 0, tree_expression *e = 0)
+    : id (i), expr (e), neg (false) { }
+
+  tree_classdef_attribute (tree_identifier *i, bool b)
+    : id (i), expr (0), neg (b) { }
+
+  ~tree_classdef_attribute (void)
+  {
+    delete id;
+    delete expr;
+  }
+
+  tree_identifier *ident (void) { return id; }
+
+  tree_expression *expression (void) { return expr; }
+
+  bool negate (void) { return neg; }
+
+  void accept (tree_walker&);
+
+private:
+  
+  tree_identifier *id;
+  tree_expression *expr;
+  bool neg;
+
+  // No copying!
+
+  tree_classdef_attribute (const tree_classdef_attribute&);
+
+  tree_classdef_attribute& operator = (const tree_classdef_attribute&);
+};
+
+class tree_classdef_attribute_list : public octave_base_list<tree_classdef_attribute *>
+{
+public:
+
+  tree_classdef_attribute_list (void) { }
+
+  tree_classdef_attribute_list (tree_classdef_attribute *a) { append (a); }
+
+  tree_classdef_attribute_list (const octave_base_list<tree_classdef_attribute *>& a)
+    : octave_base_list<tree_classdef_attribute *> (a) { }
+
+  ~tree_classdef_attribute_list (void);
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_attribute_list (const tree_classdef_attribute_list&);
+
+  tree_classdef_attribute_list& operator = (const tree_classdef_attribute_list&);
+};
+
+class tree_classdef_superclass
+{
+public:
+
+  tree_classdef_superclass (tree_identifier *i = 0, tree_identifier *p = 0)
+    : id (i), pkg (p) { }
+
+  ~tree_classdef_superclass (void)
+  {
+    delete id;
+    delete pkg;
+  }
+
+  tree_identifier *ident (void) { return id; }
+
+  tree_identifier * package (void) { return pkg; }
+
+  void accept (tree_walker&);
+
+private:
+
+  tree_identifier *id;
+  tree_identifier *pkg;
+
+  // No copying!
+
+  tree_classdef_superclass (const tree_classdef_superclass&);
+
+  tree_classdef_superclass& operator = (const tree_classdef_superclass&);
+};
+
+class tree_classdef_superclass_list : public octave_base_list<tree_classdef_superclass *>
+{
+public:
+
+  tree_classdef_superclass_list (void) { }
+
+  tree_classdef_superclass_list (tree_classdef_superclass *sc) { append (sc); }
+
+  tree_classdef_superclass_list (const octave_base_list<tree_classdef_superclass *>& a)
+    : octave_base_list<tree_classdef_superclass *> (a) { }
+
+  ~tree_classdef_superclass_list (void);
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_superclass_list (const tree_classdef_superclass_list&);
+
+  tree_classdef_superclass_list& operator = (const tree_classdef_superclass_list&);
+};
+
+template <typename T>
+class tree_classdef_element : public tree
+{
+public:
+
+  tree_classdef_element (tree_classdef_attribute_list *a,
+                         octave_base_list<T> *elist,
+                         octave_comment_list *lc, octave_comment_list *tc,
+                         int l = -1, int c = -1)
+    : tree (l, c), attr_list (a), elt_list (elist),
+      lead_comm (lc), trail_comm (tc)
+  { }
+
+  ~tree_classdef_element (void)
+  {
+    delete attr_list;
+    delete elt_list;
+    delete lead_comm;
+    delete trail_comm;
+  }
+
+  tree_classdef_attribute_list *attribute_list (void) { return attr_list; }
+
+  octave_base_list<T> *element_list (void) { return elt_list; }
+
+  octave_comment_list *leading_comment (void) { return lead_comm; }
+
+  octave_comment_list *trailing_comment (void) { return trail_comm; }
+
+  void accept (tree_walker&) { }
+
+private:
+
+  // List of attributes that apply to this class.
+  tree_classdef_attribute_list *attr_list;
+
+  // The list of objects contained in this block.
+  octave_base_list<T> *elt_list;
+  
+  // Comment preceding the token marking the beginning of the block.
+  octave_comment_list *lead_comm;
+
+  // Comment preceding END token.
+  octave_comment_list *trail_comm;
+
+  // No copying!
+
+  tree_classdef_element (const tree_classdef_element&);
+
+  tree_classdef_element& operator = (const tree_classdef_element&);
+};
+
+class tree_classdef_property
+{
+public:
+
+  tree_classdef_property (tree_identifier *i = 0, tree_expression *e = 0)
+    : id (i), expr (e) { }
+
+  ~tree_classdef_property (void)
+  {
+    delete id;
+    delete expr;
+  }
+
+  tree_identifier *ident (void) { return id; }
+
+  tree_expression *expression (void) { return expr; }
+
+  void accept (tree_walker&);
+
+private:
+
+  tree_identifier *id;
+  tree_expression *expr;
+
+  // No copying!
+
+  tree_classdef_property (const tree_classdef_property&);
+
+  tree_classdef_property& operator = (const tree_classdef_property&);
+};
+
+class tree_classdef_property_list : public octave_base_list<tree_classdef_property *>
+{
+public:
+
+  tree_classdef_property_list (void) { }
+
+  tree_classdef_property_list (tree_classdef_property* p) { append (p); }
+
+  tree_classdef_property_list (const octave_base_list<tree_classdef_property *>& a)
+    : octave_base_list<tree_classdef_property *> (a) { }
+
+  ~tree_classdef_property_list (void);
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_property_list (const tree_classdef_property_list&);
+
+  tree_classdef_property_list& operator = (const tree_classdef_property_list&);
+};
+
+class tree_classdef_properties_block
+  : public tree_classdef_element<tree_classdef_property *>
+{
+public:
+
+  tree_classdef_properties_block (tree_classdef_attribute_list *a,
+                                  tree_classdef_property_list *plist,
+                                  octave_comment_list *lc,
+                                  octave_comment_list *tc,
+                                  int l = -1, int c = -1)
+    : tree_classdef_element<tree_classdef_property *> (a, plist, lc, tc, l, c) { }
+
+  ~tree_classdef_properties_block (void) { }
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_properties_block (const tree_classdef_properties_block&);
+
+  tree_classdef_properties_block& operator = (const tree_classdef_properties_block&);
+};
+
+class tree_classdef_methods_list : public octave_base_list<octave_value>
+{
+public:
+
+  tree_classdef_methods_list (void) { }
+
+  tree_classdef_methods_list (const octave_value& f) { append (f); }
+
+  tree_classdef_methods_list (const octave_base_list<octave_value>& a)
+    : octave_base_list<octave_value> (a) { }
+
+  ~tree_classdef_methods_list (void) { }
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_methods_list (const tree_classdef_methods_list&);
+
+  tree_classdef_methods_list& operator = (const tree_classdef_methods_list&);
+};
+
+class tree_classdef_methods_block : public tree_classdef_element<octave_value>
+{
+public:
+
+  tree_classdef_methods_block (tree_classdef_attribute_list *a,
+                               tree_classdef_methods_list *mlist,
+                               octave_comment_list *lc,
+                               octave_comment_list *tc, int l = -1, int c = -1)
+    : tree_classdef_element<octave_value> (a, mlist, lc, tc, l, c) { }
+
+  ~tree_classdef_methods_block (void) { }
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_methods_block (const tree_classdef_methods_block&);
+
+  tree_classdef_methods_block& operator = (const tree_classdef_methods_block&);
+};
+
+class tree_classdef_event
+{
+public:
+
+  tree_classdef_event (tree_identifier *i = 0) : id (i) { }
+
+  ~tree_classdef_event (void)
+  {
+    delete id;
+  }
+
+  tree_identifier *ident (void) { return id; }
+
+  void accept (tree_walker&);
+
+private:
+
+  tree_identifier *id;
+
+  // No copying!
+
+  tree_classdef_event (const tree_classdef_event&);
+
+  tree_classdef_event& operator = (const tree_classdef_event&);
+};
+
+class tree_classdef_events_list : public octave_base_list<tree_classdef_event *>
+{
+public:
+
+  tree_classdef_events_list (void) { }
+
+  tree_classdef_events_list (tree_classdef_event *e) { append (e); }
+
+  tree_classdef_events_list (const octave_base_list<tree_classdef_event *>& a)
+    : octave_base_list<tree_classdef_event *> (a) { }
+
+  ~tree_classdef_events_list (void);
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_events_list (const tree_classdef_events_list&);
+
+  tree_classdef_events_list& operator = (const tree_classdef_events_list&);
+};
+
+class tree_classdef_events_block
+  : public tree_classdef_element<tree_classdef_event *>
+{
+public:
+
+  tree_classdef_events_block (tree_classdef_attribute_list *a,
+                              tree_classdef_events_list *elist,
+                              octave_comment_list *lc,
+                              octave_comment_list *tc, int l = -1, int c = -1)
+    : tree_classdef_element<tree_classdef_event *> (a, elist, lc, tc, l, c) { }
+
+  ~tree_classdef_events_block (void) { }
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_events_block (const tree_classdef_events_block&);
+
+  tree_classdef_events_block& operator = (const tree_classdef_events_block&);
+};
+
+class tree_classdef_enum
+{
+public:
+
+  tree_classdef_enum (void) : id (0), expr (0) { }
+
+  tree_classdef_enum (tree_identifier *i, tree_expression *e)
+    : id (i), expr (e) { }
+
+  ~tree_classdef_enum (void)
+  {
+    delete id;
+    delete expr;
+  }
+
+  tree_identifier *ident (void) { return id; }
+
+  tree_expression *expression (void) { return expr; }
+
+  void accept (tree_walker&);
+
+private:
+
+  tree_identifier *id;
+  tree_expression *expr;
+
+  // No copying!
+
+  tree_classdef_enum (const tree_classdef_enum&);
+
+  tree_classdef_enum& operator = (const tree_classdef_enum&);
+};
+
+class tree_classdef_enum_list : public octave_base_list<tree_classdef_enum *>
+{
+public:
+
+  tree_classdef_enum_list (void) { }
+
+  tree_classdef_enum_list (tree_classdef_enum *e) { append (e); }
+
+  tree_classdef_enum_list (const octave_base_list<tree_classdef_enum *>& a)
+    : octave_base_list<tree_classdef_enum *> (a) { }
+
+  ~tree_classdef_enum_list (void);
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_enum_list (const tree_classdef_enum_list&);
+
+  tree_classdef_enum_list& operator = (const tree_classdef_enum_list&);
+};
+
+class tree_classdef_enum_block
+  : public tree_classdef_element<tree_classdef_enum *>
+{
+public:
+
+  tree_classdef_enum_block (tree_classdef_attribute_list *a,
+                            tree_classdef_enum_list *elist,
+                            octave_comment_list *lc,
+                            octave_comment_list *tc, int l = -1, int c = -1)
+    : tree_classdef_element<tree_classdef_enum *> (a, elist, lc, tc, l, c) { }
+
+  ~tree_classdef_enum_block (void) { }
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_enum_block (const tree_classdef_enum_block&);
+
+  tree_classdef_enum_block& operator = (const tree_classdef_enum_block&);
+};
+
+class tree_classdef_body
+{
+public:
+
+  typedef std::list<tree_classdef_properties_block *>::iterator properties_list_iterator;
+  typedef std::list<tree_classdef_properties_block *>::const_iterator properties_list_const_iterator;
+
+  typedef std::list<tree_classdef_methods_block *>::iterator methods_list_iterator;
+  typedef std::list<tree_classdef_methods_block *>::const_iterator methods_list_const_iterator;
+
+  typedef std::list<tree_classdef_events_block *>::iterator events_list_iterator;
+  typedef std::list<tree_classdef_events_block *>::const_iterator events_list_const_iterator;
+
+  typedef std::list<tree_classdef_enum_block *>::iterator enum_list_iterator;
+  typedef std::list<tree_classdef_enum_block *>::const_iterator enum_list_const_iterator;
+
+  tree_classdef_body (void)
+    : properties_lst (), methods_lst (), events_lst (), enum_lst () { }
+
+  tree_classdef_body (tree_classdef_properties_block *pb)
+    : properties_lst (), methods_lst (), events_lst (), enum_lst ()
+  {
+    append (pb);
+  }
+
+  tree_classdef_body (tree_classdef_methods_block *mb)
+    : properties_lst (), methods_lst (), events_lst (), enum_lst ()
+  {
+    append (mb);
+  }
+
+  tree_classdef_body (tree_classdef_events_block *evb)
+    : properties_lst (), methods_lst (), events_lst (), enum_lst ()
+  {
+    append (evb);
+  }
+
+  tree_classdef_body (tree_classdef_enum_block *enb)
+    : properties_lst (), methods_lst (), events_lst (), enum_lst ()
+  {
+    append (enb);
+  }
+
+  ~tree_classdef_body (void);
+
+  void append (tree_classdef_properties_block *pb)
+  {
+    properties_lst.push_back (pb);
+  }
+
+  void append (tree_classdef_methods_block *mb)
+  {
+    methods_lst.push_back (mb);
+  }
+
+  void append (tree_classdef_events_block *evb)
+  {
+    events_lst.push_back (evb);
+  }
+
+  void append (tree_classdef_enum_block *enb)
+  {
+    enum_lst.push_back (enb);
+  }
+
+  std::list<tree_classdef_properties_block *> properties_list (void)
+  {
+    return properties_lst;
+  }
+
+  std::list<tree_classdef_methods_block *> methods_list (void)
+  {
+    return methods_lst;
+  }
+
+  std::list<tree_classdef_events_block *> events_list (void)
+  {
+    return events_lst;
+  }
+
+  std::list<tree_classdef_enum_block *> enum_list (void)
+  {
+    return enum_lst;
+  }
+
+  void accept (tree_walker&);
+
+private:
+
+  std::list<tree_classdef_properties_block *> properties_lst;
+
+  std::list<tree_classdef_methods_block *> methods_lst;
+
+  std::list<tree_classdef_events_block *> events_lst;
+
+  std::list<tree_classdef_enum_block *> enum_lst;
+
+  // No copying!
+
+  tree_classdef_body (const tree_classdef_body&);
+
+  tree_classdef_body& operator = (const tree_classdef_body&);
+};
+
+// Classdef definition.
+
+class tree_classdef : public tree_command
+{
+public:
+
+  tree_classdef (tree_classdef_attribute_list *a, tree_identifier *i,
+                 tree_classdef_superclass_list *sc,
+                 tree_classdef_body *b, octave_comment_list *lc,
+                 octave_comment_list *tc, int l = -1, int c = -1)
+    : tree_command (l, c), attr_list (a), id (i),
+      supclass_list (sc), element_list (b), lead_comm (lc), trail_comm (tc) { }
+
+  ~tree_classdef (void)
+  {
+    delete attr_list;
+    delete id;
+    delete supclass_list;
+    delete element_list;
+    delete lead_comm;
+    delete trail_comm;
+  }
+
+  tree_classdef_attribute_list *attribute_list (void) { return attr_list; }
+
+  tree_identifier *ident (void) { return id; }
+
+  tree_classdef_superclass_list *superclass_list (void) { return supclass_list; }
+
+  tree_classdef_body *body (void) { return element_list; }
+
+  octave_comment_list *leading_comment (void) { return lead_comm; }
+  octave_comment_list *trailing_comment (void) { return trail_comm; }
+
+  octave_function* make_meta_class (void);
+
+  tree_classdef *dup (symbol_table::scope_id scope,
+                      symbol_table::context_id context) const;
+
+  void accept (tree_walker& tw);
+
+private:
+
+  tree_classdef_attribute_list *attr_list;
+
+  tree_identifier *id;
+
+  tree_classdef_superclass_list *supclass_list;
+
+  tree_classdef_body *element_list;
+
+  octave_comment_list *lead_comm;
+  octave_comment_list *trail_comm;
+
+  // No copying!
+
+  tree_classdef (const tree_classdef&);
+
+  tree_classdef& operator = (const tree_classdef&);
+};
+
+#endif
--- a/libinterp/parse-tree/pt-eval.cc	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/pt-eval.cc	Mon Feb 11 15:45:26 2013 -0500
@@ -637,6 +637,12 @@
 }
 
 void
+tree_evaluator::visit_funcall (tree_funcall&)
+{
+  panic_impossible ();
+}
+
+void
 tree_evaluator::visit_parameter_list (tree_parameter_list&)
 {
   panic_impossible ();
--- a/libinterp/parse-tree/pt-eval.h	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/pt-eval.h	Mon Feb 11 15:45:26 2013 -0500
@@ -102,6 +102,8 @@
 
   void visit_fcn_handle (tree_fcn_handle&);
 
+  void visit_funcall (tree_funcall&);
+
   void visit_parameter_list (tree_parameter_list&);
 
   void visit_postfix_expression (tree_postfix_expression&);
--- a/libinterp/parse-tree/pt-exp.h	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/pt-exp.h	Mon Feb 11 15:45:26 2013 -0500
@@ -40,7 +40,7 @@
 public:
 
   tree_expression (int l = -1, int c = -1)
-    : tree (l, c), num_parens (0), postfix_indexed (false),
+    : tree (l, c), num_parens (0), postfix_index_type ('\0'),
       print_flag (false) { }
 
   virtual ~tree_expression (void) { }
@@ -85,7 +85,9 @@
 
   int paren_count (void) const { return num_parens; }
 
-  bool is_postfix_indexed (void) const { return postfix_indexed; }
+  bool is_postfix_indexed (void) const { return (postfix_index_type != '\0'); }
+
+  char postfix_index (void) const { return postfix_index_type; }
 
   // Check if the result of the expression should be printed.
   // Should normally be used in conjunction with
@@ -106,9 +108,9 @@
       return this;
     }
 
-  tree_expression *mark_postfix_indexed (void)
+  tree_expression *set_postfix_index (char type)
     {
-      postfix_indexed = true;
+      postfix_index_type = type;
       return this;
     }
 
@@ -121,7 +123,7 @@
   virtual void copy_base (const tree_expression& e)
     {
       num_parens = e.num_parens;
-      postfix_indexed = e.postfix_indexed;
+      postfix_index_type = e.postfix_index_type;
       print_flag = e.print_flag;
     }
 
@@ -135,9 +137,10 @@
   //                  ==> 0 for expression e2
   int num_parens;
 
-  // A flag that says whether this expression has an index associated
-  // with it.  See the code in tree_identifier::rvalue for the rationale.
-  bool postfix_indexed;
+  // The first index type associated with this expression. This field
+  // is 0 (character '\0') if the expression has no associated index.
+  // See the code in tree_identifier::rvalue for the rationale.
+  char postfix_index_type;
 
   // Print result of rvalue for this expression?
   bool print_flag;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-funcall.cc	Mon Feb 11 15:45:26 2013 -0500
@@ -0,0 +1,83 @@
+/*
+
+Copyright (C) 2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ov-fcn.h"
+#include "pt-funcall.h"
+#include "pt-walk.h"
+
+// Function call objects.
+
+void
+tree_funcall::print (std::ostream& os, bool pr_as_read_syntax,
+                     bool pr_orig_text)
+{
+  print_raw (os, pr_as_read_syntax, pr_orig_text);
+}
+
+void
+tree_funcall::print_raw (std::ostream& os, bool pr_as_read_syntax,
+                         bool pr_orig_text)
+{
+  if (pr_orig_text)
+    {
+      os << original_text ();
+    }
+  else
+    {
+      octave_function *fp = fcn.function_value ();
+      std::string nm = fp ? fp->name () : std::string ("<invalid-function>");
+
+      os << nm << " (";
+
+      octave_idx_type len = args.length ();
+      for (octave_idx_type i = 0; i < len; i++)
+        {
+          args(i).print_raw (os, pr_as_read_syntax);
+
+          if (i < len - 1)
+            os << ", ";
+        }
+
+      os << ")";
+    }
+}
+
+tree_funcall *
+tree_funcall::dup (symbol_table::scope_id,
+                  symbol_table::context_id context) const
+{
+  tree_funcall *new_fc = new tree_funcall (fcn, args, line (), column ());
+
+  new_fc->copy_base (*new_fc);
+
+  return new_fc;
+}
+
+void
+tree_funcall::accept (tree_walker& tw)
+{
+  tw.visit_funcall (*this);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-funcall.h	Mon Feb 11 15:45:26 2013 -0500
@@ -0,0 +1,101 @@
+/*
+
+Copyright (C) 2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_tree_funcall_h)
+#define octave_tree_funcall_h 1
+
+#include "ov.h"
+#include "oct-obj.h"
+#include "parse.h"
+#include "pt-exp.h"
+
+// Function call.  This class only represents function calls that have
+// known functions (most useful for calls to built-in functions that
+// are generated by the parser) and fixed argument lists, known at
+// compile time.
+
+class
+tree_funcall : public tree_expression
+{
+public:
+
+  tree_funcall (const octave_value& f, const octave_value_list& a,
+                int l = -1, int c = -1)
+    : tree_expression (l, c), fcn (f), args (a)
+  {
+    if (! fcn.is_function ())
+      error ("tree_funcall: invalid function");
+  }
+
+  ~tree_funcall (void) { }
+
+  bool has_magic_end (void) const { return false; }
+
+  void print (std::ostream& os, bool pr_as_read_syntax = false,
+              bool pr_orig_txt = true);
+
+  void print_raw (std::ostream& os, bool pr_as_read_syntax = false,
+                  bool pr_orig_txt = true);
+
+  tree_funcall *dup (symbol_table::scope_id,
+                     symbol_table::context_id context) const;
+
+  octave_value rvalue1 (int nargout)
+  {
+    octave_value retval;
+
+    const octave_value_list tmp = rvalue (nargout);
+
+    if (! tmp.empty ())
+      retval = tmp(0);
+
+    return retval;
+  }
+
+  octave_value_list rvalue (int nargout)
+  {
+    return feval (fcn.function_value (), args, nargout);
+  }
+
+  octave_value function (void) const { return fcn; }
+
+  octave_value_list arguments (void) const { return args; }
+
+  void accept (tree_walker& tw);
+
+private:
+
+  // Function to call.  Error if not a valid function at time of
+  // construction.
+  octave_value fcn;
+
+  // Argument list.
+  octave_value_list args;
+
+  // No copying!
+
+  tree_funcall (const tree_funcall&);
+
+  tree_funcall& operator = (const tree_funcall&);
+};
+
+#endif
--- a/libinterp/parse-tree/pt-id.cc	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/pt-id.cc	Mon Feb 11 15:45:26 2013 -0500
@@ -75,13 +75,19 @@
       //
       // If this identifier refers to a function, we need to know
       // whether it is indexed so that we can do the same thing
-      // for 'f' and 'f()'.  If the index is present, return the
-      // function object and let tree_index_expression::rvalue
-      // handle indexing.  Otherwise, arrange to call the function
-      // here, so that we don't return the function definition as
-      // a value.
+      // for 'f' and 'f()'.  If the index is present and the function
+      // object declares it can handle it, return the function object
+      // and let tree_index_expression::rvalue handle indexing.
+      // Otherwise, arrange to call the function here, so that we don't
+      // return the function definition as a value.
 
-      if (val.is_function () && ! is_postfix_indexed ())
+      octave_function *fcn = 0;
+
+      if (val.is_function ())
+        fcn = val.function_value (true);
+
+      if (fcn && ! (is_postfix_indexed ()
+                    && fcn->is_postfix_index_handled (postfix_index ())))
         {
           octave_value_list tmp_args;
 
--- a/libinterp/parse-tree/pt-id.h	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/pt-id.h	Mon Feb 11 15:45:26 2013 -0500
@@ -32,6 +32,7 @@
 
 class tree_walker;
 
+#include "oct-lvalue.h"
 #include "pt-bp.h"
 #include "pt-exp.h"
 #include "symtab.h"
--- a/libinterp/parse-tree/pt-pr-code.cc	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/pt-pr-code.cc	Mon Feb 11 15:45:26 2013 -0500
@@ -749,6 +749,18 @@
 }
 
 void
+tree_print_code::visit_funcall (tree_funcall& fc)
+{
+  indent ();
+
+  print_parens (fc, "(");
+
+  fc.print_raw (os, true, print_original_text);
+
+  print_parens (fc, ")");
+}
+
+void
 tree_print_code::visit_parameter_list (tree_parameter_list& lst)
 {
   tree_parameter_list::iterator p = lst.begin ();
--- a/libinterp/parse-tree/pt-pr-code.h	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/pt-pr-code.h	Mon Feb 11 15:45:26 2013 -0500
@@ -109,6 +109,8 @@
 
   void visit_fcn_handle (tree_fcn_handle&);
 
+  void visit_funcall (tree_funcall&);
+
   void visit_parameter_list (tree_parameter_list&);
 
   void visit_postfix_expression (tree_postfix_expression&);
--- a/libinterp/parse-tree/pt-walk.h	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/pt-walk.h	Mon Feb 11 15:45:26 2013 -0500
@@ -52,6 +52,7 @@
 class tree_no_op_command;
 class tree_constant;
 class tree_fcn_handle;
+class tree_funcall;
 class tree_parameter_list;
 class tree_postfix_expression;
 class tree_prefix_expression;
@@ -65,6 +66,24 @@
 class tree_while_command;
 class tree_do_until_command;
 
+class tree_classdef_attribute;
+class tree_classdef_attribute_list;
+class tree_classdef_superclass;
+class tree_classdef_superclass_list;
+class tree_classdef_property;
+class tree_classdef_property_list;
+class tree_classdef_properties_block;
+class tree_classdef_methods_list;
+class tree_classdef_methods_block;
+class tree_classdef_event;
+class tree_classdef_events_list;
+class tree_classdef_events_block;
+class tree_classdef_enum;
+class tree_classdef_enum_list;
+class tree_classdef_enum_block;
+class tree_classdef_body;
+class tree_classdef;
+
 class
 tree_walker
 {
@@ -158,6 +177,9 @@
   visit_fcn_handle (tree_fcn_handle&) = 0;
 
   virtual void
+  visit_funcall (tree_funcall&) = 0;
+
+  virtual void
   visit_parameter_list (tree_parameter_list&) = 0;
 
   virtual void
@@ -193,6 +215,57 @@
   virtual void
   visit_do_until_command (tree_do_until_command&) = 0;
 
+  virtual void
+  visit_classdef_attribute (tree_classdef_attribute&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_attribute_list (tree_classdef_attribute_list&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_superclass (tree_classdef_superclass&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_superclass_list (tree_classdef_superclass_list&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_property (tree_classdef_property&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_property_list (tree_classdef_property_list&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_properties_block (tree_classdef_properties_block&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_methods_list (tree_classdef_methods_list&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_methods_block (tree_classdef_methods_block&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_event (tree_classdef_event&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_events_list (tree_classdef_events_list&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_events_block (tree_classdef_events_block&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_enum (tree_classdef_enum&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_enum_list (tree_classdef_enum_list&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_enum_block (tree_classdef_enum_block&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_body (tree_classdef_body&) { } /* = 0; */
+
+  virtual void
+  visit_classdef (tree_classdef&) { } /* = 0; */
+
 protected:
 
   tree_walker (void) { }
--- a/libinterp/parse-tree/token.cc	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/token.cc	Mon Feb 11 15:45:26 2013 -0500
@@ -72,32 +72,43 @@
   sr = s;
 }
 
-token::token (symbol_table::symbol_record *cls,
-              symbol_table::symbol_record *pkg, int l, int c)
+token::token (const std::string& pkg, const std::string& cls, int l, int c)
 {
   line_num = l;
   column_num = c;
-  type_tag = meta_rec_token;
-  mc.cr = cls;
-  mc.pr = pkg;
+  type_tag = meta_name_token;
+  mc.package_nm = new std::string (pkg);
+  mc.class_nm = new std::string (cls);
 }
 
-token::token (symbol_table::symbol_record *mth,
-              symbol_table::symbol_record *cls,
-              symbol_table::symbol_record *pkg, int l, int c)
+token::token (const std::string& mth, const std::string& pkg,
+              const std::string& cls, int l, int c)
 {
   line_num = l;
   column_num = c;
-  type_tag = scls_rec_token;
-  sc.mr = mth;
-  sc.cr = cls;
-  sc.pr = pkg;
+  type_tag = scls_name_token;
+  sc.method_nm = new std::string (mth);
+  sc.package_nm = new std::string (pkg);
+  sc.class_nm = new std::string (cls);
 }
 
 token::~token (void)
 {
   if (type_tag == string_token)
     delete str;
+
+  if (type_tag == scls_name_token)
+    {
+      delete sc.method_nm;
+      delete sc.package_nm;
+      delete sc.class_nm;
+    }
+
+  if (type_tag == meta_name_token)
+    {
+      delete mc.package_nm;
+      delete mc.class_nm;
+    }
 }
 
 std::string
@@ -128,39 +139,39 @@
   return sr;
 }
 
-symbol_table::symbol_record *
-token::method_rec (void)
+std::string
+token::superclass_method_name (void)
 {
-  assert (type_tag == scls_rec_token);
-  return sc.mr;
+  assert (type_tag == scls_name_token);
+  return *sc.method_nm;
 }
 
-symbol_table::symbol_record *
-token::class_rec (void)
+std::string
+token::superclass_package_name (void)
 {
-  assert (type_tag == scls_rec_token);
-  return sc.cr;
+  assert (type_tag == scls_name_token);
+  return *sc.package_nm;
 }
 
-symbol_table::symbol_record *
-token::package_rec (void)
+std::string
+token::superclass_class_name (void)
 {
-  assert (type_tag == scls_rec_token);
-  return sc.pr;
+  assert (type_tag == scls_name_token);
+  return *sc.class_nm;
 }
 
-symbol_table::symbol_record *
-token::meta_class_rec (void)
+std::string
+token::meta_package_name (void)
 {
-  assert (type_tag == meta_rec_token);
-  return mc.cr;
+  assert (type_tag == meta_name_token);
+  return *mc.package_nm;
 }
 
-symbol_table::symbol_record *
-token::meta_package_rec (void)
+std::string
+token::meta_class_name (void)
 {
-  assert (type_tag == meta_rec_token);
-  return mc.pr;
+  assert (type_tag == meta_name_token);
+  return *mc.class_nm;
 }
 
 std::string
--- a/libinterp/parse-tree/token.h	Mon Feb 11 13:28:04 2013 -0500
+++ b/libinterp/parse-tree/token.h	Mon Feb 11 15:45:26 2013 -0500
@@ -37,8 +37,8 @@
       double_token,
       ettype_token,
       sym_rec_token,
-      scls_rec_token,
-      meta_rec_token
+      scls_name_token,
+      meta_name_token
     };
 
   enum end_tok_type
@@ -65,11 +65,10 @@
          int l = -1, int c = -1);
   token (end_tok_type t, int l = -1, int c = -1);
   token (symbol_table::symbol_record *s, int l = -1, int c = -1);
-  token (symbol_table::symbol_record *cls,
-         symbol_table::symbol_record *pkg, int l = -1, int c = -1);
-  token (symbol_table::symbol_record *mth,
-         symbol_table::symbol_record *cls,
-         symbol_table::symbol_record *pkg, int l = -1, int c = -1);
+  token (const std::string& pkg, const std::string& cls,
+         int l = -1, int c = -1);
+  token (const std::string& mth, const std::string& pkg,
+         const std::string& cls, int l = -1, int c = -1);
 
   ~token (void);
 
@@ -81,12 +80,12 @@
   end_tok_type ettype (void);
   symbol_table::symbol_record *sym_rec (void);
 
-  symbol_table::symbol_record *method_rec (void);
-  symbol_table::symbol_record *class_rec (void);
-  symbol_table::symbol_record *package_rec (void);
+  std::string superclass_method_name (void);
+  std::string superclass_package_name (void);
+  std::string superclass_class_name (void);
 
-  symbol_table::symbol_record *meta_class_rec (void);
-  symbol_table::symbol_record *meta_package_rec (void);
+  std::string meta_package_name (void);
+  std::string meta_class_name (void);
 
   std::string text_rep (void);
 
@@ -109,14 +108,14 @@
       symbol_table::symbol_record *sr;
       struct
         {
-          symbol_table::symbol_record *mr;
-          symbol_table::symbol_record *cr;
-          symbol_table::symbol_record *pr;
+          std::string *method_nm;
+          std::string *package_nm;
+          std::string *class_nm;
         } sc;
       struct
         {
-          symbol_table::symbol_record *cr;
-          symbol_table::symbol_record *pr;
+          std::string *package_nm;
+          std::string *class_nm;
         } mc;
     };
   std::string orig_text;
--- a/liboctave/util/base-list.h	Mon Feb 11 13:28:04 2013 -0500
+++ b/liboctave/util/base-list.h	Mon Feb 11 15:45:26 2013 -0500
@@ -87,8 +87,6 @@
   // For backward compatibility.
   void append (const elt_type& s) { lst.push_back (s); }
 
-protected:
-
   octave_base_list (void) : lst () { }
 
   octave_base_list (const std::list<elt_type>& l) : lst (l) { }
--- a/test/Makefile.am	Mon Feb 11 13:28:04 2013 -0500
+++ b/test/Makefile.am	Mon Feb 11 15:45:26 2013 -0500
@@ -53,6 +53,7 @@
 include bug-35448/module.mk
 include bug-36025/module.mk
 include bug-38236/module.mk
+include classdef/module.mk
 include classes/module.mk
 include class-concat/module.mk
 include ctor-vs-method/module.mk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classdef/classdef.tst	Mon Feb 11 15:45:26 2013 -0500
@@ -0,0 +1,73 @@
+## Copyright (C) 2013 Ben Abbott
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+%%  Test script for classdef OOP.
+%%  Requires the path to contain the test classes.
+%%
+%%  Note: This script and all classes are also intended to run
+%%        in MATLAB to test compatibility.  Don't break that!
+%%
+%%  To Do:  This script tests to ensure that things done correctly work
+%%          corrrectly.  It should also check that things done incorrectly
+%%          error properly.
+%%
+%%  The classes used for the tests reside in the test/classdef with others
+%%  in the test directory.
+%%
+%%  The classes provide the ability to test most of the major features
+%%  of the classdef OOP facilities.  There are a number of classes, mostly
+%%  kind of the same, that create a hierarchy.
+
+%%  Basic classdef tests for value class
+%!shared p, q, i, amt
+%! q = foo_value_class ();
+%! p = foo_value_class (4, 4*12, 50e3);
+%! i = p.rate / (12 * 100);
+%! amt = (p.principle * i) / (1 - (1 + i)^(-p.term));
+%!assert (isempty (q.rate));
+%!assert (isempty (q.principle));
+%!assert (isempty (q.term));
+%!assert (class (p), "foo_value_class");
+%!assert (p.term, 48);
+%!assert (p.rate, 4.0);
+%!assert (p.principle, 50e3);
+%!assert (p.amount, amt, eps ())
+%!assert (amount (p), amt, eps ())
+%!xtest
+%! assert (properties (p), {'rate'; 'term'; 'principle'})
+%!xtest
+%! assert (methods (p), {'amount'; 'foo_value_class'})
+%!assert (isempty (foo_value_class().rate))
+%!error <property `rate' is not constant> foo_value_class.rate
+
+%%  Static method and Constant Property
+%!assert (foo_static_method_constant_property.radians_per_cycle, 2*pi);
+%!assert (foo_static_method_constant_property().radians_per_cycle, 2*pi);
+%!assert (foo_static_method_constant_property().pie, pi);
+%!error <property `frequency' is not constant> foo_static_method_constant_property.frequency
+%!error <method `cosine' is not static> foo_static_method_constant_property.cosine
+%!test
+%! obj = foo_static_method_constant_property;
+%! obj.frequency = 10;
+%! assert (obj.cosine (0.1), cos (2 * pi * 10 * 0.1), eps ())
+%! assert (obj.sine (0.1), sin (2 * pi * 10 * 0.1), eps ())
+
+%!xtest
+%! obj = foo_method_changes_property_size (3);
+%! obj = obj.move_element_to_end (2);
+%! assert (obj.element, [1 3 2])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classdef/foo_method_changes_property_size.m	Mon Feb 11 15:45:26 2013 -0500
@@ -0,0 +1,14 @@
+classdef foo_method_changes_property_size
+  properties
+    element;
+  end
+  methods
+    function obj = foo_method_changes_property_size (n)
+      obj.element = 1:n;
+    end
+    function obj = move_element_to_end (obj, n)
+      obj.element(end+1) = obj.element(n);
+      obj.element(n) = [];
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classdef/foo_static_method_constant_property.m	Mon Feb 11 15:45:26 2013 -0500
@@ -0,0 +1,30 @@
+classdef foo_static_method_constant_property
+  properties
+    frequency;
+  end
+  properties (Constant = true)
+    pie = pi;
+  end
+  methods
+    function obj = foo_static_method_constant_property (f)
+      if (nargin == 1)
+        obj.frequency = f;
+      elseif (nargin ~= 0)
+        error ('foo_static_method_constant_property:SyntaxError', ...
+               'foo_static_method_constant_property: Invalid syntax')
+      end
+    end
+    function res = cosine (obj, t)
+      res = cos (obj.radians_per_cycle () * obj.frequency * t);
+    end
+    function res = sine (obj, t)
+      res = sin (obj.radians_per_cycle () * obj.frequency * t);
+    end
+  end
+  methods (Static)
+    function res = radians_per_cycle ()
+      res = 2 * foo_static_method_constant_property.pie;
+    end
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classdef/foo_value_class.m	Mon Feb 11 15:45:26 2013 -0500
@@ -0,0 +1,28 @@
+classdef foo_value_class
+  properties
+    rate;
+    term;
+    principle;
+  end
+  methods
+    function obj = foo_value_class (r, t, p)
+      if (nargin == 3)
+        obj.rate = r;
+        obj.term = t;
+        obj.principle = p;
+      elseif (nargin ~= 0)
+        error ('foo_value_class:SyntaxError', ...
+               'foo_value_class: Invalid syntax')
+      end
+    end
+    function amt = amount (obj)
+      i = obj.rate / (12 * 100);
+      if (i == 0 && obj.term == 0)
+        amt = obj.principle;
+      else
+        amt = (obj.principle * i) / (1 - (1 + i)^(-obj.term));
+      end
+    end
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classdef/module.mk	Mon Feb 11 15:45:26 2013 -0500
@@ -0,0 +1,7 @@
+classdef_FCN_FILES = \
+  classdef/foo_method_changes_property_size.m \
+  classdef/foo_static_method_constant_property.m \
+  classdef/foo_value_class.m \
+  classdef/classdef.tst
+
+FCN_FILES += $(classdef_FCN_FILES)