From 664a57ec688840950db9010f7474d87898210ae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Tue, 30 May 2017 18:09:33 +0200 Subject: [PATCH] Fixed issue with multi-layer variable stacks. --- include/anthem/Body.h | 7 +++++-- src/anthem/ASTUtils.cpp | 4 ++-- tests/TestTranslation.cpp | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/include/anthem/Body.h b/include/anthem/Body.h index 8c78ef7..003cd49 100644 --- a/include/anthem/Body.h +++ b/include/anthem/Body.h @@ -62,11 +62,12 @@ struct BodyTermTranslateVisitor std::vector> parameters; parameters.reserve(function.arguments.size()); - variableStack.push(¶meters); - for (size_t i = 0; i < function.arguments.size(); i++) parameters.emplace_back(std::make_unique(ast::VariableDeclaration::Type::Body)); + // TODO: implement pushing with scoped guards to avoid bugs + variableStack.push(¶meters); + ast::And conjunction; for (size_t i = 0; i < function.arguments.size(); i++) @@ -75,6 +76,8 @@ struct BodyTermTranslateVisitor conjunction.arguments.emplace_back(ast::Formula::make(ast::Variable(parameters[i].get()), translate(argument, context, ruleContext, variableStack))); } + variableStack.pop(); + ast::Predicate predicate(std::string(function.name)); predicate.arguments.reserve(function.arguments.size()); diff --git a/src/anthem/ASTUtils.cpp b/src/anthem/ASTUtils.cpp index 4ae6d4d..0cc7c86 100644 --- a/src/anthem/ASTUtils.cpp +++ b/src/anthem/ASTUtils.cpp @@ -29,7 +29,7 @@ void VariableStack::pop() std::experimental::optional VariableStack::findUserVariableDeclaration(const char *variableName) const { - const auto variableNameMatches = + const auto variableDeclarationMatches = [&variableName](const auto &variableDeclaration) { return variableDeclaration->type == VariableDeclaration::Type::UserDefined @@ -39,7 +39,7 @@ std::experimental::optional VariableStack::findUserV for (auto i = m_layers.rbegin(); i != m_layers.rend(); i++) { auto &layer = **i; - const auto matchingVariableDeclaration = std::find_if(layer.begin(), layer.end(), variableNameMatches); + const auto matchingVariableDeclaration = std::find_if(layer.begin(), layer.end(), variableDeclarationMatches); if (matchingVariableDeclaration != layer.end()) return matchingVariableDeclaration->get(); diff --git a/tests/TestTranslation.cpp b/tests/TestTranslation.cpp index e2355b6..38bd4d0 100644 --- a/tests/TestTranslation.cpp +++ b/tests/TestTranslation.cpp @@ -181,6 +181,22 @@ TEST_CASE("[translation] Rules are translated correctly", "[translation]") CHECK(output.str() == "((V1 in U1 and V2 in 1..10 and exists X1, X2 (X1 in U1 and X2 in 6..12 and q(X1, X2))) -> p(V1, V2))\n"); } + SECTION("intervals with variable") + { + input << ":- q(N), 1 = 1..N."; + anthem::translate("input", input, context); + + CHECK(output.str() == "((exists X1 (X1 in U1 and q(X1)) and exists X2, X3 (X2 in 1 and X3 in 1..U1 and X2 = X3)) -> #false)\n"); + } + + SECTION("intervals with two variables") + { + input << ":- q(M, N), M = 1..N."; + anthem::translate("input", input, context); + + CHECK(output.str() == "((exists X1, X2 (X1 in U1 and X2 in U2 and q(X1, X2)) and exists X3, X4 (X3 in U1 and X4 in 1..U2 and X3 = X4)) -> #false)\n"); + } + SECTION("comparisons") { input << "p(M, N, O, P) :- M < N, P != O.";