apricot 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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)))
|