diff --git a/src/macro/Expressions.cc b/src/macro/Expressions.cc index 64d6f1e80bcedcee7fa2fab75c1548f869139520..dff5e5481e116032e1286d3bac5df1f0c700aafc 100644 --- a/src/macro/Expressions.cc +++ b/src/macro/Expressions.cc @@ -861,6 +861,8 @@ UnaryOp::eval() return argbt->normpdf(); case codes::UnaryOp::normcdf: return argbt->normcdf(); + case codes::UnaryOp::defined: + return argbt->defined(); } } catch (StackTrace &ex) @@ -1203,6 +1205,8 @@ UnaryOp::to_string() const noexcept return "normpdf(" + retval + ")"; case codes::UnaryOp::normcdf: return "normcdf(" + retval + ")"; + case codes::UnaryOp::defined: + return "defined(" + retval + ")"; } // Suppress GCC warning exit(EXIT_FAILURE); @@ -1463,6 +1467,9 @@ UnaryOp::print(ostream &output, bool matlab_output) const noexcept case codes::UnaryOp::normcdf: output << "normcdf("; break; + case codes::UnaryOp::defined: + output << "defined("; + break; } arg->print(output, matlab_output); diff --git a/src/macro/Expressions.hh b/src/macro/Expressions.hh index 757dacdfde841c9d7d494a05ede8346916bd574a..d77599a9b2df4bf4d0f5c080696645988c18e07c 100644 --- a/src/macro/Expressions.hh +++ b/src/macro/Expressions.hh @@ -191,6 +191,7 @@ namespace macro virtual StringPtr cast_string() const { throw StackTrace("This type cannot be cast to a string"); } virtual TuplePtr cast_tuple() const { throw StackTrace("This type cannot be cast to a tuple"); } virtual ArrayPtr cast_array() const { throw StackTrace("This type cannot be cast to an array"); } + virtual BoolPtr defined() const { throw StackTrace("Operator `defined` does not exist for this type"); } }; @@ -358,6 +359,10 @@ namespace macro { return make_shared<Array>(vector<ExpressionPtr>{make_shared<String>(value, env)}, env); } + inline BoolPtr defined() const override + { + return make_shared<Bool>(env.isSymbolDefined(value), env); + } }; diff --git a/src/macro/ForwardDeclarationsAndEnums.hh b/src/macro/ForwardDeclarationsAndEnums.hh index 5b342e8caf3819f6e47c25acb4449667adabd95d..d34b0a49b417128b3962f59f0c7aacbf2e907083 100644 --- a/src/macro/ForwardDeclarationsAndEnums.hh +++ b/src/macro/ForwardDeclarationsAndEnums.hh @@ -104,7 +104,8 @@ namespace macro lgamma, round, normpdf, - normcdf + normcdf, + defined }; enum class BinaryOp diff --git a/src/macro/Parser.yy b/src/macro/Parser.yy index 2de754cf61c40d02d09282c8f354199db3dab50b..13244b40a32faa36513913e143191610b9b53554 100644 --- a/src/macro/Parser.yy +++ b/src/macro/Parser.yy @@ -70,6 +70,8 @@ using namespace macro; %token BOOL REAL STRING TUPLE ARRAY +%token DEFINED + %left OR %left AND %left EQUAL_EQUAL NOT_EQUAL @@ -392,6 +394,8 @@ primary_expr : LPAREN expr RPAREN { $$ = make_shared<TrinaryOp>(codes::TrinaryOp::normpdf, $3, $5, $7, driver.env, @$); } | NORMCDF LPAREN expr COMMA expr COMMA expr RPAREN { $$ = make_shared<TrinaryOp>(codes::TrinaryOp::normcdf, $3, $5, $7, driver.env, @$); } + | DEFINED LPAREN NAME RPAREN + { $$ = make_shared<UnaryOp>(codes::UnaryOp::defined, make_shared<String>($3, driver.env, @3), driver.env, @$); } ; oper_expr : primary_expr diff --git a/src/macro/Tokenizer.ll b/src/macro/Tokenizer.ll index 941b30d742e54486996d219ccbd27e682b367744..e93b4f791481588e9d8eded081611deff6c8ae25 100644 --- a/src/macro/Tokenizer.ll +++ b/src/macro/Tokenizer.ll @@ -156,6 +156,8 @@ CONT \\\\{SPC}* <expr,eval>tuple { return token::TUPLE; } <expr,eval>array { return token::ARRAY; } +<expr,eval>defined { return token::DEFINED; } + <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;