DISABLE FDs (REMOVE ME).
[jackhill/mal.git] / jq / core.jq
CommitLineData
51ff32e2 1include "utils";
da5289bb 2include "printer";
7650046a 3include "reader";
da5289bb
A
4
5def core_identify:
6 {
136fb719
A
7 "env": {
8 kind: "fn",
9 function: "env",
10 inputs: 0
11 },
da5289bb
A
12 "prn": {
13 kind: "fn",
14 function: "prn",
15 inputs: -1
16 },
17 "pr-str": {
18 kind: "fn",
19 function: "pr-str",
20 inputs: -1
21 },
22 "str": {
23 kind: "fn",
24 function: "str",
25 inputs: -1
26 },
27 "println": {
28 kind: "fn",
29 function: "println",
30 inputs: -1
31 },
32 "list": {
33 kind: "fn",
34 function: "list",
35 inputs: -1
36 },
37 "list?": {
38 kind: "fn",
39 function: "list?",
40 inputs: 1
41 },
42 "empty?": {
43 kind: "fn",
44 function: "empty?",
45 inputs: 1
46 },
47 "count": {
48 kind: "fn",
49 function: "count",
50 inputs: 1
51 },
52 "=": {
53 kind: "fn",
54 function: "=",
55 inputs: 2
56 },
57 "<": {
58 kind: "fn",
59 function: "<",
60 inputs: 2
61 },
62 "<=": {
63 kind: "fn",
64 function: "<=",
65 inputs: 2
66 },
67 ">": {
68 kind: "fn",
69 function: ">",
70 inputs: 2
71 },
72 ">=": {
73 kind: "fn",
74 function: ">=",
75 inputs: 2
76 },
7650046a
A
77 "read-string": {
78 kind: "fn",
79 function: "read-string",
80 inputs: 1
81 },
82 "slurp": {
83 kind: "fn",
84 function: "slurp",
85 inputs: 1
eedfbb43
A
86 },
87 "atom": {
88 kind: "fn",
89 function: "atom",
90 inputs: 1
91 },
92 "atom?": {
93 kind: "fn",
94 function: "atom?",
95 inputs: 1
96 },
97 "deref": {
98 kind: "fn",
99 function: "deref",
100 inputs: 1
101 },
102 "reset!": { # defined in interp
103 kind: "fn",
104 function: "reset!",
105 inputs: 2
106 },
107 "swap!": { # defined in interp
108 kind: "fn",
109 function: "swap!",
4db6de12 110 inputs: -3
a451ec51
A
111 },
112 "cons": {
113 kind: "fn",
114 function: "cons",
115 inputs: 2
116 },
117 "concat": {
118 kind: "fn",
119 function: "concat",
120 inputs: -1
e41d9de3
A
121 },
122 "nth": {
123 kind: "fn",
124 function: "nth",
125 inputs: 2
126 },
127 "first": {
128 kind: "fn",
129 function: "first",
130 inputs: 1
131 },
132 "rest": {
133 kind: "fn",
134 function: "rest",
135 inputs: 1
4db6de12
A
136 },
137 "throw": {
138 kind: "fn",
139 function: "throw",
140 inputs: 1
141 },
142 "apply": { # defined in interp
143 kind: "fn",
144 function: "apply",
145 inputs: -3
146 },
147 "map": { # defined in interp
148 kind: "fn",
149 function: "map",
150 inputs: 2
151 },
152 "nil?": {
153 kind: "fn",
154 function: "nil?",
155 inputs: 1
156 },
157 "true?": {
158 kind: "fn",
159 function: "true?",
160 inputs: 1
161 },
162 "false?": {
163 kind: "fn",
164 function: "false?",
165 inputs: 1
166 },
167 "symbol": {
168 kind: "fn",
169 function: "symbol",
170 inputs: 1
171 },
172 "symbol?": {
173 kind: "fn",
174 function: "symbol?",
175 inputs: 1
176 },
177 "keyword": {
178 kind: "fn",
179 function: "keyword",
180 inputs: 1
181 },
182 "keyword?": {
183 kind: "fn",
184 function: "keyword?",
185 inputs: 1
186 },
187 "vector": {
188 kind: "fn",
189 function: "vector",
190 inputs: -1
191 },
192 "vector?": {
193 kind: "fn",
194 function: "vector?",
195 inputs: 1
196 },
197 "sequential?": {
198 kind: "fn",
199 function: "sequential?",
200 inputs: 1
201 },
202 "hash-map": {
203 kind: "fn",
204 function: "hash-map",
205 inputs: -1
206 },
207 "map?": {
208 kind: "fn",
209 function: "map?",
210 inputs: 1
211 },
212 "assoc": {
213 kind: "fn",
214 function: "assoc",
215 inputs: -2
216 },
217 "dissoc": {
218 kind: "fn",
219 function: "dissoc",
220 inputs: -2
221 },
222 "get": {
223 kind: "fn",
224 function: "get",
225 inputs: 2
226 },
227 "contains?": {
228 kind: "fn",
229 function: "contains?",
230 inputs: 2
231 },
232 "keys": {
233 kind: "fn",
234 function: "keys",
235 inputs: 1
236 },
237 "vals": {
238 kind: "fn",
239 function: "vals",
240 inputs: 1
b103f95e
A
241 },
242 "string?": {
243 kind: "fn",
244 function: "string?",
245 inputs: 1
246 },
247 "fn?": {
248 kind: "fn",
249 function: "fn?",
250 inputs: 1
251 },
252 "number?": {
253 kind: "fn",
254 function: "number?",
255 inputs: 1
256 },
257 "macro?": {
258 kind: "fn",
259 function: "macro?",
260 inputs: 1
261 },
262 "readline": {
263 kind: "fn",
264 function: "readline",
265 inputs: 1
266 },
267 "time-ms": {
268 kind: "fn",
269 function: "time-ms",
270 inputs: 0
271 },
272 "meta": {
273 kind: "fn",
274 function: "meta",
275 inputs: 1
276 },
277 "with-meta": {
278 kind: "fn",
279 function: "with-meta",
280 inputs: 2
281 },
282 "seq": {
283 kind: "fn",
284 function: "seq",
285 inputs: 1
286 },
287 "conj": {
288 kind: "fn",
289 function: "conj",
290 inputs: -3
7650046a 291 }
da5289bb 292 };
51ff32e2 293
23f9ce8e
A
294def vec2list(obj):
295 if obj.kind == "list" then
296 obj.value | map(vec2list(.)) | wrap("list")
297 else
4db6de12
A
298 if obj.kind == "vector" then
299 obj.value | map(vec2list(.)) | wrap("list")
300 else
301 if obj.kind == "hashmap" then
302 obj.value | map_values(.value |= vec2list(.)) | wrap("hashmap")
303 else
304 obj
305 end
306 end
307 end;
23f9ce8e 308
fed3ca50
A
309def make_sequence:
310 . as $dot
311 | if .value|length == 0 then null | wrap("nil") else
312 (
313 select(.kind == "string") | .value | split("") | map(wrap("string"))
314 ) // (
315 select(.kind == "list" or .kind == "vector") | .value
316 ) // jqmal_error("cannot make sequence from \(.kind)") | wrap("list")
317 end;
318
51ff32e2
A
319def core_interp(arguments; env):
320 (
321 select(.function == "number_add") |
322 arguments | map(.value) | .[0] + .[1] | wrap("number")
23f9ce8e 323 ) // (
51ff32e2
A
324 select(.function == "number_sub") |
325 arguments | map(.value) | .[0] - .[1] | wrap("number")
326 ) // (
327 select(.function == "number_mul") |
328 arguments | map(.value) | .[0] * .[1] | wrap("number")
329 ) // (
330 select(.function == "number_div") |
331 arguments | map(.value) | .[0] / .[1] | wrap("number")
136fb719
A
332 ) // (
333 select(.function == "env") |
334 env | tojson | wrap("string")
da5289bb
A
335 ) // (
336 select(.function == "prn") |
83b974c5 337 arguments | map(pr_str(env; {readable: true})) | join(" ") | _display | null | wrap("nil")
da5289bb
A
338 ) // (
339 select(.function == "pr-str") |
fed3ca50 340 arguments | map(pr_str(env; {readable: true})) | join(" ") | wrap("string")
da5289bb
A
341 ) // (
342 select(.function == "str") |
fed3ca50 343 arguments | map(pr_str(env; {readable: false})) | join("") | wrap("string")
da5289bb
A
344 ) // (
345 select(.function == "println") |
83b974c5 346 arguments | map(pr_str(env; {readable: false})) | join(" ") | _display | null | wrap("nil")
da5289bb
A
347 ) // (
348 select(.function == "list") |
349 arguments | wrap("list")
350 ) // (
351 select(.function == "list?") | null | wrap(arguments | first.kind == "list" | tostring)
352 ) // (
353 select(.function == "empty?") | null | wrap(arguments|first.value | length == 0 | tostring)
354 ) // (
355 select(.function == "count") | arguments|first.value | length | wrap("number")
356 ) // (
23f9ce8e 357 select(.function == "=") | null | wrap(vec2list(arguments[0]) == vec2list(arguments[1]) | tostring)
da5289bb
A
358 ) // (
359 select(.function == "<") | null | wrap(arguments[0].value < arguments[1].value | tostring)
360 ) // (
361 select(.function == "<=") | null | wrap(arguments[0].value <= arguments[1].value | tostring)
362 ) // (
363 select(.function == ">") | null | wrap(arguments[0].value > arguments[1].value | tostring)
364 ) // (
365 select(.function == ">=") | null | wrap(arguments[0].value >= arguments[1].value | tostring)
7650046a
A
366 ) // (
367 select(.function == "slurp") | arguments | map(.value) | issue_extern("read") | wrap("string")
368 ) // (
369 select(.function == "read-string") | arguments | first.value | read_str | read_form.value
eedfbb43
A
370 ) // (
371 select(.function == "atom?") | null | wrap(arguments | first.kind == "atom" | tostring)
a451ec51
A
372 ) // (
373 select(.function == "cons") | ([arguments[0]] + arguments[1].value) | wrap("list")
374 ) // (
375 select(.function == "concat") | arguments | map(.value) | (add//[]) | wrap("list")
e41d9de3
A
376 ) // (
377 select(.function == "nth")
b103f95e 378 | _debug(arguments)
e41d9de3
A
379 | arguments[0].value as $lst
380 | arguments[1].value as $idx
381 | if ($lst|length < $idx) or ($idx < 0) then
382 jqmal_error("index out of range")
383 else
384 $lst[$idx]
385 end
386 ) // (
387 select(.function == "first") | arguments[0].value | first // {kind:"nil"}
388 ) // (
389 select(.function == "rest") | arguments[0]?.value?[1:]? // [] | wrap("list")
4db6de12
A
390 ) // (
391 select(.function == "throw") | jqmal_error(arguments[0] | tojson)
392 ) // (
393 select(.function == "nil?") | null | wrap((arguments[0].kind == "nil") | tostring)
394 ) // (
395 select(.function == "true?") | null | wrap((arguments[0].kind == "true") | tostring)
396 ) // (
397 select(.function == "false?") | null | wrap((arguments[0].kind == "false") | tostring)
398 ) // (
399 select(.function == "symbol?") | null | wrap((arguments[0].kind == "symbol") | tostring)
400 ) // (
401 select(.function == "symbol") | arguments[0].value | wrap("symbol")
402 ) // (
403 select(.function == "keyword") | arguments[0].value | wrap("keyword")
404 ) // (
405 select(.function == "keyword?") | null | wrap((arguments[0].kind == "keyword") | tostring)
406 ) // (
407 select(.function == "vector") | arguments | wrap("vector")
408 ) // (
409 select(.function == "vector?") | null | wrap((arguments[0].kind == "vector") | tostring)
410 ) // (
411 select(.function == "sequential?") | null | wrap((arguments[0].kind == "vector" or arguments[0].kind == "list") | tostring)
412 ) // (
413 select(.function == "hash-map") |
414 if (arguments|length) % 2 == 1 then
415 jqmal_error("Odd number of arguments to hash-map")
416 else
417 [ arguments |
418 nwise(2) |
419 try {
420 key: (.[0] | extract_string),
421 value: {
422 kkind: .[0].kind,
423 value: .[1]
424 }
425 }
426 ] | from_entries | wrap("hashmap")
427 end
428 ) // (
429 select(.function == "map?") | null | wrap((arguments[0].kind == "hashmap") | tostring)
430 ) // (
431 select(.function == "assoc") |
432 if (arguments|length) % 2 == 0 then
433 jqmal_error("Odd number of key-values to assoc")
434 else
435 arguments[0].value + ([ arguments[1:] |
436 nwise(2) |
437 try {
438 key: (.[0] | extract_string),
439 value: {
440 kkind: .[0].kind,
441 value: .[1]
442 }
443 }
444 ] | from_entries) | wrap("hashmap")
445 end
446 ) // (
447 select(.function == "dissoc") |
448 arguments[1:] | map(.value) as $keynames |
449 arguments[0].value | with_entries(select(.key as $k | $keynames | contains([$k]) | not)) | wrap("hashmap")
450 ) // (
451 select(.function == "get") | arguments[0].value[arguments[1].value].value // {kind:"nil"}
452 ) // (
453 select(.function == "contains?") | null | wrap((arguments[0].value | has(arguments[1].value)) | tostring)
454 ) // (
455 select(.function == "keys") | arguments[0].value | with_entries(.value as $v | .key as $k | {key: $k, value: {value: $k, kind: $v.kkind}}) | to_entries | map(.value) | wrap("list")
456 ) // (
457 select(.function == "vals") | arguments[0].value | map(.value) | to_entries | map(.value) | wrap("list")
b103f95e
A
458 ) // (
459 select(.function == "string?") | null | wrap((arguments[0].kind == "string") | tostring)
460 ) // (
fed3ca50 461 select(.function == "fn?") | null | wrap((arguments[0].kind == "fn" or (arguments[0].kind == "function" and (arguments[0].is_macro|not))) | tostring)
b103f95e
A
462 ) // (
463 select(.function == "number?") | null | wrap((arguments[0].kind == "number") | tostring)
464 ) // (
465 select(.function == "macro?") | null | wrap((arguments[0].is_macro == true) | tostring)
466 ) // (
467 select(.function == "readline") | arguments[0].value | __readline | wrap("string")
468 ) // (
469 select(.function == "time-ms") | now * 1000 | wrap("number")
470 ) // (
471 select(.function == "meta") | arguments[0].meta // {kind:"nil"}
472 ) // (
473 select(.function == "with-meta") | arguments[0] | .meta |= arguments[1]
fed3ca50
A
474 ) // (
475 select(.function == "seq") | arguments[0] | make_sequence
476 ) // (
477 select(.function == "conj")
478 | arguments[0] as $orig
479 | arguments[1:] as $stuff
480 | if $orig.kind == "list" then
481 [ $stuff|reverse[], $orig.value[] ] | wrap("list")
482 else
483 [ $orig.value[], $stuff[] ] | wrap("vector")
484 end
597522fa 485 ) // jqmal_error("Unknown native function \(.function)");