changeset 26686:581d01526b34

eliminate unnecessary tree_funcall class The tree_funcall class was only used to handled generated calls to internal functions used by classdef superclass reference and metaclass query operations. This change replaces those function calls by something more direct. * pt-classdef.h, pt-classdef.cc (tree_superclass_ref, tree_metaclass_query): New classes. * pt-walk.h (tree_walker::visit_tree_funcall): Delete. Update all derived classes. (tree_walker::visit_superclass_ref, tree_walker::visit_metaclass_query): New virtual functions. * pt-pr-code.h, pt-pr-code.cc (tree_print_code::visit (tree_print_code::visit_superclass_ref, tree_print_code::visit_metaclass_query): Correctly print these parse tree elements. * oct-parse.yy (superclass_identifier, meta_identifier): Use new tree_superclass_ref tree_metaclass_query classes instead of tree_funcall to represent these language elements. * lex.ll (base_lexer::handle_superclass_identifier): Attempt to make intent of code clearer. Save line and column info in token. * pt-eval.h, pt-eval.cc (tree_evaluator::visit_funcall): Delete. (tree_evaluator::visit_superclass_ref, tree_evaluator::visit_metaclass_query): New functions. Handle superclass reference and metaclass query operations more directly. * ov-classdef.h, ov-classdef.cc (F__superclass_reference__, F__meta_class_query__): Delete. (class octave_classdef_superclass_ref): Work directly with method or object and class names as strings instead of octave_value objects. (octave_classdef::superclass_ref, octave_classdef::metaclass_query): New static functions. * token.h, token.cc: Attempt to use clearer names for superclass reference tokens. * pt-funcall.h, pt-funcall.cc: Delete. * libinterp/parse-tree/module.mk: Update. * pt-all.h: Update.
author John W. Eaton <jwe@octave.org>
date Thu, 07 Feb 2019 00:03:55 +0000
parents 466e9b261689
children 3e1f8934c4de
files libinterp/octave-value/ov-classdef.cc libinterp/octave-value/ov-classdef.h libinterp/parse-tree/lex.ll libinterp/parse-tree/module.mk libinterp/parse-tree/oct-parse.yy libinterp/parse-tree/parse.h libinterp/parse-tree/pt-all.h libinterp/parse-tree/pt-anon-scopes.cc libinterp/parse-tree/pt-anon-scopes.h libinterp/parse-tree/pt-bp.cc libinterp/parse-tree/pt-bp.h libinterp/parse-tree/pt-check.cc libinterp/parse-tree/pt-check.h libinterp/parse-tree/pt-classdef.cc libinterp/parse-tree/pt-classdef.h libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h libinterp/parse-tree/pt-funcall.cc libinterp/parse-tree/pt-funcall.h libinterp/parse-tree/pt-jit.cc libinterp/parse-tree/pt-jit.h libinterp/parse-tree/pt-pr-code.cc libinterp/parse-tree/pt-pr-code.h libinterp/parse-tree/pt-walk.h libinterp/parse-tree/token.cc libinterp/parse-tree/token.h
diffstat 26 files changed, 244 insertions(+), 393 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/octave-value/ov-classdef.cc	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/octave-value/ov-classdef.cc	Thu Feb 07 00:03:55 2019 +0000
@@ -36,10 +36,10 @@
 #include "ov-fcn-handle.h"
 #include "ov-typeinfo.h"
 #include "ov-usr-fcn.h"
+#include "parse.h"
 #include "pt-assign.h"
 #include "pt-classdef.h"
 #include "pt-eval.h"
-#include "pt-funcall.h"
 #include "pt-idx.h"
 #include "pt-misc.h"
 #include "pt-stmt.h"
@@ -1125,8 +1125,11 @@
 public:
   octave_classdef_superclass_ref (void) = delete;
 
-  octave_classdef_superclass_ref (const octave_value_list& a)
-    : octave_function (), args (a) { }
+  octave_classdef_superclass_ref (const std::string& meth_or_obj,
+                                  const std::string& cls)
+    : octave_function (), m_method_or_object_name (meth_or_obj),
+      m_class_name (cls)
+  { }
 
   octave_classdef_superclass_ref (const octave_classdef_superclass_ref&) = delete;
 
@@ -1152,8 +1155,8 @@
     if (! ctx.ok ())
       error ("superclass calls can only occur in methods or constructors");
 
-    std::string mname = args(0).string_value ();
-    std::string cname = args(1).string_value ();
+    std::string mname = m_method_or_object_name;
+    std::string cname = m_class_name;
 
     cdef_class cls = lookup_class (cname);
 
@@ -1232,9 +1235,24 @@
   }
 
 private:
