Refactored error handling.

This commit is contained in:
Patrick Lühne 2017-05-31 18:03:19 +02:00
parent aea640a624
commit 0d8b1e94da
No known key found for this signature in database
GPG Key ID: 05F3611E97A70ABF
11 changed files with 224 additions and 142 deletions

View File

@ -43,10 +43,10 @@ ast::Comparison::Operator translate(Clingo::AST::ComparisonOperator comparisonOp
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, RuleContext &ruleContext, ast::VariableStack &variableStack)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Function &function, const Clingo::AST::Literal &literal, const Clingo::AST::Term &, RuleContext &ruleContext, ast::VariableStack &variableStack)
{
if (literal.sign == Clingo::AST::Sign::DoubleNegation)
throwErrorAtLocation(literal.location, "double-negated literals currently unsupported", context);
throw TranslationException(literal.location, "double-negated literals currently unsupported");
if (function.arguments.empty())
{
@ -73,7 +73,7 @@ struct BodyTermTranslateVisitor
for (size_t i = 0; i < function.arguments.size(); i++)
{
auto &argument = function.arguments[i];
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(ast::Variable(parameters[i].get()), translate(argument, context, ruleContext, variableStack)));
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(ast::Variable(parameters[i].get()), translate(argument, ruleContext, variableStack)));
}
variableStack.pop();
@ -93,11 +93,11 @@ struct BodyTermTranslateVisitor
}
template<class T>
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &, const Clingo::AST::Term &term, Context &context, RuleContext &, ast::VariableStack &)
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &, const Clingo::AST::Term &term, RuleContext &, ast::VariableStack &)
{
assert(!term.data.is<Clingo::AST::Function>());
throwErrorAtLocation(term.location, "term currently unsupported in this context, expected function", context);
throw TranslationException(term.location, "term currently unsupported in this context, expected function");
return std::experimental::nullopt;
}
};
@ -106,22 +106,22 @@ struct BodyTermTranslateVisitor
struct BodyLiteralTranslateVisitor
{
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, Context &, RuleContext &, ast::VariableStack &)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, 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, RuleContext &ruleContext, ast::VariableStack &variableStack)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &literal, RuleContext &ruleContext, ast::VariableStack &variableStack)
{
return term.data.accept(BodyTermTranslateVisitor(), literal, term, context, ruleContext, variableStack);
return term.data.accept(BodyTermTranslateVisitor(), literal, term, ruleContext, variableStack);
}
// TODO: refactor
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Comparison &comparison, const Clingo::AST::Literal &literal, Context &context, RuleContext &ruleContext, ast::VariableStack &variableStack)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Comparison &comparison, const Clingo::AST::Literal &literal, 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)
throwErrorAtLocation(literal.location, "negated comparisons currently unsupported", context);
throw TranslationException(literal.location, "negated comparisons currently unsupported");
const auto operator_ = translate(comparison.comparison);
@ -132,17 +132,17 @@ struct BodyLiteralTranslateVisitor
ast::And conjunction;
conjunction.arguments.reserve(3);
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::In>(ast::Variable(parameters[0].get()), translate(comparison.left, ruleContext, variableStack)));
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(ast::Variable(parameters[1].get()), translate(comparison.right, ruleContext, variableStack)));
conjunction.arguments.emplace_back(ast::Formula::make<ast::Comparison>(operator_, ast::Variable(parameters[0].get()), ast::Variable(parameters[1].get())));
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, RuleContext &, ast::VariableStack &)
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &literal, RuleContext &, ast::VariableStack &)
{
throwErrorAtLocation(literal.location, "literal currently unsupported in this context, expected function or term", context);
throw TranslationException(literal.location, "literal currently unsupported in this context, expected function or term");
return std::experimental::nullopt;
}
};
@ -151,18 +151,18 @@ struct BodyLiteralTranslateVisitor
struct BodyBodyLiteralTranslateVisitor
{
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Literal &literal, const Clingo::AST::BodyLiteral &bodyLiteral, Context &context, RuleContext &ruleContext, ast::VariableStack &variableStack)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Literal &literal, const Clingo::AST::BodyLiteral &bodyLiteral, RuleContext &ruleContext, ast::VariableStack &variableStack)
{
if (bodyLiteral.sign != Clingo::AST::Sign::None)
throwErrorAtLocation(bodyLiteral.location, "only positive body literals supported currently", context);
throw TranslationException(bodyLiteral.location, "only positive body literals supported currently");
return literal.data.accept(BodyLiteralTranslateVisitor(), literal, context, ruleContext, variableStack);
return literal.data.accept(BodyLiteralTranslateVisitor(), literal, ruleContext, variableStack);
}
template<class T>
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::BodyLiteral &bodyLiteral, Context &context, RuleContext &, ast::VariableStack &)
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::BodyLiteral &bodyLiteral, RuleContext &, ast::VariableStack &)
{
throwErrorAtLocation(bodyLiteral.location, "body literal currently unsupported in this context, expected literal", context);
throw TranslationException(bodyLiteral.location, "body literal currently unsupported in this context, expected literal");
return std::experimental::nullopt;
}
};

