Add API function to get list of option names (#6971)
authorGereon Kremer <nafur42@gmail.com>
Wed, 4 Aug 2021 18:17:42 +0000 (11:17 -0700)
committerGitHub <noreply@github.com>
Wed, 4 Aug 2021 18:17:42 +0000 (18:17 +0000)
This PR adds a new API function api::Solver::getOptionNames() that exposes a list of all option names as strings. This PR will be followed by another that adds a method to further inspect a particular option by name, and thereby allows to inspect the solver options in a sensible way.

src/api/cpp/cvc5.cpp
src/api/cpp/cvc5.h
src/options/mkoptions.py
src/options/options_public.h
src/options/options_public_template.cpp
test/unit/api/solver_black.cpp

index 05f8bd07377f73b28bb848f5e0ca4d9f05bbcfa0..aca5fa9813989a35fbe8f72ac61748fed688f437 100644 (file)
@@ -59,6 +59,7 @@
 #include "options/main_options.h"
 #include "options/option_exception.h"
 #include "options/options.h"
+#include "options/options_public.h"
 #include "options/smt_options.h"
 #include "proof/unsat_core.h"
 #include "smt/model.h"
@@ -7047,6 +7048,15 @@ std::string Solver::getOption(const std::string& option) const
   CVC5_API_TRY_CATCH_END;
 }
 
+std::vector<std::string> Solver::getOptionNames() const
+{
+  CVC5_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return options::getNames();
+  ////////
+  CVC5_API_TRY_CATCH_END;
+}
+
 std::vector<Term> Solver::getUnsatAssumptions(void) const
 {
   CVC5_API_TRY_CATCH_BEGIN;
index 3b6ba7069750d2180955dc68564fef6b036e084e..0d8a268ae91ef2a9c20bbfb569307b16ef8b2abe 100644 (file)
@@ -3718,6 +3718,13 @@ class CVC5_EXPORT Solver
    */
   std::string getOption(const std::string& option) const;
 
+  /**
+   * Get all option names that can be used with `setOption`, `getOption` and
+   * `getOptionInfo`.
+   * @return all option names
+   */
+  std::vector<std::string> getOptionNames() const;
+
   /**
    * Get the set of unsat ("failed") assumptions.
    * SMT-LIB:
index 7231106d5bac6d2fbbf1fa7a21324d8b335eb970..02087d6a0b68bd1d0a8f0410257ac4c5054b9abb 100644 (file)
@@ -741,6 +741,7 @@ def codegen_all_modules(modules, build_dir, dst_dir, tpl_options_h,
     options_getall = []      # options for options::getAll()
     options_getoptions = []  # options for Options::getOptions()
     options_handler = []     # option handler calls
+    options_names = set()    # option names
     help_common = []         # help text for all common options
     help_others = []         # help text for all non-common options
     setoption_handlers = []  # handlers for set-option command
@@ -823,15 +824,16 @@ def codegen_all_modules(modules, build_dir, dst_dir, tpl_options_h,
             # Generate handlers for setOption/getOption
             if option.long:
                 # Make long and alias names available via set/get-option
-                keys = set()
+                names = set()
                 if option.long:
-                    keys.add(long_get_option(option.long))
+                    names.add(long_get_option(option.long))
                 if option.alias:
-                    keys.update(option.alias)
-                assert keys
+                    names.update(option.alias)
+                assert names
+                options_names.update(names)
 
                 cond = ' || '.join(
-                    ['key == "{}"'.format(x) for x in sorted(keys)])
+                    ['name == "{}"'.format(x) for x in sorted(names)])
 
                 setoption_handlers.append('  if ({}) {{'.format(cond))
                 if option.type == 'bool':
@@ -839,16 +841,16 @@ def codegen_all_modules(modules, build_dir, dst_dir, tpl_options_h,
                         TPL_CALL_ASSIGN_BOOL.format(
                             module=module.id,
                             name=option.name,
-                            option='key',
+                            option='name',
                             value='optionarg == "true"'))
                 elif argument_req and option.name and not mode_handler:
                     setoption_handlers.append(
                         TPL_CALL_ASSIGN.format(
                             module=module.id,
                             name=option.name,
-                            option='key'))
+                            option='name'))
                 elif option.handler:
-                    h = '    opts.handler().{handler}("{smtname}", key'
+                    h = '    opts.handler().{handler}("{smtname}", name'
                     if argument_req:
                         h += ', optionarg'
                     h += ');'
@@ -927,6 +929,9 @@ def codegen_all_modules(modules, build_dir, dst_dir, tpl_options_h,
                             predicates='\n'.join(predicates)
                         ))
 
+    options_all_names = ', '.join(map(lambda s: '"' + s + '"', sorted(options_names)))
+    options_all_names = '\n'.join(textwrap.wrap(options_all_names, width=80, break_on_hyphens=False))
+
     data = {
         'holder_fwd_decls': get_holder_fwd_decls(modules),
         'holder_mem_decls': get_holder_mem_decls(modules),
@@ -943,6 +948,7 @@ def codegen_all_modules(modules, build_dir, dst_dir, tpl_options_h,
         'options_short': ''.join(getopt_short),
         'assigns': '\n'.join(assign_impls),
         'options_getall': '\n  '.join(options_getall),
+        'options_all_names': options_all_names,
         'getoption_handlers': '\n'.join(getoption_handlers),
         'setoption_handlers': '\n'.join(setoption_handlers),
     }
index 03d7ec41adc3ef6a6d1a10b7e6fa86214585d950..06981a837ce230130daa26f19a58a72cefa48c21 100644 (file)
@@ -74,14 +74,14 @@ std::vector<std::string> parse(Options& opts,
  * Retrieve an option value by name (as given in key) from the Options object
  * opts as a string.
  */
-std::string get(const Options& opts, const std::string& key) CVC5_EXPORT;
+std::string get(const Options& opts, const std::string& name) CVC5_EXPORT;
 
 /**
  * Update the Options object opts, set the value of the option specified by key
  * to the value parsed from optionarg.
  */
 void set(Options& opts,
-         const std::string& key,
+         const std::string& name,
          const std::string& optionarg) CVC5_EXPORT;
 
 /**
@@ -89,6 +89,11 @@ void set(Options& opts,
  */
 std::vector<std::vector<std::string> > getAll(const Options& opts) CVC5_EXPORT;
 
+/**
+ * Get a (sorted) list of all option names that are available.
+ */
+std::vector<std::string> getNames() CVC5_EXPORT;
+
 }  // namespace cvc5::options
 
 #endif