-  octave_value_list args;
+
+  std::string m_method_or_object_name;
+  std::string m_class_name;
 };
 
+octave_value
+octave_classdef::superclass_ref (const std::string& meth_or_obj,
+                                 const std::string& cls)
+{
+  return octave_value (new octave_classdef_superclass_ref (meth_or_obj, cls));
+}
+
+octave_value
+octave_classdef::metaclass_query (const std::string& cls)
+{
+  return to_ov (lookup_class (cls));
+}
+
 //----------------------------------------------------------------------------
 
 void
@@ -1979,34 +1997,6 @@
     t.expression ()->accept (*this);
   }
 
-  void visit_funcall (octave::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 class_name = args(1).string_value ();
-
-                    cdef_class cls = lookup_class (class_name, false);
-
-                    if (cls.ok ())
-                      ctor_list.push_back (cls);
-                  }
-              }
-          }
-      }
-  }
-
   std::list<cdef_class> get_constructor_list (void) const
   { return ctor_list; }
 
@@ -2047,6 +2037,19 @@
   void visit_while_command (octave::tree_while_command&) { }
   void visit_do_until_command (octave::tree_do_until_command&) { }
 
+  void visit_superclass_ref (octave::tree_superclass_ref& t)
+  {
+    if (t.method_or_object_name () == obj_name)
+      {
+        std::string class_name = t.class_name ();
+
+        cdef_class cls = lookup_class (class_name, false);
+
+        if (cls.ok ())
+          ctor_list.push_back (cls);
+      }
+  }
+
 private:
   // The name of the constructor being analyzed.
   std::string who;
@@ -3911,35 +3914,6 @@
   return to_ov (lookup_package (cname));
 }
 
-DEFUN (__superclass_reference__, args, ,
-       doc: /* -*- texinfo -*-
-@deftypefn {} {} __superclass_reference__ ()
-Undocumented internal function.
-@end deftypefn */)
-{
-  return ovl (new octave_classdef_superclass_ref (args));
-}
-
-DEFUN (__meta_class_query__, args, ,
-       doc: /* -*- texinfo -*-
-@deftypefn {} {} __meta_class_query__ ()
-Undocumented internal function.
-@end deftypefn */)
-{
-#if DEBUG_TRACE
-  std::cerr << "__meta_class_query__ ("
-            << args(0).string_value () << ')'
-            << std::endl;
-#endif
-
-  if (args.length () != 1)
-    print_usage ();
-
-  std::string cls = args(0).xstring_value ("CLASS_NAME must be a string");
-
-  return to_ov (lookup_class (cls));
-}
-
 DEFUN (metaclass, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {} metaclass (obj)
--- a/libinterp/octave-value/ov-classdef.h	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/octave-value/ov-classdef.h	Thu Feb 07 00:03:55 2019 +0000
@@ -1560,6 +1560,11 @@
     return object.get_property (idx, name);
   }
 
+  static octave_value superclass_ref (const std::string& meth_or_obj,
+                                      const std::string& cls);
+
+  static octave_value metaclass_query (const std::string& cls);
+
 public:
   int type_id (void) const { return t_id; }
   std::string type_name (void) const { return t_name; }
