dlvhex  2.5.0
src/HigherOrderPlugin.cpp
Go to the documentation of this file.
00001 /* dlvhex -- Answer-Set Programming with external interfaces.
00002  * Copyright (C) 2005-2007 Roman Schindlauer
00003  * Copyright (C) 2006-2015 Thomas Krennwallner
00004  * Copyright (C) 2009-2016 Peter Schüller
00005  * Copyright (C) 2011-2016 Christoph Redl
00006  * Copyright (C) 2015-2016 Tobias Kaminski
00007  * Copyright (C) 2015-2016 Antonius Weinzierl
00008  *
00009  * This file is part of dlvhex.
00010  *
00011  * dlvhex is free software; you can redistribute it and/or modify it
00012  * under the terms of the GNU Lesser General Public License as
00013  * published by the Free Software Foundation; either version 2.1 of
00014  * the License, or (at your option) any later version.
00015  *
00016  * dlvhex is distributed in the hope that it will be useful, but
00017  * WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  * Lesser General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with dlvhex; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00024  * 02110-1301 USA.
00025  */
00026 
00034 #ifdef HAVE_CONFIG_H
00035 #include "config.h"
00036 #endif                           // HAVE_CONFIG_H
00037 
00038 //#define BOOST_SPIRIT_DEBUG
00039 
00040 #include "dlvhex2/HigherOrderPlugin.h"
00041 #include "dlvhex2/PlatformDefinitions.h"
00042 #include "dlvhex2/ProgramCtx.h"
00043 #include "dlvhex2/Registry.h"
00044 #include "dlvhex2/Printer.h"
00045 #include "dlvhex2/Printhelpers.h"
00046 #include "dlvhex2/PredicateMask.h"
00047 #include "dlvhex2/Logger.h"
00048 #include "dlvhex2/HexParser.h"
00049 #include "dlvhex2/HexParserModule.h"
00050 #include "dlvhex2/HexGrammar.h"
00051 
00052 #include <boost/algorithm/string/predicate.hpp>
00053 #include <boost/lexical_cast.hpp>
00054 
00055 DLVHEX_NAMESPACE_BEGIN
00056 
00057 namespace spirit = boost::spirit;
00058 namespace qi = boost::spirit::qi;
00059 
00060 HigherOrderPlugin::CtxData::CtxData():
00061 enabled(false),
00062 arities()
00063 {
00064 }
00065 
00066 
00067 HigherOrderPlugin::HigherOrderPlugin():
00068 PluginInterface()
00069 {
00070     setNameVersion("dlvhex-higherorderplugin[internal]", 2, 0, 0);
00071 }
00072 
00073 
00074 HigherOrderPlugin::~HigherOrderPlugin()
00075 {
00076 }
00077 
00078 
00079 // output help message for this plugin
00080 void HigherOrderPlugin::printUsage(std::ostream& o) const
00081 {
00082     //    123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-
00083     o << "     --higherorder-enable[=true,false]" << std::endl
00084         << "                      Enable higher order plugin (default is disabled)." << std::endl;
00085 }
00086 
00087 
00088 // accepted options: --higherorder-enable
00089 //
00090 // processes options for this plugin, and removes recognized options from pluginOptions
00091 // (do not free the pointers, the const char* directly come from argv)
00092 void HigherOrderPlugin::processOptions(
00093 std::list<const char*>& pluginOptions,
00094 ProgramCtx& ctx)
00095 {
00096     HigherOrderPlugin::CtxData& ctxdata = ctx.getPluginData<HigherOrderPlugin>();
00097     ctxdata.enabled = false;
00098 
00099     typedef std::list<const char*>::iterator Iterator;
00100     Iterator it;
00101     WARNING("create (or reuse, maybe from potassco?) cmdline option processing facility")
00102         it = pluginOptions.begin();
00103     while( it != pluginOptions.end() ) {
00104         bool processed = false;
00105         const std::string str(*it);
00106         if( boost::starts_with(str, "--higherorder-enable" ) ) {
00107             std::string m = str.substr(std::string("--higherorder-enable").length());
00108             if (m == "" || m == "=true") {
00109                 ctxdata.enabled = true;
00110             }
00111             else if (m == "=false") {
00112                 ctxdata.enabled = false;
00113             }
00114             else {
00115                 std::stringstream ss;
00116                 ss << "Unknown --strongnegation-enable option: " << m;
00117                 throw PluginError(ss.str());
00118             }
00119             processed = true;
00120         }
00121 
00122         if( processed ) {
00123             // return value of erase: element after it, maybe end()
00124             DBGLOG(DBG,"HigherOrderPlugin successfully processed option " << str);
00125             it = pluginOptions.erase(it);
00126         }
00127         else {
00128             it++;
00129         }
00130     }
00131 }
00132 
00133 
00134 class HigherOrderParserModuleSemantics:
00135 public HexGrammarSemantics
00136 {
00137     public:
00138         HigherOrderPlugin::CtxData& ctxdata;
00139 
00140     public:
00141         HigherOrderParserModuleSemantics(ProgramCtx& ctx):
00142         HexGrammarSemantics(ctx),
00143         ctxdata(ctx.getPluginData<HigherOrderPlugin>()) {
00144         }
00145 
00146         // use SemanticActionBase to redirect semantic action call into globally
00147         // specializable sem<T> struct space
00148         struct higherOrderAtom:
00149         SemanticActionBase<HigherOrderParserModuleSemantics, ID, higherOrderAtom>
00150         {
00151             higherOrderAtom(HigherOrderParserModuleSemantics& mgr):
00152             higherOrderAtom::base_type(mgr) {
00153             }
00154         };
00155 };
00156 
00157 // create semantic handler for above semantic action
00158 // (needs to be in globally specializable struct space)
00159 template<>
00160 struct sem<HigherOrderParserModuleSemantics::higherOrderAtom>
00161 {
00162     void operator()(
00163         HigherOrderParserModuleSemantics& mgr,
00164         const boost::fusion::vector2<
00165         std::string,
00166         boost::optional<std::vector<dlvhex::ID> >
00167         >& source,
00168     ID& target) {
00169         RegistryPtr reg = mgr.ctx.registry();
00170 
00171         // predicate
00172         const std::string& spred = boost::fusion::at_c<0>(source);
00173         if( spred == "_" )
00174             throw FatalError("cannot use anonymous variables as predicate in higher order atoms");
00175 
00176         // create ID for variable
00177         assert(!spred.empty() && isupper(spred[0]));
00178         ID idpred = mgr.ctx.registry()->terms.getIDByString(spred);
00179         if( idpred == ID_FAIL ) {
00180             Term term(ID::MAINKIND_TERM | ID::SUBKIND_TERM_VARIABLE, spred);
00181             idpred = mgr.ctx.registry()->terms.storeAndGetID(term);
00182         }
00183 
00184         // create atom
00185         OrdinaryAtom atom(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_ORDINARYN | ID::PROPERTY_AUX);
00186         atom.tuple.push_back(idpred);
00187 
00188         // arguments
00189         if( !!boost::fusion::at_c<1>(source) ) {
00190             const Tuple& tuple = boost::fusion::at_c<1>(source).get();
00191             atom.tuple.insert(atom.tuple.end(), tuple.begin(), tuple.end());
00192         }
00193         const unsigned arity = atom.tuple.size()-1;
00194         mgr.ctxdata.arities.insert(arity);
00195 
00196         // create atom (always nonground)
00197         target = reg->storeOrdinaryNAtom(atom);
00198         DBGLOG(DBG,"stored higher order atom " << atom << " with arity " << arity << " which got id " << target);
00199     }
00200 };
00201 
00202 namespace
00203 {
00204 
00205     template<typename Iterator, typename Skipper>
00206         struct HigherOrderParserModuleGrammarBase:
00207     // we derive from the original hex grammar
00208     // -> we can reuse its rules
00209     public HexGrammarBase<Iterator, Skipper>
00210     {
00211         typedef HexGrammarBase<Iterator, Skipper> Base;
00212 
00213         HigherOrderParserModuleSemantics& sem;
00214 
00215         HigherOrderParserModuleGrammarBase(HigherOrderParserModuleSemantics& sem):
00216         Base(sem),
00217         sem(sem) {
00218             typedef HigherOrderParserModuleSemantics Sem;
00219             higherOrderAtom
00220                 = (
00221                 Base::variable >>
00222                 (qi::lit('(') > -Base::terms >> qi::lit(')')) > qi::eps
00223                 ) [ Sem::higherOrderAtom(sem) ];
00224 
00225             #ifdef BOOST_SPIRIT_DEBUG
00226             BOOST_SPIRIT_DEBUG_NODE(higherOrderAtom);
00227             #endif
00228         }
00229 
00230         qi::rule<Iterator, ID(), Skipper> higherOrderAtom;
00231     };
00232 
00233     struct HigherOrderParserModuleGrammar:
00234     HigherOrderParserModuleGrammarBase<HexParserIterator, HexParserSkipper>,
00235     // required for interface
00236     // note: HexParserModuleGrammar =
00237     //       boost::spirit::qi::grammar<HexParserIterator, HexParserSkipper>
00238         HexParserModuleGrammar
00239     {
00240         typedef HigherOrderParserModuleGrammarBase<HexParserIterator, HexParserSkipper> GrammarBase;
00241         typedef HexParserModuleGrammar QiBase;
00242 
00243         HigherOrderParserModuleGrammar(HigherOrderParserModuleSemantics& sem):
00244         GrammarBase(sem),
00245         QiBase(GrammarBase::higherOrderAtom) {
00246         }
00247     };
00248     typedef boost::shared_ptr<HigherOrderParserModuleGrammar>
00249         HigherOrderParserModuleGrammarPtr;
00250 
00251     // moduletype = HexParserModule::BODYATOM
00252     // moduletype = HexParserModule::HEADATOM
00253     template<enum HexParserModule::Type moduletype>
00254     class HigherOrderParserModule:
00255     public HexParserModule
00256     {
00257         public:
00258             // the semantics manager is stored/owned by this module!
00259             HigherOrderParserModuleSemantics sem;
00260             // we also keep a shared ptr to the grammar module here
00261             HigherOrderParserModuleGrammarPtr grammarModule;
00262 
00263             HigherOrderParserModule(ProgramCtx& ctx):
00264             HexParserModule(moduletype),
00265             sem(ctx) {
00266                 LOG(INFO,"constructed HigherOrderParserModule");
00267             }
00268 
00269             virtual HexParserModuleGrammarPtr createGrammarModule() {
00270                 assert(!grammarModule && "for simplicity (storing only one grammarModule pointer) we currently assume this will be called only once .. should be no problem to extend");
00271                 grammarModule.reset(new HigherOrderParserModuleGrammar(sem));
00272                 LOG(INFO,"created HigherOrderParserModuleGrammar");
00273                 return grammarModule;
00274             }
00275     };
00276 
00277 }                                // anonymous namespace
00278 
00279 
00280 // create parser modules that extend and the basic hex grammar
00281 // this parser also stores the query information into the plugin
00282 std::vector<HexParserModulePtr>
00283 HigherOrderPlugin::createParserModules(ProgramCtx& ctx)
00284 {
00285     DBGLOG(DBG,"HigherOrderPlugin::createParserModules()");
00286     std::vector<HexParserModulePtr> ret;
00287 
00288     HigherOrderPlugin::CtxData& ctxdata = ctx.getPluginData<HigherOrderPlugin>();
00289     if( ctxdata.enabled ) {
00290         ret.push_back(HexParserModulePtr(
00291             new HigherOrderParserModule<HexParserModule::BODYATOM>(ctx)));
00292         ret.push_back(HexParserModulePtr(
00293             new HigherOrderParserModule<HexParserModule::HEADATOM>(ctx)));
00294     }
00295 
00296     return ret;
00297 }
00298 
00299 
00300 namespace
00301 {
00302 
00303     typedef HigherOrderPlugin::CtxData CtxData;
00304 
00305     class HigherOrderRewriter:
00306     public PluginRewriter
00307     {
00308         public:
00309             HigherOrderRewriter() {}
00310             virtual ~HigherOrderRewriter() {}
00311 
00312             virtual void rewrite(ProgramCtx& ctx);
00313     };
00314 
00315     struct AtomRewriter
00316     {
00317         RegistryPtr reg;
00318         HigherOrderPlugin::CtxData& ctxdata;
00319 
00320         AtomRewriter(RegistryPtr reg, HigherOrderPlugin::CtxData& ctxdata):
00321         reg(reg), ctxdata(ctxdata) {
00322         }
00323 
00324         ID rewrite(ID id) {
00325             const OrdinaryAtom& atom = reg->lookupOrdinaryAtom(id);
00326             assert(!atom.tuple.empty());
00327             const unsigned arity = atom.tuple.size()-1;
00328             if( ctxdata.arities.count(arity) > 0 ) {
00329                 DBGLOG(DBG,"found ordinary atom " << atom << " with arity that needs to be rewritten");
00330                 ID idaux = reg->getAuxiliaryConstantSymbol('h', ID(0, arity));
00331                 OrdinaryAtom auxAtom(atom.kind | ID::PROPERTY_AUX);
00332                 auxAtom.tuple.push_back(idaux);
00333                 auxAtom.tuple.insert(auxAtom.tuple.end(), atom.tuple.begin(), atom.tuple.end());
00334                 DBGLOG(DBG,"created ordinary atom " << auxAtom << " which will be stored back");
00335                 ID idAuxAtom;
00336                 if( id.isOrdinaryGroundAtom() )
00337                     idAuxAtom = reg->storeOrdinaryGAtom(auxAtom);
00338                 else
00339                     idAuxAtom = reg->storeOrdinaryNAtom(auxAtom);
00340                 DBGLOG(DBG,"stored auxilary higher order atom " <<
00341                     printToString<RawPrinter>(idAuxAtom, reg) << " with id " << idAuxAtom);
00342                 return idAuxAtom;
00343             }
00344             return id;
00345         }
00346     };
00347 
00348     void HigherOrderRewriter::rewrite(ProgramCtx& ctx) {
00349         DBGLOG_SCOPE(DBG,"HO",false);
00350         DBGLOG(DBG,"= HigherOrderRewriter::rewrite");
00351 
00352         HigherOrderPlugin::CtxData& ctxdata = ctx.getPluginData<HigherOrderPlugin>();
00353         assert(ctxdata.enabled && "this rewriter should only be used "
00354             "if the plugin is enabled");
00355 
00356         RegistryPtr reg = ctx.registry();
00357         assert(reg);
00358 
00359         LOG(INFO,"got the following higher order arities from parser: " << printset(ctxdata.arities));
00360 
00361         // go over all rules and record constants used as predicate inputs
00362         // go over idb and rewrite any ordinary atoms with one of the recorded arities to auxiliary atoms
00363         // go over edb and rewrite any atoms with one of the recorded arities to auxiliary atoms
00364         // create rules to get predicate inputs for all recorded arities from auxiliary atoms
00365 
00366         // go over all rules and record constants used as predicate inputs
00367         BOOST_FOREACH(ID rid, ctx.idb) {
00368             const Rule& rule = reg->rules.getByID(rid);
00369             BOOST_FOREACH(ID lit, rule.body) {
00370                 if( lit.isExternalAtom() ) {
00371                     const ExternalAtom& eatom = reg->eatoms.getByID(lit);
00372                     DBGLOG(DBG,"looking for predicate inputs in eatom " << eatom);
00373                     assert(eatom.pluginAtom != NULL && "higher order plugin requires eatom information for rewriting");
00374                     for(unsigned idx = 0; idx < eatom.inputs.size(); ++idx) {
00375                         if( eatom.pluginAtom->getInputType(idx) == PluginAtom::PREDICATE ) {
00376                             const ID inp = eatom.inputs[idx];
00377                             DBGLOG(DBG,"found predicate input " << inp << " at position " << idx);
00378                             ctxdata.predicateInputConstants.insert(inp);
00379                         }
00380                     }
00381                 }
00382             }
00383         }
00384         LOG(INFO,"found the following predicate inputs: {" << printManyToString<RawPrinter>(
00385             Tuple(ctxdata.predicateInputConstants.begin(), ctxdata.predicateInputConstants.end()),
00386             ",", reg) << "}");
00387         DBGLOG(DBG,"found the following predicate inputs: " <<
00388             printset(ctxdata.predicateInputConstants));
00389 
00390         // go over idb and rewrite any ordinary atoms with one of the recorded arities to auxiliary atoms
00391         std::vector<ID> newIdb;
00392         AtomRewriter rewriter(reg, ctxdata);
00393         BOOST_FOREACH(ID rid, ctx.idb) {
00394             const Rule& rule = reg->rules.getByID(rid);
00395 
00396             // start to build replacement rule
00397             Rule newrule(rule.kind);
00398             bool changedRule = false;
00399 
00400             // process body
00401             BOOST_FOREACH(ID lit, rule.body) {
00402                 if( lit.isOrdinaryAtom() ) {
00403                     ID newid = rewriter.rewrite(lit);
00404                     if( newid != lit ) {
00405                         changedRule = true;
00406                         newrule.body.push_back(ID::literalFromAtom(newid, lit.isNaf()));
00407                     }
00408                     else {
00409                         newrule.body.push_back(lit);
00410                     }
00411                 }
00412                 else if( lit.isAggregateAtom() ) {
00413                     assert(false && "TODO implement aggregate HO rewriting");
00414                 }
00415                 else {
00416                     newrule.body.push_back(lit);
00417                 }
00418             }
00419 
00420             // process head
00421             BOOST_FOREACH(ID id, rule.head) {
00422                 if( id.isOrdinaryAtom() ) {
00423                     ID newid = rewriter.rewrite(id);
00424                     if( newid != id ) {
00425                         changedRule = true;
00426                         newrule.head.push_back(newid);
00427                     }
00428                     else {
00429                         newrule.head.push_back(id);
00430                     }
00431                 }
00432                 else {
00433                     newrule.head.push_back(id);
00434                 }
00435             }
00436 
00437             if( changedRule ) {
00438                 ID newRid = reg->storeRule(newrule);
00439                 newIdb.push_back(newRid);
00440                 LOG(INFO,"stored rule with replaced higher order atoms " <<
00441                     printToString<RawPrinter>(newRid, reg) << " with id " << newRid);
00442             }
00443             else {
00444                 newIdb.push_back(rid);
00445             }
00446         }
00447 
00448         ctx.idb.swap(newIdb);
00449 
00450         // go over edb and rewrite any atoms with one of the recorded arities to auxiliary atoms
00451         assert(!!ctx.edb);
00452         Interpretation::Storage& bits = ctx.edb->getStorage();
00453         for(Interpretation::Storage::enumerator it = bits.first();
00454         it != bits.end(); ++it) {
00455             ID oldid(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_ORDINARYG, *it);
00456             ID newid = rewriter.rewrite(oldid);
00457             if( newid != oldid ) {
00458                 // we do not clear the original facts:
00459                 // if we clear them we may need to derive them again
00460                 // if we clear them --nofact will no longer work
00461                 // TODO think about how to do higher order more efficiently
00462                 //ctx.edb->clearFact(oldid.address);
00463                 ctx.edb->setFact(newid.address);
00464             }
00465         }
00466 
00467         // create rules to get predicate inputs for all recorded arities from auxiliary atoms
00468         WARNING("we could pre-create variables where this line is and simply use them later (more efficient, more complicated)")
00469         BOOST_FOREACH(ID pred, ctxdata.predicateInputConstants) {
00470             // create for each arity
00471             BOOST_FOREACH(unsigned arity, ctxdata.arities) {
00472                 if( arity == 0 ) {
00473                     // ground atoms
00474                     OrdinaryAtom tgt(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_ORDINARYG);
00475                     tgt.tuple.push_back(pred);
00476                     OrdinaryAtom src(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_ORDINARYG | ID::PROPERTY_AUX);
00477                     src.tuple.push_back(reg->getAuxiliaryConstantSymbol('h', ID(0, arity)));
00478 
00479                     // store
00480                     ID idtgt = reg->storeOrdinaryGAtom(tgt);
00481                     ID idsrc = reg->storeOrdinaryGAtom(src);
00482 
00483                     // rule
00484                     Rule r(ID::MAINKIND_RULE | ID::SUBKIND_RULE_REGULAR | ID::PROPERTY_AUX);
00485                     r.body.push_back(ID::posLiteralFromAtom(idsrc));
00486                     r.head.push_back(idtgt);
00487 
00488                     ID idr = reg->storeRule(r);
00489                     ctx.idb.push_back(idr);
00490                     DBGLOG(DBG,"created aux ground rule '" <<
00491                         printToString<RawPrinter>(idr, reg) << "'");
00492                 }
00493                 else {
00494                     // nonground atoms
00495                     OrdinaryAtom tgt(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_ORDINARYN);
00496                     tgt.tuple.push_back(pred);
00497                     OrdinaryAtom src(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_ORDINARYN | ID::PROPERTY_AUX);
00498                     src.tuple.push_back(reg->getAuxiliaryConstantSymbol('h', ID(0, arity)));
00499                     src.tuple.push_back(pred);
00500 
00501                     // now add variables
00502                     for(unsigned idx = 0; idx < arity; ++idx) {
00503                         std::ostringstream s;
00504                         s << "X" << idx;
00505                         Term var(
00506                             ID::MAINKIND_TERM |
00507                             ID::SUBKIND_TERM_VARIABLE |
00508                             ID::PROPERTY_AUX,
00509                             s.str());
00510                         const ID idvar = reg->storeConstOrVarTerm(var);
00511                         src.tuple.push_back(idvar);
00512                         tgt.tuple.push_back(idvar);
00513                     }
00514 
00515                     // store
00516                     ID idtgt = reg->storeOrdinaryNAtom(tgt);
00517                     ID idsrc = reg->storeOrdinaryNAtom(src);
00518 
00519                     // rule
00520                     Rule r(ID::MAINKIND_RULE | ID::SUBKIND_RULE_REGULAR | ID::PROPERTY_AUX);
00521                     r.body.push_back(ID::posLiteralFromAtom(idsrc));
00522                     r.head.push_back(idtgt);
00523 
00524                     ID idr = reg->storeRule(r);
00525                     ctx.idb.push_back(idr);
00526                     DBGLOG(DBG,"created aux nonground rule '" <<
00527                         printToString<RawPrinter>(idr, reg) << "'");
00528                 }
00529             }
00530         }
00531 
00532         // if any rewriting was required
00533         if( !ctxdata.arities.empty() ) {
00534             // disable strong safety check (sorry, at the moment there is no other way
00535             // because the strong safety check is too naive)
00536             ctx.config.setOption("SkipStrongSafetyCheck",1);
00537             ctx.config.setOption("LiberalSafety",0);
00538             LOG(WARNING,"disabled liberal safety and strong safety check due to higher order rewriting");
00539         }
00540     }
00541 
00542 }                                // anonymous namespace
00543 
00544 
00545 // rewrite program by adding auxiliary query rules
00546 PluginRewriterPtr HigherOrderPlugin::createRewriter(ProgramCtx& ctx)
00547 {
00548     HigherOrderPlugin::CtxData& ctxdata = ctx.getPluginData<HigherOrderPlugin>();
00549     if( !ctxdata.enabled )
00550         return PluginRewriterPtr();
00551 
00552     return PluginRewriterPtr(new HigherOrderRewriter);
00553 }
00554 
00555 
00556 namespace
00557 {
00558 
00559     class HOAuxPrinter:
00560     public AuxPrinter
00561     {
00562         public:
00563             typedef HigherOrderPlugin::CtxData::PredicateInputSet PredicateInputSet;
00564         public:
00565             HOAuxPrinter(
00566                 RegistryPtr reg,
00567                 PredicateMask& auxMask,
00568                 const PredicateInputSet& pis,
00569                 bool noFacts,
00570                 InterpretationConstPtr edb):
00571             reg(reg), mask(auxMask), pis(pis), noFacts(noFacts), edb(edb) {
00572             }
00573 
00574             // print an ID and return true,
00575             // or do not print it and return false
00576             virtual bool print(std::ostream& out, ID id, const std::string& prefix) const
00577             {
00578                 assert(id.isAuxiliary());
00579                 mask.updateMask();
00580                 DBGLOG(DBG,"mask is " << *mask.mask());
00581                 if( mask.mask()->getFact(id.address) ) {
00582                     // we cannot use any stored text to print this, we have to assemble it from pieces
00583                     DBGLOG(DBG,"printing auxiliary for higher order: " << id);
00584 
00585                     // get replacement atom details
00586                     const OrdinaryAtom& r_atom = reg->ogatoms.getByAddress(id.address);
00587                     assert(!r_atom.tuple.empty());
00588 
00589                     if( pis.count(r_atom.tuple.front()) != 0 ) {
00590                         DBGLOG(DBG,"not printing (in predicate inputs)");
00591                         return false;
00592                     }
00593 
00594                     // build non-higher-order atom and store to (or get from) registry
00595                     OrdinaryAtom printatom(
00596                         ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_ORDINARYG);
00597                     printatom.tuple.insert(printatom.tuple.end(),
00598                         r_atom.tuple.begin()+1, r_atom.tuple.end());
00599                     ID idprint = reg->storeOrdinaryGAtom(printatom);
00600 
00601                     // ensure that this is no fact (it could be)
00602                     if( noFacts && edb->getFact(idprint.address) )
00603                         return false;
00604 
00605                     DBGLOG(DBG,"printing from higher order: '" <<
00606                         printToString<RawPrinter>(idprint, reg));
00607 
00608                     // print using printAtomForUser (allows integration with other plugins)
00609                     return reg->printAtomForUser(out, idprint.address, prefix);
00610                 }
00611                 return false;
00612             }
00613 
00614         protected:
00615             RegistryPtr reg;
00616             PredicateMask& mask;
00617             const PredicateInputSet& pis;
00618             bool noFacts;
00619             InterpretationConstPtr edb;
00620     };
00621 
00622 }                                // anonymous namespace
00623 
00624 
00625 // register auxiliary printer for strong negation auxiliaries
00626 void HigherOrderPlugin::setupProgramCtx(ProgramCtx& ctx)
00627 {
00628     HigherOrderPlugin::CtxData& ctxdata = ctx.getPluginData<HigherOrderPlugin>();
00629     if( !ctxdata.enabled )
00630         return;
00631 
00632     RegistryPtr reg = ctx.registry();
00633 
00634     // auxiliary predicate mask
00635 
00636     ctxdata.myAuxiliaryPredicateMask.setRegistry(reg);
00637 
00638     // add all auxiliaries to mask (here we should already have parsed all of them)
00639     BOOST_FOREACH(unsigned arity, ctxdata.arities) {
00640         ctxdata.myAuxiliaryPredicateMask.addPredicate(
00641             reg->getAuxiliaryConstantSymbol('h', ID(0, arity)));
00642     }
00643 
00644     // update predicate mask
00645     ctxdata.myAuxiliaryPredicateMask.updateMask();
00646 
00647     // create auxiliary printer using mask
00648     AuxPrinterPtr hoPrinter(new HOAuxPrinter(
00649         reg, ctxdata.myAuxiliaryPredicateMask, ctxdata.predicateInputConstants,
00650         ctx.config.getOption("NoFacts") != 0, ctx.edb));
00651     reg->registerUserAuxPrinter(hoPrinter);
00652 }
00653 
00654 
00655 DLVHEX_NAMESPACE_END
00656 
00657 // this would be the code to use this plugin as a "real" plugin in a .so file
00658 // but we directly use it in dlvhex.cpp
00659 #if 0
00660 HigherOrderPlugin theHigherOrderPlugin;
00661 
00662 // return plain C type s.t. all compilers and linkers will like this code
00663 extern "C"
00664 void * PLUGINIMPORTFUNCTION()
00665 {
00666     return reinterpret_cast<void*>(& DLVHEX_NAMESPACE theHigherOrderPlugin);
00667 }
00668 #endif
00669 
00670 
00671 // vim:expandtab:ts=4:sw=4:
00672 // mode: C++
00673 // End: