Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4680 right-hear 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 LispPtr;
38
 
39
/** \class LispPtrArray is similar to LispPtr, but implements an array
40
 *  of pointers to objects.
41
 */
42
typedef CArrayGrower > 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  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 
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 
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(this); LISPASSERT(pT);
181
    LispObject * pObject = NEW WithExtraInfo(*static_cast(this), aData);
182
    return pObject;
183
  }
184
};
185
 
186
template 
187
inline ObjectHelper::~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