--- a/libinterp/parse-tree/lex.ll	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/lex.ll	Thu Feb 07 00:03:55 2019 +0000
@@ -2965,13 +2965,14 @@
   int
   base_lexer::handle_superclass_identifier (void)
   {
-    std::string meth = flex_yytext ();
-
-    size_t pos = meth.find ("@");
-    std::string cls = meth.substr (pos + 1);
-    meth = meth.substr (0, pos);
-
-    bool kw_token = (is_keyword_token (meth)
+    std::string txt = flex_yytext ();
+
+    size_t pos = txt.find ("@");
+
+    std::string meth_or_obj = txt.substr (0, pos);
+    std::string cls = txt.substr (pos + 1);
+
+    bool kw_token = (is_keyword_token (meth_or_obj)
                      || fq_identifier_contains_keyword (cls));
 
     if (kw_token)
@@ -2986,7 +2987,7 @@
         return count_token_internal (LEXICAL_ERROR);
       }
 
-    push_token (new token (SUPERCLASSREF, meth, cls,
+    push_token (new token (SUPERCLASSREF, meth_or_obj, cls,
                            m_input_line_number, m_current_input_column));
 
     m_current_input_column += flex_yyleng ();
--- a/libinterp/parse-tree/module.mk	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/module.mk	Thu Feb 07 00:03:55 2019 +0000
@@ -27,7 +27,6 @@
   %reldir%/pt-except.h \
   %reldir%/pt-exp.h \
   %reldir%/pt-fcn-handle.h \
-  %reldir%/pt-funcall.h \
   %reldir%/pt-id.h \
   %reldir%/pt-idx.h \
   %reldir%/pt-jit.h \
@@ -77,7 +76,6 @@
   %reldir%/pt-except.cc \
   %reldir%/pt-exp.cc \
   %reldir%/pt-fcn-handle.cc \
-  %reldir%/pt-funcall.cc \
   %reldir%/pt-id.cc \
   %reldir%/pt-idx.cc \
   %reldir%/pt-jit.cc \
--- a/libinterp/parse-tree/oct-parse.yy	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/oct-parse.yy	Thu Feb 07 00:03:55 2019 +0000
@@ -75,7 +75,6 @@
 #include "parse.h"
 #include "pt-all.h"
 #include "pt-eval.h"
-#include "pt-funcall.h"
 #include "symtab.h"
 #include "token.h"
 #include "unwind-prot.h"
@@ -150,7 +149,8 @@
   octave::tree_expression *tree_expression_type;
   octave::tree_constant *tree_constant_type;
   octave::tree_fcn_handle *tree_fcn_handle_type;
-  octave::tree_funcall *tree_funcall_type;
+  octave::tree_superclass_ref *tree_superclass_ref_type;
+  octave::tree_metaclass_query *tree_metaclass_query_type;
   octave::tree_function_def *tree_function_def_type;
   octave::tree_anon_fcn_handle *tree_anon_fcn_handle_type;
   octave::tree_identifier *tree_identifier_type;
@@ -248,7 +248,8 @@
 %type <tree_expression_type> primary_expr oper_expr power_expr expr_no_assign
 %type <tree_expression_type> simple_expr colon_expr assign_expr expression
 %type <tree_identifier_type> identifier fcn_name magic_tilde
-%type <tree_funcall_type> superclass_identifier meta_identifier
+%type <tree_superclass_ref_type> superclass_identifier
+%type <tree_metaclass_query_type> meta_identifier
 %type <tree_index_expression_type> word_list_cmd
 %type <tree_argument_list_type> arg_list word_list assign_lhs
 %type <tree_argument_list_type> cell_or_matrix_row
@@ -325,7 +326,8 @@
 %destructor { delete $$; } <tree_expression_type>
 %destructor { delete $$; } <tree_constant_type>
 %destructor { delete $$; } <tree_fcn_handle_type>
-%destructor { delete $$; } <tree_funcall_type>
+%destructor { delete $$; } <tree_superclass_ref_type>
+%destructor { delete $$; } <tree_metaclass_query_type>
 %destructor { delete $$; } <tree_function_def_type>
 %destructor { delete $$; } <tree_anon_fcn_handle_type>
 %destructor { delete $$; } <tree_identifier_type>
@@ -512,18 +514,22 @@
 superclass_identifier
                 : SUPERCLASSREF
                   {
-                    std::string method_nm = $1->superclass_method_name ();
-                    std::string class_nm = $1->superclass_class_name ();
-
-                    $$ = parser.make_superclass_ref (method_nm, class_nm);
+                    std::string meth_or_obj
+                      = $1->superclass_method_or_object_name ();
+                    std::string cls = $1->superclass_class_name ();
+
+                    $$ = new octave::tree_superclass_ref (meth_or_obj, cls,
+                                                          $1->line (),
+                                                          $1->column ());
                   }
                 ;
 
 meta_identifier : METAQUERY
                   {
-                    std::string class_nm = $1->text ();
-
-                    $$ = parser.make_meta_class_query (class_nm);
+                    std::string cls = $1->text ();
+
+                    $$ = new octave::tree_metaclass_query (cls, $1->line (),
+                                                           $1->column ());
                   }
                 ;
 
@@ -3548,40 +3554,6 @@
     m_lexer.m_looking_at_parameter_list = false;
   }
 
-  tree_funcall *
-  base_parser::make_superclass_ref (const std::string& method_nm,
-                                    const std::string& class_nm)
-  {
-    octave_value_list args;
-
-    args(1) = class_nm;
-    args(0) = method_nm;
-
-    symbol_table& symtab
-      = __get_symbol_table__ ("base_parser::make_superclass_ref");
-
-    octave_value fcn
-      = symtab.find_built_in_function ("__superclass_reference__");
-
-    return new tree_funcall (fcn, args);
-  }
-
-  tree_funcall *
-  base_parser::make_meta_class_query (const std::string& class_nm)
-  {
-    octave_value_list args;
-
-    args(0) = class_nm;
-
-    symbol_table& symtab
-      = __get_symbol_table__ ("base_parser::make_meta_class_query");
-
-    octave_value fcn
-      = symtab.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
--- a/libinterp/parse-tree/parse.h	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/parse.h	Thu Feb 07 00:03:55 2019 +0000
@@ -68,7 +68,6 @@
   class tree_decl_init_list;
   class tree_expression;
   class tree_fcn_handle;
-  class tree_funcall;
   class tree_function_def;
   class tree_identifier;
   class tree_if_clause;
@@ -304,13 +303,6 @@
     void
     recover_from_parsing_function (void);
 
-    tree_funcall *
-    make_superclass_ref (const std::string& method_nm,
-                         const std::string& class_nm);
-
-    tree_funcall *
-    make_meta_class_query (const std::string& class_nm);
-
     tree_classdef *
     make_classdef (token *tok_val, tree_classdef_attribute_list *a,
                    tree_identifier *id, tree_classdef_superclass_list *sc,
--- a/libinterp/parse-tree/pt-all.h	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/pt-all.h	Thu Feb 07 00:03:55 2019 +0000
@@ -40,7 +40,6 @@
 #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-anon-scopes.cc	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/pt-anon-scopes.cc	Thu Feb 07 00:03:55 2019 +0000
@@ -302,11 +302,6 @@
   }
 
   void
-  tree_anon_scopes::visit_funcall (tree_funcall& /* fc */)
-  {
-  }
-
-  void
   tree_anon_scopes::visit_parameter_list (tree_parameter_list&)
   {
     // In visit_anon_fcn_handle we only accept/visit the body of
--- a/libinterp/parse-tree/pt-anon-scopes.h	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/pt-anon-scopes.h	Thu Feb 07 00:03:55 2019 +0000
@@ -114,8 +114,6 @@
 
     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-bp.cc	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/pt-bp.cc	Thu Feb 07 00:03:55 2019 +0000
@@ -277,12 +277,6 @@
   }
 
   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	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/pt-bp.h	Thu Feb 07 00:03:55 2019 +0000
@@ -115,8 +115,6 @@
 
     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	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/pt-check.cc	Thu Feb 07 00:03:55 2019 +0000
@@ -340,10 +340,6 @@
   { }
 
   void
-  tree_checker::visit_funcall (tree_funcall& /* fc */)
-  { }
-
-  void
   tree_checker::visit_parameter_list (tree_parameter_list& lst)
   {
     auto p = lst.begin ();
--- a/libinterp/parse-tree/pt-check.h	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/pt-check.h	Thu Feb 07 00:03:55 2019 +0000
@@ -100,8 +100,6 @@
 
     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-classdef.cc	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/pt-classdef.cc	Thu Feb 07 00:03:55 2019 +0000
@@ -29,6 +29,29 @@
 
 namespace octave
 {
+  tree_superclass_ref *
+  tree_superclass_ref::dup (symbol_scope&) const
+  {
+    tree_superclass_ref *new_scr
+      = new tree_superclass_ref (m_method_or_object_name, m_class_name,
+                                 line (), column ());
+
+    new_scr->copy_base (*this);
+
+    return new_scr;
+  }
+
+  tree_metaclass_query *
+  tree_metaclass_query::dup (symbol_scope&) const
+  {
+    tree_metaclass_query *new_mcq
+      = new tree_metaclass_query (m_class_name, line (), column ());
+
+    new_mcq->copy_base (*this);
+
+    return new_mcq;
+  }
+
   // Classdef attribute
 
   // Classdef attribute_list
--- a/libinterp/parse-tree/pt-classdef.h	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/pt-classdef.h	Thu Feb 07 00:03:55 2019 +0000
@@ -41,6 +41,78 @@
 {
   class interpreter;
 
+  class tree_superclass_ref : public tree_expression
+  {
+  public:
+
+    tree_superclass_ref (void) = delete;
+
+    tree_superclass_ref (const std::string& meth_or_obj,
+                         const std::string& cls, int l = -1, int c = -1)
+      : tree_expression (l, c), m_method_or_object_name (meth_or_obj),
+        m_class_name (cls)
+    { }
+
+    // No copying!
+
+    tree_superclass_ref (const tree_superclass_ref&) = delete;
+
+    tree_superclass_ref& operator = (const tree_superclass_ref&) = delete;
+
+    std::string method_or_object_name (void) const
+    {
+      return m_method_or_object_name;
+    }
+
+    std::string class_name (void) const { return m_class_name; }
+
+    bool has_magic_end (void) const { return false; }
+
+    tree_superclass_ref * dup (symbol_scope& scope) const;
+
+    void accept (tree_walker& tw)
+    {
+      tw.visit_superclass_ref (*this);
+    }
+
+  private:
+
+    std::string m_method_or_object_name;
+    std::string m_class_name;
+  };
+
+  class tree_metaclass_query : public tree_expression
+  {
+  public:
+
+    tree_metaclass_query (void) = delete;
+
+    tree_metaclass_query (const std::string& cls, int l = -1, int c = -1)
+      : tree_expression (l, c), m_class_name (cls)
+    { }
+
+    // No copying!
+
+    tree_metaclass_query (const tree_metaclass_query&) = delete;
+
+    tree_metaclass_query& operator = (const tree_metaclass_query&) = delete;
+
+    std::string class_name (void) const { return m_class_name; }
+
+    bool has_magic_end (void) const { return false; }
+
+    tree_metaclass_query * dup (symbol_scope& scope) const;
+
+    void accept (tree_walker& tw)
+    {
+      tw.visit_metaclass_query (*this);
+    }
+
+  private:
+
+    std::string m_class_name;
+  };
+
   class tree_classdef_attribute
   {
   public:
--- a/libinterp/parse-tree/pt-eval.cc	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/pt-eval.cc	Thu Feb 07 00:03:55 2019 +0000
@@ -46,6 +46,7 @@
 #include "ov-usr-fcn.h"
 #include "ov-re-sparse.h"
 #include "ov-cx-sparse.h"
+#include "parse.h"
 #include "profiler.h"
 #include "pt-all.h"
 #include "pt-anon-scopes.h"
@@ -2697,38 +2698,6 @@
   }
 
   void
-  tree_evaluator::visit_funcall (tree_funcall& expr)
-  {
-    octave_value_list retval;
-
-    octave_value fcn = expr.function ();
-
-    octave_value_list args = expr.arguments ();
-
-    int nargout = m_nargout_stack.top ();
-
-    retval = feval (fcn.function_value (), args, nargout);
-
-    if (retval.length () == 1 && retval(0).is_function ())
-      {
-        // The return object is a function.  We may need to re-index it
-        // using the same logic as for identifier.  This is primarily
-        // used for superclass references in classdef.
-
-        octave_value val = retval(0);
-        octave_function *f = val.function_value (true);
-
-        if (f && ! (expr.is_postfix_indexed ()
-                    && f->accepts_postfix_index (expr.postfix_index ())))
-          {
-            retval = f->call (*this, nargout);
-          }
-      }
-
-    push_result (retval);
-  }
-
-  void
   tree_evaluator::visit_parameter_list (tree_parameter_list&)
   {
     panic_impossible ();
@@ -3426,6 +3395,45 @@
       }
   }
 
+  void
+  tree_evaluator::visit_superclass_ref (tree_superclass_ref& expr)
+  {
+    std::string meth_or_obj = expr.method_or_object_name ();
+    std::string cls = expr.class_name ();
+
+    octave_value tmp = octave_classdef::superclass_ref (meth_or_obj, cls);
+
+    if (! expr.is_postfix_indexed ())
+      {
+        // There was no index, so this superclass_ref object is not
+        // part of an index expression.  It is also not an identifier in
+        // the syntax tree but we need to handle it as if it were.  So
+        // call the function here.
+
+        octave_function *f = tmp.function_value (true);
+
+        assert (f);
+
+        int nargout = m_nargout_stack.top ();
+
+        push_result (f->call (*this, nargout));
+        return;
+      }
+
+    // The superclass_ref function object will be indexed as part of the
+    // enclosing index expression.
+
+    push_result (tmp);
+  }
+
+  void
+  tree_evaluator::visit_metaclass_query (tree_metaclass_query& expr)
+  {
+    std::string cls = expr.class_name ();
+
+    push_result (octave_classdef::metaclass_query (cls));
+  }
+
   void tree_evaluator::bind_ans (const octave_value& val, bool print)
   {
     static std::string ans = "ans";
--- a/libinterp/parse-tree/pt-eval.h	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/pt-eval.h	Thu Feb 07 00:03:55 2019 +0000
@@ -231,8 +231,6 @@
 
     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&);
@@ -264,6 +262,9 @@
     void visit_while_command (tree_while_command&);
     void visit_do_until_command (tree_do_until_command&);
 
+    void visit_superclass_ref (tree_superclass_ref&);
+    void visit_metaclass_query (tree_metaclass_query&);
+
     void bind_ans (const octave_value& val, bool print);
 
     bool statement_printing_enabled (void);
--- a/libinterp/parse-tree/pt-funcall.cc	Wed Feb 06 15:02:37 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
-
-Copyright (C) 2012-2019 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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#include "ov-fcn.h"
-#include "pt-funcall.h"
-#include "pt-walk.h"
-
-namespace octave
-{
-  // 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 = m_fcn.function_value ();
-        std::string nm = (fp ? fp->name () : "<invalid-function>");
-
-        os << nm << " (";
-
-        octave_idx_type n = m_args.length ();
-        for (octave_idx_type i = 0; i < n; i++)
-          {
-            m_args(i).print_raw (os, pr_as_read_syntax);
-
-            if (i < n - 1)
-              os << ", ";
-          }
-
-        os << ')';
-      }
-  }
-
-  tree_funcall *
-  tree_funcall::dup (symbol_scope&) const
-  {
-    tree_funcall *new_fc
-      = new tree_funcall (m_fcn, m_args, line (), column ());
-
-    new_fc->copy_base (*this);
-
-    return new_fc;
-  }
-}
--- a/libinterp/parse-tree/pt-funcall.h	Wed Feb 06 15:02:37 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
-
-Copyright (C) 2012-2019 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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if ! defined (octave_tree_funcall_h)
-#define octave_tree_funcall_h 1
-
-#include "octave-config.h"
-
-#include "ov.h"
-#include "ovl.h"
-#include "parse.h"
-#include "pt-exp.h"
-#include "pt-walk.h"
-
-namespace octave
-{
-  // 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), m_fcn (f), m_args (a)
-    {
-      if (! m_fcn.is_function ())
-        error ("tree_funcall: invalid function");
-    }
-
-    // No copying!
-
-    tree_funcall (const tree_funcall&) = delete;
-
-    tree_funcall& operator = (const tree_funcall&) = delete;
-
-    ~tree_funcall (void) = default;
-
-    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_scope& scope) const;
-
-    octave_value function (void) const { return m_fcn; }
-
-    octave_value_list arguments (void) const { return m_args; }
-
-    void accept (tree_walker& tw)
-    {
-      tw.visit_funcall (*this);
-    }
-
-  private:
-
-    // Function to call.  Error if not a valid function at time of
-    // construction.
-    octave_value m_fcn;
-
-    // Argument list.
-    octave_value_list m_args;
-  };
-}
-
-#endif
--- a/libinterp/parse-tree/pt-jit.cc	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/pt-jit.cc	Thu Feb 07 00:03:55 2019 +0000
@@ -741,12 +741,6 @@
   }
 
   void
