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 keyword
= new MalFunc(
39 a
=> new MalString("\u029e" + ((MalString
)a
[0]).getValue()));
41 static MalFunc keyword_Q
= new MalFunc(
43 if (a
[0] is MalString
&&
44 ((MalString
)a
[0]).getValue()[0] == '\u029e') {
53 static MalFunc time_ms
= new MalFunc(
54 a
=> new MalInt(DateTime
.Now
.Ticks
/ TimeSpan
.TicksPerMillisecond
));
57 static public MalFunc pr_str
= new MalFunc(
58 a
=> new MalString(printer
._pr_str_args(a
, " ", true)) );
60 static public MalFunc str
= new MalFunc(
61 a
=> new MalString(printer
._pr_str_args(a
, "", false)) );
63 static public MalFunc prn
= new MalFunc(
65 Console
.WriteLine(printer
._pr_str_args(a
, " ", true));
69 static public MalFunc println
= new MalFunc(
71 Console
.WriteLine(printer
._pr_str_args(a
, " ", false));
75 static public MalFunc mal_readline
= new MalFunc(
77 var line
= readline
.Readline(((MalString
)a
[0]).getValue());
78 if (line
== null) { return types.Nil; }
79 else { return new MalString(line); }
82 static public MalFunc read_string
= new MalFunc(
83 a
=> reader
.read_str(((MalString
)a
[0]).getValue()));
85 static public MalFunc slurp
= new MalFunc(
86 a
=> new MalString(File
.ReadAllText(
87 ((MalString
)a
[0]).getValue())));
90 // List/Vector functions
91 static public MalFunc list_Q
= new MalFunc(
92 a
=> a
[0].GetType() == typeof(MalList
) ? True
: False
);
94 static public MalFunc vector_Q
= new MalFunc(
95 a
=> a
[0].GetType() == typeof(MalVector
) ? True
: False
);
98 static public MalFunc hash_map_Q
= new MalFunc(
99 a
=> a
[0].GetType() == typeof(MalHashMap
) ? True
: False
);
101 static MalFunc contains_Q
= new MalFunc(
103 string key
= ((MalString
)a
[1]).getValue();
104 var dict
= ((MalHashMap
)a
[0]).getValue();
105 return dict
.ContainsKey(key
) ? True
: False
;
108 static MalFunc assoc
= new MalFunc(
110 var new_hm
= ((MalHashMap
)a
[0]).copy();
111 return new_hm
.assoc_BANG((MalList
)a
.slice(1));
114 static MalFunc dissoc
= new MalFunc(
116 var new_hm
= ((MalHashMap
)a
[0]).copy();
117 return new_hm
.dissoc_BANG((MalList
)a
.slice(1));
120 static MalFunc
get = new MalFunc(
122 string key
= ((MalString
)a
[1]).getValue();
126 var dict
= ((MalHashMap
)a
[0]).getValue();
127 return dict
.ContainsKey(key
) ? dict
[key
] : Nil
;
131 static MalFunc keys
= new MalFunc(
133 var dict
= ((MalHashMap
)a
[0]).getValue();
134 MalList key_lst
= new MalList();
135 foreach (var key
in dict
.Keys
) {
136 key_lst
.conj_BANG(new MalString(key
));
141 static MalFunc vals
= new MalFunc(
143 var dict
= ((MalHashMap
)a
[0]).getValue();
144 MalList val_lst
= new MalList();
145 foreach (var val
in dict
.Values
) {
146 val_lst
.conj_BANG(val
);
151 // Sequence functions
152 static public MalFunc sequential_Q
= new MalFunc(
153 a
=> a
[0] is MalList
? True
: False
);
155 static MalFunc cons
= new MalFunc(
157 var lst
= new List
<MalVal
>();
159 lst
.AddRange(((MalList
)a
[1]).getValue());
160 return (MalVal
)new MalList(lst
);
163 static MalFunc concat
= new MalFunc(
165 if (a
.size() == 0) { return new MalList(); }
166 var lst
= new List
<MalVal
>();
167 lst
.AddRange(((MalList
)a
[0]).getValue());
168 for(int i
=1; i
<a
.size(); i
++) {
169 lst
.AddRange(((MalList
)a
[i
]).getValue());
171 return (MalVal
)new MalList(lst
);
174 static MalFunc nth
= new MalFunc(
176 var idx
= (int)((MalInt
)a
[1]).getValue();
177 if (idx
< ((MalList
)a
[0]).size()) {
178 return ((MalList
)a
[0])[idx
];
180 throw new Mal
.types
.MalException(
181 "nth: index out of range");
185 static MalFunc first
= new MalFunc(
186 a
=> ((MalList
)a
[0])[0]);
188 static MalFunc rest
= new MalFunc(
189 a
=> ((MalList
)a
[0]).rest());
191 static MalFunc empty_Q
= new MalFunc(
192 a
=> ((MalList
)a
[0]).size() == 0 ? True
: False
);
194 static MalFunc count
= new MalFunc(
198 :new MalInt(((MalList
)a
[0]).size());
201 static MalFunc conj
= new MalFunc(
203 var src_lst
= ((MalList
)a
[0]).getValue();
204 var new_lst
= new List
<MalVal
>();
205 new_lst
.AddRange(src_lst
);
206 if (a
[0] is MalVector
) {
207 for(int i
=1; i
<a
.size(); i
++) {
210 return new MalVector(new_lst
);
212 for(int i
=1; i
<a
.size(); i
++) {
213 new_lst
.Insert(0, a
[i
]);
215 return new MalList(new_lst
);
220 // General list related functions
221 static MalFunc apply
= new MalFunc(
223 var f
= (MalFunc
)a
[0];
224 var lst
= new List
<MalVal
>();
225 lst
.AddRange(a
.slice(1,a
.size()-1).getValue());
226 lst
.AddRange(((MalList
)a
[a
.size()-1]).getValue());
227 return f
.apply(new MalList(lst
));
230 static MalFunc map
= new MalFunc(
232 MalFunc f
= (MalFunc
) a
[0];
233 var src_lst
= ((MalList
)a
[1]).getValue();
234 var new_lst
= new List
<MalVal
>();
235 for(int i
=0; i
<src_lst
.Count
; i
++) {
236 new_lst
.Add(f
.apply(new MalList(src_lst
[i
])));
238 return new MalList(new_lst
);
242 // Metadata functions
243 static MalFunc meta
= new MalFunc(
244 a
=> a
[0].getMeta());
246 static MalFunc with_meta
= new MalFunc(
247 a
=> ((MalVal
)a
[0]).copy().setMeta(a
[1]));
251 static MalFunc atom_Q
= new MalFunc(
252 a
=> a
[0] is MalAtom
? True
: False
);
254 static MalFunc deref
= new MalFunc(
255 a
=> ((MalAtom
)a
[0]).getValue());
257 static MalFunc reset_BANG
= new MalFunc(
258 a
=> ((MalAtom
)a
[0]).setValue(a
[1]));
260 static MalFunc swap_BANG
= new MalFunc(
262 MalAtom atm
= (MalAtom
)a
[0];
263 MalFunc f
= (MalFunc
)a
[1];
264 var new_lst
= new List
<MalVal
>();
265 new_lst
.Add(atm
.getValue());
266 new_lst
.AddRange(((MalList
)a
.slice(2)).getValue());
267 return atm
.setValue(f
.apply(new MalList(new_lst
)));
272 static public Dictionary
<string, MalVal
> ns
=
273 new Dictionary
<string, MalVal
> {
275 a
=> Mal
.types
._equal_Q(a
[0], a
[1]) ? True
: False
)},
276 {"throw", mal_throw}
,
280 {"symbol", new MalFunc(a => new MalSymbol((MalString)a[0]))}
,
281 {"symbol?", symbol_Q}
,
282 {"keyword", keyword}
,
283 {"keyword?", keyword_Q}
,
288 {"println", println}
,
289 {"readline", mal_readline}
,
290 {"read-string", read_string}
,
292 {"<", new MalFunc(a => (MalInt)a[0] < (MalInt)a[1])}
,
293 {"<=", new MalFunc(a => (MalInt)a[0] <= (MalInt)a[1])}
,
294 {">", new MalFunc(a => (MalInt)a[0] > (MalInt)a[1])}
,
295 {">=", new MalFunc(a => (MalInt)a[0] >= (MalInt)a[1])}
,
296 {"+", new MalFunc(a => (MalInt)a[0] + (MalInt)a[1])}
,
297 {"-", new MalFunc(a => (MalInt)a[0] - (MalInt)a[1])}
,
298 {"*", new MalFunc(a => (MalInt)a[0] * (MalInt)a[1])}
,
299 {"/", new MalFunc(a => (MalInt)a[0] / (MalInt)a[1])}
,
300 {"time-ms", time_ms}
,
302 {"list", new MalFunc(a => new MalList(a.getValue()))}
,
304 {"vector", new MalFunc(a => new MalVector(a.getValue()))}
,
305 {"vector?", vector_Q}
,
306 {"hash-map", new MalFunc(a => new MalHashMap(a))}
,
307 {"map?", hash_map_Q}
,
308 {"contains?", contains_Q}
,
315 {"sequential?", sequential_Q}
,
327 {"with-meta", with_meta}
,
329 {"atom", new MalFunc(a => new MalAtom(a[0]))}
,
332 {"reset!", reset_BANG}
,
333 {"swap!", swap_BANG}
,