diff --git a/src/macro/Directives.cc b/src/macro/Directives.cc index 7a89e45a..e76bf449 100644 --- a/src/macro/Directives.cc +++ b/src/macro/Directives.cc @@ -245,19 +245,35 @@ For::interpret(ostream &output, vector &paths) void If::interpret(ostream &output, vector &paths) { + bool first_clause = true; for (const auto & [expr, body] : expr_and_body) try { - auto tmp = expr->eval(); - RealPtr dp = dynamic_pointer_cast(tmp); - BoolPtr bp = dynamic_pointer_cast(tmp); - if (!bp && !dp) - error(StackTrace("@#if", - "The condition must evaluate to a boolean or a double", location)); - if ((bp && *bp) || (dp && *dp)) + if ((ifdef || ifndef) && first_clause) { - interpretBody(body, output, paths); - break; + first_clause = false; + VariablePtr vp = dynamic_pointer_cast(expr); + assert(vp); + if ((ifdef && env.isVariableDefined(vp->getName())) + || (ifndef && !env.isVariableDefined(vp->getName()))) + { + interpretBody(body, output, paths); + break; + } + } + else + { + auto tmp = expr->eval(); + RealPtr dp = dynamic_pointer_cast(tmp); + BoolPtr bp = dynamic_pointer_cast(tmp); + if (!bp && !dp) + error(StackTrace("@#if", + "The condition must evaluate to a boolean or a double", location)); + if ((bp && *bp) || (dp && *dp)) + { + interpretBody(body, output, paths); + break; + } } } catch (StackTrace &ex) @@ -286,31 +302,3 @@ If::interpretBody(const vector &body, ostream &output, vectorinterpret(output, paths); } } - -void -Ifdef::interpret(ostream &output, vector &paths) -{ - for (const auto & [expr, body] : expr_and_body) - if (VariablePtr vp = dynamic_pointer_cast(expr); - dynamic_pointer_cast(expr) - || (vp && env.isVariableDefined(vp->getName()))) - { - interpretBody(body, output, paths); - break; - } - printEndLineInfo(output); -} - -void -Ifndef::interpret(ostream &output, vector &paths) -{ - for (const auto & [expr, body] : expr_and_body) - if (VariablePtr vp = dynamic_pointer_cast(expr); - dynamic_pointer_cast(expr) - || (vp && !env.isVariableDefined(vp->getName()))) - { - interpretBody(body, output, paths); - break; - } - printEndLineInfo(output); -} diff --git a/src/macro/Directives.hh b/src/macro/Directives.hh index db71ae3f..cc7ec6e1 100644 --- a/src/macro/Directives.hh +++ b/src/macro/Directives.hh @@ -175,24 +175,25 @@ namespace macro * If there is an `else` statement it is the last element in the vector. Its condition is true. */ const vector>> expr_and_body; + const bool ifdef, ifndef; public: If(vector>> expr_and_body_arg, - Environment &env_arg, Tokenizer::location location_arg) : - Directive(env_arg, move(location_arg)), expr_and_body{move(expr_and_body_arg)} { } + Environment &env_arg, Tokenizer::location location_arg, + bool ifdef_arg = false, bool ifndef_arg = false) : + Directive(env_arg, move(location_arg)), expr_and_body{move(expr_and_body_arg)}, + ifdef{ifdef_arg}, ifndef{ifndef_arg} { } void interpret(ostream &output, vector &paths) override; protected: void interpretBody(const vector &body, ostream &output, vector &paths); }; - class Ifdef : public If { public: Ifdef(vector>> expr_and_body_arg, Environment &env_arg, Tokenizer::location location_arg) : - If(move(expr_and_body_arg), env_arg, move(location_arg)) { } - void interpret(ostream &output, vector &paths) override; + If(move(expr_and_body_arg), env_arg, move(location_arg), true, false) { } }; @@ -201,8 +202,7 @@ namespace macro public: Ifndef(vector>> expr_and_body_arg, Environment &env_arg, Tokenizer::location location_arg) : - If(move(expr_and_body_arg), env_arg, move(location_arg)) { } - void interpret(ostream &output, vector &paths) override; + If(move(expr_and_body_arg), env_arg, move(location_arg), false, true) { } }; } #endif