changeset 23518:8744d4ed8fb4

provide DEFMETHOD macros Allow a reference to the interpreter object to be passed to built-in interpreter functions. * find-defun-files.sh: Adjust regexp pattern for finding built-in functions. * mk-builtins.pl: Handle DEFMETHOD variants of built-in function macros. * defun-int.h, defun.cc (install_builtin_function): New overloads for methods. * defun-int.h (FORWARD_DECLARE_METHODX, FORWARD_DECLARE_METHOD, DECLARE_METHODX, DECLARE_METHOD, DECLARE_STATIC_METHODX, DECLARE_STATIC_METHOD): New macros. * defun.h (DEFMETHOD, DEFMETHODX, DEFCONSTMETHOD): New macros. * libinterp/gendoc.pl: Likewise. * ov-builtin.h, ov-builtin.cc (octave_builtin::meth): New typedef. (octave_builtin::m): New data member. (octave_builtin::method): New function. (octave_builtin::octave_builtin, octave_builtin::call): Handle methods. * ov-dld-fcn.h, ov-dld-fcn.cc (octave_dld_function::create, octave_dld_function::octave_dld_function): Handle methods.
author John W. Eaton <jwe@octave.org>
date Fri, 19 May 2017 16:01:18 -0400
parents 1bc8f1f50b54
children 4fe410bd918d
files build-aux/find-defun-files.sh build-aux/mk-builtins.pl libinterp/corefcn/defun-int.h libinterp/corefcn/defun.cc libinterp/corefcn/defun.h libinterp/gendoc.pl libinterp/octave-value/ov-builtin.cc libinterp/octave-value/ov-builtin.h libinterp/octave-value/ov-dld-fcn.cc libinterp/octave-value/ov-dld-fcn.h
diffstat 10 files changed, 188 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/build-aux/find-defun-files.sh	Fri May 19 15:53:32 2017 -0400
+++ b/build-aux/find-defun-files.sh	Fri May 19 16:01:18 2017 -0400
@@ -27,7 +27,7 @@
 # so we have to repeat ourselves because some stupid egreps don't like
 # empty elements in alternation patterns.
 
-DEFUN_PATTERN="^[ \t]*DEF(CONSTFUN|UN|UN_DLD|UNX|UNX_DLD)[ \t]*\\("
+DEFUN_PATTERN="^[ \t]*DEF(CONSTFUN|METHOD|METHOD_DLD|METHODX|METHODX_DLD|UN|UN_DLD|UNX|UNX_DLD)[ \t]*\\("
 
 srcdir="$1"
 if [ "$1" ]; then
--- a/build-aux/mk-builtins.pl	Fri May 19 15:53:32 2017 -0400
+++ b/build-aux/mk-builtins.pl	Fri May 19 16:01:18 2017 -0400
@@ -71,6 +71,11 @@
 
 #include \"ovl.h\"
 
+namespace octave
+{
+  class interpreter;
+}
+
 ";
 
   while ($file = shift (@ARGV))