-  jit_convert::visit_funcall (tree_funcall&)
-  {
-    throw jit_fail_exception ();
-  }
-
-  void
   jit_convert::visit_parameter_list (tree_parameter_list&)
   {
     throw jit_fail_exception ("No visit_parameter_list implementation");
--- a/libinterp/parse-tree/pt-jit.h	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/pt-jit.h	Thu Feb 07 00:03:55 2019 +0000
@@ -133,8 +133,6 @@
 
     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-pr-code.cc	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/pt-pr-code.cc	Thu Feb 07 00:03:55 2019 +0000
@@ -732,18 +732,6 @@
   }
 
   void
-  tree_print_code::visit_funcall (tree_funcall& fc)
-  {
-    indent ();
-
-    print_parens (fc, "(");
-
-    fc.print_raw (m_os, true, m_print_original_text);
-
-    print_parens (fc, ")");
-  }
-
-  void
   tree_print_code::visit_parameter_list (tree_parameter_list& lst)
   {
     auto p = lst.begin ();
@@ -1145,6 +1133,18 @@
   }
 
   void
+  tree_print_code::visit_superclass_ref (tree_superclass_ref& scr)
+  {
+    m_os << scr.method_or_object_name () << "@" << scr.class_name ();
+  }
+
+  void
+  tree_print_code::visit_metaclass_query (tree_metaclass_query& mcq)
+  {
+    m_os << "?" << mcq.class_name ();
+  }
+
+  void
   tree_print_code::print_fcn_handle_body (tree_expression *e)
   {
     if (e)
--- a/libinterp/parse-tree/pt-pr-code.h	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/pt-pr-code.h	Thu Feb 07 00:03:55 2019 +0000
@@ -117,8 +117,6 @@
 
     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&);
