rouge-lang 0.0.7 → 0.0.8

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