102
include/anthem/Exception.h Normal file
View File

@ -0,0 +1,102 @@
#ifndef __ANTHEM__EXCEPTION_H
#define __ANTHEM__EXCEPTION_H
#include <exception>
#include <string>
#include <anthem/Location.h>
namespace anthem
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Exception
//
////////////////////////////////////////////////////////////////////////////////////////////////////
// TODO: implement stream operators to modify message
class Exception: public std::exception
{
public:
Exception() = delete;
Exception(const Exception &other) = delete;
Exception &operator=(const Exception &other) = delete;
Exception(Exception &&other) = default;
Exception &operator=(Exception &&other) = default;
explicit Exception(const Location &location)
: Exception(location, "unspecified error")
{
}
explicit Exception(const Location &location, const char *message)
: Exception(location, static_cast<std::string>(message))
{
}
explicit Exception(const Location &location, const std::string &message)
: m_location{location},
m_message{message},
// TODO: refactor
m_plainMessage{std::string(m_location.sectionStart) + ":" + std::to_string(m_location.rowStart)
+ ":" + std::to_string(m_location.columnStart) + " " + m_message}
{
}
~Exception() noexcept = default;
const char *what() const noexcept
{
return m_plainMessage.c_str();
}
const Location &location() const
{
return m_location;
}
const std::string &message() const
{
return m_message;
}
private:
Location m_location;
std::string m_message;
std::string m_plainMessage;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
class LogicException : public Exception
{
using Exception::Exception;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
class TranslationException : public Exception
{
using Exception::Exception;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
class SimplificationException : public Exception
{
using Exception::Exception;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
class CompletionException : public Exception
{
using Exception::Exception;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
#endif

View File

@ -5,6 +5,7 @@
#include <experimental/optional>
#include <anthem/AST.h>
#include <anthem/Exception.h>
#include <anthem/RuleContext.h>
#include <anthem/Utils.h>
#include <anthem/output/Formatting.h>
@ -24,10 +25,10 @@ namespace anthem
struct TermCollectFunctionTermsVisitor
{
void visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext)
void visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, RuleContext &ruleContext)
{
if (function.external)
throwErrorAtLocation(term.location, "external functions currently unsupported", context);
throw LogicException(term.location, "external functions currently unsupported");
ruleContext.headTerms.reserve(ruleContext.headTerms.size() + function.arguments.size());
@ -36,9 +37,9 @@ struct TermCollectFunctionTermsVisitor
}
template<class T>
void visit(const T &, const Clingo::AST::Term &term, Context &context, RuleContext &)
void visit(const T &, const Clingo::AST::Term &term, RuleContext &)
{
throwErrorAtLocation(term.location, "term currently unsupported in this context, function expected", context);
throw LogicException(term.location, "term currently unsupported in this function expected");
}
};
@ -46,19 +47,19 @@ struct TermCollectFunctionTermsVisitor
struct LiteralCollectFunctionTermsVisitor
{
void visit(const Clingo::AST::Boolean &, const Clingo::AST::Literal &, Context &, RuleContext &)
void visit(const Clingo::AST::Boolean &, const Clingo::AST::Literal &, RuleContext &)
{
}
void visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &, Context &context, RuleContext &ruleContext)
void visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &, RuleContext &ruleContext)
{
term.data.accept(TermCollectFunctionTermsVisitor(), term, context, ruleContext);
term.data.accept(TermCollectFunctionTermsVisitor(), term, ruleContext);
}
template<class T>
void visit(const T &, const Clingo::AST::Literal &literal, Context &context, RuleContext &)
void visit(const T &, const Clingo::AST::Literal &literal, RuleContext &)
{
throwErrorAtLocation(literal.location, "only disjunctions of literals allowed as head literals", context);
throw LogicException(literal.location, "only disjunctions of literals allowed as head literals");
}
};
@ -67,47 +68,47 @@ 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, RuleContext &ruleContext)
void visit(const Clingo::AST::Literal &literal, const Clingo::AST::HeadLiteral &, RuleContext &ruleContext)
{
ruleContext.numberOfHeadLiterals = 1;
literal.data.accept(LiteralCollectFunctionTermsVisitor(), literal, context, ruleContext);
literal.data.accept(LiteralCollectFunctionTermsVisitor(), literal, ruleContext);
}
void visit(const Clingo::AST::Disjunction &disjunction, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &ruleContext)
void visit(const Clingo::AST::Disjunction &disjunction, const Clingo::AST::HeadLiteral &headLiteral, RuleContext &ruleContext)
{
ruleContext.numberOfHeadLiterals = disjunction.elements.size();
for (const auto &conditionalLiteral : disjunction.elements)
{
if (!conditionalLiteral.condition.empty())
throwErrorAtLocation(headLiteral.location, "conditional head literals currently unsupported", context);
throw LogicException(headLiteral.location, "conditional head literals currently unsupported");
conditionalLiteral.literal.data.accept(LiteralCollectFunctionTermsVisitor(), conditionalLiteral.literal, context, ruleContext);
conditionalLiteral.literal.data.accept(LiteralCollectFunctionTermsVisitor(), conditionalLiteral.literal, ruleContext);
}
}
void visit(const Clingo::AST::Aggregate &aggregate, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &ruleContext)
void visit(const Clingo::AST::Aggregate &aggregate, const Clingo::AST::HeadLiteral &headLiteral, RuleContext &ruleContext)
{
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);
throw LogicException(headLiteral.location, "aggregates with left or right guards currently unsupported");
for (const auto &conditionalLiteral : aggregate.elements)
{
if (!conditionalLiteral.condition.empty())
throwErrorAtLocation(headLiteral.location, "conditional literals in aggregates currently unsupported", context);
throw LogicException(headLiteral.location, "conditional literals in aggregates currently unsupported");
conditionalLiteral.literal.data.accept(LiteralCollectFunctionTermsVisitor(), conditionalLiteral.literal, context, ruleContext);
conditionalLiteral.literal.data.accept(LiteralCollectFunctionTermsVisitor(), conditionalLiteral.literal, ruleContext);
}
}
template<class T>
void visit(const T &, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &)
void visit(const T &, const Clingo::AST::HeadLiteral &headLiteral, RuleContext &)
{
throwErrorAtLocation(headLiteral.location, "head literal currently unsupported in this context, expected literal, disjunction, or aggregate", context);
throw LogicException(headLiteral.location, "head literal currently unsupported in this expected literal, disjunction, or aggregate");
}
};
@ -118,10 +119,10 @@ struct HeadLiteralCollectFunctionTermsVisitor
struct FunctionTermTranslateVisitor
{
// TODO: check correctness
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, size_t &headVariableIndex)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, RuleContext &ruleContext, size_t &headVariableIndex)
{
if (function.external)
throwErrorAtLocation(term.location, "external functions currently unsupported", context);
throw TranslationException(term.location, "external functions currently unsupported");
std::vector<ast::Term> arguments;
arguments.reserve(function.arguments.size());
@ -133,9 +134,9 @@ struct FunctionTermTranslateVisitor
}
template<class T>
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Term &term, Context &context, RuleContext &, size_t &)
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Term &term, RuleContext &, size_t &)
{
throwErrorAtLocation(term.location, "term currently unsupported in this context, function expected", context);
throw TranslationException(term.location, "term currently unsupported in this function expected");
return std::experimental::nullopt;
}
};
@ -144,20 +145,20 @@ struct FunctionTermTranslateVisitor
struct LiteralTranslateVisitor
{
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, Context &, RuleContext &, size_t &)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, 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, RuleContext &ruleContext, size_t &headVariableIndex)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &, RuleContext &ruleContext, size_t &headVariableIndex)
{
return term.data.accept(FunctionTermTranslateVisitor(), term, context, ruleContext, headVariableIndex);
return term.data.accept(FunctionTermTranslateVisitor(), term, ruleContext, headVariableIndex);
}
template<class T>
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &literal, Context &context, RuleContext &, size_t &)
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &literal, RuleContext &, size_t &)
{
throwErrorAtLocation(literal.location, "only disjunctions of literals allowed as head literals", context);
throw TranslationException(literal.location, "only disjunctions of literals allowed as head literals");
return std::experimental::nullopt;
}
};
@ -166,12 +167,12 @@ struct LiteralTranslateVisitor
struct HeadLiteralTranslateToConsequentVisitor
{
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Literal &literal, const Clingo::AST::HeadLiteral &, Context &context, RuleContext &ruleContext, size_t &headVariableIndex)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Literal &literal, const Clingo::AST::HeadLiteral &, RuleContext &ruleContext, size_t &headVariableIndex)
{
if (literal.sign == Clingo::AST::Sign::DoubleNegation)
throwErrorAtLocation(literal.location, "double-negated head literals currently unsupported", context);
throw TranslationException(literal.location, "double-negated head literals currently unsupported");
auto translatedLiteral = literal.data.accept(LiteralTranslateVisitor(), literal, context, ruleContext, headVariableIndex);
auto translatedLiteral = literal.data.accept(LiteralTranslateVisitor(), literal, ruleContext, headVariableIndex);
if (literal.sign == Clingo::AST::Sign::None)
return translatedLiteral;
@ -182,7 +183,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, RuleContext &ruleContext, size_t &headVariableIndex)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Disjunction &disjunction, const Clingo::AST::HeadLiteral &headLiteral, RuleContext &ruleContext, size_t &headVariableIndex)
{
std::vector<ast::Formula> arguments;
arguments.reserve(disjunction.elements.size());
@ -190,12 +191,12 @@ struct HeadLiteralTranslateToConsequentVisitor
for (const auto &conditionalLiteral : disjunction.elements)
{
if (!conditionalLiteral.condition.empty())
throwErrorAtLocation(headLiteral.location, "conditional head literals currently unsupported", context);
throw TranslationException(headLiteral.location, "conditional head literals currently unsupported");
auto argument = visit(conditionalLiteral.literal, headLiteral, context, ruleContext, headVariableIndex);
auto argument = visit(conditionalLiteral.literal, headLiteral, ruleContext, headVariableIndex);
if (!argument)
throwErrorAtLocation(headLiteral.location, "could not parse argument", context);
throw TranslationException(headLiteral.location, "could not parse argument");
arguments.emplace_back(std::move(argument.value()));
}
@ -203,18 +204,18 @@ 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, RuleContext &ruleContext, size_t &headVariableIndex)
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Aggregate &aggregate, const Clingo::AST::HeadLiteral &headLiteral, RuleContext &ruleContext, size_t &headVariableIndex)
{
if (aggregate.left_guard || aggregate.right_guard)
throwErrorAtLocation(headLiteral.location, "aggregates with left or right guards currently unsupported", context);
throw TranslationException(headLiteral.location, "aggregates with left or right guards currently unsupported");
const auto translateConditionalLiteral =
[&](const auto &conditionalLiteral)
{
if (!conditionalLiteral.condition.empty())
throwErrorAtLocation(headLiteral.location, "conditional head literals currently unsupported", context);
throw TranslationException(headLiteral.location, "conditional head literals currently unsupported");
return this->visit(conditionalLiteral.literal, headLiteral, context, ruleContext, headVariableIndex);
return this->visit(conditionalLiteral.literal, headLiteral, ruleContext, headVariableIndex);
};
if (aggregate.elements.size() == 1)
@ -228,7 +229,7 @@ struct HeadLiteralTranslateToConsequentVisitor
auto argument = translateConditionalLiteral(conditionalLiteral);
if (!argument)
throwErrorAtLocation(headLiteral.location, "could not parse argument", context);
throw TranslationException(headLiteral.location, "could not parse argument");
arguments.emplace_back(std::move(argument.value()));
}
@ -237,9 +238,9 @@ struct HeadLiteralTranslateToConsequentVisitor
}
template<class T>
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &, size_t &)
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::HeadLiteral &headLiteral, RuleContext &, size_t &)
{
throwErrorAtLocation(headLiteral.location, "head literal currently unsupported in this context, expected literal, disjunction, or aggregate", context);
throw TranslationException(headLiteral.location, "head literal currently unsupported in this expected literal, disjunction, or aggregate");
return std::experimental::nullopt;
}
};

