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.
Files changed (49) hide show
  1. data/.gitignore +3 -0
  2. data/.rspec +1 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +7 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.lock +26 -0
  7. data/README.md +90 -0
  8. data/Rakefile +9 -0
  9. data/apricot.gemspec +22 -0
  10. data/bin/apricot +58 -0
  11. data/examples/bot.apr +23 -0
  12. data/examples/cinch-bot.apr +12 -0
  13. data/examples/hanoi.apr +10 -0
  14. data/examples/hello.apr +1 -0
  15. data/examples/plot.apr +28 -0
  16. data/examples/quine.apr +1 -0
  17. data/kernel/core.apr +928 -0
  18. data/lib/apricot/ast/identifier.rb +111 -0
  19. data/lib/apricot/ast/list.rb +99 -0
  20. data/lib/apricot/ast/literals.rb +240 -0
  21. data/lib/apricot/ast/node.rb +45 -0
  22. data/lib/apricot/ast/scopes.rb +147 -0
  23. data/lib/apricot/ast/toplevel.rb +66 -0
  24. data/lib/apricot/ast/variables.rb +64 -0
  25. data/lib/apricot/ast.rb +3 -0
  26. data/lib/apricot/compiler.rb +55 -0
  27. data/lib/apricot/cons.rb +27 -0
  28. data/lib/apricot/errors.rb +38 -0
  29. data/lib/apricot/generator.rb +15 -0
  30. data/lib/apricot/identifier.rb +91 -0
  31. data/lib/apricot/list.rb +96 -0
  32. data/lib/apricot/macroexpand.rb +47 -0
  33. data/lib/apricot/misc.rb +11 -0
  34. data/lib/apricot/namespace.rb +59 -0
  35. data/lib/apricot/parser.rb +541 -0
  36. data/lib/apricot/printers.rb +12 -0
  37. data/lib/apricot/repl.rb +254 -0
  38. data/lib/apricot/ruby_ext.rb +254 -0
  39. data/lib/apricot/seq.rb +44 -0
  40. data/lib/apricot/special_forms.rb +735 -0
  41. data/lib/apricot/stages.rb +60 -0
  42. data/lib/apricot/version.rb +3 -0
  43. data/lib/apricot.rb +30 -0
  44. data/spec/compiler_spec.rb +499 -0
  45. data/spec/identifier_spec.rb +58 -0
  46. data/spec/list_spec.rb +96 -0
  47. data/spec/parser_spec.rb +312 -0
  48. data/spec/spec_helper.rb +10 -0
  49. 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)))