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 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
- git clone git://github.com/unnali/rouge
18
- cd rouge
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! (Expect plenty of stack traces.)
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
- $ r c -- -I../rouge/lib -rrouge
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
- (.count coll))
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
- (if (empty? coll)
76
- nil
77
- (let [[hd & tl] coll]
78
- (cons (f hd) (map f tl))))))
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
- class << Rouge
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 Rouge[:"rouge.builtin"]
37
+ core.refer builtin
36
38
 
37
39
  user = Rouge[:user]
38
- user.refer Rouge[:"rouge.builtin"]
39
- user.refer Rouge[:"rouge.core"]
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
- s = self.next
26
- if s.nil?
43
+ nseq = self.next
44
+ if nseq.nil?
27
45
  Empty
28
46
  else
29
- s
47
+ nseq
30
48
  end
31
49
  end
32
50
 
33
- def cons(o)
34
- Cons.new(o, self)
51
+ def cons(head)
52
+ Cons.new(head, self)
35
53
  end
36
54
 
37
55
  def length
38
- l = 0
56
+ len = 0
39
57
  cursor = self
40
58
 
41
59
  while cursor != Empty
42
- l += 1
60
+ len += 1
43
61
  cursor = cursor.more
44
62
  end
45
63
 
46
- l
64
+ len
47
65
  end
48
66
 
49
67
  alias count length
50
68
 
51
- def [](i)
52
- return to_a[i] if i.is_a? Range
69
+ def [](idx)
70
+ return to_a[idx] if idx.is_a? Range
53
71
 
54
72
  cursor = self
55
73
 
56
- i += self.length if i < 0
74
+ idx += self.length if idx < 0
57
75
 
58
- while i > 0
59
- i -= 1
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
- (seq.is_a?(ISeq) and self.to_a == seq.to_a) or
69
- (seq.is_a?(::Array) and self.to_a == seq)
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
- r = []
90
- self.each {|e| r << block.call(e)}
91
- r
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
- return Empty if elements.length.zero?
159
+ length = elements.length
160
+ return Empty if length.zero?
139
161
 
140
162
  head = nil
141
- (elements.length - 1).downto(0).each do |i|
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, i)
155
- @array, @i = array, i
177
+ def initialize(array, idx)
178
+ @array, @idx = array, idx
156
179
  end
157
180
 
158
181
  def first
159
- @array[@i]
182
+ @array[@idx]
160
183
  end
161
184
 
162
185
  def next
163
- if @i + 1 < @array.length
164
- Array.new(@array, @i + 1)
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
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Rouge
4
- VERSION = "0.0.4"
4
+ VERSION = "0.0.5"
5
5
  end
6
6
 
7
7
  # vim: set sw=2 et cc=80:
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
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-03 00:00:00.000000000 Z
12
+ date: 2012-12-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake