#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(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); } }; //////////////////////////////////////////////////////////////////////////////////////////////////// } }