diff --git a/src/macro/Expressions.cc b/src/macro/Expressions.cc index 64d6f1e8..dff5e548 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 757dacdf..d77599a9 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(vector{make_shared(value, env)}, env); } + inline BoolPtr defined() const override + { + return make_shared(env.isSymbolDefined(value), env); + } }; diff --git a/src/macro/ForwardDeclarationsAndEnums.hh b/src/macro/ForwardDeclarationsAndEnums.hh index 5b342e8c..d34b0a49 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 2de754cf..13244b40 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(codes::TrinaryOp::normpdf, $3, $5, $7, driver.env, @$); } | NORMCDF LPAREN expr COMMA expr COMMA expr RPAREN { $$ = make_shared(codes::TrinaryOp::normcdf, $3, $5, $7, driver.env, @$); } + | DEFINED LPAREN NAME RPAREN + { $$ = make_shared(codes::UnaryOp::defined, make_shared($3, driver.env, @3), driver.env, @$); } ; oper_expr : primary_expr diff --git a/src/macro/Tokenizer.ll b/src/macro/Tokenizer.ll index 941b30d7..e93b4f79 100644 --- a/src/macro/Tokenizer.ll +++ b/src/macro/Tokenizer.ll @@ -156,6 +156,8 @@ CONT \\\\{SPC}* tuple { return token::TUPLE; } array { return token::ARRAY; } +defined { return token::DEFINED; } + ((([0-9]*\.[0-9]+)|([0-9]+\.))([ed][-+]?[0-9]+)?)|([0-9]+([ed][-+]?[0-9]+)?)|nan|inf { yylval->build(yytext); return token::NUMBER;