diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc index 72909abeaecf6c4d4c3fa7201a153d3a91ed52e5..7ff82308861b6e610e9ce938e8c3978d1e613419 100644 --- a/src/ParsingDriver.cc +++ b/src/ParsingDriver.cc @@ -3092,17 +3092,17 @@ ParsingDriver::add_external_function_arg(expr_t arg) stack_external_function_args.top().push_back(arg); } -pair<bool, double> +optional<int> ParsingDriver::is_there_one_integer_argument() const { if (stack_external_function_args.top().size() != 1) - return { false, 0 }; + return nullopt; auto numNode = dynamic_cast<NumConstNode *>(stack_external_function_args.top().front()); auto unaryNode = dynamic_cast<UnaryOpNode *>(stack_external_function_args.top().front()); if (!numNode && !unaryNode) - return { false, 0 }; + return nullopt; eval_context_t ectmp; double model_var_arg; @@ -3114,12 +3114,12 @@ ParsingDriver::is_there_one_integer_argument() const } catch (ExprNode::EvalException &e) { - return { false, 0 }; + return nullopt; } } else if (unaryNode->op_code != UnaryOpcode::uminus) - return { false, 0 }; + return nullopt; else { try @@ -3128,13 +3128,13 @@ ParsingDriver::is_there_one_integer_argument() const } catch (ExprNode::EvalException &e) { - return { false, 0 }; + return nullopt; } } if (model_var_arg != floor(model_var_arg)) - return { false, 0 }; - return { true, model_var_arg }; + return nullopt; + return static_cast<int>(model_var_arg); } expr_t @@ -3155,12 +3155,12 @@ ParsingDriver::add_model_var_or_external_function(const string &function_name, b if (undeclared_model_vars.contains(function_name)) undeclared_model_variable_error("Unknown symbol: " + function_name, function_name); - pair<bool, double> rv = is_there_one_integer_argument(); - if (!rv.first) + optional<int> rv{is_there_one_integer_argument()}; + if (!rv) model_error("Symbol " + function_name +" is being treated as if it were a function (i.e., takes an argument that is not an integer).", ""); - nid = add_model_variable(mod_file->symbol_table.getID(function_name), static_cast<int>(rv.second)); + nid = add_model_variable(mod_file->symbol_table.getID(function_name), *rv); stack_external_function_args.pop(); return nid; } @@ -3191,12 +3191,12 @@ ParsingDriver::add_model_var_or_external_function(const string &function_name, b undeclared_model_vars.insert(function_name); undeclared_model_variable_error("Unknown symbol: " + function_name, function_name); - pair<bool, double> rv = is_there_one_integer_argument(); - if (rv.first) + optional<int>rv{is_there_one_integer_argument()}; + if (rv) { // assume it's a lead/lagged variable int symb_id = declare_exogenous(function_name); - return add_model_variable(symb_id, static_cast<int>(rv.second)); + return add_model_variable(symb_id, *rv); } else error("To use an external function (" + function_name diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh index c17d7eed892cc27d94f077435a04414a36cc324d..6cafa8daf321bc46f81524b00e570fb606ee8238 100644 --- a/src/ParsingDriver.hh +++ b/src/ParsingDriver.hh @@ -28,6 +28,7 @@ #include <vector> #include <istream> #include <stack> +#include <optional> #include "ModFile.hh" #include "SymbolList.hh" @@ -842,7 +843,7 @@ public: //! Adds an external function argument void add_external_function_arg(expr_t arg); //! Test to see if model/external function has exactly one integer argument - pair<bool, double> is_there_one_integer_argument() const; + optional<int> is_there_one_integer_argument() const; //! Adds an external function call node expr_t add_model_var_or_external_function(const string &function_name, bool in_model_block); //! Adds a native statement diff --git a/src/macro/Environment.cc b/src/macro/Environment.cc index 7e568fa3d31d5ed68216420ae1a13008351d8d00..7ceb75372a8a5cc53cbd576d92c7e86d8b7bc9b3 100644 --- a/src/macro/Environment.cc +++ b/src/macro/Environment.cc @@ -17,6 +17,8 @@ * along with Dynare. If not, see <https://www.gnu.org/licenses/>. */ +#include <cassert> + #include "Environment.hh" #include "Expressions.hh" @@ -99,7 +101,7 @@ Environment::isFunctionDefined(const string &name) const noexcept } void -Environment::print(ostream &output, const vector<string> &vars, int line, bool save) const +Environment::print(ostream &output, const vector<string> &vars, const optional<int> &line, bool save) const { if (!save && !variables.empty()) output << "Macro Variables:" << endl; @@ -128,9 +130,10 @@ Environment::print(ostream &output, const vector<string> &vars, int line, bool s } void -Environment::printVariable(ostream &output, const string &name, int line, bool save) const +Environment::printVariable(ostream &output, const string &name, const optional<int> &line, bool save) const { - output << (save ? "options_.macrovars_line_" + to_string(line) + "." : " ") + assert(!save || line); + output << (save ? "options_.macrovars_line_" + to_string(*line) + "." : " ") << name << " = "; getVariable(name)->eval(const_cast<Environment &>(*this))->print(output, save); if (save) @@ -139,9 +142,10 @@ Environment::printVariable(ostream &output, const string &name, int line, bool s } void -Environment::printFunction(ostream &output, const tuple<FunctionPtr, ExpressionPtr> &function, int line, bool save) const +Environment::printFunction(ostream &output, const tuple<FunctionPtr, ExpressionPtr> &function, const optional<int> &line, bool save) const { - output << (save ? "options_.macrovars_line_" + to_string(line) + ".function." : " "); + assert(!save || line); + output << (save ? "options_.macrovars_line_" + to_string(*line) + ".function." : " "); if (save) { get<0>(function)->printName(output); diff --git a/src/macro/Environment.hh b/src/macro/Environment.hh index ee315cf979a4396d1a08beda89253888690af45f..9135711857a8cb583804ec6c0368c850c9df0a0b 100644 --- a/src/macro/Environment.hh +++ b/src/macro/Environment.hh @@ -1,5 +1,5 @@ /* - * Copyright © 2019-2021 Dynare Team + * Copyright © 2019-2022 Dynare Team * * This file is part of Dynare. * @@ -24,6 +24,7 @@ #include <map> #include <vector> +#include <optional> namespace macro { @@ -44,9 +45,9 @@ namespace macro bool isVariableDefined(const string &name) const noexcept; bool isFunctionDefined(const string &name) const noexcept; inline bool isSymbolDefined(const string &name) const noexcept { return isVariableDefined(name) || isFunctionDefined(name); } - void print(ostream &output, const vector<string> &vars, int line = -1, bool save = false) const; - void printVariable(ostream &output, const string &name, int line, bool save) const; - void printFunction(ostream &output, const tuple<FunctionPtr, ExpressionPtr> &function, int line, bool save) const; + void print(ostream &output, const vector<string> &vars, const optional<int> &line = nullopt, bool save = false) const; + void printVariable(ostream &output, const string &name, const optional<int> &line, bool save) const; + void printFunction(ostream &output, const tuple<FunctionPtr, ExpressionPtr> &function, const optional<int> &line, bool save) const; inline size_t size() const noexcept { return variables.size() + functions.size(); } inline const Environment *getGlobalEnv() const noexcept { return parent == nullptr ? this : parent->getGlobalEnv(); } };