@@ -149,6 +147,10 @@
 
     void visit_do_until_command (tree_do_until_command&);
 
+    void visit_superclass_ref (tree_superclass_ref&);
+
+    void visit_metaclass_query (tree_metaclass_query&);
+
     void print_fcn_handle_body (tree_expression *);
 
   private:
--- a/libinterp/parse-tree/pt-walk.h	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/pt-walk.h	Thu Feb 07 00:03:55 2019 +0000
@@ -65,7 +65,6 @@
   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;
@@ -79,6 +78,8 @@
   class tree_while_command;
   class tree_do_until_command;
 
+  class tree_superclass_ref;
+  class tree_metaclass_query;
   class tree_classdef_attribute;
   class tree_classdef_attribute_list;
   class tree_classdef_superclass;
@@ -204,9 +205,6 @@
     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
@@ -243,6 +241,12 @@
     visit_do_until_command (tree_do_until_command&) = 0;
 
     virtual void
+    visit_superclass_ref (tree_superclass_ref&) { } /* = 0; */
+
+    virtual void
+    visit_metaclass_query (tree_metaclass_query&) { } /* = 0; */
+
+    virtual void
     visit_classdef_attribute (tree_classdef_attribute&) { } /* = 0; */
 
     virtual void
--- a/libinterp/parse-tree/token.cc	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/token.cc	Thu Feb 07 00:03:55 2019 +0000
@@ -73,11 +73,11 @@
       m_orig_text ()
   { }
 
