introduce epilogue block

issue#70
Houtan Bastani 2018-09-03 17:16:28 +02:00
parent e3550a8fc0
commit 9f0c30740e
13 changed files with 383 additions and 17 deletions

View File

@ -152,7 +152,10 @@ enum class SymbolType
statementDeclaredVariable = 14, //!< Local variable assigned within a Statement (see subsample statement for example)
logTrend = 15, //!< Log-trend variable
unusedEndogenous = 16,
endogenousVAR = 17 //!< Variables declared in a var_model statement
endogenousVAR = 17, //!< Variables declared in a var_model statement
endogenousEpilogue = 18, //!< Endogenous Variables used in the epilogue block
exogenousEpilogue = 19, //!< Variables used in the epilogue block
parameterEpilogue = 20 //!< Variables used in the epilogue block
};
enum ExpressionType

View File

@ -27,7 +27,7 @@
#include "Statement.hh"
#include "StaticModel.hh"
#include "DynamicModel.hh"
#include "SteadyStateModel.hh"
#include "ModelEquationBlock.hh"
class SteadyStatement : public Statement
{

View File

@ -148,7 +148,7 @@ class ParsingDriver;
%token SBVAR TREND_VAR DEFLATOR GROWTH_FACTOR MS_IRF MS_VARIANCE_DECOMPOSITION GROWTH
%token MS_ESTIMATION MS_SIMULATION MS_COMPUTE_MDD MS_COMPUTE_PROBABILITIES MS_FORECAST
%token SVAR_IDENTIFICATION EQUATION EXCLUSION LAG UPPER_CHOLESKY LOWER_CHOLESKY MONTHLY QUARTERLY
%token MARKOV_SWITCHING CHAIN DURATION NUMBER_OF_REGIMES NUMBER_OF_LAGS
%token MARKOV_SWITCHING CHAIN DURATION NUMBER_OF_REGIMES NUMBER_OF_LAGS EPILOGUE
%token SVAR SVAR_GLOBAL_IDENTIFICATION_CHECK COEFF COEFFICIENTS VARIANCES CONSTANTS EQUATIONS
%token EXTERNAL_FUNCTION EXT_FUNC_NAME EXT_FUNC_NARGS FIRST_DERIV_PROVIDED SECOND_DERIV_PROVIDED
%token SELECTED_VARIABLES_ONLY COVA_COMPUTE SIMULATION_FILE_TAG FILE_TAG
@ -221,6 +221,7 @@ statement : parameters
| estimated_params_init
| set_time
| data
| epilogue
| var_model
| pac_model
| trend_component_model
@ -348,6 +349,7 @@ log_trend_var_list : log_trend_var_list symbol
;
var : VAR var_list ';'
| VAR '(' EPILOGUE ')' epilogue_var_list ';'
| VAR '(' DEFLATOR EQUAL { driver.begin_trend(); } hand_side ')' nonstationary_var_list ';'
{ driver.end_nonstationary_var(false, $6); }
| VAR '(' LOG_DEFLATOR EQUAL { driver.begin_trend(); } hand_side ')' nonstationary_var_list ';'
@ -537,13 +539,17 @@ nonstationary_var_list : nonstationary_var_list symbol
{ driver.declare_nonstationary_var($1, $2, $3); }
;
varexo : VAREXO varexo_list ';';
varexo : VAREXO varexo_list ';'
| VAREXO '(' EPILOGUE ')' epilogue_varexo_list ';'
;
varexo_det : VAREXO_DET varexo_det_list ';';
predetermined_variables : PREDETERMINED_VARIABLES predetermined_variables_list ';';
parameters : PARAMETERS parameter_list ';';
| PARAMETERS '(' EPILOGUE ')' epilogue_parameter_list ';';
;
model_local_variable : MODEL_LOCAL_VARIABLE model_local_variable_list ';';
@ -598,6 +604,32 @@ var_list : var_list symbol
{ driver.declare_endogenous($1, $2, $3); }
;
epilogue_var_list : epilogue_var_list symbol
{ driver.declare_epilogue_endogenous($2); }
| epilogue_var_list COMMA symbol
{ driver.declare_epilogue_endogenous($3); }
| symbol
{ driver.declare_epilogue_endogenous($1); }
| epilogue_var_list symbol named_var
{ driver.declare_epilogue_endogenous($2, "", $3); }
| epilogue_var_list COMMA symbol named_var
{ driver.declare_epilogue_endogenous($3, "", $4); }
| symbol named_var
{ driver.declare_epilogue_endogenous($1, "", $2); }
| epilogue_var_list symbol TEX_NAME
{ driver.declare_epilogue_endogenous($2, $3); }
| epilogue_var_list COMMA symbol TEX_NAME
{ driver.declare_epilogue_endogenous($3, $4); }
| symbol TEX_NAME
{ driver.declare_epilogue_endogenous($1, $2); }
| epilogue_var_list symbol TEX_NAME named_var
{ driver.declare_epilogue_endogenous($2, $3, $4); }
| epilogue_var_list COMMA symbol TEX_NAME named_var
{ driver.declare_epilogue_endogenous($3, $4, $5); }
| symbol TEX_NAME named_var
{ driver.declare_epilogue_endogenous($1, $2, $3); }
;
varexo_list : varexo_list symbol
{ driver.declare_exogenous($2); }
| varexo_list COMMA symbol
@ -650,6 +682,32 @@ varexo_det_list : varexo_det_list symbol
{ driver.declare_exogenous_det($1, $2, $3); }
;
epilogue_varexo_list : epilogue_varexo_list symbol
{ driver.declare_epilogue_exogenous($2); }
| epilogue_varexo_list COMMA symbol
{ driver.declare_epilogue_exogenous($3); }
| symbol
{ driver.declare_epilogue_exogenous($1); }
| epilogue_varexo_list symbol named_var
{ driver.declare_epilogue_exogenous($2, "", $3); }
| epilogue_varexo_list COMMA symbol named_var
{ driver.declare_epilogue_exogenous($3, "", $4); }
| symbol named_var
{ driver.declare_epilogue_exogenous($1, "", $2); }
| epilogue_varexo_list symbol TEX_NAME
{ driver.declare_epilogue_exogenous($2, $3); }
| epilogue_varexo_list COMMA symbol TEX_NAME
{ driver.declare_epilogue_exogenous($3, $4); }
| symbol TEX_NAME
{ driver.declare_epilogue_exogenous($1, $2); }
| epilogue_varexo_list symbol TEX_NAME named_var
{ driver.declare_epilogue_exogenous($2, $3, $4); }
| epilogue_varexo_list COMMA symbol TEX_NAME named_var
{ driver.declare_epilogue_exogenous($3, $4, $5); }
| symbol TEX_NAME named_var
{ driver.declare_epilogue_exogenous($1, $2, $3); }
;
parameter_list : parameter_list symbol
{ driver.declare_parameter($2); }
| parameter_list COMMA symbol
@ -676,6 +734,32 @@ parameter_list : parameter_list symbol
{ driver.declare_parameter($1, $2, $3); }
;
epilogue_parameter_list : epilogue_parameter_list symbol
{ driver.declare_parameter($2); }
| epilogue_parameter_list COMMA symbol
{ driver.declare_parameter($3); }
| symbol
{ driver.declare_parameter($1); }
| epilogue_parameter_list symbol named_var
{ driver.declare_parameter($2, "", $3); }
| epilogue_parameter_list COMMA symbol named_var
{ driver.declare_parameter($3, "", $4); }
| symbol named_var
{ driver.declare_parameter($1, "", $2); }
| epilogue_parameter_list symbol TEX_NAME
{ driver.declare_parameter($2, $3); }
| epilogue_parameter_list COMMA symbol TEX_NAME
{ driver.declare_parameter($3, $4); }
| symbol TEX_NAME
{ driver.declare_parameter($1, $2); }
| epilogue_parameter_list symbol TEX_NAME named_var
{ driver.declare_parameter($2, $3, $4); }
| epilogue_parameter_list COMMA symbol TEX_NAME named_var
{ driver.declare_parameter($3, $4, $5); }
| symbol TEX_NAME named_var
{ driver.declare_parameter($1, $2, $3); }
;
predetermined_variables_list : predetermined_variables_list symbol
{ driver.add_predetermined_variable($2); }
| predetermined_variables_list COMMA symbol
@ -864,6 +948,18 @@ histval_file : HISTVAL_FILE '(' FILENAME EQUAL filename ')' ';'
{ driver.histval_file($5); }
;
epilogue : EPILOGUE ';' { driver.begin_epilogue(); }
epilogue_equation_list END ';' { driver.end_epilogue(); }
;
epilogue_equation_list : epilogue_equation_list epilogue_equation
| epilogue_equation
;
epilogue_equation : symbol EQUAL expression ';'
{ driver.add_epilogue_equal($1, $3); }
;
model_options : BLOCK { driver.block(); }
| o_cutoff
| o_mfs

View File

@ -204,6 +204,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
<INITIAL>shock_groups {BEGIN DYNARE_BLOCK; return token::SHOCK_GROUPS;}
<INITIAL>mshocks {BEGIN DYNARE_BLOCK; return token::MSHOCKS;}
<INITIAL>estimated_params {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS;}
<INITIAL>epilogue {BEGIN DYNARE_BLOCK; return token::EPILOGUE;}
/* priors is an alias for estimated_params */
<INITIAL>priors {BEGIN DYNARE_BLOCK;return token::ESTIMATED_PARAMS;}
<INITIAL>estimated_params_init {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS_INIT;}
@ -629,6 +630,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
<DYNARE_STATEMENT>save_draws {return token::SAVE_DRAWS; }
<DYNARE_STATEMENT>deflator {return token::DEFLATOR;}
<DYNARE_STATEMENT>log_deflator {return token::LOG_DEFLATOR;}
<DYNARE_STATEMENT>epilogue {return token::EPILOGUE;}
<DYNARE_STATEMENT>growth_factor {return token::GROWTH_FACTOR;}
<DYNARE_STATEMENT>log_growth_factor {return token::LOG_GROWTH_FACTOR;}
<DYNARE_STATEMENT>growth {return token::GROWTH;}

View File

@ -748,6 +748,9 @@ VariableNode::prepareForDerivation()
break;
case SymbolType::externalFunction:
case SymbolType::endogenousVAR:
case SymbolType::endogenousEpilogue:
case SymbolType::exogenousEpilogue:
case SymbolType::parameterEpilogue:
cerr << "VariableNode::prepareForDerivation: impossible case" << endl;
exit(EXIT_FAILURE);
}
@ -781,7 +784,10 @@ VariableNode::computeDerivative(int deriv_id)
exit(EXIT_FAILURE);
case SymbolType::externalFunction:
case SymbolType::endogenousVAR:
cerr << "Impossible case!" << endl;
case SymbolType::endogenousEpilogue:
case SymbolType::exogenousEpilogue:
case SymbolType::parameterEpilogue:
cerr << "VariableNode::computeDerivative: Impossible case!" << endl;
exit(EXIT_FAILURE);
}
// Suppress GCC warning
@ -857,6 +863,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
switch (type)
{
case SymbolType::parameter:
case SymbolType::parameterEpilogue:
if (output_type == oMatlabOutsideModel)
output << "M_.params" << "(" << tsid + 1 << ")";
else
@ -927,6 +934,13 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
if (lag != 0)
output << LEFT_ARRAY_SUBSCRIPT(output_type) << lag << RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
case oEpilogueFile:
output << datatree.symbol_table.getName(symb_id)
<< LEFT_ARRAY_SUBSCRIPT(output_type) << "epilogue_it__";
if (lag != 0)
output << lag;
output << RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
default:
cerr << "VariableNode::writeOutput: should not reach this point" << endl;
exit(EXIT_FAILURE);
@ -980,6 +994,13 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
if (lag != 0)
output << LEFT_ARRAY_SUBSCRIPT(output_type) << lag << RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
case oEpilogueFile:
output << datatree.symbol_table.getName(symb_id)
<< LEFT_ARRAY_SUBSCRIPT(output_type) << "epilogue_it__";
if (lag != 0)
output << lag;
output << RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
default:
cerr << "VariableNode::writeOutput: should not reach this point" << endl;
exit(EXIT_FAILURE);
@ -1033,19 +1054,33 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
if (lag != 0)
output << LEFT_ARRAY_SUBSCRIPT(output_type) << lag << RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
case oEpilogueFile:
output << datatree.symbol_table.getName(symb_id)
<< LEFT_ARRAY_SUBSCRIPT(output_type) << "epilogue_it__";
if (lag != 0)
output << lag;
output << RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
default:
cerr << "VariableNode::writeOutput: should not reach this point" << endl;
exit(EXIT_FAILURE);
}
break;
case SymbolType::endogenousEpilogue:
case SymbolType::exogenousEpilogue:
output << datatree.symbol_table.getName(symb_id)
<< LEFT_ARRAY_SUBSCRIPT(output_type) << "epilogue_it__";
if (lag != 0)
output << lag;
output << RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
case SymbolType::externalFunction:
case SymbolType::trend:
case SymbolType::logTrend:
case SymbolType::statementDeclaredVariable:
case SymbolType::unusedEndogenous:
case SymbolType::endogenousVAR:
cerr << "Impossible case" << endl;
cerr << "VariableNode::writeOutput: Impossible case" << endl;
exit(EXIT_FAILURE);
}
}
@ -1264,7 +1299,10 @@ VariableNode::getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recur
exit(EXIT_FAILURE);
case SymbolType::externalFunction:
case SymbolType::endogenousVAR:
cerr << "Impossible case!" << endl;
case SymbolType::endogenousEpilogue:
case SymbolType::exogenousEpilogue:
case SymbolType::parameterEpilogue:
cerr << "VariableNode::getChainRuleDerivative: Impossible case" << endl;
exit(EXIT_FAILURE);
}
// Suppress GCC warning
@ -1302,6 +1340,9 @@ VariableNode::computeXrefs(EquationInfo &ei) const
case SymbolType::unusedEndogenous:
case SymbolType::externalFunction:
case SymbolType::endogenousVAR:
case SymbolType::endogenousEpilogue:
case SymbolType::exogenousEpilogue:
case SymbolType::parameterEpilogue:
break;
}
}
@ -6705,6 +6746,7 @@ AbstractExternalFunctionNode::getIndxInTefTerms(int the_symb_id, const deriv_nod
auto it = tef_terms.find({ the_symb_id, arguments });
if (it != tef_terms.end())
return it->second;
cout << endl << endl << tef_terms.size() << "." <<the_symb_id << endl << endl;
throw UnknownFunctionNameAndArgs();
}

