// objects.h // // A representation of the Prolog-level obejcts for the Qu-Prolog // Abstract Machine (QuAM). // // ##Copyright## // // Copyright 2000-2016 Peter Robinson (pjr@itee.uq.edu.au) // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.00 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // ##Copyright## // // $Id: objects.h,v 1.12 2006/01/31 23:17:51 qp Exp $ #ifndef OBJECTS_H #define OBJECTS_H #include #include //#include "atom_table.h" #include "debug.h" // Qu-Prolog debug code facilities #include "defs.h" // Qu-Prolog data type definitions &c. #include "string_table.h" #include "truth3.h" // Dynamic cast doesn't work the way it should. #define OBJECT_CAST(type, expr) reinterpret_cast(expr) // Forward references for all the subclasses of Object, inserted so // that ordering of the subclasses is not important (and also to // provide a handy reference :-) class AtomTable; class Constant; // abstract class Atom; class Short; class Long; class Double; class StringObject; class Reference; // abstract class Variable; class ObjectVariable; class Structure; class List; // abstract class Cons; class QuantifiedTerm; class Substitution; class SubstitutionBlock; // Garbage collection bit static const heapobject GC_B = 0x00000001ULL; ////////////////////////////////////////////////////////////////////// // The Object class specification class Object { // The Heap and Object classes are tightly bound. friend class Heap; friend class AtomTable; public: // Buckybits for the broadest types in the tag static const heapobject TypeMask = 0x000000F0ULL; static const heapobject TypeVar = 0x00000000ULL; // variable static const heapobject TypeShort = 0x00000010ULL; // short static const heapobject TypeLong = 0x00000030ULL; // long static const heapobject TypeDouble = 0x00000050ULL; // double static const heapobject TypeAtom = 0x00000040ULL; // atom static const heapobject TypeString = 0x00000020ULL; // string static const heapobject TypeStruct = 0x00000070ULL; // struct static const heapobject TypeCons = 0x00000060ULL; // Cons (list) static const heapobject TypeObjVar = 0x00000080ULL; // object variable static const heapobject TypeQuant = 0x00000090ULL; // quantifier static const heapobject TypeSubst = 0x000000A0ULL; // substitution static const heapobject TypeSubBlock = 0x000000B0ULL; // substitution block // Types for unification switch // number = { short, long, double} // other = {sub, subblock, obvar, quant, other-var} static const heapobject UnifyMask = 0x0000000EULL; static const heapobject UVar = 0x00000000ULL; // variable static const heapobject UVarOC = 0x00000002ULL; // var with OC flag set static const heapobject UNumber = 0x00000004ULL; // number static const heapobject UAtom = 0x00000006ULL; // atom static const heapobject UString = 0x00000008ULL; // string static const heapobject UStruct = 0x0000000AULL; // structure static const heapobject UCons = 0x0000000cULL; // cons static const heapobject UOther = 0x0000000EULL; // other static const heapobject TypeTagMask = 0x000000FFULL; static const heapobject VarTag = GC_B | UVar | TypeVar; static const heapobject VarOCTag = GC_B | UVarOC | TypeVar; static const heapobject VarOtherTag = GC_B | UOther | TypeVar; static const heapobject ShortTag = GC_B | UNumber | TypeShort; static const heapobject LongTag = GC_B | UNumber | TypeLong; static const heapobject DoubleTag = GC_B | UNumber | TypeDouble; static const heapobject AtomTag = GC_B | UAtom | TypeAtom; static const heapobject StringTag = GC_B | UString | TypeString; static const heapobject StructTag = GC_B | UStruct | TypeStruct; static const heapobject ConsTag = GC_B | UCons | TypeCons; static const heapobject ObjVarTag = GC_B | UOther | TypeObjVar; static const heapobject QuantTag = GC_B | UOther | TypeQuant; static const heapobject SubstTag = GC_B | UOther | TypeSubst; static const heapobject SubBlockTag = GC_B | UOther | TypeSubBlock; static const heapobject NumberTag = 0x00000015ULL; static const heapobject DerefMask = 0x00000070ULL; static const heapobject tVar = TypeVar >> 4; static const heapobject tShort = TypeShort >> 4; static const heapobject tLong = TypeLong >> 4; static const heapobject tDouble = TypeDouble >> 4; static const heapobject tAtom = TypeAtom >> 4; static const heapobject tString = TypeString >> 4; static const heapobject tStruct = TypeStruct >> 4; static const heapobject tCons = TypeCons >> 4; static const heapobject tObjVar = TypeObjVar >> 4; static const heapobject tSubst = TypeSubst >> 4; static const heapobject tSubBlock = TypeSubBlock >> 4; static const heapobject tQuant = TypeQuant >> 4; protected: // contents of structure heapobject tag; public: // For masking the top bits static const heapobject TopMask = -256LL; // fff..fff00ULL static const heapobject TopSBMask = -4096LL; // fff..ff000ULL // Special tag for unify_x_ref instruction static const heapobject RefTag = 0x000000FEULL; inline u_int tTag() const; inline heapobject getTag() const; inline u_int getType(void) const; inline u_int switchOffset() const; // Returns the first word of the storage after the tag inline heapobject *storage(void); #ifdef OBJECT_OVERRIDES // For mutiterms virtual bool OverridesStrictEquals(Object* o2, Thread* ctx, bool &result); virtual bool OverridesUnify(Object* o2, Thread* ctx, bool in_quant, bool &result); #endif // Some boolean functions for eliciting the type of Object being // pointed to. inline bool isRefTag(void) const; inline bool isVariable(void) const; inline bool isVariableExtended(void) const; inline bool isNormalVariable(void) const; inline bool isFrozenVariable(void) const; inline bool isThawedVariable(void) const; inline bool isObjectVariable(void) const; inline bool isLocalObjectVariable(void) const; inline bool isAnyVariable(void) const; inline bool isStructure(void) const; inline bool isList(void) const; // isCons() || isNil() inline bool isCons(void) const; inline bool isNil(void) const; // isAtom() && this == AtomTable::Nil inline bool inList(Object*); inline bool isAnyStructure(void) const; inline bool isQuantifiedTerm(void) const; inline bool isConstant(void) const; inline bool isNumber(void) const; inline bool isInteger(void) const; inline bool isAtom(void) const; inline bool isString(void) const; inline bool isEmptyString(void); inline bool isShort(void) const; inline bool isLong(void) const; inline bool isDouble(void) const; inline bool isSubstitution(void) const; inline bool isSubstitutionBlock(void) const; // Returns the value of a Short or Long. inline qint64 getInteger(void); inline double getDouble(void); inline heapobject* last(void); public: // Dummy constructor - needed for atom constructor. Object(void) {} // Dispatching for the size() message, which returns the size of // the Object being pointed to size_t size_dispatch(void); #ifndef NDEBUG public: // Testing substitution block lists to see if they are legal inline bool isLegalSub(void); inline bool hasLegalSub(void); // Dispatching for the DEBUG printMe() message, which displays a // representation of the Object being pointed to inline void printMe_dispatch(AtomTable&, bool all = true); bool check_object(); #endif // // variableDereference() follows the (ob)variable-reference chain from // an object -- iteratively, not recursively -- and returns the object // at the end of the (ob)variable chain. // inline Object* variableDereference(); // // Check whether the object variable is in the distinctness information list. // NOTE: // ObjectVariable should be dereferenced before this function is called. // bool isObjectVariableInDistinctList(const ObjectVariable *objvar) const; // // Check whether two object variables are distinct. // Return true if object variables are known to be distinct. // NOTE: // ObjectVariable1 and ObjectVariable2 should be dereferenced // before this function is called. // bool distinctFrom(const Object *objvar) const; // // The function returns true if the object_variable is distinct from // all domains in the i-th to SubSize-th entry of the substitution. // bool distinctFromDomains(const SubstitutionBlock *sub_block, size_t i); // // The substitution is scanned from right to left for the local object // variable on a domain or range place. If the last occurrence of the // local object variable is as a range element, then save the corresponding // domain element and the new end of the substitution which // is one where local object variable is found. // bool containLocalObjectVariable(Object* sub, Object*& domElem, Object*& newEnd); inline bool equalConstants(Object* const2); inline bool equalUninterp(Object* const2); // // Return the length of the bound variables list. // size_t boundListLength(void); }; ////////////////////////////////////////////////////////////////////// // The Constant class specification // (NB. This is intended to be an ``abstract'' class) class Constant : public Object { protected: friend class Heap; friend class Object; friend class AtomTable; public: // Dummy constructor - needed for atom constructor Constant(void):Object() {} #ifdef QP_DEBUG public: inline void printMe(AtomTable&, bool); #endif }; ////////////////////////////////////////////////////////////////////// // The Atom class specification // (NB. These do not appear on the heap.) class Atom : public Constant { protected: // Pointer into the string table for the atom's name char* string_table_ptr; // Either an Atom * or int, depending on hasAssociatedItem() wordptr associatedval; public: // Buckybits static const heapobject AssociatedMask = 0x00000300ULL; static const heapobject AssociatedNone = 0x00000000ULL; static const heapobject AssociatedInteger = 0x00000100ULL; static const heapobject AssociatedAtom = 0x00000200ULL; typedef heapobject AssociatedItem; public: // Constructor - needed to initialize atom table. Atom(void):Constant() { tag = AtomTag; string_table_ptr = NULL; associatedval = 0; } public: // String related things inline void setStringTablePtr(char*); inline char* getStringTablePtr(void) const; inline char* getName(void) const; inline bool isEmpty(void) const; inline bool getBool(void) const; public: // Accessors and mutators inline bool hasAssociatedItem(void) const; inline bool hasAssociatedAtom(void) const; inline bool hasAssociatedInteger(void) const; inline void associateInteger(const qint64 val); inline void associateAtom(Atom *atm); inline Atom *getAssociatedAtom(void) const; inline qint64 getAssociatedInteger(void) const; public: static inline size_t size(void); #ifdef QP_DEBUG public: inline void printMe(AtomTable&, bool); #endif }; ////////////////////////////////////////////////////////////////////// // The Short class specification class Short : public Constant { protected: // Value is encoded in tag; no extra elements required public: static const heapobject Zero = ShortTag; // Accessors and mutators inline qint64 getValue(void) const; public: static inline size_t size(void); #ifdef QP_DEBUG public: inline void printMe(AtomTable&, bool); #endif }; ////////////////////////////////////////////////////////////////////// // The Double class specification class Double : public Constant { public: static const size_t DOUBLE_SIZE = sizeof(double)/BYTES_PER_WORD; protected: heapobject x[DOUBLE_SIZE]; public: // Accessor (no mutator) inline double getValue(void) const; public: static inline size_t size(void); inline wordlong hashFn(void) const; #ifdef QP_DEBUG public: inline void printMe(AtomTable&, bool); #endif }; ////////////////////////////////////////////////////////////////////// // The Long class specification class Long : public Constant { protected: // The value of the Long wordptr value; public: // Accessor (no mutator) inline qint64 getValue(void) const; public: static inline size_t size(void); #ifdef QP_DEBUG public: inline void printMe(AtomTable&, bool); #endif }; class StringObject : public Object { protected: heapobject theChars[1]; public: char* getChars() { return (char*)theChars; } inline size_t size(void) const; inline wordlong hashFn(void) const; }; ////////////////////////////////////////////////////////////////////// // The Structure class specification // (A functor and n arguments. The functor is argument 0.) class Structure : public Object { protected: // Arity is encoded in the tag Object *argument[1]; // arity + 1 arguments (argument[0] is functor) public: // Accessor for arity (there is no mutator to avoid realloc() type // problems. inline size_t getArity(void) const; // Accessor and mutator for arguments. Argument 0 is the functor, // arguments proper are in the range 1..`arity'. inline Object *getArgument(const size_t n) const; inline void setArgument(const size_t n, Object * plobj); // Additional wrappers for argument 0 inline Object *getFunctor(void) const; inline void setFunctor(Object * plobj); public: // Note, not static, since the size depends on the number of // arguments. inline size_t size(void) const; // Does the real work of figuring out the size. static inline size_t size(size_t arity); #ifdef QP_DEBUG public: inline void printMe(AtomTable&, bool); #endif }; ////////////////////////////////////////////////////////////////////// // The Cons class specification // class Cons: public Object { protected: Object *head; Object *tail; public: static const heapobject FlagTypeMask = 0x00000c00ULL; static const heapobject FlagAnyList = 0x00000000ULL; static const heapobject FlagObjectVariableList = 0x00000400ULL; static const heapobject FlagSubstitutionBlockList = 0x00000800ULL; static const heapobject FlagDelayedProblemList = 0x00000c00ULL; static const heapobject FlagInvertibleMask = 0x00000200ULL; static const heapobject FlagNotInvertible = 0x00000000ULL; static const heapobject FlagInvertible = 0x00000200ULL; static const u_int TailOffset = 2; public: static inline size_t size(void); inline void makeSubstitutionBlockList(void); inline void makeObjectVariableList(void); inline void makeDelayedProblemList(void); inline bool isAnyList(void) const; inline bool isSubstitutionBlockList(void) const; inline bool isObjectVariableList(void) const; inline bool isDelayedProblemList(void) const; public: inline void makeInvertible(void); inline bool isInvertible(void) const; public: inline void setHead(Object * const); inline Object *getHead(void) const; inline void setTail(Object * const); inline Object *getTail(void) const; inline Object **getTailAddress(void); #ifdef QP_DEBUG public: inline void printMe(AtomTable&, bool); #endif }; ////////////////////////////////////////////////////////////////////// // The QuantifiedTerm class specification class QuantifiedTerm : public Object { protected: Object *quantifier; Object *boundvars; Object *body; public: // Accessors inline Object *getQuantifier(void) const; inline Object *getBoundVars(void) const; // A list of some sort inline Object *getBody(void) const; // Mutators inline void setQuantifier(Object *o); inline void setBoundVars(Object *l); inline void setBody(Object *o); public: static inline size_t size(void); #ifdef QP_DEBUG public: inline void printMe(AtomTable&, bool); #endif }; ////////////////////////////////////////////////////////////////////// // The Substitution class specification class Substitution : public Object { protected: Object *sub_block_list; // A Prolog list of parallel substitutions Object *term; public: // Accessors inline Object *getSubstitutionBlockList(void) const; inline Object *getTerm(void) const; // Mutators/ inline void setSubstitutionBlockList(Object *l); inline void setTerm(Object *o); public: static inline size_t size(void); #ifdef QP_DEBUG public: inline void printMe(AtomTable&, bool); #endif }; ////////////////////////////////////////////////////////////////////// // The SubstitutionBlock class specification // (A list of parallel substitutions to be performed on a term) class SubstitutionBlock: public Object { friend class Heap; protected: // Size of block is encoded in the tag struct { ObjectVariable *dom; Object *ran; } substitution[1]; public: // Buckybits static const heapobject InvertibleMask = 0x00000200ULL; static const heapobject FlagInvertible = 0x00000200ULL; static const heapobject FlagNotInvertible = 0x00000000ULL; // Accessor type for Invertible enum Invertible { NotInvertible = 0ULL, IsInvertible = FlagInvertible }; // Accessors inline size_t getSize(void) const; inline ObjectVariable *getDomain(const size_t n) const; inline Object *getRange(const size_t n) const; // Mutators inline void decrementSize(void); inline void setDomain(const size_t n, Object *dom); inline void setRange(const size_t n, Object *ran); inline void setSubstitutionPair(const size_t n, Object *dom, Object *ran); // Invertibility operations inline bool isInvertible(void) const; inline void makeInvertible(void); // Miscellaneous inline bool containsLocal(void) const; public: // Note, not static, as size depends on the size of storage for // underlying domain/range pairs. inline size_t size(void) const; // Does the real work of figuring out the size. static inline size_t size(size_t sub_size); #ifdef QP_DEBUG public: inline void printMe(AtomTable&, bool); #endif }; ////////////////////////////////////////////////////////////////////// // The Reference class specification // (NB. This is intended to be an ``abstract'' class) class Reference : public Object { protected: heapobject info[1]; // In a Variable that has extra information: // info[0] = reference // info[1] = name (Atom *) // info[2] = delayed problem list (Object *) // In an ObjectVariable that has extra information: // info[0] = reference // info[1] = name (Atom *) // info[2] = delayed problem list (Object *) // info[3] = distinctness information (Object *) public: static const u_int NameOffset = 2; static const u_int DelaysOffset = 3; // Buckybits static const heapobject FlagExtraMask = 0x00000F00ULL; static const heapobject FlagOccurs = 0x00000100ULL; static const heapobject FlagExtraInfo = 0x00000200ULL; static const heapobject FlagTemperature = 0x00000400ULL; static const heapobject FlagCollected = 0x00001000ULL; static const heapobject FlagPerm = 0x00002000ULL; // Accessors and mutators inline Object *getReference(void) const; inline void setReference(Object *plobj); inline bool hasExtraInfo(void) const; inline void setExtraInfo(void); inline Atom *getName(void) const; inline heapobject *getNameAddress(void); inline void setName(Object*); // Delay chains inline Object *getDelays(void) const; inline heapobject *getDelaysAddress(void); inline void setDelays(Object*); // Collection operations inline bool isCollected(void) const; inline void setCollectedFlag(void); inline void unsetCollectedFlag(void); // Perm vars operations inline bool isPerm(void) const; inline void setPermFlag(void); inline bool isUnbound(void) const; }; ////////////////////////////////////////////////////////////////////// // The Variable class specification // (An Object which is a reference to another Object) class Variable : public Reference { public: // No extra functionality required beyond what is inherited from // Reference public: // Note, not static, since the size depends on the // possible presence of extra information. inline size_t size(void) const; // Does the real work of figuring out the size. static inline size_t size(bool has_extra_info); // Temperature operations inline void freeze(void); inline bool isFrozen(void); inline void thaw(void); inline bool isThawed(void); // OccursCheck operations inline bool isOccursChecked(void) const; inline void setOccursCheck(void); inline void setOccursCheckOther(void); inline bool isLifeSet(void) const; inline u_int getLife(void) const; inline void setLife(u_int); // Copy the tags of another variable (without extra info) // to this var (with extra info). inline void copyTag(Object*); inline heapobject getID(void) const; inline void setID(heapobject); #ifdef QP_DEBUG public: inline void printMe(AtomTable&, bool); #endif }; ////////////////////////////////////////////////////////////////////// // The ObjectVariable class specification class ObjectVariable: public Reference { public: static const u_int DistinctnessOffset = 4; static const heapobject FlagLocalMask = 0x00000800ULL; static const heapobject FlagLocal = 0x00000800ULL; // Temperature operations inline void freeze(void); inline bool isFrozen(void); inline void thaw(void); inline bool isThawed(void); // Accessors and mutators inline Object *getDistinctness(void) const; inline heapobject *getDistinctnessAddress(void); inline void setDistinctness(Object * l); inline void setLocal(void); inline bool isLocal(void) const; public: // Note, not static, as the size depends on the possible presence of // extra information. inline size_t size(void) const; // Does the real work of figuring out the size. static inline size_t size(bool has_extra_info); bool isObjectVariableInDomain(SubstitutionBlock *); inline void makeLocalObjectVariable(void); #ifdef QP_DEBUG public: inline void printMe(AtomTable&, bool); #endif }; // // // ---------------------------- // Bodies of inline functions // ---------------------------- // // #endif // OBJECTS_H #ifndef OBJECTS_H_INLINE // MEGA-KLUDGE!!!!!! #define OBJECTS_H_INLINE #include "atom_table.h" ////////////////////////////////////////////////////////////////////// // Inline functions for the Object class inline u_int Object::tTag(void) const { return (tag & TypeMask) >> 4; } inline u_int Object::getType(void) const { return (tag & TypeTagMask); } inline heapobject Object::getTag(void) const { return tag; } inline u_int Object::switchOffset() const { switch ((tag & TypeMask) >> 4) { case tVar: return 0; break; case tShort: case tLong: case tDouble: case tAtom: case tString: return 5; break; case tStruct: return 3; break; case tCons: return 2; break; case tObjVar: return 1; break; case tSubst: return 6; break; case tQuant: return 4; break; default: assert(false); return 0; break; } assert(false); return 0; } inline heapobject * Object::storage(void) { return reinterpret_cast(this) + 1; } inline bool Object::isRefTag(void) const { return tag == RefTag; } inline bool Object::isVariable(void) const { return (tag & TypeMask) == TypeVar; } inline bool Object::isVariableExtended(void) const { return (tag & (TypeMask | Reference::FlagExtraInfo)) == (TypeVar | Reference::FlagExtraInfo); } inline bool Object::isFrozenVariable(void) const { return (tag & (TypeMask | Reference::FlagTemperature)) == (TypeVar | Reference::FlagTemperature); } inline bool Object::isThawedVariable(void) const { return (tag & (TypeMask | Reference::FlagTemperature)) == TypeVar; } inline bool Object::isObjectVariable(void) const { return (tag & TypeMask) == TypeObjVar; } inline bool Object::isLocalObjectVariable(void) const { return ((tag & (TypeMask | ObjectVariable::FlagLocalMask)) == (TypeObjVar | ObjectVariable::FlagLocal)); } inline bool Object::isAnyVariable(void) const { return isVariable() || isObjectVariable(); } inline bool Object::isStructure(void) const { return (tag & TypeMask) == TypeStruct; } inline bool Object::isCons() const { return (tag & TypeMask) == TypeCons; } inline bool Object::isNil(void) const { return this == AtomTable::nil; } inline bool Object::isList(void) const { return isCons() || isNil(); } inline bool Object::isAnyStructure(void) const { return isStructure() || isCons(); } inline bool Object::isQuantifiedTerm(void) const { return (tag & TypeMask) == TypeQuant; } inline bool Object::isConstant(void) const { u_int t = (tag & UnifyMask) >> 1; return ((t > 1) && (t < 5)); } inline bool Object::isShort(void) const { return (tag & TypeMask) == TypeShort; } inline bool Object::isString(void) const { return (tag & TypeMask) == TypeString; } inline bool Object::isEmptyString(void) { return (this->isString() && (OBJECT_CAST(StringObject*, this)->getChars()[0] == '\0')); } inline bool Object::isLong(void) const { return (tag & TypeMask) == TypeLong; } inline bool Object::isDouble(void) const { return (tag & TypeMask) == TypeDouble; } inline bool Object::isNumber(void) const { return (tag & UnifyMask) == UNumber; } inline bool Object::isInteger(void) const { return isShort() || isLong(); } inline bool Object::isAtom(void) const { return (tag & TypeMask) == TypeAtom; } inline bool Object::isSubstitution(void) const { return (tag & TypeMask) == TypeSubst; } inline bool Object::isSubstitutionBlock(void) const { return (tag & TypeMask ) == TypeSubBlock; } inline heapobject* Object::last(void) { assert(!isNumber()); assert(size_dispatch() > 1); return (reinterpret_cast(this) + size_dispatch() - 1); } #ifdef QP_DEBUG inline bool Object::isLegalSub(void) { if (isNil()) { return true; } if (!isCons()) { return false; } Cons* sub = OBJECT_CAST(Cons*, this); if (!sub->isSubstitutionBlockList() || !sub->getTail()->isLegalSub() || !sub->getHead()->isSubstitutionBlock()) { return false; } SubstitutionBlock* subblock = OBJECT_CAST(SubstitutionBlock*, sub->getHead()); if (subblock->getSize() == 0) { return false; } for (size_t i = 1; i <= subblock->getSize(); i++) { if (!subblock->getDomain(i)->variableDereference()->isObjectVariable()) { return false; } if (!subblock->getRange(i)->variableDereference()->hasLegalSub()) { return false; } } return true; } inline bool Object::hasLegalSub(void) { if (!isSubstitution()) { return true; } return (OBJECT_CAST(Substitution*, this)->getSubstitutionBlockList()->isLegalSub()); } // The next best thing to generic dispatching inline void Object::printMe_dispatch(AtomTable& atoms, bool all) { if (this == NULL) { std::cerr << "(undefined)"; return; } switch (tTag ()) { case tVar: OBJECT_CAST(Variable *, this)->printMe(atoms, all); break; case tShort: OBJECT_CAST(Short *, this)->printMe(atoms, all); break; case tLong: OBJECT_CAST(Long *, this)->printMe(atoms, all); break; case tAtom: OBJECT_CAST(Atom *, this)->printMe(atoms, all); break; case tDouble: OBJECT_CAST(Double *, this)->printMe(atoms, all); break; case tCons: OBJECT_CAST(Cons *, this)->printMe(atoms, all); break; case tStruct: OBJECT_CAST(Structure *, this)->printMe(atoms, all); break; case tSubst: OBJECT_CAST(Substitution *, this)->printMe(atoms, all); break; case tSubBlock: OBJECT_CAST(SubstitutionBlock *, this)->printMe(atoms, all); break; case tObjVar: OBJECT_CAST(ObjectVariable *, this)->printMe(atoms, all); break; case tQuant: OBJECT_CAST(QuantifiedTerm *, this)->printMe(atoms, all); break; default: // Not all Tags considered! std::cerr << "Bogus type" << std::endl; std::cerr << (wordptr)(this) << " -> " << *((heapobject*)(this)) << std::endl; assert(false); } } #endif ////////////////////////////////////////////////////////////////////// // Inline functions for the Atom class inline char* Atom::getStringTablePtr(void) const { return string_table_ptr; } inline char* Atom::getName(void) const { return string_table_ptr; } inline void Atom::setStringTablePtr(char* stl) { string_table_ptr = stl; } inline bool Atom::isEmpty(void) const { return string_table_ptr == NULL; } inline bool Atom::getBool(void) const { return this == AtomTable::success; } inline bool Atom::hasAssociatedItem(void) const { return (tag & AssociatedMask) != 0; } inline bool Atom::hasAssociatedAtom(void) const { return (tag & AssociatedMask) == AssociatedAtom; } inline bool Atom::hasAssociatedInteger(void) const { return (tag & AssociatedMask) == AssociatedInteger; } inline void Atom::associateInteger(const qint64 val) { tag = (tag & ~AssociatedMask) | AssociatedInteger; associatedval = val; } inline void Atom::associateAtom(Atom *atm) { tag = (tag & ~AssociatedMask) | AssociatedAtom; associatedval = reinterpret_cast(atm); } inline Atom *Atom::getAssociatedAtom(void) const { assert(sizeof(void *) == sizeof(heapobject)); assert(hasAssociatedAtom()); return reinterpret_cast(associatedval); } inline qint64 Atom::getAssociatedInteger (void) const { assert(sizeof(void *) == sizeof(heapobject)); assert(hasAssociatedInteger()); return associatedval; } inline size_t Atom::size(void) { return sizeof(Atom) / BYTES_PER_WORD; } #ifdef QP_DEBUG inline void Atom::printMe(AtomTable& atoms, bool) { std::cerr << "[" << std::hex << (wordptr) this << std::dec << "] Atom: \"" << this->getName() << "\" "; #ifndef WIN32 switch (tag & AssociatedMask) { case AssociatedNone: std::cerr << "(no info)"; break; case AssociatedInteger: std::cerr << "int: " << getAssociatedInteger(); break; case AssociatedAtom: std::cerr << "atom: [" << std::hex << (wordptr) getAssociatedAtom() << std::dec << "]"; break; } #endif } #endif ////////////////////////////////////////////////////////////////////// // Inline functions for the Short class inline qint64 Short::getValue(void) const { // N.B. The alternative of using >> 8 is apparently not portable // in the case of signed quantities. return (qint64)((qint64)(tag & TopMask) / 256); } inline size_t Short::size(void) { return sizeof(Short) / BYTES_PER_WORD; } #ifdef QP_DEBUG inline void Short::printMe(AtomTable& atoms, bool) { std::cerr << "[" << std::hex << (wordptr) this << std::dec << "] Short: \"" << getValue() << "\" "; } #endif ////////////////////////////////////////////////////////////////////// // Inline functions for the Double class inline double Double::getValue(void) const { double res = *((double*)x); return res; } #ifdef QP_DEBUG inline void Double::printMe(AtomTable& atoms, bool) { std::cerr << "[" << hex << (wordptr) this << dec << "] Double: \"" << getValue() << "\" "; } #endif inline size_t Double::size(void) { return sizeof(Double) / BYTES_PER_WORD; } inline wordlong Double::hashFn(void) const { u_char s[sizeof(double)]; double d = getValue(); memcpy(s, &d, sizeof(double)); wordlong value = 0; u_char* sp = s; while (*sp != '\0') { value *= 167; value ^= *sp++; } return(value); } ////////////////////////////////////////////////////////////////////// // Inline functions for the Long class inline qint64 Long::getValue(void) const { assert(sizeof(qint64) == sizeof(heapobject)); return (qint64)value; } inline size_t Long::size(void) { return sizeof(Long) / BYTES_PER_WORD; } #ifdef QP_DEBUG inline void Long::printMe(AtomTable& atoms, bool) { std::cerr << "[" << std::hex << (wordptr) this << std::dec << "] Long: \"" << getValue() << "\" "; } #endif ////////////////////////////////////////////////////////////////////// // Inline functions for the StringObject class inline size_t StringObject::size() const { return (tag >> 8) - 1 + sizeof(StringObject) / BYTES_PER_WORD; } inline wordlong StringObject::hashFn(void) const { char *s; wordlong value = 0; s = (char*)theChars; while (*s != '\0') { value *= 167; value ^= *s++; } return(value); } ////////////////////////////////////////////////////////////////////// // Inline functions for the Structure class inline size_t Structure::getArity(void) const { return (tag & TopMask) >> 8; } // Returns argument `n' of the Structure, with argument 0 being // considered as a reference to the functor. inline Object *Structure::getArgument(const size_t n) const { assert(sizeof(Object *) == sizeof(heapobject)); // Can only access valid arguments assert(0 <= n && n <= getArity()); return argument[n]; } inline Object *Structure::getFunctor(void) const { assert(sizeof(Object *) == sizeof(heapobject)); return getArgument(0); } // Sets argument `n' of the Structure to `plobj', again, with argument // 0 being considered the functor. inline void Structure::setArgument(const size_t n, Object * plobj) { assert(sizeof(Object *) == sizeof(heapobject)); // Can only set valid arguments assert(0 <= n && n <= getArity ()); argument[n] = plobj; } inline void Structure::setFunctor(Object * plobj) { setArgument(0, plobj); } inline size_t Structure::size(void) const { return size(getArity()); } inline size_t Structure::size(size_t arity) { return arity + sizeof(Structure) / BYTES_PER_WORD; } #ifdef QP_DEBUG inline void Structure::printMe(AtomTable& atoms, bool all) { std::cerr << "[" << std::hex << (wordptr) this << std::dec << "] Structure:[" << (wordptr)tag << "] arity: " << getArity() << " functor: [ "; getFunctor()->printMe_dispatch(atoms, all); std::cerr << " ] "; for (size_t i = 1; i <= getArity(); i++) { std::cerr << i << ": [ "; getArgument(i)->printMe_dispatch(atoms, all); std::cerr << " ] "; } } #endif ////////////////////////////////////////////////////////////////////// // Inline functions for the Cons class inline size_t Cons::size(void) { return(sizeof(Cons) / BYTES_PER_WORD); } inline void Cons::makeSubstitutionBlockList(void) { assert(isAnyList()); tag |= FlagSubstitutionBlockList; } inline void Cons::makeObjectVariableList(void) { assert(isAnyList()); tag |= FlagObjectVariableList; } inline void Cons::makeDelayedProblemList(void) { assert(isAnyList()); tag |= FlagDelayedProblemList; } inline bool Cons::isAnyList(void) const { return (tag & FlagTypeMask) == FlagAnyList; } inline bool Cons::isSubstitutionBlockList(void) const { return (tag & FlagSubstitutionBlockList) == FlagSubstitutionBlockList; } inline bool Cons::isDelayedProblemList(void) const { return (tag & FlagTypeMask) == FlagDelayedProblemList; } inline void Cons::makeInvertible(void) { assert(isSubstitutionBlockList()); tag |= FlagInvertible; } inline bool Cons::isInvertible(void) const { assert(isSubstitutionBlockList()); return (tag & FlagInvertibleMask) == FlagInvertible; } inline void Cons::setHead(Object* const plobj) { assert(sizeof(Object *) == sizeof(heapobject)); head = plobj; } inline Object * Cons::getHead(void) const { assert(sizeof(Object *) == sizeof(heapobject)); return head; } inline void Cons::setTail(Object* const plobj) { assert(sizeof(Object *) == sizeof(heapobject)); tail = plobj; } inline Object * Cons::getTail(void) const { assert(sizeof(Object *) == sizeof(heapobject)); return tail; } inline Object ** Cons::getTailAddress(void) { assert(sizeof(Object *) == sizeof(heapobject)); return &tail; } #ifdef QP_DEBUG inline void Cons::printMe(AtomTable& atoms, bool all) { std::cerr << "[" << std::hex << (wordptr) this << std::dec << "] Cons: "; if (isSubstitutionBlockList()) { std::cerr << "(Sub) "; if (isInvertible()) std::cerr << "(Invertible) "; } std::cerr << " head: [ "; getHead()->printMe_dispatch(atoms, all); std::cerr << " ] tail: [ "; getTail()->printMe_dispatch(atoms, all); std::cerr << " ]"; } #endif ////////////////////////////////////////////////////////////////////// // Inline functions for the QuantifiedTerm class inline size_t QuantifiedTerm::size(void) { return sizeof(QuantifiedTerm) / BYTES_PER_WORD; } inline Object *QuantifiedTerm::getQuantifier(void) const { assert(sizeof(Object *) == sizeof(heapobject)); return quantifier; } inline Object *QuantifiedTerm::getBoundVars(void) const { assert(sizeof(Object *) == sizeof(heapobject)); return boundvars; } inline Object *QuantifiedTerm::getBody(void) const { assert(sizeof(Object *) == sizeof(heapobject)); return body; } inline void QuantifiedTerm::setQuantifier(Object *o) { assert(sizeof(Object *) == sizeof(heapobject)); quantifier = o; } inline void QuantifiedTerm::setBoundVars(Object *l) { assert(sizeof(Object *) == sizeof(heapobject)); assert(l->isList() || l->isVariable()); boundvars = l; } inline void QuantifiedTerm::setBody(Object *o) { assert(sizeof(Object *) == sizeof(heapobject)); body = o; } #ifdef QP_DEBUG inline void QuantifiedTerm::printMe(AtomTable& atoms, bool all) { std::cerr << "[" << std::hex << (wordptr) this << std::dec << "] QuantifiedTerm: quantifier: [ "; getQuantifier()->printMe_dispatch(atoms, all); std::cerr << " ] boundvars: [ "; getBoundVars()->printMe_dispatch(atoms, all); std::cerr << " ] body: [ "; getBody()->printMe_dispatch(atoms, all); std::cerr << " ]"; } #endif ////////////////////////////////////////////////////////////////////// // Inline functions for the Substitution class inline size_t Substitution::size(void) { return sizeof(Substitution) / BYTES_PER_WORD; } inline Object *Substitution::getSubstitutionBlockList(void) const { assert(sizeof(Object *) == sizeof(heapobject)); return sub_block_list; } inline Object *Substitution::getTerm(void) const { assert(sizeof(Object *) == sizeof(heapobject)); return term; } inline void Substitution::setSubstitutionBlockList(Object *l) { assert(sizeof(Object *) == sizeof(heapobject)); assert(l->isList()); sub_block_list = l; } inline void Substitution::setTerm(Object *o) { assert(sizeof(Object *) == sizeof(heapobject)); term = o; } #ifdef QP_DEBUG inline void Substitution::printMe(AtomTable& atoms, bool all) { std::cerr << "[" << std::hex << (wordptr) this << std::dec << "] Substitution: subst: [ "; getSubstitutionBlockList()->printMe_dispatch(atoms, all); std::cerr << " ] term: [ "; getTerm()->printMe_dispatch(atoms, all); std::cerr << " ]"; } #endif ////////////////////////////////////////////////////////////////////// // Inline functions for the SubstitutionBlock class inline size_t SubstitutionBlock::size(void) const { return size(getSize()); } inline size_t SubstitutionBlock::size(size_t sub_size) { return sizeof(SubstitutionBlock) / BYTES_PER_WORD + (sub_size - 1) * 2; } inline bool SubstitutionBlock::isInvertible(void) const { return (tag & InvertibleMask) == FlagInvertible; } inline void SubstitutionBlock::makeInvertible(void) { tag |= FlagInvertible; } inline size_t SubstitutionBlock::getSize(void) const { return tag >> 12; } inline ObjectVariable *SubstitutionBlock::getDomain(const size_t n) const { // Can only access valid pairs assert(1 <= n && n <= getSize()); return substitution[n-1].dom; } inline Object *SubstitutionBlock::getRange(const size_t n) const { // Can only access valid pairs assert(1 <= n && n <= getSize()); return substitution[n-1].ran; } inline void SubstitutionBlock::decrementSize(void) { assert(getSize() > 0); const size_t new_size = getSize() - 1; tag = (tag & ~TopSBMask) | (new_size << 12); } inline void SubstitutionBlock::setDomain(const size_t n, Object *dom) { assert(sizeof(Object *) == sizeof(heapobject)); // Can only set valid pairs // assert(1 <= n && n <= getSize()); // assert(dom->isObjectVariable()); substitution[n-1].dom = OBJECT_CAST(ObjectVariable*, dom); } inline void SubstitutionBlock::setRange(const size_t n, Object *ran) { assert(sizeof(Object *) == sizeof(heapobject)); // Can only set valid pairs // assert(1 <= n && n <= getSize()); substitution[n-1].ran = ran; } inline void SubstitutionBlock::setSubstitutionPair(const size_t n, Object *dom, Object *ran) { assert(sizeof(Object *) == sizeof(heapobject)); // Can only set valid pairs assert(1 <= n && n <= getSize()); assert(dom->isObjectVariable()); substitution[n-1].dom = OBJECT_CAST(ObjectVariable*, dom); substitution[n-1].ran = ran; } // // Check whether the substitution contains any local object variable on // the first range (or domain) position. If it is the case, it means that // all the other ranges (or domains) are local object variables as well. // inline bool SubstitutionBlock::containsLocal(void) const { assert(getSize() > 0); return getDomain(1)->isLocalObjectVariable() || getRange(1)->isLocalObjectVariable(); } #ifdef QP_DEBUG inline void SubstitutionBlock::printMe(AtomTable& atoms, bool all) { std::cerr << "[" << std::hex << (wordptr) this << " : " << tag << std::dec << "] SubstitutionBlock: "; if (isInvertible()) { std::cerr << "(invertible) "; } std::cerr << " size = " << getSize() << " " << endl; for (size_t i = 1; i <= getSize(); i++) { std::cerr << "dom: [ "; getDomain(i)->printMe_dispatch(atoms, all); std::cerr << " ] "; std::cerr << "ran: [ "; getRange(i)->printMe_dispatch(atoms, all); std::cerr << " ] "; } } #endif inline bool Reference::isCollected(void) const { return (tag & FlagCollected) == FlagCollected; } inline void Reference::setCollectedFlag(void) { tag = tag | FlagCollected; } inline void Reference::unsetCollectedFlag(void) { tag = tag & ~FlagCollected; } inline bool Reference::isPerm(void) const { return (tag & FlagPerm) == FlagPerm; } inline void Reference::setPermFlag(void) { tag = tag | FlagPerm; } inline Object *Reference::getReference(void) const { assert(sizeof(Object *) == sizeof(heapobject)); return (Object*)(info[0]); } inline void Reference::setReference(Object *plobj) { assert(sizeof(Object *) == sizeof(heapobject)); info[0] = (heapobject)plobj; } inline bool Reference::hasExtraInfo(void) const { return tag & FlagExtraInfo; } inline void Reference::setExtraInfo(void) { tag |= FlagExtraInfo; } inline Atom * Reference::getName(void) const { assert(sizeof(Object *) == sizeof(heapobject)); if(hasExtraInfo()) { return OBJECT_CAST(Atom *, (Object*)(info[1])); } else { return NULL; } } inline heapobject* Reference::getNameAddress(void) { assert(sizeof(Object *) == sizeof(heapobject)); // Only a valid operation if Reference has extra information assert(hasExtraInfo()); return &info[1]; } inline void Reference::setName(Object* name) { assert(name->isAtom()); assert(hasExtraInfo()); info[1] = (heapobject)name; } inline Object *Reference::getDelays(void) const { assert(sizeof(Object *) == sizeof(heapobject)); if (hasExtraInfo()) { return (Object*)(info[2]); } else { return AtomTable::nil; } } inline void Reference::setDelays(Object *delays) { assert(sizeof(Object *) == sizeof(heapobject)); assert(hasExtraInfo()); assert(delays->isList() || delays->isVariable()); info[2] = (heapobject)delays; } inline heapobject* Reference::getDelaysAddress(void) { assert(hasExtraInfo()); return &info[2]; } ////////////////////////////////////////////////////////////////////// // Inline functions for the Variable class inline size_t Variable::size(void) const { return size(hasExtraInfo()); } ////////////////////////////////////////////////////////////////////// // Inline functions for the (abstract) Reference class inline void Variable::freeze(void) { tag = (tag & ~TypeTagMask) | VarOtherTag | FlagTemperature; } inline bool Variable::isFrozen(void) { return (tag & FlagTemperature) != 0; } inline void Variable::thaw(void) { if ((tag & FlagExtraInfo) != 0) tag = (tag & ~FlagTemperature); else if ((tag & FlagOccurs) == 0) tag = (tag & ~(TypeTagMask | FlagTemperature)) | VarTag; else tag = (tag & ~(TypeTagMask | FlagTemperature)) | VarOCTag; } inline bool Variable::isThawed(void) { return (tag & FlagTemperature) == 0; } inline bool Variable::isOccursChecked(void) const { return (tag & FlagOccurs) != 0; } inline void Variable::setOccursCheck(void) { assert(isVariable()); tag = tag | FlagOccurs | VarOCTag; } inline void Variable::setOccursCheckOther(void) { assert((tag & TypeTagMask) == VarOtherTag); tag = tag | FlagOccurs; } inline size_t Variable::size(bool has_extra_info) { return sizeof(Variable) / BYTES_PER_WORD + (has_extra_info ? 3 : 0); } inline bool Variable::isLifeSet(void) const { return ((tag & 0xffff0000) != 0); } inline u_int Variable::getLife(void) const { return (tag >> 16); } inline void Variable::setLife(u_int i) { assert(i != 0); tag |= i << 16; } inline void Variable::copyTag(Object* other) { assert(hasExtraInfo()); assert(other->isVariable()); assert(!OBJECT_CAST(Variable*, other)->hasExtraInfo()); tag |= (other->getTag() & ~TypeTagMask); } inline heapobject Variable::getID(void) const { return info[3]; } inline void Variable::setID(heapobject v) { info[3] = v; } #ifdef QP_DEBUG inline void Variable::printMe(AtomTable& atoms, bool all) { std::cerr << "[" << std::hex << (wordptr) this << std::dec << "] Variable: "; if (isFrozen()) { std::cerr << "(frozen) "; } if (isOccursChecked()) { std::cerr << "(occurs checked) "; } if (getReference() != (Object *) this) { std::cerr << "<" <ref: [ "; getReference()->printMe_dispatch(atoms, all); std::cerr << " ] "; } else { std::cerr << "(unbound)"; if (hasExtraInfo()) { std::cerr << "Name {"; getName()->printMe_dispatch(atoms, all); if (all) { std::cerr << "} Delays {"; getDelays()->printMe_dispatch(atoms, false); } std::cerr << "}"; } } } #endif ////////////////////////////////////////////////////////////////////// // Inline functions for the ObjectVariable class inline Object *ObjectVariable::getDistinctness(void) const { assert(sizeof(Object *) == sizeof(heapobject)); assert(hasExtraInfo()); return (Object*)(info[3]); } ////////////////////////////////////////////////////////////////////// // Inline functions for the (abstract) Reference class inline void ObjectVariable::freeze(void) { tag = (tag & ~FlagTemperature) | FlagTemperature; } inline bool ObjectVariable::isFrozen(void) { return (tag & FlagTemperature) == FlagTemperature; } inline void ObjectVariable::thaw(void) { tag = (tag & ~FlagTemperature); } inline bool ObjectVariable::isThawed(void) { return (tag & FlagTemperature) == 0; } inline heapobject* ObjectVariable::getDistinctnessAddress(void) { assert(sizeof(Object *) == sizeof(heapobject)); assert(hasExtraInfo()); return &info[3]; } inline void ObjectVariable::setDistinctness(Object *distinctness) { assert(sizeof(Object *) == sizeof(heapobject)); assert(hasExtraInfo()); assert(distinctness->isList() || distinctness->isVariable()); info[3] = (heapobject)distinctness; } inline size_t ObjectVariable::size(void) const { return size(hasExtraInfo()); } inline size_t ObjectVariable::size(bool has_extra_info) { return sizeof(ObjectVariable) / BYTES_PER_WORD + (has_extra_info ? 3 : 0); } inline void ObjectVariable::makeLocalObjectVariable(void) { tag |= ObjectVariable::FlagLocal; } ///////////////////////////////////////////////////////// // Other methods inline qint64 Object::getInteger(void) { assert(isShort() || isLong()); if (isShort()) { return OBJECT_CAST(Short *, this)->getValue(); } else { return OBJECT_CAST(Long *, this)->getValue(); } } inline double Object::getDouble(void) { assert(isDouble()); return OBJECT_CAST(Double *, this)->getValue(); } #ifdef QP_DEBUG inline void ObjectVariable::printMe(AtomTable& atoms, bool all) { std::cerr << "[" << std::hex << (wordptr) this << std::dec << "] ObjVar: "; if (isFrozen()) { std::cerr << "(frozen) "; } if (getReference() != OBJECT_CAST(const Object*, this)) { std::cerr << "ref: [ "; getReference()->printMe_dispatch(atoms, all); std::cerr << " ] "; } else { std::cerr << "(unbound)"; if (hasExtraInfo()) { std::cerr << "Name {"; getName()->printMe_dispatch(atoms, all); std::cerr << "} Delays {"; if (all) { getDelays()->printMe_dispatch(atoms, false); std::cerr << "} Distinctness {"; getDistinctness()->printMe_dispatch(atoms, false); } std::cerr << "}"; } } } #endif // QP_DEBUG // // variableDereference() follows the (ob)variable-reference chain from // an object -- iteratively, not recursively -- and returns the object // at the end of the (ob)variable chain. // //inline Object* Object* Object::variableDereference() { Object* o = this; // // Ensure we're not about to dereference a NULL pointer // assert(o != NULL); #ifdef QP_DEBUG if (!o->check_object()) cerr << "object error " << hex << (wordlong)o << " -> " << (wordlong)(*((heapobject*)o)) << dec << endl; assert(o->check_object()); #endif while ((o->getTag() & Object::DerefMask) == 0) { // // While still a (ob)variable, hence referring to something else, // move to what it's referring to // Object* n = OBJECT_CAST(Reference*, o)->getReference(); assert(n != NULL); if ( n == o ) { return o; // An unbound (ob)variable } o = n; } return o; } inline bool Object::inList(Object* o) { for (Object* l = this; l->isCons(); l = OBJECT_CAST(Cons*, l)->getTail()->variableDereference()) { if (o == OBJECT_CAST(Cons*, l)->getHead()->variableDereference()) { return true; } } return false; } // // Equal constant. // inline bool Object::equalConstants(Object* const2) { assert(this->isConstant()); assert(const2->isConstant()); if (this == const2) return true; if (isAtom()) return false; if (getTag() != const2->getTag()) return false; size_t s = size_dispatch(); heapobject* ptr1 = storage(); heapobject* ptr2 = const2->storage(); for (size_t i = 1; i < s; i++) { if (*ptr1 != *ptr2) return false; ptr1++; ptr2++; } return true; } inline bool Object::equalUninterp(Object* const2) { assert(isNumber() || isString()); if (this == const2) return true; if (getTag() != const2->getTag()) return false; size_t s = size_dispatch(); heapobject* ptr1 = storage(); heapobject* ptr2 = const2->storage(); for (size_t i = 1; i < s; i++) { if (*ptr1 != *ptr2) return false; ptr1++; ptr2++; } return true; } // function for GC (threading - Jonker's algorithm // assumes that what p points at is a pointer inline void threadGC(heapobject* p) { assert(p != NULL); heapobject* tmp = (heapobject*)(*p); assert(*tmp != 0); *p = *tmp; *tmp = (heapobject)p; } #ifdef __MINGW32__ #define bzero(ptr,size) memset (ptr, 0, size); #endif static const int bitsPerWord = 8*sizeof(u_int); class GCBits { private: int size; u_int* bits; static const u_int bitMask = (u_int)-1; public: GCBits(int s) { assert(s > 0); size = s / bitsPerWord; bits = new u_int[size]; bzero(bits, size*sizeof(u_int)); } ~GCBits() { delete [] bits; } void set(int i) { assert(i >= 0); assert((i / bitsPerWord) < size); bits[i / bitsPerWord] |= 1 << (i % bitsPerWord); } void setWord(int i, u_int v) { assert(i >= 0); assert(i < size); bits[i] = v; } bool isSet(int i) { assert(i >= 0); assert((i / bitsPerWord) < size); return ((bits[i / bitsPerWord] & (1 << (i % bitsPerWord))) != 0); } u_int* getBitsPtr() { return bits; } }; class ObjectsStack { private: Object** top; Object** base; Object** high; public: ObjectsStack(size_t size) { base = new Object*[size]; top = base; high = base + size; } ~ObjectsStack() { delete [] base; } void push(Object* ho) { assert(top < high - 1); *top = ho; top++; } #ifdef QP_DEBUG bool atEnd() { return top == (high-1); } #endif Object* pop() { assert(top > base); top--; return *top; } Object** getTop() const { return top; } void setTop(Object** newtop) { top = newtop; } void reset() { top = base; } }; //#endif // HEAP_H #endif // OBJECTS_H_INLINE