-  token::token (int tv, const std::string& method_nm,
-                const std::string& class_nm, int l, int c)
+  token::token (int tv, const std::string& meth_or_obj,
+                const std::string& cls, int l, int c)
     : m_maybe_cmd (false), m_tspc (false), m_line_num (l), m_column_num (c),
       m_tok_val (tv), m_type_tag (scls_name_token),
-      m_tok_info (method_nm, class_nm), m_orig_text ()
+      m_tok_info (meth_or_obj, cls), m_orig_text ()
   { }
 
   token::~token (void)
@@ -132,17 +132,17 @@
   }
 
   std::string
-  token::superclass_method_name (void) const
+  token::superclass_method_or_object_name (void) const
   {
     assert (m_type_tag == scls_name_token);
-    return m_tok_info.m_superclass_info->m_method_nm;
+    return m_tok_info.m_superclass_info->m_method_or_object_name;
   }
 
   std::string
   token::superclass_class_name (void) const
   {
     assert (m_type_tag == scls_name_token);
-    return m_tok_info.m_superclass_info->m_class_nm;
+    return m_tok_info.m_superclass_info->m_class_name;
   }
 
   std::string
--- a/libinterp/parse-tree/token.h	Wed Feb 06 15:02:37 2019 -0800
+++ b/libinterp/parse-tree/token.h	Thu Feb 07 00:03:55 2019 +0000
@@ -120,7 +120,7 @@
     end_tok_type ettype (void) const;
     symbol_record sym_rec (void) const;
 
