Commit | Line | Data |
---|---|---|
53beaa0a JM |
1 | using System; |
2 | using System.Collections.Generic; | |
3 | using Mal; | |
4 | ||
5 | namespace 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) { | |
163 | if (print_readably) { | |
afdf531e JM |
164 | return "\"" + value.Replace("\\", "\\\\") |
165 | .Replace("\"", "\\\"") | |
166 | .Replace("\n", "\\n") + "\""; | |
53beaa0a JM |
167 | } else { |
168 | return value; | |
169 | } | |
170 | } | |
171 | } | |
172 | ||
173 | ||
174 | ||
175 | public class MalList : MalVal { | |
176 | public string start = "(", end = ")"; | |
177 | List<MalVal> value; | |
178 | public MalList() { | |
179 | value = new List<MalVal>(); | |
180 | } | |
181 | public MalList(List<MalVal> val) { | |
182 | value = val; | |
183 | } | |
184 | public MalList(params MalVal[] mvs) { | |
5a159ae7 | 185 | value = new List<MalVal>(); |
53beaa0a JM |
186 | conj_BANG(mvs); |
187 | } | |
188 | ||
53beaa0a | 189 | public List<MalVal> getValue() { return value; } |
b56c49a1 | 190 | public override bool list_Q() { return true; } |
53beaa0a JM |
191 | |
192 | public override string ToString() { | |
193 | return start + printer.join(value, " ", true) + end; | |
194 | } | |
195 | public override string ToString(bool print_readably) { | |
196 | return start + printer.join(value, " ", print_readably) + end; | |
197 | } | |
198 | ||
199 | public MalList conj_BANG(params MalVal[] mvs) { | |
200 | for (int i = 0; i < mvs.Length; i++) { | |
201 | value.Add(mvs[i]); | |
202 | } | |
203 | return this; | |
204 | } | |
b56c49a1 JM |
205 | |
206 | public int size() { return value.Count; } | |
faee4d12 | 207 | public MalVal nth(int idx) { |
aaba2493 | 208 | return value.Count > idx ? value[idx] : Nil; |
faee4d12 | 209 | } |
afdf531e | 210 | public MalVal this[int idx] { |
aaba2493 | 211 | get { return value.Count > idx ? value[idx] : Nil; } |
afdf531e | 212 | } |
b18969c0 | 213 | public MalList rest() { |
b56c49a1 JM |
214 | if (size() > 0) { |
215 | return new MalList(value.GetRange(1, value.Count-1)); | |
216 | } else { | |
217 | return new MalList(); | |
218 | } | |
219 | } | |
b18969c0 JM |
220 | public virtual MalList slice(int start) { |
221 | return new MalList(value.GetRange(start, value.Count-start)); | |
222 | } | |
223 | public virtual MalList slice(int start, int end) { | |
224 | return new MalList(value.GetRange(start, end-start)); | |
225 | } | |
226 | ||
53beaa0a JM |
227 | } |
228 | ||
229 | public class MalVector : MalList { | |
230 | // Same implementation except for instantiation methods | |
231 | public MalVector() :base() { | |
232 | start = "["; | |
233 | end = "]"; | |
234 | } | |
235 | public MalVector(List<MalVal> val) | |
236 | :base(val) { | |
237 | start = "["; | |
238 | end = "]"; | |
239 | } | |
53beaa0a | 240 | |
b56c49a1 | 241 | public override bool list_Q() { return false; } |
b18969c0 JM |
242 | |
243 | public override MalList slice(int start, int end) { | |
244 | var val = this.getValue(); | |
245 | return new MalVector(val.GetRange(start, val.Count-start)); | |
246 | } | |
53beaa0a JM |
247 | } |
248 | ||
249 | public class MalHashMap : MalVal { | |
250 | Dictionary<string, MalVal> value; | |
251 | public MalHashMap(Dictionary<string, MalVal> val) { | |
252 | value = val; | |
253 | } | |
254 | public MalHashMap(MalList lst) { | |
255 | value = new Dictionary<String, MalVal>(); | |
faee4d12 | 256 | assoc_BANG(lst); |
53beaa0a | 257 | } |
17ae845e | 258 | public new MalHashMap copy() { |
faee4d12 JM |
259 | var new_self = (MalHashMap)this.MemberwiseClone(); |
260 | new_self.value = new Dictionary<string, MalVal>(value); | |
261 | return new_self; | |
53beaa0a JM |
262 | } |
263 | ||
b56c49a1 JM |
264 | public Dictionary<string, MalVal> getValue() { return value; } |
265 | ||
53beaa0a JM |
266 | public override string ToString() { |
267 | return "{" + printer.join(value, " ", true) + "}"; | |
268 | } | |
afdf531e | 269 | public override string ToString(bool print_readably) { |
53beaa0a JM |
270 | return "{" + printer.join(value, " ", print_readably) + "}"; |
271 | } | |
272 | ||
faee4d12 JM |
273 | public MalHashMap assoc_BANG(MalList lst) { |
274 | for (int i=0; i<lst.size(); i+=2) { | |
275 | value[((MalString)lst[i]).getValue()] = lst[i+1]; | |
276 | } | |
277 | return this; | |
53beaa0a | 278 | } |
faee4d12 JM |
279 | |
280 | public MalHashMap dissoc_BANG(MalList lst) { | |
281 | for (int i=0; i<lst.size(); i++) { | |
282 | value.Remove(((MalString)lst[i]).getValue()); | |
53beaa0a JM |
283 | } |
284 | return this; | |
285 | } | |
286 | } | |
287 | ||
17ae845e JM |
288 | public class MalAtom : MalVal { |
289 | MalVal value; | |
290 | public MalAtom(MalVal value) { this.value = value; } | |
291 | //public MalAtom copy() { return new MalAtom(value); } | |
292 | public MalVal getValue() { return value; } | |
293 | public MalVal setValue(MalVal value) { return this.value = value; } | |
294 | public override string ToString() { | |
295 | return "(atom " + printer._pr_str(value, true) + ")"; | |
296 | } | |
297 | public override string ToString(Boolean print_readably) { | |
298 | return "(atom " + printer._pr_str(value, print_readably) + ")"; | |
299 | } | |
300 | } | |
301 | ||
c3b508af | 302 | public class MalFunc : MalVal { |
96115d4f JM |
303 | Func<MalList, MalVal> fn = null; |
304 | MalVal ast = null; | |
305 | Mal.env.Env env = null; | |
306 | MalList fparams; | |
faa20db2 | 307 | bool macro = false; |
c3b508af | 308 | public MalFunc(Func<MalList, MalVal> fn) { |
96115d4f JM |
309 | this.fn = fn; |
310 | } | |
c3b508af | 311 | public MalFunc(MalVal ast, Mal.env.Env env, MalList fparams, |
96115d4f JM |
312 | Func<MalList, MalVal> fn) { |
313 | this.fn = fn; | |
314 | this.ast = ast; | |
315 | this.env = env; | |
316 | this.fparams = fparams; | |
317 | } | |
318 | ||
319 | public override string ToString() { | |
320 | if (ast != null) { | |
321 | return "<fn* " + Mal.printer._pr_str(fparams,true) + | |
322 | " " + Mal.printer._pr_str(ast, true) + ">"; | |
323 | } else { | |
324 | return "<builtin_function " + fn.ToString() + ">"; | |
325 | } | |
afdf531e | 326 | } |
b56c49a1 | 327 | |
afdf531e | 328 | public MalVal apply(MalList args) { |
96115d4f JM |
329 | return fn(args); |
330 | } | |
331 | ||
332 | public MalVal getAst() { return ast; } | |
333 | public Mal.env.Env getEnv() { return env; } | |
334 | public MalList getFParams() { return fparams; } | |
335 | public Mal.env.Env genEnv(MalList args) { | |
336 | return new Mal.env.Env(env, fparams, args); | |
afdf531e | 337 | } |
faa20db2 JM |
338 | public bool isMacro() { return macro; } |
339 | public void setMacro() { macro = true; } | |
340 | ||
afdf531e | 341 | } |
53beaa0a JM |
342 | } |
343 | } |