Makefile: fix recursive make of compiled impls.
[jackhill/mal.git] / cpp / Types.h
1 #ifndef INCLUDE_TYPES_H
2 #define INCLUDE_TYPES_H
3
4 #include "MAL.h"
5
6 #include <exception>
7 #include <map>
8
9 class malEmptyInputException : public std::exception { };
10
11 class malValue : public RefCounted {
12 public:
13 malValue() {
14 TRACE_OBJECT("Creating malValue %p\n", this);
15 }
16 malValue(malValuePtr meta) : m_meta(meta) {
17 TRACE_OBJECT("Creating malValue %p\n", this);
18 }
19 virtual ~malValue() {
20 TRACE_OBJECT("Destroying malValue %p\n", this);
21 }
22
23 malValuePtr withMeta(malValuePtr meta) const;
24 virtual malValuePtr doWithMeta(malValuePtr meta) const = 0;
25 malValuePtr meta() const;
26
27 bool isTrue() const;
28
29 bool isEqualTo(const malValue* rhs) const;
30
31 virtual malValuePtr eval(malEnvPtr env);
32
33 virtual String print(bool readably) const = 0;
34
35 protected:
36 virtual bool doIsEqualTo(const malValue* rhs) const = 0;
37
38 malValuePtr m_meta;
39 };
40
41 template<class T>
42 T* value_cast(malValuePtr obj, const char* typeName) {
43 T* dest = dynamic_cast<T*>(obj.ptr());
44 MAL_CHECK(dest != NULL, "%s is not a %s",
45 obj->print(true).c_str(), typeName);
46 return dest;
47 }
48
49 #define VALUE_CAST(Type, Value) value_cast<Type>(Value, #Type)
50 #define DYNAMIC_CAST(Type, Value) (dynamic_cast<Type*>((Value).ptr()))
51 #define STATIC_CAST(Type, Value) (static_cast<Type*>((Value).ptr()))
52
53 #define WITH_META(Type) \
54 virtual malValuePtr doWithMeta(malValuePtr meta) const { \
55 return new Type(*this, meta); \
56 } \
57
58 class malConstant : public malValue {
59 public:
60 malConstant(String name) : m_name(name) { }
61 malConstant(const malConstant& that, malValuePtr meta)
62 : malValue(meta), m_name(that.m_name) { }
63
64 virtual String print(bool readably) const { return m_name; }
65
66 virtual bool doIsEqualTo(const malValue* rhs) const {
67 return this == rhs; // these are singletons
68 }
69
70 WITH_META(malConstant);
71
72 private:
73 const String m_name;
74 };
75
76 class malInteger : public malValue {
77 public:
78 malInteger(int value) : m_value(value) { }
79 malInteger(const malInteger& that, malValuePtr meta)
80 : malValue(meta), m_value(that.m_value) { }
81
82 virtual String print(bool readably) const {
83 return std::to_string(m_value);
84 }
85
86 int value() const { return m_value; }
87
88 virtual bool doIsEqualTo(const malValue* rhs) const {
89 return m_value == static_cast<const malInteger*>(rhs)->m_value;
90 }
91
92 WITH_META(malInteger);
93
94 private:
95 const int m_value;
96 };
97
98 class malStringBase : public malValue {
99 public:
100 malStringBase(const String& token)
101 : m_value(token) { }
102 malStringBase(const malStringBase& that, malValuePtr meta)
103 : malValue(meta), m_value(that.value()) { }
104
105 virtual String print(bool readably) const { return m_value; }
106
107 String value() const { return m_value; }
108
109 private:
110 const String m_value;
111 };
112
113 class malString : public malStringBase {
114 public:
115 malString(const String& token)
116 : malStringBase(token) { }
117 malString(const malString& that, malValuePtr meta)
118 : malStringBase(that, meta) { }
119
120 virtual String print(bool readably) const;
121
122 String escapedValue() const;
123
124 virtual bool doIsEqualTo(const malValue* rhs) const {
125 return value() == static_cast<const malString*>(rhs)->value();
126 }
127
128 WITH_META(malString);
129 };
130
131 class malKeyword : public malStringBase {
132 public:
133 malKeyword(const String& token)
134 : malStringBase(token) { }
135 malKeyword(const malKeyword& that, malValuePtr meta)
136 : malStringBase(that, meta) { }
137
138 virtual bool doIsEqualTo(const malValue* rhs) const {
139 return value() == static_cast<const malKeyword*>(rhs)->value();
140 }
141
142 WITH_META(malKeyword);
143 };
144
145 class malSymbol : public malStringBase {
146 public:
147 malSymbol(const String& token)
148 : malStringBase(token) { }
149 malSymbol(const malSymbol& that, malValuePtr meta)
150 : malStringBase(that, meta) { }
151
152 virtual malValuePtr eval(malEnvPtr env);
153
154 virtual bool doIsEqualTo(const malValue* rhs) const {
155 return value() == static_cast<const malSymbol*>(rhs)->value();
156 }
157
158 WITH_META(malSymbol);
159 };
160
161 class malSequence : public malValue {
162 public:
163 malSequence(malValueVec* items);
164 malSequence(malValueIter begin, malValueIter end);
165 malSequence(const malSequence& that, malValuePtr meta);
166 virtual ~malSequence();
167
168 virtual String print(bool readably) const;
169
170 malValueVec* evalItems(malEnvPtr env) const;
171 int count() const { return m_items->size(); }
172 bool isEmpty() const { return m_items->empty(); }
173 malValuePtr item(int index) const { return (*m_items)[index]; }
174
175 malValueIter begin() const { return m_items->begin(); }
176 malValueIter end() const { return m_items->end(); }
177
178 virtual bool doIsEqualTo(const malValue* rhs) const;
179
180 virtual malValuePtr conj(malValueIter argsBegin,
181 malValueIter argsEnd) const = 0;
182
183 malValuePtr first() const;
184 virtual malValuePtr rest() const;
185
186 private:
187 malValueVec* const m_items;
188 };
189
190 class malList : public malSequence {
191 public:
192 malList(malValueVec* items) : malSequence(items) { }
193 malList(malValueIter begin, malValueIter end)
194 : malSequence(begin, end) { }
195 malList(const malList& that, malValuePtr meta)
196 : malSequence(that, meta) { }
197
198 virtual String print(bool readably) const;
199 virtual malValuePtr eval(malEnvPtr env);
200
201 virtual malValuePtr conj(malValueIter argsBegin,
202 malValueIter argsEnd) const;
203
204 WITH_META(malList);
205 };
206
207 class malVector : public malSequence {
208 public:
209 malVector(malValueVec* items) : malSequence(items) { }
210 malVector(malValueIter begin, malValueIter end)
211 : malSequence(begin, end) { }
212 malVector(const malVector& that, malValuePtr meta)
213 : malSequence(that, meta) { }
214
215 virtual malValuePtr eval(malEnvPtr env);
216 virtual String print(bool readably) const;
217
218 virtual malValuePtr conj(malValueIter argsBegin,
219 malValueIter argsEnd) const;
220
221 WITH_META(malVector);
222 };
223
224 class malApplicable : public malValue {
225 public:
226 malApplicable() { }
227 malApplicable(malValuePtr meta) : malValue(meta) { }
228
229 virtual malValuePtr apply(malValueIter argsBegin,
230 malValueIter argsEnd,
231 malEnvPtr env) const = 0;
232 };
233
234 class malHash : public malValue {
235 public:
236 typedef std::map<String, malValuePtr> Map;
237
238 malHash(malValueIter argsBegin, malValueIter argsEnd, bool isEvaluated);
239 malHash(const malHash::Map& map);
240 malHash(const malHash& that, malValuePtr meta)
241 : malValue(meta), m_map(that.m_map), m_isEvaluated(that.m_isEvaluated) { }
242
243 malValuePtr assoc(malValueIter argsBegin, malValueIter argsEnd) const;
244 malValuePtr dissoc(malValueIter argsBegin, malValueIter argsEnd) const;
245 bool contains(malValuePtr key) const;
246 malValuePtr eval(malEnvPtr env);
247 malValuePtr get(malValuePtr key) const;
248 malValuePtr keys() const;
249 malValuePtr values() const;
250
251 virtual String print(bool readably) const;
252
253 virtual bool doIsEqualTo(const malValue* rhs) const;
254
255 WITH_META(malHash);
256
257 private:
258 const Map m_map;
259 const bool m_isEvaluated;
260 };
261
262 class malBuiltIn : public malApplicable {
263 public:
264 typedef malValuePtr (ApplyFunc)(const String& name,
265 malValueIter argsBegin,
266 malValueIter argsEnd,
267 malEnvPtr env);
268
269 malBuiltIn(const String& name, ApplyFunc* handler)
270 : m_name(name), m_handler(handler) { }
271
272 malBuiltIn(const malBuiltIn& that, malValuePtr meta)
273 : malApplicable(meta), m_name(that.m_name), m_handler(that.m_handler) { }
274
275 virtual malValuePtr apply(malValueIter argsBegin,
276 malValueIter argsEnd,
277 malEnvPtr env) const;
278
279 virtual String print(bool readably) const {
280 return STRF("#builtin-function(%s)", m_name.c_str());
281 }
282
283 virtual bool doIsEqualTo(const malValue* rhs) const {
284 return this == rhs; // these are singletons
285 }
286
287 String name() const { return m_name; }
288
289 WITH_META(malBuiltIn);
290
291 private:
292 const String m_name;
293 ApplyFunc* m_handler;
294 };
295
296 class malLambda : public malApplicable {
297 public:
298 malLambda(const StringVec& bindings, malValuePtr body, malEnvPtr env);
299 malLambda(const malLambda& that, malValuePtr meta);
300 malLambda(const malLambda& that, bool isMacro);
301
302 virtual malValuePtr apply(malValueIter argsBegin,
303 malValueIter argsEnd,
304 malEnvPtr env) const;
305
306 malValuePtr getBody() const { return m_body; }
307 malEnvPtr makeEnv(malValueIter argsBegin, malValueIter argsEnd) const;
308
309 virtual bool doIsEqualTo(const malValue* rhs) const {
310 return this == rhs; // do we need to do a deep inspection?
311 }
312
313 virtual String print(bool readably) const {
314 return STRF("#user-%s(%p)", m_isMacro ? "macro" : "function", this);
315 }
316
317 bool isMacro() const { return m_isMacro; }
318
319 virtual malValuePtr doWithMeta(malValuePtr meta) const;
320
321 private:
322 const StringVec m_bindings;
323 const malValuePtr m_body;
324 const malEnvPtr m_env;
325 const bool m_isMacro;
326 };
327
328 class malAtom : public malValue {
329 public:
330 malAtom(malValuePtr value) : m_value(value) { }
331 malAtom(const malAtom& that, malValuePtr meta)
332 : malValue(meta), m_value(that.m_value) { }
333
334 virtual bool doIsEqualTo(const malValue* rhs) const {
335 return this->m_value->isEqualTo(rhs);
336 }
337
338 virtual String print(bool readably) const {
339 return "(atom " + m_value->print(readably) + ")";
340 };
341
342 malValuePtr deref() const { return m_value; }
343
344 malValuePtr reset(malValuePtr value) { return m_value = value; }
345
346 WITH_META(malAtom);
347
348 private:
349 malValuePtr m_value;
350 };
351
352 namespace mal {
353 malValuePtr atom(malValuePtr value);
354 malValuePtr boolean(bool value);
355 malValuePtr builtin(const String& name, malBuiltIn::ApplyFunc handler);
356 malValuePtr falseValue();
357 malValuePtr hash(malValueIter argsBegin, malValueIter argsEnd,
358 bool isEvaluated);
359 malValuePtr hash(const malHash::Map& map);
360 malValuePtr integer(int value);
361 malValuePtr integer(const String& token);
362 malValuePtr keyword(const String& token);
363 malValuePtr lambda(const StringVec&, malValuePtr, malEnvPtr);
364 malValuePtr list(malValueVec* items);
365 malValuePtr list(malValueIter begin, malValueIter end);
366 malValuePtr list(malValuePtr a);
367 malValuePtr list(malValuePtr a, malValuePtr b);
368 malValuePtr list(malValuePtr a, malValuePtr b, malValuePtr c);
369 malValuePtr macro(const malLambda& lambda);
370 malValuePtr nilValue();
371 malValuePtr string(const String& token);
372 malValuePtr symbol(const String& token);
373 malValuePtr trueValue();
374 malValuePtr vector(malValueVec* items);
375 malValuePtr vector(malValueIter begin, malValueIter end);
376 };
377
378 #endif // INCLUDE_TYPES_H