dlvhex
2.5.0
|
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: