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(
40 if (a
[0] is MalString
&&
41 ((MalString
)a
[0]).getValue()[0] == '\u029e') {
44 return new MalString("\u029e" + ((MalString
)a
[0]).getValue());
48 static MalFunc keyword_Q
= new MalFunc(
50 if (a
[0] is MalString
&&
51 ((MalString
)a
[0]).getValue()[0] == '\u029e') {
60 static MalFunc time_ms
= new MalFunc(
61 a
=> new MalInt(DateTime
.Now
.Ticks
/ TimeSpan
.TicksPerMillisecond
));
64 static public MalFunc pr_str
= new MalFunc(
65 a
=> new MalString(printer
._pr_str_args(a
, " ", true)) );
67 static public MalFunc str
= new MalFunc(
68 a
=> new MalString(printer
._pr_str_args(a
, "", false)) );
70 static public MalFunc prn
= new MalFunc(
72 Console
.WriteLine(printer
._pr_str_args(a
, " ", true));
76 static public MalFunc println
= new MalFunc(
78 Console
.WriteLine(printer
._pr_str_args(a
, " ", false));
82 static public MalFunc mal_readline
= new MalFunc(
84 var line
= readline
.Readline(((MalString
)a
[0]).getValue());
85 if (line
== null) { return types.Nil; }
86 else { return new MalString(line); }
89 static public MalFunc read_string
= new MalFunc(
90 a
=> reader
.read_str(((MalString
)a
[0]).getValue()));
92 static public MalFunc slurp
= new MalFunc(
93 a
=> new MalString(File
.ReadAllText(
94 ((MalString
)a
[0]).getValue())));
97 // List/Vector functions
98 static public MalFunc list_Q
= new MalFunc(
99 a
=> a
[0].GetType() == typeof(MalList
) ? True
: False
);
101 static public MalFunc vector_Q
= new MalFunc(
102 a
=> a
[0].GetType() == typeof(MalVector
) ? True
: False
);
105 static public MalFunc hash_map_Q
= new MalFunc(
106 a
=> a
[0].GetType() == typeof(MalHashMap
) ? True
: False
);
108 static MalFunc contains_Q
= new MalFunc(
110 string key
= ((MalString
)a
[1]).getValue();
111 var dict
= ((MalHashMap
)a
[0]).getValue();
112 return dict
.ContainsKey(key
) ? True
: False
;
115 static MalFunc assoc
= new MalFunc(
117 var new_hm
= ((MalHashMap
)a
[0]).copy();
118 return new_hm
.assoc_BANG((MalList
)a
.slice(1));
121 static MalFunc dissoc
= new MalFunc(
123 var new_hm
= ((MalHashMap
)a
[0]).copy();
124 return new_hm
.dissoc_BANG((MalList
)a
.slice(1));
127 static MalFunc
get = new MalFunc(
129 string key
= ((MalString
)a
[1]).getValue();
133 var dict
= ((MalHashMap
)a
[0]).getValue();
134 return dict
.ContainsKey(key
) ? dict
[key
] : Nil
;
138 static MalFunc keys
= new MalFunc(
140 var dict
= ((MalHashMap
)a
[0]).getValue();
141 MalList key_lst
= new MalList();
142 foreach (var key
in dict
.Keys
) {
143 key_lst
.conj_BANG(new MalString(key
));
148 static MalFunc vals
= new MalFunc(
150 var dict
= ((MalHashMap
)a
[0]).getValue();
151 MalList val_lst
= new MalList();
152 foreach (var val
in dict
.Values
) {
153 val_lst
.conj_BANG(val
);
158 // Sequence functions
159 static public MalFunc sequential_Q
= new MalFunc(
160 a
=> a
[0] is MalList
? True
: False
);
162 static MalFunc cons
= new MalFunc(
164 var lst
= new List
<MalVal
>();
166 lst
.AddRange(((MalList
)a
[1]).getValue());
167 return (MalVal
)new MalList(lst
);
170 static MalFunc concat
= new MalFunc(
172 if (a
.size() == 0) { return new MalList(); }
173 var lst
= new List
<MalVal
>();
174 lst
.AddRange(((MalList
)a
[0]).getValue());
175 for(int i
=1; i
<a
.size(); i
++) {
176 lst
.AddRange(((MalList
)a
[i
]).getValue());
178 return (MalVal
)new MalList(lst
);
181 static MalFunc nth
= new MalFunc(
183 var idx
= (int)((MalInt
)a
[1]).getValue();
184 if (idx
< ((MalList
)a
[0]).size()) {
185 return ((MalList
)a
[0])[idx
];
187 throw new Mal
.types
.MalException(
188 "nth: index out of range");
192 static MalFunc first
= new MalFunc(
193 a
=> ((MalList
)a
[0])[0]);
195 static MalFunc rest
= new MalFunc(
196 a
=> ((MalList
)a
[0]).rest());
198 static MalFunc empty_Q
= new MalFunc(
199 a
=> ((MalList
)a
[0]).size() == 0 ? True
: False
);
201 static MalFunc count
= new MalFunc(
205 :new MalInt(((MalList
)a
[0]).size());
208 static MalFunc conj
= new MalFunc(
210 var src_lst
= ((MalList
)a
[0]).getValue();
211 var new_lst
= new List
<MalVal
>();
212 new_lst
.AddRange(src_lst
);
213 if (a
[0] is MalVector
) {
214 for(int i
=1; i
<a
.size(); i
++) {
217 return new MalVector(new_lst
);
219 for(int i
=1; i
<a
.size(); i
++) {
220 new_lst
.Insert(0, a
[i
]);
222 return new MalList(new_lst
);
227 // General list related functions
228 static MalFunc apply
= new MalFunc(
230 var f
= (MalFunc
)a
[0];
231 var lst
= new List
<MalVal
>();
232 lst
.AddRange(a
.slice(1,a
.size()-1).getValue());
233 lst
.AddRange(((MalList
)a
[a
.size()-1]).getValue());
234 return f
.apply(new MalList(lst
));
237 static MalFunc map
= new MalFunc(
239 MalFunc f
= (MalFunc
) a
[0];
240 var src_lst
= ((MalList
)a
[1]).getValue();
241 var new_lst
= new List
<MalVal
>();
242 for(int i
=0; i
<src_lst
.Count
; i
++) {
243 new_lst
.Add(f
.apply(new MalList(src_lst
[i
])));
245 return new MalList(new_lst
);
249 // Metadata functions
250 static MalFunc meta
= new MalFunc(
251 a
=> a
[0].getMeta());
253 static MalFunc with_meta
= new MalFunc(
254 a
=> ((MalVal
)a
[0]).copy().setMeta(a
[1]));
258 static MalFunc atom_Q
= new MalFunc(
259 a
=> a
[0] is MalAtom
? True
: False
);
261 static MalFunc deref
= new MalFunc(
262 a
=> ((MalAtom
)a
[0]).getValue());
264 static MalFunc reset_BANG
= new MalFunc(
265 a
=> ((MalAtom
)a
[0]).setValue(a
[1]));
267 static MalFunc swap_BANG
= new MalFunc(
269 MalAtom atm
= (MalAtom
)a
[0];
270 MalFunc f
= (MalFunc
)a
[1];
271 var new_lst
= new List
<MalVal
>();
272 new_lst
.Add(atm
.getValue());
273 new_lst
.AddRange(((MalList
)a
.slice(2)).getValue());
274 return atm
.setValue(f
.apply(new MalList(new_lst
)));
279 static public Dictionary
<string, MalVal
> ns
=
280 new Dictionary
<string, MalVal
> {
282 a
=> Mal
.types
._equal_Q(a
[0], a
[1]) ? True
: False
)},
283 {"throw", mal_throw}
,
287 {"symbol", new MalFunc(a => new MalSymbol((MalString)a[0]))}
,
288 {"symbol?", symbol_Q}
,
289 {"keyword", keyword}
,
290 {"keyword?", keyword_Q}
,
295 {"println", println}
,
296 {"readline", mal_readline}
,
297 {"read-string", read_string}
,
299 {"<", new MalFunc(a => (MalInt)a[0] < (MalInt)a[1])}
,
300 {"<=", new MalFunc(a => (MalInt)a[0] <= (MalInt)a[1])}
,
301 {">", new MalFunc(a => (MalInt)a[0] > (MalInt)a[1])}
,
302 {">=", new MalFunc(a => (MalInt)a[0] >= (MalInt)a[1])}
,
303 {"+", new MalFunc(a => (MalInt)a[0] + (MalInt)a[1])}
,
304 {"-", new MalFunc(a => (MalInt)a[0] - (MalInt)a[1])}
,
305 {"*", new MalFunc(a => (MalInt)a[0] * (MalInt)a[1])}
,
306 {"/", new MalFunc(a => (MalInt)a[0] / (MalInt)a[1])}
,
307 {"time-ms", time_ms}
,
309 {"list", new MalFunc(a => new MalList(a.getValue()))}
,
311 {"vector", new MalFunc(a => new MalVector(a.getValue()))}
,
312 {"vector?", vector_Q}
,
313 {"hash-map", new MalFunc(a => new MalHashMap(a))}
,
314 {"map?", hash_map_Q}
,
315 {"contains?", contains_Q}
,
322 {"sequential?", sequential_Q}
,
334 {"with-meta", with_meta}
,
336 {"atom", new MalFunc(a => new MalAtom(a[0]))}
,
339 {"reset!", reset_BANG}
,
340 {"swap!", swap_BANG}
,