#include #include #include #include namespace anthem { namespace ast { //////////////////////////////////////////////////////////////////////////////////////////////////// // // ASTCopy // //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// // Preparing Copying //////////////////////////////////////////////////////////////////////////////////////////////////// template struct VariantDeepCopyVisitor { template Variant visit(const T &x) { return prepareCopy(x); } }; //////////////////////////////////////////////////////////////////////////////////////////////////// template std::unique_ptr prepareCopy(const std::unique_ptr &uniquePtr) { return std::make_unique(prepareCopy(*uniquePtr)); } //////////////////////////////////////////////////////////////////////////////////////////////////// const auto prepareCopyVariant = [](const auto &variant) -> typename std::decay::type { using VariantType = typename std::decay::type; return variant.accept(VariantDeepCopyVisitor()); }; //////////////////////////////////////////////////////////////////////////////////////////////////// const auto prepareCopyVariantVector = [](const auto &variantVector) -> typename std::decay::type { using Type = typename std::decay::type::value_type; std::vector result; result.reserve(variantVector.size()); for (const auto &variant : variantVector) result.emplace_back(prepareCopyVariant(variant)); return result; }; //////////////////////////////////////////////////////////////////////////////////////////////////// const auto prepareCopyVector = [](const auto &vector) -> typename std::decay::type { using Type = typename std::decay::type::value_type; std::vector result; result.reserve(vector.size()); for (const auto &element : vector) result.emplace_back(prepareCopy(element)); return result; }; //////////////////////////////////////////////////////////////////////////////////////////////////// BinaryOperation prepareCopy(const BinaryOperation &other) { return BinaryOperation(other.operator_, prepareCopy(other.left), prepareCopy(other.right)); } //////////////////////////////////////////////////////////////////////////////////////////////////// Boolean prepareCopy(const Boolean &other) { return Boolean(other.value); } //////////////////////////////////////////////////////////////////////////////////////////////////// Comparison prepareCopy(const Comparison &other) { return Comparison(other.operator_, prepareCopy(other.left), prepareCopy(other.right)); } //////////////////////////////////////////////////////////////////////////////////////////////////// Function prepareCopy(const Function &other) { return Function(other.declaration, prepareCopy(other.arguments)); } //////////////////////////////////////////////////////////////////////////////////////////////////// In prepareCopy(const In &other) { return In(prepareCopy(other.element), prepareCopy(other.set)); } //////////////////////////////////////////////////////////////////////////////////////////////////// Integer prepareCopy(const Integer &other) { return Integer(other.value); } //////////////////////////////////////////////////////////////////////////////////////////////////// Interval prepareCopy(const Interval &other) { return Interval(prepareCopy(other.from), prepareCopy(other.to)); } //////////////////////////////////////////////////////////////////////////////////////////////////// Predicate prepareCopy(const Predicate &other) { return Predicate(other.declaration, prepareCopy(other.arguments)); } //////////////////////////////////////////////////////////////////////////////////////////////////// SpecialInteger prepareCopy(const SpecialInteger &other) { return SpecialInteger(other.type); } //////////////////////////////////////////////////////////////////////////////////////////////////// String prepareCopy(const String &other) { return String(std::string(other.text)); } //////////////////////////////////////////////////////////////////////////////////////////////////// UnaryOperation prepareCopy(const UnaryOperation &other) { return UnaryOperation(other.operator_, prepareCopy(other.argument)); } //////////////////////////////////////////////////////////////////////////////////////////////////// Variable prepareCopy(const Variable &other) { return Variable(other.declaration); } //////////////////////////////////////////////////////////////////////////////////////////////////// VariableDeclaration prepareCopy(const VariableDeclaration &other) { return VariableDeclaration(other.type, std::string(other.name)); } //////////////////////////////////////////////////////////////////////////////////////////////////// VariableDeclarationPointers prepareCopy(const VariableDeclarationPointers &other) { return prepareCopyVector(other); } //////////////////////////////////////////////////////////////////////////////////////////////////// And prepareCopy(const And &other) { return And(prepareCopy(other.arguments)); } //////////////////////////////////////////////////////////////////////////////////////////////////// Biconditional prepareCopy(const Biconditional &other) { return Biconditional(prepareCopy(other.left), prepareCopy(other.right)); } //////////////////////////////////////////////////////////////////////////////////////////////////// Exists prepareCopy(const Exists &other) { Exists copy(prepareCopy(other.variables), prepareCopy(other.argument)); // TODO: refactor for (size_t i = 0; i < other.variables.size(); i++) copy.argument.accept(ReplaceVariableInFormulaVisitor(), copy.argument, other.variables[i].get(), copy.variables[i].get()); return copy; } //////////////////////////////////////////////////////////////////////////////////////////////////// ForAll prepareCopy(const ForAll &other) { ForAll copy(prepareCopy(other.variables), prepareCopy(other.argument)); // TODO: refactor for (size_t i = 0; i < other.variables.size(); i++) copy.argument.accept(ReplaceVariableInFormulaVisitor(), copy.argument, other.variables[i].get(), copy.variables[i].get()); return copy; } //////////////////////////////////////////////////////////////////////////////////////////////////// Implies prepareCopy(const Implies &other) { return Implies(prepareCopy(other.antecedent), prepareCopy(other.consequent)); } //////////////////////////////////////////////////////////////////////////////////////////////////// Not prepareCopy(const Not &other) { return Not(prepareCopy(other.argument)); } //////////////////////////////////////////////////////////////////////////////////////////////////// Or prepareCopy(const Or &other) { return Or(prepareCopy(other.arguments)); } //////////////////////////////////////////////////////////////////////////////////////////////////// Formula prepareCopy(const Formula &formula) { return prepareCopyVariant(formula); } //////////////////////////////////////////////////////////////////////////////////////////////////// Term prepareCopy(const Term &term) { return prepareCopyVariant(term); } //////////////////////////////////////////////////////////////////////////////////////////////////// std::vector prepareCopy(const std::vector &terms) { return prepareCopyVariantVector(terms); } //////////////////////////////////////////////////////////////////////////////////////////////////// std::vector prepareCopy(const std::vector &formulas) { return prepareCopyVariantVector(formulas); } //////////////////////////////////////////////////////////////////////////////////////////////////// // Fixing Dangling Variables //////////////////////////////////////////////////////////////////////////////////////////////////// // Fix all dangling variables in a given term struct FixDanglingVariablesInTermVisitor { template void visit(BinaryOperation &binaryOperation, Arguments &&... arguments) { binaryOperation.left.accept(*this, std::forward(arguments)...); binaryOperation.right.accept(*this, std::forward(arguments)...); } template void visit(Boolean &, Arguments &&...) { } template void visit(Function &function, Arguments &&... arguments) { for (auto &argument : function.arguments) argument.accept(*this, std::forward(arguments)...); } template void visit(Integer &, Arguments &&...) { } template void visit(Interval &interval, Arguments &&... arguments) { interval.from.accept(*this, std::forward(arguments)...); interval.to.accept(*this, std::forward(arguments)...); } template void visit(SpecialInteger &, Arguments &&...) { } template void visit(String &, Arguments &&...) { } template void visit(UnaryOperation &unaryOperation, Arguments &&... arguments) { unaryOperation.argument.accept(*this, std::forward(arguments)...); } void visit(Variable &variable, ScopedFormula &scopedFormula, VariableStack &variableStack, std::map &replacements) { const auto match = replacements.find(variable.declaration); // Replace the variable if it is flagged for replacement if (match != replacements.cend()) { variable.declaration = match->second; return; } // If the variable is not flagged for replacement yet, check whether it is dangling const auto isVariableDangling = !variableStack.contains(*variable.declaration); if (!isVariableDangling) return; // If the variable is dangling, declare it correctly and flag it for future replacement auto newVariableDeclaration = std::make_unique(variable.declaration->type, std::string(variable.declaration->name)); scopedFormula.freeVariables.emplace_back(std::move(newVariableDeclaration)); replacements[variable.declaration] = scopedFormula.freeVariables.back().get(); variable.declaration = scopedFormula.freeVariables.back().get(); } }; //////////////////////////////////////////////////////////////////////////////////////////////////// // Fix all dangling variables in a given formula struct FixDanglingVariablesInFormulaVisitor { template void visit(And &and_, Arguments &&... arguments) { for (auto &argument : and_.arguments) argument.accept(*this, std::forward(arguments)...); } template void visit(Biconditional &biconditional, Arguments &&... arguments) { biconditional.left.accept(*this, std::forward(arguments)...); biconditional.right.accept(*this, std::forward(arguments)...); } template void visit(Boolean &, Arguments &&...) { } template void visit(Comparison &comparison, Arguments &&... arguments) { comparison.left.accept(FixDanglingVariablesInTermVisitor(), std::forward(arguments)...); comparison.right.accept(FixDanglingVariablesInTermVisitor(), std::forward(arguments)...); } void visit(Exists &exists, ScopedFormula &scopedFormula, VariableStack &variableStack, std::map &replacements) { variableStack.push(&exists.variables); exists.argument.accept(*this, scopedFormula, variableStack, replacements); variableStack.pop(); } void visit(ForAll &forAll, ScopedFormula &scopedFormula, VariableStack &variableStack, std::map &replacements) { variableStack.push(&forAll.variables); forAll.argument.accept(*this, scopedFormula, variableStack, replacements); variableStack.pop(); } template void visit(Implies &implies, Arguments &&... arguments) { implies.antecedent.accept(*this, std::forward(arguments)...); implies.consequent.accept(*this, std::forward(arguments)...); } template void visit(In &in, Arguments &&... arguments) { in.element.accept(FixDanglingVariablesInTermVisitor(), std::forward(arguments)...); in.set.accept(FixDanglingVariablesInTermVisitor(), std::forward(arguments)...); } template void visit(Not ¬_, Arguments &&... arguments) { not_.argument.accept(*this, std::forward(arguments)...); } template void visit(Or &or_, Arguments &&... arguments) { for (auto &argument : or_.arguments) argument.accept(*this, std::forward(arguments)...); } template void visit(Predicate &predicate, Arguments &&... arguments) { for (auto &argument : predicate.arguments) argument.accept(FixDanglingVariablesInTermVisitor(), std::forward(arguments)...); } }; //////////////////////////////////////////////////////////////////////////////////////////////////// void fixDanglingVariables(ScopedFormula &scopedFormula) { VariableStack variableStack; variableStack.push(&scopedFormula.freeVariables); std::map replacements; scopedFormula.formula.accept(FixDanglingVariablesInFormulaVisitor(), scopedFormula, variableStack, replacements); } //////////////////////////////////////////////////////////////////////////////////////////////////// } }