From b3798a0baacf138c389e9969f5a41cff97b58839 Mon Sep 17 00:00:00 2001 From: Houtan Bastani Date: Mon, 5 Aug 2019 14:04:57 -0400 Subject: [PATCH] macro processor: introduce bool casts --- src/macro/Expressions.cc | 39 +++++++++++++++++++++++- src/macro/Expressions.hh | 10 ++++-- src/macro/ForwardDeclarationsAndEnums.hh | 1 + src/macro/Parser.yy | 6 ++-- src/macro/Tokenizer.ll | 1 + 5 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/macro/Expressions.cc b/src/macro/Expressions.cc index d1a55187..a740b6f9 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(value == btp2->value, env); } +BoolPtr +String::cast_bool() const +{ + try + { + return make_shared(static_cast(stoi(value)), env); + } + catch (...) + { + throw StackTrace(value + " cannot be converted to a boolean"); + } +} + DoublePtr String::cast_int() const { @@ -518,6 +531,14 @@ Array::sum() const return make_shared(retval, env); } +BoolPtr +Array::cast_bool() const +{ + if (arr.size() != 1) + throw StackTrace("Array must be of size 1 to be cast to a boolean"); + return arr.at(0)->eval()->cast_bool(); +} + DoublePtr Array::cast_int() const { @@ -568,6 +589,14 @@ Tuple::contains(const BaseTypePtr &btp) const return make_shared(false, env); } +BoolPtr +Tuple::cast_bool() const +{ + if (tup.size() != 1) + throw StackTrace("Tuple must be of size 1 to be cast to a boolean"); + return tup.at(0)->eval()->cast_bool(); +} + DoublePtr Tuple::cast_int() const { @@ -767,6 +796,8 @@ UnaryOp::eval() auto argbt = arg->eval(); switch (op_code) { + case codes::UnaryOp::cast_bool: + return argbt->cast_bool(); case codes::UnaryOp::cast_int: return argbt->cast_int(); case codes::UnaryOp::cast_double: @@ -1097,6 +1128,8 @@ UnaryOp::to_string() const noexcept string retval = arg->to_string(); switch (op_code) { + case codes::UnaryOp::cast_bool: + return "(bool)" + retval; case codes::UnaryOp::cast_int: return "(int)" + retval; case codes::UnaryOp::cast_double: @@ -1307,6 +1340,9 @@ UnaryOp::print(ostream &output, bool matlab_output) const noexcept { switch (op_code) { + case codes::UnaryOp::cast_bool: + output << "(bool)"; + break; case codes::UnaryOp::cast_int: output << "(int)"; break; @@ -1407,7 +1443,8 @@ UnaryOp::print(ostream &output, bool matlab_output) const noexcept arg->print(output, matlab_output); - if (op_code != codes::UnaryOp::cast_int + if (op_code != codes::UnaryOp::cast_bool + && op_code != codes::UnaryOp::cast_int && op_code != codes::UnaryOp::cast_double && op_code != codes::UnaryOp::cast_string && op_code != codes::UnaryOp::cast_tuple diff --git a/src/macro/Expressions.hh b/src/macro/Expressions.hh index d195ac15..7d7143ff 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 BoolPtr cast_bool() const { throw StackTrace("This type cannot be cast to a boolean"); } virtual DoublePtr cast_int() const { throw StackTrace("This type cannot be cast to an integer"); } virtual DoublePtr cast_double() const { throw StackTrace("This type cannot be cast to a double"); } virtual StringPtr cast_string() const { throw StackTrace("This type cannot be cast to a string"); } @@ -207,6 +208,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 BoolPtr cast_bool() const override { return make_shared(value, env); } inline DoublePtr cast_int() const override { return value ? make_shared(1, env) : make_shared(0, env); } inline DoublePtr cast_double() const override { return cast_int(); } inline StringPtr cast_string() const override { return make_shared(this->to_string(), env); } @@ -302,6 +304,7 @@ namespace macro return normcdf(make_shared(0, env), make_shared(1, env)); } DoublePtr normcdf(const BaseTypePtr &btp1, const BaseTypePtr &btp2) const override; + inline BoolPtr cast_bool() const override { return make_shared(static_cast(value), env); } inline DoublePtr cast_int() const override { return make_shared(static_cast(value), env); } inline DoublePtr cast_double() const override { return make_shared(value, env); } inline StringPtr cast_string() const override { return make_shared(this->to_string(), env); } @@ -337,8 +340,9 @@ 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(value.size(), env); } - inline DoublePtr cast_int() const override; - inline DoublePtr cast_double() const override; + BoolPtr cast_bool() const override; + DoublePtr cast_int() const override; + DoublePtr cast_double() const override; inline StringPtr cast_string() const override { return make_shared(value, env); } inline TuplePtr cast_tuple() const override { @@ -373,6 +377,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(tup.size(), env); } + BoolPtr cast_bool() const override; DoublePtr cast_int() const override; DoublePtr cast_double() const override; inline StringPtr cast_string() const override { return make_shared(this->to_string(), env); } @@ -419,6 +424,7 @@ namespace macro BoolPtr contains(const BaseTypePtr &btp) const override; inline DoublePtr length() const override { return make_shared(arr.size(), env); } DoublePtr sum() const override; + BoolPtr cast_bool() const override; DoublePtr cast_int() const override; DoublePtr cast_double() const override; inline StringPtr cast_string() const override { return make_shared(this->to_string(), env); } diff --git a/src/macro/ForwardDeclarationsAndEnums.hh b/src/macro/ForwardDeclarationsAndEnums.hh index 78070e8d..09eb1065 100644 --- a/src/macro/ForwardDeclarationsAndEnums.hh +++ b/src/macro/ForwardDeclarationsAndEnums.hh @@ -67,6 +67,7 @@ namespace macro enum class UnaryOp { + cast_bool, cast_int, cast_double, cast_string, diff --git a/src/macro/Parser.yy b/src/macro/Parser.yy index 7940dcfa..36ff4903 100644 --- a/src/macro/Parser.yy +++ b/src/macro/Parser.yy @@ -65,7 +65,7 @@ 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 DOUBLE STRING TUPLE ARRAY +%token BOOL INT DOUBLE STRING TUPLE ARRAY %left OR %left AND @@ -78,7 +78,7 @@ using namespace macro; %left PLUS MINUS %left TIMES DIVIDE %precedence UMINUS UPLUS NOT -%precedence CAST_INT CAST_DOUBLE CAST_STRING CAST_TUPLE CAST_ARRAY +%precedence CAST_BOOL CAST_INT CAST_DOUBLE CAST_STRING CAST_TUPLE CAST_ARRAY %nonassoc POWER %token NAME TEXT QUOTED_STRING NUMBER EOL @@ -322,6 +322,8 @@ expr : LPAREN expr RPAREN { $$ = make_shared($2, $4, $6, driver.env, @$); } | LBRACKET expr FOR expr IN expr WHEN expr RBRACKET { $$ = make_shared($2, $4, $6, $8, driver.env, @$); } + | LPAREN BOOL RPAREN expr %prec CAST_BOOL + { $$ = make_shared(codes::UnaryOp::cast_bool, $4, driver.env, @$); } | LPAREN INT RPAREN expr %prec CAST_INT { $$ = make_shared(codes::UnaryOp::cast_int, $4, driver.env, @$); } | LPAREN DOUBLE RPAREN expr %prec CAST_DOUBLE diff --git a/src/macro/Tokenizer.ll b/src/macro/Tokenizer.ll index dfb15c0f..a9939128 100644 --- a/src/macro/Tokenizer.ll +++ b/src/macro/Tokenizer.ll @@ -142,6 +142,7 @@ CONT \\\\{SPC}* normpdf { return token::NORMPDF; } normcdf { return token::NORMCDF; } +bool { return token::BOOL; } int { return token::INT; } double { return token::DOUBLE; } string { return token::STRING; }