Merge branch 'master' of git+ssh://ares@repo.or.cz/srv/git/lispp
[lispp.git] / LispObj.h
blob138367afbcb8f5d9f1fc58e178f328b32444347e
2 #ifndef H_LISP_OBJ
3 #define H_LISP_OBJ
5 #include <cassert>
6 #include <ostream>
7 #include <vector>
8 #include <string>
10 namespace Lisp
13 class Obj;
14 class NIL;
15 class Cons;
16 class String;
17 class Fixnum;
18 class Floatnum;
19 class Symbol;
20 class Package;
21 class Func;
24 class Obj
26 public:
28 enum eObjectType
30 eBaseObj = 0,
31 eNullObj,
32 eStringObj,
33 eConsObj,
34 eFixnumObj,
35 eFloatnumObj,
36 eSymbolObj,
37 ePackageObj,
38 eFunctionObj
41 /* api any lispobj must implement */
42 virtual eObjectType getObjectType() const = 0;
44 /* create a fresh one */
45 virtual Obj* create(void) const = 0;
47 /* make a copy */
48 virtual Obj* clone(void) const = 0;
50 /* print to stream */
51 virtual void print(std::ostream& out) const = 0;
53 /* check a string to see if it represents this kind of object */
54 //virtual bool identify(std::string in) const = 0;
56 /* compare by value */
57 virtual bool operator==(const Obj* other) = 0;
59 inline bool hasRef() {
60 return (references_ != 0);
63 inline void incRef() {
64 references_++;
67 inline void decRef() {
68 assert(references_ != 0);
69 references_--;
73 protected:
74 Obj() {};
75 Obj(const Obj& other) {};
76 Obj& operator=(const Obj& other) {};
78 std::size_t references_;
80 }; /* class Obj */
82 typedef long FixnumValue;
83 typedef double FloatnumValue;
84 typedef std::string StringValue;
86 class Env;
88 /** The lisp environment: an associative container that associates symbols
89 with their properties **/
91 class Env {
93 private:
95 /** parent namespace **/
96 Env *parent_;
98 // to do -- this needs to be a hash table or something
99 // with faster lookup.
100 typedef std::pair<Obj*,Obj*> Binding;
102 std::vector<Binding> env_;
105 * detect if a symbol is bound
107 class IsBound
109 private:
110 Obj* bound_;
111 public:
112 IsBound(Obj* bound) :
113 bound_(bound)
116 bool operator()(const Env::Binding& binding) {
117 return (bound_ == binding.first);
119 }; /* class IsBound */
121 class DecBindingRef
123 public:
124 DecBindingRef() {};
125 void operator()(const Env::Binding& binding) {
126 binding.first->decRef();
127 binding.second->decRef();
128 if (!binding.first->hasRef())
129 delete binding.first;
130 if (!binding.second->hasRef())
131 delete binding.second;
136 static Env *root_environment;
137 static Env *current_environment;
139 public:
142 Env() :
143 parent_(NULL)
145 root_environment = this;
146 current_environment = this;
149 Env(Env* parent) :
150 parent_(parent)
154 std::size_t add(Obj* obj)
156 Binding bind(obj, NULL);
157 obj->incRef();
158 std::size_t result = env_.size();
159 env_.push_back(bind);
160 return result;
163 // test if object has been bound by value
164 bool isBound(Obj* obj)
166 std::vector<Binding>::iterator result = std::find_if(env_.begin(), env_.end(), IsBound(obj));
167 if ((result == env_.end()) && (parent_ != NULL))
168 return parent_->isBound(obj);
169 else
170 return (result != env_.end());
174 //! return pointer to bound object that has same value
175 Obj* bound(Obj* obj)
177 std::vector<Binding>::iterator result;
178 result = std::find_if(env_.begin(), env_.end(), IsBound(obj));
179 if (result == env_.end()) {
180 if (parent_ != NULL)
182 return parent_->bound(obj);
183 } else
184 return NULL;
185 } else {
186 return result->first;
190 // return pointer to bound value
191 Obj* boundto(Obj* obj)
193 std::vector<Binding>::iterator result;
194 result = std::find_if(env_.begin(), env_.end(), IsBound(obj));
195 if (result == env_.end())
196 if (parent_ != NULL)
197 return parent_->boundto(obj);
198 else
199 return NULL;
200 else
201 return result->second;
205 std::size_t bind(Obj *value, Obj* binding)
207 Obj *bindee = bound(value);
208 if (bindee == NULL)
209 bindee = value;
210 Binding bind(bindee, binding);
211 bindee->incRef();
212 binding->incRef();
213 std::size_t result = env_.size();
214 env_.push_back(bind);
215 return result;
218 void unbind(Obj *value)
220 std::vector<Binding>::iterator binder;
221 binder = std::find_if(env_.begin(), env_.end(), IsBound(value));
222 if (binder == env_.end()) {
223 if (parent_ != NULL)
224 parent_->unbind(value);
225 else
226 return;
228 else {
229 DecBindingRef finalizer;
230 finalizer(*binder);
231 env_.erase(binder);
233 return;
236 Env *child(void)
238 current_environment = new Env(this);
239 return current_environment;
242 virtual ~Env()
244 DecBindingRef finalizer;
245 for_each(env_.begin(), env_.end(), finalizer);
247 assert(this == Env::current_environment);
248 Env::current_environment = parent_;
256 #endif