Haxe: update README, fix macro eval, add conj.
[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) const = 0;
231 };
232
233 class malHash : public malValue {
234 public:
235 typedef std::map<String, malValuePtr> Map;
236
237 malHash(malValueIter argsBegin, malValueIter argsEnd, bool isEvaluated);
238 malHash(const malHash::Map& map);
239 malHash(const malHash& that, malValuePtr meta)
240 : malValue(meta), m_map(that.m_map), m_isEvaluated(that.m_isEvaluated) { }
241
242 malValuePtr assoc(malValueIter argsBegin, malValueIter argsEnd) const;
243 malValuePtr dissoc(malValueIter argsBegin, malValueIter argsEnd) const;
244 bool contains(malValuePtr key) const;
245 malValuePtr eval(malEnvPtr env);
246 malValuePtr get(malValuePtr key) const;
247 malValuePtr keys() const;
248 malValuePtr values() const;
249
250 virtual String print(bool readably) const;
251
252 virtual bool doIsEqualTo(const malValue* rhs) const;
253
254 WITH_META(malHash);
255
256 private:
257 const Map m_map;
258 const bool m_isEvaluated;
259 };
260
261 class malBuiltIn : public malApplicable {
262 public:
263 typedef malValuePtr (ApplyFunc)(const String& name,
264 malValueIter argsBegin,
265 malValueIter argsEnd);
266
267 malBuiltIn(const String& name, ApplyFunc* handler)
268 : m_name(name), m_handler(handler) { }
269
270 malBuiltIn(const malBuiltIn& that, malValuePtr meta)
271 : malApplicable(meta), m_name(that.m_name), m_handler(that.m_handler) { }
272
273 virtual malValuePtr apply(malValueIter argsBegin,
274 malValueIter argsEnd) const;
275
276 virtual String print(bool readably) const {
277 return STRF("#builtin-function(%s)", m_name.c_str());
278 }
279
280 virtual bool doIsEqualTo(const malValue* rhs) const {
281 return this == rhs; // these are singletons
282 }
283
284 String name() const { return m_name; }
285
286 WITH_META(malBuiltIn);
287
288 private:
289 const String m_name;
290 ApplyFunc* m_handler;
291 };
292
293 class malLambda : public malApplicable {
294 public:
295 malLambda(const StringVec& bindings, malValuePtr body, malEnvPtr env);
296 malLambda(const malLambda& that, malValuePtr meta);
297 malLambda(const malLambda& that, bool isMacro);
298
299 virtual malValuePtr apply(malValueIter argsBegin,
300 malValueIter argsEnd) const;
301
302 malValuePtr getBody() const { return m_body; }
303 malEnvPtr makeEnv(malValueIter argsBegin, malValueIter argsEnd) const;
304
305 virtual bool doIsEqualTo(const malValue* rhs) const {
306 return this == rhs; // do we need to do a deep inspection?
307 }
308
309 virtual String print(bool readably) const {
310 return STRF("#user-%s(%p)", m_isMacro ? "macro" : "function", this);
311 }
312
313 bool isMacro() const { return m_isMacro; }
314
315 virtual malValuePtr doWithMeta(malValuePtr meta) const;
316
317 private:
318 const StringVec m_bindings;
319 const malValuePtr m_body;
320 const malEnvPtr m_env;
321 const bool m_isMacro;
322 };
323
324 class malAtom : public malValue {
325 public:
326 malAtom(malValuePtr value) : m_value(value) { }
327 malAtom(const malAtom& that, malValuePtr meta)
328 : malValue(meta), m_value(that.m_value) { }
329
330 virtual bool doIsEqualTo(const malValue* rhs) const {
331 return this->m_value->isEqualTo(rhs);
332 }
333
334 virtual String print(bool readably) const {
335 return "(atom " + m_value->print(readably) + ")";
336 };
337
338 malValuePtr deref() const { return m_value; }
339
340 malValuePtr reset(malValuePtr value) { return m_value = value; }
341
342 WITH_META(malAtom);
343
344 private:
345 malValuePtr m_value;
346 };
347
348 namespace mal {
349 malValuePtr atom(malValuePtr value);
350 malValuePtr boolean(bool value);
351 malValuePtr builtin(const String& name, malBuiltIn::ApplyFunc handler);
352 malValuePtr falseValue();
353 malValuePtr hash(malValueIter argsBegin, malValueIter argsEnd,
354 bool isEvaluated);
355 malValuePtr hash(const malHash::Map& map);
356 malValuePtr integer(int value);
357 malValuePtr integer(const String& token);
358 malValuePtr keyword(const String& token);
359 malValuePtr lambda(const StringVec&, malValuePtr, malEnvPtr);
360 malValuePtr list(malValueVec* items);
361 malValuePtr list(malValueIter begin, malValueIter end);
362 malValuePtr list(malValuePtr a);
363 malValuePtr list(malValuePtr a, malValuePtr b);
364 malValuePtr list(malValuePtr a, malValuePtr b, malValuePtr c);
365 malValuePtr macro(const malLambda& lambda);
366 malValuePtr nilValue();
367 malValuePtr string(const String& token);
368 malValuePtr symbol(const String& token);
369 malValuePtr trueValue();
370 malValuePtr vector(malValueVec* items);
371 malValuePtr vector(malValueIter begin, malValueIter end);
372 };
373
374 #endif // INCLUDE_TYPES_H