View File

@ -3,10 +3,10 @@
#include <cstdlib>
#include <clingo.hh>
namespace anthem
{
namespace input
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
@ -16,6 +16,23 @@ namespace input
struct Location
{
Location() = default;
Location(const Clingo::Location &clingoLocation)
: sectionStart{clingoLocation.begin_file()},
sectionEnd{clingoLocation.end_file()},
rowStart{clingoLocation.begin_line()},
rowEnd{clingoLocation.end_line()},
columnStart{clingoLocation.begin_column()},
columnEnd{clingoLocation.end_column()}
{
}
Location(const Location &other) = default;
Location &operator=(const Location &other) = default;
Location(Location &&other) = default;
Location &operator=(Location &&other) = default;
const char *sectionStart = nullptr;
const char *sectionEnd = nullptr;
@ -28,7 +45,6 @@ struct Location
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -42,17 +42,17 @@ struct StatementVisitor
context.logger.log(output::Priority::Debug) << "[program] " << program.name;
if (!program.parameters.empty())
throwErrorAtLocation(statement.location, "program parameters currently unsupported", context);
throw LogicException(statement.location, "program parameters currently unsupported");
}
void visit(const Clingo::AST::Rule &rule, const Clingo::AST::Statement &, std::vector<ast::ScopedFormula> &scopedFormulas, Context &context)
void visit(const Clingo::AST::Rule &rule, const Clingo::AST::Statement &, std::vector<ast::ScopedFormula> &scopedFormulas, Context &)
{
RuleContext ruleContext;
ast::VariableStack variableStack;
variableStack.push(&ruleContext.freeVariables);
// Collect all head terms
rule.head.data.accept(HeadLiteralCollectFunctionTermsVisitor(), rule.head, context, ruleContext);
rule.head.data.accept(HeadLiteralCollectFunctionTermsVisitor(), rule.head, ruleContext);
// Create new variable declarations for the head terms
ruleContext.headVariablesStartIndex = ruleContext.freeVariables.size();
@ -68,16 +68,12 @@ struct StatementVisitor
// Compute consequent
auto headVariableIndex = ruleContext.headVariablesStartIndex;
auto consequent = rule.head.data.accept(HeadLiteralTranslateToConsequentVisitor(), rule.head, context, ruleContext, headVariableIndex);
auto consequent = rule.head.data.accept(HeadLiteralTranslateToConsequentVisitor(), rule.head, ruleContext, headVariableIndex);
assert(ruleContext.headTerms.size() == headVariableIndex - ruleContext.headVariablesStartIndex);
if (!consequent)
{
// TODO: think about throwing an exception instead
context.logger.log(output::Priority::Error) << "could not translate formula consequent";
return;
}
throw TranslationException(rule.head.location, "could not translate formula consequent");
// Generate auxiliary variables replacing the head atoms arguments
for (auto i = ruleContext.headTerms.cbegin(); i != ruleContext.headTerms.cend(); i++)
@ -86,7 +82,7 @@ struct StatementVisitor
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 set = translate(headTerm, ruleContext, variableStack);
auto in = ast::In(std::move(element), std::move(set));
antecedent.arguments.emplace_back(std::move(in));
@ -97,10 +93,10 @@ struct StatementVisitor
{
const auto &bodyLiteral = *i;
auto argument = bodyLiteral.data.accept(BodyBodyLiteralTranslateVisitor(), bodyLiteral, context, ruleContext, variableStack);
auto argument = bodyLiteral.data.accept(BodyBodyLiteralTranslateVisitor(), bodyLiteral, ruleContext, variableStack);
if (!argument)
throwErrorAtLocation(bodyLiteral.location, "could not translate body literal", context);
throw TranslationException(bodyLiteral.location, "could not translate body literal");
antecedent.arguments.emplace_back(std::move(argument.value()));
}
@ -155,9 +151,9 @@ struct StatementVisitor
}
template<class T>
void visit(const T &, const Clingo::AST::Statement &statement, std::vector<ast::ScopedFormula> &, Context &context)
void visit(const T &, const Clingo::AST::Statement &statement, std::vector<ast::ScopedFormula> &, Context &)
{
throwErrorAtLocation(statement.location, "statement currently unsupported, expected rule", context);
throw LogicException(statement.location, "statement currently unsupported, expected rule");
}
};

