changeset 30304:b568c29bb5be

Add support for "class" option to exist() function (bug #46260) * variables.cc (symbol_exist): Add support for "class" input by checking symbol table for function which for which is_classdef_meta () returns true. * variables.cc (Fexist): Update documentation to describe support for "class" input type. Remove warning emitted when "class" type used. Update BIST tests.
author Rik <rik@octave.org>
date Fri, 19 Nov 2021 20:57:09 -0800
parents cd63a97cb9be
children c13204f823a6
files libinterp/corefcn/variables.cc
diffstat 1 files changed, 37 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/variables.cc	Fri Nov 19 08:04:45 2021 -0500
+++ b/libinterp/corefcn/variables.cc	Fri Nov 19 20:57:09 2021 -0800
@@ -176,8 +176,6 @@
          || search_builtin || search_class))
     error (R"(exist: unrecognized type argument "%s")", type.c_str ());
 
-  symbol_table& symtab = interp.get_symbol_table ();
-
   if (search_any || search_var)
     {
       octave_value val = interp.varval (name);
@@ -192,10 +190,12 @@
         return 0;
     }
 
+  symbol_table& symtab = interp.get_symbol_table ();
+
   // We shouldn't need to look in the global symbol table, since any name
   // that is visible in the current scope will be in the local symbol table.
 
-  if (search_any || search_file || search_dir)
+  if (search_any || search_file || search_dir || search_class)
     {
       bool have_fcn_ext = false;
 
@@ -217,15 +217,16 @@
 
       std::string file_name;
 
-      if (search_any || search_file)
+      if (search_any || search_file || search_class)
         {
           load_path& lp = interp.get_load_path ();
 
-          // Class constructor.
+          // Look for class constructor first
           file_name = lp.find_method (xname, xname);
 
           if (have_fcn_ext && ! file_name.empty ())
             {
+              // Verify extension of file_name found matches ext of name.
               pos = file_name.rfind ('.');
 
               if (pos != std::string::npos)
@@ -247,7 +248,6 @@
             }
 
           // Autoloads can only have simple names without extensions.
-
           if (! have_fcn_ext && file_name.empty ())
             {
               tree_evaluator& tw = interp.get_evaluator ();
@@ -255,26 +255,35 @@
               file_name = tw.lookup_autoload (name);
             }
 
-          // Use original name here.
-
+          // If nothing found, look for function using original name.
           if (file_name.empty ())
             file_name = lp.find_fcn (name);
         }
 
       std::size_t len = file_name.length ();
 
-      if (len > 0)
+      if (len > 0 && (search_any || search_file || search_class))
         {
           if (search_any || search_file)
             {
               if (len > 4 && (file_name.substr (len-4) == ".oct"
                               || file_name.substr (len-4) == ".mex"))
                 return 3;
+            }
+
+          if (search_class)
+            {
+              octave_value oval = symtab.find_function (name);
+              if (oval.is_defined () && oval.is_classdef_meta ())
+                return 8;
               else
-                return 2;
+                return 0;
             }
+
+          return 2;
         }
 
+      // Nothing found in symbol table, try searching in path
       file_name = file_in_path (name, "");
 
       if (file_name.empty ())
@@ -379,7 +388,7 @@
 @var{name} is a directory.
 
 @item 8
-@var{name} is a class.  (Note: not currently implemented)
+@var{name} is a classdef class.
 
 @item 103
 @var{name} is a function not associated with a file (entered on the command
@@ -406,8 +415,7 @@
 Check only for files and directories.
 
 @item @qcode{"class"}
-Check only for classes.  (Note: This option is accepted, but not currently
-implemented)
+Check only for classdef classes.
 @end table
 
 If no type is given, and there are multiple possible matches for name,
@@ -433,13 +441,11 @@
 
   // For compatibility with undocumented Matlab behavior, return 0 if
   // there is an empty built-in object as the only argument.
-
   if (args(0).builtin_type () != btyp_unknown && args(0).isempty ())
     return ovl (0);
 
   // Also for compatibility, return 0 if the second argument is an empty
   // built-in object.
-
   if (nargin == 2 && args(1).builtin_type () != btyp_unknown
       && args(1).isempty ())
     return ovl (0);
@@ -451,9 +457,6 @@
       std::string type
         = args(1).xstring_value ("exist: TYPE must be a string");
 
-      if (type == "class")
-        warning (R"(exist: "class" type argument is not implemented)");
-
       return ovl (symbol_exist (interp, name, type));
     }
   else
@@ -471,16 +474,15 @@
 %!assert (exist ("__var1", "builtin"), 0)
 %!assert (exist ("__var1", "dir"), 0)
 %!assert (exist ("__var1", "file"), 0)
+%!assert (exist ("__var1", "class"), 0)
 
-%!test
-%! if (isunix ())
-%!   assert (exist ("/bin/sh"), 2);
-%!   assert (exist ("/bin/sh", "file"), 2);
-%!   assert (exist ("/bin/sh", "dir"), 0);
-%!   assert (exist ("/dev/null"), 2);
-%!   assert (exist ("/dev/null", "file"), 2);
-%!   assert (exist ("/dev/null", "dir"), 0);
-%! endif
+%!testif ; isunix ()
+%! assert (exist ("/bin/sh"), 2);
+%! assert (exist ("/bin/sh", "file"), 2);
+%! assert (exist ("/bin/sh", "dir"), 0);
+%! assert (exist ("/dev/null"), 2);
+%! assert (exist ("/dev/null", "file"), 2);
+%! assert (exist ("/dev/null", "dir"), 0);
 
 %!assert (exist ("print_usage"), 2)
 %!assert (exist ("print_usage.m"), 2)
@@ -512,13 +514,15 @@
 %!assert (exist ("fftw", "file"), 3)
 %!assert (exist ("fftw", "builtin"), 0)
 
-%!assert (exist ("ftp"), 2);
-%!assert (exist ("ftp.m"), 2);
-%!assert (exist ("@ftp/ftp"), 2);
-%!assert (exist ("@ftp/ftp.m"), 2);
+%!assert (exist ("ftp"), 2)
+%!assert (exist ("ftp.m"), 2)
+%!assert (exist ("@ftp/ftp"), 2)
+%!assert (exist ("@ftp/ftp.m"), 2)
+%!assert (exist ("ftp", "class"), 0)
 
-%!assert (exist ("inputParser"), 2);
-%!assert (exist ("inputParser.m"), 2);
+%!assert (exist ("inputParser"), 2)
+%!assert (exist ("inputParser.m"), 2)
+%!assert (exist ("inputParser", "class"), 8)
 
 %!assert (exist ("sin"), 5)
 %!assert (exist ("sin", "builtin"), 5)
@@ -530,7 +534,6 @@
 
 %!error exist ()
 %!error exist (1,2,3)
-%!warning <"class" type argument is not implemented> exist ("a", "class");
 %!error <TYPE must be a string> exist ("a", 1)
 %!error <NAME must be a string> exist (1)
 %!error <unrecognized type argument "foobar"> exist ("a", "foobar")