Ruby,Python,C#: readline history fixes. Ruby include path.
[jackhill/mal.git] / cs / types.cs
1 using System;
2 using System.Collections.Generic;
3 using Mal;
4
5 namespace Mal {
6 public class types {
7 //
8 // Exceptiosn/Errors
9 //
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
19 // Thrown by throw function
20 public class MalException : MalThrowable {
21 MalVal value;
22 //string Message;
23 public MalException(MalVal value) {
24 this.value = value;
25 }
26 public MalException(string value) :base(value) {
27 this.value = new MalString(value);
28 }
29 public MalVal getValue() { return value; }
30 }
31
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 {
42 if (a is MalInteger) {
43 return ((MalInteger)a).getValue() ==
44 ((MalInteger)b).getValue();
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
67
68 public abstract class MalVal {
69 MalVal meta = Nil;
70 public virtual MalVal copy() {
71 return (MalVal)this.MemberwiseClone();
72 }
73
74 // Default is just to call regular toString()
75 public virtual string ToString(bool print_readably) {
76 return this.ToString();
77 }
78 public MalVal getMeta() { return meta; }
79 public MalVal setMeta(MalVal m) { meta = m; return this; }
80 public virtual bool list_Q() { return false; }
81 }
82
83 public class MalConstant : MalVal {
84 string value;
85 public MalConstant(string name) { value = name; }
86 public new MalConstant copy() { return this; }
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
100 public class MalInteger : MalVal {
101 int value;
102 public MalInteger(int v) { value = v; }
103 public new MalInteger copy() { return this; }
104
105 public int getValue() { return value; }
106 public override string ToString() {
107 return value.ToString();
108 }
109 public override string ToString(bool print_readably) {
110 return value.ToString();
111 }
112 public static MalConstant operator <(MalInteger a, MalInteger b) {
113 return a.getValue() < b.getValue() ? True : False;
114 }
115 public static MalConstant operator <=(MalInteger a, MalInteger b) {
116 return a.getValue() <= b.getValue() ? True : False;
117 }
118 public static MalConstant operator >(MalInteger a, MalInteger b) {
119 return a.getValue() > b.getValue() ? True : False;
120 }
121 public static MalConstant operator >=(MalInteger a, MalInteger b) {
122 return a.getValue() >= b.getValue() ? True : False;
123 }
124 public static MalInteger operator +(MalInteger a, MalInteger b) {
125 return new MalInteger(a.getValue() + b.getValue());
126 }
127 public static MalInteger operator -(MalInteger a, MalInteger b) {
128 return new MalInteger(a.getValue() - b.getValue());
129 }
130 public static MalInteger operator *(MalInteger a, MalInteger b) {
131 return new MalInteger(a.getValue() * b.getValue());
132 }
133 public static MalInteger operator /(MalInteger a, MalInteger b) {
134 return new MalInteger(a.getValue() / b.getValue());
135 }
136 }
137
138 public class MalSymbol : MalVal {
139 string value;
140 public MalSymbol(string v) { value = v; }
141 public new MalSymbol copy() { return this; }
142
143 public string getName() { return value; }
144 public override string ToString() {
145 return value;
146 }
147 public override string ToString(bool print_readably) {
148 return value;
149 }
150 }
151
152 public class MalString : MalVal {
153 string value;
154 public MalString(string v) { value = v; }
155 public new MalString copy() { return this; }
156
157 public string getValue() { return value; }
158 public override string ToString() {
159 return "\"" + value + "\"";
160 }
161 public override string ToString(bool print_readably) {
162 if (print_readably) {
163 return "\"" + value.Replace("\\", "\\\\")
164 .Replace("\"", "\\\"")
165 .Replace("\n", "\\n") + "\"";
166 } else {
167 return value;
168 }
169 }
170 }
171
172
173
174 public class MalList : MalVal {
175 public string start = "(", end = ")";
176 List<MalVal> value;
177 public MalList() {
178 value = new List<MalVal>();
179 }
180 public MalList(List<MalVal> val) {
181 value = val;
182 }
183 public MalList(params MalVal[] mvs) {
184 value = new List<MalVal>();
185 conj_BANG(mvs);
186 }
187
188 public List<MalVal> getValue() { return value; }
189 public override bool list_Q() { return true; }
190
191 public override string ToString() {
192 return start + printer.join(value, " ", true) + end;
193 }
194 public override string ToString(bool print_readably) {
195 return start + printer.join(value, " ", print_readably) + end;
196 }
197
198 public MalList conj_BANG(params MalVal[] mvs) {
199 for (int i = 0; i < mvs.Length; i++) {
200 value.Add(mvs[i]);
201 }
202 return this;
203 }
204
205 public int size() { return value.Count; }
206 public MalVal nth(int idx) {
207 return value.Count > 0 ? value[idx] : Nil;
208 }
209 public MalVal this[int idx] {
210 get { return value.Count > 0 ? value[idx] : Nil; }
211 }
212 public MalList rest() {
213 if (size() > 0) {
214 return new MalList(value.GetRange(1, value.Count-1));
215 } else {
216 return new MalList();
217 }
218 }
219 public virtual MalList slice(int start) {
220 return new MalList(value.GetRange(start, value.Count-start));
221 }
222 public virtual MalList slice(int start, int end) {
223 return new MalList(value.GetRange(start, end-start));
224 }
225
226 }
227
228 public class MalVector : MalList {
229 // Same implementation except for instantiation methods
230 public MalVector() :base() {
231 start = "[";
232 end = "]";
233 }
234 public MalVector(List<MalVal> val)
235 :base(val) {
236 start = "[";
237 end = "]";
238 }
239
240 public override bool list_Q() { return false; }
241
242 public override MalList slice(int start, int end) {
243 var val = this.getValue();
244 return new MalVector(val.GetRange(start, val.Count-start));
245 }
246 }
247
248 public class MalHashMap : MalVal {
249 Dictionary<string, MalVal> value;
250 public MalHashMap(Dictionary<string, MalVal> val) {
251 value = val;
252 }
253 public MalHashMap(MalList lst) {
254 value = new Dictionary<String, MalVal>();
255 assoc_BANG(lst);
256 }
257 public new MalHashMap copy() {
258 var new_self = (MalHashMap)this.MemberwiseClone();
259 new_self.value = new Dictionary<string, MalVal>(value);
260 return new_self;
261 }
262
263 public Dictionary<string, MalVal> getValue() { return value; }
264
265 public override string ToString() {
266 return "{" + printer.join(value, " ", true) + "}";
267 }
268 public override string ToString(bool print_readably) {
269 return "{" + printer.join(value, " ", print_readably) + "}";
270 }
271
272 public MalHashMap assoc_BANG(MalList lst) {
273 for (int i=0; i<lst.size(); i+=2) {
274 value[((MalString)lst[i]).getValue()] = lst[i+1];
275 }
276 return this;
277 }
278
279 public MalHashMap dissoc_BANG(MalList lst) {
280 for (int i=0; i<lst.size(); i++) {
281 value.Remove(((MalString)lst[i]).getValue());
282 }
283 return this;
284 }
285 }
286
287 public class MalAtom : MalVal {
288 MalVal value;
289 public MalAtom(MalVal value) { this.value = value; }
290 //public MalAtom copy() { return new MalAtom(value); }
291 public MalVal getValue() { return value; }
292 public MalVal setValue(MalVal value) { return this.value = value; }
293 public override string ToString() {
294 return "(atom " + printer._pr_str(value, true) + ")";
295 }
296 public override string ToString(Boolean print_readably) {
297 return "(atom " + printer._pr_str(value, print_readably) + ")";
298 }
299 }
300
301 public class MalFunction : MalVal {
302 Func<MalList, MalVal> fn = null;
303 MalVal ast = null;
304 Mal.env.Env env = null;
305 MalList fparams;
306 bool macro = false;
307 public MalFunction(Func<MalList, MalVal> fn) {
308 this.fn = fn;
309 }
310 public MalFunction(MalVal ast, Mal.env.Env env, MalList fparams,
311 Func<MalList, MalVal> fn) {
312 this.fn = fn;
313 this.ast = ast;
314 this.env = env;
315 this.fparams = fparams;
316 }
317
318 public override string ToString() {
319 if (ast != null) {
320 return "<fn* " + Mal.printer._pr_str(fparams,true) +
321 " " + Mal.printer._pr_str(ast, true) + ">";
322 } else {
323 return "<builtin_function " + fn.ToString() + ">";
324 }
325 }
326
327 public MalVal apply(MalList args) {
328 return fn(args);
329 }
330
331 public MalVal getAst() { return ast; }
332 public Mal.env.Env getEnv() { return env; }
333 public MalList getFParams() { return fparams; }
334 public Mal.env.Env genEnv(MalList args) {
335 return new Mal.env.Env(env, fparams, args);
336 }
337 public bool isMacro() { return macro; }
338 public void setMacro() { macro = true; }
339
340 }
341 }
342 }