rouge-lang 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/.autotest +11 -0
- data/.gitignore +20 -0
- data/.rspec +1 -0
- data/.travis.yml +3 -0
- data/Gemfile +6 -0
- data/LICENSE +19 -0
- data/README.md +119 -0
- data/Rakefile +8 -0
- data/bin/rouge +2 -0
- data/lib/boot.rg +402 -0
- data/lib/rouge.rb +56 -0
- data/lib/rouge/atom.rb +25 -0
- data/lib/rouge/builtins.rb +596 -0
- data/lib/rouge/compiler.rb +108 -0
- data/lib/rouge/context.rb +235 -0
- data/lib/rouge/metadata.rb +19 -0
- data/lib/rouge/namespace.rb +125 -0
- data/lib/rouge/printer.rb +78 -0
- data/lib/rouge/reader.rb +433 -0
- data/lib/rouge/repl.rb +82 -0
- data/lib/rouge/seq.rb +221 -0
- data/lib/rouge/symbol.rb +77 -0
- data/lib/rouge/var.rb +69 -0
- data/lib/rouge/version.rb +7 -0
- data/lib/rouge/wrappers.rb +27 -0
- data/misc/TODO +45 -0
- data/misc/vimrc +1 -0
- data/rouge-lang.gemspec +28 -0
- data/spec/atom_spec.rb +39 -0
- data/spec/builtins_spec.rb +708 -0
- data/spec/compiler_spec.rb +137 -0
- data/spec/context_spec.rb +293 -0
- data/spec/core_spec.rg +123 -0
- data/spec/metadata_spec.rb +59 -0
- data/spec/namespace_spec.rb +125 -0
- data/spec/printer_spec.rb +191 -0
- data/spec/reader_spec.rb +422 -0
- data/spec/rouge_spec.rb +66 -0
- data/spec/seq_spec.rb +202 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/symbol_spec.rb +35 -0
- data/spec/var_spec.rb +61 -0
- data/spec/wrappers_spec.rb +51 -0
- metadata +216 -0
data/.autotest
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2012 Arlen Christian Mart Cuss
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
5
|
+
the Software without restriction, including without limitation the rights to
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
7
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
8
|
+
so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
# Rouge [](http://travis-ci.org/unnali/rouge)
|
2
|
+
|
3
|
+
**Ruby + Clojure = Rouge.**
|
4
|
+
|
5
|
+
Why?
|
6
|
+
|
7
|
+
* Clojure is elegant and fun.
|
8
|
+
* Quick boot time (currently around 0.1s).
|
9
|
+
* Ruby's gems tend to be modern with decent APIs.
|
10
|
+
|
11
|
+
You can try a Rouge REPL online at **[Try Rouge](http://try.rouge.io)**.
|
12
|
+
|
13
|
+
Rouge is not yet mature enough to have an installer or distributions. Just
|
14
|
+
clone the source and run the `rouge` script to start:
|
15
|
+
|
16
|
+
``` bash
|
17
|
+
git clone git://github.com/unnali/rouge
|
18
|
+
cd rouge
|
19
|
+
bundle install
|
20
|
+
bin/rouge
|
21
|
+
```
|
22
|
+
|
23
|
+
You'll see the `user=>` prompt. Enjoy! (Expect plenty of stack traces.)
|
24
|
+
|
25
|
+
You can discuss on Google Groups' [rouge-talk](https://groups.google.com/forum/#!forum/rouge-talk),
|
26
|
+
or on `#rouge` on Freenode.
|
27
|
+
|
28
|
+
## example
|
29
|
+
|
30
|
+
See [boot.rg](https://github.com/unnali/rouge/blob/master/lib/boot.rg),
|
31
|
+
[em-rg](https://github.com/unnali/em-rg),
|
32
|
+
[mechanize-rg](https://github.com/unnali/mechanize-rg), but to demonstrate
|
33
|
+
salient features:
|
34
|
+
|
35
|
+
``` clojure
|
36
|
+
; define a macro
|
37
|
+
(defmacro defn [name args & body]
|
38
|
+
`(def ~name (fn ~name ~args ~@body)))
|
39
|
+
|
40
|
+
; call a Ruby method on Kernel (if the ruby namespace is referred)
|
41
|
+
(defn require [lib]
|
42
|
+
(.require Kernel lib))
|
43
|
+
|
44
|
+
; call a Ruby method on an Array with a block argument
|
45
|
+
(defn reduce [f coll]
|
46
|
+
(.inject coll | f))
|
47
|
+
|
48
|
+
; using Ruby's AMQP gem with an inline block
|
49
|
+
(.subscribe queue {:ack true} | [metadata payload]
|
50
|
+
(puts (str "got a message: " payload))
|
51
|
+
(.ack metadata))
|
52
|
+
```
|
53
|
+
|
54
|
+
What about in Rails?
|
55
|
+
|
56
|
+
```
|
57
|
+
$ r c -- -I../rouge/lib -rrouge
|
58
|
+
Loading development environment (Rails 3.2.6)
|
59
|
+
1.9.3p194 :002 > Rouge::REPL.repl []
|
60
|
+
user=> (.where ruby/Content {:id 1})
|
61
|
+
Content Load (0.7ms) SELECT "contents".* FROM "contents" WHERE "contents"."id" = 1
|
62
|
+
[#<Content id: 1, content_group_id: 1, name: "welcome", content: "blah blah", created_at: "2012-08-26 11:30:50", updated_at: "2012-08-26 11:50:27", order: nil>]
|
63
|
+
user=>
|
64
|
+
```
|
65
|
+
|
66
|
+
## TODO
|
67
|
+
|
68
|
+
See [TODO](https://github.com/unnali/rouge/blob/master/misc/TODO), but big ones
|
69
|
+
include:
|
70
|
+
|
71
|
+
* making seqs nicer
|
72
|
+
* persistent datastructures everywhere
|
73
|
+
* defprotocol
|
74
|
+
|
75
|
+
## contributions
|
76
|
+
|
77
|
+
**Yes, please!**
|
78
|
+
|
79
|
+
* Fork the project.
|
80
|
+
* Make your feature addition or bug fix.
|
81
|
+
* Add tests! This is so I don't break your lovely addition in the future by accident.
|
82
|
+
* Commit and pull request! (Bonus points for topic branches.)
|
83
|
+
|
84
|
+
**Also**, if there's something in particular you want that's missing, feel free to put your vote in by [opening an Issue](https://github.com/unnali/rouge/issues/new) so I know where to direct my attention.
|
85
|
+
|
86
|
+
## authorship
|
87
|
+
|
88
|
+
Original author: [Arlen Christian Mart Cuss](https://github.com/unnali).
|
89
|
+
|
90
|
+
Unreserved thanks to the following people for their contributions.
|
91
|
+
|
92
|
+
* [Russell Whitaker](https://github.com/russellwhitaker)
|
93
|
+
* [Misha Moroshko](https://github.com/moroshko)
|
94
|
+
* [Anthony Grimes](https://github.com/Raynes)
|
95
|
+
* [Joel Holdbrooks](https://github.com/noprompt)
|
96
|
+
|
97
|
+
## copyright and licensing
|
98
|
+
|
99
|
+
The [MIT license](http://opensource.org/licenses/MIT).
|
100
|
+
|
101
|
+
Copyright © 2012 Arlen Christian Mart Cuss
|
102
|
+
|
103
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
104
|
+
this software and associated documentation files (the "Software"), to deal in
|
105
|
+
the Software without restriction, including without limitation the rights to
|
106
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
107
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
108
|
+
so, subject to the following conditions:
|
109
|
+
|
110
|
+
The above copyright notice and this permission notice shall be included in all
|
111
|
+
copies or substantial portions of the Software.
|
112
|
+
|
113
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
114
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
115
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
116
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
117
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
118
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
119
|
+
SOFTWARE.
|
data/Rakefile
ADDED
data/bin/rouge
ADDED
data/lib/boot.rg
ADDED
@@ -0,0 +1,402 @@
|
|
1
|
+
;; -*- mode: clojure; -*-
|
2
|
+
|
3
|
+
(ns ^{:doc "The Rouge core."
|
4
|
+
:author "Arlen Christian Mart Cuss"}
|
5
|
+
rouge.core
|
6
|
+
(:use ruby))
|
7
|
+
|
8
|
+
(def seq (fn rouge.core/seq [coll]
|
9
|
+
(.seq Rouge.Seq coll)))
|
10
|
+
|
11
|
+
(def concat (fn rouge.core/concat [& lists]
|
12
|
+
; XXX lazy seq
|
13
|
+
(seq (.inject (.to_a (.map lists | .to_a)) | .+))))
|
14
|
+
|
15
|
+
(def list (fn rouge.core/list [& elements]
|
16
|
+
elements))
|
17
|
+
|
18
|
+
(defmacro defn [name args & body]
|
19
|
+
(let [fn-name (.intern (.join [(.name (.ns (context))) (.name name)] "/"))]
|
20
|
+
`(def ~name (fn ~(Rouge.Symbol. fn-name) ~args ~@body))))
|
21
|
+
|
22
|
+
(defmacro when [cond & body]
|
23
|
+
`(if ~cond
|
24
|
+
(do
|
25
|
+
~@body)))
|
26
|
+
|
27
|
+
(defn vector [& args]
|
28
|
+
(.to_a args))
|
29
|
+
|
30
|
+
(defmacro lazy-seq [& body]
|
31
|
+
`(Rouge.Seq.Lazy. (fn [] ~@body)))
|
32
|
+
|
33
|
+
(defn reduce [f coll]
|
34
|
+
(.inject (.to_a coll) | f))
|
35
|
+
|
36
|
+
(defmacro when [cond & body]
|
37
|
+
`(if ~cond
|
38
|
+
(do
|
39
|
+
~@body)))
|
40
|
+
|
41
|
+
(defn cons [head tail]
|
42
|
+
(Rouge.Seq.Cons. head tail))
|
43
|
+
|
44
|
+
(defn count [coll]
|
45
|
+
(.count coll))
|
46
|
+
|
47
|
+
(defn = [a b]
|
48
|
+
(.== a b))
|
49
|
+
|
50
|
+
(defn nil? [x]
|
51
|
+
(.nil? x))
|
52
|
+
|
53
|
+
(defn identical? [x y]
|
54
|
+
"Returns true if x and y are the same object."
|
55
|
+
(= (.object_id x) (.object_id y)))
|
56
|
+
|
57
|
+
(defmacro or
|
58
|
+
([])
|
59
|
+
([x] x)
|
60
|
+
([x & xs] `(let [r# ~x]
|
61
|
+
(if r# r# (or ~@xs)))))
|
62
|
+
|
63
|
+
(defmacro and
|
64
|
+
([] true)
|
65
|
+
([x] x)
|
66
|
+
([x & xs] `(let [r# ~x]
|
67
|
+
(if (not r#) r# (and ~@xs)))))
|
68
|
+
|
69
|
+
(defn empty? [coll]
|
70
|
+
(or (nil? coll)
|
71
|
+
(= 0 (count coll))))
|
72
|
+
|
73
|
+
(defn map [f coll]
|
74
|
+
(lazy-seq
|
75
|
+
(if (empty? coll)
|
76
|
+
nil
|
77
|
+
(let [[hd & tl] coll]
|
78
|
+
(cons (f hd) (map f tl))))))
|
79
|
+
|
80
|
+
(defn str [& args]
|
81
|
+
(let [args (.to_a (map .to_s args))]
|
82
|
+
(.join args "")))
|
83
|
+
|
84
|
+
(defn pr-str [& args]
|
85
|
+
(let [args (.to_a (map #(.print Rouge % (String.)) args))]
|
86
|
+
(.join args " ")))
|
87
|
+
|
88
|
+
(defn print [& args]
|
89
|
+
(.print Kernel (apply pr-str args)))
|
90
|
+
|
91
|
+
(defn puts [& args]
|
92
|
+
(.print Kernel (apply str args) "\n"))
|
93
|
+
|
94
|
+
(defn class [object]
|
95
|
+
(.class object))
|
96
|
+
|
97
|
+
(defn sequential? [coll]
|
98
|
+
(or (.is_a? coll Rouge.Seq.ISeq)
|
99
|
+
(.is_a? coll Array)))
|
100
|
+
|
101
|
+
(defn not [bool]
|
102
|
+
(or (= bool nil)
|
103
|
+
(= bool false)))
|
104
|
+
|
105
|
+
(defn + [& args]
|
106
|
+
(if (empty? args)
|
107
|
+
0
|
108
|
+
(reduce .+ args)))
|
109
|
+
|
110
|
+
(defn - [a & args]
|
111
|
+
(reduce .- (concat (list a) args)))
|
112
|
+
|
113
|
+
(defn * [& args]
|
114
|
+
(if (empty? args)
|
115
|
+
1
|
116
|
+
(reduce .* args)))
|
117
|
+
|
118
|
+
(defn / [a & args]
|
119
|
+
(reduce ./ (concat (list a) args)))
|
120
|
+
|
121
|
+
(defn require [lib]
|
122
|
+
(.require Kernel lib))
|
123
|
+
|
124
|
+
(defn range [from til]
|
125
|
+
; XXX this will blow so many stacks
|
126
|
+
(if (= from til)
|
127
|
+
Rouge.Seq.Empty
|
128
|
+
(cons from (range (+ 1 from) til))))
|
129
|
+
|
130
|
+
(defn seq? [object]
|
131
|
+
(or (= (class object) Rouge.Seq.Cons)
|
132
|
+
(= object Rouge.Seq.Empty)))
|
133
|
+
|
134
|
+
(def *ns* 'user) ; XXX what
|
135
|
+
|
136
|
+
(defn ns-publics [ns]
|
137
|
+
)
|
138
|
+
|
139
|
+
(defn nth [coll index]
|
140
|
+
(.[] (seq coll) index))
|
141
|
+
|
142
|
+
(defn first [coll]
|
143
|
+
(let [s (seq coll)]
|
144
|
+
(and s
|
145
|
+
(.first s))))
|
146
|
+
|
147
|
+
(defn rest [coll]
|
148
|
+
(let [s (seq coll)]
|
149
|
+
(if s
|
150
|
+
(.more s)
|
151
|
+
())))
|
152
|
+
|
153
|
+
(defn next [coll]
|
154
|
+
(let [s (seq coll)]
|
155
|
+
(and s
|
156
|
+
(.next s))))
|
157
|
+
|
158
|
+
(defn second [coll]
|
159
|
+
(first (next coll)))
|
160
|
+
|
161
|
+
(defn > [a b]
|
162
|
+
(.> a b))
|
163
|
+
|
164
|
+
(defn < [a b]
|
165
|
+
(.< a b))
|
166
|
+
|
167
|
+
(defmacro macroexpand [form]
|
168
|
+
`(.compile Rouge.Compiler (.ns (context)) (Set.) ~form))
|
169
|
+
|
170
|
+
(defn push-thread-bindings [map]
|
171
|
+
(.push Rouge.Var map))
|
172
|
+
|
173
|
+
(defn pop-thread-bindings []
|
174
|
+
(.pop Rouge.Var))
|
175
|
+
|
176
|
+
(defn hash-map [& keyvals]
|
177
|
+
(apply .[] Hash keyvals))
|
178
|
+
|
179
|
+
(defmacro binding [bindings & body]
|
180
|
+
(let [var-ize (fn [var-vals]
|
181
|
+
(.flatten
|
182
|
+
(.to_a
|
183
|
+
(map
|
184
|
+
(fn [pair]
|
185
|
+
(let [[key val] pair]
|
186
|
+
[`(.name (var ~key)) val]))
|
187
|
+
(.each_slice var-vals 2)))
|
188
|
+
1))]
|
189
|
+
`(try
|
190
|
+
(push-thread-bindings (hash-map ~@(var-ize bindings)))
|
191
|
+
~@body
|
192
|
+
(finally
|
193
|
+
(pop-thread-bindings)))))
|
194
|
+
|
195
|
+
(defn deref [derefable]
|
196
|
+
(.deref derefable))
|
197
|
+
|
198
|
+
(defn atom [initial]
|
199
|
+
(Rouge.Atom. initial))
|
200
|
+
|
201
|
+
(defn swap! [atom f & args]
|
202
|
+
(apply .swap! atom f args))
|
203
|
+
|
204
|
+
(defn reset! [atom v]
|
205
|
+
(.reset! atom v))
|
206
|
+
|
207
|
+
(defn quot [n1 n2]
|
208
|
+
"Quotient of dividing n1 by n2."
|
209
|
+
(.div n1 n2))
|
210
|
+
|
211
|
+
(defn rem [n1 n2]
|
212
|
+
"Remainder of dividing n1 by n2."
|
213
|
+
(.remainder n1 n2))
|
214
|
+
|
215
|
+
(defn mod [n1 n2]
|
216
|
+
"Modulus of n1 and n2."
|
217
|
+
(.modulo n1 n2))
|
218
|
+
|
219
|
+
(defn inc [n]
|
220
|
+
"Returns one greater than n."
|
221
|
+
(+ n 1))
|
222
|
+
|
223
|
+
(defn dec [n]
|
224
|
+
"Returns one less than n."
|
225
|
+
(- n 1))
|
226
|
+
|
227
|
+
(defn max [x & more]
|
228
|
+
"Returns the greatest value of a set of values."
|
229
|
+
(reduce #(if (> %1 %2) %1 %2) (apply vector x more)))
|
230
|
+
|
231
|
+
(defn min [x & more]
|
232
|
+
"Returns the least value of a set of values."
|
233
|
+
(reduce #(if (< %1 %2) %1 %2) (apply vector x more)))
|
234
|
+
|
235
|
+
(defn zero? [n]
|
236
|
+
"Returns true if n is zero, otherwise false."
|
237
|
+
(.zero? n))
|
238
|
+
|
239
|
+
(defn pos? [n]
|
240
|
+
"Returns true if n is positive, otherwise false."
|
241
|
+
(.> n 0))
|
242
|
+
|
243
|
+
(defn neg? [n]
|
244
|
+
"Returns true if n is negative, otherwise false."
|
245
|
+
(.> 0 n))
|
246
|
+
|
247
|
+
(defn odd? [n]
|
248
|
+
"Returns true if n is odd, otherwise false."
|
249
|
+
(.odd? n))
|
250
|
+
|
251
|
+
(defn even? [n]
|
252
|
+
"Returns true if n is even, otherwise false."
|
253
|
+
(.even? n))
|
254
|
+
|
255
|
+
(defn number? [n]
|
256
|
+
(.is_a? n Numeric))
|
257
|
+
|
258
|
+
(defn integer? [n]
|
259
|
+
"Returns true if n is an integer."
|
260
|
+
(.is_a? n Integer))
|
261
|
+
|
262
|
+
(defn float? [n]
|
263
|
+
"Returns true if n is a floating point number."
|
264
|
+
(.is_a? n Float))
|
265
|
+
|
266
|
+
(defn complex? [n]
|
267
|
+
"Returns true if n is a complex number."
|
268
|
+
(.is_a? n Complex))
|
269
|
+
|
270
|
+
(defn rational? [n]
|
271
|
+
"Returns true if n is a rational number."
|
272
|
+
(or (.is_a? n Rational)
|
273
|
+
(.is_a? n Integer)))
|
274
|
+
|
275
|
+
(defn bit-and [n1 n2]
|
276
|
+
"Bitwise and."
|
277
|
+
(if (and (integer? n1) (integer? n2))
|
278
|
+
(.& n1 n2)
|
279
|
+
(let [msg (str "bit operation not supported for "
|
280
|
+
(class (or (and (not (integer? n1)) n1)
|
281
|
+
(and (not (integer? n2)) n2))))]
|
282
|
+
(throw (ArgumentError. msg)))))
|
283
|
+
|
284
|
+
(defn bit-or [n1 n2]
|
285
|
+
"Bitwise or."
|
286
|
+
(if (and (integer? n1) (integer? n2))
|
287
|
+
(.| n1 n2)
|
288
|
+
(let [msg (str "bit operation not supported for "
|
289
|
+
(class (or (and (not (integer? n1)) n1)
|
290
|
+
(and (not (integer? n2)) n2))))]
|
291
|
+
(throw (ArgumentError. msg)))))
|
292
|
+
|
293
|
+
(defn bit-xor [n1 n2]
|
294
|
+
"Bitwise exclusive or."
|
295
|
+
(.send n1 (.to_sym "^") n2))
|
296
|
+
|
297
|
+
(defn bit-not [n]
|
298
|
+
"Bitwise complement."
|
299
|
+
(.send n (.to_sym "~")))
|
300
|
+
|
301
|
+
(defn bit-shift-left [n1 n2]
|
302
|
+
"Bitwise shift left."
|
303
|
+
(if (and (integer? n1) (integer? n2))
|
304
|
+
(.<< n1 n2)
|
305
|
+
(let [msg (str "bit operation not supported for "
|
306
|
+
(class (or (and (not (integer? n1)) n1)
|
307
|
+
(and (not (integer? n2)) n2))))]
|
308
|
+
(throw (ArgumentError. msg)))))
|
309
|
+
|
310
|
+
(defn bit-shift-right [n1 n2]
|
311
|
+
"Bitwise shift right."
|
312
|
+
(if (and (integer? n1) (integer? n2))
|
313
|
+
(.>> n1 n2)
|
314
|
+
(let [msg (str "bit operation not supported for "
|
315
|
+
(class (or (and (not (integer? n1)) n1)
|
316
|
+
(and (not (integer? n2)) n2))))]
|
317
|
+
(throw (ArgumentError. msg)))))
|
318
|
+
|
319
|
+
(defn conj [coll & xs]
|
320
|
+
; only cons and vector. Also SUCKS.
|
321
|
+
(if (= 0 (count xs))
|
322
|
+
coll
|
323
|
+
(let [c (class coll)
|
324
|
+
[hd & tl] xs]
|
325
|
+
(if (= c Rouge.Seq.Cons)
|
326
|
+
(apply conj (Rouge.Seq.Cons coll hd) tl)
|
327
|
+
(apply conj (.push (.dup coll) hd) tl)))))
|
328
|
+
|
329
|
+
(defn get [map key] ; and [map key not-found]
|
330
|
+
(.[] map key))
|
331
|
+
|
332
|
+
(defn meta [x]
|
333
|
+
; TODO
|
334
|
+
nil)
|
335
|
+
|
336
|
+
(defn with-meta [x m]
|
337
|
+
; TODO
|
338
|
+
x)
|
339
|
+
|
340
|
+
(defmacro .
|
341
|
+
[recv method & args]
|
342
|
+
`(.send ~recv ~(.name method) ~@args))
|
343
|
+
|
344
|
+
(defmacro ->
|
345
|
+
; (-> x) => x
|
346
|
+
([x] x)
|
347
|
+
; (-> e (a b)) => (a e b)
|
348
|
+
; (-> e a) => (a e)
|
349
|
+
([x f]
|
350
|
+
(if (seq? f)
|
351
|
+
`(~(first f) ~x ~@(rest f))
|
352
|
+
`(~f ~x)))
|
353
|
+
([x f & rest]
|
354
|
+
`(-> (-> ~x ~f) ~@rest)))
|
355
|
+
|
356
|
+
(defn re-pattern [s]
|
357
|
+
(.compile Regexp s))
|
358
|
+
|
359
|
+
(ns rouge.test
|
360
|
+
(:use rouge.core ruby))
|
361
|
+
|
362
|
+
(def ^:dynamic *test-level* [])
|
363
|
+
(def *tests-passed* (atom 0))
|
364
|
+
(def *tests-failed* (atom []))
|
365
|
+
|
366
|
+
(defmacro testing [what & tests]
|
367
|
+
`(do
|
368
|
+
(when (= [] *test-level*)
|
369
|
+
(puts))
|
370
|
+
(puts (* " " (count *test-level*) 2) "testing: " ~what)
|
371
|
+
(binding [*test-level* (conj *test-level* ~what)]
|
372
|
+
~@tests
|
373
|
+
{:passed @*tests-passed*
|
374
|
+
:failed @*tests-failed*})))
|
375
|
+
|
376
|
+
(defmacro is [check]
|
377
|
+
`(let [result# (try
|
378
|
+
{:error nil, :result ~check}
|
379
|
+
(catch Exception e#
|
380
|
+
{:error e#, :result false}))]
|
381
|
+
(if (not (get result# :result))
|
382
|
+
(do
|
383
|
+
(swap! *tests-failed* conj (conj *test-level* (pr-str '~check)))
|
384
|
+
(puts "FAIL in ???")
|
385
|
+
(puts "expected: " ~(pr-str check))
|
386
|
+
(let [actual#
|
387
|
+
(let [error# (get result# :error)]
|
388
|
+
(if error#
|
389
|
+
error#
|
390
|
+
(if (and (seq? '~check)
|
391
|
+
(= 'not (first '~check)))
|
392
|
+
(second '~check)
|
393
|
+
`(not ~'~check))))]
|
394
|
+
(puts " actual: " (pr-str actual#))))
|
395
|
+
(do
|
396
|
+
(swap! *tests-passed* inc)
|
397
|
+
true))))
|
398
|
+
|
399
|
+
(defmacro pending [& body]
|
400
|
+
(puts "TODO rouge.test/pending"))
|
401
|
+
|
402
|
+
; vim: set ft=clojure cc=80:
|