#define YAP_CPP_INTERFACE 1 /** * * @defgroup yap-cplus-interface An object oriented interface for YAP. * * * @tableofcontents * * * C++ interface to YAP. Designed to be object oriented and to fit naturally * with the swig interface language generator. It uses ideas from the old YAP * interface and from the SWI foreign language interface. * * @{ * */ #include // Bad export from Python #ifdef HAVE_STAT #undef HAVE_STAT #endif #include extern "C" { #include #ifdef __cplusplus #define old_cplusplus __cplusplus #undef __cplusplus #endif #if USE_GMP #include #endif #ifdef old_cplusplus #define __cplusplus old_cplusplus #undef old_cplusplus #endif #include "Yap.h" #include "Yatom.h" #include "YapHeap.h" #include "pl-shared.h" #include "clause.h" #include "yapio.h" #include "Foreign.h" #include "attvar.h" #include "SWI-Stream.h" #include "YapText.h" #include "yapie.hh" #if HAVE_STDARG_H #include #endif #if HAVE_STDINT_H #include #endif #if HAVE_STRING_H #include #endif #if _MSC_VER || defined(__MINGW32__) #include #endif // taken from yap_structs.h #include "iopreds.h" extern Term Yap_StringToTerm(const char *s, size_t len, term_t bindings); // we cannot consult YapInterface.h, that conflicts with what we declare, though // it shouldn't } //#include class YAPEngine; class YAPAtom; class YAPFunctor; class YAPApplTerm; class YAPPairTerm; class YAPQuery; /** * @brief Generic Prolog Term */ class YAPTerm { friend class YAPPredicate; friend class YAPApplTerm; friend class YAPPairTerm; friend class YAPListTerm; friend class YAPQuery; protected: yhandle_t t; /// handle to term, equivalent to term_t void mk(Term t0); /// internal method to convert from term to handle Term gt(); /// get handle and obtain term YAPTerm(Term tn) { mk( tn ); } /// private method to convert from Term (internal YAP representation) to YAPTerm inline Term term() { return gt(); } /// private method to convert from YAPTerm to Term (internal YAP representation) public: // do nothing constructor YAPTerm() { mk(TermNil); } /// integer to term YAPTerm(intptr_t i); /// pointer to term YAPTerm(void *ptr); /// parse string s and construct a term. YAPTerm(char *s) { Term tp ; mk( YAP_ReadBuffer(s,&tp) ); } /// extract the tag of a term, after dereferencing. YAP_tag_t tag(); /// copy the term ( term copy ) YAPTerm deepCopy(); //const YAPTerm *vars(); /// this term is == to t1 bool exactlyEqual(YAPTerm t1); bool unify(YAPTerm t1); /// t = t1 bool unifiable(YAPTerm t1); /// we can unify t and t1 bool variant(YAPTerm t1); /// t =@= t1, the two terms are equal up to variable renaming intptr_t hashTerm(size_t sz, size_t depth, bool variant); /// term hash, bool isVar() { return IsVarTerm( gt() ); } /// type check for unbound bool isAtom() { return IsAtomTerm( gt() ); } /// type check for atom bool isInteger() { return IsIntegerTerm( gt() ); } /// type check for integer bool isFloat() { return IsFloatTerm( gt() ); } /// type check for floating-point bool isString() { return IsStringTerm( gt() ); } /// type check for a string " ... " bool isCompound() { return !(IsVarTerm( gt() ) || IsNumTerm( gt() )); } /// is a primitive term bool isAppl() { return IsApplTerm( gt() ); } /// is a structured term bool isPair() { return IsPairTerm( gt() ); } /// is a pair term bool isGround() { return Yap_IsGroundTerm( gt() ); } /// term is ground bool isList() { return Yap_IsListTerm( gt() ); } /// term is a list /// extract the argument i of the term, where i in 1...arity inline YAPTerm getArg(int i) { Term t0 = gt(); if (IsApplTerm(t0)) return YAPTerm(ArgOfTerm(i, t0)); else if (IsPairTerm(t0)) { if (i==1) return YAPTerm(HeadOfTerm(t0)); if (i==2) return YAPTerm(TailOfTerm(t0)); } return YAPTerm((Term)0); } /// return a string with a textual representation of the term char *text(); }; /** * @brief Variable Term */ class YAPVarTerm: public YAPTerm { YAPVarTerm(Term t) { if (IsVarTerm(t)) mk( t ); } public: /// constructor YAPVarTerm(); /// get the internal representation CELL *getVar() { return VarOfTerm( gt() ); } /// is the variable bound to another one bool unbound() { return IsUnboundVar(VarOfTerm( gt() )); } }; /** * @brief Compound Term */ class YAPApplTerm: public YAPTerm { friend class YAPTerm; YAPApplTerm(Term t0) { mk(t0); } public: YAPApplTerm(YAPTerm t0) { mk(t0.term()); } YAPApplTerm(YAPFunctor f, YAPTerm ts[]); YAPApplTerm(YAPFunctor f); YAPFunctor getFunctor(); YAPTerm getArg(int i); }; /** * @brief List Constructor Term */ class YAPPairTerm: public YAPTerm { friend class YAPTerm; YAPPairTerm(Term t0) { if (IsPairTerm(t0)) mk( t0 ); else mk(0); } public: YAPPairTerm(YAPTerm hd, YAPTerm tl); YAPPairTerm(); YAPTerm getHead() { return YAPTerm(HeadOfTerm( gt() )); } YAPTerm getTail() { return YAPTerm(TailOfTerm( gt() )); } }; /** * @brief Integer Term */ class YAPIntegerTerm: public YAPTerm { public: YAPIntegerTerm(intptr_t i); intptr_t getInteger() { return IntegerOfTerm( gt() ); } bool isTagged() { return IsIntTerm( gt() ); } }; class YAPListTerm: public YAPTerm { public: /// Create a list term out of a standard term. Check if a valid operation. /// /// @param[in] the term YAPListTerm(Term t0) { mk(t0); /* else type_error */ } /* /// Create a list term out of an array of terms. /// /// @param[in] the array of terms /// @param[in] the length of the array YAPListTerm(YAPTerm ts[], size_t n); */ // YAPListTerm( vector v ); /// Return the number of elements in a list term. size_t length() { Term *tailp; Term t1 = gt(); return Yap_SkipList(&t1, &tailp); } /// Extract the first element of a list. /// /// @param[in] the list YAPTerm car(); /// Extract the tail elements of a list. /// /// @param[in] the list YAPListTerm cdr() { Term to = gt(); if (IsPairTerm( to )) return YAPListTerm(TailOfTerm( to )); else return MkIntTerm(-1); } /// Check if the list is empty. /// /// @param[in] the list bool nil(); }; /** * @brief Atom */ class YAPAtom { friend class YAPPredicate; friend class YAPFunctor; friend class YAPAtomTerm; Atom a; /// construct new YAPAtom from Atom YAPAtom( Atom at ) { a = at; } public: /// construct new YAPAtom from string YAPAtom( char * s) { a = Yap_LookupAtom( s ); } /// construct new YAPAtom from wide string YAPAtom( wchar_t * s) { a = Yap_LookupMaybeWideAtom( s ); } /// construct new YAPAtom from max-length string YAPAtom( char * s, size_t len) { a = Yap_LookupAtomWithLength( s, len ); } /// construct new YAPAtom from max-length wide string YAPAtom( wchar_t * s, size_t len) { a = Yap_LookupMaybeWideAtomWithLength( s, len ); } /// get name of atom char *getName(void); }; /** * @brief String Term */ class YAPStringTerm: public YAPTerm { public: /// your standard constructor YAPStringTerm(char *s) ; /// use this one to construct length limited strings YAPStringTerm(char *s, size_t len); /// construct using wide chars YAPStringTerm(wchar_t *s) ; /// construct using length-limited wide chars YAPStringTerm(wchar_t *s, size_t len); const char *getString() { return StringOfTerm( gt() ); } }; /** * @brief Atom Term */ class YAPAtomTerm: public YAPTerm { public: YAPAtomTerm(YAPAtom a): YAPTerm() { mk( MkAtomTerm(a.a) ); } YAPAtomTerm(Atom a): YAPTerm() { mk( MkAtomTerm(a) ); } YAPAtomTerm(char *s) ; YAPAtomTerm(char *s, size_t len); YAPAtomTerm(wchar_t *s) ; YAPAtomTerm(wchar_t *s, size_t len); YAPAtom getAtom() { return YAPAtom(AtomOfTerm( gt() )); } }; /** * @brief YAPFunctor represents Prolog functors Name/Arity */ class YAPFunctor { friend class YAPApplTerm; friend class YAPPredicate; Functor f; /// Constructor: receives Prolog functor and casts it to YAPFunctor /// /// Notice that this is designed for internal use only. YAPFunctor( Functor ff) { f = ff; } public: /// Constructor: receives name as a string plus arity /// /// Notice that this is designed for ISO-LATIN-1 right now YAPFunctor( char * s, arity_t arity) { f = Yap_MkFunctor( Yap_LookupAtom( s ), arity ); } /// Constructor: receives name as a wide string plus arity /// /// Notice that this is designed for UNICODE right now YAPFunctor( wchar_t * s, arity_t arity) { f = Yap_MkFunctor( Yap_LookupWideAtom( s ), arity ); } /// Constructor: receives name as an atom, plus arity /// /// This is the default method, and the most popi;at YAPFunctor( YAPAtom at, arity_t arity) { f = Yap_MkFunctor( at.a, arity ); } /// Getter: extract name of functor as an atom /// /// this is for external usage. YAPAtom name(void) { return YAPAtom( NameOfFunctor( f ) ); } /// Getter: extract arity of functor as an unsigned integer /// /// this is for external usage. arity_t arity(void) { return ArityOfFunctor( f ); } }; /** * @brief Predicates * * This class interfaces with PredEntry in Yatom.g */ class YAPPredicate { friend class YAPQuery; private: PredEntry *ap; /// auxiliary routine to find a predicate in the current module. PredEntry *getPred( Term t, Term **outp ) ; /// String constructor for predicates /// /// It also communicates the array of arguments t[] abd the array of variables /// back to yapquery YAPPredicate(const char *s, Term **outp, yhandle_t& vnames ) throw (int); /// Term constructor for predicates /// /// It is just a call to getPred inline YAPPredicate(Term t) { ap = getPred( t , (Term **)NULL ); } /// Cast constructor for predicates, /// if we have the implementation data. /// inline YAPPredicate(PredEntry *pe) { ap = pe; } public: /// Functor constructor for predicates /// /// Asssumes that we use the current module. YAPPredicate(YAPFunctor f); /// Functor constructor for predicates, is given a specific module. /// inline YAPPredicate(YAPFunctor f, YAPTerm mod) { ap = RepPredProp(PredPropByFunc(f.f,mod.t)); } /// Name/arity constructor for predicates. /// inline YAPPredicate(YAPAtom at, YAPTerm mod) { ap = RepPredProp(PredPropByAtom(at.a,mod.t)); } /// Name/0 constructor for predicates. /// YAPPredicate(YAPAtom at); /// Mod:Name/Arity constructor for predicates. /// inline YAPPredicate(YAPAtom at, arity_t arity, YAPTerm mod) { if (arity) { Functor f = Yap_MkFunctor(at.a, arity); ap = RepPredProp(PredPropByFunc(f,mod.t)); } else { ap = RepPredProp(PredPropByAtom(at.a,mod.t)); } } /// Atom/Arity constructor for predicates. /// YAPPredicate(YAPAtom at, arity_t arity); /// String constructor for predicates. /// /// String is a Prolog term, we extract the main functor after considering the module qualifiers. inline YAPPredicate(char *s) throw (int) { Term t, tp; t = YAP_ReadBuffer(s,&tp); if (t == 0L) throw YAPError::YAP_SYNTAX_ERROR; ap = getPred( t, (Term **)NULL ); } /// String constructor for predicates, also keeps arguments in tp[] /// /// String is a Prolog term, we extract the main functor after considering the module qualifiers. inline YAPPredicate(char *s, Term **outp) throw (int) { Term t, tp; t = YAP_ReadBuffer(s,&tp); if (t == 0L) throw YAPError::YAP_SYNTAX_ERROR; ap = getPred( t, (Term **)NULL ); } /// meta-call this predicate, with arguments ts[] /// int call(YAPTerm ts[]); /// module of a predicate /// /// notice that modules are currently treated as atoms, this should change. YAPAtom module() { if (ap->ModuleOfPred == PROLOG_MODULE) return YAPAtom(AtomProlog); else return YAPAtom(AtomOfTerm(ap->ModuleOfPred)); } /// name of predicate /// /// notice that we return the atom, not a string. YAPAtom name() { if (ap->ArityOfPE) return YAPAtom((Atom)ap->FunctorOfPred); else return YAPAtom(NameOfFunctor(ap->FunctorOfPred)); } /// arity of predicate /// /// we return a positive number. arity_t getArity() { return ap->ArityOfPE; } }; /** * @brief Queries * * interface to a YAP Query; * uses an SWI-like status info internally. */ class YAPQuery: public YAPPredicate { int q_open; int q_state; Term *q_g; yamop *q_p, *q_cp; jmp_buf q_env; int q_flags; YAP_dogoalinfo q_h; YAPQuery *oq; yhandle_t vnames; void initQuery( Term ts[] ); void initQuery( YAPTerm t[], arity_t arity ); public: /// main constructor, uses a predicate and an array of terms /// /// It is given a YAPPredicate _p_ , and an array of terms that must have at least /// the same arity as the functor. YAPQuery(YAPPredicate p, YAPTerm t[]); /// full constructor, /// /// It is given a functor, module, and an array of terms that must have at least /// the same arity as the functor. YAPQuery(YAPFunctor f, YAPTerm mod, YAPTerm t[]); /// functor/term constructor, /// /// It is given a functor, and an array of terms that must have at least /// the same arity as the functor. Works within the current module. YAPQuery(YAPFunctor f, YAPTerm t[]); /// string constructor with varnames /// /// It is given a string, calls the parser and obtains a Prolog term that should be a callable /// goal and a list of variables. Useful for top-level simulation. Works within the current module. inline YAPQuery(char *s): YAPPredicate(s, &this->q_g, vnames) { Term *ts = this->q_g; initQuery( ts ); } /// set flags for query execution, currently only for exception handling void setFlag(int flag) {q_flags |= flag; } /// reset flags for query execution, currently only for exception handling void resetFlag(int flag) {q_flags &= ~flag; } /// first query /// /// actually implemented by calling the next(); inline bool first() { return next(); } /// ask for the next solution of the current query /// same call for every solution bool next(); /// remove alternatives in the current search space, and finish the current query void cut(); /// finish the current query: undo all bindings. void close(); /// query variables. YAPListTerm namedVars(); }; // Java support /// This class implements a callback Prolog-side. It will be inherited by the Java or Python /// class that actually implements the callback. class YAPCallback { public: virtual ~YAPCallback() { printf("~YAPCallback\n"); } virtual void run() { __android_log_print(ANDROID_LOG_INFO, __FUNCTION__, "callback"); } virtual void run(char *s) { } }; /** * @brief YAP Engine: takes care of the execution environment where we can go executing goals. * * */ class YAPEngine { private: YAPCallback *_callback; YAP_init_args init_args; YAPError yerror; public: YAPEngine(char *savedState = (char *)NULL, size_t stackSize = 0, size_t trailSize = 0, size_t maxStackSize = 0, size_t maxTrailSize = 0, char *libDir = (char *)NULL, char *bootFile = (char *)NULL, char *goal = (char *)NULL, char *topLevel = (char *)NULL, bool script = FALSE, bool fastBoot = FALSE, YAPCallback *callback=(YAPCallback *)NULL); /// construct a new engine, including aaccess to callbacks /// kill engine ~YAPEngine() { delYAPCallback(); } /// remove current callback void delYAPCallback() { _callback = 0; } /// set a new callback void setYAPCallback(YAPCallback *cb) { delYAPCallback(); _callback = cb; } /// execute the callback. void run() { if (_callback) _callback->run(); } /// execute the callback with a text argument. void run( char *s) { if (_callback) _callback->run(s); } /// execute the callback with a text argument. YAPError hasError( ) { return yerror; } /// build a query on the engine YAPQuery *query( char *s ); /// build a query on the engine handling exceptions YAPQuery *safeQuery( char *s ); }; /* * @} * */