Fix the interpretation of @#elseif clauses within an @#ifdef or @#ifndef

parent df8d8ef1
Pipeline #4326 passed with stages
in 3 minutes and 2 seconds
...@@ -245,19 +245,35 @@ For::interpret(ostream &output, vector<filesystem::path> &paths) ...@@ -245,19 +245,35 @@ For::interpret(ostream &output, vector<filesystem::path> &paths)
void void
If::interpret(ostream &output, vector<filesystem::path> &paths) If::interpret(ostream &output, vector<filesystem::path> &paths)
{ {
bool first_clause = true;
for (const auto & [expr, body] : expr_and_body) for (const auto & [expr, body] : expr_and_body)
try try
{ {
auto tmp = expr->eval(); if ((ifdef || ifndef) && first_clause)
RealPtr dp = dynamic_pointer_cast<Real>(tmp);
BoolPtr bp = dynamic_pointer_cast<Bool>(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); first_clause = false;
break; VariablePtr vp = dynamic_pointer_cast<Variable>(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<Real>(tmp);
BoolPtr bp = dynamic_pointer_cast<Bool>(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) catch (StackTrace &ex)
...@@ -286,31 +302,3 @@ If::interpretBody(const vector<DirectivePtr> &body, ostream &output, vector<file ...@@ -286,31 +302,3 @@ If::interpretBody(const vector<DirectivePtr> &body, ostream &output, vector<file
statement->interpret(output, paths); statement->interpret(output, paths);
} }
} }
void
Ifdef::interpret(ostream &output, vector<filesystem::path> &paths)
{
for (const auto & [expr, body] : expr_and_body)
if (VariablePtr vp = dynamic_pointer_cast<Variable>(expr);
dynamic_pointer_cast<BaseType>(expr)
|| (vp && env.isVariableDefined(vp->getName())))
{
interpretBody(body, output, paths);
break;
}
printEndLineInfo(output);
}
void
Ifndef::interpret(ostream &output, vector<filesystem::path> &paths)
{
for (const auto & [expr, body] : expr_and_body)
if (VariablePtr vp = dynamic_pointer_cast<Variable>(expr);
dynamic_pointer_cast<BaseType>(expr)
|| (vp && !env.isVariableDefined(vp->getName())))
{
interpretBody(body, output, paths);
break;
}
printEndLineInfo(output);
}
...@@ -175,24 +175,25 @@ namespace macro ...@@ -175,24 +175,25 @@ namespace macro
* If there is an `else` statement it is the last element in the vector. Its condition is true. * If there is an `else` statement it is the last element in the vector. Its condition is true.
*/ */
const vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body; const vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body;
const bool ifdef, ifndef;
public: public:
If(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg, If(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg,
Environment &env_arg, Tokenizer::location location_arg) : Environment &env_arg, Tokenizer::location location_arg,
Directive(env_arg, move(location_arg)), expr_and_body{move(expr_and_body_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<filesystem::path> &paths) override; void interpret(ostream &output, vector<filesystem::path> &paths) override;
protected: protected:
void interpretBody(const vector<DirectivePtr> &body, ostream &output, void interpretBody(const vector<DirectivePtr> &body, ostream &output,
vector<filesystem::path> &paths); vector<filesystem::path> &paths);
}; };
class Ifdef : public If class Ifdef : public If
{ {
public: public:
Ifdef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg, Ifdef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg,
Environment &env_arg, Tokenizer::location location_arg) : Environment &env_arg, Tokenizer::location location_arg) :
If(move(expr_and_body_arg), env_arg, move(location_arg)) { } If(move(expr_and_body_arg), env_arg, move(location_arg), true, false) { }
void interpret(ostream &output, vector<filesystem::path> &paths) override;
}; };
...@@ -201,8 +202,7 @@ namespace macro ...@@ -201,8 +202,7 @@ namespace macro
public: public:
Ifndef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg, Ifndef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg,
Environment &env_arg, Tokenizer::location location_arg) : Environment &env_arg, Tokenizer::location location_arg) :
If(move(expr_and_body_arg), env_arg, move(location_arg)) { } If(move(expr_and_body_arg), env_arg, move(location_arg), false, true) { }
void interpret(ostream &output, vector<filesystem::path> &paths) override;
}; };
} }
#endif #endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment