226 lines
7.8 KiB
C++
226 lines
7.8 KiB
C++
#ifndef __ANTHEM__BODY_H
|
|
#define __ANTHEM__BODY_H
|
|
|
|
#include <algorithm>
|
|
|
|
#include <anthem/Context.h>
|
|
#include <anthem/Utils.h>
|
|
#include <anthem/output/ClingoOutput.h>
|
|
#include <anthem/output/Formatting.h>
|
|
|
|
namespace anthem
|
|
{
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Body
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
struct TermPrintVisitor
|
|
{
|
|
void visit(const Clingo::Symbol &, const Clingo::AST::Literal &, const Clingo::AST::Term &term, Context &context)
|
|
{
|
|
throwErrorAtLocation(term.location, "“symbol” terms currently unsupported in this context", context);
|
|
}
|
|
|
|
void visit(const Clingo::AST::Variable &, const Clingo::AST::Literal &, const Clingo::AST::Term &term, Context &context)
|
|
{
|
|
throwErrorAtLocation(term.location, "“variable” terms currently unsupported in this context", context);
|
|
}
|
|
|
|
void visit(const Clingo::AST::UnaryOperation &, const Clingo::AST::Literal &, const Clingo::AST::Term &term, Context &context)
|
|
{
|
|
throwErrorAtLocation(term.location, "“unary operation” terms currently unsupported in this context", context);
|
|
}
|
|
|
|
void visit(const Clingo::AST::BinaryOperation &, const Clingo::AST::Literal &, const Clingo::AST::Term &term, Context &context)
|
|
{
|
|
throwErrorAtLocation(term.location, "“binary operation” terms currently unsupported in this context", context);
|
|
}
|
|
|
|
void visit(const Clingo::AST::Interval &, const Clingo::AST::Literal &, const Clingo::AST::Term &term, Context &context)
|
|
{
|
|
throwErrorAtLocation(term.location, "“interval” terms currently unsupported in this context", context);
|
|
}
|
|
|
|
// TODO: check correctness
|
|
void visit(const Clingo::AST::Function &function, const Clingo::AST::Literal &literal, const Clingo::AST::Term &, Context &context)
|
|
{
|
|
if (literal.sign == Clingo::AST::Sign::DoubleNegation)
|
|
throwErrorAtLocation(literal.location, "double-negated literals currently unsupported", context);
|
|
|
|
auto &outputStream = context.logger.outputStream();
|
|
|
|
if (function.arguments.empty())
|
|
{
|
|
outputStream << output::Function(function.name);
|
|
return;
|
|
}
|
|
|
|
outputStream << output::Keyword("exists") << " ";
|
|
|
|
for (auto i = function.arguments.cbegin(); i != function.arguments.cend(); i++)
|
|
{
|
|
if (i != function.arguments.cbegin())
|
|
outputStream << ", ";
|
|
|
|
const auto variableName = std::string(AuxiliaryBodyVariablePrefix) + std::to_string(context.auxiliaryBodyLiteralID + i - function.arguments.cbegin());
|
|
|
|
outputStream << output::Variable(variableName.c_str());
|
|
}
|
|
|
|
outputStream << " (";
|
|
|
|
for (auto i = function.arguments.cbegin(); i != function.arguments.cend(); i++)
|
|
{
|
|
const auto &argument = *i;
|
|
|
|
if (i != function.arguments.cbegin())
|
|
outputStream << " " << Clingo::AST::BinaryOperator::And << " ";
|
|
|
|
const auto variableName = std::string(AuxiliaryBodyVariablePrefix) + std::to_string(context.auxiliaryBodyLiteralID + i - function.arguments.cbegin());
|
|
|
|
outputStream
|
|
<< output::Variable(variableName.c_str())
|
|
<< " " << output::Keyword("in") << " "
|
|
<< argument;
|
|
}
|
|
|
|
outputStream
|
|
<< " " << Clingo::AST::BinaryOperator::And << " "
|
|
<< literal.sign
|
|
<< output::Function(function.name) << "(";
|
|
|
|
for (auto i = function.arguments.cbegin(); i != function.arguments.cend(); i++)
|
|
{
|
|
if (i != function.arguments.cbegin())
|
|
outputStream << ", ";
|
|
|
|
const auto variableName = std::string(AuxiliaryBodyVariablePrefix) + std::to_string(context.auxiliaryBodyLiteralID + i - function.arguments.cbegin());
|
|
|
|
outputStream << output::Variable(variableName.c_str());
|
|
}
|
|
|
|
outputStream << "))";
|
|
|
|
context.auxiliaryBodyLiteralID += function.arguments.size();
|
|
}
|
|
|
|
void visit(const Clingo::AST::Pool &, const Clingo::AST::Literal &, const Clingo::AST::Term &term, Context &context)
|
|
{
|
|
throwErrorAtLocation(term.location, "“pool” terms currently unsupported", context);
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
struct LiteralPrintVisitor
|
|
{
|
|
void visit(const Clingo::AST::Boolean &, const Clingo::AST::Literal &literal, Context &context)
|
|
{
|
|
throwErrorAtLocation(literal.location, "“boolean” literals currently unsupported in this context", context);
|
|
}
|
|
|
|
void visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &literal, Context &context)
|
|
{
|
|
term.data.accept(TermPrintVisitor(), literal, term, context);
|
|
}
|
|
|
|
// TODO: refactor
|
|
void visit(const Clingo::AST::Comparison &comparison, const Clingo::AST::Literal &literal, Context &context)
|
|
{
|
|
assert(literal.sign == Clingo::AST::Sign::None);
|
|
|
|
const char *operatorName = "";
|
|
|
|
switch (comparison.comparison)
|
|
{
|
|
case Clingo::AST::ComparisonOperator::GreaterThan:
|
|
operatorName = ">";
|
|
break;
|
|
case Clingo::AST::ComparisonOperator::LessThan:
|
|
operatorName = "<";
|
|
break;
|
|
case Clingo::AST::ComparisonOperator::LessEqual:
|
|
operatorName = "<=";
|
|
break;
|
|
case Clingo::AST::ComparisonOperator::GreaterEqual:
|
|
operatorName = ">=";
|
|
break;
|
|
case Clingo::AST::ComparisonOperator::NotEqual:
|
|
operatorName = "!=";
|
|
break;
|
|
case Clingo::AST::ComparisonOperator::Equal:
|
|
operatorName = "=";
|
|
break;
|
|
}
|
|
|
|
const auto variableName1 = std::string(AuxiliaryBodyVariablePrefix) + std::to_string(context.auxiliaryBodyLiteralID);
|
|
const auto variableName2 = std::string(AuxiliaryBodyVariablePrefix) + std::to_string(context.auxiliaryBodyLiteralID + 1);
|
|
|
|
context.logger.outputStream()
|
|
<< output::Keyword("exists") << " " << output::Variable(variableName1.c_str())
|
|
<< ", " << output::Variable(variableName2.c_str())
|
|
<< " ("
|
|
<< output::Variable(variableName1.c_str())
|
|
<< " " << output::Keyword("in") << " " << comparison.left
|
|
<< " " << Clingo::AST::BinaryOperator::And << " "
|
|
<< output::Variable(variableName2.c_str())
|
|
<< " " << output::Keyword("in") << " " << comparison.right
|
|
<< " " << Clingo::AST::BinaryOperator::And << " "
|
|
<< output::Variable(variableName1.c_str())
|
|
<< " " << output::Operator(operatorName) << " "
|
|
<< output::Variable(variableName2.c_str())
|
|
<< ")";
|
|
|
|
context.auxiliaryBodyLiteralID += 2;
|
|
}
|
|
|
|
void visit(const Clingo::AST::CSPLiteral &, const Clingo::AST::Literal &literal, Context &context)
|
|
{
|
|
throwErrorAtLocation(literal.location, "CSP literals currently unsupported", context);
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
struct BodyLiteralPrintVisitor
|
|
{
|
|
void visit(const Clingo::AST::Literal &literal, const Clingo::AST::BodyLiteral &, Context &context)
|
|
{
|
|
literal.data.accept(LiteralPrintVisitor(), literal, context);
|
|
}
|
|
|
|
void visit(const Clingo::AST::ConditionalLiteral &, const Clingo::AST::BodyLiteral &bodyLiteral, Context &context)
|
|
{
|
|
throwErrorAtLocation(bodyLiteral.location, "“conditional literal” body literals currently unsupported", context);
|
|
}
|
|
|
|
void visit(const Clingo::AST::Aggregate &, const Clingo::AST::BodyLiteral &bodyLiteral, Context &context)
|
|
{
|
|
throwErrorAtLocation(bodyLiteral.location, "“aggregate” body literals currently unsupported", context);
|
|
}
|
|
|
|
void visit(const Clingo::AST::BodyAggregate &, const Clingo::AST::BodyLiteral &bodyLiteral, Context &context)
|
|
{
|
|
throwErrorAtLocation(bodyLiteral.location, "“body aggregate” body literals currently unsupported", context);
|
|
}
|
|
|
|
void visit(const Clingo::AST::TheoryAtom &, const Clingo::AST::BodyLiteral &bodyLiteral, Context &context)
|
|
{
|
|
throwErrorAtLocation(bodyLiteral.location, "“theory atom” body literals currently unsupported", context);
|
|
}
|
|
|
|
void visit(const Clingo::AST::Disjoint &, const Clingo::AST::BodyLiteral &bodyLiteral, Context &context)
|
|
{
|
|
throwErrorAtLocation(bodyLiteral.location, "“disjoint” body literals currently unsupported", context);
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}
|
|
|
|
#endif
|