Use `if` statements with initializers allowed by C++17

issue#70
Houtan Bastani 2019-10-28 11:09:36 +01:00
parent 361e99bee5
commit 217dadabbd
No known key found for this signature in database
GPG Key ID: 000094FB955BE169
5 changed files with 186 additions and 270 deletions

View File

@ -239,8 +239,8 @@ DynamicModel::operator=(const DynamicModel &m)
void void
DynamicModel::compileDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int symb_id, int lag, const map_idx_t &map_idx) const DynamicModel::compileDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int symb_id, int lag, const map_idx_t &map_idx) const
{ {
auto it = derivatives[1].find({ eq, getDerivID(symbol_table.getID(SymbolType::endogenous, symb_id), lag) }); if (auto it = derivatives[1].find({ eq, getDerivID(symbol_table.getID(SymbolType::endogenous, symb_id), lag) });
if (it != derivatives[1].end()) it != derivatives[1].end())
(it->second)->compile(code_file, instruction_number, false, temporary_terms, map_idx, true, false); (it->second)->compile(code_file, instruction_number, false, temporary_terms, map_idx, true, false);
else else
{ {
@ -252,8 +252,7 @@ DynamicModel::compileDerivative(ofstream &code_file, unsigned int &instruction_n
void void
DynamicModel::compileChainRuleDerivative(ofstream &code_file, unsigned int &instruction_number, int eqr, int varr, int lag, const map_idx_t &map_idx) const DynamicModel::compileChainRuleDerivative(ofstream &code_file, unsigned int &instruction_number, int eqr, int varr, int lag, const map_idx_t &map_idx) const
{ {
auto it = first_chain_rule_derivatives.find({ eqr, varr, lag }); if (auto it = first_chain_rule_derivatives.find({ eqr, varr, lag }); it != first_chain_rule_derivatives.end())
if (it != first_chain_rule_derivatives.end())
(it->second)->compile(code_file, instruction_number, false, temporary_terms, map_idx, true, false); (it->second)->compile(code_file, instruction_number, false, temporary_terms, map_idx, true, false);
else else
{ {

View File

@ -39,13 +39,11 @@ ExprNode::getDerivative(int deriv_id)
prepareForDerivation(); prepareForDerivation();
// Return zero if derivative is necessarily null (using symbolic a priori) // Return zero if derivative is necessarily null (using symbolic a priori)
auto it = non_null_derivatives.find(deriv_id); if (auto it = non_null_derivatives.find(deriv_id); it == non_null_derivatives.end())
if (it == non_null_derivatives.end())
return datatree.Zero; return datatree.Zero;
// If derivative is stored in cache, use the cached value, otherwise compute it (and cache it) // If derivative is stored in cache, use the cached value, otherwise compute it (and cache it)
map<int, expr_t>::const_iterator it2 = derivatives.find(deriv_id); if (auto it2 = derivatives.find(deriv_id); it2 != derivatives.end())
if (it2 != derivatives.end())
return it2->second; return it2->second;
else else
{ {
@ -95,8 +93,7 @@ ExprNode::checkIfTemporaryTermThenWrite(ostream &output, ExprNodeOutputType outp
const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs) const const temporary_terms_idxs_t &temporary_terms_idxs) const
{ {
auto it = temporary_terms.find(const_cast<ExprNode *>(this)); if (auto it = temporary_terms.find(const_cast<ExprNode *>(this)); it == temporary_terms.end())
if (it == temporary_terms.end())
return false; return false;
if (output_type == ExprNodeOutputType::matlabDynamicModelSparse) if (output_type == ExprNodeOutputType::matlabDynamicModelSparse)
@ -252,8 +249,7 @@ ExprNode::createEndoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector
while (lag >= 0) while (lag >= 0)
{ {
expr_t orig_expr = decreaseLeadsLags(lag); expr_t orig_expr = decreaseLeadsLags(lag);
it = subst_table.find(orig_expr); if (it = subst_table.find(orig_expr); it == subst_table.end())
if (it == subst_table.end())
{ {
int symb_id = datatree.symbol_table.addEndoLeadAuxiliaryVar(orig_expr->idx, substexpr); int symb_id = datatree.symbol_table.addEndoLeadAuxiliaryVar(orig_expr->idx, substexpr);
neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(datatree.AddVariable(symb_id, 0), substexpr))); neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(datatree.AddVariable(symb_id, 0), substexpr)));
@ -288,8 +284,7 @@ ExprNode::createExoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<
while (lag >= 0) while (lag >= 0)
{ {
expr_t orig_expr = decreaseLeadsLags(lag); expr_t orig_expr = decreaseLeadsLags(lag);
it = subst_table.find(orig_expr); if (it = subst_table.find(orig_expr); it == subst_table.end())
if (it == subst_table.end())
{ {
int symb_id = datatree.symbol_table.addExoLeadAuxiliaryVar(orig_expr->idx, substexpr); int symb_id = datatree.symbol_table.addExoLeadAuxiliaryVar(orig_expr->idx, substexpr);
neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(datatree.AddVariable(symb_id, 0), substexpr))); neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(datatree.AddVariable(symb_id, 0), substexpr)));
@ -408,8 +403,7 @@ ExprNode::fillErrorCorrectionRow(int eqn,
expr_t e = datatree.AddTimes(datatree.AddVariable(m.first), datatree.AddPossiblyNegativeConstant(-constant)); expr_t e = datatree.AddTimes(datatree.AddVariable(m.first), datatree.AddPossiblyNegativeConstant(-constant));
if (param_id != -1) if (param_id != -1)
e = datatree.AddTimes(e, datatree.AddVariable(param_id)); e = datatree.AddTimes(e, datatree.AddVariable(param_id));
auto coor = tuple(eqn, -orig_lag, colidx); if (auto coor = tuple(eqn, -orig_lag, colidx); A0star.find(coor) == A0star.end())
if (A0star.find(coor) == A0star.end())
A0star[coor] = e; A0star[coor] = e;
else else
A0star[coor] = datatree.AddPlus(e, A0star[coor]); A0star[coor] = datatree.AddPlus(e, A0star[coor]);
@ -464,8 +458,7 @@ void
NumConstNode::writeJsonAST(ostream &output) const NumConstNode::writeJsonAST(ostream &output) const
{ {
output << R"({"node_type" : "NumConstNode", "value" : )"; output << R"({"node_type" : "NumConstNode", "value" : )";
double testval = datatree.num_constants.getDouble(id); if (double testval = datatree.num_constants.getDouble(id); testval < 1.0 && testval > -1.0 && testval != 0.0)
if (testval < 1.0 && testval > -1.0 && testval != 0.0)
output << "0"; output << "0";
output << datatree.num_constants.get(id) << "}"; output << datatree.num_constants.get(id) << "}";
} }
@ -888,8 +881,7 @@ VariableNode::computeDerivative(int deriv_id)
void void
VariableNode::collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const VariableNode::collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const
{ {
auto it = temporary_terms.find(const_cast<VariableNode *>(this)); if (temporary_terms.find(const_cast<VariableNode *>(this)) != temporary_terms.end())
if (it != temporary_terms.end())
temporary_terms_inuse.insert(idx); temporary_terms_inuse.insert(idx);
if (get_type() == SymbolType::modelLocalVariable) if (get_type() == SymbolType::modelLocalVariable)
datatree.getLocalVariable(symb_id)->collectTemporary_terms(temporary_terms, temporary_terms_inuse, Curr_Block); datatree.getLocalVariable(symb_id)->collectTemporary_terms(temporary_terms, temporary_terms_inuse, Curr_Block);
@ -1000,8 +992,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
} }
int i; int i;
int tsid = datatree.symbol_table.getTypeSpecificID(symb_id); switch (int tsid = datatree.symbol_table.getTypeSpecificID(symb_id); type)
switch (type)
{ {
case SymbolType::parameter: case SymbolType::parameter:
if (output_type == ExprNodeOutputType::matlabOutsideModel) if (output_type == ExprNodeOutputType::matlabOutsideModel)
@ -1733,7 +1724,6 @@ VariableNode::decreaseLeadsLagsPredeterminedVariables() const
expr_t expr_t
VariableNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const VariableNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const
{ {
expr_t value;
switch (get_type()) switch (get_type())
{ {
case SymbolType::endogenous: case SymbolType::endogenous:
@ -1742,8 +1732,7 @@ VariableNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vecto
else else
return createEndoLeadAuxiliaryVarForMyself(subst_table, neweqs); return createEndoLeadAuxiliaryVarForMyself(subst_table, neweqs);
case SymbolType::modelLocalVariable: case SymbolType::modelLocalVariable:
value = datatree.getLocalVariable(symb_id); if (expr_t value = datatree.getLocalVariable(symb_id); value->maxEndoLead() <= 1)
if (value->maxEndoLead() <= 1)
return const_cast<VariableNode *>(this); return const_cast<VariableNode *>(this);
else else
return value->substituteEndoLeadGreaterThanTwo(subst_table, neweqs, deterministic_model); return value->substituteEndoLeadGreaterThanTwo(subst_table, neweqs, deterministic_model);
@ -1756,8 +1745,6 @@ expr_t
VariableNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const VariableNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{ {
VariableNode *substexpr; VariableNode *substexpr;
expr_t value;
subst_table_t::const_iterator it;
int cur_lag; int cur_lag;
switch (get_type()) switch (get_type())
{ {
@ -1765,8 +1752,7 @@ VariableNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector
if (lag >= -1) if (lag >= -1)
return const_cast<VariableNode *>(this); return const_cast<VariableNode *>(this);
it = subst_table.find(this); if (auto it = subst_table.find(this); it != subst_table.end())
if (it != subst_table.end())
return const_cast<VariableNode *>(it->second); return const_cast<VariableNode *>(it->second);
substexpr = datatree.AddVariable(symb_id, -1); substexpr = datatree.AddVariable(symb_id, -1);
@ -1777,8 +1763,7 @@ VariableNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector
while (cur_lag >= lag) while (cur_lag >= lag)
{ {
VariableNode *orig_expr = datatree.AddVariable(symb_id, cur_lag); VariableNode *orig_expr = datatree.AddVariable(symb_id, cur_lag);
it = subst_table.find(orig_expr); if (auto it = subst_table.find(orig_expr); it == subst_table.end())
if (it == subst_table.end())
{ {
int aux_symb_id = datatree.symbol_table.addEndoLagAuxiliaryVar(symb_id, cur_lag+1, substexpr); int aux_symb_id = datatree.symbol_table.addEndoLagAuxiliaryVar(symb_id, cur_lag+1, substexpr);
neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(datatree.AddVariable(aux_symb_id, 0), substexpr))); neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(datatree.AddVariable(aux_symb_id, 0), substexpr)));
@ -1793,8 +1778,7 @@ VariableNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector
return substexpr; return substexpr;
case SymbolType::modelLocalVariable: case SymbolType::modelLocalVariable:
value = datatree.getLocalVariable(symb_id); if (expr_t value = datatree.getLocalVariable(symb_id); value->maxEndoLag() <= 1)
if (value->maxEndoLag() <= 1)
return const_cast<VariableNode *>(this); return const_cast<VariableNode *>(this);
else else
return value->substituteEndoLagGreaterThanTwo(subst_table, neweqs); return value->substituteEndoLagGreaterThanTwo(subst_table, neweqs);
@ -1806,7 +1790,6 @@ VariableNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector
expr_t expr_t
VariableNode::substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const VariableNode::substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const
{ {
expr_t value;
switch (get_type()) switch (get_type())
{ {
case SymbolType::exogenous: case SymbolType::exogenous:
@ -1815,8 +1798,7 @@ VariableNode::substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode
else else
return createExoLeadAuxiliaryVarForMyself(subst_table, neweqs); return createExoLeadAuxiliaryVarForMyself(subst_table, neweqs);
case SymbolType::modelLocalVariable: case SymbolType::modelLocalVariable:
value = datatree.getLocalVariable(symb_id); if (expr_t value = datatree.getLocalVariable(symb_id); value->maxExoLead() == 0)
if (value->maxExoLead() == 0)
return const_cast<VariableNode *>(this); return const_cast<VariableNode *>(this);
else else
return value->substituteExoLead(subst_table, neweqs, deterministic_model); return value->substituteExoLead(subst_table, neweqs, deterministic_model);
@ -1829,8 +1811,6 @@ expr_t
VariableNode::substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const VariableNode::substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{ {
VariableNode *substexpr; VariableNode *substexpr;
expr_t value;
subst_table_t::const_iterator it;
int cur_lag; int cur_lag;
switch (get_type()) switch (get_type())
{ {
@ -1838,8 +1818,7 @@ VariableNode::substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *
if (lag >= 0) if (lag >= 0)
return const_cast<VariableNode *>(this); return const_cast<VariableNode *>(this);
it = subst_table.find(this); if (auto it = subst_table.find(this); it != subst_table.end())
if (it != subst_table.end())
return const_cast<VariableNode *>(it->second); return const_cast<VariableNode *>(it->second);
substexpr = datatree.AddVariable(symb_id, 0); substexpr = datatree.AddVariable(symb_id, 0);
@ -1850,8 +1829,7 @@ VariableNode::substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *
while (cur_lag >= lag) while (cur_lag >= lag)
{ {
VariableNode *orig_expr = datatree.AddVariable(symb_id, cur_lag); VariableNode *orig_expr = datatree.AddVariable(symb_id, cur_lag);
it = subst_table.find(orig_expr); if (auto it = subst_table.find(orig_expr); it == subst_table.end())
if (it == subst_table.end())
{ {
int aux_symb_id = datatree.symbol_table.addExoLagAuxiliaryVar(symb_id, cur_lag+1, substexpr); int aux_symb_id = datatree.symbol_table.addExoLagAuxiliaryVar(symb_id, cur_lag+1, substexpr);
neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(datatree.AddVariable(aux_symb_id, 0), substexpr))); neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(datatree.AddVariable(aux_symb_id, 0), substexpr)));
@ -1866,8 +1844,7 @@ VariableNode::substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *
return substexpr; return substexpr;
case SymbolType::modelLocalVariable: case SymbolType::modelLocalVariable:
value = datatree.getLocalVariable(symb_id); if (expr_t value = datatree.getLocalVariable(symb_id); value->maxExoLag() == 0)
if (value->maxExoLag() == 0)
return const_cast<VariableNode *>(this); return const_cast<VariableNode *>(this);
else else
return value->substituteExoLag(subst_table, neweqs); return value->substituteExoLag(subst_table, neweqs);
@ -1885,7 +1862,6 @@ VariableNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpN
expr_t expr_t
VariableNode::differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const VariableNode::differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{ {
expr_t value;
switch (get_type()) switch (get_type())
{ {
case SymbolType::endogenous: case SymbolType::endogenous:
@ -1896,9 +1872,8 @@ VariableNode::differentiateForwardVars(const vector<string> &subset, subst_table
return const_cast<VariableNode *>(this); return const_cast<VariableNode *>(this);
else else
{ {
auto it = subst_table.find(this);
VariableNode *diffvar; VariableNode *diffvar;
if (it != subst_table.end()) if (auto it = subst_table.find(this); it != subst_table.end())
diffvar = const_cast<VariableNode *>(it->second); diffvar = const_cast<VariableNode *>(it->second);
else else
{ {
@ -1912,8 +1887,7 @@ VariableNode::differentiateForwardVars(const vector<string> &subset, subst_table
return datatree.AddPlus(datatree.AddVariable(symb_id, 0), diffvar); return datatree.AddPlus(datatree.AddVariable(symb_id, 0), diffvar);
} }
case SymbolType::modelLocalVariable: case SymbolType::modelLocalVariable:
value = datatree.getLocalVariable(symb_id); if (expr_t value = datatree.getLocalVariable(symb_id); value->maxEndoLead() <= 0)
if (value->maxEndoLead() <= 0)
return const_cast<VariableNode *>(this); return const_cast<VariableNode *>(this);
else else
return value->differentiateForwardVars(subset, subst_table, neweqs); return value->differentiateForwardVars(subset, subst_table, neweqs);
@ -2063,9 +2037,9 @@ VariableNode::isVarModelReferenced(const string &model_info_name) const
void void
VariableNode::getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const VariableNode::getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const
{ {
string varname = datatree.symbol_table.getName(symb_id);
if (get_type() == SymbolType::endogenous) if (get_type() == SymbolType::endogenous)
if (model_endos_and_lags.find(varname) == model_endos_and_lags.end()) if (string varname = datatree.symbol_table.getName(symb_id);
model_endos_and_lags.find(varname) == model_endos_and_lags.end())
model_endos_and_lags[varname] = min(model_endos_and_lags[varname], lag); model_endos_and_lags[varname] = min(model_endos_and_lags[varname], lag);
else else
model_endos_and_lags[varname] = lag; model_endos_and_lags[varname] = lag;
@ -2398,7 +2372,6 @@ UnaryOpNode::computeTemporaryTerms(const pair<int, int> &derivOrder,
bool is_matlab) const bool is_matlab) const
{ {
expr_t this2 = const_cast<UnaryOpNode *>(this); expr_t this2 = const_cast<UnaryOpNode *>(this);
auto it = reference_count.find(this2); auto it = reference_count.find(this2);
if (it == reference_count.end()) if (it == reference_count.end())
{ {
@ -3763,8 +3736,7 @@ UnaryOpNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNo
{ {
if (op_code == UnaryOpcode::expectation) if (op_code == UnaryOpcode::expectation)
{ {
auto it = subst_table.find(const_cast<UnaryOpNode *>(this)); if (auto it = subst_table.find(const_cast<UnaryOpNode *>(this)); it != subst_table.end())
if (it != subst_table.end())
return const_cast<VariableNode *>(it->second); return const_cast<VariableNode *>(it->second);
//Arriving here, we need to create an auxiliary variable for this Expectation Operator: //Arriving here, we need to create an auxiliary variable for this Expectation Operator:
@ -4525,8 +4497,8 @@ BinaryOpNode::writeJsonOutput(ostream &output,
// If left argument has a lower precedence, or if current and left argument are both power operators, // If left argument has a lower precedence, or if current and left argument are both power operators,
// add parenthesis around left argument // add parenthesis around left argument
auto *barg1 = dynamic_cast<BinaryOpNode *>(arg1); if (auto *barg1 = dynamic_cast<BinaryOpNode *>(arg1);
if (arg1->precedenceJson(temporary_terms) < prec arg1->precedenceJson(temporary_terms) < prec
|| (op_code == BinaryOpcode::power && barg1 != nullptr && barg1->op_code == BinaryOpcode::power)) || (op_code == BinaryOpcode::power && barg1 != nullptr && barg1->op_code == BinaryOpcode::power))
{ {
output << "("; output << "(";
@ -4590,8 +4562,7 @@ BinaryOpNode::writeJsonOutput(ostream &output,
- it is a minus operator with same precedence than current operator - it is a minus operator with same precedence than current operator
- it is a divide operator with same precedence than current operator */ - it is a divide operator with same precedence than current operator */
auto *barg2 = dynamic_cast<BinaryOpNode *>(arg2); auto *barg2 = dynamic_cast<BinaryOpNode *>(arg2);
int arg2_prec = arg2->precedenceJson(temporary_terms); if (int arg2_prec = arg2->precedenceJson(temporary_terms); arg2_prec < prec
if (arg2_prec < prec
|| (op_code == BinaryOpcode::power && barg2 != nullptr && barg2->op_code == BinaryOpcode::power) || (op_code == BinaryOpcode::power && barg2 != nullptr && barg2->op_code == BinaryOpcode::power)
|| (op_code == BinaryOpcode::minus && arg2_prec == prec) || (op_code == BinaryOpcode::minus && arg2_prec == prec)
|| (op_code == BinaryOpcode::divide && arg2_prec == prec)) || (op_code == BinaryOpcode::divide && arg2_prec == prec))
@ -4759,8 +4730,7 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
- it is a minus operator with same precedence than current operator - it is a minus operator with same precedence than current operator
- it is a divide operator with same precedence than current operator */ - it is a divide operator with same precedence than current operator */
auto *barg2 = dynamic_cast<BinaryOpNode *>(arg2); auto *barg2 = dynamic_cast<BinaryOpNode *>(arg2);
int arg2_prec = arg2->precedence(output_type, temporary_terms); if (int arg2_prec = arg2->precedence(output_type, temporary_terms); arg2_prec < prec
if (arg2_prec < prec
|| (op_code == BinaryOpcode::power && barg2 != nullptr && barg2->op_code == BinaryOpcode::power && !isLatexOutput(output_type)) || (op_code == BinaryOpcode::power && barg2 != nullptr && barg2->op_code == BinaryOpcode::power && !isLatexOutput(output_type))
|| (op_code == BinaryOpcode::minus && arg2_prec == prec) || (op_code == BinaryOpcode::minus && arg2_prec == prec)
|| (op_code == BinaryOpcode::divide && arg2_prec == prec && !isLatexOutput(output_type))) || (op_code == BinaryOpcode::divide && arg2_prec == prec && !isLatexOutput(output_type)))
@ -5674,18 +5644,15 @@ BinaryOpNode::getPacAREC(int lhs_symb_id, int lhs_orig_symb_id,
vector<pair<expr_t, int>> terms; vector<pair<expr_t, int>> terms;
decomposeAdditiveTerms(terms, 1); decomposeAdditiveTerms(terms, 1);
for (auto it = terms.begin(); it != terms.end(); it++) for (auto it = terms.begin(); it != terms.end(); it++)
{ if (auto bopn = dynamic_cast<BinaryOpNode *>(it->first); bopn != nullptr)
auto bopn = dynamic_cast<BinaryOpNode *>(it->first); {
if (bopn != nullptr) ec_params_and_vars = getPacEC(bopn, lhs_symb_id, lhs_orig_symb_id);
{ if (ec_params_and_vars.first >= 0)
ec_params_and_vars = getPacEC(bopn, lhs_symb_id, lhs_orig_symb_id); {
if (ec_params_and_vars.first >= 0) terms.erase(it);
{ break;
terms.erase(it); }
break; }
}
}
}
if (ec_params_and_vars.first < 0) if (ec_params_and_vars.first < 0)
{ {
@ -5863,36 +5830,30 @@ BinaryOpNode::getPacOptimizingShareAndExprNodes(int lhs_symb_id, int lhs_orig_sy
optim_part = non_optim_part = additive_part = nullptr; optim_part = non_optim_part = additive_part = nullptr;
for (auto it = terms.begin(); it != terms.end(); it++) for (auto it = terms.begin(); it != terms.end(); it++)
{ if (auto bopn = dynamic_cast<BinaryOpNode *>(it->first); bopn != nullptr)
auto bopn = dynamic_cast<BinaryOpNode *>(it->first); {
if (bopn != nullptr) tie(optim_share, optim_part) =
{ getPacOptimizingShareAndExprNodesHelper(bopn, lhs_symb_id, lhs_orig_symb_id);
tie(optim_share, optim_part) = if (optim_share >= 0 && optim_part != nullptr)
getPacOptimizingShareAndExprNodesHelper(bopn, lhs_symb_id, lhs_orig_symb_id); {
if (optim_share >= 0 && optim_part != nullptr) terms.erase(it);
{ break;
terms.erase(it); }
break; }
}
}
}
if (optim_part == nullptr) if (optim_part == nullptr)
return {-1, nullptr, nullptr, nullptr}; return {-1, nullptr, nullptr, nullptr};
for (auto it = terms.begin(); it != terms.end(); it++) for (auto it = terms.begin(); it != terms.end(); it++)
{ if (auto bopn = dynamic_cast<BinaryOpNode *>(it->first); bopn != nullptr)
auto bopn = dynamic_cast<BinaryOpNode *>(it->first); {
if (bopn != nullptr) non_optim_part = getPacNonOptimizingPart(bopn, optim_share);
{ if (non_optim_part != nullptr)
non_optim_part = getPacNonOptimizingPart(bopn, optim_share); {
if (non_optim_part != nullptr) terms.erase(it);
{ break;
terms.erase(it); }
break; }
}
}
}
if (non_optim_part == nullptr) if (non_optim_part == nullptr)
return {-1, nullptr, nullptr, nullptr}; return {-1, nullptr, nullptr, nullptr};
@ -6352,8 +6313,7 @@ TrinaryOpNode::writeJsonOutput(ostream &output,
const bool isdynamic) const const bool isdynamic) const
{ {
// If current node is a temporary term // If current node is a temporary term
auto it = temporary_terms.find(const_cast<TrinaryOpNode *>(this)); if (temporary_terms.find(const_cast<TrinaryOpNode *>(this)) != temporary_terms.end())
if (it != temporary_terms.end())
{ {
output << "T" << idx; output << "T" << idx;
return; return;

View File

@ -63,16 +63,13 @@ ModFile::evalAllExpressions(bool warn_uninit)
// Loop over all statements, and fill global eval context if relevant // Loop over all statements, and fill global eval context if relevant
for (auto &st : statements) for (auto &st : statements)
{ {
auto ips = dynamic_cast<InitParamStatement *>(st.get()); if (auto ips = dynamic_cast<InitParamStatement *>(st.get()); ips)
if (ips)
ips->fillEvalContext(global_eval_context); ips->fillEvalContext(global_eval_context);
auto ies = dynamic_cast<InitOrEndValStatement *>(st.get()); if (auto ies = dynamic_cast<InitOrEndValStatement *>(st.get()); ies)
if (ies)
ies->fillEvalContext(global_eval_context); ies->fillEvalContext(global_eval_context);
auto lpass = dynamic_cast<LoadParamsAndSteadyStateStatement *>(st.get()); if (auto lpass = dynamic_cast<LoadParamsAndSteadyStateStatement *>(st.get()); lpass)
if (lpass)
lpass->fillEvalContext(global_eval_context); lpass->fillEvalContext(global_eval_context);
} }
@ -83,18 +80,16 @@ ModFile::evalAllExpressions(bool warn_uninit)
// Check if some symbols are not initialized, and give them a zero value then // Check if some symbols are not initialized, and give them a zero value then
for (int id = 0; id <= symbol_table.maxID(); id++) for (int id = 0; id <= symbol_table.maxID(); id++)
{ if (auto type = symbol_table.getType(id);
SymbolType type = symbol_table.getType(id); (type == SymbolType::endogenous || type == SymbolType::exogenous || type == SymbolType::exogenousDet
if ((type == SymbolType::endogenous || type == SymbolType::exogenous || type == SymbolType::exogenousDet || type == SymbolType::parameter || type == SymbolType::modelLocalVariable)
|| type == SymbolType::parameter || type == SymbolType::modelLocalVariable) && global_eval_context.find(id) == global_eval_context.end())
&& global_eval_context.find(id) == global_eval_context.end()) {
{ if (warn_uninit)
if (warn_uninit) warnings << "WARNING: Can't find a numeric initial value for "
warnings << "WARNING: Can't find a numeric initial value for " << symbol_table.getName(id) << ", using zero" << endl;
<< symbol_table.getName(id) << ", using zero" << endl; global_eval_context[id] = 0;
global_eval_context[id] = 0; }
}
}
} }
void void
@ -418,16 +413,14 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
// Declare endogenous used for PAC model-consistent expectations // Declare endogenous used for PAC model-consistent expectations
for (auto & statement : statements) for (auto & statement : statements)
{ if (auto pms = dynamic_cast<PacModelStatement *>(statement.get());
auto pms = dynamic_cast<PacModelStatement *>(statement.get()); pms != nullptr)
if (pms != nullptr) {
{ if (pms->growth != nullptr)
if (pms->growth != nullptr) pac_growth.push_back(pms->growth);
pac_growth.push_back(pms->growth); if (pms->aux_model_name == "")
if (pms->aux_model_name == "") dynamic_model.declarePacModelConsistentExpectationEndogs(pms->name);
dynamic_model.declarePacModelConsistentExpectationEndogs(pms->name); }
}
}
// Get all equation tags associated with VARs and Trend Component Models // Get all equation tags associated with VARs and Trend Component Models
set<string> eqtags; set<string> eqtags;
@ -461,51 +454,48 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
// Pac Model // Pac Model
int i = 0; int i = 0;
for (auto & statement : statements) for (auto & statement : statements)
{ if (auto pms = dynamic_cast<PacModelStatement *>(statement.get()); pms != nullptr)
auto pms = dynamic_cast<PacModelStatement *>(statement.get()); {
if (pms != nullptr) if (pms->growth != nullptr)
{ pms->overwriteGrowth(pac_growth.at(i++));
if (pms->growth != nullptr)
pms->overwriteGrowth(pac_growth.at(i++));
int max_lag; int max_lag;
vector<int> lhs; vector<int> lhs;
vector<bool> nonstationary; vector<bool> nonstationary;
string aux_model_type; string aux_model_type;
if (trend_component_model_table.isExistingTrendComponentModelName(pms->aux_model_name)) if (trend_component_model_table.isExistingTrendComponentModelName(pms->aux_model_name))
{ {
aux_model_type = "trend_component"; aux_model_type = "trend_component";
max_lag = trend_component_model_table.getMaxLag(pms->aux_model_name) + 1; max_lag = trend_component_model_table.getMaxLag(pms->aux_model_name) + 1;
lhs = dynamic_model.getUndiffLHSForPac(pms->aux_model_name, diff_subst_table); lhs = dynamic_model.getUndiffLHSForPac(pms->aux_model_name, diff_subst_table);
// All lhs variables in a trend component model are nonstationary // All lhs variables in a trend component model are nonstationary
nonstationary.insert(nonstationary.end(), trend_component_model_table.getDiff(pms->aux_model_name).size(), true); nonstationary.insert(nonstationary.end(), trend_component_model_table.getDiff(pms->aux_model_name).size(), true);
} }
else if (var_model_table.isExistingVarModelName(pms->aux_model_name)) else if (var_model_table.isExistingVarModelName(pms->aux_model_name))
{ {
aux_model_type = "var"; aux_model_type = "var";
max_lag = var_model_table.getMaxLag(pms->aux_model_name); max_lag = var_model_table.getMaxLag(pms->aux_model_name);
lhs = var_model_table.getLhs(pms->aux_model_name); lhs = var_model_table.getLhs(pms->aux_model_name);
// nonstationary variables in a VAR are those that are in diff // nonstationary variables in a VAR are those that are in diff
nonstationary = var_model_table.getDiff(pms->aux_model_name); nonstationary = var_model_table.getDiff(pms->aux_model_name);
} }
else if (pms->aux_model_name == "") else if (pms->aux_model_name == "")
max_lag = 0; max_lag = 0;
else else
{ {
cerr << "Error: aux_model_name not recognized as VAR model or Trend Component model" << endl; cerr << "Error: aux_model_name not recognized as VAR model or Trend Component model" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
auto eqtag_and_lag = dynamic_model.walkPacParameters(pms->name); auto eqtag_and_lag = dynamic_model.walkPacParameters(pms->name);
original_model.getPacMaxLag(pms->name, eqtag_and_lag); original_model.getPacMaxLag(pms->name, eqtag_and_lag);
if (pms->aux_model_name == "") if (pms->aux_model_name == "")
dynamic_model.addPacModelConsistentExpectationEquation(pms->name, symbol_table.getID(pms->discount), dynamic_model.addPacModelConsistentExpectationEquation(pms->name, symbol_table.getID(pms->discount),
eqtag_and_lag, diff_subst_table); eqtag_and_lag, diff_subst_table);
else else
dynamic_model.fillPacModelInfo(pms->name, lhs, max_lag, aux_model_type, dynamic_model.fillPacModelInfo(pms->name, lhs, max_lag, aux_model_type,
eqtag_and_lag, nonstationary, pms->growth); eqtag_and_lag, nonstationary, pms->growth);
dynamic_model.substitutePacExpectation(pms->name); dynamic_model.substitutePacExpectation(pms->name);
} }
}
dynamic_model.addEquationsForVar(); dynamic_model.addEquationsForVar();
@ -527,17 +517,14 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
{ {
PlannerObjectiveStatement *pos = nullptr; PlannerObjectiveStatement *pos = nullptr;
for (auto & statement : statements) for (auto & statement : statements)
{ if (auto pos2 = dynamic_cast<PlannerObjectiveStatement *>(statement.get()); pos2 != nullptr)
auto pos2 = dynamic_cast<PlannerObjectiveStatement *>(statement.get()); if (pos != nullptr)
if (pos2 != nullptr) {
if (pos != nullptr) cerr << "ERROR: there can only be one planner_objective statement" << endl;
{ exit(EXIT_FAILURE);
cerr << "ERROR: there can only be one planner_objective statement" << endl; }
exit(EXIT_FAILURE); else
} pos = pos2;
else
pos = pos2;
}
assert(pos != nullptr); assert(pos != nullptr);
const StaticModel &planner_objective = pos->getPlannerObjective(); const StaticModel &planner_objective = pos->getPlannerObjective();
@ -695,11 +682,8 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
if (mod_file_struct.ramsey_policy_present) if (mod_file_struct.ramsey_policy_present)
for (auto & statement : statements) for (auto & statement : statements)
{ if (auto *rps = dynamic_cast<RamseyPolicyStatement *>(statement.get()); rps != nullptr)
auto *rps = dynamic_cast<RamseyPolicyStatement *>(statement.get()); rps->checkRamseyPolicyList();
if (rps != nullptr)
rps->checkRamseyPolicyList();
}
if (mod_file_struct.identification_present && symbol_table.exo_det_nbr() > 0) if (mod_file_struct.identification_present && symbol_table.exo_det_nbr() > 0)
{ {
@ -1023,8 +1007,7 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
{ {
/* Special treatment for initval block: insert initial values for the /* Special treatment for initval block: insert initial values for the
auxiliary variables and initialize exo det */ auxiliary variables and initialize exo det */
auto *ivs = dynamic_cast<InitValStatement *>(statement.get()); if (auto *ivs = dynamic_cast<InitValStatement *>(statement.get()); ivs != nullptr)
if (ivs != nullptr)
{ {
ivs->writeOutput(mOutputFile, basename, minimal_workspace); ivs->writeOutput(mOutputFile, basename, minimal_workspace);
static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel); static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel);
@ -1032,27 +1015,22 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
} }
// Special treatment for endval block: insert initial values for the auxiliary variables // Special treatment for endval block: insert initial values for the auxiliary variables
auto *evs = dynamic_cast<EndValStatement *>(statement.get()); if (auto *evs = dynamic_cast<EndValStatement *>(statement.get()); evs != nullptr)
if (evs != nullptr)
{ {
evs->writeOutput(mOutputFile, basename, minimal_workspace); evs->writeOutput(mOutputFile, basename, minimal_workspace);
static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel); static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel);
} }
auto *ips = dynamic_cast<InitParamStatement *>(statement.get()); if (auto *ips = dynamic_cast<InitParamStatement *>(statement.get()); ips != nullptr)
if (ips != nullptr)
ips->writeOutput(mOutputFile, basename, minimal_workspace); ips->writeOutput(mOutputFile, basename, minimal_workspace);
auto *ss = dynamic_cast<ShocksStatement *>(statement.get()); if (auto *ss = dynamic_cast<ShocksStatement *>(statement.get()); ss != nullptr)
if (ss != nullptr)
ss->writeOutput(mOutputFile, basename, minimal_workspace); ss->writeOutput(mOutputFile, basename, minimal_workspace);
auto *eps = dynamic_cast<EstimatedParamsStatement *>(statement.get()); if (auto *eps = dynamic_cast<EstimatedParamsStatement *>(statement.get()); eps != nullptr)
if (eps != nullptr)
eps->writeOutput(mOutputFile, basename, minimal_workspace); eps->writeOutput(mOutputFile, basename, minimal_workspace);
auto *sgs = dynamic_cast<ShockGroupsStatement *>(statement.get()); if (auto *sgs = dynamic_cast<ShockGroupsStatement *>(statement.get()); sgs != nullptr)
if (sgs != nullptr)
sgs->writeOutput(mOutputFile, basename, minimal_workspace); sgs->writeOutput(mOutputFile, basename, minimal_workspace);
} }
else else
@ -1063,21 +1041,18 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
/* Special treatment for initval block: insert initial values for the /* Special treatment for initval block: insert initial values for the
auxiliary variables and initialize exo det */ auxiliary variables and initialize exo det */
auto ivs = dynamic_cast<InitValStatement *>(statement.get()); if (auto ivs = dynamic_cast<InitValStatement *>(statement.get()); ivs != nullptr)
if (ivs != nullptr)
{ {
static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel); static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel);
ivs->writeOutputPostInit(mOutputFile); ivs->writeOutputPostInit(mOutputFile);
} }
// Special treatment for endval block: insert initial values for the auxiliary variables // Special treatment for endval block: insert initial values for the auxiliary variables
auto evs = dynamic_cast<EndValStatement *>(statement.get()); if (auto evs = dynamic_cast<EndValStatement *>(statement.get()); evs != nullptr)
if (evs != nullptr)
static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel); static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel);
// Special treatment for load params and steady state statement: insert initial values for the auxiliary variables // Special treatment for load params and steady state statement: insert initial values for the auxiliary variables
auto lpass = dynamic_cast<LoadParamsAndSteadyStateStatement *>(statement.get()); if (auto lpass = dynamic_cast<LoadParamsAndSteadyStateStatement *>(statement.get()); lpass && !no_static)
if (lpass && !no_static)
static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel); static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel);
} }

View File

@ -290,15 +290,13 @@ void
Ifdef::interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) Ifdef::interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths)
{ {
for (auto & it : expr_and_body) for (auto & it : expr_and_body)
{ if (VariablePtr vp = dynamic_pointer_cast<Variable>(it.first);
VariablePtr vp = dynamic_pointer_cast<Variable>(it.first); dynamic_pointer_cast<BaseType>(it.first)
if (dynamic_pointer_cast<BaseType>(it.first) || (vp && env.isVariableDefined(vp->getName())))
|| (vp && env.isVariableDefined(vp->getName()))) {
{ interpretBody(it.second, output, no_line_macro, paths);
interpretBody(it.second, output, no_line_macro, paths); break;
break; }
}
}
printEndLineInfo(output, no_line_macro); printEndLineInfo(output, no_line_macro);
} }
@ -306,14 +304,12 @@ void
Ifndef::interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) Ifndef::interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths)
{ {
for (auto & it : expr_and_body) for (auto & it : expr_and_body)
{ if (VariablePtr vp = dynamic_pointer_cast<Variable>(it.first);
VariablePtr vp = dynamic_pointer_cast<Variable>(it.first); !(dynamic_pointer_cast<BaseType>(it.first)
if (!(dynamic_pointer_cast<BaseType>(it.first) || (vp && env.isVariableDefined(vp->getName()))))
|| (vp && env.isVariableDefined(vp->getName())))) {
{ interpretBody(it.second, output, no_line_macro, paths);
interpretBody(it.second, output, no_line_macro, paths); break;
break; }
}
}
printEndLineInfo(output, no_line_macro); printEndLineInfo(output, no_line_macro);
} }

View File

@ -55,13 +55,11 @@ Bool::logical_and(const BaseTypePtr &btp) const
BoolPtr BoolPtr
Bool::logical_or(const BaseTypePtr &btp) const Bool::logical_or(const BaseTypePtr &btp) const
{ {
auto btp2 = dynamic_pointer_cast<Bool>(btp); if (auto btp2 = dynamic_pointer_cast<Bool>(btp); btp2)
if (btp2)
return make_shared<Bool>(value || *btp2, env); return make_shared<Bool>(value || *btp2, env);
auto btp3 = dynamic_pointer_cast<Real>(btp); if (auto btp2 = dynamic_pointer_cast<Real>(btp); btp2)
if (btp3) return make_shared<Bool>(value || *btp2, env);
return make_shared<Bool>(value || *btp3, env);
throw StackTrace("Type mismatch for operands of || operator"); throw StackTrace("Type mismatch for operands of || operator");
} }
@ -165,13 +163,11 @@ Real::is_equal(const BaseTypePtr &btp) const
BoolPtr BoolPtr
Real::logical_and(const BaseTypePtr &btp) const Real::logical_and(const BaseTypePtr &btp) const
{ {
auto btp2 = dynamic_pointer_cast<Real>(btp); if (auto btp2 = dynamic_pointer_cast<Real>(btp); btp2)
if (btp2)
return make_shared<Bool>(value && *btp2, env); return make_shared<Bool>(value && *btp2, env);
auto btp3 = dynamic_pointer_cast<Bool>(btp); if (auto btp2 = dynamic_pointer_cast<Bool>(btp); btp2)
if (btp3) return make_shared<Bool>(value && *btp2, env);
return make_shared<Bool>(value && *btp3, env);
throw StackTrace("Type mismatch for operands of && operator"); throw StackTrace("Type mismatch for operands of && operator");
} }
@ -179,13 +175,11 @@ Real::logical_and(const BaseTypePtr &btp) const
BoolPtr BoolPtr
Real::logical_or(const BaseTypePtr &btp) const Real::logical_or(const BaseTypePtr &btp) const
{ {
auto btp2 = dynamic_pointer_cast<Real>(btp); if (auto btp2 = dynamic_pointer_cast<Real>(btp); !btp2)
if (!btp2)
return make_shared<Bool>(value || *btp2, env); return make_shared<Bool>(value || *btp2, env);
auto btp3 = dynamic_pointer_cast<Bool>(btp); if (auto btp2 = dynamic_pointer_cast<Bool>(btp); btp2)
if (btp3) return make_shared<Bool>(value || *btp2, env);
return make_shared<Bool>(value || *btp3, env);
throw StackTrace("Type mismatch for operands of || operator"); throw StackTrace("Type mismatch for operands of || operator");
} }
@ -302,12 +296,10 @@ String::cast_bool() const
{ {
auto f = [](const char& a, const char& b) { return (tolower(a) == tolower(b)); }; auto f = [](const char& a, const char& b) { return (tolower(a) == tolower(b)); };
string tf = "true"; if (string tf = "true"; equal(value.begin(), value.end(), tf.begin(), f))
if (equal(value.begin(), value.end(), tf.begin(), f))
return make_shared<Bool>(true, env); return make_shared<Bool>(true, env);
tf = "false"; if (string tf = "false"; equal(value.begin(), value.end(), tf.begin(), f))
if (equal(value.begin(), value.end(), tf.begin(), f))
return make_shared<Bool>(false, env); return make_shared<Bool>(false, env);
try try
@ -648,36 +640,30 @@ Variable::eval()
vector<ExpressionPtr> index = map->getValue(); vector<ExpressionPtr> index = map->getValue();
vector<int> ind; vector<int> ind;
for (auto it : index) for (auto it : index)
{ // Necessary to handle indexes like: y[1:2,2]
// Necessary to handle indexes like: y[1:2,2] // In general this evaluates to [[1:2],2] but when subscripting we want to expand it to [1,2,2]
// In general this evaluates to [[1:2],2] but when subscripting we want to expand it to [1,2,2] if (auto db = dynamic_pointer_cast<Real>(it); db)
auto db = dynamic_pointer_cast<Real>(it); {
if (db) if (!*(db->isinteger()))
{ throw StackTrace("variable", "When indexing a variable you must pass "
if (!*(db->isinteger())) "an int or an int array", location);
throw StackTrace("variable", "When indexing a variable you must pass " ind.emplace_back(*db);
"an int or an int array", location); }
ind.emplace_back(*db); else if (dynamic_pointer_cast<Array>(it))
} for (auto it1 : dynamic_pointer_cast<Array>(it)->getValue())
else if (dynamic_pointer_cast<Array>(it)) if (db = dynamic_pointer_cast<Real>(it1); db)
for (auto it1 : dynamic_pointer_cast<Array>(it)->getValue())
{ {
db = dynamic_pointer_cast<Real>(it1); if (!*(db->isinteger()))
if (db) throw StackTrace("variable", "When indexing a variable you must pass "
{ "an int or an int array", location);
if (!*(db->isinteger())) ind.emplace_back(*db);
throw StackTrace("variable", "When indexing a variable you must pass "
"an int or an int array", location);
ind.emplace_back(*db);
}
else
throw StackTrace("variable", "You cannot index a variable with a "
"nested array", location);
} }
else else
throw StackTrace("variable", "You can only index a variable with an int or " throw StackTrace("variable", "You cannot index a variable with a "
"an int array", location); "nested array", location);
} else
throw StackTrace("variable", "You can only index a variable with an int or "
"an int array", location);
switch (env.getType(name)) switch (env.getType(name))
{ {