rouge-lang 0.0.7 → 0.0.8

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/.gitignore CHANGED
@@ -18,3 +18,4 @@ test/tmp
18
18
  test/version_tmp
19
19
  tmp
20
20
  .rvmrc
21
+ *.swp
data/bin/rouge CHANGED
@@ -4,25 +4,37 @@ $: << "#{File.dirname(__FILE__)}/../lib"
4
4
  require 'rouge'
5
5
  require 'optparse'
6
6
 
7
+ # Boots Rouge and evaluates code in a new context. Prints non-nil results if
8
+ # print is true.
9
+ def evaluate(code, print = false)
10
+ Rouge.boot!
11
+ res = Rouge::Context.new(Rouge[:user]).readeval(code)
12
+
13
+ if print && res
14
+ puts Rouge.print(res, '')
15
+ end
16
+ end
17
+
7
18
  options = {:backtrace => true}
8
19
 
9
20
  option_parser = OptionParser.new do |opts|
10
- opts.banner = "rouge [switch] [filename]"
21
+ opts.banner = "Usage: rouge [switch] [filename]"
11
22
 
12
23
  opts.on('-v', '--version', 'Print version number') do
13
24
  puts "Rouge #{Rouge::VERSION}"
14
25
  exit 0
15
26
  end
16
27
 
17
- opts.on('-e STR', '--eval STR', 'Evaluate the contents of STR') do |str|
18
- Rouge.boot!
19
- Rouge::Context.new(Rouge[:user]).readeval(str)
28
+ opts.on('-e STR', '--eval STR',
29
+ 'Evaluate expressions in STR; print non-nil results') do |str|
30
+ evaluate(str, true)
20
31
  exit 0
21
32
  end
22
33
 
23
34
  opts.on('--time-startup', 'Report boot up time') do
35
+ start = Time.now
24
36
  Rouge.boot!
25
- puts Time.now - Rouge.start
37
+ puts Time.now - start
26
38
  exit 0
27
39
  end
28
40
 
@@ -37,8 +49,20 @@ rescue OptionParser::MissingArgument => e
37
49
  puts "rouge: #{e}"
38
50
  end
39
51
 
40
- if ARGV.length == 1
41
- file = ARGV[0]
52
+ # Using a standalone '-', which traditionally is the switch for indicating
53
+ # acceptance of standard input, causes some subtle issues with the
54
+ # OptionParser.
55
+ if ARGV.include?('-')
56
+ code = ''
57
+ while line = STDIN.gets
58
+ code << line
59
+ end
60
+ evaluate(code, true)
61
+ exit 0
62
+ end
63
+
64
+ if ARGV.length >= 1
65
+ file = ARGV.shift
42
66
 
43
67
  if File.file?(file)
44
68
  code = File.read(file)
@@ -52,13 +76,8 @@ if ARGV.length == 1
52
76
  code = code[code.index("\n") + 1..-1]
53
77
  end
54
78
 
55
- Rouge.boot!
56
- Rouge::Context.new(Rouge[:user]).readeval(code)
57
-
79
+ evaluate(code)
58
80
  exit 0
59
- elsif ARGV.length > 1
60
- STDERR.puts option_parser.help
61
- exit 1
62
81
  end
63
82
 
64
83
  Rouge.repl(options)
data/lib/rouge.rb CHANGED
@@ -4,11 +4,6 @@ if RUBY_VERSION < "1.9"
4
4
  STDERR.puts "Rouge will probably not run on anything less than Ruby 1.9."
5
5
  end
6
6
 
7
- module Rouge; end
8
-
9
- start = Time.now
10
- Rouge.define_singleton_method :start, lambda {start}
11
-
12
7
  module Rouge
13
8
  require 'rouge/version'
14
9
  require 'rouge/wrappers'
@@ -36,6 +31,7 @@ module Rouge
36
31
 
37
32
  core = Rouge[:"rouge.core"]
38
33
  core.refer builtin
34
+ core.set_here(:"*command-line-args*", ARGV)
39
35
 
40
36
  user = Rouge[:user]
