#include #include namespace anthem { namespace ast { //////////////////////////////////////////////////////////////////////////////////////////////////// // // AST Utils // //////////////////////////////////////////////////////////////////////////////////////////////////// void VariableStack::push(Layer layer) { m_layers.push_back(layer); } //////////////////////////////////////////////////////////////////////////////////////////////////// void VariableStack::pop() { m_layers.pop_back(); } //////////////////////////////////////////////////////////////////////////////////////////////////// std::optional VariableStack::findUserVariableDeclaration(const char *variableName) const { const auto variableDeclarationMatches = [&variableName](const auto &variableDeclaration) { return variableDeclaration->type == VariableDeclaration::Type::UserDefined && variableDeclaration->name == variableName; }; for (auto i = m_layers.rbegin(); i != m_layers.rend(); i++) { auto &layer = **i; const auto matchingVariableDeclaration = std::find_if(layer.begin(), layer.end(), variableDeclarationMatches); if (matchingVariableDeclaration != layer.end()) return matchingVariableDeclaration->get(); } return std::nullopt; } //////////////////////////////////////////////////////////////////////////////////////////////////// bool VariableStack::contains(const VariableDeclaration &variableDeclaration) const { const auto variableDeclarationMatches = [&variableDeclaration](const auto &other) { return &variableDeclaration == other.get(); }; const auto layerContainsVariableDeclaration = [&variableDeclarationMatches](const auto &layer) { return (std::find_if(layer->cbegin(), layer->cend(), variableDeclarationMatches) != layer->cend()); }; return (std::find_if(m_layers.cbegin(), m_layers.cend(), layerContainsVariableDeclaration) != m_layers.cend()); } //////////////////////////////////////////////////////////////////////////////////////////////////// struct CollectFreeVariablesVisitor { //////////////////////////////////////////////////////////////////////////////////////////////// // Formulas //////////////////////////////////////////////////////////////////////////////////////////////// void visit(And &and_, VariableStack &variableStack, std::vector &freeVariables) { for (auto &argument : and_.arguments) argument.accept(*this, variableStack, freeVariables); } void visit(Biconditional &biconditional, VariableStack &variableStack, std::vector &freeVariables) { biconditional.left.accept(*this, variableStack, freeVariables); biconditional.right.accept(*this, variableStack, freeVariables); } void visit(Boolean &, VariableStack &, std::vector &) { } void visit(Comparison &comparison, VariableStack &variableStack, std::vector &freeVariables) { comparison.left.accept(*this, variableStack, freeVariables); comparison.right.accept(*this, variableStack, freeVariables); } void visit(Exists &exists, VariableStack &variableStack, std::vector &freeVariables) { variableStack.push(&exists.variables); exists.argument.accept(*this, variableStack, freeVariables); variableStack.pop(); } void visit(ForAll &forAll, VariableStack &variableStack, std::vector &freeVariables) { variableStack.push(&forAll.variables); forAll.argument.accept(*this, variableStack, freeVariables); variableStack.pop(); } void visit(Implies &implies, VariableStack &variableStack, std::vector &freeVariables) { implies.antecedent.accept(*this, variableStack, freeVariables); implies.consequent.accept(*this, variableStack, freeVariables); } void visit(In &in, VariableStack &variableStack, std::vector &freeVariables) { in.element.accept(*this, variableStack, freeVariables); in.set.accept(*this, variableStack, freeVariables); } void visit(Not ¬_, VariableStack &variableStack, std::vector &freeVariables) { not_.argument.accept(*this, variableStack, freeVariables); } void visit(Or &or_, VariableStack &variableStack, std::vector &freeVariables) { for (auto &argument : or_.arguments) argument.accept(*this, variableStack, freeVariables); } void visit(Predicate &predicate, VariableStack &variableStack, std::vector &freeVariables) { for (auto &argument : predicate.arguments) argument.accept(*this, variableStack, freeVariables); } //////////////////////////////////////////////////////////////////////////////////////////////// // Terms //////////////////////////////////////////////////////////////////////////////////////////////// void visit(BinaryOperation &binaryOperation, VariableStack &variableStack, std::vector &freeVariables) { binaryOperation.left.accept(*this, variableStack, freeVariables); binaryOperation.right.accept(*this, variableStack, freeVariables); } void visit(Constant &, VariableStack &, std::vector &) { } void visit(Function &function, VariableStack &variableStack, std::vector &freeVariables) { for (auto &argument : function.arguments) argument.accept(*this, variableStack, freeVariables); } void visit(Integer &, VariableStack &, std::vector &) { } void visit(Interval &interval, VariableStack &variableStack, std::vector &freeVariables) { interval.from.accept(*this, variableStack, freeVariables); interval.to.accept(*this, variableStack, freeVariables); } void visit(SpecialInteger &, VariableStack &, std::vector &) { } void visit(String &, VariableStack &, std::vector &) { } void visit(UnaryOperation &unaryOperation, VariableStack &variableStack, std::vector &freeVariables) { unaryOperation.argument.accept(*this, variableStack, freeVariables); } void visit(Variable &variable, VariableStack &variableStack, std::vector &freeVariables) { if (variableStack.contains(*variable.declaration)) return; if (std::find(freeVariables.cbegin(), freeVariables.cend(), variable.declaration) != freeVariables.cend()) return; freeVariables.emplace_back(variable.declaration); } }; //////////////////////////////////////////////////////////////////////////////////////////////////// struct CollectPredicateSignaturesVisitor : public RecursiveFormulaVisitor { static void accept(const Predicate &predicate, const Formula &, std::vector &predicateSignatures, Context &context) { const auto predicateSignatureMatches = [&predicate](const auto &predicateSignature) { return matches(predicate, predicateSignature); }; if (std::find_if(predicateSignatures.cbegin(), predicateSignatures.cend(), predicateSignatureMatches) != predicateSignatures.cend()) return; // TODO: avoid copies auto predicateSignature = PredicateSignature(std::string(predicate.name), predicate.arity()); // Ignore predicates that are declared #external if (context.externalPredicateSignatures) { const auto matchesPredicateSignature = [&](const auto &otherPredicateSignature) { return ast::matches(predicateSignature, otherPredicateSignature.predicateSignature); }; auto &externalPredicateSignatures = context.externalPredicateSignatures.value(); const auto matchingExternalPredicateSignature = std::find_if(externalPredicateSignatures.begin(), externalPredicateSignatures.end(), matchesPredicateSignature); if (matchingExternalPredicateSignature != externalPredicateSignatures.end()) { matchingExternalPredicateSignature->used = true; return; } } predicateSignatures.emplace_back(std::move(predicateSignature)); } // Ignore all other types of expressions template static void accept(const T &, const Formula &, std::vector &, const Context &) { } }; //////////////////////////////////////////////////////////////////////////////////////////////////// bool matches(const Predicate &lhs, const Predicate &rhs) { return (lhs.name == rhs.name && lhs.arity() == rhs.arity()); } //////////////////////////////////////////////////////////////////////////////////////////////////// bool matches(const Predicate &predicate, const PredicateSignature &signature) { return (predicate.name == signature.name && predicate.arity() == signature.arity); } //////////////////////////////////////////////////////////////////////////////////////////////////// bool matches(const PredicateSignature &lhs, const PredicateSignature &rhs) { return (lhs.name == rhs.name && lhs.arity == rhs.arity); } //////////////////////////////////////////////////////////////////////////////////////////////////// // TODO: remove const_cast void collectPredicateSignatures(const Formula &formula, std::vector &predicateSignatures, Context &context) { auto &formulaMutable = const_cast(formula); formulaMutable.accept(CollectPredicateSignaturesVisitor(), formulaMutable, predicateSignatures, context); } //////////////////////////////////////////////////////////////////////////////////////////////////// } }