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) { | |
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 | } |