From 3a21eda40ef0385e3a2558c990496fc0603ce01a Mon Sep 17 00:00:00 2001 From: Houtan Bastani Date: Mon, 26 Aug 2019 18:12:04 +0200 Subject: [PATCH] macro processor: support @#echomacrovars with symbol_list closes #26 --- doc/macroprocessor/macroprocessor.tex | 8 ++- src/macro/Directives.cc | 4 +- src/macro/Directives.hh | 4 ++ src/macro/Environment.cc | 74 +++++++++++++++++---------- src/macro/Environment.hh | 4 +- src/macro/Parser.yy | 14 +++++ 6 files changed, 75 insertions(+), 33 deletions(-) diff --git a/doc/macroprocessor/macroprocessor.tex b/doc/macroprocessor/macroprocessor.tex index 4d26aa16..ed8bab86 100644 --- a/doc/macroprocessor/macroprocessor.tex +++ b/doc/macroprocessor/macroprocessor.tex @@ -530,13 +530,17 @@ There is also \verb+@#ifndef+, which is the opposite of \verb+@#ifdef+ \begin{itemize} \item The echo directive will simply display a message on standard output \item The error directive will display the message and make Dynare stop (only makes sense inside a conditional directive) - \item The echomacrovars directive will display all of the macro variables and their values + \item The echomacrovars directive will display all of the macro variables (or + those specified) and their values, optionally saving them \end{itemize} \begin{block}{Syntax} \verb+@#echo +\textit{string\_expr} \\ \verb+@#error +\textit{string\_expr} \\ -\verb+@#echomacrovars + +\verb+@#echomacrovars +\\ +\verb+@#echomacrovars +\textit{list\_of\_variables}\\ +\verb+@#echomacrovars (save)+\\ +\verb+@#echomacrovars (save)+\textit{list\_of\_variables}\\ \end{block} \begin{block}{Examples} diff --git a/src/macro/Directives.cc b/src/macro/Directives.cc index f2f67926..e1207a28 100644 --- a/src/macro/Directives.cc +++ b/src/macro/Directives.cc @@ -147,9 +147,9 @@ void EchoMacroVars::interpret(ostream &output, bool no_line_macro) { if (save) - env.print(output, location.begin.line, true); + env.print(output, vars, location.begin.line, true); else - env.print(cout); + env.print(cout, vars); printEndLineInfo(output, no_line_macro); } diff --git a/src/macro/Directives.hh b/src/macro/Directives.hh index 1c1409e5..09f34339 100644 --- a/src/macro/Directives.hh +++ b/src/macro/Directives.hh @@ -145,10 +145,14 @@ namespace macro { private: const bool save; + const vector vars; public: EchoMacroVars(bool save_arg, Environment &env_arg, Tokenizer::location location_arg) : Directive(env_arg, move(location_arg)), save{save_arg} { } + EchoMacroVars(bool save_arg, vector vars_arg, + Environment &env_arg, Tokenizer::location location_arg) : + Directive(env_arg, move(location_arg)), save{save_arg}, vars{move(vars_arg)} { } void interpret(ostream &output, bool no_line_macro) override; }; diff --git a/src/macro/Environment.cc b/src/macro/Environment.cc index fcb8aa5c..17e3f756 100644 --- a/src/macro/Environment.cc +++ b/src/macro/Environment.cc @@ -101,42 +101,60 @@ Environment::isFunctionDefined(const string &name) const noexcept } void -Environment::print(ostream &output, int line, bool save) const +Environment::print(ostream &output, const vector &vars, int line, bool save) const { if (!save && !variables.empty()) output << "Macro Variables:" << endl; - for (auto & it : variables) - { - output << (save ? "options_.macrovars_line_" + to_string(line) + "." : " " ); - output << it.first << " = "; - getVariable(it.first)->eval()->print(output, save); - if (save) - output << ";"; - output << endl; - } + if (vars.empty()) + for (auto & it : variables) + printVariable(output, it.first, line, save); + else + for (const auto & it : vars) + if (isVariableDefined(it)) + printVariable(output, it, line, save); if (!save && !functions.empty()) output << "Macro Functions:" << endl; - for (auto & it : functions) - { - output << (save ? "options_.macrovars_line_" + to_string(line) + ".function." : " " ); - if (save) - { - get<0>(it.second)->printName(output); - output << " = '"; - } - - get<0>(it.second)->print(output); - output << " = "; - get<1>(it.second)->print(output); - - if (save) - output << "';"; - output << endl; - } + if (vars.empty()) + for (const auto & it : functions) + printFunction(output, it.second, line, save); + else + for (const auto & it : vars) + if (isFunctionDefined(it)) + printFunction(output, functions.find(it)->second, line, save); if (parent) - parent->print(output, line, save); + parent->print(output, vars, line, save); +} + +void +Environment::printVariable(ostream &output, const string & name, int line, bool save) const +{ + output << (save ? "options_.macrovars_line_" + to_string(line) + "." : " " ); + output << name << " = "; + getVariable(name)->eval()->print(output, save); + if (save) + output << ";"; + output << endl; +} + +void +Environment::printFunction(ostream &output, const tuple & function, int line, bool save) const +{ + output << (save ? "options_.macrovars_line_" + to_string(line) + ".function." : " " ); + if (save) + { + get<0>(function)->printName(output); + output << " = '"; + } + + get<0>(function)->print(output); + output << " = "; + get<1>(function)->print(output); + + if (save) + output << "';"; + output << endl; } diff --git a/src/macro/Environment.hh b/src/macro/Environment.hh index 905905ff..c37d7c61 100644 --- a/src/macro/Environment.hh +++ b/src/macro/Environment.hh @@ -43,7 +43,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, int line = -1, bool save = false) const; + void print(ostream &output, const vector &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 & function, 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(); } }; diff --git a/src/macro/Parser.yy b/src/macro/Parser.yy index b46cea4b..b84009af 100644 --- a/src/macro/Parser.yy +++ b/src/macro/Parser.yy @@ -100,6 +100,7 @@ using namespace macro; %type symbol %type > comma_expr function_args tuple_comma_expr +%type > name_list %% @@ -138,10 +139,23 @@ directive_one_line : INCLUDE expr { $$ = make_shared($2, driver.env, @$); } | ECHOMACROVARS { $$ = make_shared(false, driver.env, @$); } + | ECHOMACROVARS name_list + { $$ = make_shared(false, $2, driver.env, @$); } | ECHOMACROVARS LPAREN SAVE RPAREN { $$ = make_shared(true, driver.env, @$); } + | ECHOMACROVARS LPAREN SAVE RPAREN name_list + { $$ = make_shared(true, $5, driver.env, @$); } ; +name_list : NAME + { $$ = vector{$1}; } + | name_list NAME + { + $1.emplace_back($2); + $$ = $1; + } + ; + directive_multiline : for | if | ifdef