Change quasiquote algorithm
[jackhill/mal.git] / impls / groovy / core.groovy
CommitLineData
a9cd6543
JM
1import types
2import types.MalException
3import types.MalSymbol
3d1dbb20 4import types.MalFunc
a9cd6543
JM
5import reader
6import printer
7
8class core {
9 def static do_pr_str(args) {
10 return printer._pr_list(args, " ", true)
11 }
12 def static do_str(args) {
13 return printer._pr_list(args, "", false)
14 }
15 def static do_prn(args) {
16 println(printer._pr_list(args, " ", true))
17 }
18 def static do_println(args) {
19 println(printer._pr_list(args, " ", false))
20 }
21
22 def static do_concat(args) {
23 args.inject([], { a, b -> a + (b as List) })
24 }
25 def static do_nth(args) {
26 if (args[0].size() <= args[1]) {
27 throw new MalException("nth: index out of range")
28 }
29 args[0][args[1]]
30 }
31 def static do_apply(args) {
32 def start_args = args.drop(1).take(args.size()-2) as List
33 args[0](start_args + (args.last() as List))
34 }
35
36 def static do_swap_BANG(args) {
37 def (atm,f) = [args[0], args[1]]
38 atm.value = f([atm.value] + (args.drop(2) as List))
39 }
40
8e32dbb6
JM
41 def static do_conj(args) {
42 if (types.list_Q(args[0])) {
43 args.drop(1).inject(args[0], { a, b -> [b] + a })
44 } else {
45 types.vector(args.drop(1).inject(args[0], { a, b -> a + [b] }))
46 }
47 }
48 def static do_seq(args) {
49 def obj = args[0]
50 switch (obj) {
51 case { types.list_Q(obj) }:
52 return obj.size() == 0 ? null : obj
53 case { types.vector_Q(obj) }:
54 return obj.size() == 0 ? null : obj.clone()
55 case { types.string_Q(obj) }:
56 return obj.size() == 0 ? null : obj.collect{ it.toString() }
57 case null:
58 return null
59 default:
60 throw new MalException("seq: called on non-sequence")
61 }
62 }
63
a9cd6543
JM
64 static ns = [
65 "=": { a -> a[0]==a[1]},
66 "throw": { a -> throw new MalException(a[0]) },
67
68 "nil?": { a -> a[0] == null },
69 "true?": { a -> a[0] == true },
70 "false?": { a -> a[0] == false },
8e32dbb6 71 "string?": { a -> types.string_Q(a[0]) },
a9cd6543
JM
72 "symbol": { a -> new MalSymbol(a[0]) },
73 "symbol?": { a -> a[0] instanceof MalSymbol },
74 "keyword": { a -> types.keyword(a[0]) },
75 "keyword?": { a -> types.keyword_Q(a[0]) },
3d1dbb20
JM
76 "number?": { a -> a[0] instanceof Integer },
77 "fn?": { a -> (a[0] instanceof MalFunc && !a[0].ismacro) ||
78 a[0] instanceof Closure },
79 "macro?": { a -> a[0] instanceof MalFunc && a[0].ismacro },
a9cd6543
JM
80
81 "pr-str": core.&do_pr_str,
82 "str": core.&do_str,
83 "prn": core.&do_prn,
84 "println": core.&do_println,
85 "read-string": reader.&read_str,
86 "readline": { a -> System.console().readLine(a[0]) },
87 "slurp": { a -> new File(a[0]).text },
88
89 "<": { a -> a[0]<a[1]},
90 "<=": { a -> a[0]<=a[1]},
91 ">": { a -> a[0]>a[1]},
92 ">=": { a -> a[0]>=a[1]},
93 "+": { a -> a[0]+a[1]},
94 "-": { a -> a[0]-a[1]},
95 "*": { a -> a[0]*a[1]},
96 "/": { a -> a[0]/a[1]}, // /
97 "time-ms": { a -> System.currentTimeMillis() },
98
99 "list": { a -> a},
100 "list?": { a -> types.list_Q(a[0]) },
101 "vector": { a -> types.vector(a) },
102 "vector?": { a -> types.vector_Q(a[0]) },
103 "hash-map": { a -> types.hash_map(a) },
104 "map?": { a -> types.hash_map_Q(a[0]) },
105 "assoc": { a -> types.assoc_BANG(types.copy(a[0]), a.drop(1)) },
106 "dissoc": { a -> types.dissoc_BANG(types.copy(a[0]), a.drop(1)) },
107 "get": { a -> a[0] == null ? null : a[0][a[1]] },
108 "contains?": { a -> a[0].containsKey(a[1]) },
109 "keys": { a -> a[0].keySet() as List },
110 "vals": { a -> a[0].values() as List },
111
112 "sequential?": { a -> types.&sequential_Q(a[0]) },
113 "cons": { a -> [a[0]] + (a[1] as List) },
114 "concat": core.&do_concat,
fbfe6784 115 "vec": { a -> types.vector_Q(a[0]) ? a[0] : types.vector(a[0]) },
a9cd6543 116 "nth": core.&do_nth,
c36d5b39
DM
117 "first": { a -> a[0] == null || a[0].size() == 0 ? null : a[0][0] },
118 "rest": { a -> a[0] == null ? [] as List : a[0].drop(1) },
a9cd6543
JM
119 "empty?": { a -> a[0] == null || a[0].size() == 0 },
120 "count": { a -> a[0] == null ? 0 : a[0].size() },
121 "apply": core.&do_apply,
122 "map": { a -> a[1].collect { x -> a[0].call([x]) } },
123
4ed89670 124 "conj": core.&do_conj,
8e32dbb6 125 "seq": core.&do_seq,
a9cd6543
JM
126
127 "meta": { a -> a[0].hasProperty("meta") ? a[0].getProperties().meta : null },
128 "with-meta": { a -> def b = types.copy(a[0]); b.getMetaClass().meta = a[1]; b },
129 "atom": { a -> new types.MalAtom(a[0]) },
130 "atom?": { a -> a[0] instanceof types.MalAtom },
131 "deref": { a -> a[0].value },
132 "reset!": { a -> a[0].value = a[1] },
133 "swap!": core.&do_swap_BANG
134 ]
135}
136