diff --git a/potassco/aspif_text.h b/potassco/aspif_text.h index e19844a..25437a3 100644 --- a/potassco/aspif_text.h +++ b/potassco/aspif_text.h @@ -101,6 +101,7 @@ class AspifTextOutput : public Potassco::AbstractProgram { private: std::ostream& printName(std::ostream& os, Lit_t lit); + std::ostream& printHide(std::ostream& os); void writeDirectives(); void visitTheories(); bool assignAtomName(Atom_t id, const std::string& name); @@ -116,7 +117,7 @@ class AspifTextOutput : public Potassco::AbstractProgram { TheoryData theory_; Data* data_; int step_; - int showAtoms_; + bool showAtoms_; Atom_t startAtom_; Atom_t maxAtom_; }; diff --git a/src/aspif_text.cpp b/src/aspif_text.cpp index d75b44d..c0c0f82 100644 --- a/src/aspif_text.cpp +++ b/src/aspif_text.cpp @@ -403,16 +403,25 @@ std::ostream& AspifTextOutput::printName(std::ostream& os, Lit_t lit) { } else { os << "x_" << id; - if (showAtoms_ == 0) { - showAtoms_ = 1; + if (!showAtoms_) { + showAtoms_ = true; + if (data_->atoms.empty()) { data_->atoms.push_back(0); } + data_->setGenName(0); } } maxAtom_ = std::max(maxAtom_, id); return os; } +std::ostream& AspifTextOutput::printHide(std::ostream& os) { + if (data_->genName && data_->atoms[0] == data_->genName) { + data_->atoms[0] = 0; + os << "#show.\n"; + } + return os; +} void AspifTextOutput::initProgram(bool incremental) { step_ = incremental ? 0 : -1; - showAtoms_ = 0; + showAtoms_ = false; startAtom_ = 0; maxAtom_ = 0; data_->reset(); @@ -422,6 +431,7 @@ void AspifTextOutput::beginStep() { if (step_) { os_ << "% #program step(" << step_ << ").\n"; theory_.update(); } else { os_ << "% #program base.\n"; } ++step_; + startAtom_ = data_->atoms.size(); } } void AspifTextOutput::rule(Head_t ht, const AtomSpan& head, const LitSpan& body) { @@ -577,6 +587,7 @@ void AspifTextOutput::writeDirectives() { for (uint32_t n = get(); n--; sep = ", ") { printName(os_ << sep, get()); } break; case Directive_t::Output: + printHide(os_); sep = " : "; term = "."; os_ << "#show " << data_->out[get()]->first; for (uint32_t n = get(); n--; sep = ", ") { @@ -618,10 +629,7 @@ void AspifTextOutput::writeDirectives() { os_ << term << "\n"; } if (showAtoms_) { - if (showAtoms_ == 1) { - os_ << "#show.\n"; - showAtoms_ = 2; - } + printHide(os_); for (Atom_t a = startAtom_; a < data_->atoms.size(); ++a) { if (const std::string* n = data_->getAtomName(a)) { if (*n->c_str() != '&') { @@ -629,7 +637,6 @@ void AspifTextOutput::writeDirectives() { } } } - startAtom_ = data_->atoms.size(); } os_ << std::flush; } diff --git a/tests/test_text.cpp b/tests/test_text.cpp index a6c403c..508c085 100644 --- a/tests/test_text.cpp +++ b/tests/test_text.cpp @@ -243,7 +243,7 @@ TEST_CASE("Text writer ", "[text]") { out.output(toSpan("-a"), toSpan(&cond1, 1)); out.output(toSpan("x_1"), toSpan(&cond2, 1)); out.endStep(); - REQUIRE(output.str() == "{-a;x_2}.\n#show x_1 : x_2.\n#show.\n#show -a : -a.\n"); + REQUIRE(output.str() == "{-a;x_2}.\n#show.\n#show x_1 : x_2.\n#show -a : -a.\n"); } SECTION("basic rule") { input << "x1 :- x2, not x3, x4.\n#output foo : x1.\n#output bar : x3."; @@ -288,13 +288,13 @@ TEST_CASE("Text writer ", "[text]") { SECTION("output statements") { input << "{x1;x2}.\n#output foo.\n#output bar : x1.\n#output \"Hello World\" : x2, not x1."; read(prg, input); - REQUIRE(output.str() == "{bar;x_2}.\n#show foo.\n#show \"Hello World\" : x_2, not bar.\n#show.\n" + REQUIRE(output.str() == "{bar;x_2}.\n#show.\n#show foo.\n#show \"Hello World\" : x_2, not bar.\n" "#show bar : bar.\n"); } SECTION("duplicate output condition") { input << "{a}.\n#output x:a.\n#output y:a.\n"; read(prg, input); - REQUIRE(output.str() == "{x_1}.\n#show x : x_1.\n#show y : x_1.\n#show.\n"); + REQUIRE(output.str() == "{x_1}.\n#show.\n#show x : x_1.\n#show y : x_1.\n"); } SECTION("bogus duplicate output condition") { input << "{a}.\n#output x:a.\n#output x:a.\n"; @@ -306,27 +306,27 @@ TEST_CASE("Text writer ", "[text]") { SECTION("simple") { input << "#output a:x1.\n#output a:x2.\n"; read(prg, input); - REQUIRE(output.str() == "{x_1;x_2}.\n#show a : x_1.\n#show a : x_2.\n#show.\n"); + REQUIRE(output.str() == "{x_1;x_2}.\n#show.\n#show a : x_1.\n#show a : x_2.\n"); } SECTION("complex") { input << "#output a:x1.\n#output a:x1,x2.\n"; read(prg, input); - REQUIRE(output.str() == "{a;x_2}.\n#show a : a, x_2.\n#show.\n#show a : a.\n"); + REQUIRE(output.str() == "{a;x_2}.\n#show.\n#show a : a, x_2.\n#show a : a.\n"); } SECTION("complex reversed") { input << "#output a:x1,x2.\n#output a:x1.\n"; read(prg, input); - REQUIRE(output.str() == "{a;x_2}.\n#show a : a, x_2.\n#show.\n#show a : a.\n"); + REQUIRE(output.str() == "{a;x_2}.\n#show.\n#show a : a, x_2.\n#show a : a.\n"); } SECTION("duplicate condition first") { input << "#output a:x1.\n#output b:x1.\n#output a:x2.\n"; read(prg, input); - REQUIRE(output.str() == "{x_1;x_2}.\n#show a : x_1.\n#show b : x_1.\n#show a : x_2.\n#show.\n"); + REQUIRE(output.str() == "{x_1;x_2}.\n#show.\n#show a : x_1.\n#show b : x_1.\n#show a : x_2.\n"); } SECTION("duplicate condition all") { input << "#output a:x1.\n#output b:x1.\n#output a:x2.\n#output f:x2.\n"; read(prg, input); - REQUIRE(output.str() == "{x_1;x_2}.\n#show a : x_1.\n#show b : x_1.\n#show a : x_2.\n#show f : x_2.\n#show.\n"); + REQUIRE(output.str() == "{x_1;x_2}.\n#show.\n#show a : x_1.\n#show b : x_1.\n#show a : x_2.\n#show f : x_2.\n"); } } SECTION("implicit show") { @@ -348,17 +348,17 @@ TEST_CASE("Text writer ", "[text]") { SECTION("duplicate one") { input << "#output a:b.\n#output b:b.\n"; read(prg, input); - REQUIRE(output.str() == "{x_1;x_2}.\n#show a : x_2.\n#show b : x_2.\n#show.\n"); + REQUIRE(output.str() == "{x_1;x_2}.\n#show.\n#show a : x_2.\n#show b : x_2.\n"); } SECTION("duplicate two") { input << "#output b:b.\n#output a:b.\n"; read(prg, input); - REQUIRE(output.str() == "{x_1;x_2}.\n#show b : x_2.\n#show a : x_2.\n#show.\n"); + REQUIRE(output.str() == "{x_1;x_2}.\n#show.\n#show b : x_2.\n#show a : x_2.\n"); } SECTION("duplicate three") { input << "#output a:a.\n#output b:b.\n#output c:b.\n"; read(prg, input); - REQUIRE(output.str() == "{a;x_2}.\n#show b : x_2.\n#show c : x_2.\n#show.\n#show a : a.\n"); + REQUIRE(output.str() == "{a;x_2}.\n#show.\n#show b : x_2.\n#show c : x_2.\n#show a : a.\n"); } } SECTION("output reserved name") { @@ -367,24 +367,24 @@ TEST_CASE("Text writer ", "[text]") { SECTION("match") { input << "#output x_2:b.\n#output x_1:a."; read(prg, input); - REQUIRE(output.str() == "{x_1;x_2}.\n#show x_2 : x_2.\n#show x_1 : x_1.\n#show.\n"); + REQUIRE(output.str() == "{x_1;x_2}.\n#show.\n#show x_2 : x_2.\n#show x_1 : x_1.\n"); } SECTION("mismatch") { input << "#output x_2:a.\n#output x_1:b."; read(prg, input); - REQUIRE(output.str() == "{x_1;x_2}.\n#show x_2 : x_1.\n#show x_1 : x_2.\n#show.\n"); + REQUIRE(output.str() == "{x_1;x_2}.\n#show.\n#show x_2 : x_1.\n#show x_1 : x_2.\n"); } } SECTION("some") { SECTION("match") { input << "#output x_2:b."; read(prg, input); - REQUIRE(output.str() == "{x_1;x_2}.\n#show x_2 : x_2.\n#show.\n"); + REQUIRE(output.str() == "{x_1;x_2}.\n#show.\n#show x_2 : x_2.\n"); } SECTION("mismatch") { input << "#output x_2:a."; read(prg, input); - REQUIRE(output.str() == "{x_1;x_2}.\n#show x_2 : x_1.\n#show.\n"); + REQUIRE(output.str() == "{x_1;x_2}.\n#show.\n#show x_2 : x_1.\n"); } } SECTION("incremental handled as some") { @@ -398,9 +398,9 @@ TEST_CASE("Text writer ", "[text]") { out.endStep(); REQUIRE(output.str() == "% #program base.\n" "{x_1;x_2}.\n" + "#show.\n" "#show x_3 : x_1.\n" - "#show x_2 : x_2.\n" - "#show.\n"); + "#show x_2 : x_2.\n"); output.str(""); out.beginStep(); out.rule(Head_t::Choice, toSpan(head = {3}), toSpan(cond = {1, 2})); // {3} :- 1, 2. @@ -419,12 +419,12 @@ TEST_CASE("Text writer ", "[text]") { out.output(toSpan("a"), toSpan(&al, 1)); // #show a : x_1. SECTION("unique alternative") { out.endStep(); - REQUIRE(output.str() == "{x_1}.\n#show x_1 : x_1.\n#show a : x_1.\n#show.\n"); + REQUIRE(output.str() == "{x_1}.\n#show.\n#show x_1 : x_1.\n#show a : x_1.\n"); } SECTION("two alternatives") { out.output(toSpan("b"), toSpan(&al, 1)); // #show b : x_1. out.endStep(); - REQUIRE(output.str() == "{x_1}.\n#show x_1 : x_1.\n#show a : x_1.\n#show b : x_1.\n#show.\n"); + REQUIRE(output.str() == "{x_1}.\n#show.\n#show x_1 : x_1.\n#show a : x_1.\n#show b : x_1.\n"); } } SECTION("write external - ") { @@ -632,16 +632,15 @@ TEST_CASE("Text writer writes theory", "[text]") { // Ensure that we don't use "foo" for x_3. REQUIRE(output.str() == "{x_1;x_2}.\n" "x_4 :- &atom{elem : x_1, not x_2; p : x_1}.\n" - "#show foo : &atom{elem : x_1, not x_2; p : x_1}.\n#show.\n"); + "#show.\n#show foo : &atom{elem : x_1, not x_2; p : x_1}.\n"); } SECTION("twice") { out.output(Potassco::toSpan("bar"), Potassco::toSpan((body = {3}))); out.endStep(); REQUIRE(output.str() == "{x_1;x_2}.\n" "x_4 :- &atom{elem : x_1, not x_2; p : x_1}.\n" - "#show foo : &atom{elem : x_1, not x_2; p : x_1}.\n" - "#show bar : &atom{elem : x_1, not x_2; p : x_1}.\n" - "#show.\n"); + "#show.\n#show foo : &atom{elem : x_1, not x_2; p : x_1}.\n" + "#show bar : &atom{elem : x_1, not x_2; p : x_1}.\n"); } } }