View File

@ -5,6 +5,7 @@
#include <anthem/AST.h>
#include <anthem/ASTUtils.h>
#include <anthem/Exception.h>
#include <anthem/RuleContext.h>
#include <anthem/Utils.h>
#include <anthem/output/Formatting.h>
@ -18,7 +19,7 @@ namespace anthem
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::BinaryOperation::Operator translate(Clingo::AST::BinaryOperator binaryOperator, const Clingo::AST::Term &term, Context &context)
ast::BinaryOperation::Operator translate(Clingo::AST::BinaryOperator binaryOperator, const Clingo::AST::Term &term)
{
switch (binaryOperator)
{
@ -33,7 +34,7 @@ ast::BinaryOperation::Operator translate(Clingo::AST::BinaryOperator binaryOpera
case Clingo::AST::BinaryOperator::Modulo:
return ast::BinaryOperation::Operator::Modulo;
default:
throwErrorAtLocation(term.location, "“binary operation” terms currently unsupported", context);
throw TranslationException(term.location, "“binary operation” terms currently unsupported");
}
return ast::BinaryOperation::Operator::Plus;
@ -41,13 +42,13 @@ ast::BinaryOperation::Operator translate(Clingo::AST::BinaryOperator binaryOpera
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::Term translate(const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack);
ast::Term translate(const Clingo::AST::Term &term, 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, RuleContext &ruleContext, const ast::VariableStack &variableStack)
std::experimental::optional<ast::Term> visit(const Clingo::Symbol &symbol, const Clingo::AST::Term &term, RuleContext &ruleContext, const ast::VariableStack &variableStack)
{
switch (symbol.type())
{
@ -68,10 +69,10 @@ struct TermTranslateVisitor
for (const auto &argument : symbol.arguments())
{
auto translatedArgument = visit(argument, term, context, ruleContext, variableStack);
auto translatedArgument = visit(argument, term, ruleContext, variableStack);
if (!translatedArgument)
throwErrorAtLocation(term.location, "could not translate argument", context);
throw TranslationException(term.location, "could not translate argument");
functionRaw.arguments.emplace_back(std::move(translatedArgument.value()));
}
@ -83,7 +84,7 @@ struct TermTranslateVisitor
return std::experimental::nullopt;
}
std::experimental::optional<ast::Term> visit(const Clingo::AST::Variable &variable, const Clingo::AST::Term &, Context &, RuleContext &ruleContext, const ast::VariableStack &variableStack)
std::experimental::optional<ast::Term> visit(const Clingo::AST::Variable &variable, const Clingo::AST::Term &, RuleContext &ruleContext, const ast::VariableStack &variableStack)
{
const auto matchingVariableDeclaration = variableStack.findUserVariableDeclaration(variable.name);
const auto isAnonymousVariable = (strcmp(variable.name, "_") == 0);
@ -99,58 +100,58 @@ struct TermTranslateVisitor
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, RuleContext &, const ast::VariableStack &)
std::experimental::optional<ast::Term> visit(const Clingo::AST::UnaryOperation &, const Clingo::AST::Term &term, RuleContext &, const ast::VariableStack &)
{
throwErrorAtLocation(term.location, "“unary operation” terms currently unsupported", context);
throw TranslationException(term.location, "“unary operation” terms currently unsupported");
return std::experimental::nullopt;
}
std::experimental::optional<ast::Term> visit(const Clingo::AST::BinaryOperation &binaryOperation, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack)
std::experimental::optional<ast::Term> visit(const Clingo::AST::BinaryOperation &binaryOperation, const Clingo::AST::Term &term, RuleContext &ruleContext, const ast::VariableStack &variableStack)
{
const auto operator_ = translate(binaryOperation.binary_operator, term, context);
auto left = translate(binaryOperation.left, context, ruleContext, variableStack);
auto right = translate(binaryOperation.right, context, ruleContext, variableStack);
const auto operator_ = translate(binaryOperation.binary_operator, term);
auto left = translate(binaryOperation.left, ruleContext, variableStack);
auto right = translate(binaryOperation.right, 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, RuleContext &ruleContext, const ast::VariableStack &variableStack)
std::experimental::optional<ast::Term> visit(const Clingo::AST::Interval &interval, const Clingo::AST::Term &, RuleContext &ruleContext, const ast::VariableStack &variableStack)
{
auto left = translate(interval.left, context, ruleContext, variableStack);
auto right = translate(interval.right, context, ruleContext, variableStack);
auto left = translate(interval.left, ruleContext, variableStack);
auto right = translate(interval.right, 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, RuleContext &ruleContext, const ast::VariableStack &variableStack)
std::experimental::optional<ast::Term> visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, RuleContext &ruleContext, const ast::VariableStack &variableStack)
{
if (function.external)
throwErrorAtLocation(term.location, "external functions currently unsupported", context);
throw TranslationException(term.location, "external functions currently unsupported");
std::vector<ast::Term> arguments;
arguments.reserve(function.arguments.size());
for (const auto &argument : function.arguments)
arguments.emplace_back(translate(argument, context, ruleContext, variableStack));
arguments.emplace_back(translate(argument, 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, RuleContext &, const ast::VariableStack &)
std::experimental::optional<ast::Term> visit(const Clingo::AST::Pool &, const Clingo::AST::Term &term, RuleContext &, const ast::VariableStack &)
{
throwErrorAtLocation(term.location, "“pool” terms currently unsupported", context);
throw TranslationException(term.location, "“pool” terms currently unsupported");
return std::experimental::nullopt;
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::Term translate(const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack)
ast::Term translate(const Clingo::AST::Term &term, RuleContext &ruleContext, const ast::VariableStack &variableStack)
{
auto translatedTerm = term.data.accept(TermTranslateVisitor(), term, context, ruleContext, variableStack);
auto translatedTerm = term.data.accept(TermTranslateVisitor(), term, ruleContext, variableStack);
if (!translatedTerm)
throwErrorAtLocation(term.location, "could not translate term", context);
throw TranslationException(term.location, "could not translate term");
return std::move(translatedTerm.value());
}

View File

@ -6,7 +6,7 @@
#include <clingo.hh>
#include <anthem/Context.h>
#include <anthem/input/Location.h>
#include <anthem/Location.h>
namespace anthem
{
@ -17,34 +17,6 @@ namespace anthem
//
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T1, class T2>
T1 location_cast(const T2 &location);
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
inline input::Location location_cast(const Clingo::Location &location)
{
return {location.begin_file(), location.end_file(), location.begin_line(), location.end_line(),
location.begin_column(), location.end_column()};
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// TODO: refactor
inline void throwErrorAtLocation(const Clingo::Location &clingoLocation, const char *errorMessage,
Context &context)
{
const auto location = location_cast<input::Location>(clingoLocation);
// TODO: think about removing this to avoid double error messages
context.logger.log(output::Priority::Error, location) << errorMessage;
throw std::runtime_error(errorMessage);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline bool isPrefix(const char *prefix, const char *string)
{
const auto prefixLength = std::strlen(prefix);

View File

@ -3,7 +3,7 @@
#include <string>
#include <anthem/input/Location.h>
#include <anthem/Location.h>
#include <anthem/output/ColorStream.h>
#include <anthem/output/FormatScope.h>
#include <anthem/output/Priority.h>
@ -34,7 +34,7 @@ class Logger
void setColorPolicy(ColorStream::ColorPolicy colorPolicy);
FormatScope log(Priority priority);
FormatScope log(Priority priority, const input::Location &location);
FormatScope log(Priority priority, const Location &location);
private:
ColorStream m_outputStream;

View File

@ -3,9 +3,6 @@ set(target anthem)
file(GLOB core_sources "anthem/*.cpp")
file(GLOB core_headers "../include/anthem/*.h")
file(GLOB input_sources "anthem/input/*.cpp")
file(GLOB input_headers "../include/anthem/input/*.h")
file(GLOB output_sources "anthem/output/*.cpp")
file(GLOB output_headers "../include/anthem/output/*.h")
@ -13,9 +10,6 @@ set(sources
${core_sources}
${core_headers}
${input_sources}
${input_headers}
${output_sources}
${output_headers}
)

View File

@ -110,7 +110,7 @@ FormatScope Logger::log(Priority priority)
////////////////////////////////////////////////////////////////////////////////////////////////////
FormatScope Logger::log(Priority priority, const input::Location &location)
FormatScope Logger::log(Priority priority, const Location &location)
{
const auto priorityID = static_cast<int>(priority);

View File

@ -15,7 +15,7 @@
std::stringstream errors;
anthem::output::Logger logger(output, errors);
anthem::Context context = {logger, {}};
anthem::Context context(std::move(logger));
context.simplify = true;
context.complete = true;