diff --git a/doc/dynare.texi b/doc/dynare.texi index 3daf01406..90d6e4ed4 100644 --- a/doc/dynare.texi +++ b/doc/dynare.texi @@ -1539,6 +1539,24 @@ a variable with a multiplicative trend). @end deffn +@anchor{model_local_variable} +@deffn Command model_local_variable @var{VARIABLE_NAME} [$@var{LATEX_NAME}$] @dots{}; + +@descriptionhead + +This optional command declares a model local variable. @xref{Conventions}, for +the syntax of @var{VARIABLE_NAME}. As you can create model local variables on +the fly in the model block (@pxref{model_local_variables_in_model_block}), the +interest of this command is primarily to assign a @var{LATEX_NAME} to the model +local variable. + +@examplehead + +@example +model_local_variable GDP_US $GDPUS$; +@end example + +@end deffn @node Expressions @section Expressions @@ -1918,16 +1936,19 @@ equation. A homogenous equation looks like: @var{MODEL_EXPRESSION}; @end example +@anchor{model_local_variables_in_model_block} Inside the model block, Dynare allows the creation of @emph{model-local -variables}, which constitute a simple way to share a common expression -between several equations. The syntax consists of a pound sign -(@code{#}) followed by the name of the new model local variable (which -must @strong{not} be declared as in @ref{Variable declarations}), an equal -sign, and the expression for which this new variable will stand. Later -on, every time this variable appears in the model, Dynare will -substitute it by the expression assigned to the variable. Note that the -scope of this variable is restricted to the model block; it cannot be -used outside. A model local variable declaration looks like: +variables}, which constitute a simple way to share a common expression between +several equations. The syntax consists of a pound sign (@code{#}) followed by +the name of the new model local variable (which must @strong{not} be declared +as in @ref{Variable declarations}, but may have been declared by +@ref{model_local_variable}), an equal sign, and the expression for which this +new variable will stand. Later on, every time this variable appears in the +model, Dynare will substitute it by the expression assigned to the +variable. Note that the scope of this variable is restricted to the model +block; it cannot be used outside. To assign a @LaTeX{} name to the model local +variable, use the declaration syntax outlined by @ref{model_local_variable}. A +model local variable declaration looks like: @example # @var{VARIABLE_NAME} = @var{MODEL_EXPRESSION}; @end example diff --git a/preprocessor/DataTree.cc b/preprocessor/DataTree.cc index e748e7598..dac7c157b 100644 --- a/preprocessor/DataTree.cc +++ b/preprocessor/DataTree.cc @@ -507,6 +507,7 @@ DataTree::AddLocalVariable(int symb_id, expr_t value) throw (LocalVariableExcept throw LocalVariableException(symbol_table.getName(symb_id)); local_variables_table[symb_id] = value; + local_variables_vector.push_back(symb_id); } expr_t diff --git a/preprocessor/DataTree.hh b/preprocessor/DataTree.hh index 5efb57bdb..26a438604 100644 --- a/preprocessor/DataTree.hh +++ b/preprocessor/DataTree.hh @@ -84,6 +84,8 @@ protected: //! Stores local variables value (maps symbol ID to corresponding node) map local_variables_table; + //! Stores the order of appearance of local variables in the model block. Needed following change in #563 + vector local_variables_vector; //! Internal implementation of AddVariable(), without the check on the lag VariableNode *AddVariableInternal(int symb_id, int lag); diff --git a/preprocessor/DynamicModel.cc b/preprocessor/DynamicModel.cc index 207066ebb..18024f2cf 100644 --- a/preprocessor/DynamicModel.cc +++ b/preprocessor/DynamicModel.cc @@ -3728,9 +3728,9 @@ DynamicModel::cloneDynamic(DynamicModel &dynamic_model) const assert(&symbol_table == &dynamic_model.symbol_table); // Convert model local variables (need to be done first) - for (map::const_iterator it = local_variables_table.begin(); - it != local_variables_table.end(); it++) - dynamic_model.AddLocalVariable(it->first, it->second->cloneDynamic(dynamic_model)); + for (vector::const_iterator it = local_variables_vector.begin(); + it != local_variables_vector.end(); it++) + dynamic_model.AddLocalVariable(*it, local_variables_table.find(*it)->second->cloneDynamic(dynamic_model)); // Convert equations for (size_t i = 0; i < equations.size(); i++) @@ -3853,9 +3853,9 @@ DynamicModel::toStatic(StaticModel &static_model) const assert(&symbol_table == &static_model.symbol_table); // Convert model local variables (need to be done first) - for (map::const_iterator it = local_variables_table.begin(); - it != local_variables_table.end(); it++) - static_model.AddLocalVariable(it->first, it->second->toStatic(static_model)); + for (vector::const_iterator it = local_variables_vector.begin(); + it != local_variables_vector.end(); it++) + static_model.AddLocalVariable(*it, local_variables_table.find(*it)->second->toStatic(static_model)); // Convert equations int static_only_index = 0; diff --git a/preprocessor/DynareBison.yy b/preprocessor/DynareBison.yy index b8a6107c3..52931d891 100644 --- a/preprocessor/DynareBison.yy +++ b/preprocessor/DynareBison.yy @@ -129,7 +129,7 @@ class ParsingDriver; %token TEX RAMSEY_MODEL RAMSEY_POLICY RAMSEY_CONSTRAINTS PLANNER_DISCOUNT DISCRETIONARY_POLICY DISCRETIONARY_TOL %token TEX_NAME %token UNIFORM_PDF UNIT_ROOT_VARS USE_DLL USEAUTOCORR GSA_SAMPLE_FILE USE_UNIVARIATE_FILTERS_IF_SINGULARITY_IS_DETECTED -%token VALUES VAR VAREXO VAREXO_DET VAROBS PREDETERMINED_VARIABLES PLOT_SHOCK_DECOMPOSITION +%token VALUES VAR VAREXO VAREXO_DET VAROBS PREDETERMINED_VARIABLES PLOT_SHOCK_DECOMPOSITION MODEL_LOCAL_VARIABLE %token WRITE_LATEX_DYNAMIC_MODEL WRITE_LATEX_STATIC_MODEL WRITE_LATEX_ORIGINAL_MODEL %token XLS_SHEET XLS_RANGE LMMCP OCCBIN BANDPASS_FILTER COLORMAP QOQ YOY AOA %left COMMA @@ -203,6 +203,7 @@ statement : parameters | varexo | varexo_det | predetermined_variables + | model_local_variable | change_type | periods | model @@ -381,6 +382,8 @@ predetermined_variables : PREDETERMINED_VARIABLES predetermined_variables_list ' parameters : PARAMETERS parameter_list ';'; +model_local_variable : MODEL_LOCAL_VARIABLE model_local_variable_list ';'; + named_var_elem : symbol EQUAL QUOTED_STRING { pair *pr = new pair($1, $3); @@ -525,6 +528,20 @@ predetermined_variables_list : predetermined_variables_list symbol { driver.add_predetermined_variable($1); } ; +model_local_variable_list : model_local_variable_list symbol + { driver.declare_model_local_variable($2); } + | model_local_variable_list COMMA symbol + { driver.declare_model_local_variable($3); } + | symbol + { driver.declare_model_local_variable($1); } + | model_local_variable_list symbol TEX_NAME + { driver.declare_model_local_variable($2, $3); } + | model_local_variable_list COMMA symbol TEX_NAME + { driver.declare_model_local_variable($3, $4); } + | symbol TEX_NAME + { driver.declare_model_local_variable($1, $2); } + ; + change_type : CHANGE_TYPE '(' change_type_arg ')' change_type_var_list ';' { driver.change_type($3, $5); } ; diff --git a/preprocessor/DynareFlex.ll b/preprocessor/DynareFlex.ll index 9553fab45..092d39d9b 100644 --- a/preprocessor/DynareFlex.ll +++ b/preprocessor/DynareFlex.ll @@ -111,6 +111,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 log_trend_var {BEGIN DYNARE_STATEMENT; return token::LOG_TREND_VAR;} predetermined_variables {BEGIN DYNARE_STATEMENT; return token::PREDETERMINED_VARIABLES;} parameters {BEGIN DYNARE_STATEMENT; return token::PARAMETERS;} +model_local_variable {BEGIN DYNARE_STATEMENT; return token::MODEL_LOCAL_VARIABLE;} periods {BEGIN DYNARE_STATEMENT; return token::PERIODS;} model_info {BEGIN DYNARE_STATEMENT; return token::MODEL_INFO;} estimation {BEGIN DYNARE_STATEMENT; return token::ESTIMATION;} diff --git a/preprocessor/ModelTree.cc b/preprocessor/ModelTree.cc index 61be06e4f..cb3523a62 100644 --- a/preprocessor/ModelTree.cc +++ b/preprocessor/ModelTree.cc @@ -1418,24 +1418,25 @@ ModelTree::writeModelLocalVariables(ostream &output, ExprNodeOutputType output_t for (size_t i = 0; i < equations.size(); i++) equations[i]->collectVariables(eModelLocalVariable, used_local_vars); - for (set::const_iterator it = used_local_vars.begin(); - it != used_local_vars.end(); ++it) - { - int id = *it; - expr_t value = local_variables_table.find(id)->second; - value->writeExternalFunctionOutput(output, output_type, tt, tef_terms); + for (vector::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; + value->writeExternalFunctionOutput(output, output_type, tt, tef_terms); - if (IS_C(output_type)) - output << "double "; - else if (IS_JULIA(output_type)) - output << " @inbounds "; + if (IS_C(output_type)) + output << "double "; + else if (IS_JULIA(output_type)) + output << " @inbounds "; - /* We append underscores to avoid name clashes with "g1" or "oo_" (see - also VariableNode::writeOutput) */ - output << symbol_table.getName(id) << "__ = "; - value->writeOutput(output, output_type, tt, tef_terms); - output << ";" << endl; - } + /* We append underscores to avoid name clashes with "g1" or "oo_" (see + also VariableNode::writeOutput) */ + output << symbol_table.getName(id) << "__ = "; + value->writeOutput(output, output_type, tt, tef_terms); + output << ";" << endl; + } } void @@ -1468,21 +1469,26 @@ ModelTree::writeJsonModelLocalVariables(ostream &output, deriv_node_temp_terms_t } output << "]" << ", \"model_local_variables\": ["; - for (set::const_iterator it = used_local_vars.begin(); - it != used_local_vars.end(); ++it) - { - if (it != used_local_vars.begin()) - output << ", "; - int id = *it; - expr_t value = local_variables_table.find(id)->second; + bool printed = false; + for (vector::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; - /* We append underscores to avoid name clashes with "g1" or "oo_" (see - also VariableNode::writeOutput) */ - output << "{\"variable\": \"" << symbol_table.getName(id) << "__\"" - << ", \"value\": \""; - value->writeJsonOutput(output, tt, tef_terms); - output << "\"}" << endl; - } + if (printed) + output << ", "; + else + printed = true; + + /* We append underscores to avoid name clashes with "g1" or "oo_" (see + also VariableNode::writeOutput) */ + output << "{\"variable\": \"" << symbol_table.getName(id) << "__\"" + << ", \"value\": \""; + value->writeJsonOutput(output, tt, tef_terms); + output << "\"}" << endl; + } output << "]"; } @@ -1660,11 +1666,11 @@ ModelTree::writeLatexModelFile(const string &basename, ExprNodeOutputType output << "\\footnotesize" << endl; // Write model local variables - for (map::const_iterator it = local_variables_table.begin(); - it != local_variables_table.end(); it++) + for (vector::const_iterator it = local_variables_vector.begin(); + it != local_variables_vector.end(); it++) { - int id = it->first; - expr_t value = it->second; + int id = *it; + expr_t value = local_variables_table.find(id)->second; content_output << "\\begin{dmath*}" << endl << symbol_table.getTeXName(id) << " = "; diff --git a/preprocessor/ParsingDriver.cc b/preprocessor/ParsingDriver.cc index b606365dc..f2615caee 100644 --- a/preprocessor/ParsingDriver.cc +++ b/preprocessor/ParsingDriver.cc @@ -2226,6 +2226,15 @@ ParsingDriver::add_model_equal_with_zero_rhs(expr_t arg) return add_model_equal(arg, model_tree->Zero); } +void +ParsingDriver::declare_model_local_variable(string *name, string *tex_name) +{ + declare_symbol(name, eModelLocalVariable, tex_name, NULL); + delete name; + if (tex_name != NULL) + delete tex_name; +} + void ParsingDriver::declare_and_init_model_local_variable(string *name, expr_t rhs) { diff --git a/preprocessor/ParsingDriver.hh b/preprocessor/ParsingDriver.hh index f7bb115b3..74ee8ff66 100644 --- a/preprocessor/ParsingDriver.hh +++ b/preprocessor/ParsingDriver.hh @@ -303,6 +303,8 @@ public: void declare_exogenous_det(string *name, string *tex_name = NULL, vector *> *partition_value = NULL); //! Declares a parameter void declare_parameter(string *name, string *tex_name = NULL, vector *> *partition_value = NULL); + //! Declares a model local variable + void declare_model_local_variable(string *name, string *tex_name = NULL); //! Declares a statement local variable void declare_statement_local_variable(string *name); //! Completes a subsample statement