Nim: rename stepA_interop to stepA_mal
[jackhill/mal.git] / nim / core.nim
CommitLineData
4ce9e165 1import strutils, rdstdin, tables, algorithm, times, types, printer, reader
8de9f308 2
3type MalError* = object of Exception
4 t*: MalType
819bd786 5
6# String functions
7proc pr_str(xs: varargs[MalType]): MalType =
4ce9e165 8 str(xs.map(proc(x: MalType): string = x.pr_str(true)).join(" "))
819bd786 9
10proc do_str(xs: varargs[MalType]): MalType =
4ce9e165 11 str(xs.map(proc(x: MalType): string = x.pr_str(false)).join)
819bd786 12
13proc prn(xs: varargs[MalType]): MalType =
14 echo xs.map(proc(x: MalType): string = x.pr_str(true)).join(" ")
15 result = nilObj
16
17proc println(xs: varargs[MalType]): MalType =
18 let line = xs.map(proc(x: MalType): string = x.pr_str(false)).join(" ")
19 echo line.replace("\\n", "\n")
20 result = nilObj
21
3603af96 22proc read_str(xs: varargs[MalType]): MalType =
23 read_str(xs[0].str)
24
8de9f308 25proc readline(xs: varargs[MalType]): MalType =
26 str readLineFromStdin(xs[0].str)
27
3603af96 28proc slurp(xs: varargs[MalType]): MalType =
29 str readFile(xs[0].str)
30
dc7f0b6a 31proc cons(xs: varargs[MalType]): MalType =
32 result = list(xs[0])
33 for x in xs[1].list: result.list.add x
34
35proc concat(xs: varargs[MalType]): MalType =
36 result = list()
37 for x in xs:
38 for i in x.list:
39 result.list.add i
40
f5cf5237 41proc nth(xs: varargs[MalType]): MalType =
42 if xs[1].number < xs[0].list.len: return xs[0].list[xs[1].number]
43 else: raise newException(ValueError, "nth: index out of range")
44
45proc first(xs: varargs[MalType]): MalType =
4ce9e165 46 if xs[0].kind in {List, Vector} and xs[0].list.len > 0:
47 xs[0].list[0]
f5cf5237 48 else: nilObj
49
50proc rest(xs: varargs[MalType]): MalType =
4ce9e165 51 if xs[0].kind in {List, Vector} and xs[0].list.len > 0:
52 list xs[0].list[1 .. -1]
f5cf5237 53 else: list()
54
8de9f308 55proc throw(xs: varargs[MalType]): MalType =
56 raise (ref MalError)(t: list xs)
57
58proc assoc(xs: varargs[MalType]): MalType =
4ce9e165 59 result = hash_map()
60 result.hash_map[] = xs[0].hash_map[]
8de9f308 61 for i in countup(1, xs.high, 2):
62 result.hash_map[xs[i].str] = xs[i+1]
63
64proc dissoc(xs: varargs[MalType]): MalType =
4ce9e165 65 result = hash_map()
66 result.hash_map[] = xs[0].hash_map[]
8de9f308 67 for i in 1 .. xs.high:
68 if result.hash_map.hasKey(xs[i].str): result.hash_map.del(xs[i].str)
69
70proc get(xs: varargs[MalType]): MalType =
71 if xs[0].kind == HashMap:
72 xs[0].hash_map[xs[1].str]
73 else:
74 nilObj
75
76proc contains_q(xs: varargs[MalType]): MalType =
77 boolObj xs[0].hash_map.hasKey(xs[1].str)
78
79proc keys(xs: varargs[MalType]): MalType =
80 result = list()
81 for key in xs[0].hash_map.keys:
82 result.list.add str(key)
83
84proc vals(xs: varargs[MalType]): MalType =
85 result = list()
86 for value in xs[0].hash_map.values:
87 result.list.add value
88
89proc conj(xs: varargs[MalType]): MalType =
90 if xs[0].kind == List:
91 result = list()
92 for i in countdown(xs.high, 1):
93 result.list.add xs[i]
94 result.list.add xs[0].list
95 else:
96 result = vector()
97 result.list.add xs[0].list
98 for i in 1..xs.high:
99 result.list.add xs[i]
100 result.meta = xs[0].meta
101
102proc apply(xs: varargs[MalType]): MalType =
103 var s = newSeq[MalType]()
104 if xs.len > 2:
105 for j in 1 .. xs.high-1:
106 s.add xs[j]
107 s.add xs[xs.high].list
108 xs[0].getFun()(s)
109
110proc map(xs: varargs[MalType]): MalType =
111 result = list()
112 for i in 0 .. xs[1].list.high:
113 result.list.add xs[0].getFun()(xs[1].list[i])
114
115proc with_meta(xs: varargs[MalType]): MalType =
116 result = xs[0]
117 new result.meta
118 result.meta[] = xs[1]
119
120proc meta(xs: varargs[MalType]): MalType =
121 if xs[0].meta != nil: xs[0].meta[]
122 else: nilObj
123
124proc deref(xs: varargs[MalType]): MalType =
125 xs[0].val[]
126
127proc reset_bang(xs: varargs[MalType]): MalType =
128 xs[0].val[] = xs[1]
129 result = xs[0].val[]
130
131proc swap_bang(xs: varargs[MalType]): MalType =
132 var args = @[xs[0].val[]]
133 for i in 2 .. xs.high:
134 args.add xs[i]
135 xs[0].val[] = xs[1].getFun()(args)
136 result = xs[0].val[]
137
4ce9e165 138proc time_ms(xs: varargs[MalType]): MalType =
139 number int(epochTime() * 1000)
140
819bd786 141template wrapNumberFun(op: expr): expr =
8de9f308 142 fun proc(xs: varargs[MalType]): MalType =
143 number op(xs[0].number, xs[1].number)
819bd786 144
145template wrapBoolFun(op: expr): expr =
146 fun proc(xs: varargs[MalType]): MalType =
147 if op(xs[0].number, xs[1].number): trueObj else: falseObj
148
149let ns* = {
150 "+": wrapNumberFun(`+`),
151 "-": wrapNumberFun(`-`),
152 "*": wrapNumberFun(`*`),
153 "/": wrapNumberFun(`div`),
154
155 "<": wrapBoolFun(`<`),
156 "<=": wrapBoolFun(`<=`),
157 ">": wrapBoolFun(`>`),
158 ">=": wrapBoolFun(`>=`),
159
160 "list": fun list,
161 "list?": fun list_q,
162 "vector": fun vector,
163 "vector?": fun vector_q,
8de9f308 164 "hash-map": fun hash_map,
165 "map?": fun hash_map_q,
819bd786 166 "empty?": fun empty_q,
8de9f308 167 "assoc": fun assoc,
168 "dissoc": fun dissoc,
169 "get": fun get,
170 "contains?": fun contains_q,
171 "keys": fun keys,
172 "vals": fun vals,
173
819bd786 174 "=": fun equal,
175
176 "pr-str": fun pr_str,
177 "str": fun do_str,
178 "prn": fun prn,
179 "println": fun println,
3603af96 180
181 "read-string": fun read_str,
8de9f308 182 "readline": fun readline,
3603af96 183 "slurp": fun slurp,
8de9f308 184
185 "sequential?": fun seq_q,
dc7f0b6a 186 "cons": fun cons,
187 "concat": fun concat,
8de9f308 188 "count": fun count,
f5cf5237 189 "nth": fun nth,
190 "first": fun first,
191 "rest": fun rest,
8de9f308 192 "conj": fun conj,
193 "apply": fun apply,
194 "map": fun map,
195
196 "throw": fun throw,
197
198 "nil?": fun nil_q,
199 "true?": fun true_q,
200 "false?": fun false_q,
201 "symbol": fun symbol,
202 "symbol?": fun symbol_q,
203 "keyword": fun keyword,
204 "keyword?": fun keyword_q,
205
206 "with-meta": fun with_meta,
207 "meta": fun meta,
208 "atom": fun atom,
209 "atom?": fun atom_q,
210 "deref": fun deref,
211 "reset!": fun reset_bang,
212 "swap!": fun swap_bang,
4ce9e165 213
214 "time-ms": fun time_ms,
819bd786 215}