From 5fc83fad293379198f28a7a683aa0361f0ffb9d5 Mon Sep 17 00:00:00 2001 From: Houtan Bastani <houtan@dynare.org> Date: Fri, 2 Aug 2019 14:53:24 -0400 Subject: [PATCH] macro processor: introduce integer casts --- src/macro/Expressions.cc | 39 +++++++++++++++++++++++- src/macro/Expressions.hh | 6 ++++ src/macro/ForwardDeclarationsAndEnums.hh | 1 + src/macro/Parser.yy | 5 +++ src/macro/Tokenizer.ll | 2 ++ 5 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/macro/Expressions.cc b/src/macro/Expressions.cc index 7eb2ce97..ce8e91b8 100644 --- a/src/macro/Expressions.cc +++ b/src/macro/Expressions.cc @@ -297,6 +297,19 @@ String::is_equal(const BaseTypePtr &btp) const return make_shared<Bool>(value == btp2->value, env); } +DoublePtr +String::cast_int() const +{ + try + { + return make_shared<Double>(stoi(value), env); + } + catch (...) + { + throw StackTrace(value + " cannot be converted to an int"); + } +} + BaseTypePtr Array::plus(const BaseTypePtr &btp) const { @@ -492,6 +505,14 @@ Array::sum() const return make_shared<Double>(retval, env); } +DoublePtr +Array::cast_int() const +{ + if (arr.size() != 1) + throw StackTrace("Array must be of size 1 to be cast to an int"); + return arr.at(0)->eval()->cast_int(); +} + BoolPtr Tuple::is_equal(const BaseTypePtr &btp) const { @@ -526,6 +547,14 @@ Tuple::contains(const BaseTypePtr &btp) const return make_shared<Bool>(false, env); } +DoublePtr +Tuple::cast_int() const +{ + if (tup.size() != 1) + throw StackTrace("Tuple must be of size 1 to be cast to an int"); + return tup.at(0)->eval()->cast_int(); +} + BaseTypePtr Array::eval() { @@ -709,6 +738,8 @@ UnaryOp::eval() auto argbt = arg->eval(); switch (op_code) { + case codes::UnaryOp::cast_int: + return argbt->cast_int(); case codes::UnaryOp::logical_not: return argbt->logical_not(); case codes::UnaryOp::unary_minus: @@ -1029,6 +1060,8 @@ UnaryOp::to_string() const noexcept string retval = arg->to_string(); switch (op_code) { + case codes::UnaryOp::cast_int: + return "(int)" + retval; case codes::UnaryOp::logical_not: return "!" + retval; case codes::UnaryOp::unary_minus: @@ -1229,6 +1262,9 @@ UnaryOp::print(ostream &output, bool matlab_output) const noexcept { switch (op_code) { + case codes::UnaryOp::cast_int: + output << "(int)"; + break; case codes::UnaryOp::logical_not: output << "!"; break; @@ -1314,7 +1350,8 @@ UnaryOp::print(ostream &output, bool matlab_output) const noexcept arg->print(output, matlab_output); - if (op_code != codes::UnaryOp::logical_not + if (op_code != codes::UnaryOp::cast_int + && op_code != codes::UnaryOp::logical_not && op_code != codes::UnaryOp::unary_plus && op_code != codes::UnaryOp::unary_minus) output << ")"; diff --git a/src/macro/Expressions.hh b/src/macro/Expressions.hh index 2b4670f8..d75bf2cd 100644 --- a/src/macro/Expressions.hh +++ b/src/macro/Expressions.hh @@ -180,6 +180,7 @@ namespace macro virtual DoublePtr normpdf(const BaseTypePtr &btp1, const BaseTypePtr &btp2) const { throw StackTrace("Operator `normpdf` does not exist for this type"); } virtual DoublePtr normcdf() const { throw StackTrace("Operator `normcdf` does not exist for this type"); } virtual DoublePtr normcdf(const BaseTypePtr &btp1, const BaseTypePtr &btp2) const { throw StackTrace("Operator `normcdf` does not exist for this type"); } + virtual DoublePtr cast_int() const { throw StackTrace("This type cannot be cast to an integer"); } }; @@ -202,6 +203,7 @@ namespace macro BoolPtr logical_and(const BaseTypePtr &btp) const override; BoolPtr logical_or(const BaseTypePtr &btp) const override; BoolPtr logical_not() const override; + inline DoublePtr cast_int() const override { return value ? make_shared<Double>(1, env) : make_shared<Double>(0, env); } }; @@ -286,6 +288,7 @@ namespace macro return normcdf(make_shared<Double>(0, env), make_shared<Double>(1, env)); } DoublePtr normcdf(const BaseTypePtr &btp1, const BaseTypePtr &btp2) const override; + inline DoublePtr cast_int() const override { return make_shared<Double>(static_cast<int>(value), env); } }; class String final : public BaseType @@ -310,6 +313,7 @@ namespace macro BoolPtr is_greater_equal(const BaseTypePtr &btp) const override; BoolPtr is_equal(const BaseTypePtr &btp) const override; inline DoublePtr length() const override { return make_shared<Double>(value.size(), env); } + inline DoublePtr cast_int() const override; }; @@ -335,6 +339,7 @@ namespace macro BoolPtr is_equal(const BaseTypePtr &btp) const override; BoolPtr contains(const BaseTypePtr &btp) const override; inline DoublePtr length() const override { return make_shared<Double>(tup.size(), env); } + DoublePtr cast_int() const override; }; @@ -376,6 +381,7 @@ namespace macro BoolPtr contains(const BaseTypePtr &btp) const override; inline DoublePtr length() const override { return make_shared<Double>(arr.size(), env); } DoublePtr sum() const override; + DoublePtr cast_int() const override; }; diff --git a/src/macro/ForwardDeclarationsAndEnums.hh b/src/macro/ForwardDeclarationsAndEnums.hh index 996446e4..3da2c3c1 100644 --- a/src/macro/ForwardDeclarationsAndEnums.hh +++ b/src/macro/ForwardDeclarationsAndEnums.hh @@ -67,6 +67,7 @@ namespace macro enum class UnaryOp { + cast_int, logical_not, unary_minus, unary_plus, diff --git a/src/macro/Parser.yy b/src/macro/Parser.yy index 1cf97875..d2764da2 100644 --- a/src/macro/Parser.yy +++ b/src/macro/Parser.yy @@ -65,6 +65,8 @@ using namespace macro; %token SQRT CBRT SIGN MAX MIN FLOOR CEIL TRUNC SUM MOD %token ERF ERFC GAMMA LGAMMA ROUND NORMPDF NORMCDF LENGTH +%token INT + %left OR %left AND %left EQUAL_EQUAL NOT_EQUAL @@ -76,6 +78,7 @@ using namespace macro; %left PLUS MINUS %left TIMES DIVIDE %precedence UMINUS UPLUS NOT +%precedence CAST_INT %nonassoc POWER %token <string> NAME TEXT QUOTED_STRING NUMBER EOL @@ -319,6 +322,8 @@ expr : LPAREN expr RPAREN { $$ = make_shared<Comprehension>($2, $4, $6, driver.env, @$); } | LBRACKET expr FOR expr IN expr WHEN expr RBRACKET { $$ = make_shared<Comprehension>($2, $4, $6, $8, driver.env, @$); } + | LPAREN INT RPAREN expr %prec CAST_INT + { $$ = make_shared<UnaryOp>(codes::UnaryOp::cast_int, $4, driver.env, @$); } | NOT expr { $$ = make_shared<UnaryOp>(codes::UnaryOp::logical_not, $2, driver.env, @$); } | MINUS expr %prec UMINUS diff --git a/src/macro/Tokenizer.ll b/src/macro/Tokenizer.ll index fce6e6fb..d09a57b3 100644 --- a/src/macro/Tokenizer.ll +++ b/src/macro/Tokenizer.ll @@ -142,6 +142,8 @@ CONT \\\\{SPC}* <expr,eval>normpdf { return token::NORMPDF; } <expr,eval>normcdf { return token::NORMCDF; } +<expr,eval>int { return token::INT; } + <expr,eval>((([0-9]*\.[0-9]+)|([0-9]+\.))([ed][-+]?[0-9]+)?)|([0-9]+([ed][-+]?[0-9]+)?)|nan|inf { yylval->build<string>(yytext); return token::NUMBER; -- GitLab