3 using System
.Collections
.Generic
;
4 using MalVal
= Mal
.types
.MalVal
;
5 using MalConstant
= Mal
.types
.MalConstant
;
6 using MalInt
= Mal
.types
.MalInt
;
7 using MalSymbol
= Mal
.types
.MalSymbol
;
8 using MalString
= Mal
.types
.MalString
;
9 using MalList
= Mal
.types
.MalList
;
10 using MalVector
= Mal
.types
.MalVector
;
11 using MalHashMap
= Mal
.types
.MalHashMap
;
12 using MalAtom
= Mal
.types
.MalAtom
;
13 using MalFunc
= Mal
.types
.MalFunc
;
17 static MalConstant Nil
= Mal
.types
.Nil
;
18 static MalConstant True
= Mal
.types
.True
;
19 static MalConstant False
= Mal
.types
.False
;
22 static public MalFunc mal_throw
= new MalFunc(
23 a
=> { throw new Mal.types.MalException(a[0]); }
);
26 static MalFunc nil_Q
= new MalFunc(
27 a
=> a
[0] == Nil
? True
: False
);
29 static MalFunc true_Q
= new MalFunc(
30 a
=> a
[0] == True
? True
: False
);
32 static MalFunc false_Q
= new MalFunc(
33 a
=> a
[0] == False
? True
: False
);
35 static MalFunc symbol_Q
= new MalFunc(
36 a
=> a
[0] is MalSymbol
? True
: False
);
38 static MalFunc string_Q
= new MalFunc(
40 if (a
[0] is MalString
) {
41 var s
= ((MalString
)a
[0]).getValue();
42 return (s
.Length
== 0 || s
[0] != '\u029e') ? True
: False
;
48 static MalFunc keyword
= new MalFunc(
50 if (a
[0] is MalString
&&
51 ((MalString
)a
[0]).getValue()[0] == '\u029e') {
54 return new MalString("\u029e" + ((MalString
)a
[0]).getValue());
58 static MalFunc keyword_Q
= new MalFunc(
60 if (a
[0] is MalString
) {
61 var s
= ((MalString
)a
[0]).getValue();
62 return (s
.Length
> 0 && s
[0] == '\u029e') ? True
: False
;
68 static MalFunc number_Q
= new MalFunc(
69 a
=> a
[0] is MalInt
? True
: False
);
71 static MalFunc function_Q
= new MalFunc(
72 a
=> a
[0] is MalFunc
&& !((MalFunc
)a
[0]).isMacro() ? True
: False
);
74 static MalFunc macro_Q
= new MalFunc(
75 a
=> a
[0] is MalFunc
&& ((MalFunc
)a
[0]).isMacro() ? True
: False
);
79 static MalFunc time_ms
= new MalFunc(
80 a
=> new MalInt(DateTime
.Now
.Ticks
/ TimeSpan
.TicksPerMillisecond
));
83 static public MalFunc pr_str
= new MalFunc(
84 a
=> new MalString(printer
._pr_str_args(a
, " ", true)) );
86 static public MalFunc str
= new MalFunc(
87 a
=> new MalString(printer
._pr_str_args(a
, "", false)) );
89 static public MalFunc prn
= new MalFunc(
91 Console
.WriteLine(printer
._pr_str_args(a
, " ", true));
95 static public MalFunc println
= new MalFunc(
97 Console
.WriteLine(printer
._pr_str_args(a
, " ", false));
101 static public MalFunc mal_readline
= new MalFunc(
103 var line
= readline
.Readline(((MalString
)a
[0]).getValue());
104 if (line
== null) { return types.Nil; }
105 else { return new MalString(line); }
108 static public MalFunc read_string
= new MalFunc(
109 a
=> reader
.read_str(((MalString
)a
[0]).getValue()));
111 static public MalFunc slurp
= new MalFunc(
112 a
=> new MalString(File
.ReadAllText(
113 ((MalString
)a
[0]).getValue())));
116 // List/Vector functions
117 static public MalFunc list_Q
= new MalFunc(
118 a
=> a
[0].GetType() == typeof(MalList
) ? True
: False
);
120 static public MalFunc vector_Q
= new MalFunc(
121 a
=> a
[0].GetType() == typeof(MalVector
) ? True
: False
);
124 static public MalFunc hash_map_Q
= new MalFunc(
125 a
=> a
[0].GetType() == typeof(MalHashMap
) ? True
: False
);
127 static MalFunc contains_Q
= new MalFunc(
129 string key
= ((MalString
)a
[1]).getValue();
130 var dict
= ((MalHashMap
)a
[0]).getValue();
131 return dict
.ContainsKey(key
) ? True
: False
;
134 static MalFunc assoc
= new MalFunc(
136 var new_hm
= ((MalHashMap
)a
[0]).copy();
137 return new_hm
.assoc_BANG((MalList
)a
.slice(1));
140 static MalFunc dissoc
= new MalFunc(
142 var new_hm
= ((MalHashMap
)a
[0]).copy();
143 return new_hm
.dissoc_BANG((MalList
)a
.slice(1));
146 static MalFunc
get = new MalFunc(
148 string key
= ((MalString
)a
[1]).getValue();
152 var dict
= ((MalHashMap
)a
[0]).getValue();
153 return dict
.ContainsKey(key
) ? dict
[key
] : Nil
;
157 static MalFunc keys
= new MalFunc(
159 var dict
= ((MalHashMap
)a
[0]).getValue();
160 MalList key_lst
= new MalList();
161 foreach (var key
in dict
.Keys
) {
162 key_lst
.conj_BANG(new MalString(key
));
167 static MalFunc vals
= new MalFunc(
169 var dict
= ((MalHashMap
)a
[0]).getValue();
170 MalList val_lst
= new MalList();
171 foreach (var val
in dict
.Values
) {
172 val_lst
.conj_BANG(val
);
177 // Sequence functions
178 static public MalFunc sequential_Q
= new MalFunc(
179 a
=> a
[0] is MalList
? True
: False
);
181 static MalFunc cons
= new MalFunc(
183 var lst
= new List
<MalVal
>();
185 lst
.AddRange(((MalList
)a
[1]).getValue());
186 return (MalVal
)new MalList(lst
);
189 static MalFunc concat
= new MalFunc(
191 if (a
.size() == 0) { return new MalList(); }
192 var lst
= new List
<MalVal
>();
193 lst
.AddRange(((MalList
)a
[0]).getValue());
194 for(int i
=1; i
<a
.size(); i
++) {
195 lst
.AddRange(((MalList
)a
[i
]).getValue());
197 return (MalVal
)new MalList(lst
);
200 static MalFunc nth
= new MalFunc(
202 var idx
= (int)((MalInt
)a
[1]).getValue();
203 if (idx
< ((MalList
)a
[0]).size()) {
204 return ((MalList
)a
[0])[idx
];
206 throw new Mal
.types
.MalException(
207 "nth: index out of range");
211 static MalFunc first
= new MalFunc(
212 a
=> a
[0] == Nil
? Nil
: ((MalList
)a
[0])[0]);
214 static MalFunc rest
= new MalFunc(
215 a
=> a
[0] == Nil
? new MalList() : ((MalList
)a
[0]).rest());
217 static MalFunc empty_Q
= new MalFunc(
218 a
=> ((MalList
)a
[0]).size() == 0 ? True
: False
);
220 static MalFunc count
= new MalFunc(
224 :new MalInt(((MalList
)a
[0]).size());
227 static MalFunc conj
= new MalFunc(
229 var src_lst
= ((MalList
)a
[0]).getValue();
230 var new_lst
= new List
<MalVal
>();
231 new_lst
.AddRange(src_lst
);
232 if (a
[0] is MalVector
) {
233 for(int i
=1; i
<a
.size(); i
++) {
236 return new MalVector(new_lst
);
238 for(int i
=1; i
<a
.size(); i
++) {
239 new_lst
.Insert(0, a
[i
]);
241 return new MalList(new_lst
);
246 static MalFunc seq
= new MalFunc(
250 } else if (a
[0] is MalVector
) {
251 return (((MalVector
)a
[0]).size() == 0)
253 : new MalList(((MalVector
)a
[0]).getValue());
254 } else if (a
[0] is MalList
) {
255 return (((MalList
)a
[0]).size() == 0)
258 } else if (a
[0] is MalString
) {
259 var s
= ((MalString
)a
[0]).getValue();
263 var chars_list
= new List
<MalVal
>();
264 foreach (var c
in s
) {
265 chars_list
.Add(new MalString(c
.ToString()));
267 return new MalList(chars_list
);
272 // General list related functions
273 static MalFunc apply
= new MalFunc(
275 var f
= (MalFunc
)a
[0];
276 var lst
= new List
<MalVal
>();
277 lst
.AddRange(a
.slice(1,a
.size()-1).getValue());
278 lst
.AddRange(((MalList
)a
[a
.size()-1]).getValue());
279 return f
.apply(new MalList(lst
));
282 static MalFunc map
= new MalFunc(
284 MalFunc f
= (MalFunc
) a
[0];
285 var src_lst
= ((MalList
)a
[1]).getValue();
286 var new_lst
= new List
<MalVal
>();
287 for(int i
=0; i
<src_lst
.Count
; i
++) {
288 new_lst
.Add(f
.apply(new MalList(src_lst
[i
])));
290 return new MalList(new_lst
);
294 // Metadata functions
295 static MalFunc meta
= new MalFunc(
296 a
=> a
[0].getMeta());
298 static MalFunc with_meta
= new MalFunc(
299 a
=> ((MalVal
)a
[0]).copy().setMeta(a
[1]));
303 static MalFunc atom_Q
= new MalFunc(
304 a
=> a
[0] is MalAtom
? True
: False
);
306 static MalFunc deref
= new MalFunc(
307 a
=> ((MalAtom
)a
[0]).getValue());
309 static MalFunc reset_BANG
= new MalFunc(
310 a
=> ((MalAtom
)a
[0]).setValue(a
[1]));
312 static MalFunc swap_BANG
= new MalFunc(
314 MalAtom atm
= (MalAtom
)a
[0];
315 MalFunc f
= (MalFunc
)a
[1];
316 var new_lst
= new List
<MalVal
>();
317 new_lst
.Add(atm
.getValue());
318 new_lst
.AddRange(((MalList
)a
.slice(2)).getValue());
319 return atm
.setValue(f
.apply(new MalList(new_lst
)));
324 static public Dictionary
<string, MalVal
> ns
=
325 new Dictionary
<string, MalVal
> {
327 a
=> Mal
.types
._equal_Q(a
[0], a
[1]) ? True
: False
)},
328 {"throw", mal_throw}
,
332 {"symbol", new MalFunc(a => new MalSymbol((MalString)a[0]))}
,
333 {"symbol?", symbol_Q}
,
334 {"string?", string_Q}
,
335 {"keyword", keyword}
,
336 {"keyword?", keyword_Q}
,
337 {"number?", number_Q}
,
344 {"println", println}
,
345 {"readline", mal_readline}
,
346 {"read-string", read_string}
,
348 {"<", new MalFunc(a => (MalInt)a[0] < (MalInt)a[1])}
,
349 {"<=", new MalFunc(a => (MalInt)a[0] <= (MalInt)a[1])}
,
350 {">", new MalFunc(a => (MalInt)a[0] > (MalInt)a[1])}
,
351 {">=", new MalFunc(a => (MalInt)a[0] >= (MalInt)a[1])}
,
352 {"+", new MalFunc(a => (MalInt)a[0] + (MalInt)a[1])}
,
353 {"-", new MalFunc(a => (MalInt)a[0] - (MalInt)a[1])}
,
354 {"*", new MalFunc(a => (MalInt)a[0] * (MalInt)a[1])}
,
355 {"/", new MalFunc(a => (MalInt)a[0] / (MalInt)a[1])}
,
356 {"time-ms", time_ms}
,
358 {"list", new MalFunc(a => new MalList(a.getValue()))}
,
360 {"vector", new MalFunc(a => new MalVector(a.getValue()))}
,
361 {"vector?", vector_Q}
,
362 {"hash-map", new MalFunc(a => new MalHashMap(a))}
,
363 {"map?", hash_map_Q}
,
364 {"contains?", contains_Q}
,
371 {"sequential?", sequential_Q}
,
374 {"vec", new MalFunc(a => new MalVector(((MalList)a[0]).getValue()))}
,
385 {"with-meta", with_meta}
,
387 {"atom", new MalFunc(a => new MalAtom(a[0]))}
,
390 {"reset!", reset_BANG}
,
391 {"swap!", swap_BANG}
,