Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /** \file lispobject.h
  2.  *  Implementation of basic LispObject, which is the base class for
  3.  *  anything that can be put in a linked list.
  4.  *
  5.  * class LispObject. This class implements one lisp object, which is a
  6.  * abstract class containing reference counting and a next pointer.
  7.  * derive from this to implement specific types of list elements.
  8.  * The local class LispPtr implements automatic garbage collection
  9.  * through reference counting.
  10.  *
  11.  */
  12.  
  13. #ifndef __lispobject_h__
  14. #define __lispobject_h__
  15.  
  16. #include "yacasbase.h"
  17. #include "refcount.h"
  18. #include "lispstring.h"
  19. #include "genericobject.h"
  20.  
  21. #ifdef YACAS_DEBUG
  22. #define DBG_(xxx) xxx
  23. #else
  24. #define DBG_(xxx) /*xxx*/
  25. #endif
  26.  
  27. class LispObject;
  28. class BigNumber;
  29.  
  30.  
  31. /** class LispPtr. A LispPtr is a smart pointer to a LispObject.
  32.  *  It does the reference counting, and consequent destruction if needed.
  33.  *  LispPtr is used in LispObject as a pointer to the next object; and
  34.  *  LispPtr::GoNext() advances one step in this LispObject::Nixed() chain.
  35.  *  Diverse built-in functions use LispPtr to hold temporary values.
  36.  */
  37. typedef RefPtr<LispObject> LispPtr;
  38.  
  39. /** \class LispPtrArray is similar to LispPtr, but implements an array
  40.  *  of pointers to objects.
  41.  */
  42. typedef CArrayGrower<LispPtr, ArrOpsCustomObj<LispPtr> > LispPtrArray;
  43.  
  44.  
  45. #ifdef YACAS_DEBUG
  46. void IncNrObjects();
  47. void DecNrObjects();
  48. #else
  49. #define IncNrObjects()
  50. #define DecNrObjects()
  51. #endif
  52.  
  53. // Should we DecNrObjects by the delete, or in the destructor?
  54. // Put a DecNrObjects_xxx() macro in both places, and CHOOSE here.
  55. #define DecNrObjects_delete()    DECNROBJECTS_CHOOSE(DecNrObjects(),)
  56. #define DecNrObjects_destructor()  DECNROBJECTS_CHOOSE(,DecNrObjects())
  57. #define DECNROBJECTS_CHOOSE(bydelete,bydestructor) bydestructor
  58.  
  59.  
  60. template <int> struct Undefined;
  61. template <> struct Undefined<1>{};
  62.  
  63.  
  64. /** class LispObject is the base object class that can be put in
  65.  *  linked lists. It either has a pointer to a string, obtained through
  66.  *  String(), or it is a holder for a sublist, obtainable through SubList(),
  67.  *  or it is a generic object, in which case Generic() returns non-NULL.
  68.  *  Only one of these three functions should return a non-NULL value.
  69.  *  It is a reference-counted object. LispPtr handles the reference counting.
  70.  */
  71. class LispObject : public YacasBase
  72. {
  73. public:
  74.   inline LispPtr& Nixed();
  75.  
  76. public: //Derivables
  77.   virtual ~LispObject();
  78.  
  79.   /** Return string representation, or NULL if the object doesn't have one.
  80.    *  the string representation is only relevant if the object is a
  81.    *  simple atom. This method returns NULL by default.
  82.    */
  83.   virtual LispString * String()  { return NULL; }
  84.   /** If this object is a list, return a pointer to it.
  85.    *  Default behaviour is to return NULL.
  86.    */
  87.   virtual LispPtr* SubList()      { return NULL; }
  88.   virtual GenericClass* Generic() { return NULL; }
  89.  
  90.   /** If this is a number, return a BigNumber representation
  91.    */
  92.   virtual BigNumber* Number(LispInt aPrecision) { return NULL; }
  93.  
  94.   virtual LispObject* Copy() = 0;
  95.  
  96.  /** Return a pointer to extra info. This allows for annotating
  97.   *  an object. Returns NULL by default.
  98.   *  LispObject's implementation of this handles almost all derived classes.
  99.   */
  100.   virtual LispObject* ExtraInfo() { return NULL; }
  101.   virtual LispObject* SetExtraInfo(LispObject* aData) = 0;
  102. public:
  103.   LispInt Equal(LispObject& aOther);
  104.   inline LispInt operator==(LispObject& aOther);
  105.   inline LispInt operator!=(LispObject& aOther);
  106.   DBG_( LispChar * iFileName; )
  107.   DBG_( LispInt iLine; )
  108.   inline void SetFileAndLine(LispChar * aFileName, LispInt aLine)
  109.   {
  110.     DBG_( iFileName = aFileName; )
  111.     DBG_( iLine = aLine; )
  112.   }
  113. protected:
  114.   inline LispObject() :
  115. #ifdef YACAS_DEBUG
  116.    iFileName(NULL),iLine(0),
  117. #endif // YACAS_DEBUG
  118.    iNext(),iReferenceCount()
  119.   {
  120.     IncNrObjects();
  121.     DBG_( iFileName = NULL; )
  122.     DBG_( iLine = 0; )
  123.   }
  124.   inline LispObject(const LispObject& other) :
  125. #ifdef YACAS_DEBUG
  126.   iFileName(other.iFileName),iLine(other.iLine),
  127. #endif // YACAS_DEBUG
  128.   iNext(),iReferenceCount()
  129.   {
  130.     IncNrObjects();
  131.   }
  132.  
  133.   inline LispObject& operator=(const LispObject& other)
  134.   {
  135. #ifdef YACAS_DEBUG
  136.     iFileName = other.iFileName;
  137.     iLine     = other.iLine;
  138. #endif // YACAS_DEBUG
  139.     IncNrObjects();
  140.     return *this;
  141.   }
  142.  
  143.  
  144. private:
  145.   LispPtr   iNext;
  146. public:
  147.   ReferenceCount iReferenceCount;
  148. };
  149.  
  150.  
  151. template <class T>
  152. class WithExtraInfo : public T
  153. {
  154. public:
  155.   WithExtraInfo(T& aT, LispObject* aData = 0) : T(aT), iExtraInfo(aData) {}
  156.   WithExtraInfo(const WithExtraInfo& other) : T(other), iExtraInfo(other.iExtraInfo) {}
  157.     virtual LispObject* ExtraInfo() { return iExtraInfo; }
  158.   virtual LispObject* SetExtraInfo(LispObject* aData) { iExtraInfo = aData; return this; }
  159.   virtual LispObject* Copy()
  160.   {
  161.     if (!iExtraInfo.ptr()) return T::Copy();
  162.         return NEW WithExtraInfo(*this, iExtraInfo->Copy());
  163.   }
  164. private:
  165.   LispPtr iExtraInfo;
  166. };
  167.  
  168.  
  169. template <class T, class U = LispObject>
  170. class ObjectHelper : public U
  171. {
  172. protected:
  173.   typedef ObjectHelper ASuper;  // for use by the derived class
  174.   ObjectHelper() {}
  175.   ObjectHelper(const ObjectHelper& other) : U(other) {}
  176.   virtual ~ObjectHelper() = 0;  // so we're abstract
  177.   virtual LispObject* SetExtraInfo(LispObject* aData)
  178.   {
  179.     if (!aData) return this;
  180.     //T * pT = dynamic_cast<T*>(this); LISPASSERT(pT);
  181.     LispObject * pObject = NEW WithExtraInfo<T>(*static_cast<T*>(this), aData);
  182.     return pObject;
  183.   }
  184. };
  185.  
  186. template <typename T, class U>
  187. inline ObjectHelper<T,U>::~ObjectHelper() {}
  188.  
  189.  
  190. /**
  191.  * class LispIterator works almost like LispPtr, but doesn't enforce
  192.  * reference counting, so it should be faster.  Use LispIterator
  193.  * (instead of LispPtr) to traverse a lisp expression non-destructively.
  194.  */
  195. class LispIterator : public YacasBase
  196. {
  197. public:
  198.   // ala TEMPLATE CLASS iterator
  199.   //typedef forward_iterator_tag iterator_category;
  200.   typedef LispPtr    value_type;
  201.   typedef int /*ptrdiff_t*/  difference_type;
  202.   typedef LispPtr*  pointer;
  203.   typedef LispPtr&  reference;
  204. public:
  205.   LispIterator() : _Ptr(0) {}  // construct with null node pointer
  206.   LispIterator(pointer ptr) : _Ptr(ptr) {}  // construct with node pointer
  207.   /*non-standard*/ LispIterator(reference ref) : _Ptr(&ref) {}  // construct with node reference
  208.   reference operator*() const { return (*(_Ptr)); }  // return designated value
  209.   pointer operator->() const { return (_Ptr); }  // return pointer to class object
  210.   inline LispIterator& operator++()  // preincrement
  211.   {
  212.     //precondition: _Ptr != NULL
  213.     LISPASSERT(_Ptr != NULL);
  214.     //expand: _Ptr = _Nextnode(_Ptr);
  215.     LispObject * pObj = _Ptr->operator->();
  216.     _Ptr = pObj ? &(pObj->Nixed()) : NULL;
  217.     return (*this);
  218.   }
  219.   LispIterator operator++(int) { LispIterator _Tmp = *this; ++*this; return (_Tmp); }  // postincrement
  220.   bool operator==(const LispIterator& other) const { return (_Ptr == other._Ptr); }  // test for iterator equality
  221.   bool operator!=(const LispIterator& other) const { return (!(*this == other)); }  // test for iterator inequality
  222.   // The following operators are not used yet, and would need to be tested before used.
  223.   //LispIterator& operator--() { _Ptr = _Prevnode(_Ptr); return (*this); }  // predecrement
  224.   //LispIterator operator--(int) { LispIterator _Tmp = *this; --*this; return (_Tmp); }  // postdecrement
  225. protected:
  226.   pointer _Ptr;  // pointer to node
  227. public:
  228.   inline LispObject* getObj() const { return (*_Ptr).operator->(); }
  229. };
  230.  
  231. #include "lispobject.inl"
  232.  
  233.  
  234. #endif
  235.