rouge-lang 0.0.4 → 0.0.5

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