View File

@ -87,7 +87,8 @@ enum ExprNodeOutputType
oJuliaDynamicSteadyStateOperator, //!< Julia code, dynamic model, inside a steady state operator
oSteadyStateFile, //!< Matlab code, in the generated steady state file
oJuliaSteadyStateFile, //!< Julia code, in the generated steady state file
oMatlabDseries //!< Matlab code for dseries
oMatlabDseries, //!< Matlab code for dseries
oEpilogueFile //!< Matlab code, in the generated epilogue file
};
#define IS_MATLAB(output_type) ((output_type) == oMatlabStaticModel \
@ -98,7 +99,8 @@ enum ExprNodeOutputType
|| (output_type) == oMatlabDynamicSteadyStateOperator \
|| (output_type) == oMatlabDynamicSparseSteadyStateOperator \
|| (output_type) == oSteadyStateFile \
|| (output_type) == oMatlabDseries)
|| (output_type) == oMatlabDseries \
|| (output_type) == oEpilogueFile)
#define IS_JULIA(output_type) ((output_type) == oJuliaStaticModel \
|| (output_type) == oJuliaDynamicModel \

View File

@ -48,8 +48,8 @@ dynare_m_SOURCES = \
CodeInterpreter.hh \
ExternalFunctionsTable.cc \
ExternalFunctionsTable.hh \
SteadyStateModel.hh \
SteadyStateModel.cc \
ModelEquationBlock.hh \
ModelEquationBlock.cc \
WarningConsolidation.hh \
WarningConsolidation.cc \
ExtendedPreprocessorTypes.hh \