@@ -88,33 +93,47 @@
 
     while (<$fh>)
     {
-      if (/^[ \t]*DEF(CONSTFUN|UN)[ \t]*\( *([^ ,]*).*$/)
+      if (/^[ \t]*DEF(CONSTFUN|CONSTMETHOD|METHOD|UN)[ \t]*\( *([^ ,]*).*$/)
       {
         $name = "F$2";
+        $is_method = ($1 eq "METHOD" || $1 eq "CONSTMETHOD");
       }
-      elsif (/^[ \t]*DEFUNX[ \t]*\( *"[^"]*" *, *([^ ,]*).*$/)
+      elsif (/^[ \t]*DEF(METHOD|UN)X[ \t]*\( *"[^"]*" *, *([^ ,]*).*$/)
       {
-        $name = $1;
+        $name = $2;
+        $is_method = ($1 eq "METHOD");
       }
       elsif ($defun_dld_are_built_in)
       {
-        if (/^[ \t]*DEFUN_DLD[ \t]*\( *([^ ,]*).*$/)
+        if (/^[ \t]*DEF(METHOD|UN)_DLD[ \t]*\( *([^ ,]*).*$/)
         {
-          $name = "F$1";
+          $name = "F$2";
+          $is_method = ($1 eq "METHOD");
         }
-        elsif (/^[ \t]*DEFUNX_DLD[ \t]*\( *"[^"]*" *, *([^ ,]*).*$/)
+        elsif (/^[ \t]*DEF(METHOD|UN)X_DLD[ \t]*\( *"[^"]*" *, *([^ ,]*).*$/)
         {
-          $name = "$1";
+          $name = "$2";
+          $is_method = ($1 eq "METHOD");
         }
       }
 
       if ($name)
       {
-        print "extern OCTINTERP_API octave_value_list
+        if ($is_method)
+        {
+          print "extern OCTINTERP_API octave_value_list
+$name (octave::interpreter&, const octave_value_list& = octave_value_list (), int = 0);
+";
+        }
+        else
+        {
+          print "extern OCTINTERP_API octave_value_list
 $name (const octave_value_list& = octave_value_list (), int = 0);
+";
+        }
 
-";
         $name = "";
+        $is_method = 0;
       }
     }
   }
@@ -182,23 +201,23 @@
 
     while ($line = <$fh>)
     {
-      if ($line =~ /^ *DEFUN *\( *([^ ,]*) *,.*$/)
+      if ($line =~ /^ *DEF(METHOD|UN) *\( *([^ ,]*) *,.*$/)
       {
         $type = "fun";
-        $fname = "F$1";
-        $name = "$1";
+        $fname = "F$2";
+        $name = "$2";
       }
-      elsif ($line =~ /^ *DEFUNX *\( *"([^"]*)" *, *([^ ,]*) *,.*$/)
+      elsif ($line =~ /^ *DEF(METHOD|UN)X *\( *"([^"]*)" *, *([^ ,]*) *,.*$/)
       {
         $type = "fun";
-        $fname = "$2";
-        $name = "$1";
+        $fname = "$3";
+        $name = "$2";
       }
-      elsif ($line =~ /^ *DEFCONSTFUN *\( *([^ ,]*) *,.*$/)
+      elsif ($line =~ /^ *DEFCONST(FUN|METHOD) *\( *([^ ,]*) *,.*$/)
       {
         $type = "fun";
-        $fname = "F$1";
-        $name = "$1";
+        $fname = "F$2";
+        $name = "$2";
         $const = 1;
       }
       elsif ($line =~ /^ *DEFALIAS *\( *([^ ,]*) *, *([^ )]*) *\).*$/)
@@ -209,17 +228,17 @@
       }
       elsif ($defun_dld_are_built_in)
       {
-        if ($line =~ /^ *DEFUN_DLD *\( *([^ ,]*) *,.*$/)
+        if ($line =~ /^ *DEF(METHOD|UN)_DLD *\( *([^ ,]*) *,.*$/)
         {
           $type = "fun";
-          $fname = "F$1";
-          $name = "$1";
+          $fname = "F$2";
+          $name = "$2";
         }
-        elsif ($line =~ /^ *DEFUNX_DLD *\( *"([^"]*)" *, *([^ ,]*) *,.*$/)
+        elsif ($line =~ /^ *DEF(METHOD|UN)X_DLD *\( *"([^"]*)" *, *([^ ,]*) *,.*$/)
         {
           $type = "fun";
-          $fname = "$2";
-          $name = "$1";
+          $fname = "$3";
+          $name = "$2";
         }
       }
 
--- a/libinterp/corefcn/defun-int.h	Fri May 19 15:53:32 2017 -0400
+++ b/libinterp/corefcn/defun-int.h	Fri May 19 16:01:18 2017 -0400
@@ -32,6 +32,11 @@
 #include "symtab.h"
 #include "version.h"
 
+namespace octave
+{
+  class interpreter;
+}
+
 class octave_value;
 
 extern OCTINTERP_API void print_usage (void);
@@ -46,11 +51,21 @@
                           bool can_hide_function = true);
 
 extern OCTINTERP_API void
+install_builtin_function (octave_builtin::meth m, const std::string& name,
+                          const std::string& file, const std::string& doc,
+                          bool can_hide_function = true);
+
+extern OCTINTERP_API void
 install_dld_function (octave_dld_function::fcn f, const std::string& name,
                       const octave::dynamic_library& shl, const std::string& doc,
                       bool relative = false);
 
 extern OCTINTERP_API void
+install_dld_function (octave_dld_function::meth m, const std::string& name,
+                      const octave::dynamic_library& shl, const std::string& doc,
+                      bool relative = false);
+
+extern OCTINTERP_API void
 install_mex_function (void *fptr, bool fmex, const std::string& name,
                       const octave::dynamic_library& shl, bool relative = false);
 
@@ -101,22 +116,45 @@
   extern OCTAVE_EXPORT octave_value_list        \
   name (const octave_value_list&, int)
 
+#define FORWARD_DECLARE_METHODX(name)                           \
+  extern OCTAVE_EXPORT octave_value_list                        \
+  name (octave::interpreter&, const octave_value_list&, int)
+
 #define FORWARD_DECLARE_FUN(name)               \
   FORWARD_DECLARE_FUNX (F ## name)
 
+#define FORWARD_DECLARE_METHOD(name)            \
+  FORWARD_DECLARE_METHODX (F ## name)
+
 #define DECLARE_FUNX(name, args_name, nargout_name)             \
   OCTAVE_EXPORT octave_value_list                               \
   name (const octave_value_list& args_name, int nargout_name)
 
+#define DECLARE_METHODX(name, interp_name, args_name, nargout_name)     \
+  OCTAVE_EXPORT octave_value_list                                       \
+  name (octave::interpreter& interp_name,                               \
+        const octave_value_list& args_name, int nargout_name)
+
 #define DECLARE_FUN(name, args_name, nargout_name)      \
   DECLARE_FUNX (F ## name, args_name, nargout_name)
 
+#define DECLARE_METHOD(name, interp_name, args_name, nargout_name)      \
+  DECLARE_METHODX (F ## name, interp_name, args_name, nargout_name)
+
 #define DECLARE_STATIC_FUNX(name, args_name, nargout_name)      \
   static octave_value_list                                      \
   name (const octave_value_list& args_name, int nargout_name)
 
+#define DECLARE_STATIC_METHODX(name, interp_name, args_name, nargout_name) \
+  static octave_value_list                                              \
+  name (octave::interpreter& interp_name,                               \
+        const octave_value_list& args_name, int nargout_name)
+
 #define DECLARE_STATIC_FUN(name, args_name, nargout_name)       \
-  DECLARE_FUNX (F ## name, args_name, nargout_name)
+  DECLARE_STATIC_FUNX (F ## name, args_name, nargout_name)
+
+#define DECLARE_STATIC_METHOD(name, interp_name, args_name, nargout_name) \
+  DECLARE_STATIC_METHODX (F ## name, interp_name, args_name, nargout_name)
 
 // Define the code that will be used to insert the new function into
 // the symbol table.  We look for this name instead of the actual
--- a/libinterp/corefcn/defun.cc	Fri May 19 15:53:32 2017 -0400
+++ b/libinterp/corefcn/defun.cc	Fri May 19 16:01:18 2017 -0400
@@ -92,6 +92,16 @@
 }
 
 void
+install_builtin_function (octave_builtin::meth m, const std::string& name,
+                          const std::string& file, const std::string& doc,
+                          bool /* can_hide_function -- not yet implemented */)
+{
+  octave_value fcn (new octave_builtin (m, name, file, doc));
+
+  symbol_table::install_built_in_function (name, fcn);
+}
+
+void
 install_dld_function (octave_dld_function::fcn f, const std::string& name,
                       const octave::dynamic_library& shl, const std::string& doc,
                       bool relative)
@@ -107,6 +117,21 @@
 }
 
 void
+install_dld_function (octave_dld_function::meth m, const std::string& name,
+                      const octave::dynamic_library& shl, const std::string& doc,
+                      bool relative)
+{
+  octave_dld_function *fcn = new octave_dld_function (m, shl, name, doc);
+
+  if (relative)
+    fcn->mark_relative ();
+
+  octave_value fval (fcn);
+
+  symbol_table::install_built_in_function (name, fval);
+}
+
+void
 install_mex_function (void *fptr, bool fmex, const std::string& name,
                       const octave::dynamic_library& shl, bool relative)
 {
--- a/libinterp/corefcn/defun.h	Fri May 19 15:53:32 2017 -0400
+++ b/libinterp/corefcn/defun.h	Fri May 19 16:01:18 2017 -0400
@@ -46,6 +46,9 @@
 #define DEFUN(name, args_name, nargout_name, doc)       \
   DECLARE_FUN (name, args_name, nargout_name)
 
+#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)      \
+  DECLARE_METHOD (name, interp_name, args_name, nargout_name)
+
 // This one can be used when 'name' cannot be used directly (if it is
 // already defined as a macro).  In that case, name is already a
 // quoted string, and the internal name of the function must be passed
@@ -54,10 +57,16 @@
 #define DEFUNX(name, fname, args_name, nargout_name, doc)       \
   DECLARE_FUNX (fname, args_name, nargout_name)
 
+#define DEFMETHODX(name, fname, interp_name, args_name, nargout_name, doc) \
+  DECLARE_METHODX (fname, interp_name, args_name, nargout_name)
+
 // This is a function with a name that can't be hidden by a variable.
 #define DEFCONSTFUN(name, args_name, nargout_name, doc) \
   DECLARE_FUN (name, args_name, nargout_name)
 
+#define DEFCONSTMETHOD(name, interp_name, args_name, nargout_name, doc) \
+  DECLARE_METHOD (name, interp_name, args_name, nargout_name)
+
 // Make alias another name for the existing function name.  This macro
 // is processed by the mkbuiltins to generate code in builtins.cc to
 // create the alias in the symbol table.
--- a/libinterp/gendoc.pl	Fri May 19 15:53:32 2017 -0400
+++ b/libinterp/gendoc.pl	Fri May 19 16:01:18 2017 -0400
@@ -48,7 +48,7 @@
 
   LINE: while (my $line = <SRC_FH>)
   {
-    if ($line =~ /^\s*DEF(?:CONSTFUN|UN|UN_DLD|UNX|UNX_DLD)\s*\(/)
+    if ($line =~ /^\s*DEF(?:CONSTFUN|CONSTMETHOD|METHOD|METHOD_DLD|METHODX|METHODX_DLD|UN|UN_DLD|UNX|UNX_DLD)\s*\(/)
     {
       ($func) = $line =~ /\("?(\w+)"?,/;
       unless ($func) { die "Unable to parse $src_fname at line $.\n" }
--- a/libinterp/octave-value/ov-builtin.cc	Fri May 19 15:53:32 2017 -0400
+++ b/libinterp/octave-value/ov-builtin.cc	Fri May 19 16:01:18 2017 -0400
@@ -27,11 +27,12 @@
 #include "call-stack.h"
 #include "error.h"
 #include "errwarn.h"
-#include "ovl.h"
+#include "interpreter-private.h"
+#include "interpreter.h"
 #include "ov-builtin.h"
 #include "ov.h"
+#include "ovl.h"
 #include "profiler.h"
-#include "interpreter.h"
 #include "unwind-prot.h"
 
 
@@ -100,7 +101,15 @@
 
   profile_data_accumulator::enter<octave_builtin> block (profiler, *this);
 
-  retval = (*f) (args, nargout);
+  if (f)
+    retval = (*f) (args, nargout);
+  else
+    {
+      octave::interpreter& interp
+        = octave::__get_interpreter__ ("octave_builtin::call");
+
+      retval = (*m) (interp, args, nargout);
+    }
 
   // Do not allow null values to be returned from functions.
   // FIXME: perhaps true builtins should be allowed?
@@ -142,6 +151,12 @@
   return f;
 }
 
+octave_builtin::meth
+octave_builtin::method (void) const
+{
+  return m;
+}
+
 void
 octave_builtin::push_dispatch_class (const std::string& dispatch_type)
 {
--- a/libinterp/octave-value/ov-builtin.h	Fri May 19 15:53:32 2017 -0400
+++ b/libinterp/octave-value/ov-builtin.h	Fri May 19 16:01:18 2017 -0400
@@ -36,6 +36,11 @@
 class octave_value_list;
 class jit_type;
 
+namespace octave
+{
+  class interpreter;
+}
+
 // Builtin functions.
 
 class
@@ -46,15 +51,26 @@
 
   octave_builtin (void) : octave_function (), f (0), file (), jtype (0) { }
 
+  typedef octave_value_list (*meth) (octave::interpreter&,
+                                     const octave_value_list&, int);
+
   typedef octave_value_list (*fcn) (const octave_value_list&, int);
 
   octave_builtin (fcn ff, const std::string& nm = "",
                   const std::string& ds = "")
-    : octave_function (nm, ds), f (ff), file (), jtype (0) { }
+    : octave_function (nm, ds), f (ff), m (0), file (), jtype (0) { }
+
+  octave_builtin (meth mm, const std::string& nm = "",
+                  const std::string& ds = "")
+    : octave_function (nm, ds), f (0), m (mm), file (), jtype (0) { }
 
   octave_builtin (fcn ff, const std::string& nm, const std::string& fnm,
                   const std::string& ds)
-    : octave_function (nm, ds), f (ff), file (fnm), jtype (0) { }
+    : octave_function (nm, ds), f (ff), m (0), file (fnm), jtype (0) { }
+
+  octave_builtin (meth mm, const std::string& nm, const std::string& fnm,
+                  const std::string& ds)
+    : octave_function (nm, ds), f (0), m (mm), file (fnm), jtype (0) { }
 
   // No copying!
 
@@ -89,6 +105,8 @@
 
   fcn function (void) const;
 
+  meth method (void) const;
+
   void push_dispatch_class (const std::string& dispatch_type);
 
   bool handles_dispatch_class (const std::string& dispatch_type) const;
@@ -97,6 +115,7 @@
 
   // A pointer to the actual function.
   fcn f;
+  meth m;
 
   // The name of the file where this function was defined.
   std::string file;
--- a/libinterp/octave-value/ov-dld-fcn.cc	Fri May 19 15:53:32 2017 -0400
+++ b/libinterp/octave-value/ov-dld-fcn.cc	Fri May 19 16:01:18 2017 -0400
@@ -52,6 +52,20 @@
        && Voct_file_dir == file_name.substr (0, Voct_file_dir.length ()));
 }
 
+octave_dld_function::octave_dld_function
+  (octave_builtin::meth mm, const octave::dynamic_library& shl,
+   const std::string& nm, const std::string& ds)
+  : octave_builtin (mm, nm, ds), sh_lib (shl)
+{
+  mark_fcn_file_up_to_date (time_parsed ());
+
+  std::string file_name = fcn_file_name ();
+
+  system_fcn_file
+    = (! file_name.empty ()
+       && Voct_file_dir == file_name.substr (0, Voct_file_dir.length ()));
+}
+
 octave_dld_function::~octave_dld_function (void)
 {
   octave::dynamic_loader::remove_oct (my_name, sh_lib);
@@ -87,3 +101,11 @@
 {
   return new octave_dld_function (ff, shl, nm, ds);
 }
+
+octave_dld_function*
+octave_dld_function::create (octave_builtin::meth mm,
+                             const octave::dynamic_library& shl,
+                             const std::string& nm, const std::string& ds)
+{
+  return new octave_dld_function (mm, shl, nm, ds);
+}
--- a/libinterp/octave-value/ov-dld-fcn.h	Fri May 19 15:53:32 2017 -0400
+++ b/libinterp/octave-value/ov-dld-fcn.h	Fri May 19 16:01:18 2017 -0400
@@ -52,6 +52,10 @@
                        const std::string& nm = "",
                        const std::string& ds = "");
 
+  octave_dld_function (octave_builtin::meth mm, const octave::dynamic_library& shl,
+                       const std::string& nm = "",
+                       const std::string& ds = "");
+
   // No copying!
 
   octave_dld_function (const octave_dld_function& fn) = delete;
@@ -79,6 +83,11 @@
                                        const std::string& nm = "",
                                        const std::string& ds = "");
 
+  static octave_dld_function * create (octave_builtin::meth mm,
+                                       const octave::dynamic_library& shl,
+                                       const std::string& nm = "",
+                                       const std::string& ds = "");
+
   octave::dynamic_library get_shlib (void) const
   { return sh_lib; }