Major refactoring to uniquely link variables to their declarations (breaks simplification and completion).

This commit is contained in:
2017-05-30 03:53:51 +02:00
parent ce159c7bf0
commit 1c925d661b
23 changed files with 1176 additions and 659 deletions

View File

@@ -35,18 +35,18 @@ struct BinaryOperation
Modulo
};
BinaryOperation(const BinaryOperation &other) = delete;
BinaryOperation &operator=(const BinaryOperation &other) = delete;
BinaryOperation(BinaryOperation &&other) noexcept = default;
BinaryOperation &operator=(BinaryOperation &&other) noexcept = default;
BinaryOperation(Operator operator_, Term &&left, Term &&right)
explicit BinaryOperation(Operator operator_, Term &&left, Term &&right)
: operator_{operator_},
left{std::move(left)},
right{std::move(right)}
{
}
BinaryOperation(const BinaryOperation &other) = delete;
BinaryOperation &operator=(const BinaryOperation &other) = delete;
BinaryOperation(BinaryOperation &&other) noexcept = default;
BinaryOperation &operator=(BinaryOperation &&other) noexcept = default;
Operator operator_;
Term left;
Term right;
@@ -56,7 +56,7 @@ struct BinaryOperation
struct Boolean
{
Boolean(bool value)
explicit Boolean(bool value)
: value{value}
{
}
@@ -83,7 +83,7 @@ struct Comparison
Equal
};
Comparison(Operator operator_, Term &&left, Term &&right)
explicit Comparison(Operator operator_, Term &&left, Term &&right)
: operator_{operator_},
left{std::move(left)},
right{std::move(right)}
@@ -104,7 +104,7 @@ struct Comparison
struct Constant
{
Constant(std::string &&name)
explicit Constant(std::string &&name)
: name{std::move(name)}
{
}
@@ -121,12 +121,12 @@ struct Constant
struct Function
{
Function(std::string &&name)
explicit Function(std::string &&name)
: name{std::move(name)}
{
}
Function(std::string &&name, std::vector<Term> &&arguments)
explicit Function(std::string &&name, std::vector<Term> &&arguments)
: name{std::move(name)},
arguments{std::move(arguments)}
{
@@ -146,7 +146,7 @@ struct Function
// TODO: refactor (limit element type to primitive terms)
struct In
{
In(Term &&element, Term &&set)
explicit In(Term &&element, Term &&set)
: element{std::move(element)},
set{std::move(set)}
{
@@ -167,7 +167,7 @@ struct In
struct Integer
{
Integer(int value)
explicit Integer(int value)
: value{value}
{
}
@@ -184,7 +184,7 @@ struct Integer
struct Interval
{
Interval(Term &&from, Term &&to)
explicit Interval(Term &&from, Term &&to)
: from{std::move(from)},
to{std::move(to)}
{
@@ -201,14 +201,15 @@ struct Interval
////////////////////////////////////////////////////////////////////////////////////////////////////
// TODO: implement declaration/signature
struct Predicate
{
Predicate(std::string &&name)
explicit Predicate(std::string &&name)
: name{std::move(name)}
{
}
Predicate(std::string &&name, std::vector<Term> &&arguments)
explicit Predicate(std::string &&name, std::vector<Term> &&arguments)
: name{std::move(name)},
arguments{std::move(arguments)}
{
@@ -238,7 +239,7 @@ struct SpecialInteger
Supremum
};
SpecialInteger(Type type)
explicit SpecialInteger(Type type)
: type{type}
{
}
@@ -255,7 +256,7 @@ struct SpecialInteger
struct String
{
String(std::string &&text)
explicit String(std::string &&text)
: text{std::move(text)}
{
}
@@ -272,15 +273,8 @@ struct String
struct Variable
{
enum class Type
{
UserDefined,
Reserved
};
Variable(std::string &&name, Type type)
: name{std::move(name)},
type{type}
explicit Variable(VariableDeclaration *declaration)
: declaration{declaration}
{
}
@@ -289,6 +283,32 @@ struct Variable
Variable(Variable &&other) = default;
Variable &operator=(Variable &&other) = default;
VariableDeclaration *declaration = nullptr;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
struct VariableDeclaration
{
// TODO: remove
enum class Type
{
UserDefined,
Head,
Body
};
explicit VariableDeclaration(std::string &&name, Type type)
: name{std::move(name)},
type{type}
{
}
VariableDeclaration(const VariableDeclaration &other) = delete;
VariableDeclaration &operator=(const VariableDeclaration &other) = delete;
VariableDeclaration(VariableDeclaration &&other) = default;
VariableDeclaration &operator=(VariableDeclaration &&other) = default;
std::string name;
Type type;
};
@@ -301,7 +321,7 @@ struct And
{
And() = default;
And(std::vector<Formula> &&arguments)
explicit And(std::vector<Formula> &&arguments)
: arguments{std::move(arguments)}
{
}
@@ -318,7 +338,7 @@ struct And
struct Biconditional
{
Biconditional(Formula &&left, Formula &&right)
explicit Biconditional(Formula &&left, Formula &&right)
: left{std::move(left)},
right{std::move(right)}
{
@@ -337,7 +357,8 @@ struct Biconditional
struct Exists
{
Exists(std::vector<Variable> &&variables, Formula &&argument)
// TODO: rename “variables”
explicit Exists(std::vector<std::unique_ptr<VariableDeclaration>> &&variables, Formula &&argument)
: variables{std::move(variables)},
argument{std::move(argument)}
{
@@ -348,7 +369,7 @@ struct Exists
Exists(Exists &&other) noexcept = default;
Exists &operator=(Exists &&other) noexcept = default;
std::vector<Variable> variables;
std::vector<std::unique_ptr<VariableDeclaration>> variables;
Formula argument;
};
@@ -356,7 +377,7 @@ struct Exists
struct ForAll
{
ForAll(std::vector<Variable> &&variables, Formula &&argument)
explicit ForAll(std::vector<std::unique_ptr<VariableDeclaration>> &&variables, Formula &&argument)
: variables{std::move(variables)},
argument{std::move(argument)}
{
@@ -367,7 +388,7 @@ struct ForAll
ForAll(ForAll &&other) noexcept = default;
ForAll &operator=(ForAll &&other) noexcept = default;
std::vector<Variable> variables;
std::vector<std::unique_ptr<VariableDeclaration>> variables;
Formula argument;
};
@@ -375,7 +396,7 @@ struct ForAll
struct Implies
{
Implies(Formula &&antecedent, Formula &&consequent)
explicit Implies(Formula &&antecedent, Formula &&consequent)
: antecedent{std::move(antecedent)},
consequent{std::move(consequent)}
{
@@ -394,7 +415,7 @@ struct Implies
struct Not
{
Not(Formula &&argument)
explicit Not(Formula &&argument)
: argument{std::move(argument)}
{
}
@@ -413,7 +434,7 @@ struct Or
{
Or() = default;
Or(std::vector<Formula> &&arguments)
explicit Or(std::vector<Formula> &&arguments)
: arguments{std::move(arguments)}
{
}
@@ -427,258 +448,23 @@ struct Or
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// Deep Copying
// High-Level
////////////////////////////////////////////////////////////////////////////////////////////////////
BinaryOperation deepCopy(const BinaryOperation &other);
Boolean deepCopy(const Boolean &other);
Comparison deepCopy(const Comparison &other);
Constant deepCopy(const Constant &other);
Function deepCopy(const Function &other);
Integer deepCopy(const Integer &other);
Interval deepCopy(const Interval &other);
Predicate deepCopy(const Predicate &other);
SpecialInteger deepCopy(const SpecialInteger &other);
String deepCopy(const String &other);
Variable deepCopy(const Variable &other);
std::vector<Variable> deepCopy(const std::vector<Variable> &other);
And deepCopy(const And &other);
Biconditional deepCopy(const Biconditional &other);
Exists deepCopy(const Exists &other);
ForAll deepCopy(const ForAll &other);
Implies deepCopy(const Implies &other);
Not deepCopy(const Not &other);
Or deepCopy(const Or &other);
Formula deepCopy(const Formula &formula);
std::vector<Formula> deepCopy(const std::vector<Formula> &formulas);
Term deepCopy(const Term &term);
std::vector<Term> deepCopy(const std::vector<Term> &terms);
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Variant>
struct VariantDeepCopyVisitor
struct ScopedFormula
{
template<class T>
Variant visit(const T &x)
explicit ScopedFormula(ast::Formula &&formula, std::vector<std::unique_ptr<ast::VariableDeclaration>> &&freeVariables)
: formula{std::move(formula)},
freeVariables{std::move(freeVariables)}
{
return deepCopy(x);
}
ast::Formula formula;
std::vector<std::unique_ptr<ast::VariableDeclaration>> freeVariables;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
const auto deepCopyVariant =
[](const auto &variant) -> typename std::decay<decltype(variant)>::type
{
using VariantType = typename std::decay<decltype(variant)>::type;
return variant.accept(VariantDeepCopyVisitor<VariantType>());
};
////////////////////////////////////////////////////////////////////////////////////////////////////
const auto deepCopyVariantVector =
[](const auto &variantVector) -> typename std::decay<decltype(variantVector)>::type
{
using Type = typename std::decay<decltype(variantVector)>::type::value_type;
std::vector<Type> result;
result.reserve(variantVector.size());
for (const auto &variant : variantVector)
result.emplace_back(deepCopyVariant(variant));
return result;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
const auto deepCopyVector =
[](const auto &vector) -> typename std::decay<decltype(vector)>::type
{
using Type = typename std::decay<decltype(vector)>::type::value_type;
std::vector<Type> result;
result.reserve(vector.size());
for (const auto &element : vector)
result.emplace_back(deepCopy(element));
return result;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
inline BinaryOperation deepCopy(const BinaryOperation &other)
{
return BinaryOperation(other.operator_, deepCopy(other.left), deepCopy(other.right));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Boolean deepCopy(const Boolean &other)
{
return Boolean(other.value);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Comparison deepCopy(const Comparison &other)
{
return Comparison(other.operator_, deepCopy(other.left), deepCopy(other.right));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Constant deepCopy(const Constant &other)
{
return Constant(std::string(other.name));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Function deepCopy(const Function &other)
{
return Function(std::string(other.name), deepCopy(other.arguments));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Integer deepCopy(const Integer &other)
{
return Integer(other.value);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Interval deepCopy(const Interval &other)
{
return Interval(deepCopy(other.from), deepCopy(other.to));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Predicate deepCopy(const Predicate &other)
{
return Predicate(std::string(other.name), deepCopy(other.arguments));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline SpecialInteger deepCopy(const SpecialInteger &other)
{
return SpecialInteger(other.type);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline String deepCopy(const String &other)
{
return String(std::string(other.text));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Variable deepCopy(const Variable &other)
{
return Variable(std::string(other.name), other.type);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline std::vector<Variable> deepCopy(const std::vector<Variable> &other)
{
return deepCopyVector(other);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline And deepCopy(const And &other)
{
return And(deepCopy(other.arguments));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Biconditional deepCopy(const Biconditional &other)
{
return Biconditional(deepCopy(other.left), deepCopy(other.right));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Exists deepCopy(const Exists &other)
{
return Exists(deepCopy(other.variables), deepCopy(other.argument));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline ForAll deepCopy(const ForAll &other)
{
return ForAll(deepCopy(other.variables), deepCopy(other.argument));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline In deepCopy(const In &other)
{
return In(deepCopy(other.element), deepCopy(other.set));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Implies deepCopy(const Implies &other)
{
return Implies(deepCopy(other.antecedent), deepCopy(other.consequent));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Not deepCopy(const Not &other)
{
return Not(deepCopy(other.argument));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Or deepCopy(const Or &other)
{
return Or(deepCopy(other.arguments));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Formula deepCopy(const Formula &formula)
{
return deepCopyVariant(formula);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline std::vector<Formula> deepCopy(const std::vector<Formula> &formulas)
{
return deepCopyVariantVector(formulas);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Term deepCopy(const Term &term)
{
return deepCopyVariant(term);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline std::vector<Term> deepCopy(const std::vector<Term> &terms)
{
return deepCopyVariantVector(terms);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

60
include/anthem/ASTCopy.h Normal file
View File

@@ -0,0 +1,60 @@
#ifndef __ANTHEM__AST_COPY_H
#define __ANTHEM__AST_COPY_H
#include <anthem/AST.h>
#include <anthem/ASTVisitors.h>
namespace anthem
{
namespace ast
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ASTCopy
//
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
// Preparing Deep Copying
////////////////////////////////////////////////////////////////////////////////////////////////////
BinaryOperation prepareCopy(const BinaryOperation &other);
Boolean prepareCopy(const Boolean &other);
Comparison prepareCopy(const Comparison &other);
Constant prepareCopy(const Constant &other);
Function prepareCopy(const Function &other);
In prepareCopy(const In &other);
Integer prepareCopy(const Integer &other);
Interval prepareCopy(const Interval &other);
Predicate prepareCopy(const Predicate &other);
SpecialInteger prepareCopy(const SpecialInteger &other);
String prepareCopy(const String &other);
Variable prepareCopy(const Variable &other);
VariableDeclaration prepareCopy(const VariableDeclaration &other);
VariableDeclarationPointers prepareCopy(const VariableDeclarationPointers &other);
And prepareCopy(const And &other);
Biconditional prepareCopy(const Biconditional &other);
Exists prepareCopy(const Exists &other);
ForAll prepareCopy(const ForAll &other);
Implies prepareCopy(const Implies &other);
Not prepareCopy(const Not &other);
Or prepareCopy(const Or &other);
Term prepareCopy(const Term &term);
std::vector<Term> prepareCopy(const std::vector<Term> &terms);
Formula prepareCopy(const Formula &formula);
std::vector<Formula> prepareCopy(const std::vector<Formula> &formulas);
////////////////////////////////////////////////////////////////////////////////////////////////////
// Fixing Dangling Variables
////////////////////////////////////////////////////////////////////////////////////////////////////
void fixDanglingVariables(ScopedFormula &scopedFormula);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -1,7 +1,7 @@
#ifndef __ANTHEM__AST_FORWARD_H
#define __ANTHEM__AST_FORWARD_H
#include <experimental/optional>
#include <memory>
#include <clingo.hh>
@@ -38,6 +38,9 @@ struct Predicate;
struct SpecialInteger;
struct String;
struct Variable;
struct VariableDeclaration;
using VariableDeclarationPointer = std::unique_ptr<VariableDeclaration>;
using VariableDeclarationPointers = std::vector<VariableDeclarationPointer>;
////////////////////////////////////////////////////////////////////////////////////////////////////
// Variants
@@ -67,6 +70,12 @@ using Term = Clingo::Variant<
String,
Variable>;
////////////////////////////////////////////////////////////////////////////////////////////////////
// High-Level
////////////////////////////////////////////////////////////////////////////////////////////////////
struct ScopedFormula;
////////////////////////////////////////////////////////////////////////////////////////////////////
}

View File

@@ -1,6 +1,8 @@
#ifndef __ANTHEM__AST_UTILS_H
#define __ANTHEM__AST_UTILS_H
#include <experimental/optional>
#include <anthem/AST.h>
namespace anthem
@@ -14,16 +16,18 @@ namespace ast
//
////////////////////////////////////////////////////////////////////////////////////////////////////
// TODO: rename to VariableDeclarationStack or ParameterStack
class VariableStack
{
public:
using Layer = const std::vector<ast::Variable> *;
using Layer = ast::VariableDeclarationPointers *;
public:
void push(Layer layer);
void pop();
bool contains(const ast::Variable &variable) const;
std::experimental::optional<ast::VariableDeclaration *> findVariableDeclaration(const char *variableName) const;
bool contains(const ast::VariableDeclaration &variableDeclaration) const;
private:
std::vector<Layer> m_layers;
@@ -31,8 +35,8 @@ class VariableStack
////////////////////////////////////////////////////////////////////////////////////////////////////
std::vector<ast::Variable> collectFreeVariables(const ast::Formula &formula);
std::vector<ast::Variable> collectFreeVariables(const ast::Formula &formula, ast::VariableStack &variableStack);
std::vector<ast::VariableDeclaration *> collectFreeVariables(ast::Formula &formula);
std::vector<ast::VariableDeclaration *> collectFreeVariables(ast::Formula &formula, ast::VariableStack &variableStack);
bool matches(const ast::Predicate &lhs, const ast::Predicate &rhs);
void collectPredicates(const ast::Formula &formula, std::vector<const ast::Predicate *> &predicates);

View File

@@ -110,6 +110,7 @@ struct RecursiveFormulaVisitor
template<class T>
struct RecursiveTermVisitor
{
// TODO: return type is incorrect
template <class... Arguments>
void visit(ast::BinaryOperation &binaryOperation, ast::Term &term, Arguments &&... arguments)
{

View File

@@ -40,11 +40,12 @@ ast::Comparison::Operator translate(Clingo::AST::ComparisonOperator comparisonOp
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::Variable makeAuxiliaryBodyVariable(int i)
std::unique_ptr<ast::VariableDeclaration> makeBodyVariableDeclaration(int i)
{
auto variableName = std::string(AuxiliaryBodyVariablePrefix) + std::to_string(i);
// TODO: drop name
auto variableName = "#" + std::string(BodyVariablePrefix) + std::to_string(i);
return ast::Variable(std::move(variableName), ast::Variable::Type::Reserved);
return std::make_unique<ast::VariableDeclaration>(std::move(variableName), ast::VariableDeclaration::Type::Body);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -52,7 +53,7 @@ ast::Variable makeAuxiliaryBodyVariable(int i)
struct BodyTermTranslateVisitor
{
// TODO: refactor
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Function &function, const Clingo::AST::Literal &literal, const Clingo::AST::Term &, Context &context)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Function &function, const Clingo::AST::Literal &literal, const Clingo::AST::Term &, Context &context, RuleContext &ruleContext, ast::VariableStack &variableStack)
{
if (literal.sign == Clingo::AST::Sign::DoubleNegation)
throwErrorAtLocation(literal.location, "double-negated literals currently unsupported", context);
@@ -67,39 +68,42 @@ struct BodyTermTranslateVisitor
return ast::Formula::make<ast::Not>(std::move(predicate));
}
std::vector<ast::Variable> variables;
variables.reserve(function.arguments.size());
// Create new body variable declarations
std::vector<std::unique_ptr<ast::VariableDeclaration>> parameters;
parameters.reserve(function.arguments.size());
variableStack.push(&parameters);
for (size_t i = 0; i < function.arguments.size(); i++)
variables.emplace_back(makeAuxiliaryBodyVariable(context.auxiliaryBodyVariableID + i));
parameters.emplace_back(makeBodyVariableDeclaration(i + 1));
ast::And conjunction;
for (size_t i = 0; i < function.arguments.size(); i++)
{
const auto &argument = function.arguments[i];
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(makeAuxiliaryBodyVariable(context.auxiliaryBodyVariableID + i), translate(argument, context)));
auto &argument = function.arguments[i];
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(ast::Variable(parameters[i].get()), translate(argument, context, ruleContext, variableStack)));
}
ast::Predicate predicate(std::string(function.name));
predicate.arguments.reserve(function.arguments.size());
for (size_t i = 0; i < function.arguments.size(); i++)
predicate.arguments.emplace_back(makeAuxiliaryBodyVariable(context.auxiliaryBodyVariableID + i));
predicate.arguments.emplace_back(ast::Variable(parameters[i].get()));
if (literal.sign == Clingo::AST::Sign::None)
conjunction.arguments.emplace_back(std::move(predicate));
else if (literal.sign == Clingo::AST::Sign::Negation)
conjunction.arguments.emplace_back(ast::Formula::make<ast::Not>(std::move(predicate)));
context.auxiliaryBodyVariableID += function.arguments.size();
return ast::Formula::make<ast::Exists>(std::move(variables), std::move(conjunction));
return ast::Formula::make<ast::Exists>(std::move(parameters), std::move(conjunction));
}
template<class T>
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &, const Clingo::AST::Term &term, Context &context)
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &, const Clingo::AST::Term &term, Context &context, RuleContext &, ast::VariableStack &)
{
assert(!term.data.is<Clingo::AST::Function>());
throwErrorAtLocation(term.location, "term currently unsupported in this context, expected function", context);
return std::experimental::nullopt;
}
@@ -109,18 +113,18 @@ struct BodyTermTranslateVisitor
struct BodyLiteralTranslateVisitor
{
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, Context &)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, Context &, RuleContext &, ast::VariableStack &)
{
return ast::Formula::make<ast::Boolean>(boolean.value);
}
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &literal, Context &context)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &literal, Context &context, RuleContext &ruleContext, ast::VariableStack &variableStack)
{
return term.data.accept(BodyTermTranslateVisitor(), literal, term, context);
return term.data.accept(BodyTermTranslateVisitor(), literal, term, context, ruleContext, variableStack);
}
// TODO: refactor
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Comparison &comparison, const Clingo::AST::Literal &literal, Context &context)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Comparison &comparison, const Clingo::AST::Literal &literal, Context &context, RuleContext &ruleContext, ast::VariableStack &variableStack)
{
// Comparisons should never have a sign, because these are converted to positive comparisons by clingo
if (literal.sign != Clingo::AST::Sign::None)
@@ -128,24 +132,22 @@ struct BodyLiteralTranslateVisitor
const auto operator_ = translate(comparison.comparison);
std::vector<ast::Variable> variables;
variables.reserve(2);
variables.emplace_back(makeAuxiliaryBodyVariable(context.auxiliaryBodyVariableID));
variables.emplace_back(makeAuxiliaryBodyVariable(context.auxiliaryBodyVariableID + 1));
std::vector<std::unique_ptr<ast::VariableDeclaration>> parameters;
parameters.reserve(2);
parameters.emplace_back(makeBodyVariableDeclaration(1));
parameters.emplace_back(makeBodyVariableDeclaration(2));
ast::And conjunction;
conjunction.arguments.reserve(3);
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(makeAuxiliaryBodyVariable(context.auxiliaryBodyVariableID), translate(comparison.left, context)));
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(makeAuxiliaryBodyVariable(context.auxiliaryBodyVariableID + 1), translate(comparison.right, context)));
conjunction.arguments.emplace_back(ast::Formula::make<ast::Comparison>(operator_, makeAuxiliaryBodyVariable(context.auxiliaryBodyVariableID), makeAuxiliaryBodyVariable(context.auxiliaryBodyVariableID + 1)));
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(ast::Variable(parameters[0].get()), translate(comparison.left, context, ruleContext, variableStack)));
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(ast::Variable(parameters[1].get()), translate(comparison.right, context, ruleContext, variableStack)));
conjunction.arguments.emplace_back(ast::Formula::make<ast::Comparison>(operator_, ast::Variable(parameters[0].get()), ast::Variable(parameters[1].get())));
context.auxiliaryBodyVariableID += 2;
return ast::Formula::make<ast::Exists>(std::move(variables), std::move(conjunction));
return ast::Formula::make<ast::Exists>(std::move(parameters), std::move(conjunction));
}
template<class T>
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &literal, Context &context)
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &literal, Context &context, RuleContext &, ast::VariableStack &)
{
throwErrorAtLocation(literal.location, "literal currently unsupported in this context, expected function or term", context);
return std::experimental::nullopt;
@@ -156,16 +158,16 @@ struct BodyLiteralTranslateVisitor
struct BodyBodyLiteralTranslateVisitor
{
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Literal &literal, const Clingo::AST::BodyLiteral &bodyLiteral, Context &context)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Literal &literal, const Clingo::AST::BodyLiteral &bodyLiteral, Context &context, RuleContext &ruleContext, ast::VariableStack &variableStack)
{
if (bodyLiteral.sign != Clingo::AST::Sign::None)
throwErrorAtLocation(bodyLiteral.location, "only positive body literals supported currently", context);
return literal.data.accept(BodyLiteralTranslateVisitor(), literal, context);
return literal.data.accept(BodyLiteralTranslateVisitor(), literal, context, ruleContext, variableStack);
}
template<class T>
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::BodyLiteral &bodyLiteral, Context &context)
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::BodyLiteral &bodyLiteral, Context &context, RuleContext &, ast::VariableStack &)
{
throwErrorAtLocation(bodyLiteral.location, "body literal currently unsupported in this context, expected literal", context);
return std::experimental::nullopt;

View File

@@ -12,7 +12,7 @@ namespace anthem
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void complete(std::vector<ast::Formula> &formulas);
void complete(std::vector<ast::ScopedFormula> &scopedFormulas);
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -1,8 +1,6 @@
#ifndef __ANTHEM__CONTEXT_H
#define __ANTHEM__CONTEXT_H
#include <clingo.hh>
#include <anthem/output/Logger.h>
namespace anthem
@@ -16,25 +14,19 @@ namespace anthem
struct Context
{
void reset()
Context() = default;
explicit Context(output::Logger &&logger)
: logger{std::move(logger)}
{
headTerms.clear();
isChoiceRule = false;
numberOfHeadLiterals = 0;
auxiliaryBodyVariableID = 1;
anonymousVariableID = 1;
}
output::Logger logger;
std::vector<const Clingo::AST::Term *> headTerms;
bool isChoiceRule = false;
size_t numberOfHeadLiterals = 0;
size_t auxiliaryBodyVariableID = 1;
size_t anonymousVariableID = 1;
bool simplify = false;
bool complete = false;
size_t anonymousVariableID = 1;
};
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -2,8 +2,10 @@
#define __ANTHEM__HEAD_H
#include <algorithm>
#include <experimental/optional>
#include <anthem/AST.h>
#include <anthem/RuleContext.h>
#include <anthem/Utils.h>
#include <anthem/output/Formatting.h>
@@ -16,21 +18,25 @@ namespace anthem
//
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
// Collect Head Terms
////////////////////////////////////////////////////////////////////////////////////////////////////
struct TermCollectFunctionTermsVisitor
{
void visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, Context &context)
void visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext)
{
if (function.external)
throwErrorAtLocation(term.location, "external functions currently unsupported", context);
context.headTerms.reserve(context.headTerms.size() + function.arguments.size());
ruleContext.headTerms.reserve(ruleContext.headTerms.size() + function.arguments.size());
for (const auto &argument : function.arguments)
context.headTerms.emplace_back(&argument);
ruleContext.headTerms.emplace_back(&argument);
}
template<class T>
void visit(const T &, const Clingo::AST::Term &term, Context &context)
void visit(const T &, const Clingo::AST::Term &term, Context &context, RuleContext &)
{
throwErrorAtLocation(term.location, "term currently unsupported in this context, function expected", context);
}
@@ -40,17 +46,17 @@ struct TermCollectFunctionTermsVisitor
struct LiteralCollectFunctionTermsVisitor
{
void visit(const Clingo::AST::Boolean &, const Clingo::AST::Literal &, Context &)
void visit(const Clingo::AST::Boolean &, const Clingo::AST::Literal &, Context &, RuleContext &)
{
}
void visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &, Context &context)
void visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &, Context &context, RuleContext &ruleContext)
{
term.data.accept(TermCollectFunctionTermsVisitor(), term, context);
term.data.accept(TermCollectFunctionTermsVisitor(), term, context, ruleContext);
}
template<class T>
void visit(const T &, const Clingo::AST::Literal &literal, Context &context)
void visit(const T &, const Clingo::AST::Literal &literal, Context &context, RuleContext &)
{
throwErrorAtLocation(literal.location, "only disjunctions of literals allowed as head literals", context);
}
@@ -61,30 +67,30 @@ struct LiteralCollectFunctionTermsVisitor
// TODO: rename, because not only terms are collected anymore
struct HeadLiteralCollectFunctionTermsVisitor
{
void visit(const Clingo::AST::Literal &literal, const Clingo::AST::HeadLiteral &, Context &context)
void visit(const Clingo::AST::Literal &literal, const Clingo::AST::HeadLiteral &, Context &context, RuleContext &ruleContext)
{
context.numberOfHeadLiterals = 1;
ruleContext.numberOfHeadLiterals = 1;
literal.data.accept(LiteralCollectFunctionTermsVisitor(), literal, context);
literal.data.accept(LiteralCollectFunctionTermsVisitor(), literal, context, ruleContext);
}
void visit(const Clingo::AST::Disjunction &disjunction, const Clingo::AST::HeadLiteral &headLiteral, Context &context)
void visit(const Clingo::AST::Disjunction &disjunction, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &ruleContext)
{
context.numberOfHeadLiterals = disjunction.elements.size();
ruleContext.numberOfHeadLiterals = disjunction.elements.size();
for (const auto &conditionalLiteral : disjunction.elements)
{
if (!conditionalLiteral.condition.empty())
throwErrorAtLocation(headLiteral.location, "conditional head literals currently unsupported", context);
conditionalLiteral.literal.data.accept(LiteralCollectFunctionTermsVisitor(), conditionalLiteral.literal, context);
conditionalLiteral.literal.data.accept(LiteralCollectFunctionTermsVisitor(), conditionalLiteral.literal, context, ruleContext);
}
}
void visit(const Clingo::AST::Aggregate &aggregate, const Clingo::AST::HeadLiteral &headLiteral, Context &context)
void visit(const Clingo::AST::Aggregate &aggregate, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &ruleContext)
{
context.isChoiceRule = true;
context.numberOfHeadLiterals = aggregate.elements.size();
ruleContext.isChoiceRule = true;
ruleContext.numberOfHeadLiterals = aggregate.elements.size();
if (aggregate.left_guard || aggregate.right_guard)
throwErrorAtLocation(headLiteral.location, "aggregates with left or right guards currently unsupported", context);
@@ -94,23 +100,25 @@ struct HeadLiteralCollectFunctionTermsVisitor
if (!conditionalLiteral.condition.empty())
throwErrorAtLocation(headLiteral.location, "conditional literals in aggregates currently unsupported", context);
conditionalLiteral.literal.data.accept(LiteralCollectFunctionTermsVisitor(), conditionalLiteral.literal, context);
conditionalLiteral.literal.data.accept(LiteralCollectFunctionTermsVisitor(), conditionalLiteral.literal, context, ruleContext);
}
}
template<class T>
void visit(const T &, const Clingo::AST::HeadLiteral &headLiteral, Context &context)
void visit(const T &, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &)
{
throwErrorAtLocation(headLiteral.location, "head literal currently unsupported in this context, expected literal, disjunction, or aggregate", context);
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// Translate Head
////////////////////////////////////////////////////////////////////////////////////////////////////
struct FunctionTermTranslateVisitor
{
// TODO: check correctness
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, Context &context)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, size_t &headVariableIndex)
{
if (function.external)
throwErrorAtLocation(term.location, "external functions currently unsupported", context);
@@ -118,22 +126,14 @@ struct FunctionTermTranslateVisitor
std::vector<ast::Term> arguments;
arguments.reserve(function.arguments.size());
for (auto i = function.arguments.cbegin(); i != function.arguments.cend(); i++)
{
const auto &argument = *i;
const auto matchingTerm = std::find(context.headTerms.cbegin(), context.headTerms.cend(), &argument);
assert(matchingTerm != context.headTerms.cend());
auto variableName = std::string(AuxiliaryHeadVariablePrefix) + std::to_string(matchingTerm - context.headTerms.cbegin() + 1);
arguments.emplace_back(ast::Variable(std::move(variableName), ast::Variable::Type::Reserved));
}
for (size_t i = 0; i < function.arguments.size(); i++)
arguments.emplace_back(ast::Variable(ruleContext.freeVariables[headVariableIndex++].get()));
return ast::Formula::make<ast::Predicate>(function.name, std::move(arguments));
}
template<class T>
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Term &term, Context &context)
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Term &term, Context &context, RuleContext &, size_t &)
{
throwErrorAtLocation(term.location, "term currently unsupported in this context, function expected", context);
return std::experimental::nullopt;
@@ -144,18 +144,18 @@ struct FunctionTermTranslateVisitor
struct LiteralTranslateVisitor
{
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, Context &)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, Context &, RuleContext &, size_t &)
{
return ast::Formula::make<ast::Boolean>(boolean.value);
}
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &, Context &context)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &, Context &context, RuleContext &ruleContext, size_t &headVariableIndex)
{
return term.data.accept(FunctionTermTranslateVisitor(), term, context);
return term.data.accept(FunctionTermTranslateVisitor(), term, context, ruleContext, headVariableIndex);
}
template<class T>
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &literal, Context &context)
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &literal, Context &context, RuleContext &, size_t &)
{
throwErrorAtLocation(literal.location, "only disjunctions of literals allowed as head literals", context);
return std::experimental::nullopt;
@@ -166,12 +166,12 @@ struct LiteralTranslateVisitor
struct HeadLiteralTranslateToConsequentVisitor
{
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Literal &literal, const Clingo::AST::HeadLiteral &, Context &context)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Literal &literal, const Clingo::AST::HeadLiteral &, Context &context, RuleContext &ruleContext, size_t &headVariableIndex)
{
if (literal.sign == Clingo::AST::Sign::DoubleNegation)
throwErrorAtLocation(literal.location, "double-negated head literals currently unsupported", context);
auto translatedLiteral = literal.data.accept(LiteralTranslateVisitor(), literal, context);
auto translatedLiteral = literal.data.accept(LiteralTranslateVisitor(), literal, context, ruleContext, headVariableIndex);
if (literal.sign == Clingo::AST::Sign::None)
return translatedLiteral;
@@ -182,7 +182,7 @@ struct HeadLiteralTranslateToConsequentVisitor
return ast::Formula::make<ast::Not>(std::move(translatedLiteral.value()));
}
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Disjunction &disjunction, const Clingo::AST::HeadLiteral &headLiteral, Context &context)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Disjunction &disjunction, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &ruleContext, size_t &headVariableIndex)
{
std::vector<ast::Formula> arguments;
arguments.reserve(disjunction.elements.size());
@@ -192,7 +192,7 @@ struct HeadLiteralTranslateToConsequentVisitor
if (!conditionalLiteral.condition.empty())
throwErrorAtLocation(headLiteral.location, "conditional head literals currently unsupported", context);
auto argument = visit(conditionalLiteral.literal, headLiteral, context);
auto argument = visit(conditionalLiteral.literal, headLiteral, context, ruleContext, headVariableIndex);
if (!argument)
throwErrorAtLocation(headLiteral.location, "could not parse argument", context);
@@ -203,7 +203,7 @@ struct HeadLiteralTranslateToConsequentVisitor
return ast::Formula::make<ast::Or>(std::move(arguments));
}
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Aggregate &aggregate, const Clingo::AST::HeadLiteral &headLiteral, Context &context)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Aggregate &aggregate, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &ruleContext, size_t &headVariableIndex)
{
if (aggregate.left_guard || aggregate.right_guard)
throwErrorAtLocation(headLiteral.location, "aggregates with left or right guards currently unsupported", context);
@@ -214,7 +214,7 @@ struct HeadLiteralTranslateToConsequentVisitor
if (!conditionalLiteral.condition.empty())
throwErrorAtLocation(headLiteral.location, "conditional head literals currently unsupported", context);
return this->visit(conditionalLiteral.literal, headLiteral, context);
return this->visit(conditionalLiteral.literal, headLiteral, context, ruleContext, headVariableIndex);
};
if (aggregate.elements.size() == 1)
@@ -237,7 +237,7 @@ struct HeadLiteralTranslateToConsequentVisitor
}
template<class T>
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::HeadLiteral &headLiteral, Context &context)
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &, size_t &)
{
throwErrorAtLocation(headLiteral.location, "head literal currently unsupported in this context, expected literal, disjunction, or aggregate", context);
return std::experimental::nullopt;

View File

@@ -0,0 +1,34 @@
#ifndef __ANTHEM__RULE_CONTEXT_H
#define __ANTHEM__RULE_CONTEXT_H
#include <clingo.hh>
#include <anthem/ASTForward.h>
#include <anthem/output/Logger.h>
namespace anthem
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// RuleContext
//
////////////////////////////////////////////////////////////////////////////////////////////////////
struct RuleContext
{
std::vector<const Clingo::AST::Term *> headTerms;
ast::VariableDeclarationPointers freeVariables;
// Index of the first auxiliary head variable into the vector freeVariables
size_t headVariablesStartIndex = 0;
bool isChoiceRule = false;
size_t numberOfHeadLiterals = 0;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
#endif

View File

@@ -2,8 +2,10 @@
#define __ANTHEM__STATEMENT_VISITOR_H
#include <anthem/AST.h>
#include <anthem/ASTCopy.h>
#include <anthem/Body.h>
#include <anthem/Head.h>
#include <anthem/RuleContext.h>
#include <anthem/Term.h>
#include <anthem/Utils.h>
@@ -35,7 +37,7 @@ inline void reduce(ast::Implies &implies)
struct StatementVisitor
{
void visit(const Clingo::AST::Program &program, const Clingo::AST::Statement &statement, std::vector<ast::Formula> &, Context &context)
void visit(const Clingo::AST::Program &program, const Clingo::AST::Statement &statement, std::vector<ast::ScopedFormula> &, Context &context)
{
// TODO: refactor
context.logger.log(output::Priority::Debug, (std::string("[program] ") + program.name).c_str());
@@ -44,17 +46,35 @@ struct StatementVisitor
throwErrorAtLocation(statement.location, "program parameters currently unsupported", context);
}
void visit(const Clingo::AST::Rule &rule, const Clingo::AST::Statement &, std::vector<ast::Formula> &formulas, Context &context)
void visit(const Clingo::AST::Rule &rule, const Clingo::AST::Statement &, std::vector<ast::ScopedFormula> &scopedFormulas, Context &context)
{
context.reset();
RuleContext ruleContext;
ast::VariableStack variableStack;
variableStack.push(&ruleContext.freeVariables);
// Concatenate all head terms
rule.head.data.accept(HeadLiteralCollectFunctionTermsVisitor(), rule.head, context);
// Collect all head terms
rule.head.data.accept(HeadLiteralCollectFunctionTermsVisitor(), rule.head, context, ruleContext);
// Create new variable declarations for the head terms
ruleContext.headVariablesStartIndex = ruleContext.freeVariables.size();
ruleContext.freeVariables.reserve(ruleContext.headTerms.size());
for (size_t i = 0; i < ruleContext.headTerms.size(); i++)
{
// TODO: drop name
auto variableName = "#" + std::string(HeadVariablePrefix) + std::to_string(ruleContext.freeVariables.size() + 1);
auto variableDeclaration = std::make_unique<ast::VariableDeclaration>(std::move(variableName), ast::VariableDeclaration::Type::Head);
ruleContext.freeVariables.emplace_back(std::move(variableDeclaration));
}
ast::And antecedent;
// Compute consequent
auto consequent = rule.head.data.accept(HeadLiteralTranslateToConsequentVisitor(), rule.head, context);
auto headVariableIndex = ruleContext.headVariablesStartIndex;
auto consequent = rule.head.data.accept(HeadLiteralTranslateToConsequentVisitor(), rule.head, context, ruleContext, headVariableIndex);
assert(ruleContext.headTerms.size() == headVariableIndex - ruleContext.headVariablesStartIndex);
if (!consequent)
{
@@ -64,13 +84,13 @@ struct StatementVisitor
}
// Generate auxiliary variables replacing the head atoms arguments
for (auto i = context.headTerms.cbegin(); i != context.headTerms.cend(); i++)
for (auto i = ruleContext.headTerms.cbegin(); i != ruleContext.headTerms.cend(); i++)
{
const auto &headTerm = **i;
auto variableName = std::string(AuxiliaryHeadVariablePrefix) + std::to_string(i - context.headTerms.cbegin() + 1);
auto element = ast::Variable(std::move(variableName), ast::Variable::Type::Reserved);
auto set = translate(headTerm, context);
const auto auxiliaryHeadVariableID = ruleContext.headVariablesStartIndex + i - ruleContext.headTerms.cbegin();
auto element = ast::Variable(ruleContext.freeVariables[auxiliaryHeadVariableID].get());
auto set = translate(headTerm, context, ruleContext, variableStack);
auto in = ast::In(std::move(element), std::move(set));
antecedent.arguments.emplace_back(std::move(in));
@@ -81,7 +101,7 @@ struct StatementVisitor
{
const auto &bodyLiteral = *i;
auto argument = bodyLiteral.data.accept(BodyBodyLiteralTranslateVisitor(), bodyLiteral, context);
auto argument = bodyLiteral.data.accept(BodyBodyLiteralTranslateVisitor(), bodyLiteral, context, ruleContext, variableStack);
if (!argument)
throwErrorAtLocation(bodyLiteral.location, "could not translate body literal", context);
@@ -89,26 +109,38 @@ struct StatementVisitor
antecedent.arguments.emplace_back(std::move(argument.value()));
}
if (!context.isChoiceRule)
if (!ruleContext.isChoiceRule)
{
formulas.emplace_back(ast::Formula::make<ast::Implies>(std::move(antecedent), std::move(consequent.value())));
reduce(formulas.back().get<ast::Implies>());
auto formula = ast::Formula::make<ast::Implies>(std::move(antecedent), std::move(consequent.value()));
ast::ScopedFormula scopedFormula(std::move(formula), std::move(ruleContext.freeVariables));
scopedFormulas.emplace_back(std::move(scopedFormula));
reduce(scopedFormulas.back().formula.get<ast::Implies>());
}
else
{
const auto createFormula =
[&](ast::Formula &argument, bool isLastOne)
{
auto consequent = std::move(argument);
auto &consequent = argument;
if (!isLastOne)
formulas.emplace_back(ast::Formula::make<ast::Implies>(ast::deepCopy(antecedent), std::move(consequent)));
{
auto formula = ast::Formula::make<ast::Implies>(ast::prepareCopy(antecedent), std::move(consequent));
ast::ScopedFormula scopedFormula(std::move(formula), {});
ast::fixDanglingVariables(scopedFormula);
scopedFormulas.emplace_back(std::move(scopedFormula));
}
else
formulas.emplace_back(ast::Formula::make<ast::Implies>(std::move(antecedent), std::move(consequent)));
{
auto formula = ast::Formula::make<ast::Implies>(std::move(antecedent), std::move(consequent));
ast::ScopedFormula scopedFormula(std::move(formula), std::move(ruleContext.freeVariables));
scopedFormulas.emplace_back(std::move(scopedFormula));
}
auto &implies = formulas.back().get<ast::Implies>();
auto &implies = scopedFormulas.back().formula.get<ast::Implies>();
auto &antecedent = implies.antecedent.get<ast::And>();
antecedent.arguments.emplace_back(ast::deepCopy(implies.consequent));
antecedent.arguments.emplace_back(ast::prepareCopy(implies.consequent));
ast::fixDanglingVariables(scopedFormulas.back());
reduce(implies);
};
@@ -127,7 +159,7 @@ struct StatementVisitor
}
template<class T>
void visit(const T &, const Clingo::AST::Statement &statement, std::vector<ast::Formula> &, Context &context)
void visit(const T &, const Clingo::AST::Statement &statement, std::vector<ast::ScopedFormula> &, Context &context)
{
throwErrorAtLocation(statement.location, "statement currently unsupported, expected rule", context);
}

View File

@@ -4,6 +4,8 @@
#include <algorithm>
#include <anthem/AST.h>
#include <anthem/ASTUtils.h>
#include <anthem/RuleContext.h>
#include <anthem/Utils.h>
#include <anthem/output/Formatting.h>
@@ -39,13 +41,13 @@ ast::BinaryOperation::Operator translate(Clingo::AST::BinaryOperator binaryOpera
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::Term translate(const Clingo::AST::Term &term, Context &context);
ast::Term translate(const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack);
////////////////////////////////////////////////////////////////////////////////////////////////////
struct TermTranslateVisitor
{
std::experimental::optional<ast::Term> visit(const Clingo::Symbol &symbol, const Clingo::AST::Term &term, Context &context)
std::experimental::optional<ast::Term> visit(const Clingo::Symbol &symbol, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack)
{
switch (symbol.type())
{
@@ -66,7 +68,7 @@ struct TermTranslateVisitor
for (const auto &argument : symbol.arguments())
{
auto translatedArgument = visit(argument, term, context);
auto translatedArgument = visit(argument, term, context, ruleContext, variableStack);
if (!translatedArgument)
throwErrorAtLocation(term.location, "could not translate argument", context);
@@ -81,43 +83,46 @@ struct TermTranslateVisitor
return std::experimental::nullopt;
}
std::experimental::optional<ast::Term> visit(const Clingo::AST::Variable &variable, const Clingo::AST::Term &, Context &context)
std::experimental::optional<ast::Term> visit(const Clingo::AST::Variable &variable, const Clingo::AST::Term &, Context &, RuleContext &ruleContext, const ast::VariableStack &variableStack)
{
if (strcmp(variable.name, "_") == 0)
{
std::string variableName = AnonymousVariablePrefix + std::to_string(context.anonymousVariableID);
context.anonymousVariableID++;
const auto matchingVariableDeclaration = variableStack.findVariableDeclaration(variable.name);
const auto isAnonymousVariable = (strcmp(variable.name, "_") == 0);
const auto isUndeclaredUserVariable = !matchingVariableDeclaration;
const auto isUndeclared = isAnonymousVariable || isUndeclaredUserVariable;
return ast::Term::make<ast::Variable>(std::move(variableName), ast::Variable::Type::Reserved);
}
if (!isUndeclared)
return ast::Term::make<ast::Variable>(*matchingVariableDeclaration);
return ast::Term::make<ast::Variable>(std::string(variable.name), ast::Variable::Type::UserDefined);
auto variableDeclaration = std::make_unique<ast::VariableDeclaration>(std::string(variable.name), ast::VariableDeclaration::Type::UserDefined);
ruleContext.freeVariables.emplace_back(std::move(variableDeclaration));
return ast::Term::make<ast::Variable>(ruleContext.freeVariables.back().get());
}
std::experimental::optional<ast::Term> visit(const Clingo::AST::UnaryOperation &, const Clingo::AST::Term &term, Context &context)
std::experimental::optional<ast::Term> visit(const Clingo::AST::UnaryOperation &, const Clingo::AST::Term &term, Context &context, RuleContext &, const ast::VariableStack &)
{
throwErrorAtLocation(term.location, "“unary operation” terms currently unsupported", context);
return std::experimental::nullopt;
}
std::experimental::optional<ast::Term> visit(const Clingo::AST::BinaryOperation &binaryOperation, const Clingo::AST::Term &term, Context &context)
std::experimental::optional<ast::Term> visit(const Clingo::AST::BinaryOperation &binaryOperation, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack)
{
const auto operator_ = translate(binaryOperation.binary_operator, term, context);
auto left = translate(binaryOperation.left, context);
auto right = translate(binaryOperation.right, context);
auto left = translate(binaryOperation.left, context, ruleContext, variableStack);
auto right = translate(binaryOperation.right, context, ruleContext, variableStack);
return ast::Term::make<ast::BinaryOperation>(operator_, std::move(left), std::move(right));
}
std::experimental::optional<ast::Term> visit(const Clingo::AST::Interval &interval, const Clingo::AST::Term &, Context &context)
std::experimental::optional<ast::Term> visit(const Clingo::AST::Interval &interval, const Clingo::AST::Term &, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack)
{
auto left = translate(interval.left, context);
auto right = translate(interval.right, context);
auto left = translate(interval.left, context, ruleContext, variableStack);
auto right = translate(interval.right, context, ruleContext, variableStack);
return ast::Term::make<ast::Interval>(std::move(left), std::move(right));
}
std::experimental::optional<ast::Term> visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, Context &context)
std::experimental::optional<ast::Term> visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack)
{
if (function.external)
throwErrorAtLocation(term.location, "external functions currently unsupported", context);
@@ -126,12 +131,12 @@ struct TermTranslateVisitor
arguments.reserve(function.arguments.size());
for (const auto &argument : function.arguments)
arguments.emplace_back(translate(argument, context));
arguments.emplace_back(translate(argument, context, ruleContext, variableStack));
return ast::Term::make<ast::Function>(function.name, std::move(arguments));
}
std::experimental::optional<ast::Term> visit(const Clingo::AST::Pool &, const Clingo::AST::Term &term, Context &context)
std::experimental::optional<ast::Term> visit(const Clingo::AST::Pool &, const Clingo::AST::Term &term, Context &context, RuleContext &, const ast::VariableStack &)
{
throwErrorAtLocation(term.location, "“pool” terms currently unsupported", context);
return std::experimental::nullopt;
@@ -140,9 +145,9 @@ struct TermTranslateVisitor
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::Term translate(const Clingo::AST::Term &term, Context &context)
ast::Term translate(const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack)
{
auto translatedTerm = term.data.accept(TermTranslateVisitor(), term, context);
auto translatedTerm = term.data.accept(TermTranslateVisitor(), term, context, ruleContext, variableStack);
if (!translatedTerm)
throwErrorAtLocation(term.location, "could not translate term", context);

View File

@@ -57,39 +57,9 @@ inline bool isPrefix(const char *prefix, const char *string)
////////////////////////////////////////////////////////////////////////////////////////////////////
constexpr const auto AuxiliaryHeadVariablePrefix = "V";
constexpr const auto AuxiliaryBodyVariablePrefix = "X";
constexpr const auto AnonymousVariablePrefix = "A";
constexpr const auto UserVariablePrefix = "_";
////////////////////////////////////////////////////////////////////////////////////////////////////
inline bool isReservedVariableName(const char *variableName)
{
if (!isPrefix(AuxiliaryBodyVariablePrefix, variableName)
&& !isPrefix(AuxiliaryHeadVariablePrefix, variableName)
&& !isPrefix(AnonymousVariablePrefix, variableName))
{
return false;
}
assert(std::strlen(AuxiliaryBodyVariablePrefix) == std::strlen(AuxiliaryHeadVariablePrefix));
assert(std::strlen(AuxiliaryBodyVariablePrefix) == std::strlen(AnonymousVariablePrefix));
assert(std::strlen(AuxiliaryBodyVariablePrefix) == std::strlen(UserVariablePrefix));
const auto prefixLength = std::strlen(AuxiliaryBodyVariablePrefix);
if (strlen(variableName) == prefixLength)
return false;
const char *suffix = variableName + prefixLength;
for (const auto *i = suffix; *i != '\0'; i++)
if (!std::isdigit(*i))
return false;
return true;
}
constexpr const auto HeadVariablePrefix = "V";
constexpr const auto BodyVariablePrefix = "X";
constexpr const auto UserVariablePrefix = "U";
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -2,6 +2,7 @@
#define __ANTHEM__OUTPUT__AST_H
#include <cassert>
#include <map>
#include <anthem/AST.h>
#include <anthem/Utils.h>
@@ -19,36 +20,46 @@ namespace ast
//
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, BinaryOperation::Operator operator_);
output::ColorStream &operator<<(output::ColorStream &stream, const BinaryOperation &binaryOperation);
output::ColorStream &operator<<(output::ColorStream &stream, const Boolean &boolean);
output::ColorStream &operator<<(output::ColorStream &stream, const Comparison &comparison);
output::ColorStream &operator<<(output::ColorStream &stream, const Constant &constant);
output::ColorStream &operator<<(output::ColorStream &stream, const Function &function);
output::ColorStream &operator<<(output::ColorStream &stream, const In &in);
output::ColorStream &operator<<(output::ColorStream &stream, const Integer &integer);
output::ColorStream &operator<<(output::ColorStream &stream, const Interval &interval);
output::ColorStream &operator<<(output::ColorStream &stream, const Predicate &predicate);
output::ColorStream &operator<<(output::ColorStream &stream, const SpecialInteger &specialInteger);
output::ColorStream &operator<<(output::ColorStream &stream, const String &string);
output::ColorStream &operator<<(output::ColorStream &stream, const Variable &variable);
struct PrintContext
{
std::map<const ast::VariableDeclaration *, size_t> userVariableIDs;
std::map<const ast::VariableDeclaration *, size_t> headVariableIDs;
std::map<const ast::VariableDeclaration *, size_t> bodyVariableIDs;
};
output::ColorStream &operator<<(output::ColorStream &stream, const And &and_);
output::ColorStream &operator<<(output::ColorStream &stream, const Biconditional &biconditional);
output::ColorStream &operator<<(output::ColorStream &stream, const Exists &exists);
output::ColorStream &operator<<(output::ColorStream &stream, const ForAll &forAll);
output::ColorStream &operator<<(output::ColorStream &stream, const Implies &implies);
output::ColorStream &operator<<(output::ColorStream &stream, const Not &not_);
output::ColorStream &operator<<(output::ColorStream &stream, const Or &or_);
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const Formula &formula);
output::ColorStream &operator<<(output::ColorStream &stream, const Term &term);
output::ColorStream &print(output::ColorStream &stream, const BinaryOperation::Operator operator_, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const BinaryOperation &binaryOperation, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const Boolean &boolean, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const Comparison &comparison, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const Constant &constant, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const Function &function, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const In &in, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const Integer &integer, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const Interval &interval, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const Predicate &predicate, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const SpecialInteger &specialInteger, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const String &string, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const Variable &variable, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const VariableDeclaration &variableDeclaration, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const And &and_, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const Biconditional &biconditional, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const Exists &exists, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const ForAll &forAll, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const Implies &implies, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const Not &not_, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const Or &or_, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const Formula &formula, PrintContext &printContext);
output::ColorStream &print(output::ColorStream &stream, const Term &term, PrintContext &printContext);
////////////////////////////////////////////////////////////////////////////////////////////////////
// Primitives
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, BinaryOperation::Operator operator_)
inline output::ColorStream &print(output::ColorStream &stream, BinaryOperation::Operator operator_, PrintContext &)
{
switch (operator_)
{
@@ -69,14 +80,22 @@ inline output::ColorStream &operator<<(output::ColorStream &stream, BinaryOperat
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const BinaryOperation &binaryOperation)
inline output::ColorStream &print(output::ColorStream &stream, const BinaryOperation &binaryOperation, PrintContext &printContext)
{
return (stream << "(" << binaryOperation.left << " " << binaryOperation.operator_ << " " << binaryOperation.right << ")");
stream << "(";
print(stream, binaryOperation.left, printContext);
stream << " ";
print(stream, binaryOperation.operator_, printContext);
stream << " ";
print(stream, binaryOperation.right, printContext);
stream << ")";
return stream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const Boolean &boolean)
inline output::ColorStream &print(output::ColorStream &stream, const Boolean &boolean, PrintContext &)
{
if (boolean.value)
return (stream << output::Boolean("#true"));
@@ -86,7 +105,7 @@ inline output::ColorStream &operator<<(output::ColorStream &stream, const Boolea
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, Comparison::Operator operator_)
inline output::ColorStream &print(output::ColorStream &stream, Comparison::Operator operator_, PrintContext &)
{
switch (operator_)
{
@@ -109,21 +128,27 @@ inline output::ColorStream &operator<<(output::ColorStream &stream, Comparison::
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const Comparison &comparison)
inline output::ColorStream &print(output::ColorStream &stream, const Comparison &comparison, PrintContext &printContext)
{
return (stream << comparison.left << " " << comparison.operator_ << " " << comparison.right);
print(stream, comparison.left, printContext);
stream << " ";
print(stream, comparison.operator_, printContext);
stream << " ";
print(stream, comparison.right, printContext);
return stream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const Constant &constant)
inline output::ColorStream &print(output::ColorStream &stream, const Constant &constant, PrintContext &)
{
return (stream << constant.name);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const Function &function)
inline output::ColorStream &print(output::ColorStream &stream, const Function &function, PrintContext &printContext)
{
stream << function.name;
@@ -137,39 +162,49 @@ inline output::ColorStream &operator<<(output::ColorStream &stream, const Functi
if (i != function.arguments.cbegin())
stream << ", ";
stream << (*i);
print(stream, *i, printContext);
}
if (function.name.empty() && function.arguments.size() == 1)
stream << ",";
return (stream << ")");
stream << ")";
return stream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const In &in)
inline output::ColorStream &print(output::ColorStream &stream, const In &in, PrintContext &printContext)
{
return (stream << in.element << " " << output::Keyword("in") << " " << in.set);
print(stream, in.element, printContext);
stream << " " << output::Keyword("in") << " ";
print(stream, in.set, printContext);
return stream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const Integer &integer)
inline output::ColorStream &print(output::ColorStream &stream, const Integer &integer, PrintContext &)
{
return (stream << output::Number<int>(integer.value));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const Interval &interval)
inline output::ColorStream &print(output::ColorStream &stream, const Interval &interval, PrintContext &printContext)
{
return (stream << interval.from << ".." << interval.to);
print(stream, interval.from, printContext);
stream << "..";
print(stream, interval.to, printContext);
return stream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const Predicate &predicate)
inline output::ColorStream &print(output::ColorStream &stream, const Predicate &predicate, PrintContext &printContext)
{
stream << predicate.name;
@@ -183,15 +218,17 @@ inline output::ColorStream &operator<<(output::ColorStream &stream, const Predic
if (i != predicate.arguments.cbegin())
stream << ", ";
stream << (*i);
print(stream, *i, printContext);
}
return (stream << ")");
stream << ")";
return stream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const SpecialInteger &specialInteger)
inline output::ColorStream &print(output::ColorStream &stream, const SpecialInteger &specialInteger, PrintContext &)
{
switch (specialInteger.type)
{
@@ -206,31 +243,59 @@ inline output::ColorStream &operator<<(output::ColorStream &stream, const Specia
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const String &string)
inline output::ColorStream &print(output::ColorStream &stream, const String &string, PrintContext &)
{
return (stream << output::String(string.text.c_str()));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const Variable &variable)
inline output::ColorStream &print(output::ColorStream &stream, const Variable &variable, PrintContext &printContext)
{
assert(!variable.name.empty());
assert(variable.name != "_");
assert(variable.declaration != nullptr);
if (variable.type == ast::Variable::Type::Reserved || !isReservedVariableName(variable.name.c_str()))
return (stream << output::Variable(variable.name.c_str()));
return print(stream, *variable.declaration, printContext);
}
const auto variableName = std::string(UserVariablePrefix) + variable.name;
////////////////////////////////////////////////////////////////////////////////////////////////////
return (stream << output::Variable(variableName.c_str()));
inline output::ColorStream &print(output::ColorStream &stream, const VariableDeclaration &variableDeclaration, PrintContext &printContext)
{
const auto printVariableDeclaration =
[&stream, &variableDeclaration](const auto *prefix, auto &variableIDs) -> output::ColorStream &
{
auto matchingVariableID = variableIDs.find(&variableDeclaration);
if (matchingVariableID == variableIDs.cend())
{
auto emplaceResult = variableIDs.emplace(std::make_pair(&variableDeclaration, variableIDs.size() + 1));
assert(emplaceResult.second);
matchingVariableID = emplaceResult.first;
}
const auto variableName = std::string(prefix) + std::to_string(matchingVariableID->second);
return (stream << output::Variable(variableName.c_str()));
};
switch (variableDeclaration.type)
{
case VariableDeclaration::Type::UserDefined:
return printVariableDeclaration(UserVariablePrefix, printContext.userVariableIDs);
case VariableDeclaration::Type::Head:
return printVariableDeclaration(HeadVariablePrefix, printContext.headVariableIDs);
case VariableDeclaration::Type::Body:
return printVariableDeclaration(BodyVariablePrefix, printContext.bodyVariableIDs);
}
return stream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Expressions
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const And &and_)
inline output::ColorStream &print(output::ColorStream &stream, const And &and_, PrintContext &printContext)
{
stream << "(";
@@ -239,22 +304,30 @@ inline output::ColorStream &operator<<(output::ColorStream &stream, const And &a
if (i != and_.arguments.cbegin())
stream << " " << output::Keyword("and") << " ";
stream << (*i);
print(stream, *i, printContext);
}
return (stream << ")");
stream << ")";
return stream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const Biconditional &biconditional)
inline output::ColorStream &print(output::ColorStream &stream, const Biconditional &biconditional, PrintContext &printContext)
{
return (stream << "(" << biconditional.left << " <-> " << biconditional.right << ")");
stream << "(";
print(stream, biconditional.left, printContext);
stream << " <-> ";
print(stream, biconditional.right, printContext);
stream << ")";
return stream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const Exists &exists)
inline output::ColorStream &print(output::ColorStream &stream, const Exists &exists, PrintContext &printContext)
{
stream << output::Keyword("exists") << " ";
@@ -263,15 +336,18 @@ inline output::ColorStream &operator<<(output::ColorStream &stream, const Exists
if (i != exists.variables.cbegin())
stream << ", ";
stream << (*i);
print(stream, **i, printContext);
}
return (stream << " " << exists.argument);
stream << " ";
print(stream, exists.argument, printContext);
return stream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const ForAll &forAll)
inline output::ColorStream &print(output::ColorStream &stream, const ForAll &forAll, PrintContext &printContext)
{
stream << output::Keyword("forall") << " ";
@@ -280,29 +356,41 @@ inline output::ColorStream &operator<<(output::ColorStream &stream, const ForAll
if (i != forAll.variables.cbegin())
stream << ", ";
stream << (*i);
print(stream, **i, printContext);
}
return (stream << " " << forAll.argument);
stream << " ";
print(stream, forAll.argument, printContext);
return stream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const Implies &implies)
inline output::ColorStream &print(output::ColorStream &stream, const Implies &implies, PrintContext &printContext)
{
return (stream << "(" << implies.antecedent << " -> " << implies.consequent << ")");
stream << "(";
print(stream, implies.antecedent, printContext);
stream << " -> ";
print(stream, implies.consequent, printContext);
stream << ")";
return stream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const Not &not_)
inline output::ColorStream &print(output::ColorStream &stream, const Not &not_, PrintContext &printContext)
{
return (stream << output::Keyword("not ") << not_.argument);
stream << output::Keyword("not") << " ";
print(stream, not_.argument, printContext);
return stream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const Or &or_)
inline output::ColorStream &print(output::ColorStream &stream, const Or &or_, PrintContext &printContext)
{
stream << "(";
@@ -311,10 +399,12 @@ inline output::ColorStream &operator<<(output::ColorStream &stream, const Or &or
if (i != or_.arguments.cbegin())
stream << " " << output::Keyword("or") << " ";
stream << (*i);
print(stream, *i, printContext);
}
return (stream << ")");
stream << ")";
return stream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -325,24 +415,24 @@ template<class Variant>
struct VariantPrintVisitor
{
template<class T>
output::ColorStream &visit(const T &x, output::ColorStream &stream)
output::ColorStream &visit(const T &x, output::ColorStream &stream, PrintContext &printContext)
{
return (stream << x);
return print(stream, x, printContext);
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const Formula &formula)
inline output::ColorStream &print(output::ColorStream &stream, const Formula &formula, PrintContext &printContext)
{
return formula.accept(VariantPrintVisitor<ast::Formula>(), stream);
return formula.accept(VariantPrintVisitor<ast::Formula>(), stream, printContext);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const Term &term)
inline output::ColorStream &print(output::ColorStream &stream, const Term &term, PrintContext &printContext)
{
return term.accept(VariantPrintVisitor<ast::Term>(), stream);
return term.accept(VariantPrintVisitor<ast::Term>(), stream, printContext);
}
////////////////////////////////////////////////////////////////////////////////////////////////////