rouge-lang 0.0.4 → 0.0.5
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/README.md +5 -10
- data/lib/boot.rg +89 -6
- data/lib/rouge.rb +11 -9
- data/lib/rouge/seq.rb +59 -29
- data/lib/rouge/version.rb +1 -1
- data/spec/core_spec.rg +29 -1
- metadata +2 -2
data/README.md
CHANGED
@@ -8,19 +8,14 @@ Why?
|
|
8
8
|
* Quick boot time (currently around 0.1s).
|
9
9
|
* Ruby's gems tend to be modern with decent APIs.
|
10
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:
|
11
|
+
You can try a Rouge REPL online at **[Try Rouge](http://try.rouge.io)**, or install the gem to get the local REPL:
|
15
12
|
|
16
13
|
``` bash
|
17
|
-
|
18
|
-
|
19
|
-
bundle install
|
20
|
-
bin/rouge
|
14
|
+
gem install rouge-lang
|
15
|
+
rouge
|
21
16
|
```
|
22
17
|
|
23
|
-
You'll see the `user=>` prompt. Enjoy!
|
18
|
+
You'll see the `user=>` prompt. Enjoy!
|
24
19
|
|
25
20
|
You can discuss on Google Groups' [rouge-talk](https://groups.google.com/forum/#!forum/rouge-talk),
|
26
21
|
or on `#rouge` on Freenode.
|
@@ -54,7 +49,7 @@ salient features:
|
|
54
49
|
What about in Rails?
|
55
50
|
|
56
51
|
```
|
57
|
-
$
|
52
|
+
$ rails console -- -rrouge
|
58
53
|
Loading development environment (Rails 3.2.6)
|
59
54
|
1.9.3p194 :002 > Rouge::REPL.repl []
|
60
55
|
user=> (.where ruby/Content {:id 1})
|
data/lib/boot.rg
CHANGED
@@ -31,7 +31,7 @@
|
|
31
31
|
`(Rouge.Seq.Lazy. (fn [] ~@body)))
|
32
32
|
|
33
33
|
(defn reduce [f coll]
|
34
|
-
(.inject (.to_a coll) | f))
|
34
|
+
(.inject (.to_a (seq coll)) | f))
|
35
35
|
|
36
36
|
(defmacro when [cond & body]
|
37
37
|
`(if ~cond
|
@@ -42,7 +42,8 @@
|
|
42
42
|
(Rouge.Seq.Cons. head tail))
|
43
43
|
|
44
44
|
(defn count [coll]
|
45
|
-
(
|
45
|
+
(let [s (seq coll)]
|
46
|
+
(if s (.count s) 0)))
|
46
47
|
|
47
48
|
(defn = [a b]
|
48
49
|
(.== a b))
|
@@ -72,10 +73,11 @@
|
|
72
73
|
|
73
74
|
(defn map [f coll]
|
74
75
|
(lazy-seq
|
75
|
-
(
|
76
|
-
|
77
|
-
|
78
|
-
(
|
76
|
+
(let [s (seq coll)]
|
77
|
+
(if (empty? s)
|
78
|
+
nil
|
79
|
+
(let [[hd & tl] s]
|
80
|
+
(cons (f hd) (map f tl)))))))
|
79
81
|
|
80
82
|
(defn str [& args]
|
81
83
|
(let [args (.to_a (map .to_s args))]
|
@@ -94,6 +96,9 @@
|
|
94
96
|
(defn class [object]
|
95
97
|
(.class object))
|
96
98
|
|
99
|
+
(defn class? [obj class]
|
100
|
+
(.is_a? obj class))
|
101
|
+
|
97
102
|
(defn sequential? [coll]
|
98
103
|
(or (.is_a? coll Rouge.Seq.ISeq)
|
99
104
|
(.is_a? coll Array)))
|
@@ -363,6 +368,84 @@
|
|
363
368
|
.to_a
|
364
369
|
(.sort_by | keyfn)))
|
365
370
|
|
371
|
+
(defn to-array [coll]
|
372
|
+
"Returns an array of (seq coll)."
|
373
|
+
(.to_a (seq coll)))
|
374
|
+
|
375
|
+
(defmacro cond
|
376
|
+
([])
|
377
|
+
([test result & rest]
|
378
|
+
`(if ~test ~result (cond ~@rest))))
|
379
|
+
|
380
|
+
(ns ^{:doc "Implemenations of functions from clojure.string."}
|
381
|
+
rouge.string
|
382
|
+
(:use rouge.core ruby))
|
383
|
+
|
384
|
+
(defn blank? [s]
|
385
|
+
"Returns true if s is falsy, empty, or contains only whitespace."
|
386
|
+
(if s
|
387
|
+
(if (or (= (.length s) 0)
|
388
|
+
true
|
389
|
+
(if (.all? (to-array s) | #(.match #"\s" %))
|
390
|
+
true
|
391
|
+
false))
|
392
|
+
false)))
|
393
|
+
|
394
|
+
(defn lower-case [s]
|
395
|
+
"Converts the characters in string s to all lower-case."
|
396
|
+
(.downcase s))
|
397
|
+
|
398
|
+
(defn upper-case [s]
|
399
|
+
"Converts the string s to all upper-case."
|
400
|
+
(.upcase s))
|
401
|
+
|
402
|
+
(defn capitalize [s]
|
403
|
+
"Converts a string to all lower-case with the first character capitalized"
|
404
|
+
(-> s .downcase .capitalize))
|
405
|
+
|
406
|
+
(defn trim [s]
|
407
|
+
"Removes all leading and trailing whitespace characters from the string s."
|
408
|
+
(.strip s))
|
409
|
+
|
410
|
+
(defn ltrim [s]
|
411
|
+
"Removes all leading whitespace characters from the string s."
|
412
|
+
(.lstrip s))
|
413
|
+
|
414
|
+
(defn rtrim [s]
|
415
|
+
"Removes all trailing whitespace characters from the string s."
|
416
|
+
(.rstrip s))
|
417
|
+
|
418
|
+
(defn trim-newline [s]
|
419
|
+
"Removes all trailing newline characters from the string s."
|
420
|
+
(.sub s #"(\n|\r)*$" ""))
|
421
|
+
|
422
|
+
(defn split [s delimiter]
|
423
|
+
"Splits a string s in to substrings based on delimiter. The delimiter may be
|
424
|
+
either another string or regular expression."
|
425
|
+
(.split s delimiter))
|
426
|
+
|
427
|
+
(defn split-lines [s]
|
428
|
+
"Split the string s in to substrings at new lines."
|
429
|
+
(.split s #"\n|\r"))
|
430
|
+
|
431
|
+
(defn join [separator coll]
|
432
|
+
"Returns a string in which all elements in coll are joined by the separator."
|
433
|
+
(.join (to-array coll) separator))
|
434
|
+
|
435
|
+
(defn reverse [s]
|
436
|
+
"Returns the string s with it's characters in reverse order."
|
437
|
+
(.reverse s))
|
438
|
+
|
439
|
+
;; TODO
|
440
|
+
#_(defn escape [s cmap])
|
441
|
+
|
442
|
+
;; TODO
|
443
|
+
#_(defn replace [s match replacement])
|
444
|
+
|
445
|
+
;; TODO
|
446
|
+
#_(defn replace-first [s match replacement])
|
447
|
+
|
448
|
+
|
366
449
|
(ns rouge.test
|
367
450
|
(:use rouge.core ruby))
|
368
451
|
|
data/lib/rouge.rb
CHANGED
@@ -9,7 +9,7 @@ module Rouge; end
|
|
9
9
|
start = Time.now
|
10
10
|
Rouge.define_singleton_method :start, lambda {start}
|
11
11
|
|
12
|
-
|
12
|
+
module Rouge
|
13
13
|
require 'rouge/version'
|
14
14
|
require 'rouge/wrappers'
|
15
15
|
require 'rouge/symbol'
|
@@ -19,36 +19,38 @@ class << Rouge
|
|
19
19
|
require 'rouge/context'
|
20
20
|
require 'rouge/repl'
|
21
21
|
|
22
|
-
def print(form, out)
|
22
|
+
def self.print(form, out)
|
23
23
|
Rouge::Printer.print form, out
|
24
24
|
end
|
25
25
|
|
26
|
-
def [](ns)
|
26
|
+
def self.[](ns)
|
27
27
|
Rouge::Namespace[ns]
|
28
28
|
end
|
29
29
|
|
30
|
-
def boot!
|
30
|
+
def self.boot!
|
31
31
|
return if @booted
|
32
32
|
@booted = true
|
33
33
|
|
34
|
+
builtin = Rouge[:"rouge.builtin"]
|
35
|
+
|
34
36
|
core = Rouge[:"rouge.core"]
|
35
|
-
core.refer
|
37
|
+
core.refer builtin
|
36
38
|
|
37
39
|
user = Rouge[:user]
|
38
|
-
user.refer
|
39
|
-
user.refer
|
40
|
+
user.refer builtin
|
41
|
+
user.refer core
|
40
42
|
user.refer Rouge[:ruby]
|
41
43
|
|
42
44
|
Rouge::Context.new(user).readeval(
|
43
45
|
File.read(Rouge.relative_to_lib('boot.rg')))
|
44
46
|
end
|
45
47
|
|
46
|
-
def repl(argv)
|
48
|
+
def self.repl(argv)
|
47
49
|
boot!
|
48
50
|
Rouge::REPL.repl(argv)
|
49
51
|
end
|
50
52
|
|
51
|
-
def relative_to_lib name
|
53
|
+
def self.relative_to_lib name
|
52
54
|
File.join(File.dirname(File.absolute_path(__FILE__)), name)
|
53
55
|
end
|
54
56
|
end
|
data/lib/rouge/seq.rb
CHANGED
@@ -1,12 +1,30 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
# Functions, clases and modules concerning the `seq' sequence abstraction.
|
3
4
|
module Rouge::Seq
|
5
|
+
# An empty seq.
|
4
6
|
Empty = Object.new
|
5
7
|
|
8
|
+
# A sequence consisting of a head (element) and tail (another sequence).
|
9
|
+
# Filled out below after ASeq's definition.
|
6
10
|
class Cons; end
|
7
11
|
|
12
|
+
# A module purely to indicate that this is a seqable type. Any class
|
13
|
+
# including ISeq should define a #seq method.
|
8
14
|
module ISeq; end
|
9
15
|
|
16
|
+
# A partial implementation of ISeq. You supply #first and #next, it gives:
|
17
|
+
#
|
18
|
+
# - #cons
|
19
|
+
# - #inspect
|
20
|
+
# - #to_s
|
21
|
+
# - #seq
|
22
|
+
# - #length (#count)
|
23
|
+
# - #[]
|
24
|
+
# - #==
|
25
|
+
# - #each
|
26
|
+
# - #map
|
27
|
+
# - #to_a
|
10
28
|
module ASeq
|
11
29
|
include ISeq
|
12
30
|
|
@@ -22,41 +40,41 @@ module Rouge::Seq
|
|
22
40
|
def next; raise NotImplementedError; end
|
23
41
|
|
24
42
|
def more
|
25
|
-
|
26
|
-
if
|
43
|
+
nseq = self.next
|
44
|
+
if nseq.nil?
|
27
45
|
Empty
|
28
46
|
else
|
29
|
-
|
47
|
+
nseq
|
30
48
|
end
|
31
49
|
end
|
32
50
|
|
33
|
-
def cons(
|
34
|
-
Cons.new(
|
51
|
+
def cons(head)
|
52
|
+
Cons.new(head, self)
|
35
53
|
end
|
36
54
|
|
37
55
|
def length
|
38
|
-
|
56
|
+
len = 0
|
39
57
|
cursor = self
|
40
58
|
|
41
59
|
while cursor != Empty
|
42
|
-
|
60
|
+
len += 1
|
43
61
|
cursor = cursor.more
|
44
62
|
end
|
45
63
|
|
46
|
-
|
64
|
+
len
|
47
65
|
end
|
48
66
|
|
49
67
|
alias count length
|
50
68
|
|
51
|
-
def [](
|
52
|
-
return to_a[
|
69
|
+
def [](idx)
|
70
|
+
return to_a[idx] if idx.is_a? Range
|
53
71
|
|
54
72
|
cursor = self
|
55
73
|
|
56
|
-
|
74
|
+
idx += self.length if idx < 0
|
57
75
|
|
58
|
-
while
|
59
|
-
|
76
|
+
while idx > 0
|
77
|
+
idx -= 1
|
60
78
|
cursor = cursor.more
|
61
79
|
return nil if cursor == Empty
|
62
80
|
end
|
@@ -65,8 +83,15 @@ module Rouge::Seq
|
|
65
83
|
end
|
66
84
|
|
67
85
|
def ==(seq)
|
68
|
-
|
69
|
-
|
86
|
+
if seq.is_a?(ISeq)
|
87
|
+
return self.to_a == seq.to_a
|
88
|
+
end
|
89
|
+
|
90
|
+
if seq.is_a?(::Array)
|
91
|
+
return self.to_a == seq
|
92
|
+
end
|
93
|
+
|
94
|
+
false
|
70
95
|
end
|
71
96
|
|
72
97
|
def each(&block)
|
@@ -86,9 +111,9 @@ module Rouge::Seq
|
|
86
111
|
def map(&block)
|
87
112
|
return self.enum_for(:map) if block.nil?
|
88
113
|
|
89
|
-
|
90
|
-
self.each {|
|
91
|
-
|
114
|
+
result = []
|
115
|
+
self.each {|elem| result << block.call(elem)}
|
116
|
+
result
|
92
117
|
end
|
93
118
|
|
94
119
|
def to_a
|
@@ -96,10 +121,6 @@ module Rouge::Seq
|
|
96
121
|
self.each {|e| r << e}
|
97
122
|
r
|
98
123
|
end
|
99
|
-
|
100
|
-
def map(&block)
|
101
|
-
Cons[*to_a.map(&block)]
|
102
|
-
end
|
103
124
|
end
|
104
125
|
|
105
126
|
class << Empty
|
@@ -135,10 +156,11 @@ module Rouge::Seq
|
|
135
156
|
def next; Rouge::Seq.seq @tail; end
|
136
157
|
|
137
158
|
def self.[](*elements)
|
138
|
-
|
159
|
+
length = elements.length
|
160
|
+
return Empty if length.zero?
|
139
161
|
|
140
162
|
head = nil
|
141
|
-
(
|
163
|
+
(length - 1).downto(0).each do |i|
|
142
164
|
head = new(elements[i], head.freeze)
|
143
165
|
end
|
144
166
|
|
@@ -148,24 +170,27 @@ module Rouge::Seq
|
|
148
170
|
attr_reader :head, :tail
|
149
171
|
end
|
150
172
|
|
173
|
+
# A seq over a Ruby Array.
|
151
174
|
class Array
|
152
175
|
include ASeq
|
153
176
|
|
154
|
-
def initialize(array,
|
155
|
-
@array, @
|
177
|
+
def initialize(array, idx)
|
178
|
+
@array, @idx = array, idx
|
156
179
|
end
|
157
180
|
|
158
181
|
def first
|
159
|
-
@array[@
|
182
|
+
@array[@idx]
|
160
183
|
end
|
161
184
|
|
162
185
|
def next
|
163
|
-
if @
|
164
|
-
Array.new(@array, @
|
186
|
+
if @idx + 1 < @array.length
|
187
|
+
Array.new(@array, @idx + 1)
|
165
188
|
end
|
166
189
|
end
|
167
190
|
end
|
168
191
|
|
192
|
+
# A lazy seq; contains the body (thunk) which is a lambda to get the "real"
|
193
|
+
# seq. Once evaluated (realised), the result is cached.
|
169
194
|
class Lazy
|
170
195
|
include ISeq
|
171
196
|
|
@@ -179,6 +204,7 @@ module Rouge::Seq
|
|
179
204
|
@result
|
180
205
|
else
|
181
206
|
@result = Rouge::Seq.seq(@body.call) || Empty
|
207
|
+
@body = nil
|
182
208
|
@realized = true
|
183
209
|
@result
|
184
210
|
end
|
@@ -196,6 +222,8 @@ module Rouge::Seq
|
|
196
222
|
def to_s; seq.to_s; end
|
197
223
|
end
|
198
224
|
|
225
|
+
# An error thrown when we try to do a seq operation on something that's not
|
226
|
+
# seqable.
|
199
227
|
UnknownSeqError = Class.new(StandardError)
|
200
228
|
|
201
229
|
def self.seq(form)
|
@@ -212,6 +240,8 @@ module Rouge::Seq
|
|
212
240
|
end
|
213
241
|
when Enumerator
|
214
242
|
seq(form.to_a)
|
243
|
+
when String
|
244
|
+
seq(form.chars)
|
215
245
|
else
|
216
246
|
raise UnknownSeqError, form.inspect
|
217
247
|
end
|
data/lib/rouge/version.rb
CHANGED
data/spec/core_spec.rg
CHANGED
@@ -37,7 +37,8 @@
|
|
37
37
|
(testing "seq"
|
38
38
|
(is (.nil? (seq ())))
|
39
39
|
(is (.nil? (seq nil)))
|
40
|
-
(is (.nil? (seq [])))
|
40
|
+
(is (.nil? (seq [])))
|
41
|
+
(is (.nil? (seq ""))))
|
41
42
|
|
42
43
|
(testing "first"
|
43
44
|
(is (.nil? (first nil)))
|
@@ -90,6 +91,7 @@
|
|
90
91
|
(testing "map"
|
91
92
|
(is (= Rouge.Seq.Lazy (class (map inc [1 2 3]))))
|
92
93
|
(is (= '(2 3 4) (map inc [1 2 3])))
|
94
|
+
(is (= '("A" "B" "C") (map .upcase "abc")))
|
93
95
|
(is (= 1
|
94
96
|
(let [q (atom 0)
|
95
97
|
lazy (map #(do (swap! q inc) (inc %)) [1 2 3])]
|
@@ -123,4 +125,30 @@
|
|
123
125
|
[hd & tl] (map #(do (swap! q inc) (inc %)) [1 2 3])]
|
124
126
|
@q)))))
|
125
127
|
|
128
|
+
(testing "cond"
|
129
|
+
(is (= 1 (cond
|
130
|
+
:else 1)))
|
131
|
+
(is (= 1 (cond
|
132
|
+
false 2
|
133
|
+
nil 3
|
134
|
+
true 1)))
|
135
|
+
(is (nil? (cond)))
|
136
|
+
(is (nil? (cond
|
137
|
+
false 1
|
138
|
+
nil 2)))
|
139
|
+
(is (= 1 (let [q (atom 0)]
|
140
|
+
(is (= :ok (cond
|
141
|
+
(swap! q inc) :ok
|
142
|
+
(swap! q inc) :bad
|
143
|
+
(swap! q inc) :very_bad)))
|
144
|
+
@q)))
|
145
|
+
(is (= 2 (let [q (atom 0)]
|
146
|
+
(is (= :ok (cond
|
147
|
+
(do
|
148
|
+
(swap! q inc)
|
149
|
+
nil) :bad
|
150
|
+
(swap! q inc) :ok
|
151
|
+
(swap! q inc) :very_bad)))
|
152
|
+
@q))))
|
153
|
+
|
126
154
|
; vim: set ft=clojure:
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rouge-lang
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|