View File

@ -44,6 +44,8 @@ ModFile::ModFile(WarningConsolidation &warnings_arg)
trend_component_model_table, var_model_table),
orig_ramsey_dynamic_model(symbol_table, num_constants, external_functions_table,
trend_component_model_table, var_model_table),
epilogue(symbol_table, num_constants, external_functions_table,
trend_component_model_table, var_model_table),
static_model(symbol_table, num_constants, external_functions_table,
trend_component_model_table, var_model_table),
steady_state_model(symbol_table, num_constants, external_functions_table,
@ -127,6 +129,9 @@ ModFile::checkPass(bool nostrict, bool stochastic)
// Check the steady state block
steady_state_model.checkPass(mod_file_struct, warnings);
// Check epilogue block
epilogue.checkPass(warnings);
if (mod_file_struct.write_latex_steady_state_model_present &&
!mod_file_struct.steady_state_model_present)
{
@ -767,6 +772,8 @@ ModFile::computingPass(bool no_tmp_terms, FileOutputType output, int params_deri
for (auto & statement : statements)
statement->computingPass();
epilogue.computingPass(true, true, false, 0, global_eval_context, true, false, false, false, true);
}
void
@ -1074,6 +1081,9 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
// Create steady state file
steady_state_model.writeSteadyStateFile(basename, mod_file_struct.ramsey_model_present, false);
// Create epilogue file
epilogue.writeEpilogueFile(basename);
}
if (!nopreprocessoroutput)

View File

@ -32,7 +32,7 @@ using namespace std;
#include "NumericalInitialization.hh"
#include "StaticModel.hh"
#include "DynamicModel.hh"
#include "SteadyStateModel.hh"
#include "ModelEquationBlock.hh"
#include "Statement.hh"
#include "ExternalFunctionsTable.hh"
#include "ConfigFile.hh"
@ -68,6 +68,8 @@ public:
DynamicModel ramsey_FOC_equations_dynamic_model;
//! A copy of the original model, used to test model linearity under ramsey problem
DynamicModel orig_ramsey_dynamic_model;
//! Epilogue model, as declared in the "epilogue" block
Epilogue epilogue;
//! Static model, as derived from the "model" block when leads and lags have been removed
StaticModel static_model;
//! Static model, as declared in the "steady_state_model" block if present

View File

@ -20,7 +20,7 @@
#include <cassert>
#include <algorithm>
#include "SteadyStateModel.hh"
#include "ModelEquationBlock.hh"
SteadyStateModel::SteadyStateModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
@ -269,3 +269,109 @@ SteadyStateModel::writeJsonSteadyStateFile(ostream &output, bool transformComput
output << "]}";
}
Epilogue::Epilogue(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg,
TrendComponentModelTable &trend_component_model_table_arg,
VarModelTable &var_model_table_arg) :
DynamicModel(symbol_table_arg, num_constants_arg, external_functions_table_arg,
trend_component_model_table_arg, var_model_table_arg)
{
}
void
Epilogue::addDefinition(int symb_id, expr_t expr)
{
AddVariable(symb_id); // Create the variable node to be used in write method
def_table.emplace_back(symb_id, expr);
endogs.emplace(symb_id);
expr->collectVariables(SymbolType::endogenous, exogs);
expr->collectVariables(SymbolType::exogenous, exogs);
expr->collectVariables(SymbolType::endogenousEpilogue, exogs);
expr->collectVariables(SymbolType::exogenousEpilogue, exogs);
for (auto it : endogs)
exogs.erase(it);
}
void
Epilogue::checkPass(WarningConsolidation &warnings) const
{
if (def_table.size() == 0)
return;
vector<int> so_far_defined;
for (const auto & it : def_table)
{
if (find(so_far_defined.begin(), so_far_defined.end(), it.first) != so_far_defined.end())
{
cerr << "WARNING: in the 'epilogue' block, variable '" << symbol_table.getName(it.first)
<< "' is declared twice" << endl;
exit(EXIT_FAILURE);
}
so_far_defined.push_back(it.first);
}
}
void
Epilogue::writeEpilogueFile(const string &basename) const
{
if (def_table.size() == 0)
return;
string filename = packageDir(basename) + "/epilogue.m";
ofstream output;
output.open(filename, ios::out | ios::binary);
if (!output.is_open())
{
cerr << "ERROR: Can't open file " << filename << " for writing" << endl;
exit(EXIT_FAILURE);
}
ExprNodeOutputType output_type = oEpilogueFile;
output << "function ds = epilogue(params, ds)" << endl
<< "% function ds = epilogue(params, ds)" << endl
<< "% Epilogue file generated by Dynare preprocessor" << endl << endl
<< "epilogue_ds_first_date__ = ds.firstdate;" << endl
<< "epilogue_loop_begin_idx__ = lastdate(ds) - ds.lastobservedperiod;" << endl
<< "epilogue_loop_end_idx__ = lastdate(ds) - firstdate(ds) + 1;" << endl << endl;
output << "% endogenous" << endl;
for (auto symb_id : endogs)
output << symbol_table.getName(symb_id) << " = ds." << symbol_table.getName(symb_id) << ".data;" << endl;
output << endl
<< "% exogenous" << endl;
for (auto symb_id : exogs)
output << symbol_table.getName(symb_id) << " = ds." << symbol_table.getName(symb_id) << ".data;" << endl;
output << endl
<< "for epilogue_it__ = epilogue_loop_begin_idx__::epilogue_loop_end_idx__" << endl;
deriv_node_temp_terms_t tef_terms;
temporary_terms_t temporary_terms;
temporary_terms_idxs_t temporary_terms_idxs;
for (const auto & it : def_table)
if (it.second->containsExternalFunction())
{
output << " ";
it.second->writeExternalFunctionOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
}
output << endl;
for (const auto & it : def_table)
{
auto node = variable_node_map.find({ it.first, 0 });
assert(node != variable_node_map.end());
output << " ";
dynamic_cast<ExprNode *>(node->second)->writeOutput(output, output_type);
output << " = ";
it.second->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ";" << endl;
}
output << "end" << endl << endl;
for (auto symb_id : endogs)
output << "ds." << symbol_table.getName(symb_id) << " = dseries(" << symbol_table.getName(symb_id)
<< ", epilogue_ds_first_date__);" << endl;
output << endl
<< "end" << endl;
output.close();
}

View File

@ -23,6 +23,7 @@
#include "DataTree.hh"
#include "Statement.hh"
#include "StaticModel.hh"
#include "DynamicModel.hh"
#include "WarningConsolidation.hh"
class SteadyStateModel : public DataTree
@ -61,4 +62,31 @@ public:
void writeJsonSteadyStateFile(ostream &output, bool transformComputingPass) const;
};
class Epilogue : public DynamicModel
{
private:
//! Associates a set of symbol IDs (the variable(s) assigned in a given statement) to an expression (their assigned value)
vector<pair<int, expr_t>> def_table;
//! List of variables found in block
set<int> endogs;
set<int> exogs;
public:
Epilogue(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg,
TrendComponentModelTable &trend_component_model_table_arg,
VarModelTable &var_model_table_arg);
//! Add an expression of the form "var = expr;"
void addDefinition(int symb_id, expr_t expr);
//! Checks that no variable is declared twice
void checkPass(WarningConsolidation &warnings) const;
//! Write the steady state file
void writeEpilogueFile(const string &basename) const;
};
#endif

