From a3e63101f4fcacbe6a4f3ed98849215cecda1e7d Mon Sep 17 00:00:00 2001 From: Houtan Bastani <houtan@dynare.org> Date: Mon, 24 Jun 2019 11:00:02 +0200 Subject: [PATCH] support `save` option of @#echomacrovars --- src/macro/Directives.cc | 12 ++++++++- src/macro/Directives.hh | 8 ++++-- src/macro/Environment.cc | 46 ++++++++++++++++++------------- src/macro/Environment.hh | 2 +- src/macro/Expressions.cc | 58 +++++++++++++++++++++++----------------- src/macro/Expressions.hh | 26 +++++++++--------- src/macro/Parser.yy | 6 +++-- src/macro/Tokenizer.ll | 3 ++- 8 files changed, 99 insertions(+), 62 deletions(-) diff --git a/src/macro/Directives.cc b/src/macro/Directives.cc index 0e84b715..daa781e8 100644 --- a/src/macro/Directives.cc +++ b/src/macro/Directives.cc @@ -120,7 +120,7 @@ Echo::interpret(ostream &output, bool no_line_macro) { error(StackTrace("@#echo", e.what(), location)); } - printLineInfo(output, no_line_macro); + printEndLineInfo(output, no_line_macro); } void @@ -141,6 +141,16 @@ Error::interpret(ostream &output, bool no_line_macro) } } +void +EchoMacroVars::interpret(ostream &output, bool no_line_macro) +{ + if (save) + env.print(output, location.begin.line, true); + else + env.print(cout); + printEndLineInfo(output, no_line_macro); +} + void For::interpret(ostream &output, bool no_line_macro) { diff --git a/src/macro/Directives.hh b/src/macro/Directives.hh index f8220c9b..314f3362 100644 --- a/src/macro/Directives.hh +++ b/src/macro/Directives.hh @@ -137,9 +137,13 @@ namespace macro class EchoMacroVars : public Directive { + private: + bool save; public: - EchoMacroVars(Environment &env_arg, const Tokenizer::location location_arg) : Directive(env_arg, move(location_arg)) { } - inline void interpret(ostream &output, bool no_line_macro) override { env.print(); } + EchoMacroVars(bool save_arg, + Environment &env_arg, const Tokenizer::location location_arg) : + Directive(env_arg, move(location_arg)), save{save_arg} { } + void interpret(ostream &output, bool no_line_macro) override; }; diff --git a/src/macro/Environment.cc b/src/macro/Environment.cc index be12f988..03206a2b 100644 --- a/src/macro/Environment.cc +++ b/src/macro/Environment.cc @@ -101,32 +101,42 @@ Environment::isFunctionDefined(const string &name) const noexcept } void -Environment::print() const +Environment::print(ostream &output, int line, bool save) const { - if (!variables.empty()) + if (!save && !variables.empty()) + output << "Macro Variables:" << endl; + + for (auto & it : variables) { - cout << "Macro Variables:" << endl; - for (auto & it : variables) - { - cout << " " << it.first << " = "; - getVariable(it.first)->eval()->print(cout); - cout << endl; - } + output << (save ? "options_.macrovars_line_" + to_string(line) + "." : " " ); + output << it.first << " = "; + getVariable(it.first)->eval()->print(output, true); + if (save) + output << ";"; + output << endl; } - if (!functions.empty()) + if (!save && !functions.empty()) + output << "Macro Functions:" << endl; + + for (auto & it : functions) { - cout << "Macro Functions:" << endl; - for (auto & it : functions) + output << (save ? "options_.macrovars_line_" + to_string(line) + ".function." : " " ); + if (save) { - cout << " "; - get<0>(it.second)->print(cout); - cout << " = "; - get<1>(it.second)->print(cout); - cout << endl; + 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 (parent) - parent->print(); + parent->print(output, line, save); } diff --git a/src/macro/Environment.hh b/src/macro/Environment.hh index 52e8ae48..78e34c8c 100644 --- a/src/macro/Environment.hh +++ b/src/macro/Environment.hh @@ -46,7 +46,7 @@ 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() const; + void print(ostream &output, int line = -1, bool save = false) 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/Expressions.cc b/src/macro/Expressions.cc index 9ad085fa..c0cc4c43 100644 --- a/src/macro/Expressions.cc +++ b/src/macro/Expressions.cc @@ -1094,35 +1094,43 @@ Comprehension::to_string() const noexcept } void -Array::print(ostream &output) const noexcept +String::print(ostream &output, bool matlab_output) const noexcept { - output << "["; + output << (matlab_output ? "'" : R"(")"); + output << value; + output << (matlab_output ? "'" : R"(")"); +} + +void +Array::print(ostream &output, bool matlab_output) const noexcept +{ +output << (matlab_output ? "{" : "["); for (auto it = arr.begin(); it != arr.end(); it++) { if (it != arr.begin()) output << ", "; - (*it)->print(output); + (*it)->print(output, matlab_output); } - output << "]"; + output << (matlab_output ? "}" : "]"); } void -Tuple::print(ostream &output) const noexcept +Tuple::print(ostream &output, bool matlab_output) const noexcept { - output << "("; + output << (matlab_output ? "{" : "("); for (auto it = tup.begin(); it != tup.end(); it++) { if (it != tup.begin()) output << ", "; - (*it)->print(output); + (*it)->print(output, matlab_output); } - output << ")"; + output << (matlab_output ? "}" : ")"); } void -Function::print(ostream &output) const noexcept +Function::printArgs(ostream &output) const noexcept { - output << name << "("; + output << "("; for (auto it = args.begin(); it != args.end(); it++) { if (it != args.begin()) @@ -1133,7 +1141,7 @@ Function::print(ostream &output) const noexcept } void -UnaryOp::print(ostream &output) const noexcept +UnaryOp::print(ostream &output, bool matlab_output) const noexcept { switch (op_code) { @@ -1220,7 +1228,7 @@ UnaryOp::print(ostream &output) const noexcept break; } - arg->print(output); + arg->print(output, matlab_output); if (op_code != codes::UnaryOp::logical_not && op_code != codes::UnaryOp::unary_plus @@ -1229,7 +1237,7 @@ UnaryOp::print(ostream &output) const noexcept } void -BinaryOp::print(ostream &output) const noexcept +BinaryOp::print(ostream &output, bool matlab_output) const noexcept { if (op_code == codes::BinaryOp::set_union || op_code == codes::BinaryOp::set_intersection @@ -1257,14 +1265,14 @@ BinaryOp::print(ostream &output) const noexcept default: break; } - arg1->print(output); + arg1->print(output, matlab_output); output << ", "; - arg2->print(output); + arg2->print(output, matlab_output); output << ")"; return; } - arg1->print(output); + arg1->print(output, matlab_output); switch(op_code) { case codes::BinaryOp::plus: @@ -1317,11 +1325,11 @@ BinaryOp::print(ostream &output) const noexcept cerr << "macro::BinaryOp::print: Should not arrive here" << endl; exit(EXIT_FAILURE); } - arg2->print(output); + arg2->print(output, matlab_output); } void -TrinaryOp::print(ostream &output) const noexcept +TrinaryOp::print(ostream &output, bool matlab_output) const noexcept { switch(op_code) { @@ -1332,23 +1340,23 @@ TrinaryOp::print(ostream &output) const noexcept output << "normcdf("; break; } - arg1->print(output); + arg1->print(output, matlab_output); output << ", "; - arg2->print(output); + arg2->print(output, matlab_output); output << ", "; - arg3->print(output); + arg3->print(output, matlab_output); output << ")"; } void -Comprehension::print(ostream &output) const noexcept +Comprehension::print(ostream &output, bool matlab_output) const noexcept { output << "["; - c_vars->print(output); + c_vars->print(output, matlab_output); output << " in "; - c_set->print(output); + c_set->print(output, matlab_output); output << " when "; - c_when->print(output); + c_when->print(output, matlab_output); output << "]"; } diff --git a/src/macro/Expressions.hh b/src/macro/Expressions.hh index 82e8539e..e3fcc221 100644 --- a/src/macro/Expressions.hh +++ b/src/macro/Expressions.hh @@ -114,7 +114,7 @@ namespace macro Expression(Environment &env_arg, const Tokenizer::location location_arg) : Node(env_arg, move(location_arg)) { } virtual string to_string() const noexcept = 0; - virtual void print(ostream &output) const noexcept = 0; + virtual void print(ostream &output, bool matlab_output = false) const noexcept = 0; virtual BaseTypePtr eval() = 0; }; @@ -193,7 +193,7 @@ namespace macro value{value_arg} { } inline codes::BaseType getType() const noexcept override { return codes::BaseType::Bool; } inline string to_string() const noexcept override { return value ? "true" : "false"; } - inline void print(ostream &output) const noexcept override { output << to_string(); } + inline void print(ostream &output, bool matlab_output = false) const noexcept override { output << to_string(); } public: operator bool() const { return value; } BoolPtr is_equal(const BaseTypePtr &btp) const override; @@ -225,7 +225,7 @@ namespace macro strs << setprecision(15) << value; return strs.str(); } - inline void print(ostream &output) const noexcept override { output << to_string(); } + inline void print(ostream &output, bool matlab_output = false) const noexcept override { output << to_string(); } public: operator double() const { return value; } BaseTypePtr plus(const BaseTypePtr &bt) const override; @@ -287,7 +287,7 @@ namespace macro value{move(value_arg)} { } inline codes::BaseType getType() const noexcept override { return codes::BaseType::String; } inline string to_string() const noexcept override { return value; } - inline void print(ostream &output) const noexcept override { output << R"(")" << value << R"(")"; } + void print(ostream &output, bool matlab_output = false) const noexcept override; public: operator string() const { return value; } BaseTypePtr plus(const BaseTypePtr &bt) const override; @@ -311,7 +311,7 @@ namespace macro tup{move(tup_arg)} { } inline codes::BaseType getType() const noexcept override { return codes::BaseType::Tuple; } string to_string() const noexcept override; - void print(ostream &output) const noexcept override; + void print(ostream &output, bool matlab_output = false) const noexcept override; BaseTypePtr eval() override; public: inline size_t size() const { return tup.size(); } @@ -344,7 +344,7 @@ namespace macro range1{move(range1_arg)}, increment{move(increment_arg)}, range2{move(range2_arg)} { } inline codes::BaseType getType() const noexcept override { return codes::BaseType::Array; } string to_string() const noexcept override; - void print(ostream &output) const noexcept override; + void print(ostream &output, bool matlab_output = false) const noexcept override; BaseTypePtr eval() override; private: BaseTypePtr evalArray(); @@ -382,7 +382,7 @@ namespace macro indices = make_shared<Array>(vector<ExpressionPtr>{indices_arg}, env); } inline string to_string() const noexcept override { return name; } - inline void print(ostream &output) const noexcept override { output << name; } + inline void print(ostream &output, bool matlab_output = false) const noexcept override { output << name; } BaseTypePtr eval() override; public: inline string getName() const noexcept { return name; } @@ -401,9 +401,11 @@ namespace macro Environment &env_arg, const Tokenizer::location location_arg) : Expression(env_arg, move(location_arg)), name{move(name_arg)}, args{move(args_arg)} { } string to_string() const noexcept override; - void print(ostream &output) const noexcept override; + inline void print(ostream &output, bool matlab_output = false) const noexcept override { printName(output); printArgs(output); } BaseTypePtr eval() override; public: + inline void printName(ostream &output) const noexcept { output << name; } + void printArgs(ostream &output) const noexcept; inline string getName() const { return name; } inline vector<ExpressionPtr> getArgs() const { return args; } }; @@ -420,7 +422,7 @@ namespace macro Environment &env_arg, const Tokenizer::location location_arg) : Expression(env_arg, move(location_arg)), op_code{move(op_code_arg)}, arg{move(arg_arg)} { } string to_string() const noexcept override; - void print(ostream &output) const noexcept override; + void print(ostream &output, bool matlab_output = false) const noexcept override; BaseTypePtr eval() override; }; @@ -438,7 +440,7 @@ namespace macro arg1{move(arg1_arg)}, arg2{move(arg2_arg)} { } public: string to_string() const noexcept override; - void print(ostream &output) const noexcept override; + void print(ostream &output, bool matlab_output = false) const noexcept override; BaseTypePtr eval() override; }; @@ -455,7 +457,7 @@ namespace macro Expression(env_arg, move(location_arg)), op_code{move(op_code_arg)}, arg1{move(arg1_arg)}, arg2{move(arg2_arg)}, arg3{move(arg3_arg)} { } string to_string() const noexcept override; - void print(ostream &output) const noexcept override; + void print(ostream &output, bool matlab_output = false) const noexcept override; BaseTypePtr eval() override; }; @@ -472,7 +474,7 @@ namespace macro Expression(env_arg, move(location_arg)), c_vars{move(c_vars_arg)}, c_set{move(c_set_arg)}, c_when{move(c_when_arg)} { } string to_string() const noexcept override; - void print(ostream &output) const noexcept override; + void print(ostream &output, bool matlab_output = false) const noexcept override; BaseTypePtr eval() override; }; } diff --git a/src/macro/Parser.yy b/src/macro/Parser.yy index 70454795..e1d7f6d7 100644 --- a/src/macro/Parser.yy +++ b/src/macro/Parser.yy @@ -64,7 +64,7 @@ using namespace macro; %token FOR ENDFOR IF IFDEF IFNDEF ELSE ENDIF TRUE FALSE %token INCLUDE INCLUDEPATH DEFINE EQUAL D_ECHO ERROR %token COMMA LPAREN RPAREN LBRACKET RBRACKET WHEN -%token BEGIN_EVAL END_EVAL ECHOMACROVARS +%token BEGIN_EVAL END_EVAL ECHOMACROVARS SAVE %token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN %token SQRT CBRT SIGN MAX MIN FLOOR CEIL TRUNC SUM MOD @@ -137,7 +137,9 @@ directive_one_line : INCLUDE expr | ERROR expr { $$ = make_shared<Error>($2, driver.env, @$); } | ECHOMACROVARS - { $$ = make_shared<EchoMacroVars>(driver.env, @$); } + { $$ = make_shared<EchoMacroVars>(false, driver.env, @$); } + | ECHOMACROVARS LPAREN SAVE RPAREN + { $$ = make_shared<EchoMacroVars>(true, driver.env, @$); } ; directive_multiline : for diff --git a/src/macro/Tokenizer.ll b/src/macro/Tokenizer.ll index 938b9b67..a1268a4a 100644 --- a/src/macro/Tokenizer.ll +++ b/src/macro/Tokenizer.ll @@ -81,7 +81,7 @@ CONT \\\\{SPC}* <directive>endif { BEGIN(end_line); return token::ENDIF; } <directive>for { BEGIN(expr); return token::FOR; } <directive>endfor { BEGIN(end_line); return token::ENDFOR; } -<directive>echomacrovars { BEGIN(end_line); return token::ECHOMACROVARS; } +<directive>echomacrovars { BEGIN(expr); return token::ECHOMACROVARS; } <expr,eval>\+ { return token::PLUS; } <expr,eval>- { return token::MINUS; } @@ -112,6 +112,7 @@ CONT \\\\{SPC}* <expr,eval>\] { return token::RBRACKET; } <expr,eval>in { return token::IN; } <expr,eval>when { return token::WHEN; } +<expr,eval>save { return token::SAVE; } <expr,eval>true { return token::TRUE; } <expr,eval>false { return token::FALSE; } -- GitLab