OCaml: put macro flag in metadata rather than special type field
[jackhill/mal.git] / cs / types.cs
CommitLineData
53beaa0a
JM
1using System;
2using System.Collections.Generic;
3using Mal;
4
5namespace Mal {
6 public class types {
afdf531e
JM
7 //
8 // Exceptiosn/Errors
9 //
53beaa0a
JM
10 public class MalThrowable : Exception {
11 public MalThrowable() : base() { }
12 public MalThrowable(string msg) : base(msg) { }
13 }
14 public class MalError : MalThrowable {
15 public MalError(string msg) :base(msg) { }
16 }
17 public class MalContinue : MalThrowable { }
18
b18969c0
JM
19 // Thrown by throw function
20 public class MalException : MalThrowable {
21 MalVal value;
8cb5cda4 22 //string Message;
b18969c0
JM
23 public MalException(MalVal value) {
24 this.value = value;
25 }
8cb5cda4 26 public MalException(string value) :base(value) {
b18969c0
JM
27 this.value = new MalString(value);
28 }
29 public MalVal getValue() { return value; }
30 }
31
afdf531e
JM
32 //
33 // General functions
34 //
35
36 public static bool _equal_Q(MalVal a, MalVal b) {
37 Type ota = a.GetType(), otb = b.GetType();
38 if (!((ota == otb) ||
39 (a is MalList && b is MalList))) {
40 return false;
41 } else {
c3b508af
JM
42 if (a is MalInt) {
43 return ((MalInt)a).getValue() ==
44 ((MalInt)b).getValue();
afdf531e
JM
45 } else if (a is MalSymbol) {
46 return ((MalSymbol)a).getName() ==
47 ((MalSymbol)b).getName();
48 } else if (a is MalString) {
49 return ((MalString)a).getValue() ==
50 ((MalString)b).getValue();
51 } else if (a is MalList) {
52 if (((MalList)a).size() != ((MalList)b).size()) {
53 return false;
54 }
55 for (int i=0; i<((MalList)a).size(); i++) {
56 if (! _equal_Q(((MalList)a)[i], ((MalList)b)[i])) {
57 return false;
58 }
59 }
60 return true;
61 } else {
62 return a == b;
63 }
64 }
65 }
66
53beaa0a
JM
67
68 public abstract class MalVal {
17ae845e
JM
69 MalVal meta = Nil;
70 public virtual MalVal copy() {
71 return (MalVal)this.MemberwiseClone();
72 }
73
53beaa0a 74 // Default is just to call regular toString()
b56c49a1 75 public virtual string ToString(bool print_readably) {
96115d4f 76 return this.ToString();
b56c49a1 77 }
17ae845e
JM
78 public MalVal getMeta() { return meta; }
79 public MalVal setMeta(MalVal m) { meta = m; return this; }
b56c49a1 80 public virtual bool list_Q() { return false; }
53beaa0a
JM
81 }
82
83 public class MalConstant : MalVal {
84 string value;
85 public MalConstant(string name) { value = name; }
17ae845e 86 public new MalConstant copy() { return this; }
53beaa0a
JM
87
88 public override string ToString() {
89 return value;
90 }
91 public override string ToString(bool print_readably) {
92 return value;
93 }
94 }
95
96 static public MalConstant Nil = new MalConstant("nil");
97 static public MalConstant True = new MalConstant("true");
98 static public MalConstant False = new MalConstant("false");
99
c3b508af 100 public class MalInt : MalVal {
aaba2493
JM
101 Int64 value;
102 public MalInt(Int64 v) { value = v; }
c3b508af 103 public new MalInt copy() { return this; }
53beaa0a 104
aaba2493 105 public Int64 getValue() { return value; }
53beaa0a
JM
106 public override string ToString() {
107 return value.ToString();
108 }
109 public override string ToString(bool print_readably) {
110 return value.ToString();
111 }
c3b508af 112 public static MalConstant operator <(MalInt a, MalInt b) {
afdf531e 113 return a.getValue() < b.getValue() ? True : False;
53beaa0a 114 }
c3b508af 115 public static MalConstant operator <=(MalInt a, MalInt b) {
afdf531e 116 return a.getValue() <= b.getValue() ? True : False;
53beaa0a 117 }
c3b508af 118 public static MalConstant operator >(MalInt a, MalInt b) {
afdf531e 119 return a.getValue() > b.getValue() ? True : False;
53beaa0a 120 }
c3b508af 121 public static MalConstant operator >=(MalInt a, MalInt b) {
afdf531e 122 return a.getValue() >= b.getValue() ? True : False;
53beaa0a 123 }
c3b508af
JM
124 public static MalInt operator +(MalInt a, MalInt b) {
125 return new MalInt(a.getValue() + b.getValue());
53beaa0a 126 }
c3b508af
JM
127 public static MalInt operator -(MalInt a, MalInt b) {
128 return new MalInt(a.getValue() - b.getValue());
53beaa0a 129 }
c3b508af
JM
130 public static MalInt operator *(MalInt a, MalInt b) {
131 return new MalInt(a.getValue() * b.getValue());
53beaa0a 132 }
c3b508af
JM
133 public static MalInt operator /(MalInt a, MalInt b) {
134 return new MalInt(a.getValue() / b.getValue());
53beaa0a
JM
135 }
136 }
137
138 public class MalSymbol : MalVal {
139 string value;
140 public MalSymbol(string v) { value = v; }
c3b508af 141 public MalSymbol(MalString v) { value = v.getValue(); }
17ae845e 142 public new MalSymbol copy() { return this; }
53beaa0a
JM
143
144 public string getName() { return value; }
145 public override string ToString() {
146 return value;
147 }
148 public override string ToString(bool print_readably) {
149 return value;
150 }
151 }
152
153 public class MalString : MalVal {
154 string value;
155 public MalString(string v) { value = v; }
17ae845e 156 public new MalString copy() { return this; }
53beaa0a
JM
157
158 public string getValue() { return value; }
159 public override string ToString() {
160 return "\"" + value + "\"";
161 }
162 public override string ToString(bool print_readably) {
b8ee29b2
JM
163 if (value.Length > 0 && value[0] == '\u029e') {
164 return ":" + value.Substring(1);
165 } else if (print_readably) {
afdf531e
JM
166 return "\"" + value.Replace("\\", "\\\\")
167 .Replace("\"", "\\\"")
168 .Replace("\n", "\\n") + "\"";
53beaa0a
JM
169 } else {
170 return value;
171 }
172 }
173 }
174
175
176
177 public class MalList : MalVal {
178 public string start = "(", end = ")";
179 List<MalVal> value;
180 public MalList() {
181 value = new List<MalVal>();
182 }
183 public MalList(List<MalVal> val) {
184 value = val;
185 }
186 public MalList(params MalVal[] mvs) {
5a159ae7 187 value = new List<MalVal>();
53beaa0a
JM
188 conj_BANG(mvs);
189 }
190
53beaa0a 191 public List<MalVal> getValue() { return value; }
b56c49a1 192 public override bool list_Q() { return true; }
53beaa0a
JM
193
194 public override string ToString() {
195 return start + printer.join(value, " ", true) + end;
196 }
197 public override string ToString(bool print_readably) {
198 return start + printer.join(value, " ", print_readably) + end;
199 }
200
201 public MalList conj_BANG(params MalVal[] mvs) {
202 for (int i = 0; i < mvs.Length; i++) {
203 value.Add(mvs[i]);
204 }
205 return this;
206 }
b56c49a1
JM
207
208 public int size() { return value.Count; }
faee4d12 209 public MalVal nth(int idx) {
aaba2493 210 return value.Count > idx ? value[idx] : Nil;
faee4d12 211 }
afdf531e 212 public MalVal this[int idx] {
aaba2493 213 get { return value.Count > idx ? value[idx] : Nil; }
afdf531e 214 }
b18969c0 215 public MalList rest() {
b56c49a1
JM
216 if (size() > 0) {
217 return new MalList(value.GetRange(1, value.Count-1));
218 } else {
219 return new MalList();
220 }
221 }
b18969c0
JM
222 public virtual MalList slice(int start) {
223 return new MalList(value.GetRange(start, value.Count-start));
224 }
225 public virtual MalList slice(int start, int end) {
226 return new MalList(value.GetRange(start, end-start));
227 }
228
53beaa0a
JM
229 }
230
231 public class MalVector : MalList {
232 // Same implementation except for instantiation methods
233 public MalVector() :base() {
234 start = "[";
235 end = "]";
236 }
237 public MalVector(List<MalVal> val)
238 :base(val) {
239 start = "[";
240 end = "]";
241 }
53beaa0a 242
b56c49a1 243 public override bool list_Q() { return false; }
b18969c0
JM
244
245 public override MalList slice(int start, int end) {
246 var val = this.getValue();
247 return new MalVector(val.GetRange(start, val.Count-start));
248 }
53beaa0a
JM
249 }
250
251 public class MalHashMap : MalVal {
252 Dictionary<string, MalVal> value;
253 public MalHashMap(Dictionary<string, MalVal> val) {
254 value = val;
255 }
256 public MalHashMap(MalList lst) {
257 value = new Dictionary<String, MalVal>();
faee4d12 258 assoc_BANG(lst);
53beaa0a 259 }
17ae845e 260 public new MalHashMap copy() {
faee4d12
JM
261 var new_self = (MalHashMap)this.MemberwiseClone();
262 new_self.value = new Dictionary<string, MalVal>(value);
263 return new_self;
53beaa0a
JM
264 }
265
b56c49a1
JM
266 public Dictionary<string, MalVal> getValue() { return value; }
267
53beaa0a
JM
268 public override string ToString() {
269 return "{" + printer.join(value, " ", true) + "}";
270 }
afdf531e 271 public override string ToString(bool print_readably) {
53beaa0a
JM
272 return "{" + printer.join(value, " ", print_readably) + "}";
273 }
274
faee4d12
JM
275 public MalHashMap assoc_BANG(MalList lst) {
276 for (int i=0; i<lst.size(); i+=2) {
277 value[((MalString)lst[i]).getValue()] = lst[i+1];
278 }
279 return this;
53beaa0a 280 }
faee4d12
JM
281
282 public MalHashMap dissoc_BANG(MalList lst) {
283 for (int i=0; i<lst.size(); i++) {
284 value.Remove(((MalString)lst[i]).getValue());
53beaa0a
JM
285 }
286 return this;
287 }
288 }
289
17ae845e
JM
290 public class MalAtom : MalVal {
291 MalVal value;
292 public MalAtom(MalVal value) { this.value = value; }
293 //public MalAtom copy() { return new MalAtom(value); }
294 public MalVal getValue() { return value; }
295 public MalVal setValue(MalVal value) { return this.value = value; }
296 public override string ToString() {
297 return "(atom " + printer._pr_str(value, true) + ")";
298 }
299 public override string ToString(Boolean print_readably) {
300 return "(atom " + printer._pr_str(value, print_readably) + ")";
301 }
302 }
303
c3b508af 304 public class MalFunc : MalVal {
96115d4f
JM
305 Func<MalList, MalVal> fn = null;
306 MalVal ast = null;
307 Mal.env.Env env = null;
308 MalList fparams;
faa20db2 309 bool macro = false;
c3b508af 310 public MalFunc(Func<MalList, MalVal> fn) {
96115d4f
JM
311 this.fn = fn;
312 }
c3b508af 313 public MalFunc(MalVal ast, Mal.env.Env env, MalList fparams,
96115d4f
JM
314 Func<MalList, MalVal> fn) {
315 this.fn = fn;
316 this.ast = ast;
317 this.env = env;
318 this.fparams = fparams;
319 }
320
321 public override string ToString() {
322 if (ast != null) {
323 return "<fn* " + Mal.printer._pr_str(fparams,true) +
324 " " + Mal.printer._pr_str(ast, true) + ">";
325 } else {
326 return "<builtin_function " + fn.ToString() + ">";
327 }
afdf531e 328 }
b56c49a1 329
afdf531e 330 public MalVal apply(MalList args) {
96115d4f
JM
331 return fn(args);
332 }
333
334 public MalVal getAst() { return ast; }
335 public Mal.env.Env getEnv() { return env; }
336 public MalList getFParams() { return fparams; }
337 public Mal.env.Env genEnv(MalList args) {
338 return new Mal.env.Env(env, fparams, args);
afdf531e 339 }
faa20db2
JM
340 public bool isMacro() { return macro; }
341 public void setMacro() { macro = true; }
342
afdf531e 343 }
53beaa0a
JM
344 }
345}