View File

@ -201,6 +201,14 @@ ParsingDriver::declare_endogenous(const string &name, const string &tex_name, co
declare_symbol(name, SymbolType::endogenous, tex_name, partition_value);
}
void
ParsingDriver::declare_epilogue_endogenous(const string &name,
const string &tex_name,
const vector<pair<string, string>> &partition_value)
{
declare_symbol(name, SymbolType::endogenousEpilogue, tex_name, partition_value);
}
void
ParsingDriver::declare_var_endogenous(const string &name)
{
@ -230,12 +238,28 @@ ParsingDriver::declare_exogenous_det(const string &name, const string &tex_name,
declare_symbol(name, SymbolType::exogenousDet, tex_name, partition_value);
}
void
ParsingDriver::declare_epilogue_exogenous(const string &name,
const string &tex_name,
const vector<pair<string, string>> &partition_value)
{
declare_symbol(name, SymbolType::exogenousEpilogue, tex_name, partition_value);
}
void
ParsingDriver::declare_parameter(const string &name, const string &tex_name, const vector<pair<string, string>> &partition_value)
{
declare_symbol(name, SymbolType::parameter, tex_name, partition_value);
}
void
ParsingDriver::declare_epilogue_parameter(const string &name,
const string &tex_name,
const vector<pair<string, string>> &partition_value)
{
declare_symbol(name, SymbolType::parameterEpilogue, tex_name, partition_value);
}
void
ParsingDriver::declare_statement_local_variable(const string &name)
{
@ -414,6 +438,9 @@ ParsingDriver::add_model_variable(int symb_id, int lag)
expr_t
ParsingDriver::add_expression_variable(const string &name)
{
if (parsing_epilogue && !mod_file->symbol_table.exists(name))
error("Variable " + name + " used in the epilogue block but was not declared.");
// If symbol doesn't exist, then declare it as a mod file local variable
if (!mod_file->symbol_table.exists(name))
mod_file->symbol_table.addSymbol(name, SymbolType::modFileLocalVariable);
@ -817,6 +844,35 @@ ParsingDriver::end_homotopy()
homotopy_values.clear();
}
void
ParsingDriver::begin_epilogue()
{
parsing_epilogue = true;
set_current_data_tree(&mod_file->epilogue);
}
void
ParsingDriver::end_epilogue()
{
parsing_epilogue = false;
reset_data_tree();
}
void
ParsingDriver::add_epilogue_equal(const string &varname, expr_t expr)
{
int id;
try
{
id = mod_file->symbol_table.getID(varname);
}
catch (SymbolTable::UnknownSymbolNameException &e)
{
error("Variable " + varname + " used in the epilogue block but was not declared.");
}
mod_file->epilogue.addDefinition(id, expr);
}
void
ParsingDriver::begin_model()
{
@ -2887,7 +2943,7 @@ ParsingDriver::add_model_var_or_external_function(const string &function_name, b
expr_t nid;
if (mod_file->symbol_table.exists(function_name))
if (mod_file->symbol_table.getType(function_name) != SymbolType::externalFunction)
if (!in_model_block)
if (!in_model_block && !parsing_epilogue)
{
if (stack_external_function_args.top().size() > 0)
error(string("Symbol ") + function_name + string(" cannot take arguments."));
@ -2915,7 +2971,7 @@ ParsingDriver::add_model_var_or_external_function(const string &function_name, b
if (!mod_file->external_functions_table.exists(symb_id))
error("Using a derivative of an external function (" + function_name + ") in the model block is currently not allowed.");
if (in_model_block)
if (in_model_block || parsing_epilogue)
if (mod_file->external_functions_table.getNargs(symb_id) == eExtFunNotSet)
error("Before using " + function_name
+"() in the model block, you must first declare it via the external_function() statement");
@ -2925,6 +2981,9 @@ ParsingDriver::add_model_var_or_external_function(const string &function_name, b
}
else
{ //First time encountering this external function i.e., not previously declared or encountered
if (parsing_epilogue)
error("Variable " + function_name + " used in the epilogue block but was not declared.");
if (in_model_block)
{
// Continue processing, noting that it was not declared

View File

@ -259,8 +259,12 @@ private:
//! Used by VAR restrictions
void clear_VAR_storage();
//! True when parsing the epilogue block
bool parsing_epilogue;
public:
ParsingDriver(WarningConsolidation &warnings_arg, bool nostrict_arg) : warnings(warnings_arg), nostrict(nostrict_arg) { };
ParsingDriver(WarningConsolidation &warnings_arg, bool nostrict_arg) :
warnings(warnings_arg), nostrict(nostrict_arg), parsing_epilogue(false) { };
//! Starts parsing, and constructs the MOD file representation
unique_ptr<ModFile> parse(istream &in, bool debug);
@ -335,12 +339,18 @@ public:
void initval_file(const string &filename);
//! Declares an endogenous variable
void declare_endogenous(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
//! Declares an endogenous variable in the epilogue block
void declare_epilogue_endogenous(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
//! Declares an exogenous variable
void declare_exogenous(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
//! Declares an exogenous variable in the epilogue block
void declare_epilogue_exogenous(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
//! Declares an exogenous deterministic variable
void declare_exogenous_det(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
//! Declares a parameter
void declare_parameter(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
//! Declare a parameter in the epilogue block
void declare_epilogue_parameter(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
//! Declares a VAR variable and adds to symbol_list
void declare_var_endogenous(const string &name);
//! Declares a model local variable
@ -402,6 +412,12 @@ public:
void end_histval(bool all_values_required);
//! Writes end of an homotopy_setup block
void end_homotopy();
//! Begin epilogue block
void begin_epilogue();
//! Endepilogue block
void end_epilogue();
//! Add equation in epilogue block
void add_epilogue_equal(const string &varname, expr_t expr);
//! Begin a model block
void begin_model();
//! End a model block, printing errors that were encountered in parsing