diff --git a/include/anthem/Body.h b/include/anthem/Body.h index 003cd49..463b85c 100644 --- a/include/anthem/Body.h +++ b/include/anthem/Body.h @@ -43,10 +43,10 @@ ast::Comparison::Operator translate(Clingo::AST::ComparisonOperator comparisonOp struct BodyTermTranslateVisitor { // TODO: refactor - std::experimental::optional 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 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::Variable(parameters[i].get()), translate(argument, context, ruleContext, variableStack))); + conjunction.arguments.emplace_back(ast::Formula::make(ast::Variable(parameters[i].get()), translate(argument, ruleContext, variableStack))); } variableStack.pop(); @@ -93,11 +93,11 @@ struct BodyTermTranslateVisitor } template - std::experimental::optional visit(const T &, const Clingo::AST::Literal &, const Clingo::AST::Term &term, Context &context, RuleContext &, ast::VariableStack &) + std::experimental::optional visit(const T &, const Clingo::AST::Literal &, const Clingo::AST::Term &term, RuleContext &, ast::VariableStack &) { assert(!term.data.is()); - 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 visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, Context &, RuleContext &, ast::VariableStack &) + std::experimental::optional visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, RuleContext &, ast::VariableStack &) { return ast::Formula::make(boolean.value); } - std::experimental::optional visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &literal, Context &context, RuleContext &ruleContext, ast::VariableStack &variableStack) + std::experimental::optional 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 visit(const Clingo::AST::Comparison &comparison, const Clingo::AST::Literal &literal, Context &context, RuleContext &ruleContext, ast::VariableStack &variableStack) + std::experimental::optional 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::Variable(parameters[0].get()), translate(comparison.left, context, ruleContext, variableStack))); - conjunction.arguments.emplace_back(ast::Formula::make(ast::Variable(parameters[1].get()), translate(comparison.right, context, ruleContext, variableStack))); + conjunction.arguments.emplace_back(ast::Formula::make(ast::Variable(parameters[0].get()), translate(comparison.left, ruleContext, variableStack))); + conjunction.arguments.emplace_back(ast::Formula::make(ast::Variable(parameters[1].get()), translate(comparison.right, ruleContext, variableStack))); conjunction.arguments.emplace_back(ast::Formula::make(operator_, ast::Variable(parameters[0].get()), ast::Variable(parameters[1].get()))); return ast::Formula::make(std::move(parameters), std::move(conjunction)); } template - std::experimental::optional visit(const T &, const Clingo::AST::Literal &literal, Context &context, RuleContext &, ast::VariableStack &) + std::experimental::optional 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 visit(const Clingo::AST::Literal &literal, const Clingo::AST::BodyLiteral &bodyLiteral, Context &context, RuleContext &ruleContext, ast::VariableStack &variableStack) + std::experimental::optional 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 - std::experimental::optional visit(const T &, const Clingo::AST::BodyLiteral &bodyLiteral, Context &context, RuleContext &, ast::VariableStack &) + std::experimental::optional 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; } }; diff --git a/include/anthem/Exception.h b/include/anthem/Exception.h new file mode 100644 index 0000000..51986c4 --- /dev/null +++ b/include/anthem/Exception.h @@ -0,0 +1,102 @@ +#ifndef __ANTHEM__EXCEPTION_H +#define __ANTHEM__EXCEPTION_H + +#include +#include + +#include + +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(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 diff --git a/include/anthem/Head.h b/include/anthem/Head.h index a44ee60..22ab07c 100644 --- a/include/anthem/Head.h +++ b/include/anthem/Head.h @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -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 - 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 - 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 - 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 visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, size_t &headVariableIndex) + std::experimental::optional 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 arguments; arguments.reserve(function.arguments.size()); @@ -133,9 +134,9 @@ struct FunctionTermTranslateVisitor } template - std::experimental::optional visit(const T &, const Clingo::AST::Term &term, Context &context, RuleContext &, size_t &) + std::experimental::optional 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 visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, Context &, RuleContext &, size_t &) + std::experimental::optional visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, RuleContext &, size_t &) { return ast::Formula::make(boolean.value); } - std::experimental::optional visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &, Context &context, RuleContext &ruleContext, size_t &headVariableIndex) + std::experimental::optional 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 - std::experimental::optional visit(const T &, const Clingo::AST::Literal &literal, Context &context, RuleContext &, size_t &) + std::experimental::optional 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 visit(const Clingo::AST::Literal &literal, const Clingo::AST::HeadLiteral &, Context &context, RuleContext &ruleContext, size_t &headVariableIndex) + std::experimental::optional 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(std::move(translatedLiteral.value())); } - std::experimental::optional visit(const Clingo::AST::Disjunction &disjunction, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &ruleContext, size_t &headVariableIndex) + std::experimental::optional visit(const Clingo::AST::Disjunction &disjunction, const Clingo::AST::HeadLiteral &headLiteral, RuleContext &ruleContext, size_t &headVariableIndex) { std::vector 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(std::move(arguments)); } - std::experimental::optional visit(const Clingo::AST::Aggregate &aggregate, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &ruleContext, size_t &headVariableIndex) + std::experimental::optional 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 - std::experimental::optional visit(const T &, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &, size_t &) + std::experimental::optional 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; } }; diff --git a/include/anthem/input/Location.h b/include/anthem/Location.h similarity index 54% rename from include/anthem/input/Location.h rename to include/anthem/Location.h index efd1d69..99c8a58 100644 --- a/include/anthem/input/Location.h +++ b/include/anthem/Location.h @@ -3,10 +3,10 @@ #include +#include + 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 diff --git a/include/anthem/StatementVisitor.h b/include/anthem/StatementVisitor.h index baf893b..fba4b29 100644 --- a/include/anthem/StatementVisitor.h +++ b/include/anthem/StatementVisitor.h @@ -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 &scopedFormulas, Context &context) + void visit(const Clingo::AST::Rule &rule, const Clingo::AST::Statement &, std::vector &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 atom’s 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 - void visit(const T &, const Clingo::AST::Statement &statement, std::vector &, Context &context) + void visit(const T &, const Clingo::AST::Statement &statement, std::vector &, Context &) { - throwErrorAtLocation(statement.location, "statement currently unsupported, expected rule", context); + throw LogicException(statement.location, "statement currently unsupported, expected rule"); } }; diff --git a/include/anthem/Term.h b/include/anthem/Term.h index f92e245..f82aecf 100644 --- a/include/anthem/Term.h +++ b/include/anthem/Term.h @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -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 visit(const Clingo::Symbol &symbol, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack) + std::experimental::optional 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 visit(const Clingo::AST::Variable &variable, const Clingo::AST::Term &, Context &, RuleContext &ruleContext, const ast::VariableStack &variableStack) + std::experimental::optional 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(ruleContext.freeVariables.back().get()); } - std::experimental::optional visit(const Clingo::AST::UnaryOperation &, const Clingo::AST::Term &term, Context &context, RuleContext &, const ast::VariableStack &) + std::experimental::optional 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 visit(const Clingo::AST::BinaryOperation &binaryOperation, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack) + std::experimental::optional 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(operator_, std::move(left), std::move(right)); } - std::experimental::optional visit(const Clingo::AST::Interval &interval, const Clingo::AST::Term &, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack) + std::experimental::optional 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(std::move(left), std::move(right)); } - std::experimental::optional visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack) + std::experimental::optional 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 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(function.name, std::move(arguments)); } - std::experimental::optional visit(const Clingo::AST::Pool &, const Clingo::AST::Term &term, Context &context, RuleContext &, const ast::VariableStack &) + std::experimental::optional 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()); } diff --git a/include/anthem/Utils.h b/include/anthem/Utils.h index f6f8fdf..439cfd8 100644 --- a/include/anthem/Utils.h +++ b/include/anthem/Utils.h @@ -6,7 +6,7 @@ #include #include -#include +#include namespace anthem { @@ -17,34 +17,6 @@ namespace anthem // //////////////////////////////////////////////////////////////////////////////////////////////////// -template -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(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); diff --git a/include/anthem/output/Logger.h b/include/anthem/output/Logger.h index 0d9f2ec..0783da0 100644 --- a/include/anthem/output/Logger.h +++ b/include/anthem/output/Logger.h @@ -3,7 +3,7 @@ #include -#include +#include #include #include #include @@ -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; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9b34e74..f7413fb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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} ) diff --git a/src/anthem/output/Logger.cpp b/src/anthem/output/Logger.cpp index 8f8fb83..504534c 100644 --- a/src/anthem/output/Logger.cpp +++ b/src/anthem/output/Logger.cpp @@ -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(priority); diff --git a/tests/TestCompletion.cpp b/tests/TestCompletion.cpp index 165b7d9..3052198 100644 --- a/tests/TestCompletion.cpp +++ b/tests/TestCompletion.cpp @@ -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;