diff --git a/ComputingTasks.cc b/ComputingTasks.cc index 2daf075dc1891d21cce3837fc530bb16fc28aeaa..740b061b1eaa192a661e6afc8eeaeb080f59fee0 100644 --- a/ComputingTasks.cc +++ b/ComputingTasks.cc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Dynare Team + * Copyright (C) 2003-2018 Dynare Team * * This file is part of Dynare. * @@ -852,15 +852,15 @@ RamseyPolicyStatement::writeOutput(ostream &output, const string &basename, bool output << "options_.k_order_solver = 1;" << endl; options_list.writeOutput(output); - output << "var_list_ = char("; + output << "var_list_ = {"; for (vector<string>::const_iterator it = ramsey_policy_list.begin(); it != ramsey_policy_list.end(); ++it) { if (it != ramsey_policy_list.begin()) - output << ","; + output << ";"; output << "'" << *it << "'"; } - output << ");" << endl + output << "};" << endl << "ramsey_policy(var_list_);" << endl; } diff --git a/DynamicModel.cc b/DynamicModel.cc index 19072ce71dab3aef3fbeca6c6bfdc6b8d93309aa..054482adc0a247ee91002af316c8c028a9c4a23b 100644 --- a/DynamicModel.cc +++ b/DynamicModel.cc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Dynare Team + * Copyright (C) 2003-2018 Dynare Team * * This file is part of Dynare. * @@ -1773,21 +1773,38 @@ DynamicModel::reform(const string name1) const } void -DynamicModel::getNonZeroHessianEquations(map<int, string> &eqs) const +DynamicModel::printNonZeroHessianEquations(ostream &output) const +{ + if (nonzero_hessian_eqs.size() != 1) + output << "["; + for (map<int, string>::const_iterator it = nonzero_hessian_eqs.begin(); + it != nonzero_hessian_eqs.end(); it++) + { + if (it != nonzero_hessian_eqs.begin()) + output << " "; + output << it->first; + } + if (nonzero_hessian_eqs.size() != 1) + output << "]"; +} + +void +DynamicModel::setNonZeroHessianEquations(map<int, string> &eqs) { for (second_derivatives_t::const_iterator it = second_derivatives.begin(); it != second_derivatives.end(); it++) - if (eqs.find(it->first.first) == eqs.end()) + if (nonzero_hessian_eqs.find(it->first.first) == nonzero_hessian_eqs.end()) { - eqs[it->first.first] = ""; + nonzero_hessian_eqs[it->first.first] = ""; for (size_t i = 0; i < equation_tags.size(); i++) if (equation_tags[i].first == it->first.first) if (equation_tags[i].second.first == "name") { - eqs[it->first.first] = equation_tags[i].second.second; + nonzero_hessian_eqs[it->first.first] = equation_tags[i].second.second; break; } } + eqs = nonzero_hessian_eqs; } void diff --git a/DynamicModel.hh b/DynamicModel.hh index c9eaec7fff9fc3e0e6d935db2e9b33428dbba6d1..edd506d25fe71f539de65cf2f1bf2849eb86971a 100644 --- a/DynamicModel.hh +++ b/DynamicModel.hh @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Dynare Team + * Copyright (C) 2003-2018 Dynare Team * * This file is part of Dynare. * @@ -80,6 +80,9 @@ private: map<pair<int, int>, set<int> > xref_exo; map<pair<int, int>, set<int> > xref_exo_det; + //! Nonzero equations in the Hessian + map<int, string> nonzero_hessian_eqs; + //! Number of columns of dynamic jacobian /*! Set by computeDerivID()s and computeDynJacobianCols() */ int dynJacobianColsNbr; @@ -271,11 +274,11 @@ public: void writeJsonXrefs(ostream &output) const; void writeJsonXrefsHelper(ostream &output, const map<pair<int, int>, set<int> > &xrefs) const; - //! Return true if the hessian is equal to zero - inline bool checkHessianZero() const; + //! Print equations that have non-zero second derivatives + void printNonZeroHessianEquations(ostream &output) const; - //! Return equations that have non-zero second derivatives - void getNonZeroHessianEquations(map<int, string> &eqs) const; + //! Set the equations that have non-zero second derivatives + void setNonZeroHessianEquations(map<int, string> &eqs); //! Set indices for var expectation in dynamic model file void setVarExpectationIndices(map<string, pair<SymbolList, int> > var_model_info); @@ -569,12 +572,6 @@ public: bool isChecksumMatching(const string &basename) const; }; -inline bool -DynamicModel::checkHessianZero() const -{ - return second_derivatives.empty(); -} - //! Classes to re-order derivatives for various sparse storage formats class derivative { diff --git a/DynareBison.yy b/DynareBison.yy index 821e97f2b0eee440fbfe71f9dd7a0f90356107ac..f492d6753c2abbd1bbf370a949aac3e6083ac495 100644 --- a/DynareBison.yy +++ b/DynareBison.yy @@ -2789,6 +2789,7 @@ dynare_sensitivity_option : o_gsa_identification | o_ar | o_kalman_algo | o_lik_init + | o_diffuse_filter | o_analytic_derivation | o_analytic_derivation_mode ; @@ -3360,16 +3361,16 @@ o_psd_fig_name : FIG_NAME EQUAL filename { driver.option_str("plot_shock_decomp. o_psd_type : TYPE EQUAL QOQ { driver.option_str("plot_shock_decomp.type", "qoq"); } | TYPE EQUAL YOY - { driver.option_str("plot_shock_decomp.type", "qoq"); } + { driver.option_str("plot_shock_decomp.type", "yoy"); } | TYPE EQUAL AOA - { driver.option_str("plot_shock_decomp.type", "qoq"); } + { driver.option_str("plot_shock_decomp.type", "aoa"); } ; o_icd_type : TYPE EQUAL QOQ { driver.option_str("initial_condition_decomp.type", "qoq"); } | TYPE EQUAL YOY - { driver.option_str("initial_condition_decomp.type", "qoq"); } + { driver.option_str("initial_condition_decomp.type", "yoy"); } | TYPE EQUAL AOA - { driver.option_str("initial_condition_decomp.type", "qoq"); } + { driver.option_str("initial_condition_decomp.type", "aoa"); } ; o_icd_plot_init_date : PLOT_INIT_DATE EQUAL date_expr { driver.option_date("initial_condition_decomp.plot_init_date", $3); } ; o_icd_plot_end_date : PLOT_END_DATE EQUAL date_expr { driver.option_date("initial_condition_decomp.plot_end_date", $3); } ; diff --git a/DynareMain.cc b/DynareMain.cc index eb2891a6e30235df2d17a4e08e2714511a84033c..16183842c4dffd9254209fde69c7ee57b2e292e7 100644 --- a/DynareMain.cc +++ b/DynareMain.cc @@ -50,12 +50,12 @@ void main2(stringstream &in, string &basename, bool debug, bool clear_all, bool ); void main1(string &modfile, string &basename, string &modfiletxt, bool debug, bool save_macro, string &save_macro_file, - bool no_line_macro, map<string, string> &defines, vector<string> &path, stringstream ¯o_output); + bool no_line_macro, bool no_empty_line_macro, map<string, string> &defines, vector<string> &path, stringstream ¯o_output); void usage() { - cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [notmpterms] [nolog] [warn_uninit]" + cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [noemptylinemacro] [notmpterms] [nolog] [warn_uninit]" << " [console] [nograph] [nointeractive] [parallel[=cluster_name]] [conffile=parallel_config_path_and_filename] [parallel_slave_open_mode] [parallel_test]" << " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] [compute_xrefs] [output=dynamic|first|second|third] [language=C|C++|julia]" << " [params_derivs_order=0|1|2]" @@ -91,6 +91,7 @@ main(int argc, char **argv) bool no_tmp_terms = false; bool only_macro = false; bool no_line_macro = false; + bool no_empty_line_macro = false; bool no_log = false; bool no_warn = false; int params_derivs_order = 2; @@ -162,6 +163,8 @@ main(int argc, char **argv) } else if (!strcmp(argv[arg], "nolinemacro")) no_line_macro = true; + else if (!strcmp(argv[arg], "noemptylinemacro")) + no_empty_line_macro = true; else if (!strcmp(argv[arg], "notmpterms")) no_tmp_terms = true; else if (!strcmp(argv[arg], "nolog")) @@ -389,7 +392,8 @@ main(int argc, char **argv) // Do macro processing stringstream macro_output; - main1(modfile, basename, modfiletxt, debug, save_macro, save_macro_file, no_line_macro, defines, path, macro_output); + main1(modfile, basename, modfiletxt, debug, save_macro, save_macro_file, no_line_macro, no_empty_line_macro, + defines, path, macro_output); if (only_macro) return EXIT_SUCCESS; diff --git a/DynareMain1.cc b/DynareMain1.cc index fe87ba83b4cf0c60aae726883dbc991b7af6e759..c801fd86d8c9b840675e34e863bb49175b681c3a 100644 --- a/DynareMain1.cc +++ b/DynareMain1.cc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Dynare Team + * Copyright (C) 2015-2017 Dynare Team * * This file is part of Dynare. * @@ -22,14 +22,18 @@ #include "macro/MacroDriver.hh" +bool compareNewline (int i, int j) { + return i == '\n' && j == '\n'; +} + void main1(string &modfile, string &basename, string &modfiletxt, bool debug, bool save_macro, string &save_macro_file, - bool no_line_macro, map<string, string> &defines, vector<string> &path, stringstream ¯o_output) + bool no_line_macro, bool no_empty_line_macro, map<string, string> &defines, vector<string> &path, stringstream ¯o_output) { // Do macro processing MacroDriver m; - m.parse(modfile, modfiletxt, macro_output, debug, no_line_macro, defines, path); + m.parse(modfile, basename, modfiletxt, macro_output, debug, no_line_macro, defines, path); if (save_macro) { if (save_macro_file.empty()) @@ -40,7 +44,11 @@ main1(string &modfile, string &basename, string &modfiletxt, bool debug, bool sa cerr << "Cannot open " << save_macro_file << " for macro output" << endl; exit(EXIT_FAILURE); } - macro_output_file << macro_output.str(); + + string str (macro_output.str()); + if (no_empty_line_macro) + str.erase(unique(str.begin(), str.end(), compareNewline), str.end()); + macro_output_file << str; macro_output_file.close(); } } diff --git a/ModFile.cc b/ModFile.cc index f83604258fa9e119ec128b9a1a51c6890455e0f5..1de813fcde3c47fc60359e16bfad9dd21930651c 100644 --- a/ModFile.cc +++ b/ModFile.cc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2017 Dynare Team + * Copyright (C) 2006-2018 Dynare Team * * This file is part of Dynare. * @@ -615,15 +615,14 @@ ModFile::computingPass(bool no_tmp_terms, FileOutputType output, int params_deri else // No computing task requested, compute derivatives up to 2nd order by default dynamic_model.computingPass(true, true, false, none, global_eval_context, no_tmp_terms, block, use_dll, byte_code, nopreprocessoroutput); - if ((linear && !mod_file_struct.ramsey_model_present && !dynamic_model.checkHessianZero()) - || (linear && mod_file_struct.ramsey_model_present && !orig_ramsey_dynamic_model.checkHessianZero())) - { - map<int, string> eqs; - if (mod_file_struct.ramsey_model_present) - orig_ramsey_dynamic_model.getNonZeroHessianEquations(eqs); - else - dynamic_model.getNonZeroHessianEquations(eqs); + map<int, string> eqs; + if (mod_file_struct.ramsey_model_present) + orig_ramsey_dynamic_model.setNonZeroHessianEquations(eqs); + else + dynamic_model.setNonZeroHessianEquations(eqs); + if (linear && !eqs.empty()) + { cerr << "ERROR: If the model is declared linear the second derivatives must be equal to zero." << endl << " The following equations had non-zero second derivatives:" << endl; for (map<int, string >::const_iterator it = eqs.begin(); it != eqs.end(); it++) @@ -770,7 +769,13 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo mOutputFile << "};" << endl; } - mOutputFile << "M_.hessian_eq_zero = " << dynamic_model.checkHessianZero() << ";" << endl; + mOutputFile << "M_.nonzero_hessian_eqs = "; + if (mod_file_struct.ramsey_model_present) + orig_ramsey_dynamic_model.printNonZeroHessianEquations(mOutputFile); + else + dynamic_model.printNonZeroHessianEquations(mOutputFile); + mOutputFile << ";" << endl + << "M_.hessian_eq_zero = isempty(M_.nonzero_hessian_eqs);" << endl; config_file.writeCluster(mOutputFile); diff --git a/ModelTree.cc b/ModelTree.cc index cb3523a627c1c7070b6cccced67a765aa47d1108..aea4f6b70b824b38563e37f82ebcfc74b267613a 100644 --- a/ModelTree.cc +++ b/ModelTree.cc @@ -1453,35 +1453,31 @@ ModelTree::writeJsonModelLocalVariables(ostream &output, deriv_node_temp_terms_t for (size_t i = 0; i < equations.size(); i++) equations[i]->collectVariables(eModelLocalVariable, used_local_vars); - output << "\"external_functions_model_local_variables\": ["; - for (set<int>::const_iterator it = used_local_vars.begin(); - it != used_local_vars.end(); ++it) - { - vector<string> efout; - expr_t value = local_variables_table.find(*it)->second; - value->writeJsonExternalFunctionOutput(efout, tt, tef_terms); - for (vector<string>::const_iterator it1 = efout.begin(); it1 != efout.end(); it1++) - { - if (it1 != efout.begin()) - output << ", "; - output << *it1; - } - } - output << "]" - << ", \"model_local_variables\": ["; + output << "\"model_local_variables\": ["; bool printed = false; for (vector<int>::const_iterator it = local_variables_vector.begin(); it != local_variables_vector.end(); it++) if (used_local_vars.find(*it) != used_local_vars.end()) { - int id = *it; - expr_t value = local_variables_table.find(id)->second; - if (printed) output << ", "; else printed = true; + int id = *it; + vector<string> efout; + expr_t value = local_variables_table.find(id)->second; + value->writeJsonExternalFunctionOutput(efout, tt, tef_terms); + for (vector<string>::const_iterator it1 = efout.begin(); it1 != efout.end(); it1++) + { + if (it1 != efout.begin()) + output << ", "; + output << *it1; + } + + if (!efout.empty()) + output << ", "; + /* We append underscores to avoid name clashes with "g1" or "oo_" (see also VariableNode::writeOutput) */ output << "{\"variable\": \"" << symbol_table.getName(id) << "__\"" diff --git a/ParsingDriver.cc b/ParsingDriver.cc index 5d2639f009c403732fd024944f4b6f55cb2d7706..b9e2a9b10ba2cc76b3bb178d367490dfd7492679 100644 --- a/ParsingDriver.cc +++ b/ParsingDriver.cc @@ -2580,8 +2580,7 @@ ParsingDriver::add_divide(expr_t arg1, expr_t arg2) } catch (DataTree::DivisionByZeroException) { - cerr << "...division by zero error encountred when reading model from .mod file" << endl; - exit(EXIT_FAILURE); + error("Division by zero error encountered when reading model from .mod file"); } } diff --git a/SymbolList.cc b/SymbolList.cc index 6e5251f1a2cee0e59bc0512c32246c107ee15efe..d6a16562c78c8e8caf10d44656380e81ce26298b 100644 --- a/SymbolList.cc +++ b/SymbolList.cc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Dynare Team + * Copyright (C) 2003-2018 Dynare Team * * This file is part of Dynare. * @@ -28,35 +28,15 @@ SymbolList::addSymbol(const string &symbol) void SymbolList::writeOutput(const string &varname, ostream &output) const { - output << varname << " = "; - write(output); - output << ";" << endl; -} - -void -SymbolList::write(ostream &output) const -{ - output << " char("; + output << varname << " = {"; for (vector<string>::const_iterator it = symbols.begin(); it != symbols.end(); ++it) { if (it != symbols.begin()) - output << ","; + output << ";"; output << "'" << *it << "'"; } - output << ")"; -} - -int -SymbolList::getSize() const -{ - return symbols.size(); -} - -vector<string> -SymbolList::getSymbols() const -{ - return symbols; + output << "};" << endl; } void @@ -78,3 +58,15 @@ SymbolList::clear() { symbols.clear(); } + +int +SymbolList::getSize() const +{ + return symbols.size(); +} + +vector<string> +SymbolList::getSymbols() const +{ + return symbols; +} diff --git a/SymbolTable.cc b/SymbolTable.cc index f1409587cd79f531875eb49b8178c66b255ee012..dde3d141bc047ed7d1202920b61538721ab0cd92 100644 --- a/SymbolTable.cc +++ b/SymbolTable.cc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Dynare Team + * Copyright (C) 2003-2018 Dynare Team * * This file is part of Dynare. * @@ -219,14 +219,13 @@ SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException) if (exo_nbr() > 0) { - output << "M_.exo_names = '" << getName(exo_ids[0]) << "';" << endl; - output << "M_.exo_names_tex = '" << getTeXName(exo_ids[0]) << "';" << endl; - output << "M_.exo_names_long = '" << getLongName(exo_ids[0]) << "';" << endl; - for (int id = 1; id < exo_nbr(); id++) - output << "M_.exo_names = char(M_.exo_names, '" << getName(exo_ids[id]) << "');" << endl - << "M_.exo_names_tex = char(M_.exo_names_tex, '" << getTeXName(exo_ids[id]) << "');" << endl - << "M_.exo_names_long = char(M_.exo_names_long, '" << getLongName(exo_ids[id]) << "');" << endl; - + output << "M_.exo_names = cell(" << exo_nbr() << ",1);" << endl; + output << "M_.exo_names_tex = cell(" << exo_nbr() << ",1);" << endl; + output << "M_.exo_names_long = cell(" << exo_nbr() << ",1);" << endl; + for (int id = 0; id < exo_nbr(); id++) + output << "M_.exo_names(" << id+1 << ") = {'" << getName(exo_ids[id]) << "'};" << endl + << "M_.exo_names_tex(" << id+1 << ") = {'" << getTeXName(exo_ids[id]) << "'};" << endl + << "M_.exo_names_long(" << id+1 << ") = {'" << getLongName(exo_ids[id]) << "'};" << endl; map<string, map<int, string> > partitions = getPartitionsForType(eExogenous); for (map<string, map<int, string> >::const_iterator it = partitions.begin(); it != partitions.end(); it++) @@ -248,14 +247,13 @@ SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException) if (exo_det_nbr() > 0) { - output << "M_.exo_det_names = '" << getName(exo_det_ids[0]) << "';" << endl; - output << "M_.exo_det_names_tex = '" << getTeXName(exo_det_ids[0]) << "';" << endl; - output << "M_.exo_det_names_long = '" << getLongName(exo_det_ids[0]) << "';" << endl; - for (int id = 1; id < exo_det_nbr(); id++) - output << "M_.exo_det_names = char(M_.exo_det_names, '" << getName(exo_det_ids[id]) << "');" << endl - << "M_.exo_det_names_tex = char(M_.exo_det_names_tex, '" << getTeXName(exo_det_ids[id]) << "');" << endl - << "M_.exo_det_names_long = char(M_.exo_det_names_long, '" << getLongName(exo_det_ids[id]) << "');" << endl; - + output << "M_.exo_det_names = cell(" << exo_det_nbr() << ",1);" << endl; + output << "M_.exo_det_names_tex = cell(" << exo_det_nbr() << ",1);" << endl; + output << "M_.exo_det_names_long = cell(" << exo_det_nbr() << ",1);" << endl; + for (int id = 0; id < exo_det_nbr(); id++) + output << "M_.exo_det_names(" << id+1 << ") = {'" << getName(exo_det_ids[id]) << "'};" << endl + << "M_.exo_det_names_tex(" << id+1 << ") = {'" << getTeXName(exo_det_ids[id]) << "'};" << endl + << "M_.exo_det_names_long(" << id+1 << ") = {'" << getLongName(exo_det_ids[id]) << "'};" << endl; output << "M_.exo_det_partitions = struct();" << endl; map<string, map<int, string> > partitions = getPartitionsForType(eExogenousDet); for (map<string, map<int, string> >::const_iterator it = partitions.begin(); @@ -278,14 +276,13 @@ SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException) if (endo_nbr() > 0) { - output << "M_.endo_names = '" << getName(endo_ids[0]) << "';" << endl; - output << "M_.endo_names_tex = '" << getTeXName(endo_ids[0]) << "';" << endl; - output << "M_.endo_names_long = '" << getLongName(endo_ids[0]) << "';" << endl; - for (int id = 1; id < endo_nbr(); id++) - output << "M_.endo_names = char(M_.endo_names, '" << getName(endo_ids[id]) << "');" << endl - << "M_.endo_names_tex = char(M_.endo_names_tex, '" << getTeXName(endo_ids[id]) << "');" << endl - << "M_.endo_names_long = char(M_.endo_names_long, '" << getLongName(endo_ids[id]) << "');" << endl; - + output << "M_.endo_names = cell(" << endo_nbr() << ",1);" << endl; + output << "M_.endo_names_tex = cell(" << endo_nbr() << ",1);" << endl; + output << "M_.endo_names_long = cell(" << endo_nbr() << ",1);" << endl; + for (int id = 0; id < endo_nbr(); id++) + output << "M_.endo_names(" << id+1 << ") = {'" << getName(endo_ids[id]) << "'};" << endl + << "M_.endo_names_tex(" << id+1 << ") = {'" << getTeXName(endo_ids[id]) << "'};" << endl + << "M_.endo_names_long(" << id+1 << ") = {'" << getLongName(endo_ids[id]) << "'};" << endl; output << "M_.endo_partitions = struct();" << endl; map<string, map<int, string> > partitions = getPartitionsForType(eEndogenous); for (map<string, map<int, string> >::const_iterator it = partitions.begin(); @@ -308,19 +305,17 @@ SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException) if (param_nbr() > 0) { - output << "M_.param_names = '" << getName(param_ids[0]) << "';" << endl; - output << "M_.param_names_tex = '" << getTeXName(param_ids[0]) << "';" << endl; - output << "M_.param_names_long = '" << getLongName(param_ids[0]) << "';" << endl; - for (int id = 1; id < param_nbr(); id++) + output << "M_.param_names = cell(" << param_nbr() << ",1);" << endl; + output << "M_.param_names_tex = cell(" << param_nbr() << ",1);" << endl; + output << "M_.param_names_long = cell(" << param_nbr() << ",1);" << endl; + for (int id = 0; id < param_nbr(); id++) { - output << "M_.param_names = char(M_.param_names, '" << getName(param_ids[id]) << "');" << endl - << "M_.param_names_tex = char(M_.param_names_tex, '" << getTeXName(param_ids[id]) << "');" << endl - << "M_.param_names_long = char(M_.param_names_long, '" << getLongName(param_ids[id]) << "');" << endl; - + output << "M_.param_names(" << id+1 << ") = {'" << getName(param_ids[id]) << "'};" << endl + << "M_.param_names_tex(" << id+1 << ") = {'" << getTeXName(param_ids[id]) << "'};" << endl + << "M_.param_names_long(" << id+1 << ") = {'" << getLongName(param_ids[id]) << "'};" << endl; if (getName(param_ids[id]) == "dsge_prior_weight") output << "options_.dsge_var = 1;" << endl; } - output << "M_.param_partitions = struct();" << endl; map<string, map<int, string> > partitions = getPartitionsForType(eParameter); for (map<string, map<int, string> >::const_iterator it = partitions.begin(); @@ -394,7 +389,7 @@ SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException) if (observedVariablesNbr() > 0) { int ic = 1; - output << "options_.varobs = cell(1);" << endl; + output << "options_.varobs = cell(" << observedVariablesNbr() << ", 1);" << endl; for (vector<int>::const_iterator it = varobs.begin(); it != varobs.end(); it++, ic++) output << "options_.varobs(" << ic << ") = {'" << getName(*it) << "'};" << endl; diff --git a/macro/MacroBison.yy b/macro/MacroBison.yy index 27c0e4b28c11dc61735eee686730545d698b054e..a2523356c9b7c482b6f5a10ed9422a28e10efc4f 100644 --- a/macro/MacroBison.yy +++ b/macro/MacroBison.yy @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2016 Dynare Team + * Copyright (C) 2008-2017 Dynare Team * * This file is part of Dynare. * @@ -74,7 +74,7 @@ class MacroDriver; } %token DEFINE LINE FOR IN IF ELSE ENDIF ECHO_DIR ERROR IFDEF IFNDEF -%token LPAREN RPAREN LBRACKET RBRACKET EQUAL EOL LENGTH +%token LPAREN RPAREN LBRACKET RBRACKET EQUAL EOL LENGTH ECHOMACROVARS SAVE %token <int_val> INTEGER %token <string_val> NAME STRING @@ -121,6 +121,10 @@ statement : expr { TYPERR_CATCH(driver.error(@$, $2), @$); } | LINE STRING INTEGER /* Ignore @#line declarations */ + | ECHOMACROVARS + { driver.printvars(@$, true); } + | ECHOMACROVARS LPAREN SAVE RPAREN + { out << driver.printvars(@$, false); } ; expr : INTEGER diff --git a/macro/MacroDriver.cc b/macro/MacroDriver.cc index 4d2399ec0ba91f9a300ecd708c45839305dc54d4..bd15152b366c5830305a6035d95308bb256940ae 100644 --- a/macro/MacroDriver.cc +++ b/macro/MacroDriver.cc @@ -37,10 +37,13 @@ MacroDriver::~MacroDriver() } void -MacroDriver::parse(const string &f, const string &modfiletxt, ostream &out, bool debug, bool no_line_macro, - map<string, string> defines, vector<string> path) +MacroDriver::parse(const string &f, const string &fb, const string &modfiletxt, + ostream &out, bool debug, bool no_line_macro_arg, map<string, string> defines, + vector<string> path) { file = f; + basename = fb; + no_line_macro = no_line_macro_arg; /* Copy the file into a stringstream, and add an extra end-of-line. This is a @@ -205,3 +208,27 @@ MacroDriver::error(const Macro::parser::location_type &l, const MacroValue *valu error(l, sval->value); } + +string +MacroDriver::printvars(const Macro::parser::location_type &l, const bool tostdout) const +{ + if (tostdout) + { + cout << "Macroprocessor: Printing macro variable values from " << file + << " at line " << l.begin.line << endl; + for (map<string, const MacroValue *>::const_iterator it = env.begin(); + it != env.end(); it++) + cout << " " << it->first << " = " << it->second->print() << endl; + cout << endl; + return ""; + } + + stringstream intomfile; + if (!no_line_macro) + intomfile << "@#line \"" << file << "\" " << l.begin.line << endl; + + for (map<string, const MacroValue *>::const_iterator it = env.begin(); + it != env.end(); it++) + intomfile<< "options_.macrovars_line_" << l.begin.line << "." << it->first << " = " << it->second->print() << ";" << endl; + return intomfile.str(); +} diff --git a/macro/MacroDriver.hh b/macro/MacroDriver.hh index c76947de228faadaac514920e6796e93a4069b33..53b1271d8193131a04c9ff261d0dde463ce2a171 100644 --- a/macro/MacroDriver.hh +++ b/macro/MacroDriver.hh @@ -182,12 +182,18 @@ public: //! Starts parsing a file, returns output in out /*! \param no_line_macro should we omit the @#line statements ? */ - void parse(const string &f, const string &modfiletxt, ostream &out, bool debug, bool no_line_macro, + void parse(const string &f, const string &fb, const string &modfiletxt, ostream &out, bool debug, bool no_line_macro_arg, map<string, string> defines, vector<string> path); //! Name of main file being parsed string file; + //! Basename of main file being parsed + string basename; + + //! Whether or not to print @#line + bool no_line_macro; + //! Reference to the lexer class MacroFlex *lexer; @@ -197,6 +203,9 @@ public: //! Error handler void error(const Macro::parser::location_type &l, const string &m) const; + //! Print variables + string printvars(const Macro::parser::location_type &l, const bool save) const; + //! Set a variable void set_variable(const string &name, const MacroValue *value); diff --git a/macro/MacroFlex.ll b/macro/MacroFlex.ll index 9c9bc66f79bc73b4f9df8d7d439ceb13a1dfa29c..5125ffa73906f12668b492ffd99f9b3915f41a72 100644 --- a/macro/MacroFlex.ll +++ b/macro/MacroFlex.ll @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2016 Dynare Team + * Copyright (C) 2008-2017 Dynare Team * * This file is part of Dynare. * @@ -236,6 +236,9 @@ CONT \\\\ <STMT>line { return token::LINE; } <STMT>define { return token::DEFINE; } +<STMT>echomacrovars { return token::ECHOMACROVARS; } +<STMT>save { return token::SAVE; } + <STMT>for { reading_for_statement = true; return token::FOR; } <STMT>endfor { driver.error(*yylloc, "@#endfor is not matched by a @#for statement"); } diff --git a/macro/MacroValue.cc b/macro/MacroValue.cc index b20beb5db8d00392f2a8192a17fd2f76c7b48af7..db8c8ac293979ecf87a9fdf16c3a4c8d680106d0 100644 --- a/macro/MacroValue.cc +++ b/macro/MacroValue.cc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2014 Dynare Team + * Copyright (C) 2008-2017 Dynare Team * * This file is part of Dynare. * @@ -280,6 +280,12 @@ IntMV::toString() const return ss.str(); } +string +IntMV::print() const +{ + return toString(); +} + const MacroValue * IntMV::toArray() const { @@ -398,6 +404,12 @@ StringMV::toString() const return value; } +string +StringMV::print() const +{ + return "'" + value + "'"; +} + const MacroValue * StringMV::toArray() const { diff --git a/macro/MacroValue.hh b/macro/MacroValue.hh index 1097841d9831f9e0c37b5c5e116c6bce691dfbe9..ced2918958ae30939f4514d81fe1666f401e05b1 100644 --- a/macro/MacroValue.hh +++ b/macro/MacroValue.hh @@ -23,6 +23,7 @@ #include <string> #include <vector> #include <sstream> +#include <boost/lexical_cast.hpp> using namespace std; @@ -91,6 +92,8 @@ public: virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError); //! Converts value to string virtual string toString() const = 0; + //! Converts value to be printed + virtual string print() const = 0; //! Converts value to array form virtual const MacroValue *toArray() const = 0; //! Gets length @@ -147,6 +150,7 @@ public: //! Computes logical negation virtual const MacroValue *operator!() const throw (TypeError); virtual string toString() const; + virtual string print() const; //! Converts value to array form /*! Returns an integer array containing a single value */ virtual const MacroValue *toArray() const; @@ -187,6 +191,7 @@ public: virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError); //! Returns underlying string value virtual string toString() const; + virtual string print() const; //! Converts value to array form /*! Returns a string array containing a single value */ virtual const MacroValue *toArray() const; @@ -226,6 +231,7 @@ public: virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError); //! Returns a string containing the concatenation of string representations of elements virtual string toString() const; + virtual string print() const; //! Returns itself virtual const MacroValue *toArray() const; //! Gets length @@ -335,6 +341,43 @@ ArrayMV<T>::toString() const return ss.str(); } +template<typename T> +string +ArrayMV<T>::print() const +{ + bool printStrArr = false; + try + { + typename vector<T>::const_iterator it = values.begin(); + boost::lexical_cast<int>(*it); + } + catch (boost::bad_lexical_cast &) + { + printStrArr= true; + } + ostringstream ss; + if (printStrArr) + ss << "{"; + else + ss << "["; + for (typename vector<T>::const_iterator it = values.begin(); + it != values.end(); it++) + { + if (it != values.begin()) + ss << ", "; + + if (printStrArr) + ss << "'" << *it << "'"; + else + ss << *it; + } + if (printStrArr) + ss << "}"; + else + ss << "]"; + return ss.str(); +} + template<typename T> const MacroValue * ArrayMV<T>::toArray() const