41
37
  user.refer builtin
@@ -245,8 +245,13 @@ class << Rouge::Builtins
245
245
 
246
246
  def ns(context, name, *args)
247
247
  ns = Rouge[name.name]
248
+ ns.refer Rouge[:"ruby"]
248
249
  ns.refer Rouge[:"rouge.builtin"]
249
250
 
251
+ unless name.name == :"rouge.core"
252
+ ns.refer Rouge[:"rouge.core"]
253
+ end
254
+
250
255
  args.each do |arg|
251
256
  kind, *params = arg.to_a
252
257
 
data/lib/rouge/context.rb CHANGED
@@ -67,7 +67,7 @@ class Rouge::Context
67
67
  while true
68
68
  begin
69
69
  form = reader.lex
70
- rescue Rouge::Reader::EndOfDataError
70
+ rescue Rouge::Reader::EOFError
71
71
  return r
72
72
  end
73
73
 
data/lib/rouge/printer.rb CHANGED
@@ -8,6 +8,8 @@ module Rouge::Printer
8
8
  case form
9
9
  when Integer
10
10
  out << form.to_s
11
+ when Rational
12
+ out << "#{form.numerator}/#{form.denominator}"
11
13
  when Rouge::Symbol
12
14
  if form.ns_s
13
15
  out << form.ns_s
data/lib/rouge/reader.rb CHANGED
@@ -3,7 +3,9 @@ require 'rouge/wrappers'
3
3
 
4
4
  class Rouge::Reader
5
5
  class UnexpectedCharacterError < StandardError; end
6
+ class NumberFormatError < StandardError; end
6
7
  class EndOfDataError < StandardError; end
8
+ class EOFError < StandardError; end
7
9
 
8
10
  attr_accessor :ns
9
11
 
@@ -17,54 +19,179 @@ class Rouge::Reader
17
19
  end
18
20
 
19
21
  def lex
