LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/main - command_executor.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 80 111 72.1 %
Date: 2026-08-17 10:31:59 Functions: 10 13 76.9 %
Branches: 66 96 68.8 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * An additional layer between commands and invoking them.
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "main/command_executor.h"
      14                 :            : 
      15                 :            : #ifndef __WIN32__
      16                 :            : #include <sys/resource.h>
      17                 :            : #endif /* ! __WIN32__ */
      18                 :            : 
      19                 :            : #include <cvc5/cvc5_parser.h>
      20                 :            : 
      21                 :            : #include <iomanip>
      22                 :            : #include <iostream>
      23                 :            : #include <memory>
      24                 :            : #include <string>
      25                 :            : #include <vector>
      26                 :            : 
      27                 :            : #include "base/output.h"
      28                 :            : #include "main/main.h"
      29                 :            : #include "parser/commands.h"
      30                 :            : #include "smt/solver_engine.h"
      31                 :            : 
      32                 :            : using namespace cvc5::parser;
      33                 :            : 
      34                 :            : namespace cvc5::main {
      35                 :            : 
      36                 :            : // Function to cancel any (externally-imposed) limit on CPU time.
      37                 :            : // This is used for competitions while a solution (proof or model)
      38                 :            : // is being dumped (so that we don't give "sat" or "unsat" then get
      39                 :            : // interrupted partway through outputting a proof!).
      40                 :          0 : void setNoLimitCPU()
      41                 :            : {
      42                 :            :   // Windows doesn't have these things, just ignore
      43                 :            : #ifndef __WIN32__
      44                 :            :   struct rlimit rlc;
      45                 :          0 :   int st = getrlimit(RLIMIT_CPU, &rlc);
      46         [ -  - ]:          0 :   if (st == 0)
      47                 :            :   {
      48                 :          0 :     rlc.rlim_cur = rlc.rlim_max;
      49                 :          0 :     setrlimit(RLIMIT_CPU, &rlc);
      50                 :            :   }
      51                 :            : #endif /* ! __WIN32__ */
      52                 :          0 : }
      53                 :            : 
      54                 :      28710 : CommandExecutor::CommandExecutor(std::unique_ptr<cvc5::Solver>& solver)
      55                 :      28710 :     : d_solver(solver),
      56                 :      28710 :       d_symman(new SymbolManager(d_solver->getTermManager())),
      57                 :      28710 :       d_result(),
      58                 :      28710 :       d_parseOnly(false)
      59                 :            : {
      60                 :      28710 : }
      61                 :      57420 : CommandExecutor::~CommandExecutor() {}
      62                 :            : 
      63                 :      24426 : void CommandExecutor::storeOptionsAsOriginal()
      64                 :            : {
      65                 :      24426 :   d_solver->d_originalOptions->copyValues(d_solver->d_slv->getOptions());
      66                 :            :   // cache the value of parse-only, which is set by the command line only
      67                 :            :   // and thus will not change in a run.
      68                 :      24426 :   d_parseOnly = d_solver->getOptionInfo("parse-only").boolValue();
      69                 :      24426 : }
      70                 :            : 
      71                 :      92327 : void CommandExecutor::setOptionInternal(const std::string& key,
      72                 :            :                                         const std::string& value)
      73                 :            : {
      74                 :            :   // set option, marked not from user.
      75                 :      92327 :   d_solver->d_slv->setOption(key, value, false);
      76                 :      92327 : }
      77                 :            : 
      78                 :      24361 : void CommandExecutor::printStatistics(std::ostream& out) const
      79                 :            : {
      80         [ -  + ]:      24361 :   if (d_solver->getOptionInfo("stats").boolValue())
      81                 :            :   {
      82                 :            :     {
      83                 :          0 :       const auto& stats = d_solver->getStatistics();
      84                 :            :       auto it =
      85                 :          0 :           stats.begin(d_solver->getOptionInfo("stats-internal").boolValue(),
      86                 :          0 :                       d_solver->getOptionInfo("stats-all").boolValue());
      87         [ -  - ]:          0 :       for (; it != stats.end(); ++it)
      88                 :            :       {
      89                 :          0 :         out << it->first << " = " << it->second << std::endl;
      90                 :            :       }
      91                 :          0 :     }
      92                 :            :     {
      93                 :          0 :       const auto& stats = d_solver->getTermManager().getStatistics();
      94                 :            :       auto it =
      95                 :          0 :           stats.begin(d_solver->getOptionInfo("stats-internal").boolValue(),
      96                 :          0 :                       d_solver->getOptionInfo("stats-all").boolValue());
      97         [ -  - ]:          0 :       for (; it != stats.end(); ++it)
      98                 :            :       {
      99                 :          0 :         out << it->first << " = " << it->second << std::endl;
     100                 :            :       }
     101                 :          0 :     }
     102                 :            :   }
     103                 :      24361 : }
     104                 :            : 
     105                 :          0 : void CommandExecutor::printStatisticsSafe(int fd) const
     106                 :            : {
     107         [ -  - ]:          0 :   if (d_solver->getOptionInfo("stats").boolValue())
     108                 :            :   {
     109                 :          0 :     d_solver->getTermManager().printStatisticsSafe(fd);
     110                 :          0 :     d_solver->printStatisticsSafe(fd);
     111                 :            :   }
     112                 :          0 : }
     113                 :            : 
     114                 :     672249 : bool CommandExecutor::doCommand(Command* cmd)
     115                 :            : {
     116                 :            :   // formerly was guarded by verbosity > 2
     117         [ +  - ]:     672249 :   Trace("cmd-exec") << "Invoking: " << *cmd << std::endl;
     118                 :     672249 :   return doCommandSingleton(cmd->d_cmd.get());
     119                 :            : }
     120                 :            : 
     121                 :          0 : void CommandExecutor::reset()
     122                 :            : {
     123                 :          0 :   printStatistics(d_solver->getDriverOptions().err());
     124                 :          0 :   Cmd::resetSolver(d_solver.get());
     125                 :          0 : }
     126                 :            : 
     127                 :     677551 : bool CommandExecutor::doCommandSingleton(Cmd* cmd)
     128                 :            : {
     129                 :     677551 :   bool status = solverInvoke(d_solver.get(), d_symman->toSymManager(), cmd);
     130                 :            : 
     131                 :     677549 :   cvc5::Result res;
     132                 :     677549 :   bool hasResult = false;
     133         [ +  - ]:     677549 :   const CheckSatCommand* cs = dynamic_cast<const CheckSatCommand*>(cmd);
     134         [ +  + ]:     677549 :   if (cs != nullptr)
     135                 :            :   {
     136                 :      26911 :     d_result = res = cs->getResult();
     137                 :      26911 :     hasResult = true;
     138                 :            :   }
     139                 :            :   const CheckSatAssumingCommand* csa =
     140         [ +  - ]:     677549 :       dynamic_cast<const CheckSatAssumingCommand*>(cmd);
     141         [ +  + ]:     677549 :   if (csa != nullptr)
     142                 :            :   {
     143                 :       4145 :     d_result = res = csa->getResult();
     144                 :       4145 :     hasResult = true;
     145                 :            :   }
     146                 :            : 
     147                 :            :   // if we didnt set a result, return the status
     148         [ +  + ]:     677549 :   if (!hasResult)
     149                 :            :   {
     150                 :     646493 :     return status;
     151                 :            :   }
     152                 :            : 
     153                 :            :   // dump the model/proof/unsat core if option is set
     154         [ +  + ]:      31056 :   if (status)
     155                 :            :   {
     156                 :      31008 :     bool isResultUnsat = res.isUnsat();
     157                 :      31008 :     bool isResultSat = res.isSat();
     158                 :      31008 :     std::vector<std::unique_ptr<Cmd> > getterCommands;
     159                 :      62016 :     if (d_solver->getOptionInfo("dump-models").boolValue()
     160 [ +  + ][ +  + ]:      62026 :         && (isResultSat
                 [ +  - ]
     161         [ -  + ]:         10 :             || (res.isUnknown()
     162         [ -  - ]:          0 :                 && res.getUnknownExplanation()
     163                 :            :                        == cvc5::UnknownExplanation::INCOMPLETE)))
     164                 :            :     {
     165                 :         10 :       getterCommands.emplace_back(new GetModelCommand());
     166                 :            :     }
     167                 :      31008 :     if (d_solver->getOptionInfo("dump-proofs").boolValue() && isResultUnsat)
     168                 :            :     {
     169                 :       5266 :       getterCommands.emplace_back(new GetProofCommand());
     170                 :            :     }
     171                 :            : 
     172                 :      62016 :     if ((d_solver->getOptionInfo("dump-instantiations").boolValue()
     173                 :      61994 :          || d_solver->getOptionInfo("dump-instantiations-debug").boolValue())
     174 [ +  + ][ +  + ]:      93002 :         && GetInstantiationsCommand::isEnabled(d_solver.get(), res))
                 [ +  + ]
     175                 :            :     {
     176                 :         12 :       getterCommands.emplace_back(new GetInstantiationsCommand());
     177                 :            :     }
     178                 :            : 
     179                 :      62016 :     if (d_solver->getOptionInfo("dump-unsat-cores").boolValue()
     180 [ +  + ][ +  + ]:      62016 :         && isResultUnsat)
                 [ +  - ]
     181                 :            :     {
     182                 :          3 :       getterCommands.emplace_back(new GetUnsatCoreCommand());
     183                 :            :     }
     184                 :            : 
     185                 :      62016 :     if (d_solver->getOptionInfo("dump-unsat-cores-lemmas").boolValue()
     186 [ -  + ][ -  - ]:      62016 :         && isResultUnsat)
                 [ +  - ]
     187                 :            :     {
     188                 :          0 :       getterCommands.emplace_back(new GetUnsatCoreLemmasCommand());
     189                 :            :     }
     190                 :            : 
     191                 :      62016 :     if (d_solver->getOptionInfo("dump-difficulty").boolValue()
     192 [ +  + ][ +  + ]:      62016 :         && (isResultUnsat || isResultSat || res.isUnknown()))
         [ +  + ][ -  + ]
                 [ +  - ]
     193                 :            :     {
     194                 :         11 :       getterCommands.emplace_back(new GetDifficultyCommand());
     195                 :            :     }
     196                 :            : 
     197         [ +  + ]:      31008 :     if (!getterCommands.empty())
     198                 :            :     {
     199                 :            :       // set no time limit during dumping if applicable
     200         [ -  + ]:       5302 :       if (d_solver->getOptionInfo("force-no-limit-cpu-while-dump").boolValue())
     201                 :            :       {
     202                 :          0 :         setNoLimitCPU();
     203                 :            :       }
     204         [ +  + ]:      10604 :       for (const auto& getterCommand : getterCommands)
     205                 :            :       {
     206                 :       5302 :         status = doCommandSingleton(getterCommand.get());
     207         [ -  + ]:       5302 :         if (!status)
     208                 :            :         {
     209                 :          0 :           break;
     210                 :            :         }
     211                 :            :       }
     212                 :            :     }
     213                 :      31008 :   }
     214                 :      31056 :   return status;
     215                 :     677549 : }
     216                 :            : 
     217                 :     677551 : bool CommandExecutor::solverInvoke(cvc5::Solver* solver,
     218                 :            :                                    SymManager* sm,
     219                 :            :                                    Cmd* cmd)
     220                 :            : {
     221                 :            :   // print output for -o raw-benchmark
     222         [ +  + ]:     677551 :   if (solver->isOutputOn("raw-benchmark"))
     223                 :            :   {
     224                 :     138665 :     solver->getOutput("raw-benchmark") << cmd->toString() << std::endl;
     225                 :            :   }
     226                 :            : 
     227                 :            :   // In parse-only mode, we do not invoke any of the commands except define-*
     228                 :            :   // declare-*, set-logic, and reset commands. We invoke define-* and declare-*
     229                 :            :   // commands because they add function names to the symbol table.
     230 [ +  - ][ +  + ]:     277261 :   if (d_parseOnly && dynamic_cast<SetBenchmarkLogicCommand*>(cmd) == nullptr
     231 [ +  - ][ +  + ]:     268665 :       && dynamic_cast<ResetCommand*>(cmd) == nullptr
     232 [ +  - ][ +  + ]:     268630 :       && dynamic_cast<DeclarationDefinitionCommand*>(cmd) == nullptr
     233 [ +  - ][ +  + ]:     101305 :       && dynamic_cast<DatatypeDeclarationCommand*>(cmd) == nullptr
     234 [ +  + ][ +  - ]:     954812 :       && dynamic_cast<DefineFunctionRecCommand*>(cmd) == nullptr)
         [ +  + ][ +  + ]
     235                 :            :   {
     236                 :      99693 :     return true;
     237                 :            :   }
     238                 :            : 
     239                 :     577858 :   cmd->invokeAndPrintResult(solver, sm);
     240                 :     577856 :   return !cmd->fail();
     241                 :            : }
     242                 :            : 
     243                 :      24361 : void CommandExecutor::flushOutputStreams()
     244                 :            : {
     245                 :      24361 :   printStatistics(d_solver->getDriverOptions().err());
     246                 :            : 
     247                 :            :   // make sure out and err streams are flushed too
     248                 :      24361 :   d_solver->getDriverOptions().out() << std::flush;
     249                 :      24361 :   d_solver->getDriverOptions().err() << std::flush;
     250                 :      24361 : }
     251                 :            : 
     252                 :            : }  // namespace cvc5::main

Generated by: LCOV version 1.14