-    std::string superclass_method_name (void) const;
+    std::string superclass_method_or_object_name (void) const;
     std::string superclass_class_name (void) const;
 
     std::string text_rep (void) const;
@@ -155,8 +155,8 @@
         : m_sr (new symbol_record (sr))
       { }
 
-      tok_info (const std::string& method_nm, const std::string& class_nm)
-        : m_superclass_info (new superclass_info (method_nm, class_nm))
+      tok_info (const std::string& meth_or_obj, const std::string& cls)
+        : m_superclass_info (new superclass_info (meth_or_obj, cls))
       { }
 
       tok_info (const tok_info&) = delete;
@@ -177,9 +177,9 @@
       {
         superclass_info (void) = delete;
 
-        superclass_info (const std::string& method_nm,
-                         const std::string& class_nm)
-          : m_method_nm (method_nm), m_class_nm (class_nm)
+        superclass_info (const std::string& meth_or_obj,
+                         const std::string& cls)
+          : m_method_or_object_name (meth_or_obj), m_class_name (cls)
         { }
 
         superclass_info (const superclass_info&) = delete;
@@ -188,8 +188,8 @@
 
         ~superclass_info (void) = default;
 
-        std::string m_method_nm;
-        std::string m_class_nm;
+        std::string m_method_or_object_name;
+        std::string m_class_name;
       };
 
       superclass_info *m_superclass_info;