apricot 0.0.1
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.
- data/.gitignore +3 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +26 -0
- data/README.md +90 -0
- data/Rakefile +9 -0
- data/apricot.gemspec +22 -0
- data/bin/apricot +58 -0
- data/examples/bot.apr +23 -0
- data/examples/cinch-bot.apr +12 -0
- data/examples/hanoi.apr +10 -0
- data/examples/hello.apr +1 -0
- data/examples/plot.apr +28 -0
- data/examples/quine.apr +1 -0
- data/kernel/core.apr +928 -0
- data/lib/apricot/ast/identifier.rb +111 -0
- data/lib/apricot/ast/list.rb +99 -0
- data/lib/apricot/ast/literals.rb +240 -0
- data/lib/apricot/ast/node.rb +45 -0
- data/lib/apricot/ast/scopes.rb +147 -0
- data/lib/apricot/ast/toplevel.rb +66 -0
- data/lib/apricot/ast/variables.rb +64 -0
- data/lib/apricot/ast.rb +3 -0
- data/lib/apricot/compiler.rb +55 -0
- data/lib/apricot/cons.rb +27 -0
- data/lib/apricot/errors.rb +38 -0
- data/lib/apricot/generator.rb +15 -0
- data/lib/apricot/identifier.rb +91 -0
- data/lib/apricot/list.rb +96 -0
- data/lib/apricot/macroexpand.rb +47 -0
- data/lib/apricot/misc.rb +11 -0
- data/lib/apricot/namespace.rb +59 -0
- data/lib/apricot/parser.rb +541 -0
- data/lib/apricot/printers.rb +12 -0
- data/lib/apricot/repl.rb +254 -0
- data/lib/apricot/ruby_ext.rb +254 -0
- data/lib/apricot/seq.rb +44 -0
- data/lib/apricot/special_forms.rb +735 -0
- data/lib/apricot/stages.rb +60 -0
- data/lib/apricot/version.rb +3 -0
- data/lib/apricot.rb +30 -0
- data/spec/compiler_spec.rb +499 -0
- data/spec/identifier_spec.rb +58 -0
- data/spec/list_spec.rb +96 -0
- data/spec/parser_spec.rb +312 -0
- data/spec/spec_helper.rb +10 -0
- metadata +188 -0
data/kernel/core.apr
ADDED
@@ -0,0 +1,928 @@
|
|
1
|
+
; The core apricot library
|
2
|
+
|
3
|
+
(ns Apricot::Core)
|
4
|
+
|
5
|
+
; Basics
|
6
|
+
|
7
|
+
(def raise Kernel/raise)
|
8
|
+
|
9
|
+
; Needed in defn, will redefine with documentation later.
|
10
|
+
(def list
|
11
|
+
(fn list [& items]
|
12
|
+
(.to_list items)))
|
13
|
+
|
14
|
+
; Needed in defn, will redefine with documentation later.
|
15
|
+
(def concat
|
16
|
+
(fn concat [& colls]
|
17
|
+
(.to_list (.reduce (.map colls | :to_a) [] :+))))
|
18
|
+
|
19
|
+
(def defn
|
20
|
+
(fn defn [name & body]
|
21
|
+
(let [doc-string (if (.is_a? (.first body) String)
|
22
|
+
(.shift body))
|
23
|
+
metadata (if (.is_a? (.first body) Hash)
|
24
|
+
(.shift body)
|
25
|
+
{})
|
26
|
+
arglists (if (.is_a? (.first body) Array)
|
27
|
+
(list (.first body))
|
28
|
+
(.to_list
|
29
|
+
(.map body | #(if (.is_a? % Apricot::List)
|
30
|
+
(.first %)))))
|
31
|
+
f (.intern Apricot::Identifier (.gensym Apricot))]
|
32
|
+
(list 'let [f (concat (list 'fn name) body)]
|
33
|
+
(list 'def name f)
|
34
|
+
(list '.apricot_meta=
|
35
|
+
f
|
36
|
+
(.merge! {:name (list 'quote name)
|
37
|
+
:doc doc-string
|
38
|
+
:arglists (list 'quote arglists)}
|
39
|
+
metadata))
|
40
|
+
f))))
|
41
|
+
(.apricot_meta=
|
42
|
+
defn
|
43
|
+
{:name 'defn
|
44
|
+
:doc "Define a new function."
|
45
|
+
:arglists '([name doc-string? metadata? [params ...] body]
|
46
|
+
[name doc-string? metadata? ([params ...] body) ...+])
|
47
|
+
:macro true})
|
48
|
+
|
49
|
+
(defn defmacro
|
50
|
+
"Like defn, but the resulting function name is declared as a macro and will
|
51
|
+
be used as a macro by the compiler when it is called."
|
52
|
+
{:arglists '([name doc-string? metadata? [params ...] body]
|
53
|
+
[name doc-string? metadata? ([params ...] body) ...+])
|
54
|
+
:macro true}
|
55
|
+
[name & body]
|
56
|
+
(let [f (.intern Apricot::Identifier (.gensym Apricot))]
|
57
|
+
(list 'let [f (concat (list 'defn name) body)]
|
58
|
+
(list '.store (list '.apricot_meta f) :macro true)
|
59
|
+
f)))
|
60
|
+
|
61
|
+
(defn list
|
62
|
+
"Create a new list containing the items."
|
63
|
+
[& items] (.to_list items))
|
64
|
+
|
65
|
+
(defn concat
|
66
|
+
"Concatenate the items in the supplied colls into a single list."
|
67
|
+
[& colls] (.to_list (.reduce (.map colls | :to_a) [] :+)))
|
68
|
+
|
69
|
+
(defn array
|
70
|
+
"Create a new array containing the items."
|
71
|
+
[& items] items)
|
72
|
+
|
73
|
+
(defn set
|
74
|
+
"Create a new set containing the items."
|
75
|
+
[& items] (Set. items))
|
76
|
+
|
77
|
+
(defn hash
|
78
|
+
"Create a new hash map from the items. The items are interpreted as a list of
|
79
|
+
key/value pairs so there must be an even number of them."
|
80
|
+
[& items]
|
81
|
+
(if (.even? (.length items))
|
82
|
+
(let [h {}]
|
83
|
+
(.each_slice items 2 | #(.store h %1 %2))
|
84
|
+
h)
|
85
|
+
(raise ArgumentError "hash requires an even number of arguments")))
|
86
|
+
|
87
|
+
(defn cons
|
88
|
+
"Return a new list where head is the first element and tail is the rest."
|
89
|
+
[head tail] (Apricot::Cons. head tail))
|
90
|
+
|
91
|
+
(defn apply
|
92
|
+
"Applies fn f to the argument list formed by prepending intervening
|
93
|
+
arguments to args."
|
94
|
+
([f args]
|
95
|
+
(.apricot_call f & args))
|
96
|
+
([f x & args]
|
97
|
+
(.apricot_call f & (cons x (.concat args (.pop args))))))
|
98
|
+
|
99
|
+
;; At this point everything is defined that syntax quote requires
|
100
|
+
|
101
|
+
(defn identifier
|
102
|
+
"Return an identifier with the given name."
|
103
|
+
[name] (.intern Apricot::Identifier name))
|
104
|
+
|
105
|
+
(defn symbol
|
106
|
+
"Return a symbol with the given name."
|
107
|
+
[name] (.to_sym name))
|
108
|
+
|
109
|
+
(defn gensym
|
110
|
+
"Return a new identifier with a unique name. If a prefix string is supplied,
|
111
|
+
the name is prefix__# where # is some unique number. If prefix is not
|
112
|
+
supplied, the prefix is 'g'."
|
113
|
+
[[prefix "g"]]
|
114
|
+
(identifier (.gensym Apricot prefix)))
|
115
|
+
|
116
|
+
(defn require
|
117
|
+
"Require the given Ruby files. Works just like using Ruby's 'require' on
|
118
|
+
each of the arguments."
|
119
|
+
[& files]
|
120
|
+
; (. Kernel require %) does not call the Rubygems custom require for some
|
121
|
+
; reason, so we use this method. (MAIN is the special toplevel object).
|
122
|
+
(.each files | #(. MAIN send :require %)))
|
123
|
+
|
124
|
+
(defn str
|
125
|
+
"With no args, return the empty string. With one arg x, return x converted
|
126
|
+
to a string. With more than one arg, return the concatenation of the str
|
127
|
+
values of the args."
|
128
|
+
([] "")
|
129
|
+
([x] (.apricot_str x))
|
130
|
+
([x & args]
|
131
|
+
(.reduce args (.apricot_str x) | #(.concat %1 (.apricot_str %2)))))
|
132
|
+
|
133
|
+
(defn print
|
134
|
+
"Print the object(s) to standard output."
|
135
|
+
[& args] (Kernel/print (apply str args)))
|
136
|
+
|
137
|
+
(defn println
|
138
|
+
"Print the object(s) followed by a newline at the end to standard output."
|
139
|
+
[& args] (Kernel/puts (apply str args)))
|
140
|
+
|
141
|
+
(def macroexpand Apricot/macroexpand)
|
142
|
+
(def macroexpand-1 Apricot/macroexpand_1)
|
143
|
+
|
144
|
+
; Type predicates
|
145
|
+
|
146
|
+
(defn instance?
|
147
|
+
"Test if x is an instance of class c. Return true or false."
|
148
|
+
[c x] (.is_a? x c))
|
149
|
+
|
150
|
+
(defn module?
|
151
|
+
"Return true if x is an instance of Module."
|
152
|
+
[x] (instance? Module x))
|
153
|
+
|
154
|
+
(defn class?
|
155
|
+
"Return true if x is an instance of Class."
|
156
|
+
[x] (instance? Class x))
|
157
|
+
|
158
|
+
(defn seq?
|
159
|
+
"Return true if x is an instance of an Apricot::Seq class."
|
160
|
+
[x] (instance? Apricot::Seq x))
|
161
|
+
|
162
|
+
(defn array?
|
163
|
+
"Return true if x is an instance of Array."
|
164
|
+
[x] (instance? Array x))
|
165
|
+
|
166
|
+
(defn list?
|
167
|
+
"Return true if x is an instance of Apricot::List."
|
168
|
+
[x] (instance? Apricot::List x))
|
169
|
+
|
170
|
+
(defn hash?
|
171
|
+
"Return true if x is an instance of Hash."
|
172
|
+
[x] (instance? Hash x))
|
173
|
+
|
174
|
+
(defn set?
|
175
|
+
"Return true if x is an instance of Set."
|
176
|
+
[x] (instance? Set x))
|
177
|
+
|
178
|
+
(defn string?
|
179
|
+
"Return true if x is an instance of String."
|
180
|
+
[x] (instance? String x))
|
181
|
+
|
182
|
+
(defn regexp?
|
183
|
+
"Return true if x is an instance of Regexp."
|
184
|
+
[x] (instance? Regexp x))
|
185
|
+
|
186
|
+
(defn identifier?
|
187
|
+
"Return true if x is an instance of Apricot::Identifier."
|
188
|
+
[x] (instance? Apricot::Identifier x))
|
189
|
+
|
190
|
+
(defn symbol?
|
191
|
+
"Return true if x is an instance of Symbol."
|
192
|
+
[x] (instance? Symbol x))
|
193
|
+
|
194
|
+
(defn number?
|
195
|
+
"Return true if x is an instance of Numeric."
|
196
|
+
[x] (instance? Numeric x))
|
197
|
+
|
198
|
+
(defn ratio?
|
199
|
+
"Return true if x is an instance of Rational."
|
200
|
+
[x] (instance? Rational x))
|
201
|
+
|
202
|
+
(defn integer?
|
203
|
+
"Return true if x is an instance of Integer."
|
204
|
+
[x] (instance? Integer x))
|
205
|
+
|
206
|
+
(defn fixnum?
|
207
|
+
"Return true if x is an instance of Fixnum."
|
208
|
+
[x] (instance? Fixnum x))
|
209
|
+
|
210
|
+
(defn bignum?
|
211
|
+
"Return true if x is an instance of Bignum."
|
212
|
+
[x] (instance? Bignum x))
|
213
|
+
|
214
|
+
(defn float?
|
215
|
+
"Return true if x is an instance of Float."
|
216
|
+
[x] (instance? Float x))
|
217
|
+
|
218
|
+
(defn complex?
|
219
|
+
"Return true if x is an instance of Complex."
|
220
|
+
[x] (instance? Complex x))
|
221
|
+
|
222
|
+
(defn range?
|
223
|
+
"Return true if x is an instance of Range."
|
224
|
+
[x] (instance? Range x))
|
225
|
+
|
226
|
+
(defn comparable?
|
227
|
+
"Return true if x is an instance of a Comparable class."
|
228
|
+
[x] (instance? Comparable x))
|
229
|
+
|
230
|
+
(defn enumerable?
|
231
|
+
"Return true if x is an instance of an Enumerable class."
|
232
|
+
[x] (instance? Enumerable x))
|
233
|
+
|
234
|
+
; Basic logic predicates, functions, and macros
|
235
|
+
|
236
|
+
(defn nil?
|
237
|
+
"Return true if x is nil, false otherwise."
|
238
|
+
[x] (.nil? x))
|
239
|
+
|
240
|
+
(defn true?
|
241
|
+
"Return true if x is the value true, false otherwise."
|
242
|
+
[x] (.equal? x true))
|
243
|
+
|
244
|
+
(defn false?
|
245
|
+
"Return true if x is the value false, false otherwise."
|
246
|
+
[x] (.equal? x false))
|
247
|
+
|
248
|
+
(defn not
|
249
|
+
"Return true if x is logical false, false otherwise."
|
250
|
+
[x] (if x false true))
|
251
|
+
|
252
|
+
(defmacro and
|
253
|
+
"Evaluate exprs one at a time, from left to right. If a form returns logical
|
254
|
+
false (nil or false), return that value and don't evaluate any of the other
|
255
|
+
expressions, otherwise return the value of the last expr. (and) returns
|
256
|
+
true."
|
257
|
+
([] true)
|
258
|
+
([x] x)
|
259
|
+
([x & more]
|
260
|
+
`(let [and# ~x]
|
261
|
+
(if and# (and ~@more) and#))))
|
262
|
+
|
263
|
+
(defmacro or
|
264
|
+
"Evaluate exprs one at a time, from left to right. If a form returns a
|
265
|
+
logical true value, return that value and don't evaluate any of the other
|
266
|
+
expressions, otherwise return the value of the last expression. (or) returns
|
267
|
+
nil."
|
268
|
+
([] nil)
|
269
|
+
([x] x)
|
270
|
+
([x & more]
|
271
|
+
`(let [or# ~x]
|
272
|
+
(if or# or# (or ~@more)))))
|
273
|
+
|
274
|
+
; Collection functions
|
275
|
+
|
276
|
+
(defn seq
|
277
|
+
"Returns a seq on the collection. If the collection is empty, returns nil.
|
278
|
+
(seq nil) returns nil."
|
279
|
+
[coll] (.to_seq coll))
|
280
|
+
|
281
|
+
(defn first
|
282
|
+
"Return the first item in the collection. Call seq on the argument. If coll
|
283
|
+
is nil, return nil."
|
284
|
+
[coll] (.first (seq coll)))
|
285
|
+
|
286
|
+
(defn rest
|
287
|
+
"Return a possibly empty seq of the items after the first. Call seq on the
|
288
|
+
argument."
|
289
|
+
[coll] (.rest (seq coll)))
|
290
|
+
|
291
|
+
(defn next
|
292
|
+
"Return a seq of the items after the first. Call seq on the argument. If
|
293
|
+
there are no more items, return nil."
|
294
|
+
[coll] (.next (seq coll)))
|
295
|
+
|
296
|
+
(defn empty?
|
297
|
+
"Return true if coll has no items - same as (not (seq coll)). Please use the
|
298
|
+
idiom (seq x) rather than (not (empty? x))"
|
299
|
+
[coll] (not (seq coll)))
|
300
|
+
|
301
|
+
(defn second
|
302
|
+
"Same as (first (next coll))."
|
303
|
+
[coll] (first (next coll)))
|
304
|
+
|
305
|
+
(defn ffirst
|
306
|
+
"Same as (first (first coll))."
|
307
|
+
[coll] (first (first coll)))
|
308
|
+
|
309
|
+
(defn nfirst
|
310
|
+
"Same as (next (first coll))."
|
311
|
+
[coll] (next (first coll)))
|
312
|
+
|
313
|
+
(defn fnext
|
314
|
+
"Same as (first (next coll))."
|
315
|
+
[coll] (first (next coll)))
|
316
|
+
|
317
|
+
(defn last
|
318
|
+
"Return the last item in coll."
|
319
|
+
[coll] (.last coll))
|
320
|
+
|
321
|
+
(defn butlast [coll]
|
322
|
+
"Return all but the last item in coll."
|
323
|
+
(if (empty? coll)
|
324
|
+
[]
|
325
|
+
(.take coll (. (.count coll) - 1))))
|
326
|
+
|
327
|
+
(defn nth
|
328
|
+
"Return the value at the given index in coll. If the index is out of bounds,
|
329
|
+
return not-found if it is supplied. Otherwise raise an exception."
|
330
|
+
([coll index]
|
331
|
+
(.fetch coll index))
|
332
|
+
([coll index not-found]
|
333
|
+
(.fetch coll index not-found)))
|
334
|
+
|
335
|
+
(defn count
|
336
|
+
"Return the number of items in coll."
|
337
|
+
[coll] (.count coll))
|
338
|
+
|
339
|
+
(defn take
|
340
|
+
"Return the first n items in coll."
|
341
|
+
[n coll] (.take coll n))
|
342
|
+
|
343
|
+
(defn drop
|
344
|
+
"Return all but the first n items in coll."
|
345
|
+
[n coll] (.drop coll n))
|
346
|
+
|
347
|
+
(defn reverse
|
348
|
+
"Return the items in coll in reverse order."
|
349
|
+
[coll] (.reverse coll))
|
350
|
+
|
351
|
+
(defn map
|
352
|
+
"Return an array consisting of the result of applying f to the set of first
|
353
|
+
items of each coll, followed by applying f to the set of second items in
|
354
|
+
each coll, until any one of the colls is exhausted. Any remaining items in
|
355
|
+
other colls are exhausted. Function f should accept number-of-colls
|
356
|
+
arguments."
|
357
|
+
([f coll]
|
358
|
+
(.map coll | f))
|
359
|
+
([f coll & colls]
|
360
|
+
(.map (.zip coll & colls) | #(apply f %))))
|
361
|
+
|
362
|
+
(defn reduce
|
363
|
+
"f should be a function of 2 arguments. If val is not supplied, return the
|
364
|
+
result of applying f to the first 2 items in coll, then applying f to that
|
365
|
+
result and the 3rd item, etc. If coll contains no items, f must accept no
|
366
|
+
arguments as well, and reduce returns the result of calling f with no
|
367
|
+
arguments. If coll has only 1 item, it is returned and f is not called. If
|
368
|
+
val is supplied, return the result of applying f to val and the first item
|
369
|
+
in coll, then applying f to that result and the 2nd item, etc. If coll
|
370
|
+
contains no items, return val and f is not called."
|
371
|
+
([f coll]
|
372
|
+
(if (empty? coll)
|
373
|
+
(f)
|
374
|
+
(.reduce coll | f)))
|
375
|
+
([f val coll]
|
376
|
+
(.reduce coll val | f)))
|
377
|
+
|
378
|
+
(defn contains?
|
379
|
+
"Return true if val is present in the given collection, otherwise return
|
380
|
+
false. Note that for hashes this checks for a key."
|
381
|
+
[coll val]
|
382
|
+
(.include? coll val))
|
383
|
+
|
384
|
+
; Hash map functions
|
385
|
+
(defn get
|
386
|
+
"Return the value mapped to key, not-found or nil if key not present."
|
387
|
+
([map key]
|
388
|
+
(.fetch map key nil))
|
389
|
+
([map key not-found]
|
390
|
+
(.fetch map key not-found)))
|
391
|
+
|
392
|
+
(defn keys
|
393
|
+
"Return an array of the map's keys."
|
394
|
+
[map] (.keys map))
|
395
|
+
|
396
|
+
(defn vals
|
397
|
+
"Return an array of the map's values."
|
398
|
+
[map] (.values map))
|
399
|
+
|
400
|
+
; Number predicates and functions
|
401
|
+
|
402
|
+
(defn zero?
|
403
|
+
"Return true if num is zero, false otherwise."
|
404
|
+
{:inline (fn [x] `(.zero? ~x))}
|
405
|
+
[x] (.zero? x))
|
406
|
+
|
407
|
+
(defn pos?
|
408
|
+
"Return true if num is greater than zero, false otherwise."
|
409
|
+
{:inline (fn [x] `(. ~x > 0))}
|
410
|
+
[x] (. x > 0))
|
411
|
+
|
412
|
+
(defn neg?
|
413
|
+
"Return true if num is less than zero, false otherwise."
|
414
|
+
{:inline (fn [x] `(. ~x < 0))}
|
415
|
+
[x] (. x < 0))
|
416
|
+
|
417
|
+
(defn even?
|
418
|
+
"Return true if num is even, false otherwise."
|
419
|
+
{:inline (fn [x] `(.even? ~x))}
|
420
|
+
[x] (.even? x))
|
421
|
+
|
422
|
+
(defn odd?
|
423
|
+
"Return true if num is odd, false otherwise."
|
424
|
+
{:inline (fn [x] `(.odd? ~x))}
|
425
|
+
[x] (.odd? x))
|
426
|
+
|
427
|
+
(defn nary-inline
|
428
|
+
{:private true}
|
429
|
+
[op]
|
430
|
+
(fn
|
431
|
+
([x y] `(. ~x ~op ~y))
|
432
|
+
([x y & more]
|
433
|
+
(.reduce more
|
434
|
+
`(. ~x ~op ~y)
|
435
|
+
| (fn [a b] `(. ~a ~op ~b))))))
|
436
|
+
|
437
|
+
(defn +
|
438
|
+
"Return the sum of nums. (+) returns 0."
|
439
|
+
{:inline (fn
|
440
|
+
([] 0)
|
441
|
+
([x] x)
|
442
|
+
([x & more] (apply (nary-inline '+) x more)))}
|
443
|
+
([] 0)
|
444
|
+
([x] x)
|
445
|
+
([x y] (.+ x y))
|
446
|
+
([x y & more]
|
447
|
+
(.reduce more (.+ x y) :+)))
|
448
|
+
|
449
|
+
(defn *
|
450
|
+
"Return the product of nums. (*) returns 1."
|
451
|
+
{:inline (fn
|
452
|
+
([] 1)
|
453
|
+
([x] x)
|
454
|
+
([x & more] (apply (nary-inline '*) x more)))}
|
455
|
+
([] 1)
|
456
|
+
([x] x)
|
457
|
+
([x y] (.* x y))
|
458
|
+
([x y & more]
|
459
|
+
(.reduce more (.* x y) :*)))
|
460
|
+
|
461
|
+
(defn -
|
462
|
+
"If no ys are supplied, return the negation of x, otherwise subtract the ys
|
463
|
+
from x and return the result."
|
464
|
+
{:inline (fn
|
465
|
+
([x] `(. ~x -@))
|
466
|
+
([x & more] (apply (nary-inline '-) x more)))
|
467
|
+
:inline-arities #(. % > 0)}
|
468
|
+
([x] (. x -@)) ; Ruby's horribly named -@ method is the negation operator
|
469
|
+
([x y] (.- x y))
|
470
|
+
([x y & more]
|
471
|
+
(.reduce more (.- x y) :-)))
|
472
|
+
|
473
|
+
(defn /
|
474
|
+
"If no denominators are supplied, return 1/numerator, otherwise return
|
475
|
+
numerator divided by all of the denominators."
|
476
|
+
{:inline (fn
|
477
|
+
([x] `(. 1 quo ~x))
|
478
|
+
([x & more] (apply (nary-inline 'quo) x more)))
|
479
|
+
:inline-arities #(. % > 0)}
|
480
|
+
([x] (.quo 1 x))
|
481
|
+
([x y] (.quo x y))
|
482
|
+
([x y & more]
|
483
|
+
(.reduce more (.quo x y) :quo)))
|
484
|
+
|
485
|
+
(defn quot
|
486
|
+
"Return quotient of dividing numerator by denominator."
|
487
|
+
[num div] (.truncate (.fdiv num div)))
|
488
|
+
|
489
|
+
(defn rem
|
490
|
+
"Return remainder of dividing numerator by denominator."
|
491
|
+
[num div] (.remainder num div))
|
492
|
+
|
493
|
+
(defn mod
|
494
|
+
"Return the modulus of num and div. Truncates toward negative infinity."
|
495
|
+
[num div] (.modulo num div))
|
496
|
+
|
497
|
+
(defn pow
|
498
|
+
"Return num raised to the exponent exp."
|
499
|
+
[num exp] (.** num exp))
|
500
|
+
|
501
|
+
(defn int
|
502
|
+
"Coerce to integer."
|
503
|
+
[x] (.to_i x))
|
504
|
+
|
505
|
+
(defn float
|
506
|
+
"Coerce to floating point."
|
507
|
+
[x] (.to_f x))
|
508
|
+
|
509
|
+
(def ratio Kernel/Rational)
|
510
|
+
|
511
|
+
(defn inc
|
512
|
+
"Return a number one greater than x."
|
513
|
+
{:inline (fn [x] `(. ~x + 1))}
|
514
|
+
[x] (. x + 1))
|
515
|
+
|
516
|
+
(defn dec
|
517
|
+
"Return a number one less than x."
|
518
|
+
{:inline (fn [x] `(. ~x - 1))}
|
519
|
+
[x] (. x - 1))
|
520
|
+
|
521
|
+
; Equality and inequality
|
522
|
+
|
523
|
+
(defn identical?
|
524
|
+
"Test if the two arguments are the same object."
|
525
|
+
[x y] (.equal? x y))
|
526
|
+
|
527
|
+
(defn =
|
528
|
+
"Return true if all of the arguments are equal, otherwise false. (=) returns
|
529
|
+
true."
|
530
|
+
([x] true)
|
531
|
+
([x y] (. x == y))
|
532
|
+
([x y & more]
|
533
|
+
(and
|
534
|
+
(. x == y)
|
535
|
+
(.all? more | #(. x == %)))))
|
536
|
+
|
537
|
+
(defn not=
|
538
|
+
"Return true if any of the arguments are not equal, otherwise false. (not=
|
539
|
+
returns false. Same as (not (= x y ...))."
|
540
|
+
([x] false)
|
541
|
+
([x y] (. x != y))
|
542
|
+
([x y & more]
|
543
|
+
(not (apply = x y more))))
|
544
|
+
|
545
|
+
(defn compare
|
546
|
+
"Return a negative number, zero, or a positive number when x is logically
|
547
|
+
'less than', 'equal to', or 'greater than' y, respectively."
|
548
|
+
[x y] (. x <=> y))
|
549
|
+
|
550
|
+
(defn >
|
551
|
+
"Return true if nums are in monotonically decreasing order, otherwise false."
|
552
|
+
([x] true)
|
553
|
+
([x y] (. x > y))
|
554
|
+
([x y & more]
|
555
|
+
(and
|
556
|
+
(. x > y)
|
557
|
+
(.all? (.each_cons (cons y more) 2) | #(. %1 > %2)))))
|
558
|
+
|
559
|
+
(defn <
|
560
|
+
"Return true if nums are in monotonically increasing order, otherwise false."
|
561
|
+
([x] true)
|
562
|
+
([x y] (. x < y))
|
563
|
+
([x y & more]
|
564
|
+
(and
|
565
|
+
(. x < y)
|
566
|
+
(.all? (.each_cons (cons y more) 2) | #(. %1 < %2)))))
|
567
|
+
|
568
|
+
(defn >=
|
569
|
+
"Return true if nums are in monotonically non-increasing order, otherwise
|
570
|
+
false."
|
571
|
+
([x] true)
|
572
|
+
([x y] (. x >= y))
|
573
|
+
([x y & more]
|
574
|
+
(and
|
575
|
+
(. x >= y)
|
576
|
+
(.all? (.each_cons (cons y more) 2) | #(. %1 >= %2)))))
|
577
|
+
|
578
|
+
(defn <=
|
579
|
+
"Return true if nums are in monotonically non-decreasing order, otherwise
|
580
|
+
false."
|
581
|
+
([x] true)
|
582
|
+
([x y] (. x <= y))
|
583
|
+
([x y & more]
|
584
|
+
(and
|
585
|
+
(. x <= y)
|
586
|
+
(.all? (.each_cons (cons y more) 2) | #(. %1 <= %2)))))
|
587
|
+
|
588
|
+
(defn max
|
589
|
+
"Return the greatest of the arguments."
|
590
|
+
([x] x)
|
591
|
+
([x & more]
|
592
|
+
(.max (cons x more))))
|
593
|
+
|
594
|
+
(defn min
|
595
|
+
"Return the least of the arguments."
|
596
|
+
([x] x)
|
597
|
+
([x & more]
|
598
|
+
(.min (cons x more))))
|
599
|
+
|
600
|
+
; Bitwise operations
|
601
|
+
|
602
|
+
(defn bit-not
|
603
|
+
"Return the bitwise complement of x (ie. flip all the bits)."
|
604
|
+
[x] (. x #|~|)) ; Use arbitrary identifier syntax since ~ is a special char
|
605
|
+
|
606
|
+
(defn bit-and
|
607
|
+
"Return the bitwise and of the arguments."
|
608
|
+
([x y] (. x & y))
|
609
|
+
([x y & more]
|
610
|
+
(.reduce more (. x & y) | #(. %1 & %2))))
|
611
|
+
|
612
|
+
(defn bit-or
|
613
|
+
"Return the bitwise or of the arguments."
|
614
|
+
([x y] (. x | y))
|
615
|
+
([x y & more]
|
616
|
+
(.reduce more (. x | y) | #(. %1 | %2))))
|
617
|
+
|
618
|
+
(defn bit-xor
|
619
|
+
"Return the bitwise exclusive or of the arguments."
|
620
|
+
([x y] (. x ^ y))
|
621
|
+
([x y & more]
|
622
|
+
(.reduce more (. x ^ y) | #(. %1 ^ %2))))
|
623
|
+
|
624
|
+
(defn bit-and-not
|
625
|
+
"Return the bitwise and of the first argument and the bitwise complement of
|
626
|
+
all arguments after the first."
|
627
|
+
([x y] (bit-and x (bit-not y)))
|
628
|
+
([x y & more]
|
629
|
+
(.reduce more (bit-and x (bit-not y)) | #(bit-and %1 (bit-not %2)))))
|
630
|
+
|
631
|
+
(defn bit-shift-left
|
632
|
+
"Return the bitwise shift left of x by n bits."
|
633
|
+
[x n] (. x << n))
|
634
|
+
|
635
|
+
(defn bit-shift-right
|
636
|
+
"Return the bitwise shift right of x by n bits."
|
637
|
+
[x n] (. x >> n))
|
638
|
+
|
639
|
+
(defn bit-clear
|
640
|
+
"Return x with the bit at index n set to 0."
|
641
|
+
[x n] (bit-and-not x (bit-shift-left 1 n)))
|
642
|
+
|
643
|
+
(defn bit-set
|
644
|
+
"Return x with the bit at index n set to 1."
|
645
|
+
[x n] (bit-or x (bit-shift-left 1 n)))
|
646
|
+
|
647
|
+
(defn bit-flip
|
648
|
+
"Return x with the bit at index n flipped from its previous value."
|
649
|
+
[x n] (bit-xor x (bit-shift-left 1 n)))
|
650
|
+
|
651
|
+
(defn bit-test
|
652
|
+
"Return true if the bit at index n is 1, otherwise false."
|
653
|
+
[x n] (not= 0 (bit-and x (bit-shift-left 1 n))))
|
654
|
+
|
655
|
+
; Functional programming functions
|
656
|
+
(defn complement
|
657
|
+
"Take a fn f and return a fn that takes the same arguments as f, has the
|
658
|
+
same effects, if any, and returns the opposite truth value."
|
659
|
+
[f]
|
660
|
+
(fn
|
661
|
+
([] (not (f)))
|
662
|
+
([x] (not (f x)))
|
663
|
+
([x y] (not (f x y)))
|
664
|
+
([x y & zs] (not (apply f x y zs)))))
|
665
|
+
|
666
|
+
(defn constantly
|
667
|
+
"Return a function that takes any number of arguments and returns x."
|
668
|
+
[x] (fn [& args] x))
|
669
|
+
|
670
|
+
(defn identity
|
671
|
+
"Return the argument."
|
672
|
+
[x] x)
|
673
|
+
|
674
|
+
; TODO: Stole this from Clojure. It probably isn't as efficient as it could be
|
675
|
+
; in Apricot.
|
676
|
+
(defn comp
|
677
|
+
"Take a set of functions and return a fn that is the composition of those
|
678
|
+
fns. The returned fn takes a variable number of args, applies the rightmost
|
679
|
+
of fns to the args, the next fn (right-to-left) to the result, etc."
|
680
|
+
([] identity)
|
681
|
+
([f] f)
|
682
|
+
([f g]
|
683
|
+
(fn
|
684
|
+
([] (f (g)))
|
685
|
+
([x] (f (g x)))
|
686
|
+
([x y] (f (g x y)))
|
687
|
+
([x y z] (f (g x y z)))
|
688
|
+
([x y z & args] (f (apply g x y z args)))))
|
689
|
+
([f g h]
|
690
|
+
(fn
|
691
|
+
([] (f (g (h))))
|
692
|
+
([x] (f (g (h x))))
|
693
|
+
([x y] (f (g (h x y))))
|
694
|
+
([x y z] (f (g (h x y z))))
|
695
|
+
([x y z & args] (f (g (apply h x y z args))))))
|
696
|
+
([f1 f2 f3 & fs]
|
697
|
+
(let [fs (reverse (apply list f1 f2 f3 fs))]
|
698
|
+
(fn [& args]
|
699
|
+
(loop [ret (apply (first fs) args) fs (next fs)]
|
700
|
+
(if fs
|
701
|
+
(recur ((first fs) ret) (next fs))
|
702
|
+
ret))))))
|
703
|
+
|
704
|
+
(defn partial
|
705
|
+
"Take a function f and fewer than the normal arguments to f, and return a fn
|
706
|
+
that takes a variable number of additional args. When called, the returned
|
707
|
+
function calls f with args + additional args."
|
708
|
+
([f] f)
|
709
|
+
([f arg1]
|
710
|
+
(fn [& args] (apply f arg1 args)))
|
711
|
+
([f arg1 arg2]
|
712
|
+
(fn [& args] (apply f arg1 arg2 args)))
|
713
|
+
([f arg1 arg2 arg3]
|
714
|
+
(fn [& args] (apply f arg1 arg2 arg3 args)))
|
715
|
+
([f arg1 arg2 arg3 & more]
|
716
|
+
(fn [& args] (apply f arg1 arg2 arg3 (concat more args)))))
|
717
|
+
|
718
|
+
; Useful macros
|
719
|
+
|
720
|
+
(defmacro when
|
721
|
+
"Evaluate test. If logical true, evaluate body in an implicit do."
|
722
|
+
[test & body]
|
723
|
+
`(if ~test (do ~@body)))
|
724
|
+
|
725
|
+
(defmacro when-not
|
726
|
+
"Evaluate test. If logical false, evaluate body in an implicit do."
|
727
|
+
[test & body]
|
728
|
+
`(if ~test nil (do ~@body)))
|
729
|
+
|
730
|
+
(defmacro ..
|
731
|
+
"form => method-name or (method-name args*)
|
732
|
+
|
733
|
+
Expands into a method send (.) of the first method on the first argument,
|
734
|
+
followed by the next method on the result, etc. For instance:
|
735
|
+
|
736
|
+
(.. \"one two three\" split reverse (join \" \"))
|
737
|
+
|
738
|
+
expands to:
|
739
|
+
|
740
|
+
(. (. (. \"one two three\" split) reverse) (join \" \"))
|
741
|
+
|
742
|
+
but is easier to write, read, and understand."
|
743
|
+
([x form]
|
744
|
+
`(. ~x ~form))
|
745
|
+
([x form & more]
|
746
|
+
`(.. (. ~x ~form) ~@more)))
|
747
|
+
|
748
|
+
(defmacro ->
|
749
|
+
"Thread the expr through the forms. Insert x as the second item in the first
|
750
|
+
form, making a list of it if it is not a list already. If there are more
|
751
|
+
forms, insert the first form as the second item in second form, etc."
|
752
|
+
([x] x)
|
753
|
+
([x form]
|
754
|
+
(if (seq? form)
|
755
|
+
`(~(first form) ~x ~@(next form))
|
756
|
+
(list form x)))
|
757
|
+
([x form & more]
|
758
|
+
`(-> (-> ~x ~form) ~@more)))
|
759
|
+
|
760
|
+
(defmacro ->>
|
761
|
+
"Thread the expr through the forms. Insert x as the last item in the first
|
762
|
+
form, making a list of it if it is not a list already. If there are more
|
763
|
+
forms, insert the first form as the last item in second form, etc."
|
764
|
+
([x] x)
|
765
|
+
([x form]
|
766
|
+
(if (seq? form)
|
767
|
+
`(~(first form) ~@(next form) ~x)
|
768
|
+
(list form x)))
|
769
|
+
([x form & more]
|
770
|
+
`(->> (->> ~x ~form) ~@more)))
|
771
|
+
|
772
|
+
(defmacro if-let
|
773
|
+
"bindings => var test
|
774
|
+
|
775
|
+
If test is true, evaluate then with var bound to the value of test,
|
776
|
+
otherwise yield else."
|
777
|
+
[bindings then [else nil]]
|
778
|
+
`(let [temp# ~(bindings 1)]
|
779
|
+
(if temp#
|
780
|
+
(let [~(bindings 0) temp#]
|
781
|
+
~then)
|
782
|
+
~else)))
|
783
|
+
|
784
|
+
(defmacro cond
|
785
|
+
"Take a set of test/expr pairs. Evaluate each test one at a time. If a test
|
786
|
+
returns logical true, evaluate and return the value of the corresponding
|
787
|
+
expr and don't evaluate any of the other tests or exprs. (cond) returns
|
788
|
+
nil."
|
789
|
+
[& clauses]
|
790
|
+
(when-not (even? (count clauses))
|
791
|
+
(raise ArgumentError "cond requires an even number of forms"))
|
792
|
+
(when-not (empty? clauses)
|
793
|
+
`(if ~(first clauses)
|
794
|
+
~(second clauses)
|
795
|
+
(cond ~@(drop 2 clauses)))))
|
796
|
+
|
797
|
+
(defmacro case
|
798
|
+
"when => [expr ...+] expr
|
799
|
+
else => expr
|
800
|
+
|
801
|
+
Works like Ruby's case/when syntax (uses the === method).
|
802
|
+
|
803
|
+
Example:
|
804
|
+
(case x
|
805
|
+
[Array] \"x is an array\"
|
806
|
+
[String Symbol] \"x is a string or symbol\"
|
807
|
+
[1 2] \"x is equal to 1 or 2\"
|
808
|
+
\"x is unknown\")"
|
809
|
+
{:arglists '([x when ... else?])}
|
810
|
+
[x & forms]
|
811
|
+
(let [else (if (odd? (count forms))
|
812
|
+
(.pop forms))
|
813
|
+
val (gensym "case")
|
814
|
+
expand (fn expand [& forms]
|
815
|
+
(if (seq forms)
|
816
|
+
`(if (or ~@(map (fn [test] `(. ~test === ~val))
|
817
|
+
(first forms)))
|
818
|
+
~(second forms)
|
819
|
+
~(apply expand (drop 2 forms)))
|
820
|
+
else))]
|
821
|
+
`(let [~val ~x]
|
822
|
+
~(apply expand forms))))
|
823
|
+
|
824
|
+
(defmacro doto
|
825
|
+
"Evaluate x then call all of the methods and functions with the value of x
|
826
|
+
supplied at the front of the given arguments. The forms are evaluated in
|
827
|
+
order. Return x.
|
828
|
+
|
829
|
+
(doto (Hash.) (.store :a 1) (.store :b 2)) ;=> {:a 1, :b 2}"
|
830
|
+
[x & forms]
|
831
|
+
(let [gx (gensym "doto")]
|
832
|
+
`(let [~gx ~x]
|
833
|
+
~@(map (fn [f]
|
834
|
+
(if (seq? f)
|
835
|
+
`(~(first f) ~gx ~@(rest f))
|
836
|
+
`(~f ~gx)))
|
837
|
+
forms)
|
838
|
+
~gx)))
|
839
|
+
|
840
|
+
; Miscellaneous (to be sorted)
|
841
|
+
|
842
|
+
(defn eval
|
843
|
+
"Evaluate the form data structure (not text!) and return the result."
|
844
|
+
[form] (Apricot::Compiler/eval_form form))
|
845
|
+
|
846
|
+
(defmacro each [binding & body]
|
847
|
+
`(.each ~(last binding)
|
848
|
+
| (fn [~(first binding)] ~@body)))
|
849
|
+
|
850
|
+
(defmacro while-let [binding & body]
|
851
|
+
`(loop []
|
852
|
+
(let ~binding
|
853
|
+
(when ~(first binding)
|
854
|
+
~@body
|
855
|
+
(recur)))))
|
856
|
+
|
857
|
+
; Structs
|
858
|
+
|
859
|
+
(defmacro defstruct [name & fields]
|
860
|
+
`(def ~name (Struct. ~@(map symbol fields))))
|
861
|
+
|
862
|
+
; Macros for defining Ruby classes and methods
|
863
|
+
|
864
|
+
(defmacro defmethod [target name & body]
|
865
|
+
`(.send ~target :define_method ~(symbol name) | (fn ~name ~@body)))
|
866
|
+
|
867
|
+
(defmacro defclass
|
868
|
+
([name]
|
869
|
+
`(def ~name (Class.)))
|
870
|
+
([name superclass]
|
871
|
+
`(def ~name (Class. ~superclass))))
|
872
|
+
|
873
|
+
; Metadata
|
874
|
+
|
875
|
+
(defn meta
|
876
|
+
"Return the metadata of obj."
|
877
|
+
[obj] (.apricot_meta obj))
|
878
|
+
|
879
|
+
; Documentation
|
880
|
+
|
881
|
+
(defn doc
|
882
|
+
"Print the documentation for the given function or macro."
|
883
|
+
[f]
|
884
|
+
(let [m (meta f)]
|
885
|
+
(println "-------------------------")
|
886
|
+
(println (m :name))
|
887
|
+
(println (m :arglists))
|
888
|
+
(if (m :macro)
|
889
|
+
(println "Macro"))
|
890
|
+
(println " " (m :doc))))
|
891
|
+
|
892
|
+
; REPL Utilities
|
893
|
+
|
894
|
+
(defn decode
|
895
|
+
"Print the Rubinius bytecode for the given Proc or Method."
|
896
|
+
[f]
|
897
|
+
(case f
|
898
|
+
[Proc] (Kernel/puts (.. f block compiled_code decode))
|
899
|
+
[Method] (Kernel/puts (.. f executable decode))
|
900
|
+
(raise (str "Don't know how to decode " (.inspect f)))))
|
901
|
+
|
902
|
+
(defmacro time
|
903
|
+
"Evaluate the forms in body and return the time it took."
|
904
|
+
[& body]
|
905
|
+
`(do
|
906
|
+
(require "benchmark")
|
907
|
+
(.realtime Benchmark | (fn [] ~@body))))
|
908
|
+
|
909
|
+
(defmacro benchmark-ips
|
910
|
+
"clause => [label form ...]
|
911
|
+
|
912
|
+
Measure how many times per second each of the clause's bodies can be
|
913
|
+
executed. Output is organized using the given label strings.
|
914
|
+
|
915
|
+
This requires the benchmark-ips gem:
|
916
|
+
gem install benchmark-ips"
|
917
|
+
[& clauses]
|
918
|
+
(let [bm (gensym)
|
919
|
+
make-report (fn [clause]
|
920
|
+
`(.report ~bm ~(first clause) | (fn [] ~@(rest clause))))
|
921
|
+
reports (map make-report clauses)]
|
922
|
+
`(do
|
923
|
+
(try
|
924
|
+
(require "benchmark/ips")
|
925
|
+
(.ips Benchmark | (fn [~bm] ~@reports))
|
926
|
+
(rescue [_ LoadError]
|
927
|
+
(raise "benchmark-ips requires the benchmark-ips gem")))
|
928
|
+
nil)))
|