C#: add step7_quote
[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 public MalException(MalVal value) {
23 this.value = value;
24 }
25 public MalException(string value) {
26 this.value = new MalString(value);
27 }
28 public MalVal getValue() { return value; }
29 }
30
31 //
32 // General functions
33 //
34
35 public static bool _equal_Q(MalVal a, MalVal b) {
36 Type ota = a.GetType(), otb = b.GetType();
37 if (!((ota == otb) ||
38 (a is MalList && b is MalList))) {
39 return false;
40 } else {
41 if (a is MalInteger) {
42 return ((MalInteger)a).getValue() ==
43 ((MalInteger)b).getValue();
44 } else if (a is MalSymbol) {
45 return ((MalSymbol)a).getName() ==
46 ((MalSymbol)b).getName();
47 } else if (a is MalString) {
48 return ((MalString)a).getValue() ==
49 ((MalString)b).getValue();
50 } else if (a is MalList) {
51 if (((MalList)a).size() != ((MalList)b).size()) {
52 return false;
53 }
54 for (int i=0; i<((MalList)a).size(); i++) {
55 if (! _equal_Q(((MalList)a)[i], ((MalList)b)[i])) {
56 return false;
57 }
58 }
59 return true;
60 } else {
61 return a == b;
62 }
63 }
64 }
65
66
67 public abstract class MalVal {
68 // Default is just to call regular toString()
69 public virtual string ToString(bool print_readably) {
70 return this.ToString();
71 }
72 public virtual bool list_Q() { return false; }
73 }
74
75 public class MalConstant : MalVal {
76 string value;
77 public MalConstant(string name) { value = name; }
78 public MalConstant copy() { return this; }
79
80 public override string ToString() {
81 return value;
82 }
83 public override string ToString(bool print_readably) {
84 return value;
85 }
86 }
87
88 static public MalConstant Nil = new MalConstant("nil");
89 static public MalConstant True = new MalConstant("true");
90 static public MalConstant False = new MalConstant("false");
91
92 public class MalInteger : MalVal {
93 int value;
94 public MalInteger(int v) { value = v; }
95 public MalInteger copy() { return this; }
96
97 public int getValue() { return value; }
98 public override string ToString() {
99 return value.ToString();
100 }
101 public override string ToString(bool print_readably) {
102 return value.ToString();
103 }
104 public static MalConstant operator <(MalInteger a, MalInteger b) {
105 return a.getValue() < b.getValue() ? True : False;
106 }
107 public static MalConstant operator <=(MalInteger a, MalInteger b) {
108 return a.getValue() <= b.getValue() ? True : False;
109 }
110 public static MalConstant operator >(MalInteger a, MalInteger b) {
111 return a.getValue() > b.getValue() ? True : False;
112 }
113 public static MalConstant operator >=(MalInteger a, MalInteger b) {
114 return a.getValue() >= b.getValue() ? True : False;
115 }
116 public static MalInteger operator +(MalInteger a, MalInteger b) {
117 return new MalInteger(a.getValue() + b.getValue());
118 }
119 public static MalInteger operator -(MalInteger a, MalInteger b) {
120 return new MalInteger(a.getValue() - b.getValue());
121 }
122 public static MalInteger operator *(MalInteger a, MalInteger b) {
123 return new MalInteger(a.getValue() * b.getValue());
124 }
125 public static MalInteger operator /(MalInteger a, MalInteger b) {
126 return new MalInteger(a.getValue() / b.getValue());
127 }
128 }
129
130 public class MalSymbol : MalVal {
131 string value;
132 public MalSymbol(string v) { value = v; }
133 public MalSymbol copy() { return this; }
134
135 public string getName() { return value; }
136 public override string ToString() {
137 return value;
138 }
139 public override string ToString(bool print_readably) {
140 return value;
141 }
142 }
143
144 public class MalString : MalVal {
145 string value;
146 public MalString(string v) { value = v; }
147 public MalString copy() { return this; }
148
149 public string getValue() { return value; }
150 public override string ToString() {
151 return "\"" + value + "\"";
152 }
153 public override string ToString(bool print_readably) {
154 if (print_readably) {
155 return "\"" + value.Replace("\\", "\\\\")
156 .Replace("\"", "\\\"")
157 .Replace("\n", "\\n") + "\"";
158 } else {
159 return value;
160 }
161 }
162 }
163
164
165
166 public class MalList : MalVal {
167 public string start = "(", end = ")";
168 List<MalVal> value;
169 public MalList() {
170 value = new List<MalVal>();
171 }
172 public MalList(List<MalVal> val) {
173 value = val;
174 }
175 public MalList(params MalVal[] mvs) {
176 value = new List<MalVal>();
177 conj_BANG(mvs);
178 }
179
180 public MalList copy() {
181 return (MalList)this.MemberwiseClone();
182 }
183
184 public List<MalVal> getValue() { return value; }
185 public override bool list_Q() { return true; }
186
187 public override string ToString() {
188 return start + printer.join(value, " ", true) + end;
189 }
190 public override string ToString(bool print_readably) {
191 return start + printer.join(value, " ", print_readably) + end;
192 }
193
194 public MalList conj_BANG(params MalVal[] mvs) {
195 for (int i = 0; i < mvs.Length; i++) {
196 value.Add(mvs[i]);
197 }
198 return this;
199 }
200
201 public int size() { return value.Count; }
202 public MalVal nth(int idx) { return value[idx]; }
203 public MalVal this[int idx] {
204 get { return value[idx]; }
205 }
206 public MalList rest() {
207 if (size() > 0) {
208 return new MalList(value.GetRange(1, value.Count-1));
209 } else {
210 return new MalList();
211 }
212 }
213 public virtual MalList slice(int start) {
214 return new MalList(value.GetRange(start, value.Count-start));
215 }
216 public virtual MalList slice(int start, int end) {
217 return new MalList(value.GetRange(start, end-start));
218 }
219
220 }
221
222 public class MalVector : MalList {
223 // Same implementation except for instantiation methods
224 public MalVector() :base() {
225 start = "[";
226 end = "]";
227 }
228 public MalVector(List<MalVal> val)
229 :base(val) {
230 start = "[";
231 end = "]";
232 }
233 /*
234 public MalVector(MalVal[] mvs) : base(mvs.ToArray()) {
235 start = "[";
236 end = "]";
237 }
238 */
239 public new MalVector copy() {
240 return (MalVector)this.MemberwiseClone();
241 }
242
243 public override bool list_Q() { return false; }
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 }
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>();
258 assoc_BANG(lst.getValue().ToArray());
259 }
260 /*
261 public MalHashMap(params MalVal[] mvs) {
262 value = new Dictionary<String, MalVal>();
263 assoc_BANG(mvs);
264 }
265 */
266 public MalHashMap copy() {
267 return (MalHashMap)this.MemberwiseClone();
268 }
269
270 public Dictionary<string, MalVal> getValue() { return value; }
271
272 public override string ToString() {
273 return "{" + printer.join(value, " ", true) + "}";
274 }
275 public override string ToString(bool print_readably) {
276 return "{" + printer.join(value, " ", print_readably) + "}";
277 }
278
279 /*
280 public Set _entries() {
281 return value.entrySet();
282 }
283 */
284
285 public MalHashMap assoc_BANG(params MalVal[] mvs) {
286 for (int i=0; i<mvs.Length; i+=2) {
287 value.Add(((MalString)mvs[i]).getValue(), mvs[i+1]);
288 }
289 return this;
290 }
291 }
292
293 public class MalFunction : MalVal {
294 Func<MalList, MalVal> fn = null;
295 MalVal ast = null;
296 Mal.env.Env env = null;
297 MalList fparams;
298 public MalFunction(Func<MalList, MalVal> fn) {
299 this.fn = fn;
300 }
301 public MalFunction(MalVal ast, Mal.env.Env env, MalList fparams,
302 Func<MalList, MalVal> fn) {
303 this.fn = fn;
304 this.ast = ast;
305 this.env = env;
306 this.fparams = fparams;
307 }
308
309 public override string ToString() {
310 if (ast != null) {
311 return "<fn* " + Mal.printer._pr_str(fparams,true) +
312 " " + Mal.printer._pr_str(ast, true) + ">";
313 } else {
314 return "<builtin_function " + fn.ToString() + ">";
315 }
316 }
317
318 public MalVal apply(MalList args) {
319 return fn(args);
320 }
321
322 public MalVal getAst() { return ast; }
323 public Mal.env.Env getEnv() { return env; }
324 public MalList getFParams() { return fparams; }
325 public Mal.env.Env genEnv(MalList args) {
326 return new Mal.env.Env(env, fparams, args);
327 }
328 }
329 }
330 }