index 70c6f420ab0e4fd81353fd0204e764b10ca9f30f..220445327dba5a0d6acc1134c2ad8b2b5d70c3ab 100644 (file)
@@ -458,30 +458,30 @@ std::vector<std::string> parse(
   return nonoptions;
 }
 
-std::string get(const Options& options, const std::string& key)
+std::string get(const Options& options, const std::string& name)
 {
-  Trace("options") << "Options::getOption(" << key << ")" << std::endl;
+  Trace("options") << "Options::getOption(" << name << ")" << std::endl;
   ${getoption_handlers}$
 
-  throw UnrecognizedOptionException(key);
+  throw UnrecognizedOptionException(name);
 }
 
-void setInternal(Options& opts, const std::string& key,
+void setInternal(Options& opts, const std::string& name,
                                 const std::string& optionarg)
                                 {
-  ${setoption_handlers}$
-  throw UnrecognizedOptionException(key);
+${setoption_handlers}$
+  throw UnrecognizedOptionException(name);
 }
 
-void set(Options& opts, const std::string& key, const std::string& optionarg)
+void set(Options& opts, const std::string& name, const std::string& optionarg)
 {
 
-  Trace("options") << "setOption(" << key << ", " << optionarg << ")"
+  Trace("options") << "setOption(" << name << ", " << optionarg << ")"
                    << std::endl;
   // first update this object
-  setInternal(opts, key, optionarg);
+  setInternal(opts, name, optionarg);
   // then, notify the provided listener
-  opts.notifyListener(key);
+  opts.notifyListener(name);
 }
 
 std::vector<std::vector<std::string> > getAll(const Options& opts)
@@ -493,4 +493,11 @@ ${options_getall}$
   return res;
 }
 
+std::vector<std::string> getNames()
+{
+  return {
+${options_all_names}$
+  };
+}
+
 }  // namespace cvc5::options
index ce989c9eadba03c1eea3faaba7cb534163ceda0a..08f5596c5c11f17190721411ae2b9e6ab7b8f1c3 100644 (file)
@@ -1301,6 +1301,14 @@ TEST_F(TestApiBlackSolver, getOption)
   ASSERT_THROW(d_solver.getOption("asdf"), CVC5ApiException);
 }
 
+TEST_F(TestApiBlackSolver, getOptionNames)
+{
+  std::vector<std::string> names = d_solver.getOptionNames();
+  ASSERT_TRUE(names.size() > 100);
+  ASSERT_NE(std::find(names.begin(), names.end(), "verbose"), names.end());
+  ASSERT_EQ(std::find(names.begin(), names.end(), "foobar"), names.end());
+}
+
 TEST_F(TestApiBlackSolver, getUnsatAssumptions1)
 {
   d_solver.setOption("incremental", "false");