Major refactoring to uniquely link variables to their declarations (breaks simplification and completion).
This commit is contained in:
@@ -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
60
include/anthem/ASTCopy.h
Normal 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
|
@@ -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;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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(¶meters);
|
||||
|
||||
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;
|
||||
|
@@ -12,7 +12,7 @@ namespace anthem
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void complete(std::vector<ast::Formula> &formulas);
|
||||
void complete(std::vector<ast::ScopedFormula> &scopedFormulas);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -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;
|
||||
|
34
include/anthem/RuleContext.h
Normal file
34
include/anthem/RuleContext.h
Normal 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
|
@@ -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 atom’s 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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@@ -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 ¬_);
|
||||
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 ¬_, 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 ¬_)
|
||||
inline output::ColorStream &print(output::ColorStream &stream, const 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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
Reference in New Issue
Block a user