20
- r =
21
- case peek
22
- when MAYBE_NUMBER
23
- number
24
- when /:/
25
- keyword
26
- when /"/
27
- string
28
- when /\(/
29
- Rouge::Seq::Cons[*list(')')]
30
- when /\[/
31
- list ']'
32
- when /#/
33
- dispatch
34
- when SYMBOL
35
- # SYMBOL after \[ and #, because it includes both
36
- symbol_or_number
37
- when /{/
38
- map
39
- when /'/
40
- quotation
41
- when /`/
42
- syntaxquotation
43
- when /~/
44
- dequotation
45
- when /\^/
46
- metadata
47
- when /@/
48
- deref
49
- when nil
50
- reader_raise EndOfDataError, "in #lex"
22
+ case peek
23
+ when MAYBE_NUMBER
24
+ number
25
+ when /:/
26
+ keyword
27
+ when /"/
28
+ string
29
+ when /\(/
30
+ Rouge::Seq::Cons[*list(')')]
31
+ when /\[/
32
+ list ']'
33
+ when /#/
34
+ dispatch
35
+ when SYMBOL
36
+ # SYMBOL after \[ and #, because it includes both
37
+ symbol_or_number
38
+ when /{/
39
+ map
40
+ when /'/
41
+ quotation
42
+ when /`/
43
+ syntaxquotation
44
+ when /~/
45
+ dequotation
46
+ when /\^/
47
+ metadata
48
+ when /@/
49
+ deref
50
+ when nil
51
+ reader_raise EOFError, "in #lex"
52
+ else
53
+ reader_raise UnexpectedCharacterError, "#{peek.inspect} in #lex"
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ # Loose expression for a possible numeric literal.
60
+ MAYBE_NUMBER = /^[+\-]?\d[\da-fA-FxX._+\-\/]*/
61
+
62
+ # Ruby integer.
63
+ INT = /\d+(?:_\d+)*/
64
+
65
+ # Strict expression for a numeric literal.
66
+ NUMBER = /
67
+ [+\-]?
68
+ (?:
69
+ (?:#{INT}(?:(?:\.#{INT})?(?:[eE][+\-]?#{INT})?)?) (?# Integers and floats)
70
+ | (?:0
71
+ (?:
72
+ (?:[xX][\da-fA-F]+) (?# Hexadecimal integer)
73
+ | (?:[bB][01]+) (?# Binary integer)
74
+ | (?:[0-7]+) (?# Octal integer)
75
+ )?
76
+ )
77
+ )
78
+ /ox
79
+
80
+ RATIONAL = /#{NUMBER}\/#{NUMBER}/o
81
+
82
+ SYMBOL = /
83
+ ^(\.\[\])
84
+ |(\.?[-+]@)
85
+ |([a-zA-Z0-9\-_!&\?\*\/\.\+\|=%$<>#]+)
86
+ /x
87
+
88
+ # Advances the current character position by n characters and returns the
89
+ # updated character position.
90
+ def advance! n = 1
91
+ @n += n.abs
92
+ end
93
+
94
+ # Retracts the current character position by n characters and returns the
95
+ # updated character position.
96
+ def retract! n = 1
97
+ pos = @n - n.abs
98
+
99
+ if pos > 0
100
+ @n = pos
101
+ else
102
+ @n = 0
103
+ end
104
+ end
105
+
106
+ # Returns the character currently beneath the cursor.
107
+ def current_char
108
+ @src[@n]
109
+ end
110
+
111
+ # Returns the string of characters matching the regular expression re relative
112
+ # to the cursor position. The cursor position is then advanced by n characters
113
+ # where n is the length of the returned string.
114
+ def slurp re
115
+ re.match(@src[@n..-1])
116
+
117
+ if $&
118
+ advance!($&.length)
119
+ $&
120
+ else
121
+ reader_raise UnexpectedCharacterError, "#{current_char} in #slurp #{re}"
122
+ end
123
+ end
124
+
125
+ # Advances the cursor position beyond whitespace and comments and returns the
126
+ # resulting character.
127
+ def peek
128
+ while /[\s,;]/.match(current_char)
129
+ if $& == ";"
130
+ while /[^\n]/.match(current_char)
131
+ advance!
132
+ end
51
133
  else
52
- reader_raise UnexpectedCharacterError, "#{peek.inspect} in #lex"
134
+ advance!
53
135
  end
136
+ end
54
137
 
55
- r
138
+ current_char
56
139
  end
57
140
 
58
- private
141
+ # Returns the result of peek and advances the cursor position by character.
142
+ def consume
143
+ c = peek
144
+ advance!
145
+ c
146
+ end
147
+
148
+ # Raises the exception ex with the message msg including line information
149
+ # where the error occured. If the optional string cause is given, a more
150
+ # detailed report will be displayed.
151
+ def reader_raise ex, msg, cause = nil
152
+ # Locate the beginning of the line.
153
+ n = @n
154
+ until n == 0 || @src[n - 1] == "\n"
155
+ n -= 1
156
+ end
157
+
158
+ lines = @src[n..-1].lines.to_a
159
+ line = lines.first
160
+ line_no = (@src.lines.to_a.index(line) || 0) + 1
59
161
 
60
- def number
61
- read_number(slurp(MAYBE_NUMBER))
162
+ if cause
163
+ error_position = line.index(cause)
164
+ indicator = (" " * error_position) << ("^" * cause.length)
165
+ info = "on line #{line_no} at char #{error_position}"
166
+ parts = [msg, line.chomp, indicator, info]
167
+ else
168
+ info = "on line #{line_no}"
169
+ parts = [msg, info]
170
+ end
171
+
172
+ raise ex, parts.join("\n")
173
+ end
174
+
175
+ def number s = slurp(MAYBE_NUMBER)
176
+ if /\A#{NUMBER}\z/o.match(s)
177
+ # Match decimal numbers but not hexadecimal numbers.
178
+ if /[.eE]/.match(s) && /[^xX]/.match(s)
179
+ Float(s)
180
+ else
181
+ Integer(s)
182
+ end
183
+ elsif /\A#{RATIONAL}\z/o.match(s)
184
+ numerator, denominator = s.split("/").map {|s| number(s) }
185
+ Rational(numerator, denominator)
186
+ else
187
+ reader_raise NumberFormatError, "Invalid number #{s}", s
188
+ end
62
189
  end
63
190
 
64
191
  def keyword
65
192
  begin
66
193
  slurp(/:"/)
67
- @n -= 1
194
+ retract!
68
195
  s = string
69
196
  s.intern
70
197
  rescue UnexpectedCharacterError
@@ -76,13 +203,13 @@ class Rouge::Reader
76
203
  s = ""
77
204
  t = consume
78
205
  while true
79
- c = @src[@n]
206
+ c = current_char
80
207
 
81
208
  if c.nil?
82
- reader_raise EndOfDataError, "in string, got: #{s}"
209
+ reader_raise EndOfDataError, "in string, got: \"#{s}"
83
210
  end
84
211
 
85
- @n += 1
212
+ advance!
86
213
 
87
214
  if c == t
88
215
  break
@@ -93,23 +220,25 @@ class Rouge::Reader
93
220
 
94
221
  case c
95
222
  when nil
96
- reader_raise EndOfDataError, "in escaped string, got: #{s}"
223
+ reader_raise EndOfDataError, "in escaped string, got: \"#{s}"
97
224
  when /[abefnrstv]/
98
- c = {?a => ?\a,
99
- ?b => ?\b,
100
- ?e => ?\e,
101
- ?f => ?\f,
102
- ?n => ?\n,
103
- ?r => ?\r,
104
- ?s => ?\s,
105
- ?t => ?\t,
106
- ?v => ?\v}[c]
225
+ c = {
226
+ ?a => ?\a,
227
+ ?b => ?\b,
228
+ ?e => ?\e,
229
+ ?f => ?\f,
230
+ ?n => ?\n,
231
+ ?r => ?\r,
232
+ ?s => ?\s,
233
+ ?t => ?\t,
234
+ ?v => ?\v
235
+ }[c]
107
236
  else
108
237
  # Just leave it be.
109
238
  end
110
239
  end
111
240
 
112
- s += c
241
+ s << c
113
242
  end
114
243
  s.freeze
115
244
  end
@@ -118,21 +247,21 @@ class Rouge::Reader
118
247
  consume
119
248
  r = []
120
249
 
121
- while true
122
- if peek == ending
123
- break
124
- end
250
+ until peek == ending
125
251
  r << lex
126
252
  end
127
253
 
128
254
  consume
129
255
  r.freeze
256
+ rescue EOFError
257
+ reader_raise EndOfDataError, "in #list"
130
258
  end
131
259
 
132
260
  def symbol_or_number
133
261
  s = slurp(SYMBOL)
134
- if (s[0] == ?- or s[0] == ?+) and s[1..-1] =~ NUMBER
135
- read_number(s)
262
+
263
+ if MAYBE_NUMBER.match(s)
264
+ number(s)
136
265
  else
137
266
  Rouge::Symbol[s.intern]
138
267
  end
@@ -142,22 +271,22 @@ class Rouge::Reader
142
271
  consume
143
272
  r = {}
144
273
 
145
- while true
146
- if peek == '}'
147
- break
148
- end
149
- k = lex
150
- v = lex
274
+ until peek == '}'
275
+ k, v = lex, lex
151
276
  r[k] = v
152
277
  end
153
278
 
154
279
  consume
155
280
  r.freeze
281
+ rescue EOFError
282
+ reader_raise EndOfDataError, "in #map"
156
283
  end
157
284
 
158
285
  def quotation
159
286
  consume
160
287
  Rouge::Seq::Cons[Rouge::Symbol[:quote], lex]
288
+ rescue EOFError
289
+ reader_raise EndOfDataError, "in #quotation"
161
290
  end
162
291
 
163
292
  def syntaxquotation
@@ -166,6 +295,8 @@ class Rouge::Reader
166
295
  r = dequote(lex)
167
296
  @gensyms.shift
168
297
  r
298
+ rescue EOFError
299
+ reader_raise EndOfDataError, "in #syntaxquotation"
169
300
  end
170
301
 
171
302
  def dequotation
@@ -176,6 +307,8 @@ class Rouge::Reader
176
307
  else
177
308
  Rouge::Dequote[lex].freeze
178
309
  end
310
+ rescue EOFError
311
+ reader_raise EndOfDataError, "in #dequotation"
179
312
  end
180
313
 
181
314
  def dequote form
@@ -250,13 +383,13 @@ class Rouge::Reader
250
383
  terminator = '"'
251
384
 
252
385
  while true
253
- char = @src[@n]
386
+ char = current_char
254
387
 
255
388
  if char.nil?
256
389
  reader_raise EndOfDataError, "in regexp, got: #{expression}"
257
390
  end
258
391
 
259
- @n += 1
392
+ advance!
260
393
 
261
394
  if char == terminator
262
395
  break
@@ -281,12 +414,13 @@ class Rouge::Reader
281
414
  s = Set.new
282
415
 
283
416
  until peek == '}'
284
- el = lex
285
- s.add el
417
+ s.add(lex)
286
418
  end
287
419
 
288
420
  consume
289
421
  s.freeze
422
+ rescue EOFError
423
+ reader_raise EndOfDataError, "in #set"
290
424
  end
291
425
 
292
426
  def dispatch
@@ -314,6 +448,8 @@ class Rouge::Reader
314
448
  else
315
449
  reader_raise UnexpectedCharacterError, "#{peek.inspect} in #dispatch"
316
450
  end
451
+ rescue EOFError
452
+ reader_raise EndOfDataError, "in #dispatch"
317
453
  end
318
454
 
319
455
  def dispatch_rewrite_fn form, count
@@ -370,85 +506,16 @@ class Rouge::Reader
370
506
  end
371
507
 
372
508
  attach
509
+ rescue EOFError
510
+ reader_raise EndOfDataError, "in #meta"
373
511
  end
374
512
 
375
513
  def deref
376
514
  consume
377
515
  Rouge::Seq::Cons[Rouge::Symbol[:"rouge.core/deref"], lex]
516
+ rescue EOFError
517
+ reader_raise EndOfDataError, "in #deref"
378
518
  end
379
-
380
- def slurp re
381
- @src[@n..-1] =~ re
382
- reader_raise UnexpectedCharacterError, "#{@src[@n]} in #slurp #{re}" if !$&
383
- @n += $&.length
384
- $&
385
- end
386
-
387
- def peek
388
- while @src[@n] =~ /[\s,;]/
389
- if $& == ";"
390
- while @src[@n] =~ /[^\n]/
391
- @n += 1
392
- end
393
- else
394
- @n += 1
395
- end
396
- end
397
-
398
- @src[@n]
399
- end
400
-
401
- def consume
402
- c = peek
403
- @n += 1
404
- c
405
- end
406
-
407
- def reader_raise ex, m
408
- around =
409
- "#{@src[[@n - 3, 0].max...[@n, 0].max]}" +
410
- "#{@src[@n]}" +
411
- "#{(@src[@n + 1..@n + 3] || "").gsub(/\n.*$/, '')}"
412
-
413
- line = @src[0...@n].count("\n") + 1
414
- char = @src[0...@n].reverse.index("\n") || 0 + 1
415
-
416
- raise ex,
417
- "around: #{around}\n" +
418
- " ^\n" +
419
- "line #{line} char #{char}: #{m}"
420
- end
421
-
422
- def read_number s
423
- if NUMBER.match s
424
- if s =~ /[.eE]/
425
- Float(s)
426
- else
427
- Integer(s)
428
- end
429
- else
430
- reader_raise UnexpectedCharacterError, "#{s} in #read_number"
431
- end
432
- end
433
-
434
- # Loose expression for a possible numeric literal.
435
- MAYBE_NUMBER = /^[+-]?\d[\da-fA-FxX\._+-]*/
436
-
437
- # Ruby integer.
438
- INT = /\d+(?:_\d+)*/
439
-
440
- # Strict expression for a numeric literal.
441
- NUMBER = /
442
- ^[+-]?
443
- (?:
444
- (?:0[xX][\da-fA-F]+) (?# Hexadecimal integer)
445
- | (?:0[bB][01]+) (?# Binary integer)
446
- | (?:0\d+) (?# Octal integer)
447
- | (?:#{INT}(?:(?:\.#{INT})?(?:[eE][+-]?#{INT})?)?) (?# Integers and floats)
448
- )\z
449
- /ox
450
-
451
- SYMBOL = /^(\.\[\])|(\.?[-+]@)|([a-zA-Z0-9\-_!&\?\*\/\.\+\|=%$<>#]+)/
452
519
  end
453
520
 
454
521
  # vim: set sw=2 et cc=80:
data/lib/rouge/repl.rb CHANGED
@@ -24,7 +24,7 @@ module Rouge::REPL
24
24
  input = Readline.readline(prompt, true)
25
25
  else
26
26
  prompt = "#{" " * [0, context.ns.name.length - 2].max}#_=> "
27
- input += "\n" + Readline.readline(prompt, true)
27
+ input << "\n" + Readline.readline(prompt, true)
28
28
  end
29
29
 
30
30
  if input.nil?
@@ -39,6 +39,8 @@ module Rouge::REPL
39
39
  next
40
40
  rescue Rouge::Reader::UnexpectedCharacterError => reader_err
41
41
  repl_error.call reader_err
42
+ rescue Rouge::Reader::NumberFormatError => reader_err
43
+ repl_error.call reader_err
42
44
  end
43
45
 
44
46
  chaining = false
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.7"
4
+ VERSION = "0.0.8"
5
5
  end
6
6
 
7
7
  # vim: set sw=2 et cc=80:
@@ -154,7 +154,7 @@ describe Rouge::Builtins do
154
154
 
155
155
  describe "storing its own name" do
156
156
  let(:fn) { context.readeval('(fn lmnop [])') }
157
-
157
+
158
158
  it { fn.to_s.should eq :lmnop }
159
159
  end
160
160
 
@@ -251,9 +251,9 @@ describe Rouge::Builtins do
251
251
 
252
252
  describe "evaluating and returning one argument" do
253
253
  let(:subcontext) { Rouge::Context.new context }
254
-
254
+
255
255
  before { subcontext.set_here :x, lambda {4} }
256
-
256
+
257
257
  it { subcontext.readeval('(do (x))').should eq 4 }
258
258
  end
259
259
 
@@ -332,6 +332,12 @@ describe Rouge::Builtins do
332
332
  ROUGE
333
333
  Rouge::Namespace[:y].should be Rouge::Namespace[:moop]
334
334
  end
335
+
336
+ it "should refer rouge.core and ruby" do
337
+ context.readeval "(ns toast)"
338
+ Rouge[:toast].refers.should include(Rouge[:"rouge.core"])
339
+ Rouge[:toast].refers.should include(Rouge[:"ruby"])
340
+ end
335
341
  end
336
342
 
337
343
  it "should compile without compiling any of its components" do
@@ -353,7 +359,7 @@ describe Rouge::Builtins do
353
359
 
354
360
  describe "after readeval (def ...)" do
355
361
  before { context.readeval("(def b 'c)") }
356
-
362
+
357
363
  it { expect { context.readeval("(defmacro a [] b)")
358
364
  }.to_not raise_exception }
359
365
  end
@@ -405,7 +411,7 @@ describe Rouge::Builtins do
405
411
  end
406
412
 
407
413
  it "should compile multi-arg form with names bound" do
408
- # TODO: consider breaking out these two test assertion
414
+ # TODO: consider breaking out these two test assertion
409
415
  # blocks into their own context: they actually both fail
410
416
  # in isolation but those failures are masked because
411
417
  # the "Rouge::Builtins._compile_defmacro" test passes,
@@ -418,13 +424,13 @@ describe Rouge::Builtins do
418
424
  # lexicals.should eq Set[:f]
419
425
  # [:a1]
420
426
  #end
421
- #
427
+ #
422
428
  #Rouge::Compiler.should_receive(:compile).
423
429
  # with(ns, kind_of(Set), [:a2]) do |n, lexicals, f|
424
430
  # lexicals.should eq Set[:g]
425
431
  # [:a2]
426
432
  #end
427
- #
433
+ #
428
434
  Rouge::Builtins._compile_defmacro(
429
435
  ns, Set.new,
430
436
  Rouge::Symbol[:barge],
@@ -443,7 +449,7 @@ describe Rouge::Builtins do
443
449
  describe "apply" do
444
450
  let(:a) { lambda {|*args| args} }
445
451
  let(:subcontext) { Rouge::Context.new context }
446
-
452
+
447
453
  before { subcontext.set_here :a, a }
448
454
 
449
455
  describe "calling a function with the argument list" do
@@ -645,7 +651,7 @@ describe Rouge::Builtins do
645
651
  let(:x) { lambda {} }
646
652
 
647
653
  before { context.set_here :x, x }
648
-
654
+
649
655
  it { context.readeval("(destructure [a | b] [1 | x])").to_s.
650
656
  should eq({Rouge::Symbol[:a] => 1,
651
657
  Rouge::Symbol[:b] => x}.to_s) }
@@ -674,7 +680,7 @@ describe Rouge::Builtins do
674
680
  Rouge::Builtins._compile_destructure(
675
681
  ns, Set.new, Rouge::Symbol[:z], Rouge::Symbol[:z])
676
682
  }.to raise_exception }
677
-
683
+
678
684
  it { expect {
679
685
  Rouge::Builtins._compile_destructure(
680
686
  ns, Set[:y], Rouge::Symbol[:z], Rouge::Symbol[:y])
data/spec/core_spec.rg CHANGED
@@ -151,4 +151,7 @@
151
151
  (swap! q inc) :very_bad)))
152
152
  @q))))
153
153
 
154
+ (testing "*command-line-args*"
155
+ (is (= (class *command-line-args*)
156
+ ruby/Array)))
154
157
  ; vim: set ft=clojure:
data/spec/printer_spec.rb CHANGED
@@ -6,6 +6,7 @@ describe Rouge::Printer do
6
6
  describe ".print" do
7
7
  context "numbers" do
8
8
  it { Rouge.print(12755, "").should eq "12755" }
9
+ it { Rouge.print(Rational(1,2), "").should eq "1/2" }
9
10
  end
10
11
 
11
12
  context "symbols" do
data/spec/reader_spec.rb CHANGED
@@ -39,12 +39,23 @@ describe Rouge::Reader do
39
39
  it { @ns.read("-0333").should eq(-219) }
40
40
  end
41
41
 
42
- context "bad numbers" do
43
- it { expect { @ns.read("1.2.3")
44
- }.to raise_exception Rouge::Reader::UnexpectedCharacterError }
42
+ context "rationals" do
43
+ it { @ns.read("1/2").should be_an_instance_of Rational }
44
+ it { @ns.read("0b1000/0x4").should eq(Rational(2, 1)) }
45
+ end
45
46
 
46
- it { expect { @ns.read("12..")
47
- }.to raise_exception Rouge::Reader::UnexpectedCharacterError }
47
+ context "bad numbers" do
48
+ it {
49
+ expect {
50
+ @ns.read("1.2.3")
51
+ }.to raise_exception Rouge::Reader::NumberFormatError
52
+ }
53
+
54
+ it {
55
+ expect {
56
+ @ns.read("12..")
57
+ }.to raise_exception Rouge::Reader::NumberFormatError
58
+ }
48
59
  end
49
60
  end
50
61
 
@@ -266,10 +277,10 @@ describe Rouge::Reader do
266
277
 
267
278
  describe "empty reads" do
268
279
  it { expect { @ns.read("")
269
- }.to raise_exception(Rouge::Reader::EndOfDataError) }
280
+ }.to raise_exception(Rouge::Reader::EOFError) }
270
281
 
271
282
  it { expect { @ns.read(" \n ")
272
- }.to raise_exception(Rouge::Reader::EndOfDataError) }
283
+ }.to raise_exception(Rouge::Reader::EOFError) }
273
284
  end
274
285
 
275
286
  describe "comments" do
@@ -277,7 +288,7 @@ describe Rouge::Reader do
277
288
  it { @ns.read("[42 ;what!\n15]").should eq [42, 15] }
278
289
 
279
290
  it { expect { @ns.read(";what!")
280
- }.to raise_exception(Rouge::Reader::EndOfDataError) }
291
+ }.to raise_exception(Rouge::Reader::EOFError) }
281
292
 
282
293
  it { @ns.read(";what!\nhmm").should eq Rouge::Symbol[:hmm] }
283
294
  end
@@ -427,8 +438,7 @@ describe Rouge::Reader do
427
438
  r.lex.should eq Rouge::Symbol[:b]
428
439
  r.lex.should eq Rouge::Symbol[:c]
429
440
 
430
- expect { r.lex
431
- }.to raise_exception(Rouge::Reader::EndOfDataError)
441
+ expect { r.lex }.to raise_exception(Rouge::Reader::EOFError)
432
442
  end
433
443
  end
434
444
 
@@ -443,6 +453,23 @@ describe Rouge::Reader do
443
453
  describe "regexp" do
444
454
  it { @ns.read('#"abc"').should be_an_instance_of Regexp }
445
455
  end
456
+
457
+ describe "bad reads" do
458
+ let(:ex) { Rouge::Reader::EndOfDataError }
459
+ it { expect { @ns.read('(') }.to raise_exception(ex) }
460
+ it { expect { @ns.read('{') }.to raise_exception(ex) }
461
+ it { expect { @ns.read('[') }.to raise_exception(ex) }
462
+ it { expect { @ns.read('"') }.to raise_exception(ex) }
463
+ it { expect { @ns.read("'") }.to raise_exception(ex) }
464
+ it { expect { @ns.read('`') }.to raise_exception(ex) }
465
+ it { expect { @ns.read('~') }.to raise_exception(ex) }
466
+ it { expect { @ns.read('@') }.to raise_exception(ex) }
467
+ it { expect { @ns.read('#(') }.to raise_exception(ex) }
468
+ it { expect { @ns.read('#{') }.to raise_exception(ex) }
469
+ it { expect { @ns.read("#'") }.to raise_exception(ex) }
470
+ it { expect { @ns.read("#_") }.to raise_exception(ex) }
471
+ it { expect { @ns.read('#"') }.to raise_exception(ex) }
472
+ end
446
473
  end
447
474
 
448
475
  # vim: set sw=2 et cc=80:
data/spec/rouge_spec.rb CHANGED
@@ -18,6 +18,10 @@ describe Rouge do
18
18
  @ns[:defn].should be_an_instance_of Rouge::Macro
19
19
  }.should_not raise_exception(Rouge::Context::BindingNotFoundError)
20
20
  end
21
+
22
+ it "should contain special variables" do
23
+ @ns[:"*command-line-args*"].should be_an_instance_of Rouge::Var
24
+ end
21
25
  end
22
26
 
23
27
  describe "the user namespace" do
@@ -45,7 +49,7 @@ describe Rouge do
45
49
 
46
50
  total = r[:passed] + r[:failed].length
47
51
 
48
- message =
52
+ message =
49
53
  "#{total} example#{total == 1 ? "" : "s"}, " +
50
54
  "#{r[:failed].length} failure#{r[:failed].length == 1 ? "" : "s"}"
51
55
 
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.7
4
+ version: 0.0.8
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-16 00:00:00.000000000 Z
12
+ date: 2012-12-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -188,7 +188,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
188
188
  version: '0'
189
189
  segments:
190
190
  - 0
191
- hash: -862515277
191
+ hash: 809418637
192
192
  required_rubygems_version: !ruby/object:Gem::Requirement
193
193
  none: false
194
194
  requirements:
@@ -197,7 +197,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
197
197
  version: '0'
198
198
  segments:
199
199
  - 0
200
- hash: -862515277
200
+ hash: 809418637
201
201
  requirements: []
202
202
  rubyforge_project:
203
203
  rubygems_version: 1.8.24