Merge pull request #158 from dubek/first-rest-nil
[jackhill/mal.git] / vb / core.vb
1 Imports System
2 Imports System.IO
3 Imports System.Collections.Generic
4 Imports MalVal = Mal.types.MalVal
5 Imports MalConstant = Mal.types.MalConstant
6 Imports MalInt = Mal.types.MalInt
7 Imports MalSymbol = Mal.types.MalSymbol
8 Imports MalString = Mal.types.MalString
9 Imports MalList = Mal.types.MalList
10 Imports MalVector = Mal.types.MalVector
11 Imports MalHashMap = Mal.types.MalHashMap
12 Imports MalAtom = Mal.types.MalAtom
13 Imports MalFunc = Mal.types.MalFunc
14
15 Namespace Mal
16 Public Class core
17 Shared Nil As MalConstant = Mal.types.Nil
18 Shared MalTrue As MalConstant = Mal.types.MalTrue
19 Shared MalFalse As MalConstant = Mal.types.MalFalse
20
21 ' Errors/Exceptions
22 Shared Function mal_throw(a As MalList) As MalVal
23 throw New Mal.types.MalException(a(0))
24 End Function
25
26 ' General functions
27 Shared Function equal_Q(a As MalList) As MalVal
28 If Mal.types._equal_Q(a(0), a(1)) Then
29 return MalTrue
30 Else
31 return MalFalse
32 End If
33 End Function
34
35 ' Scalar functions
36 Shared Function nil_Q(a As MalList) As MalVal
37 If a(0) Is Nil Then
38 return MalTrue
39 Else
40 return MalFalse
41 End If
42 End Function
43
44 Shared Function true_Q(a As MalList) As MalVal
45 If a(0) Is MalTrue Then
46 return MalTrue
47 Else
48 return MalFalse
49 End If
50 End Function
51
52 Shared Function false_Q(a As MalList) As MalVal
53 If a(0) Is MalFalse Then
54 return MalTrue
55 Else
56 return MalFalse
57 End If
58 End Function
59
60 Shared Function symbol(a As MalList) As MalVal
61 return new MalSymbol(DirectCast(a(0),MalString))
62 End Function
63
64 Shared Function symbol_Q(a As MalList) As MalVal
65 If TypeOf a(0) Is MalSymbol Then
66 return MalTrue
67 Else
68 return MalFalse
69 End If
70 End Function
71
72 Shared Function keyword(a As MalList) As MalVal
73 Dim s As String = DirectCast(a(0),MalString).getValue()
74 return new MalString(ChrW(&H029e) & s)
75 End Function
76
77 Shared Function keyword_Q(a As MalList) As MalVal
78 If TypeOf a(0) Is MalString Then
79 Dim s As String = DirectCast(a(0),MalString).getValue()
80 If s.Substring(0,1) = Strings.ChrW(&H029e) Then
81 return MalTrue
82 Else
83 return MalFalse
84 End If
85 Else
86 return MalFalse
87 End If
88 End Function
89
90
91 ' Number functions
92 Shared Function lt(a As MalList) As MalVal
93 return DirectCast(a(0),MalInt) < DirectCast(a(1),MalInt)
94 End Function
95 Shared Function lte(a As MalList) As MalVal
96 return DirectCast(a(0),MalInt) <= DirectCast(a(1),MalInt)
97 End Function
98 Shared Function gt(a As MalList) As MalVal
99 return DirectCast(a(0),MalInt) > DirectCast(a(1),MalInt)
100 End Function
101 Shared Function gte(a As MalList) As MalVal
102 return DirectCast(a(0),MalInt) >= DirectCast(a(1),MalInt)
103 End Function
104 Shared Function plus(a As MalList) As MalVal
105 return DirectCast(a(0),MalInt) + DirectCast(a(1),MalInt)
106 End Function
107 Shared Function minus(a As MalList) As MalVal
108 return DirectCast(a(0),MalInt) - DirectCast(a(1),MalInt)
109 End Function
110 Shared Function mult(a As MalList) As MalVal
111 return DirectCast(a(0),MalInt) * DirectCast(a(1),MalInt)
112 End Function
113 Shared Function div(a As MalList) As MalVal
114 return DirectCast(a(0),MalInt) / DirectCast(a(1),MalInt)
115 End Function
116
117 Shared Function time_ms(a As MalList) As MalVal
118 return New MalInt(DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond)
119 End Function
120
121 ' String functions
122 Shared Function pr_str(a As MalList) As MalVal
123 return New MalString(printer._pr_str_args(a, " ", true))
124 End Function
125
126 Shared Function str(a As MalList) As MalVal
127 return new MalString(printer._pr_str_args(a, "", false))
128 End Function
129
130 Shared Function prn(a As MalList) As MalVal
131 Console.WriteLine(printer._pr_str_args(a, " ", true))
132 return Nil
133 End Function
134
135 Shared Function println(a As MalList) As MalVal
136 Console.WriteLine(printer._pr_str_args(a, " ", false))
137 return Nil
138 End Function
139
140 Shared Function mal_readline(a As MalList) As MalVal
141 Dim line As String
142 line = readline.Readline(DirectCast(a(0),MalString).getValue())
143 If line Is Nothing Then
144 return types.Nil
145 Else
146 return New MalString(line)
147 End If
148 End Function
149
150 Shared Function read_string(a As MalList) As MalVal
151 return reader.read_str(DirectCast(a(0),MalString).getValue())
152 End Function
153
154 Shared Function slurp(a As MalList) As MalVal
155 return New MalString(File.ReadAllText(DirectCast(a(0),MalString).getValue()))
156 End Function
157
158
159 ' List/Vector functions
160
161 Shared Function list(a As MalList) As MalVal
162 return New MalList(a.getValue())
163 End Function
164
165 Shared Function list_Q(a As MalList) As MalVal
166 If TypeOf a(0) Is MalList And Not TypeOf a(0) Is MalVector Then
167 return MalTrue
168 Else
169 return MalFalse
170 End If
171 End Function
172
173 Shared Function vector(a As MalList) As MalVal
174 return New MalVector(a.getValue())
175 End Function
176
177 Shared Function vector_Q(a As MalList) As MalVal
178 If TypeOf a(0) Is MalVector Then
179 return MalTrue
180 Else
181 return MalFalse
182 End If
183 End Function
184
185 ' HashMap functions
186 Shared Function hash_map(a As MalList) As MalVal
187 return New MalHashMap(a)
188 End Function
189
190 Shared Function hash_map_Q(a As MalList) As MalVal
191 If TypeOf a(0) Is MalHashMap Then
192 return MalTrue
193 Else
194 return MalFalse
195 End If
196 End Function
197
198 Shared Function contains_Q(a As MalList) As MalVal
199 Dim key As String = DirectCast(a(1),MalString).getValue()
200 Dim dict As Dictionary(Of String,MalVal) = DirectCast(a(0),MalHashMap).getValue()
201 If dict.ContainsKey(key) Then
202 return MalTrue
203 Else
204 return MalFalse
205 End If
206 End Function
207
208 Shared Function assoc(a As MalList) As MalVal
209 Dim new_hm As MalHashMap = DirectCast(a(0),MalHashMap).copy()
210 return new_hm.assoc_BANG(DirectCast(a.slice(1),MalList))
211 End Function
212
213 Shared Function dissoc(a As MalList) As MalVal
214 Dim new_hm As MalHashMap = DirectCast(a(0),MalHashMap).copy()
215 return new_hm.dissoc_BANG(DirectCast(a.slice(1),MalList))
216 End Function
217
218 Shared Function do_get(a As MalList) As MalVal
219 Dim k As String = DirectCast(a(1),MalString).getValue()
220 If a(0) Is Nil Then
221 return Nil
222 Else
223 Dim dict As Dictionary(Of String,MalVal) = DirectCast(a(0),MalHashMap).getValue()
224 If dict.ContainsKey(k) Then
225 return dict(k)
226 Else
227 return Nil
228 End If
229 End If
230 End Function
231
232 Shared Function keys(a As MalList) As MalVal
233 Dim dict As Dictionary(Of String,MalVal) = DirectCast(a(0),MalHashMap).getValue()
234 Dim key_lst As MalList = New MalList()
235 For Each key As String in dict.Keys
236 key_lst.conj_BANG(new MalString(key))
237 Next
238 return key_lst
239 End Function
240
241 Shared Function vals(a As MalList) As MalVal
242 Dim dict As Dictionary(Of String,MalVal) = DirectCast(a(0),MalHashMap).getValue()
243 Dim val_lst As MalList = New MalList()
244 For Each val As MalVal In dict.Values
245 val_lst.conj_BANG(val)
246 Next
247 return val_lst
248 End Function
249
250 ' Sequence functions
251 Shared Function sequential_Q(a As MalList) As MalVal
252 If TypeOf a(0) Is MalList Then
253 return MalTrue
254 Else
255 return MalFalse
256 End If
257 End Function
258
259 Shared Function cons(a As MalList) As MalVal
260 Dim lst As New List(Of MalVal)
261 lst.Add(a(0))
262 lst.AddRange(DirectCast(a(1),MalList).getValue())
263 return DirectCast(New MalList(lst),MalVal)
264 End Function
265
266 Shared Function concat(a As MalList) As MalVal
267 If a.size() = 0 Then
268 return new MalList()
269 End If
270 Dim lst As New List(Of MalVal)
271 lst.AddRange(DirectCast(a(0),MalList).getValue())
272 for i As Integer = 1 To a.size()-1
273 lst.AddRange(DirectCast(a(i),MalList).getValue())
274 Next
275 return DirectCast(new MalList(lst),MalVal)
276 End Function
277
278 Shared Function nth(a As MalList) As MalVal
279 Dim idx As Integer = DirectCast(a(1),MalInt).getValue()
280 If (idx < DirectCast(a(0),MalList).size()) Then
281 return DirectCast(a(0),MalList)( idx )
282 Else
283 throw new Mal.types.MalException(
284 "nth: index out of range")
285 End If
286 End Function
287
288 Shared Function first(a As MalList) As MalVal
289 If a(0) Is Nil Then
290 return Nil
291 Else
292 return DirectCast(a(0),MalList)(0)
293 End If
294 End Function
295
296 Shared Function rest(a As MalList) As MalVal
297 If a(0) Is Nil Then
298 return new MalList()
299 Else
300 return DirectCast(a(0),MalList).rest()
301 End If
302 End Function
303
304 Shared Function empty_Q(a As MalList) As MalVal
305 If DirectCast(a(0),MalList).size() = 0 Then
306 return MalTrue
307 Else
308 return MalFalse
309 End If
310 End Function
311
312 Shared Function count(a As MalList) As MalVal
313 If a(0) Is Nil Then
314 return new MalInt(0)
315 Else
316 return new MalInt(DirectCast(a(0),MalList).size())
317 End If
318 End Function
319
320 Shared Function conj(a As MalList) As MalVal
321 Dim src_lst As List(Of MalVal) = DirectCast(a(0),MalList).getValue()
322 Dim new_lst As New List(Of MalVal)
323 new_lst.AddRange(src_lst)
324 If TypeOf a(0) Is MalVector Then
325 For i As Integer = 1 To a.size()-1
326 new_lst.Add(a(i))
327 Next
328 return new MalVector(new_lst)
329 Else
330 For i As Integer = 1 To a.size()-1
331 new_lst.Insert(0, a(i))
332 Next
333 return new MalList(new_lst)
334 End If
335 End Function
336
337
338 ' General list related functions
339 Shared Function apply(a As MalList) As MalVal
340 Dim f As MalFunc = DirectCast(a(0),MalFunc)
341 Dim lst As New List(Of MalVal)
342 lst.AddRange(a.slice(1,a.size()-1).getValue())
343 lst.AddRange(DirectCast(a(a.size()-1),MalList).getValue())
344 return f.apply(New MalList(lst))
345 End Function
346
347 Shared Function map(a As MalList) As MalVal
348 Dim f As MalFunc = DirectCast(a(0),MalFunc)
349 Dim src_lst As List(Of MalVal) = DirectCast(a(1),MalList).getValue()
350 Dim new_lst As New List(Of MalVal)
351 for i As Integer = 0 To src_lst.Count-1
352 new_lst.Add(f.apply(New MalList(src_lst(i))))
353 Next
354 return new MalList(new_lst)
355 End Function
356
357
358 ' Metadata functions
359 Shared Function atom(a As MalList) As MalVal
360 return new MalAtom(a(0))
361 End Function
362
363 Shared Function meta(a As MalList) As MalVal
364 return a(0).getMeta()
365 End Function
366
367 Shared Function with_meta(a As MalList) As MalVal
368 return DirectCast(a(0),MalVal).copy().setMeta(a(1))
369 End Function
370
371
372 ' Atom functions
373 Shared Function atom_Q(a As MalList) As MalVal
374 If TypeOf a(0) Is MalAtom Then
375 return MalTrue
376 Else
377 return MalFalse
378 End If
379 End Function
380
381 Shared Function deref(a As MalList) As MalVal
382 return DirectCast(a(0),MalAtom).getValue()
383 End Function
384
385 Shared Function reset_BANG(a As MalList) As MalVal
386 return DirectCast(a(0),MalAtom).setValue(a(1))
387 End Function
388
389 Shared Function swap_BANG(a As MalList) As MalVal
390 Dim atm As MalAtom = DirectCast(a(0),MalAtom)
391 Dim f As MalFunc = DirectCast(a(1),MalFunc)
392 Dim new_lst As New List(Of MalVal)
393 new_lst.Add(atm.getValue())
394 new_lst.AddRange(DirectCast(a.slice(2),MalList).getValue())
395 return atm.setValue(f.apply(New MalList(new_lst)))
396 End Function
397
398
399
400 Shared Function ns As Dictionary(Of String, MalVal)
401 Dim ns As New Dictionary(Of String, MalVal)
402
403 ns.Add("=", New MalFunc(AddressOf equal_Q))
404 ns.Add("throw", New MalFunc(AddressOf mal_throw))
405 ns.Add("nil?", New MalFunc(AddressOf nil_Q))
406 ns.Add("true?", New MalFunc(AddressOf true_Q))
407 ns.Add("false?", New MalFunc(AddressOf false_Q))
408 ns.Add("symbol", new MalFunc(AddressOf symbol))
409 ns.Add("symbol?", New MalFunc(AddressOf symbol_Q))
410 ns.Add("keyword", new MalFunc(AddressOf keyword))
411 ns.Add("keyword?", New MalFunc(AddressOf keyword_Q))
412
413 ns.Add("pr-str",New MalFunc(AddressOf pr_str))
414 ns.Add("str", New MalFunc(AddressOf str))
415 ns.Add("prn", New MalFunc(AddressOf prn))
416 ns.Add("println", New MalFunc(AddressOf println))
417 ns.Add("readline", New MalFunc(AddressOf mal_readline))
418 ns.Add("read-string", New MalFunc(AddressOf read_string))
419 ns.Add("slurp", New MalFunc(AddressOf slurp))
420 ns.Add("<", New MalFunc(AddressOf lt))
421 ns.Add("<=", New MalFunc(AddressOf lte))
422 ns.Add(">", New MalFunc(AddressOf gt))
423 ns.Add(">=", New MalFunc(AddressOf gte))
424 ns.Add("+", New MalFunc(AddressOf plus))
425 ns.Add("-", New MalFunc(AddressOf minus))
426 ns.Add("*", New MalFunc(AddressOf mult))
427 ns.Add("/", New MalFunc(AddressOf div))
428 ns.Add("time-ms", New MalFunc(AddressOf time_ms))
429
430 ns.Add("list", New MalFunc(AddressOf list))
431 ns.Add("list?", New MalFunc(AddressOf list_Q))
432 ns.Add("vector", new MalFunc(AddressOf vector))
433 ns.Add("vector?", New MalFunc(AddressOf vector_Q))
434 ns.Add("hash-map", new MalFunc(AddressOf hash_map))
435 ns.Add("map?", New MalFunc(AddressOf hash_map_Q))
436 ns.Add("contains?", New MalFunc(AddressOf contains_Q))
437 ns.Add("assoc", New MalFunc(AddressOf assoc))
438 ns.Add("dissoc", New MalFunc(AddressOf dissoc))
439 ns.Add("get", New MalFunc(AddressOf do_get))
440 ns.Add("keys", New MalFunc(AddressOf keys))
441 ns.Add("vals", New MalFunc(AddressOf vals))
442
443 ns.Add("sequential?", New MalFunc(AddressOf sequential_Q))
444 ns.Add("cons", New MalFunc(AddressOf cons))
445 ns.Add("concat", New MalFunc(AddressOf concat))
446 ns.Add("nth", New MalFunc(AddressOf nth))
447 ns.Add("first", New MalFunc(AddressOf first))
448 ns.Add("rest", New MalFunc(AddressOf rest))
449 ns.Add("empty?", New MalFunc(AddressOf empty_Q))
450 ns.Add("count",New MalFunc(AddressOf count))
451 ns.Add("conj", New MalFunc(AddressOf conj))
452 ns.Add("apply", New MalFunc(AddressOf apply))
453 ns.Add("map", New MalFunc(AddressOf map))
454
455 ns.Add("with-meta", New MalFunc(AddressOf with_meta))
456 ns.Add("meta", New MalFunc(AddressOf meta))
457 ns.Add("atom", new MalFunc(AddressOf atom))
458 ns.Add("atom?", New MalFunc(AddressOf atom_Q))
459 ns.Add("deref", New MalFunc(AddressOf deref))
460 ns.Add("reset!", New MalFunc(AddressOf reset_BANG))
461 ns.Add("swap!", New MalFunc(AddressOf swap_BANG))
462 return ns
463 End Function
464 End Class
465 End Namespace