From 018559b8cf00feecbe0d6ed1c2a0c13eaa59080a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Thu, 24 Nov 2016 02:42:32 +0100 Subject: [PATCH] Started implementing color output (currently for head only). --- app/main.cpp | 7 +- include/anthem/Head.h | 1 + include/anthem/StatementVisitor.h | 19 +- include/anthem/Translation.h | 6 +- include/anthem/output/ClingoOutput.h | 35 +++ include/anthem/output/Formatting.h | 113 +++++-- src/anthem/Translation.cpp | 14 +- src/anthem/output/ClingoOutput.cpp | 449 +++++++++++++++++++++++++++ 8 files changed, 603 insertions(+), 41 deletions(-) create mode 100644 include/anthem/output/ClingoOutput.h create mode 100644 src/anthem/output/ClingoOutput.cpp diff --git a/app/main.cpp b/app/main.cpp index 74c88ab..5895926 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -2,6 +2,7 @@ #include +#include #include int main(int argc, char **argv) @@ -28,6 +29,8 @@ int main(int argc, char **argv) std::cout << description; }; + anthem::Context context; + try { po::store(po::command_line_parser(argc, argv) @@ -61,10 +64,10 @@ int main(int argc, char **argv) if (variablesMap.count("input")) { const auto &inputFiles = variablesMap["input"].as>(); - anthem::translate(inputFiles); + anthem::translate(inputFiles, context); } else - anthem::translate("std::cin", std::cin); + anthem::translate("std::cin", std::cin, context); } catch (const std::exception &e) { diff --git a/include/anthem/Head.h b/include/anthem/Head.h index b4f09b2..6d3a295 100644 --- a/include/anthem/Head.h +++ b/include/anthem/Head.h @@ -4,6 +4,7 @@ #include #include +#include namespace anthem { diff --git a/include/anthem/StatementVisitor.h b/include/anthem/StatementVisitor.h index 0567e98..dc40e1f 100644 --- a/include/anthem/StatementVisitor.h +++ b/include/anthem/StatementVisitor.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace anthem { @@ -18,7 +19,7 @@ struct StatementVisitor { void visit(const Clingo::AST::Program &program, const Clingo::AST::Statement &statement, Context &context) { - std::cout << "[program] " << program.name << std::endl; + context.logger.log(output::Priority::Debug, program.name); if (!program.parameters.empty()) throwErrorAtLocation(statement.location, "program parameters currently unsupported", context); @@ -26,6 +27,8 @@ struct StatementVisitor void visit(const Clingo::AST::Rule &rule, const Clingo::AST::Statement &, Context &context) { + auto &outputStream = context.logger.outputStream(); + // Concatenate all head terms rule.head.data.accept(HeadLiteralCollectFunctionTermsVisitor(), rule.head, context); @@ -37,16 +40,18 @@ struct StatementVisitor const auto &headTerm = **i; if (i != context.headTerms.cbegin()) - std::cout << ", "; + outputStream << ", "; - std::cout - << AuxiliaryHeadVariablePrefix << (i - context.headTerms.cbegin()) - << " in " << headTerm; + const auto variableName = std::string(AuxiliaryBodyVariablePrefix) + std::to_string(i - context.headTerms.cbegin()); + + outputStream + << output::Variable(variableName.c_str()) + << " " << output::Keyword("in") << " " << headTerm; } } if (rule.body.empty() && context.headTerms.empty()) - std::cout << "true"; + outputStream << output::Boolean("true"); else { // Print translated body literals @@ -64,7 +69,7 @@ struct StatementVisitor } } - std::cout << " -> "; + outputStream << " " << output::Operator("->") << " "; // Print consequent of the implication rule.head.data.accept(HeadLiteralPrintSubstitutedVisitor(), rule.head, context); diff --git a/include/anthem/Translation.h b/include/anthem/Translation.h index e2c2ad9..d72f01d 100644 --- a/include/anthem/Translation.h +++ b/include/anthem/Translation.h @@ -4,6 +4,8 @@ #include #include +#include + namespace anthem { @@ -13,8 +15,8 @@ namespace anthem // //////////////////////////////////////////////////////////////////////////////////////////////////// -void translate(const std::vector &fileNames); -void translate(const char *fileName, std::istream &stream); +void translate(const std::vector &fileNames, Context &context); +void translate(const char *fileName, std::istream &stream, Context &context); //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/include/anthem/output/ClingoOutput.h b/include/anthem/output/ClingoOutput.h new file mode 100644 index 0000000..ff0d859 --- /dev/null +++ b/include/anthem/output/ClingoOutput.h @@ -0,0 +1,35 @@ +#ifndef __ANTHEM__OUTPUT__CLINGO_OUTPUT_H +#define __ANTHEM__OUTPUT__CLINGO_OUTPUT_H + +#include + +#include + +namespace anthem +{ +namespace output +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// ClingoOutput +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ColorStream &operator<<(ColorStream &stream, const Clingo::Symbol &symbol); +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::Sign &sign); +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::Variable &variable); +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::BinaryOperator &binaryOperator); +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::UnaryOperation &unaryOperation); +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::BinaryOperation &binaryOperation); +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::Interval &interval); +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::Function &function); +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::Pool &pool); +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::Term &term); + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} + +#endif diff --git a/include/anthem/output/Formatting.h b/include/anthem/output/Formatting.h index 86938d6..9059017 100644 --- a/include/anthem/output/Formatting.h +++ b/include/anthem/output/Formatting.h @@ -84,19 +84,18 @@ inline ColorStream &operator<<(ColorStream &stream, const ResetFormat &) //////////////////////////////////////////////////////////////////////////////////////////////////// -struct Token +struct Function { + Function(const char *name) + : name{name} + { + }; + const char *name; }; //////////////////////////////////////////////////////////////////////////////////////////////////// -struct Function: public Token -{ -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - inline ColorStream &operator<<(ColorStream &stream, const Function &function) { return (stream @@ -107,8 +106,14 @@ inline ColorStream &operator<<(ColorStream &stream, const Function &function) //////////////////////////////////////////////////////////////////////////////////////////////////// -struct Keyword: public Token +struct Keyword { + Keyword(const char *name) + : name{name} + { + }; + + const char *name; }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -116,30 +121,64 @@ struct Keyword: public Token inline ColorStream &operator<<(ColorStream &stream, const Keyword &keyword) { return (stream - << Format({Color::Blue, FontWeight::Normal}) + << Format({Color::Blue, FontWeight::Bold}) << keyword.name << ResetFormat()); } + //////////////////////////////////////////////////////////////////////////////////////////////////// -struct Number: public Token +struct Operator { + Operator(const char *name) + : name{name} + { + }; + + const char *name; }; //////////////////////////////////////////////////////////////////////////////////////////////////// -inline ColorStream &operator<<(ColorStream &stream, const Number &number) +inline ColorStream &operator<<(ColorStream &stream, const Operator &operator_) +{ + return (stream << operator_.name); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +struct Number +{ + Number(T value) + : value{value} + { + }; + + T value; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +inline ColorStream &operator<<(ColorStream &stream, const Number &number) { return (stream << Format({Color::Yellow, FontWeight::Normal}) - << number.name + << number.value << ResetFormat()); } //////////////////////////////////////////////////////////////////////////////////////////////////// -struct Variable: public Token +struct Variable { + Variable(const char *name) + : name{name} + { + }; + + const char *name; }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -154,8 +193,14 @@ inline ColorStream &operator<<(ColorStream &stream, const Variable &variable) //////////////////////////////////////////////////////////////////////////////////////////////////// -struct String: public Token +struct String { + String(const char *content) + : content{content} + { + }; + + const char *content; }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -164,14 +209,20 @@ inline ColorStream &operator<<(ColorStream &stream, const String &string) { return (stream << Format({Color::Green, FontWeight::Normal}) - << "\"" << string.name << "\"" + << "\"" << string.content << "\"" << ResetFormat()); } //////////////////////////////////////////////////////////////////////////////////////////////////// -struct Boolean: public Token +struct Boolean { + Boolean(bool value) + : value{value} + { + }; + + bool value; }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -180,14 +231,20 @@ inline ColorStream &operator<<(ColorStream &stream, const Boolean &boolean) { return (stream << Format({Color::Red, FontWeight::Normal}) - << boolean.name + << (boolean.value == true ? "true" : "false") << ResetFormat()); } //////////////////////////////////////////////////////////////////////////////////////////////////// -struct Reserved: public Token +struct Reserved { + Reserved(const char *name) + : name{name} + { + }; + + const char *name; }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -202,8 +259,14 @@ inline ColorStream &operator<<(ColorStream &stream, const Reserved &reserved) //////////////////////////////////////////////////////////////////////////////////////////////////// -struct Heading1: public Token +struct Heading1 { + Heading1(const char *content) + : content{content} + { + }; + + const char *content; }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -213,7 +276,7 @@ inline ColorStream &operator<<(ColorStream &stream, const Heading1 &heading1) return (stream << Format({Color::Blue, FontWeight::Bold}) << "%---------------------------------------" << std::endl - << "% " << heading1.name << std::endl + << "% " << heading1.content << std::endl << "%---------------------------------------" << ResetFormat() << std::endl); @@ -221,8 +284,14 @@ inline ColorStream &operator<<(ColorStream &stream, const Heading1 &heading1) //////////////////////////////////////////////////////////////////////////////////////////////////// -struct Heading2: public Token +struct Heading2 { + Heading2(const char *content) + : content{content} + { + }; + + const char *content; }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -231,7 +300,7 @@ inline ColorStream &operator<<(ColorStream &stream, const Heading2 &heading2) { return (stream << Format({Color::Blue, FontWeight::Bold}) - << "% " << heading2.name + << "% " << heading2.content << ResetFormat()); } diff --git a/src/anthem/Translation.cpp b/src/anthem/Translation.cpp index 99a68cb..87b8cb6 100644 --- a/src/anthem/Translation.cpp +++ b/src/anthem/Translation.cpp @@ -18,37 +18,35 @@ namespace anthem // //////////////////////////////////////////////////////////////////////////////////////////////////// -void translate(const std::vector &fileNames) +void translate(const std::vector &fileNames, Context &context) { for (const auto &fileName : fileNames) { std::ifstream file(fileName, std::ios::in); - translate(fileName.c_str(), file); + translate(fileName.c_str(), file, context); } } //////////////////////////////////////////////////////////////////////////////////////////////////// -void translate(const char *fileName, std::istream &stream) +void translate(const char *fileName, std::istream &stream, Context &context) { std::cout << "info: reading " << fileName << std::endl; auto fileContent = std::string(std::istreambuf_iterator(stream), {}); - Context context; - const auto translateStatement = [&context](const Clingo::AST::Statement &statement) { statement.data.accept(StatementVisitor(), statement, context); - std::cout << std::endl; + context.logger.outputStream() << std::endl; }; const auto logger = - [](const auto warningCode, const auto *text) + [&context](const Clingo::WarningCode warningCode, const char *text) { - std::cout << "warning: " << text << std::endl; + context.logger.log(output::Priority::Error, text); }; Clingo::parse_program(fileContent.c_str(), translateStatement, logger); diff --git a/src/anthem/output/ClingoOutput.cpp b/src/anthem/output/ClingoOutput.cpp new file mode 100644 index 0000000..5efe8eb --- /dev/null +++ b/src/anthem/output/ClingoOutput.cpp @@ -0,0 +1,449 @@ +#include + +#include + +namespace anthem +{ +namespace output +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// ClingoOutput +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +const auto printCollection = [](auto &stream, const auto &collection, + const auto &preToken, const auto &delimiter, const auto &postToken, bool printTokensIfEmpty) +{ + if (collection.empty() && !printTokensIfEmpty) + return; + + if (collection.empty() && printTokensIfEmpty) + { + stream << preToken << postToken; + return; + } + + stream << preToken; + + // TODO: use cbegin/cend (requires support by Clingo::SymbolSpan) + for (auto i = collection.begin(); i != collection.end(); i++) + { + if (i != collection.begin()) + stream << delimiter; + + stream << *i; + } + + stream << postToken; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ColorStream &operator<<(ColorStream &stream, const Clingo::Symbol &symbol) +{ + switch (symbol.type()) + { + case Clingo::SymbolType::Infimum: + return (stream << Keyword("#inf")); + case Clingo::SymbolType::Supremum: + return (stream << Keyword("sup")); + case Clingo::SymbolType::Number: + return (stream << Number(symbol.number())); + case Clingo::SymbolType::String: + return (stream << String(symbol.string())); + case Clingo::SymbolType::Function: + { + const auto isNegative = symbol.is_negative(); + assert(isNegative != symbol.is_positive()); + + const auto isUnaryTuple = (symbol.name()[0] == '\0' && symbol.arguments().size() == 1); + const auto printIfEmpty = (symbol.name()[0] == '\0' || !symbol.arguments().empty()); + + if (isNegative) + stream << Operator("-"); + + stream << Function(symbol.name()); + + const auto postToken = (isUnaryTuple ? ",)" : ")"); + + printCollection(stream, symbol.arguments(), "(", ", ", postToken, printIfEmpty); + + return stream; + } + } + + return stream; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::Sign &sign) +{ + switch (sign) + { + case Clingo::AST::Sign::None: + return stream; + case Clingo::AST::Sign::Negation: + return (stream << Keyword("not") << " "); + case Clingo::AST::Sign::DoubleNegation: + return (stream << Keyword("not") << " " << Keyword("not") << " "); + } + + return stream; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::Variable &variable) +{ + return (stream << Variable(variable.name)); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::BinaryOperator &binaryOperator) +{ + switch (binaryOperator) + { + case Clingo::AST::BinaryOperator::XOr: + return (stream << Operator("xor")); + case Clingo::AST::BinaryOperator::Or: + return (stream << Operator("or")); + case Clingo::AST::BinaryOperator::And: + return (stream << Operator("and")); + case Clingo::AST::BinaryOperator::Plus: + return (stream << Operator("+")); + case Clingo::AST::BinaryOperator::Minus: + return (stream << Operator("-")); + case Clingo::AST::BinaryOperator::Multiplication: + return (stream << Operator("*")); + case Clingo::AST::BinaryOperator::Division: + return (stream << Operator("/")); + case Clingo::AST::BinaryOperator::Modulo: + return (stream << Operator("\\")); + } + + return stream; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::UnaryOperation &unaryOperation) +{ + return (stream + << Keyword(Clingo::AST::left_hand_side(unaryOperation.unary_operator)) + << unaryOperation.argument + << Keyword(Clingo::AST::right_hand_side(unaryOperation.unary_operator))); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::BinaryOperation &binaryOperation) +{ + return (stream << "(" << binaryOperation.left + << " " << binaryOperation.binary_operator + << " " << binaryOperation.right << ")"); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::Interval &interval) +{ + return (stream << "(" << interval.left << Operator("..") << interval.right << ")"); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::Function &function) +{ + const auto isUnaryTuple = (function.name[0] == '\0' && function.arguments.size() == 1); + const auto printIfEmpty = (function.name[0] == '\0' || !function.arguments.empty()); + + if (function.external) + stream << Operator("@"); + + const auto postToken = (isUnaryTuple ? ",)" : ")"); + + printCollection(stream, function.arguments, "(", ", ", postToken, printIfEmpty); + + return stream; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::Pool &pool) +{ + // Note: There is no representation for an empty pool + if (pool.arguments.empty()) + return (stream << "(1/0)"); + + printCollection(stream, pool.arguments, "(", ";", ")", true); + + return stream; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct TermOutputVisitor +{ + void visit(const Clingo::Symbol &symbol, ColorStream &stream) + { + stream << symbol; + } + + void visit(const Clingo::AST::Variable &variable, ColorStream &stream) + { + stream << variable; + } + + void visit(const Clingo::AST::UnaryOperation &unaryOperation, ColorStream &stream) + { + stream << unaryOperation; + } + + void visit(const Clingo::AST::BinaryOperation &binaryOperation, ColorStream &stream) + { + stream << binaryOperation; + } + + void visit(const Clingo::AST::Interval &interval, ColorStream &stream) + { + stream << interval; + } + + void visit(const Clingo::AST::Function &function, ColorStream &stream) + { + stream << function; + } + + void visit(const Clingo::AST::Pool &pool, ColorStream &stream) + { + stream << pool; + } +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ColorStream &operator<<(ColorStream &stream, const Clingo::AST::Term &term) +{ + term.data.accept(TermOutputVisitor(), stream); + + return stream; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + +/* +inline std::ostream &operator<<(std::ostream &out, Disjunction const &x) { + out << Detail::print(x.elements, "", "; ", "", false); + return out; +} + +inline std::ostream &operator<<(std::ostream &out, HeadAggregate const &x) { + if (x.left_guard) { out << x.left_guard->term << " " << x.left_guard->comparison << " "; } + out << x.function << " { " << Detail::print(x.elements, "", "; ", "", false) << " }"; + if (x.right_guard) { out << " " << x.right_guard->comparison << " " << x.right_guard->term; } + return out; +} + +inline std::ostream &operator<<(std::ostream &out, HeadAggregateElement const &x) { + out << Detail::print(x.tuple, "", ",", "", false) << " : " << x.condition; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, BodyAggregate const &x) { + if (x.left_guard) { out << x.left_guard->term << " " << x.left_guard->comparison << " "; } + out << x.function << " { " << Detail::print(x.elements, "", "; ", "", false) << " }"; + if (x.right_guard) { out << " " << x.right_guard->comparison << " " << x.right_guard->term; } + return out; +} + +inline std::ostream &operator<<(std::ostream &out, BodyAggregateElement const &x) { + out << Detail::print(x.tuple, "", ",", "", false) << " : " << Detail::print(x.condition, "", ", ", "", false); + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Aggregate const &x) { + if (x.left_guard) { out << x.left_guard->term << " " << x.left_guard->comparison << " "; } + out << "{ " << Detail::print(x.elements, "", "; ", "", false) << " }"; + if (x.right_guard) { out << " " << x.right_guard->comparison << " " << x.right_guard->term; } + return out; +} + +inline std::ostream &operator<<(std::ostream &out, ConditionalLiteral const &x) { + out << x.literal << Detail::print(x.condition, " : ", ", ", "", true); + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Literal const &x) { + out << x.sign << x.data; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Boolean const &x) { + out << (x.value ? "#true" : "#false"); + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Comparison const &x) { + out << x.left << x.comparison << x.right; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Id const &x) { + out << x.id; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, CSPLiteral const &x) { + out << x.term; + for (auto &y : x.guards) { out << y; } + return out; +} + +inline std::ostream &operator<<(std::ostream &out, CSPGuard const &x) { + out << "$" << x.comparison << x.term; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, CSPSum const &x) { + if (x.terms.empty()) { out << "0"; } + else { out << Detail::print(x.terms, "", "$+", "", false); } + return out; +} + +inline std::ostream &operator<<(std::ostream &out, CSPProduct const &x) { + if (x.variable) { out << x.coefficient << "$*$" << *x.variable.get(); } + else { out << x.coefficient; } + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Pool const &x) { + // NOTE: there is no representation for an empty pool + if (x.arguments.empty()) { out << "(1/0)"; } + else { out << Detail::print(x.arguments, "(", ";", ")", true); } + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Function const &x) { + bool tc = x.name[0] == '\0' && x.arguments.size() == 1; + bool ey = x.name[0] == '\0' || !x.arguments.empty(); + out << (x.external ? "@" : "") << x.name << Detail::print(x.arguments, "(", ",", tc ? ",)" : ")", ey); + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Interval const &x) { + out << "(" << x.left << ".." << x.right << ")"; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, BinaryOperation const &x) { + out << "(" << x.left << x.binary_operator << x.right << ")"; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, UnaryOperation const &x) { + out << left_hand_side(x.unary_operator) << x.argument << right_hand_side(x.unary_operator); + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Variable const &x) { + out << x.name; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Term const &x) { + out << x.data; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Rule const &x) { + out << x.head << Detail::print_body(x.body, " :- "); + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Definition const &x) { + out << "#const " << x.name << " = " << x.value << "."; + if (x.is_default) { out << " [default]"; } + return out; +} + +inline std::ostream &operator<<(std::ostream &out, ShowSignature const &x) { + out << "#show " << (x.csp ? "$" : "") << x.signature << "."; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, ShowTerm const &x) { + out << "#show " << (x.csp ? "$" : "") << x.term << Detail::print_body(x.body); + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Minimize const &x) { + out << Detail::print_body(x.body, ":~ ") << " [" << x.weight << "@" << x.priority << Detail::print(x.tuple, ",", ",", "", false) << "]"; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Script const &x) { + std::string s = x.code; + if (!s.empty() && s.back() == '\n') { + s.back() = '.'; + } + out << s; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Program const &x) { + out << "#program " << x.name << Detail::print(x.parameters, "(", ",", ")", false) << "."; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, External const &x) { + out << "#external " << x.atom << Detail::print_body(x.body); + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Edge const &x) { + out << "#edge (" << x.u << "," << x.v << ")" << Detail::print_body(x.body); + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Heuristic const &x) { + out << "#heuristic " << x.atom << Detail::print_body(x.body) << " [" << x.bias<< "@" << x.priority << "," << x.modifier << "]"; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, ProjectAtom const &x) { + out << "#project " << x.atom << Detail::print_body(x.body); + return out; +} + +inline std::ostream &operator<<(std::ostream &out, ProjectSignature const &x) { + out << "#project " << x.signature << "."; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, Statement const &x) { + out << x.data; + return out; +} +*/ + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +}