diff --git a/src/ComputingTasks.cc b/src/ComputingTasks.cc index 35e5cb09f163082541353703e46dd4820a4fea72..ec534f81ba293fec6adc2061a8cdf7a55fe9ac7d 100644 --- a/src/ComputingTasks.cc +++ b/src/ComputingTasks.cc @@ -643,6 +643,16 @@ StochSimulStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsoli } symbol_list.removeDuplicates("stoch_simul", warnings); + + try + { + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: stoch_simul: " << e.message << endl; + exit(EXIT_FAILURE); + } } void @@ -684,6 +694,20 @@ ForecastStatement::ForecastStatement(SymbolList symbol_list_arg, { } +void +ForecastStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) +{ + try + { + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: forecast: " << e.message << endl; + exit(EXIT_FAILURE); + } +} + void ForecastStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const { @@ -917,10 +941,10 @@ RamseyConstraintsStatement::writeJsonOutput(ostream &output) const } RamseyPolicyStatement::RamseyPolicyStatement(const SymbolTable &symbol_table_arg, - vector<string> ramsey_policy_list_arg, + SymbolList symbol_list_arg, OptionsList options_list_arg) : symbol_table{symbol_table_arg}, - ramsey_policy_list{move(ramsey_policy_list_arg)}, + symbol_list{move(symbol_list_arg)}, options_list{move(options_list_arg)} { } @@ -964,23 +988,15 @@ RamseyPolicyStatement::checkPass(ModFileStructure &mod_file_struct, WarningConso if (auto it = options_list.symbol_list_options.find("instruments"); it != options_list.symbol_list_options.end()) mod_file_struct.instruments = it->second; -} -void -RamseyPolicyStatement::checkRamseyPolicyList() -{ - for (const auto & it : ramsey_policy_list) + try { - if (!symbol_table.exists(it)) - { - cerr << "ERROR: ramsey_policy: " << it << " was not declared." << endl; - exit(EXIT_FAILURE); - } - if (symbol_table.getType(it) != SymbolType::endogenous) - { - cerr << "ERROR: ramsey_policy: " << it << " is not endogenous." << endl; - exit(EXIT_FAILURE); - } + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: ramsey_policy: " << e.message << endl; + exit(EXIT_FAILURE); } } @@ -995,16 +1011,8 @@ RamseyPolicyStatement::writeOutput(ostream &output, const string &basename, bool output << "options_.k_order_solver = true;" << endl; options_list.writeOutput(output); - output << "var_list_ = {"; - for (auto it = ramsey_policy_list.begin(); - it != ramsey_policy_list.end(); ++it) - { - if (it != ramsey_policy_list.begin()) - output << ";"; - output << "'" << *it << "'"; - } - output << "};" << endl - << "ramsey_policy(var_list_);" << endl; + symbol_list.writeOutput("var_list_", output); + output << "ramsey_policy(var_list_);" << endl; } void @@ -1016,16 +1024,12 @@ RamseyPolicyStatement::writeJsonOutput(ostream &output) const output << ", "; options_list.writeJsonOutput(output); } - output << R"(, "ramsey_policy_list": [)"; - for (auto it = ramsey_policy_list.begin(); - it != ramsey_policy_list.end(); ++it) + if (!symbol_list.empty()) { - if (it != ramsey_policy_list.begin()) - output << ","; - output << R"(")" << *it << R"(")"; + output << ", "; + symbol_list.writeJsonOutput(output); } - output << "]" - << "}"; + output << "}"; } void @@ -1088,6 +1092,16 @@ DiscretionaryPolicyStatement::checkPass(ModFileStructure &mod_file_struct, Warni if (auto it = options_list.symbol_list_options.find("instruments"); it != options_list.symbol_list_options.end()) mod_file_struct.instruments = it->second; + + try + { + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: discretionary_policy: " << e.message << endl; + exit(EXIT_FAILURE); + } } void @@ -1199,6 +1213,16 @@ EstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsoli cerr << "ERROR: The mode_file option of the estimation statement is incompatible with the use_calibration option of the estimated_params_init block." << endl; exit(EXIT_FAILURE); } + + try + { + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: estimation: " << e.message << endl; + exit(EXIT_FAILURE); + } } void @@ -1969,6 +1993,16 @@ OsrStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation (it != options_list.num_options.end() && it->second == "true") || mod_file_struct.order_option >= 3) mod_file_struct.k_order_solver = true; + + try + { + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: osr: " << e.message << endl; + exit(EXIT_FAILURE); + } } void @@ -2083,6 +2117,20 @@ DynaSaveStatement::DynaSaveStatement(SymbolList symbol_list_arg, { } +void +DynaSaveStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) +{ + try + { + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: dynasave: " << e.message << endl; + exit(EXIT_FAILURE); + } +} + void DynaSaveStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const { @@ -2111,6 +2159,20 @@ DynaTypeStatement::DynaTypeStatement(SymbolList symbol_list_arg, { } +void +DynaTypeStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) +{ + try + { + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: dynatype: " << e.message << endl; + exit(EXIT_FAILURE); + } +} + void DynaTypeStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const { @@ -2498,6 +2560,16 @@ MSSBVARIrfStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsoli << "filtered_probabilities to ms_irf" << endl; exit(EXIT_FAILURE); } + + try + { + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: ms_irf: " << e.message << endl; + exit(EXIT_FAILURE); + } } void @@ -2765,6 +2837,16 @@ ShockDecompositionStatement::checkPass(ModFileStructure &mod_file_struct, Warnin if (auto it = options_list.num_options.find("shock_decomp.with_epilogue"); it != options_list.num_options.end() && it->second == "true") mod_file_struct.with_epilogue_option = true; + + try + { + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: shock_decomposition: " << e.message << endl; + exit(EXIT_FAILURE); + } } void @@ -2805,6 +2887,16 @@ RealtimeShockDecompositionStatement::checkPass(ModFileStructure &mod_file_struct if (auto it = options_list.num_options.find("shock_decomp.with_epilogue"); it != options_list.num_options.end() && it->second == "true") mod_file_struct.with_epilogue_option = true; + + try + { + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: realtime_shock_decomposition: " << e.message << endl; + exit(EXIT_FAILURE); + } } void @@ -2878,6 +2970,16 @@ InitialConditionDecompositionStatement::checkPass(ModFileStructure &mod_file_str if (auto it = options_list.num_options.find("initial_condition_decomp.with_epilogue"); it != options_list.num_options.end() && it->second == "true") mod_file_struct.with_epilogue_option = true; + + try + { + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: initial_condition_decomposition: " << e.message << endl; + exit(EXIT_FAILURE); + } } void @@ -2911,6 +3013,21 @@ SqueezeShockDecompositionStatement::SqueezeShockDecompositionStatement(SymbolLis { } +void +SqueezeShockDecompositionStatement::checkPass(ModFileStructure &mod_file_struct, + WarningConsolidation &warnings) +{ + try + { + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: squeeze_shock_decomposition: " << e.message << endl; + exit(EXIT_FAILURE); + } +} + void SqueezeShockDecompositionStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const { @@ -2975,6 +3092,21 @@ PlotConditionalForecastStatement::PlotConditionalForecastStatement(int periods_a { } +void +PlotConditionalForecastStatement::checkPass(ModFileStructure &mod_file_struct, + WarningConsolidation &warnings) +{ + try + { + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: plot_conditional_forecast: " << e.message << endl; + exit(EXIT_FAILURE); + } +} + void PlotConditionalForecastStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const { @@ -4538,6 +4670,15 @@ void CalibSmootherStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) { mod_file_struct.calib_smoother_present = true; + try + { + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: calib_smoother: " << e.message << endl; + exit(EXIT_FAILURE); + } } void @@ -4658,6 +4799,20 @@ GMMEstimationStatement::GMMEstimationStatement(SymbolList symbol_list_arg, { } +void +GMMEstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) +{ + try + { + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: gmm_estimation: " << e.message << endl; + exit(EXIT_FAILURE); + } +} + void GMMEstimationStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const { @@ -4691,6 +4846,20 @@ SMMEstimationStatement::SMMEstimationStatement(SymbolList symbol_list_arg, { } +void +SMMEstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) +{ + try + { + symbol_list.checkPass(warnings); + } + catch (SymbolList::SymbolListException &e) + { + cerr << "ERROR: smm_estimation: " << e.message << endl; + exit(EXIT_FAILURE); + } +} + void SMMEstimationStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const { diff --git a/src/ComputingTasks.hh b/src/ComputingTasks.hh index 82c77210cf84d0f478565a07e1c0ce71c086d3e8..47f647a1bf392f7c2070d99d29e626cecb813e4c 100644 --- a/src/ComputingTasks.hh +++ b/src/ComputingTasks.hh @@ -106,7 +106,6 @@ public: DetCondForecast(SymbolList symbol_list_arg, OptionsList options_list_arg, const bool linear_decompositiontion_arg); - //virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings); void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override; }; @@ -203,6 +202,7 @@ private: public: ForecastStatement(SymbolList symbol_list_arg, OptionsList options_list_arg); + void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override; void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override; void writeJsonOutput(ostream &output) const override; }; @@ -242,11 +242,11 @@ class RamseyPolicyStatement : public Statement { private: const SymbolTable &symbol_table; - const vector<string> ramsey_policy_list; + const SymbolList symbol_list; const OptionsList options_list; public: RamseyPolicyStatement(const SymbolTable &symbol_table_arg, - vector<string> ramsey_policy_list_arg, + SymbolList symbol_list_arg, OptionsList options_list_arg); void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override; void checkRamseyPolicyList(); @@ -410,6 +410,7 @@ private: public: DynaTypeStatement(SymbolList symbol_list_arg, string filename_arg); + void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override; void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override; void writeJsonOutput(ostream &output) const override; }; @@ -422,6 +423,7 @@ private: public: DynaSaveStatement(SymbolList symbol_list_arg, string filename_arg); + void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override; void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override; void writeJsonOutput(ostream &output) const override; }; @@ -769,6 +771,7 @@ private: const SymbolList symbol_list; public: SqueezeShockDecompositionStatement(SymbolList symbol_list_arg); + void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override; void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override; void writeJsonOutput(ostream &output) const override; }; @@ -792,6 +795,7 @@ private: const SymbolList symbol_list; public: PlotConditionalForecastStatement(int periods_arg, SymbolList symbol_list_arg); + void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override; void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override; void writeJsonOutput(ostream &output) const override; }; @@ -1145,6 +1149,7 @@ private: const OptionsList options_list; public: GMMEstimationStatement(SymbolList symbol_list_arg, OptionsList options_list_arg); + void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override; void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override; void writeJsonOutput(ostream &output) const override; }; @@ -1156,6 +1161,7 @@ private: const OptionsList options_list; public: SMMEstimationStatement(SymbolList symbol_list_arg, OptionsList options_list_arg); + void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override; void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override; void writeJsonOutput(ostream &output) const override; }; diff --git a/src/DynareBison.yy b/src/DynareBison.yy index 047f81ac082f9218d7d818994729c622541a85f1..971b9e98a76bd299159e7eb2af7c91fc79441441 100644 --- a/src/DynareBison.yy +++ b/src/DynareBison.yy @@ -2322,19 +2322,12 @@ ramsey_policy : RAMSEY_POLICY ';' { driver.ramsey_policy(); } | RAMSEY_POLICY '(' ramsey_policy_options_list ')' ';' { driver.ramsey_policy(); } - | RAMSEY_POLICY ramsey_policy_list ';' + | RAMSEY_POLICY symbol_list ';' { driver.ramsey_policy(); } - | RAMSEY_POLICY '(' ramsey_policy_options_list ')' ramsey_policy_list ';' + | RAMSEY_POLICY '(' ramsey_policy_options_list ')' symbol_list ';' { driver.ramsey_policy(); } ; -ramsey_policy_list : ramsey_policy_list ramsey_policy_element - | ramsey_policy_element - ; - -ramsey_policy_element : symbol { driver.add_to_ramsey_policy_list($1); } - ; - ramsey_constraints : RAMSEY_CONSTRAINTS ';' ramsey_constraints_list END ';' { driver.add_ramsey_constraints_statement(); } ; diff --git a/src/ModFile.cc b/src/ModFile.cc index 2e26a507b5bbb12a343c7dc73d4dd945beccd8d3..06cb68fef06d2c69046b210ccb40d268364fae77 100644 --- a/src/ModFile.cc +++ b/src/ModFile.cc @@ -690,11 +690,6 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool exit(EXIT_FAILURE); } - if (mod_file_struct.ramsey_policy_present) - for (auto & statement : statements) - if (auto rps = dynamic_cast<RamseyPolicyStatement *>(statement.get()); rps) - rps->checkRamseyPolicyList(); - if (mod_file_struct.identification_present && symbol_table.exo_det_nbr() > 0) { cerr << "ERROR: identification is incompatible with deterministic exogenous variables" << endl; diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc index bf55ac51bbfcea2b7067439c766f324038d54361..e80c146d65ce50c492b8e549c77febeb71c09c10 100644 --- a/src/ParsingDriver.cc +++ b/src/ParsingDriver.cc @@ -91,7 +91,7 @@ ParsingDriver::parse(istream &in, bool debug) { mod_file = make_unique<ModFile>(warnings); - symbol_list.clear(); + symbol_list.setSymbolTable(mod_file->symbol_table); reset_data_tree(); estim_params.init(*data_tree); @@ -1464,8 +1464,6 @@ ParsingDriver::linear() void ParsingDriver::add_in_symbol_list(const string &tmp_var) { - if (tmp_var != ":") - check_symbol_existence(tmp_var); symbol_list.addSymbol(tmp_var); } @@ -2208,18 +2206,13 @@ ParsingDriver::ramsey_policy() else if (planner_discount) error("ramsey_policy: the 'planner_discount' option cannot be used when the 'optimal_policy_discount_factor' parameter is explicitly declared."); - mod_file->addStatement(make_unique<RamseyPolicyStatement>(mod_file->symbol_table, ramsey_policy_list, options_list)); + mod_file->addStatement(make_unique<RamseyPolicyStatement>(mod_file->symbol_table, + symbol_list, options_list)); options_list.clear(); - ramsey_policy_list.clear(); + symbol_list.clear(); planner_discount = nullptr; } -void -ParsingDriver::add_to_ramsey_policy_list(string name) -{ - ramsey_policy_list.push_back(move(name)); -} - void ParsingDriver::evaluate_planner_objective() { diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh index f711e9dd36e8b626b1838f8d9d9a5a921c46a5ef..a8f1d72f9000d9e20c07465da388253cf73e38f4 100644 --- a/src/ParsingDriver.hh +++ b/src/ParsingDriver.hh @@ -237,8 +237,6 @@ private: vector<ShockGroupsStatement::Group> shock_groups; //! Temporary storage for init2shocks vector<pair<int, int>> init2shocks; - //! Temporary storage for ramsey policy. Workaround for issue #1355 - vector<string> ramsey_policy_list; /* Temporary storage for planner_discount and planner_discount_latex_name options of ramsey_model and ramsey_policy */ expr_t planner_discount{nullptr}; @@ -888,8 +886,6 @@ public: void add_init2shocks(const string &endo_name, const string &exo_name); //! End init2shocks declaration void end_init2shocks(const string &name); - //! Add an element to the ramsey policy list - void add_to_ramsey_policy_list(string name); void smoother2histval(); void histval_file(const string &filename); void perfect_foresight_setup(); diff --git a/src/SymbolList.cc b/src/SymbolList.cc index aada60629acbc3337d8d34e66fde8a7968f2609c..e05d1d41e325e2c38eb71123ff74b1b1ccc13e1f 100644 --- a/src/SymbolList.cc +++ b/src/SymbolList.cc @@ -17,14 +17,47 @@ * along with Dynare. If not, see <http://www.gnu.org/licenses/>. */ +#include <regex> + #include "SymbolList.hh" +void +SymbolList::setSymbolTable(const SymbolTable &symbol_table_arg) +{ + symbol_table = &symbol_table_arg; +} + void SymbolList::addSymbol(const string &symbol) { symbols.push_back(symbol); } +void +SymbolList::checkPass(WarningConsolidation &warnings) const noexcept(false) +{ + smatch m; + regex re("^(AUX_EXPECT_|AUX_ENDO_|MULT_)"); + for (const auto & symbol : symbols) + { + if (!symbol_table->exists(symbol)) + { + if (regex_search(symbol, m, re)) + { + warnings << "WARNING: symbol_list variable " << symbol << " has not yet been declared. " + << "This is being ignored because the variable name corresponds to a possible " + << "auxiliary variable name." << endl; + return; + } + else + throw SymbolListException{"Variable " + symbol + " was not declared."}; + } + + if (symbol_table->getType(symbol) != SymbolType::endogenous) + throw SymbolListException{"Variable " + symbol + " is not endogenous."}; + } +} + void SymbolList::writeOutput(const string &varname, ostream &output) const { diff --git a/src/SymbolList.hh b/src/SymbolList.hh index a3100d8e54258773781385feb14c3e07a9f93b60..87657d9cc36d1264d1e240dca94eb4330c0003c1 100644 --- a/src/SymbolList.hh +++ b/src/SymbolList.hh @@ -26,6 +26,7 @@ #include <algorithm> #include "WarningConsolidation.hh" +#include "SymbolTable.hh" using namespace std; @@ -36,11 +37,22 @@ class SymbolList private: //! Internal container for symbol list vector<string> symbols; + const SymbolTable *symbol_table; public: + class SymbolListException + { + public: + const string message; + SymbolListException(string message_arg) : message{move(message_arg)} {}; + }; + //! Set symbol table pointer + void setSymbolTable(const SymbolTable &symbol_table_arg); //! Adds a symbol to the list void addSymbol(const string &symbol); //! Removed duplicate symbols void removeDuplicates(const string &dynare_command, WarningConsolidation &warnings); + //! Check symbols to ensure variables have been declared and are endogenous + void checkPass(WarningConsolidation &warnings) const noexcept(false); //! Output content in Matlab format /*! Creates a string array for Matlab, stored in variable "varname" */ void writeOutput(const string &varname, ostream &output) const;