changeset 22893:5ff6716cf157

allow dispatch types to be declared for built-in functions * mk-builtins.pl, gendoc.pl: Handle "classes: NAME ..." info in DEFUN macros. * defun-int.h, defun.cc (install_builtin_dispatch): New function. symtab.h (symbol_tableinstall_built_in_dispatch, symbol_table::fcn_info::install_built_in_dispatch, symbol_table::fcn_info::fcn_info_rep::install_built_in_dispatch): New functions. * svd.cc (Fsvd): Add "classes: double single" tag prior to doc: comment.
author John W. Eaton <jwe@octave.org>
date Wed, 14 Dec 2016 14:59:27 -0500
parents 5521b8a271ae
children 0ab9eecbb165
files build-aux/mk-builtins.pl libinterp/corefcn/defun-int.h libinterp/corefcn/defun.cc libinterp/corefcn/svd.cc libinterp/corefcn/symtab.h libinterp/gendoc.pl
diffstat 6 files changed, 102 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/build-aux/mk-builtins.pl	Wed Dec 14 13:27:08 2016 -0500
+++ b/build-aux/mk-builtins.pl	Wed Dec 14 14:59:27 2016 -0500
@@ -178,28 +178,30 @@
     $name = "";
     $alias = "";
 
-    while (<$fh>)
+    %dispatch_map = ();
+
+    while ($line = <$fh>)
     {
-      if (/^ *DEFUN *\( *([^ ,]*) *,.*$/)
+      if ($line =~ /^ *DEFUN *\( *([^ ,]*) *,.*$/)
       {
         $type = "fun";
         $fname = "F$1";
         $name = "$1";
       }
-      elsif (/^ *DEFUNX *\( *"([^"]*)" *, *([^ ,]*) *,.*$/)
+      elsif ($line =~ /^ *DEFUNX *\( *"([^"]*)" *, *([^ ,]*) *,.*$/)
       {
         $type = "fun";
         $fname = "$2";
         $name = "$1";
       }
-      elsif (/^ *DEFCONSTFUN *\( *([^ ,]*) *,.*$/)
+      elsif ($line =~ /^ *DEFCONSTFUN *\( *([^ ,]*) *,.*$/)
       {
         $type = "fun";
         $fname = "F$1";
         $name = "$1";
         $const = 1;
       }
-      elsif (/^ *DEFALIAS *\( *([^ ,]*) *, *([^ )]*) *\).*$/)
+      elsif ($line =~ /^ *DEFALIAS *\( *([^ ,]*) *, *([^ )]*) *\).*$/)
       {
         $type = "alias";
         $alias = "$1";
@@ -207,13 +209,13 @@
       }
       elsif ($defun_dld_are_built_in)
       {
-        if (/^ *DEFUN_DLD *\( *([^ ,]*) *,.*$/)
+        if ($line =~ /^ *DEFUN_DLD *\( *([^ ,]*) *,.*$/)
         {
           $type = "fun";
           $fname = "F$1";
           $name = "$1";
         }
-        elsif (/^ *DEFUNX_DLD *\( *"([^"]*)" *, *([^ ,]*) *,.*$/)
+        elsif ($line =~ /^ *DEFUNX_DLD *\( *"([^"]*)" *, *([^ ,]*) *,.*$/)
         {
           $type = "fun";
           $fname = "$2";
@@ -223,6 +225,15 @@
 
       if ($type eq "fun")
       {
+        if (($line = <$fh>) =~ /^ *classes:/)
+        {
+          $line =~ s/\s*classes:\s*//;
+          $line =~ s/\s*$//;
+          @classes = split (/\s+/, $line);
+
+          $dispatch_map{$name} = [@classes];
+        }
+
         ## We use the name appended to the "external-doc" tag to find
         ## the docstring for aliases to this function.
 
@@ -244,11 +255,34 @@
       {
         print "  alias_builtin (\"$alias\", \"$name\");\n";
 
+        ## Preserve dispatch info (if any) that we have for the
+        ## original function.
+
+        @classes = @{$dispatch_map{$name}};
+
+        if (@classes)
+        {
+          $dispatch_map{$alias} = [@classes];
+        }
+
         $type = "";
         $name = "";
         $alias = "";
       }
     }
+
+    foreach $fcn (keys %dispatch_map)
+    {
+      print "\n";
+
+      @classes =  @{$dispatch_map{$fcn}};
+
+      foreach $class (@classes)
+      {
+        print "  install_builtin_dispatch (\"$fcn\", \"$class\");\n";
+      }
+    }
+
     print "}\n";
   }
 
--- a/libinterp/corefcn/defun-int.h	Wed Dec 14 13:27:08 2016 -0500
+++ b/libinterp/corefcn/defun-int.h	Wed Dec 14 14:59:27 2016 -0500
@@ -57,6 +57,9 @@
 extern OCTINTERP_API void
 alias_builtin (const std::string& alias, const std::string& name);
 
+extern OCTINTERP_API void
+install_builtin_dispatch (const std::string& name, const std::string& klass);
+
 // Gets the shlib of the currently executing DLD function, if any.
 extern OCTINTERP_API octave::dynamic_library
 get_current_shlib (void);
--- a/libinterp/corefcn/defun.cc	Wed Dec 14 13:27:08 2016 -0500
+++ b/libinterp/corefcn/defun.cc	Wed Dec 14 14:59:27 2016 -0500
@@ -124,6 +124,12 @@
   symbol_table::alias_built_in_function (alias, name);
 }
 
+void
+install_builtin_dispatch (const std::string& name, const std::string& klass)
+{
+  symbol_table::install_built_in_dispatch (name, klass);
+}
+
 octave::dynamic_library
 get_current_shlib (void)
 {
--- a/libinterp/corefcn/svd.cc	Wed Dec 14 13:27:08 2016 -0500
+++ b/libinterp/corefcn/svd.cc	Wed Dec 14 14:59:27 2016 -0500
@@ -66,6 +66,7 @@
 }
 
 DEFUN (svd, args, nargout,
+       classes: double single
        doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{s} =} svd (@var{A})
 @deftypefnx {} {[@var{U}, @var{S}, @var{V}] =} svd (@var{A})
--- a/libinterp/corefcn/symtab.h	Wed Dec 14 13:27:08 2016 -0500
+++ b/libinterp/corefcn/symtab.h	Wed Dec 14 14:59:27 2016 -0500
@@ -853,6 +853,21 @@
         built_in_function = f;
       }
 
+      void install_built_in_dispatch (const std::string& klass)
+      {
+        if (built_in_function.is_defined ())
+          {
+            if (class_methods.find (klass) != class_methods.end ())
+              warning ("install_built_in_dispatch: '%s' already defined for class '%s'",
+                       name.c_str (), klass.c_str ());
+            else
+              class_methods[klass] = built_in_function;
+          }
+        else
+          error ("install_built_in_dispatch: '%s' is not a built-in function",
+                 name.c_str ());
+      }
+
       template <typename T>
       void
       clear_map (std::map<T, octave_value>& map, bool force = false)
@@ -1080,6 +1095,11 @@
       rep->install_built_in_function (f);
     }
 
+    void install_built_in_dispatch (const std::string& klass)
+    {
+      rep->install_built_in_dispatch (klass);
+    }
+
     void clear (bool force = false) { rep->clear (force); }
 
     void clear_user_function (bool force = false)
@@ -1789,6 +1809,21 @@
       panic ("alias: '%s' is undefined", name.c_str ());
   }
 
+  static void install_built_in_dispatch (const std::string& name,
+                                         const std::string& klass)
+  {
+    fcn_table_iterator p = fcn_table.find (name);
+
+    if (p != fcn_table.end ())
+      {
+        fcn_info& finfo = p->second;
+
+        finfo.install_built_in_dispatch (klass);
+      }
+    else
+      error ("install_built_in_dispatch: '%s' is undefined", name.c_str ());
+  }
+  
   static void push_context (scope_id scope = xcurrent_scope)
   {
     if (scope == xglobal_scope || scope == xtop_scope)
--- a/libinterp/gendoc.pl	Wed Dec 14 13:27:08 2016 -0500
+++ b/libinterp/gendoc.pl	Wed Dec 14 14:59:27 2016 -0500
@@ -46,15 +46,23 @@
   @func_list = ();
   @docstr = ();
 
-  LINE: while (<SRC_FH>)
+  LINE: while (my $line = <SRC_FH>)
   {
-    if (/^\s*DEF(?:CONSTFUN|UN|UN_DLD|UNX|UNX_DLD)\s*\(/)
+    if ($line =~ /^\s*DEF(?:CONSTFUN|UN|UN_DLD|UNX|UNX_DLD)\s*\(/)
     {
-      ($func) = /\("?(\w+)"?,/;
+      ($func) = $line =~ /\("?(\w+)"?,/;
       unless ($func) { die "Unable to parse $src_fname at line $.\n" }
       push (@func_list, $func);
 
-      if (<SRC_FH> =~ m#\s*doc:\s+\Q/*\E\s+\Q-*- texinfo -*-\E\s*$#)
+      ## Skip optional line that declares list of classes that this
+      ## function accepts.
+      $line = <SRC_FH>;
+      if ($line =~ m#\s*classes:#)
+      {
+        $line = <SRC_FH>;
+      }
+
+      if ($line =~ m#\s*doc:\s+\Q/*\E\s+\Q-*- texinfo -*-\E\s*$#)
       {
         $str = "-*- texinfo -*-\n";
         $reading_docstring = 1;
@@ -67,15 +75,15 @@
     }
     elsif ($reading_docstring)
     {
-      if (/^.*\s+\*\/\s*\)\s*$/)
+      if ($line =~ /^.*\s+\*\/\s*\)\s*$/)
       {
-        s#\s+\*/\s*\)\s*$##;
-        push (@docstr, $str . $_);
+        $line =~ s#\s+\*/\s*\)\s*$##;
+        push (@docstr, $str . $line);
         $reading_docstring = 0;
       }
       else
       {
-        $str .= $_;
+        $str .= $line;
       }
     }
   }