conjure-js 0.0.11 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cli/conjure-js.mjs +9336 -5028
- package/dist-vite-plugin/index.mjs +10455 -0
- package/package.json +9 -2
- package/src/bin/cli.ts +2 -2
- package/src/bin/nrepl-symbol.ts +150 -0
- package/src/bin/nrepl.ts +301 -157
- package/src/bin/version.ts +1 -1
- package/src/clojure/core.clj +764 -29
- package/src/clojure/core.clj.d.ts +76 -4
- package/src/clojure/demo/math.clj +5 -1
- package/src/clojure/generated/builtin-namespace-registry.ts +4 -0
- package/src/clojure/generated/clojure-core-source.ts +765 -29
- package/src/clojure/generated/clojure-set-source.ts +136 -0
- package/src/clojure/generated/clojure-walk-source.ts +72 -0
- package/src/clojure/set.clj +132 -0
- package/src/clojure/set.clj.d.ts +20 -0
- package/src/clojure/string.clj.d.ts +14 -0
- package/src/clojure/walk.clj +68 -0
- package/src/clojure/walk.clj.d.ts +7 -0
- package/src/core/assertions.ts +114 -6
- package/src/core/bootstrap.ts +337 -0
- package/src/core/conversions.ts +48 -31
- package/src/core/core-module.ts +303 -0
- package/src/core/env.ts +42 -7
- package/src/core/errors.ts +8 -0
- package/src/core/evaluator/apply.ts +40 -25
- package/src/core/evaluator/arity.ts +8 -8
- package/src/core/evaluator/async-evaluator.ts +565 -0
- package/src/core/evaluator/collections.ts +30 -4
- package/src/core/evaluator/destructure.ts +180 -69
- package/src/core/evaluator/dispatch.ts +24 -14
- package/src/core/evaluator/evaluate.ts +22 -20
- package/src/core/evaluator/expand.ts +45 -15
- package/src/core/evaluator/form-parsers.ts +178 -0
- package/src/core/evaluator/index.ts +7 -9
- package/src/core/evaluator/js-interop.ts +189 -0
- package/src/core/evaluator/quasiquote.ts +14 -8
- package/src/core/evaluator/recur-check.ts +6 -6
- package/src/core/evaluator/special-forms.ts +380 -173
- package/src/core/factories.ts +182 -3
- package/src/core/index.ts +55 -5
- package/src/core/module.ts +136 -0
- package/src/core/ns-forms.ts +107 -0
- package/src/core/positions.ts +9 -2
- package/src/core/printer.ts +371 -11
- package/src/core/reader.ts +127 -29
- package/src/core/registry.ts +209 -0
- package/src/core/runtime.ts +376 -0
- package/src/core/session.ts +263 -478
- package/src/core/stdlib/arithmetic.ts +516 -215
- package/src/core/stdlib/async-fns.ts +132 -0
- package/src/core/stdlib/atoms.ts +286 -63
- package/src/core/stdlib/errors.ts +54 -50
- package/src/core/stdlib/hof.ts +74 -173
- package/src/core/stdlib/js-namespace.ts +344 -0
- package/src/core/stdlib/lazy.ts +34 -0
- package/src/core/stdlib/maps-sets.ts +322 -0
- package/src/core/stdlib/meta.ts +109 -28
- package/src/core/stdlib/predicates.ts +322 -196
- package/src/core/stdlib/regex.ts +126 -98
- package/src/core/stdlib/seq.ts +564 -0
- package/src/core/stdlib/strings.ts +164 -135
- package/src/core/stdlib/transducers.ts +95 -100
- package/src/core/stdlib/utils.ts +283 -147
- package/src/core/stdlib/vars.ts +27 -27
- package/src/core/stdlib/vectors.ts +122 -0
- package/src/core/tokenizer.ts +13 -3
- package/src/core/transformations.ts +117 -9
- package/src/core/types.ts +118 -6
- package/src/host/node-host-module.ts +74 -0
- package/src/nrepl/relay.ts +432 -0
- package/src/vite-plugin-clj/codegen.ts +87 -95
- package/src/vite-plugin-clj/index.ts +242 -18
- package/src/vite-plugin-clj/namespace-utils.ts +39 -0
- package/src/vite-plugin-clj/static-analysis.ts +211 -0
- package/src/clojure/demo.clj +0 -63
- package/src/clojure/demo.clj.d.ts +0 -0
- package/src/core/core-env.ts +0 -60
- package/src/core/stdlib/collections.ts +0 -784
- package/src/host/node.ts +0 -55
|
@@ -1,361 +1,662 @@
|
|
|
1
|
+
import { is } from '../assertions'
|
|
1
2
|
import { EvaluationError } from '../errors'
|
|
2
|
-
import {
|
|
3
|
-
import { isEqual } from '../assertions'
|
|
3
|
+
import { v } from '../factories'
|
|
4
4
|
import { printString } from '../printer'
|
|
5
|
-
import
|
|
5
|
+
import { toSeq } from '../transformations'
|
|
6
|
+
import type { CljList, CljNumber, CljValue, CljVector } from '../types'
|
|
6
7
|
|
|
7
8
|
export const arithmeticFunctions: Record<string, CljValue> = {
|
|
8
|
-
'+':
|
|
9
|
-
|
|
9
|
+
'+': v
|
|
10
|
+
.nativeFn('+', function add(...nums: CljValue[]) {
|
|
10
11
|
if (nums.length === 0) {
|
|
11
|
-
return
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
return v.number(0)
|
|
13
|
+
}
|
|
14
|
+
const badIdx = nums.findIndex(function isNotNumber(a) {
|
|
15
|
+
return a.kind !== 'number'
|
|
16
|
+
})
|
|
17
|
+
if (badIdx !== -1) {
|
|
18
|
+
throw EvaluationError.atArg(
|
|
19
|
+
'+ expects all arguments to be numbers',
|
|
20
|
+
{ args: nums },
|
|
21
|
+
badIdx
|
|
22
|
+
)
|
|
17
23
|
}
|
|
18
|
-
return nums.reduce((acc, arg)
|
|
19
|
-
return
|
|
20
|
-
},
|
|
21
|
-
})
|
|
22
|
-
'Returns the sum of the arguments. Throws on non-number arguments.',
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
return nums.reduce(function sumNumbers(acc, arg) {
|
|
25
|
+
return v.number((acc as CljNumber).value + (arg as CljNumber).value)
|
|
26
|
+
}, v.number(0))
|
|
27
|
+
})
|
|
28
|
+
.doc('Returns the sum of the arguments. Throws on non-number arguments.', [
|
|
29
|
+
['&', 'nums'],
|
|
30
|
+
]),
|
|
25
31
|
|
|
26
|
-
'-':
|
|
27
|
-
|
|
32
|
+
'-': v
|
|
33
|
+
.nativeFn('-', function subtract(...nums: CljValue[]) {
|
|
28
34
|
if (nums.length === 0) {
|
|
29
35
|
throw new EvaluationError('- expects at least one argument', {
|
|
30
36
|
args: nums,
|
|
31
37
|
})
|
|
32
38
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
const badIdx = nums.findIndex(function isNotNumber(a) {
|
|
40
|
+
return a.kind !== 'number'
|
|
41
|
+
})
|
|
42
|
+
if (badIdx !== -1) {
|
|
43
|
+
throw EvaluationError.atArg(
|
|
44
|
+
'- expects all arguments to be numbers',
|
|
45
|
+
{ args: nums },
|
|
46
|
+
badIdx
|
|
47
|
+
)
|
|
37
48
|
}
|
|
38
|
-
return nums.slice(1).reduce((acc, arg)
|
|
39
|
-
return
|
|
49
|
+
return nums.slice(1).reduce(function subtractNumbers(acc, arg) {
|
|
50
|
+
return v.number((acc as CljNumber).value - (arg as CljNumber).value)
|
|
40
51
|
}, nums[0] as CljNumber)
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
52
|
+
})
|
|
53
|
+
.doc(
|
|
54
|
+
'Returns the difference of the arguments. Throws on non-number arguments.',
|
|
55
|
+
[['&', 'nums']]
|
|
56
|
+
),
|
|
45
57
|
|
|
46
|
-
'*':
|
|
47
|
-
|
|
58
|
+
'*': v
|
|
59
|
+
.nativeFn('*', function multiply(...nums: CljValue[]) {
|
|
48
60
|
if (nums.length === 0) {
|
|
49
|
-
return
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
return v.number(1)
|
|
62
|
+
}
|
|
63
|
+
const badIdx = nums.findIndex(function isNotNumber(a) {
|
|
64
|
+
return a.kind !== 'number'
|
|
65
|
+
})
|
|
66
|
+
if (badIdx !== -1) {
|
|
67
|
+
throw EvaluationError.atArg(
|
|
68
|
+
'* expects all arguments to be numbers',
|
|
69
|
+
{ args: nums },
|
|
70
|
+
badIdx
|
|
71
|
+
)
|
|
55
72
|
}
|
|
56
|
-
return nums.slice(1).reduce((acc, arg)
|
|
57
|
-
return
|
|
73
|
+
return nums.slice(1).reduce(function multiplyNumbers(acc, arg) {
|
|
74
|
+
return v.number((acc as CljNumber).value * (arg as CljNumber).value)
|
|
58
75
|
}, nums[0] as CljNumber)
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
76
|
+
})
|
|
77
|
+
.doc(
|
|
78
|
+
'Returns the product of the arguments. Throws on non-number arguments.',
|
|
79
|
+
[['&', 'nums']]
|
|
80
|
+
),
|
|
63
81
|
|
|
64
|
-
'/':
|
|
65
|
-
|
|
82
|
+
'/': v
|
|
83
|
+
.nativeFn('/', function divide(...nums: CljValue[]) {
|
|
66
84
|
if (nums.length === 0) {
|
|
67
85
|
throw new EvaluationError('/ expects at least one argument', {
|
|
68
86
|
args: nums,
|
|
69
87
|
})
|
|
70
88
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
89
|
+
const badIdx = nums.findIndex(function isNotNumber(a) {
|
|
90
|
+
return a.kind !== 'number'
|
|
91
|
+
})
|
|
92
|
+
if (badIdx !== -1) {
|
|
93
|
+
throw EvaluationError.atArg(
|
|
94
|
+
'/ expects all arguments to be numbers',
|
|
95
|
+
{ args: nums },
|
|
96
|
+
badIdx
|
|
97
|
+
)
|
|
75
98
|
}
|
|
76
|
-
return nums.slice(1).reduce((acc, arg)
|
|
99
|
+
return nums.slice(1).reduce(function divideNumbers(acc, arg, reduceIdx) {
|
|
77
100
|
if ((arg as CljNumber).value === 0) {
|
|
78
|
-
|
|
101
|
+
const err = new EvaluationError('division by zero', { args: nums })
|
|
102
|
+
err.data = { argIndex: reduceIdx + 1 }
|
|
103
|
+
throw err
|
|
79
104
|
}
|
|
80
|
-
return
|
|
105
|
+
return v.number((acc as CljNumber).value / (arg as CljNumber).value)
|
|
81
106
|
}, nums[0] as CljNumber)
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
107
|
+
})
|
|
108
|
+
.doc(
|
|
109
|
+
'Returns the quotient of the arguments. Throws on non-number arguments or division by zero.',
|
|
110
|
+
[['&', 'nums']]
|
|
111
|
+
),
|
|
86
112
|
|
|
87
|
-
'>':
|
|
88
|
-
|
|
113
|
+
'>': v
|
|
114
|
+
.nativeFn('>', function greaterThan(...nums: CljValue[]) {
|
|
89
115
|
if (nums.length < 2) {
|
|
90
116
|
throw new EvaluationError('> expects at least two arguments', {
|
|
91
117
|
args: nums,
|
|
92
118
|
})
|
|
93
119
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
120
|
+
const badIdx = nums.findIndex(function isNotNumber(a) {
|
|
121
|
+
return a.kind !== 'number'
|
|
122
|
+
})
|
|
123
|
+
if (badIdx !== -1) {
|
|
124
|
+
throw EvaluationError.atArg(
|
|
125
|
+
'> expects all arguments to be numbers',
|
|
126
|
+
{ args: nums },
|
|
127
|
+
badIdx
|
|
128
|
+
)
|
|
98
129
|
}
|
|
99
130
|
for (let i = 1; i < nums.length; i++) {
|
|
100
131
|
if ((nums[i] as CljNumber).value >= (nums[i - 1] as CljNumber).value) {
|
|
101
|
-
return
|
|
132
|
+
return v.boolean(false)
|
|
102
133
|
}
|
|
103
134
|
}
|
|
104
|
-
return
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
135
|
+
return v.boolean(true)
|
|
136
|
+
})
|
|
137
|
+
.doc(
|
|
138
|
+
'Compares adjacent arguments left to right, returns true if all values are in ascending order, false otherwise.',
|
|
139
|
+
[['&', 'nums']]
|
|
140
|
+
),
|
|
109
141
|
|
|
110
|
-
'<':
|
|
111
|
-
|
|
142
|
+
'<': v
|
|
143
|
+
.nativeFn('<', function lessThan(...nums: CljValue[]) {
|
|
112
144
|
if (nums.length < 2) {
|
|
113
145
|
throw new EvaluationError('< expects at least two arguments', {
|
|
114
146
|
args: nums,
|
|
115
147
|
})
|
|
116
148
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
149
|
+
const badIdx = nums.findIndex(function isNotNumber(a) {
|
|
150
|
+
return a.kind !== 'number'
|
|
151
|
+
})
|
|
152
|
+
if (badIdx !== -1) {
|
|
153
|
+
throw EvaluationError.atArg(
|
|
154
|
+
'< expects all arguments to be numbers',
|
|
155
|
+
{ args: nums },
|
|
156
|
+
badIdx
|
|
157
|
+
)
|
|
121
158
|
}
|
|
122
159
|
for (let i = 1; i < nums.length; i++) {
|
|
123
160
|
if ((nums[i] as CljNumber).value <= (nums[i - 1] as CljNumber).value) {
|
|
124
|
-
return
|
|
161
|
+
return v.boolean(false)
|
|
125
162
|
}
|
|
126
163
|
}
|
|
127
|
-
return
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
164
|
+
return v.boolean(true)
|
|
165
|
+
})
|
|
166
|
+
.doc(
|
|
167
|
+
'Compares adjacent arguments left to right, returns true if all values are in descending order, false otherwise.',
|
|
168
|
+
[['&', 'nums']]
|
|
169
|
+
),
|
|
132
170
|
|
|
133
|
-
'>=':
|
|
134
|
-
|
|
171
|
+
'>=': v
|
|
172
|
+
.nativeFn('>=', function greaterThanOrEqual(...nums: CljValue[]) {
|
|
135
173
|
if (nums.length < 2) {
|
|
136
174
|
throw new EvaluationError('>= expects at least two arguments', {
|
|
137
175
|
args: nums,
|
|
138
176
|
})
|
|
139
177
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
178
|
+
const badIdx = nums.findIndex(function isNotNumber(a) {
|
|
179
|
+
return a.kind !== 'number'
|
|
180
|
+
})
|
|
181
|
+
if (badIdx !== -1) {
|
|
182
|
+
throw EvaluationError.atArg(
|
|
183
|
+
'>= expects all arguments to be numbers',
|
|
184
|
+
{ args: nums },
|
|
185
|
+
badIdx
|
|
186
|
+
)
|
|
144
187
|
}
|
|
145
188
|
for (let i = 1; i < nums.length; i++) {
|
|
146
189
|
if ((nums[i] as CljNumber).value > (nums[i - 1] as CljNumber).value) {
|
|
147
|
-
return
|
|
190
|
+
return v.boolean(false)
|
|
148
191
|
}
|
|
149
192
|
}
|
|
150
|
-
return
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
193
|
+
return v.boolean(true)
|
|
194
|
+
})
|
|
195
|
+
.doc(
|
|
196
|
+
'Compares adjacent arguments left to right, returns true if all comparisons returns true for greater than or equal to checks, false otherwise.',
|
|
197
|
+
[['&', 'nums']]
|
|
198
|
+
),
|
|
155
199
|
|
|
156
|
-
'<=':
|
|
157
|
-
|
|
200
|
+
'<=': v
|
|
201
|
+
.nativeFn('<=', function lessThanOrEqual(...nums: CljValue[]) {
|
|
158
202
|
if (nums.length < 2) {
|
|
159
203
|
throw new EvaluationError('<= expects at least two arguments', {
|
|
160
204
|
args: nums,
|
|
161
205
|
})
|
|
162
206
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
207
|
+
const badIdx = nums.findIndex(function isNotNumber(a) {
|
|
208
|
+
return a.kind !== 'number'
|
|
209
|
+
})
|
|
210
|
+
if (badIdx !== -1) {
|
|
211
|
+
throw EvaluationError.atArg(
|
|
212
|
+
'<= expects all arguments to be numbers',
|
|
213
|
+
{ args: nums },
|
|
214
|
+
badIdx
|
|
215
|
+
)
|
|
167
216
|
}
|
|
168
217
|
for (let i = 1; i < nums.length; i++) {
|
|
169
218
|
if ((nums[i] as CljNumber).value < (nums[i - 1] as CljNumber).value) {
|
|
170
|
-
return
|
|
219
|
+
return v.boolean(false)
|
|
171
220
|
}
|
|
172
221
|
}
|
|
173
|
-
return
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
222
|
+
return v.boolean(true)
|
|
223
|
+
})
|
|
224
|
+
.doc(
|
|
225
|
+
'Compares adjacent arguments left to right, returns true if all comparisons returns true for less than or equal to checks, false otherwise.',
|
|
226
|
+
[['&', 'nums']]
|
|
227
|
+
),
|
|
178
228
|
|
|
179
|
-
'=':
|
|
180
|
-
|
|
229
|
+
'=': v
|
|
230
|
+
.nativeFn('=', function equals(...vals: CljValue[]) {
|
|
181
231
|
if (vals.length < 2) {
|
|
182
232
|
throw new EvaluationError('= expects at least two arguments', {
|
|
183
233
|
args: vals,
|
|
184
234
|
})
|
|
185
235
|
}
|
|
186
236
|
for (let i = 1; i < vals.length; i++) {
|
|
187
|
-
if (!
|
|
188
|
-
return
|
|
237
|
+
if (!is.equal(vals[i], vals[i - 1])) {
|
|
238
|
+
return v.boolean(false)
|
|
189
239
|
}
|
|
190
240
|
}
|
|
191
|
-
return
|
|
192
|
-
})
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
241
|
+
return v.boolean(true)
|
|
242
|
+
})
|
|
243
|
+
.doc(
|
|
244
|
+
'Compares adjacent arguments left to right, returns true if all values are structurally equal, false otherwise.',
|
|
245
|
+
[['&', 'vals']]
|
|
246
|
+
),
|
|
196
247
|
|
|
197
|
-
inc:
|
|
198
|
-
|
|
248
|
+
inc: v
|
|
249
|
+
.nativeFn('inc', function increment(x: CljValue) {
|
|
199
250
|
if (x === undefined || x.kind !== 'number') {
|
|
200
|
-
throw
|
|
251
|
+
throw EvaluationError.atArg(
|
|
201
252
|
`inc expects a number${x !== undefined ? `, got ${printString(x)}` : ''}`,
|
|
202
|
-
{ x }
|
|
253
|
+
{ x },
|
|
254
|
+
0
|
|
203
255
|
)
|
|
204
256
|
}
|
|
205
|
-
return
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
257
|
+
return v.number((x as CljNumber).value + 1)
|
|
258
|
+
})
|
|
259
|
+
.doc(
|
|
260
|
+
'Returns the argument incremented by 1. Throws on non-number arguments.',
|
|
261
|
+
[['x']]
|
|
262
|
+
),
|
|
210
263
|
|
|
211
|
-
dec:
|
|
212
|
-
|
|
264
|
+
dec: v
|
|
265
|
+
.nativeFn('dec', function decrement(x: CljValue) {
|
|
213
266
|
if (x === undefined || x.kind !== 'number') {
|
|
214
|
-
throw
|
|
267
|
+
throw EvaluationError.atArg(
|
|
215
268
|
`dec expects a number${x !== undefined ? `, got ${printString(x)}` : ''}`,
|
|
216
|
-
{ x }
|
|
269
|
+
{ x },
|
|
270
|
+
0
|
|
217
271
|
)
|
|
218
272
|
}
|
|
219
|
-
return
|
|
220
|
-
})
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
273
|
+
return v.number((x as CljNumber).value - 1)
|
|
274
|
+
})
|
|
275
|
+
.doc(
|
|
276
|
+
'Returns the argument decremented by 1. Throws on non-number arguments.',
|
|
277
|
+
[['x']]
|
|
278
|
+
),
|
|
224
279
|
|
|
225
|
-
max:
|
|
226
|
-
|
|
280
|
+
max: v
|
|
281
|
+
.nativeFn('max', function maximum(...nums: CljValue[]) {
|
|
227
282
|
if (nums.length === 0) {
|
|
228
283
|
throw new EvaluationError('max expects at least one argument', {
|
|
229
284
|
args: nums,
|
|
230
285
|
})
|
|
231
286
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
287
|
+
const badIdx = nums.findIndex(function isNotNumber(a) {
|
|
288
|
+
return a.kind !== 'number'
|
|
289
|
+
})
|
|
290
|
+
if (badIdx !== -1) {
|
|
291
|
+
throw EvaluationError.atArg(
|
|
292
|
+
'max expects all arguments to be numbers',
|
|
293
|
+
{ args: nums },
|
|
294
|
+
badIdx
|
|
295
|
+
)
|
|
236
296
|
}
|
|
237
|
-
return nums.reduce((best, arg)
|
|
238
|
-
(arg as CljNumber).value > (best as CljNumber).value ? arg : best
|
|
239
|
-
)
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
297
|
+
return nums.reduce(function findMax(best, arg) {
|
|
298
|
+
return (arg as CljNumber).value > (best as CljNumber).value ? arg : best
|
|
299
|
+
})
|
|
300
|
+
})
|
|
301
|
+
.doc(
|
|
302
|
+
'Returns the largest of the arguments. Throws on non-number arguments.',
|
|
303
|
+
[['&', 'nums']]
|
|
304
|
+
),
|
|
244
305
|
|
|
245
|
-
min:
|
|
246
|
-
|
|
306
|
+
min: v
|
|
307
|
+
.nativeFn('min', function minimum(...nums: CljValue[]) {
|
|
247
308
|
if (nums.length === 0) {
|
|
248
309
|
throw new EvaluationError('min expects at least one argument', {
|
|
249
310
|
args: nums,
|
|
250
311
|
})
|
|
251
312
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
313
|
+
const badIdx = nums.findIndex(function isNotNumber(a) {
|
|
314
|
+
return a.kind !== 'number'
|
|
315
|
+
})
|
|
316
|
+
if (badIdx !== -1) {
|
|
317
|
+
throw EvaluationError.atArg(
|
|
318
|
+
'min expects all arguments to be numbers',
|
|
319
|
+
{ args: nums },
|
|
320
|
+
badIdx
|
|
321
|
+
)
|
|
256
322
|
}
|
|
257
|
-
return nums.reduce((best, arg)
|
|
258
|
-
(arg as CljNumber).value < (best as CljNumber).value ? arg : best
|
|
259
|
-
)
|
|
260
|
-
})
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
323
|
+
return nums.reduce(function findMin(best, arg) {
|
|
324
|
+
return (arg as CljNumber).value < (best as CljNumber).value ? arg : best
|
|
325
|
+
})
|
|
326
|
+
})
|
|
327
|
+
.doc(
|
|
328
|
+
'Returns the smallest of the arguments. Throws on non-number arguments.',
|
|
329
|
+
[['&', 'nums']]
|
|
330
|
+
),
|
|
264
331
|
|
|
265
|
-
mod:
|
|
266
|
-
|
|
332
|
+
mod: v
|
|
333
|
+
.nativeFn('mod', function modulo(n: CljValue, d: CljValue) {
|
|
267
334
|
if (n === undefined || n.kind !== 'number') {
|
|
268
|
-
throw
|
|
335
|
+
throw EvaluationError.atArg(
|
|
269
336
|
`mod expects a number as first argument${n !== undefined ? `, got ${printString(n)}` : ''}`,
|
|
270
|
-
{ n }
|
|
337
|
+
{ n },
|
|
338
|
+
0
|
|
271
339
|
)
|
|
272
340
|
}
|
|
273
341
|
if (d === undefined || d.kind !== 'number') {
|
|
274
|
-
throw
|
|
342
|
+
throw EvaluationError.atArg(
|
|
275
343
|
`mod expects a number as second argument${d !== undefined ? `, got ${printString(d)}` : ''}`,
|
|
276
|
-
{ d }
|
|
344
|
+
{ d },
|
|
345
|
+
1
|
|
277
346
|
)
|
|
278
347
|
}
|
|
279
348
|
if ((d as CljNumber).value === 0) {
|
|
280
|
-
|
|
349
|
+
const err = new EvaluationError('mod: division by zero', { n, d })
|
|
350
|
+
err.data = { argIndex: 1 }
|
|
351
|
+
throw err
|
|
281
352
|
}
|
|
282
353
|
// Clojure mod always returns non-negative when divisor is positive
|
|
283
354
|
const result = (n as CljNumber).value % (d as CljNumber).value
|
|
284
|
-
return
|
|
355
|
+
return v.number(
|
|
285
356
|
result < 0 ? result + Math.abs((d as CljNumber).value) : result
|
|
286
357
|
)
|
|
287
|
-
})
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
358
|
+
})
|
|
359
|
+
.doc(
|
|
360
|
+
'Returns the remainder of the first argument divided by the second argument. Throws on non-number arguments or division by zero.',
|
|
361
|
+
[['n', 'd']]
|
|
362
|
+
),
|
|
291
363
|
|
|
292
|
-
'even?':
|
|
293
|
-
|
|
364
|
+
'even?': v
|
|
365
|
+
.nativeFn('even?', function isEven(n: CljValue) {
|
|
294
366
|
if (n === undefined || n.kind !== 'number') {
|
|
295
|
-
throw
|
|
367
|
+
throw EvaluationError.atArg(
|
|
296
368
|
`even? expects a number${n !== undefined ? `, got ${printString(n)}` : ''}`,
|
|
297
|
-
{ n }
|
|
369
|
+
{ n },
|
|
370
|
+
0
|
|
298
371
|
)
|
|
299
372
|
}
|
|
300
|
-
return
|
|
301
|
-
})
|
|
302
|
-
'Returns true if the argument is an even number, false otherwise.',
|
|
303
|
-
|
|
304
|
-
|
|
373
|
+
return v.boolean((n as CljNumber).value % 2 === 0)
|
|
374
|
+
})
|
|
375
|
+
.doc('Returns true if the argument is an even number, false otherwise.', [
|
|
376
|
+
['n'],
|
|
377
|
+
]),
|
|
305
378
|
|
|
306
|
-
'odd?':
|
|
307
|
-
|
|
379
|
+
'odd?': v
|
|
380
|
+
.nativeFn('odd?', function isOdd(n: CljValue) {
|
|
308
381
|
if (n === undefined || n.kind !== 'number') {
|
|
309
|
-
throw
|
|
382
|
+
throw EvaluationError.atArg(
|
|
310
383
|
`odd? expects a number${n !== undefined ? `, got ${printString(n)}` : ''}`,
|
|
311
|
-
{ n }
|
|
384
|
+
{ n },
|
|
385
|
+
0
|
|
312
386
|
)
|
|
313
387
|
}
|
|
314
|
-
return
|
|
315
|
-
})
|
|
316
|
-
'Returns true if the argument is an odd number, false otherwise.',
|
|
317
|
-
|
|
318
|
-
|
|
388
|
+
return v.boolean(Math.abs((n as CljNumber).value) % 2 !== 0)
|
|
389
|
+
})
|
|
390
|
+
.doc('Returns true if the argument is an odd number, false otherwise.', [
|
|
391
|
+
['n'],
|
|
392
|
+
]),
|
|
319
393
|
|
|
320
|
-
'pos?':
|
|
321
|
-
|
|
394
|
+
'pos?': v
|
|
395
|
+
.nativeFn('pos?', function isPositive(n: CljValue) {
|
|
322
396
|
if (n === undefined || n.kind !== 'number') {
|
|
323
|
-
throw
|
|
397
|
+
throw EvaluationError.atArg(
|
|
324
398
|
`pos? expects a number${n !== undefined ? `, got ${printString(n)}` : ''}`,
|
|
325
|
-
{ n }
|
|
399
|
+
{ n },
|
|
400
|
+
0
|
|
326
401
|
)
|
|
327
402
|
}
|
|
328
|
-
return
|
|
329
|
-
})
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
403
|
+
return v.boolean((n as CljNumber).value > 0)
|
|
404
|
+
})
|
|
405
|
+
.doc(
|
|
406
|
+
'Returns true if the argument is a positive number, false otherwise.',
|
|
407
|
+
[['n']]
|
|
408
|
+
),
|
|
333
409
|
|
|
334
|
-
'neg?':
|
|
335
|
-
|
|
410
|
+
'neg?': v
|
|
411
|
+
.nativeFn('neg?', function isNegative(n: CljValue) {
|
|
336
412
|
if (n === undefined || n.kind !== 'number') {
|
|
337
|
-
throw
|
|
413
|
+
throw EvaluationError.atArg(
|
|
338
414
|
`neg? expects a number${n !== undefined ? `, got ${printString(n)}` : ''}`,
|
|
339
|
-
{ n }
|
|
415
|
+
{ n },
|
|
416
|
+
0
|
|
340
417
|
)
|
|
341
418
|
}
|
|
342
|
-
return
|
|
343
|
-
})
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
419
|
+
return v.boolean((n as CljNumber).value < 0)
|
|
420
|
+
})
|
|
421
|
+
.doc(
|
|
422
|
+
'Returns true if the argument is a negative number, false otherwise.',
|
|
423
|
+
[['n']]
|
|
424
|
+
),
|
|
347
425
|
|
|
348
|
-
'zero?':
|
|
349
|
-
|
|
426
|
+
'zero?': v
|
|
427
|
+
.nativeFn('zero?', function isZero(n: CljValue) {
|
|
350
428
|
if (n === undefined || n.kind !== 'number') {
|
|
351
|
-
throw
|
|
429
|
+
throw EvaluationError.atArg(
|
|
352
430
|
`zero? expects a number${n !== undefined ? `, got ${printString(n)}` : ''}`,
|
|
353
|
-
{ n }
|
|
431
|
+
{ n },
|
|
432
|
+
0
|
|
354
433
|
)
|
|
355
434
|
}
|
|
356
|
-
return
|
|
357
|
-
})
|
|
358
|
-
'Returns true if the argument is zero, false otherwise.',
|
|
359
|
-
|
|
360
|
-
|
|
435
|
+
return v.boolean((n as CljNumber).value === 0)
|
|
436
|
+
})
|
|
437
|
+
.doc('Returns true if the argument is zero, false otherwise.', [['n']]),
|
|
438
|
+
|
|
439
|
+
abs: v
|
|
440
|
+
.nativeFn('abs', function absImpl(n: CljValue) {
|
|
441
|
+
if (n === undefined || n.kind !== 'number') {
|
|
442
|
+
throw EvaluationError.atArg(
|
|
443
|
+
`abs expects a number${n !== undefined ? `, got ${printString(n)}` : ''}`,
|
|
444
|
+
{ n },
|
|
445
|
+
0
|
|
446
|
+
)
|
|
447
|
+
}
|
|
448
|
+
return v.number(Math.abs((n as CljNumber).value))
|
|
449
|
+
})
|
|
450
|
+
.doc('Returns the absolute value of a.', [['a']]),
|
|
451
|
+
|
|
452
|
+
quot: v
|
|
453
|
+
.nativeFn('quot', function quotImpl(num: CljValue, div: CljValue) {
|
|
454
|
+
if (num === undefined || num.kind !== 'number') {
|
|
455
|
+
throw EvaluationError.atArg(
|
|
456
|
+
`quot expects a number as first argument`,
|
|
457
|
+
{ num },
|
|
458
|
+
0
|
|
459
|
+
)
|
|
460
|
+
}
|
|
461
|
+
if (div === undefined || div.kind !== 'number') {
|
|
462
|
+
throw EvaluationError.atArg(
|
|
463
|
+
`quot expects a number as second argument`,
|
|
464
|
+
{ div },
|
|
465
|
+
1
|
|
466
|
+
)
|
|
467
|
+
}
|
|
468
|
+
if ((div as CljNumber).value === 0) {
|
|
469
|
+
throw new EvaluationError('quot: division by zero', { num, div })
|
|
470
|
+
}
|
|
471
|
+
return v.number(
|
|
472
|
+
Math.trunc((num as CljNumber).value / (div as CljNumber).value)
|
|
473
|
+
)
|
|
474
|
+
})
|
|
475
|
+
.doc('quot[ient] of dividing numerator by denominator.', [['num', 'div']]),
|
|
476
|
+
|
|
477
|
+
rem: v
|
|
478
|
+
.nativeFn('rem', function remImpl(num: CljValue, div: CljValue) {
|
|
479
|
+
if (num === undefined || num.kind !== 'number') {
|
|
480
|
+
throw EvaluationError.atArg(
|
|
481
|
+
`rem expects a number as first argument`,
|
|
482
|
+
{ num },
|
|
483
|
+
0
|
|
484
|
+
)
|
|
485
|
+
}
|
|
486
|
+
if (div === undefined || div.kind !== 'number') {
|
|
487
|
+
throw EvaluationError.atArg(
|
|
488
|
+
`rem expects a number as second argument`,
|
|
489
|
+
{ div },
|
|
490
|
+
1
|
|
491
|
+
)
|
|
492
|
+
}
|
|
493
|
+
if ((div as CljNumber).value === 0) {
|
|
494
|
+
throw new EvaluationError('rem: division by zero', { num, div })
|
|
495
|
+
}
|
|
496
|
+
return v.number((num as CljNumber).value % (div as CljNumber).value)
|
|
497
|
+
})
|
|
498
|
+
.doc('remainder of dividing numerator by denominator.', [['num', 'div']]),
|
|
499
|
+
|
|
500
|
+
rand: v
|
|
501
|
+
.nativeFn('rand', function randImpl(...args: CljValue[]) {
|
|
502
|
+
if (args.length === 0) return v.number(Math.random())
|
|
503
|
+
if (args[0].kind !== 'number') {
|
|
504
|
+
throw EvaluationError.atArg(`rand expects a number`, { n: args[0] }, 0)
|
|
505
|
+
}
|
|
506
|
+
return v.number(Math.random() * (args[0] as CljNumber).value)
|
|
507
|
+
})
|
|
508
|
+
.doc(
|
|
509
|
+
'Returns a random floating point number between 0 (inclusive) and n (default 1) (exclusive).',
|
|
510
|
+
[[], ['n']]
|
|
511
|
+
),
|
|
512
|
+
|
|
513
|
+
'rand-int': v
|
|
514
|
+
.nativeFn('rand-int', function randIntImpl(n: CljValue) {
|
|
515
|
+
if (n === undefined || n.kind !== 'number') {
|
|
516
|
+
throw EvaluationError.atArg(`rand-int expects a number`, { n }, 0)
|
|
517
|
+
}
|
|
518
|
+
return v.number(Math.floor(Math.random() * (n as CljNumber).value))
|
|
519
|
+
})
|
|
520
|
+
.doc('Returns a random integer between 0 (inclusive) and n (exclusive).', [
|
|
521
|
+
['n'],
|
|
522
|
+
]),
|
|
523
|
+
|
|
524
|
+
'rand-nth': v
|
|
525
|
+
.nativeFn('rand-nth', function randNthImpl(coll: CljValue) {
|
|
526
|
+
if (coll === undefined || (!is.list(coll) && !is.vector(coll))) {
|
|
527
|
+
throw EvaluationError.atArg(
|
|
528
|
+
`rand-nth expects a list or vector`,
|
|
529
|
+
{ coll },
|
|
530
|
+
0
|
|
531
|
+
)
|
|
532
|
+
}
|
|
533
|
+
const items = (coll as CljList | CljVector).value
|
|
534
|
+
if (items.length === 0) {
|
|
535
|
+
throw new EvaluationError('rand-nth called on empty collection', {
|
|
536
|
+
coll,
|
|
537
|
+
})
|
|
538
|
+
}
|
|
539
|
+
return items[Math.floor(Math.random() * items.length)]
|
|
540
|
+
})
|
|
541
|
+
.doc('Return a random element of the (sequential) collection.', [['coll']]),
|
|
542
|
+
|
|
543
|
+
shuffle: v
|
|
544
|
+
.nativeFn('shuffle', function shuffleImpl(coll: CljValue) {
|
|
545
|
+
if (coll === undefined || coll.kind === 'nil') return v.vector([])
|
|
546
|
+
if (!is.seqable(coll)) {
|
|
547
|
+
throw EvaluationError.atArg(
|
|
548
|
+
`shuffle expects a collection, got ${printString(coll)}`,
|
|
549
|
+
{ coll },
|
|
550
|
+
0
|
|
551
|
+
)
|
|
552
|
+
}
|
|
553
|
+
const arr = [...toSeq(coll)]
|
|
554
|
+
for (let i = arr.length - 1; i > 0; i--) {
|
|
555
|
+
const j = Math.floor(Math.random() * (i + 1))
|
|
556
|
+
;[arr[i], arr[j]] = [arr[j], arr[i]]
|
|
557
|
+
}
|
|
558
|
+
return v.vector(arr)
|
|
559
|
+
})
|
|
560
|
+
.doc('Return a random permutation of coll.', [['coll']]),
|
|
561
|
+
|
|
562
|
+
'bit-and': v
|
|
563
|
+
.nativeFn('bit-and', function bitAndImpl(x: CljValue, y: CljValue) {
|
|
564
|
+
if (x?.kind !== 'number')
|
|
565
|
+
throw EvaluationError.atArg('bit-and expects numbers', { x }, 0)
|
|
566
|
+
if (y?.kind !== 'number')
|
|
567
|
+
throw EvaluationError.atArg('bit-and expects numbers', { y }, 1)
|
|
568
|
+
return v.number((x as CljNumber).value & (y as CljNumber).value)
|
|
569
|
+
})
|
|
570
|
+
.doc('Bitwise and', [['x', 'y']]),
|
|
571
|
+
|
|
572
|
+
'bit-or': v
|
|
573
|
+
.nativeFn('bit-or', function bitOrImpl(x: CljValue, y: CljValue) {
|
|
574
|
+
if (x?.kind !== 'number')
|
|
575
|
+
throw EvaluationError.atArg('bit-or expects numbers', { x }, 0)
|
|
576
|
+
if (y?.kind !== 'number')
|
|
577
|
+
throw EvaluationError.atArg('bit-or expects numbers', { y }, 1)
|
|
578
|
+
return v.number((x as CljNumber).value | (y as CljNumber).value)
|
|
579
|
+
})
|
|
580
|
+
.doc('Bitwise or', [['x', 'y']]),
|
|
581
|
+
|
|
582
|
+
'bit-xor': v
|
|
583
|
+
.nativeFn('bit-xor', function bitXorImpl(x: CljValue, y: CljValue) {
|
|
584
|
+
if (x?.kind !== 'number')
|
|
585
|
+
throw EvaluationError.atArg('bit-xor expects numbers', { x }, 0)
|
|
586
|
+
if (y?.kind !== 'number')
|
|
587
|
+
throw EvaluationError.atArg('bit-xor expects numbers', { y }, 1)
|
|
588
|
+
return v.number((x as CljNumber).value ^ (y as CljNumber).value)
|
|
589
|
+
})
|
|
590
|
+
.doc('Bitwise exclusive or', [['x', 'y']]),
|
|
591
|
+
|
|
592
|
+
'bit-not': v
|
|
593
|
+
.nativeFn('bit-not', function bitNotImpl(x: CljValue) {
|
|
594
|
+
if (x?.kind !== 'number')
|
|
595
|
+
throw EvaluationError.atArg('bit-not expects a number', { x }, 0)
|
|
596
|
+
return v.number(~(x as CljNumber).value)
|
|
597
|
+
})
|
|
598
|
+
.doc('Bitwise complement', [['x']]),
|
|
599
|
+
|
|
600
|
+
'bit-shift-left': v
|
|
601
|
+
.nativeFn(
|
|
602
|
+
'bit-shift-left',
|
|
603
|
+
function bitShiftLeftImpl(x: CljValue, n: CljValue) {
|
|
604
|
+
if (x?.kind !== 'number')
|
|
605
|
+
throw EvaluationError.atArg(
|
|
606
|
+
'bit-shift-left expects numbers',
|
|
607
|
+
{ x },
|
|
608
|
+
0
|
|
609
|
+
)
|
|
610
|
+
if (n?.kind !== 'number')
|
|
611
|
+
throw EvaluationError.atArg(
|
|
612
|
+
'bit-shift-left expects numbers',
|
|
613
|
+
{ n },
|
|
614
|
+
1
|
|
615
|
+
)
|
|
616
|
+
return v.number((x as CljNumber).value << (n as CljNumber).value)
|
|
617
|
+
}
|
|
618
|
+
)
|
|
619
|
+
.doc('Bitwise shift left', [['x', 'n']]),
|
|
620
|
+
|
|
621
|
+
'bit-shift-right': v
|
|
622
|
+
.nativeFn(
|
|
623
|
+
'bit-shift-right',
|
|
624
|
+
function bitShiftRightImpl(x: CljValue, n: CljValue) {
|
|
625
|
+
if (x?.kind !== 'number')
|
|
626
|
+
throw EvaluationError.atArg(
|
|
627
|
+
'bit-shift-right expects numbers',
|
|
628
|
+
{ x },
|
|
629
|
+
0
|
|
630
|
+
)
|
|
631
|
+
if (n?.kind !== 'number')
|
|
632
|
+
throw EvaluationError.atArg(
|
|
633
|
+
'bit-shift-right expects numbers',
|
|
634
|
+
{ n },
|
|
635
|
+
1
|
|
636
|
+
)
|
|
637
|
+
return v.number((x as CljNumber).value >> (n as CljNumber).value)
|
|
638
|
+
}
|
|
639
|
+
)
|
|
640
|
+
.doc('Bitwise shift right', [['x', 'n']]),
|
|
641
|
+
|
|
642
|
+
'unsigned-bit-shift-right': v
|
|
643
|
+
.nativeFn(
|
|
644
|
+
'unsigned-bit-shift-right',
|
|
645
|
+
function unsignedBitShiftRightImpl(x: CljValue, n: CljValue) {
|
|
646
|
+
if (x?.kind !== 'number')
|
|
647
|
+
throw EvaluationError.atArg(
|
|
648
|
+
'unsigned-bit-shift-right expects numbers',
|
|
649
|
+
{ x },
|
|
650
|
+
0
|
|
651
|
+
)
|
|
652
|
+
if (n?.kind !== 'number')
|
|
653
|
+
throw EvaluationError.atArg(
|
|
654
|
+
'unsigned-bit-shift-right expects numbers',
|
|
655
|
+
{ n },
|
|
656
|
+
1
|
|
657
|
+
)
|
|
658
|
+
return v.number((x as CljNumber).value >>> (n as CljNumber).value)
|
|
659
|
+
}
|
|
660
|
+
)
|
|
661
|
+
.doc('Bitwise shift right, without sign-extension', [['x', 'n']]),
|
|
361
662
|
}
|