rouge-lang 0.0.6 → 0.0.7

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/bin/rouge CHANGED
@@ -11,6 +11,7 @@ option_parser = OptionParser.new do |opts|
11
11
 
12
12
  opts.on('-v', '--version', 'Print version number') do
13
13
  puts "Rouge #{Rouge::VERSION}"
14
+ exit 0
14
15
  end
15
16
 
16
17
  opts.on('-e STR', '--eval STR', 'Evaluate the contents of STR') do |str|
data/lib/rouge.rb CHANGED
@@ -18,6 +18,7 @@ module Rouge
18
18
  require 'rouge/printer'
19
19
  require 'rouge/context'
20
20
  require 'rouge/repl'
21
+ require 'set'
21
22
 
22
23
  def self.print(form, out)
23
24
  Rouge::Printer.print form, out
@@ -24,6 +24,19 @@ module Rouge::Compiler
24
24
  # TODO: cache found ns/var/context or no. of context parents.
25
25
  form
26
26
  else
27
+ if form.ns and !Rouge::Namespace.get(form.ns)
28
+ # ns specified but no actual namespace so-called.
29
+ if form.ns["/"]
30
+ # ns/Const/method ?
31
+ method = form.name
32
+ form = Rouge::Symbol[form.ns]
33
+ else
34
+ # Const/method ?
35
+ method = form.name
36
+ form = Rouge::Symbol[form.ns]
37
+ end
38
+ end
39
+
27
40
  resolved = form.ns ? Rouge[form.ns] : ns
28
41
 
29
42
  lookups = form.name_parts
@@ -42,6 +55,12 @@ module Rouge::Compiler
42
55
  resolved = klass.method(:new)
43
56
  end
44
57
 
58
+ if method
59
+ receiver = resolved
60
+ receiver = receiver.deref if receiver.is_a?(Rouge::Var)
61
+ resolved = receiver.method(method)
62
+ end
63
+
45
64
  Resolved.new resolved
46
65
  end
47
66
  when Array
data/lib/rouge/context.rb CHANGED
@@ -210,6 +210,18 @@ class Rouge::Context
210
210
  raise ArgumentError,
211
211
  "Wrong number of args (#{num_args}) passed to ruby/Hash"
212
212
  end
213
+ when Set
214
+ if num_args == 1
215
+ el = args[0]
216
+ if fun.include? el
217
+ el
218
+ else
219
+ nil
220
+ end
221
+ else
222
+ raise ArgumentError,
223
+ "Wrong number of args (#{num_args}) passed to ruby/Set"
224
+ end
213
225
  else
214
226
  fun.call(*args, &block)
215
227
  end
@@ -28,6 +28,7 @@ class Rouge::Namespace
28
28
  end
29
29
 
30
30
  @refers << ns if not @refers.include? ns
31
+ self
31
32
  end
32
33
 
33
34
  def [](key)
@@ -79,6 +80,10 @@ class << Rouge::Namespace
79
80
  @namespaces[ns] = new(ns)
80
81
  end
81
82
 
83
+ def get(ns)
84
+ @namespaces[ns]
85
+ end
86
+
82
87
  def []=(ns, value)
83
88
  @namespaces[ns] = value
84
89
  end
data/lib/rouge/printer.rb CHANGED
@@ -53,6 +53,13 @@ module Rouge::Printer
53
53
  print(kv[1], out)
54
54
  end
55
55
  out << "}"
56
+ when Set
57
+ out << "\#{"
58
+ form.each_with_index do |el, i|
59
+ print el, out
60
+ out << " " unless i == (form.size - 1)
61
+ end
62
+ out << "}"
56
63
  when NilClass
57
64
  out << "nil"
58
65
  when TrueClass
data/lib/rouge/reader.rb CHANGED
@@ -16,7 +16,6 @@ class Rouge::Reader
16
16
  @gensyms = []
17
17
  end
18
18
 
19
-
20
19
  def lex
21
20
  r =
22
21
  case peek
@@ -247,32 +246,47 @@ class Rouge::Reader
247
246
  end
248
247
 
249
248
  def regexp
250
- s = ""
251
- t = '"'
249
+ expression = ""
250
+ terminator = '"'
251
+
252
252
  while true
253
- c = @src[@n]
253
+ char = @src[@n]
254
254
 
255
- if c.nil?
256
- reader_raise EndOfDataError, "in regexp, got: #{s}"
255
+ if char.nil?
256
+ reader_raise EndOfDataError, "in regexp, got: #{expression}"
257
257
  end
258
258
 
259
259
  @n += 1
260
260
 
261
- if c == t
261
+ if char == terminator
262
262
  break
263
263
  end
264
264
 
265
- if c == ?\\
266
- c = "\\"
267
- if peek == ?"
268
- c << consume
265
+ if char == ?\\
266
+ char = "\\"
267
+
268
+ # Prevent breaking early.
269
+ if peek == terminator
270
+ char << consume
269
271
  end
270
272
  end
271
273
 
272
- s << c
274
+ expression << char
273
275
  end
274
276
 
275
- Regexp.new(s).freeze
277
+ Regexp.new(expression).freeze
278
+ end
279
+
280
+ def set
281
+ s = Set.new
282
+
283
+ until peek == '}'
284
+ el = lex
285
+ s.add el
286
+ end
287
+
288
+ consume
289
+ s.freeze
276
290
  end
277
291
 
278
292
  def dispatch
@@ -284,6 +298,9 @@ class Rouge::Reader
284
298
  Rouge::Symbol[:fn],
285
299
  (1..count).map {|n| Rouge::Symbol[:"%#{n}"]}.freeze,
286
300
  body]
301
+ when "{"
302
+ consume
303
+ set
287
304
  when "'"
288
305
  consume
289
306
  Rouge::Seq::Cons[Rouge::Symbol[:var], lex]
data/lib/rouge/seq.rb CHANGED
@@ -264,6 +264,10 @@ module Rouge::Seq
264
264
  seq(form.to_a)
265
265
  when String
266
266
  seq(form.chars)
267
+ when Set
268
+ seq(form.to_a)
269
+ when Hash
270
+ seq(form.to_a)
267
271
  else
268
272
  raise UnknownSeqError, form.inspect
269
273
  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.6"
4
+ VERSION = "0.0.7"
5
5
  end
6
6
 
7
7
  # vim: set sw=2 et cc=80:
data/misc/TODO CHANGED
@@ -1,8 +1,4 @@
1
1
  NEXT:
2
- - (count "xyz") => 3, (map … "xyz") etc.
3
- - (ruby/)Time/now ==> Time.now
4
- - continue decruft Context, shift tests to Compiler as appropriate; revise most
5
- specs.
6
2
  - extend DESTRUCTURE from LET to FN, etc.
7
3
  - refactor DEFN, DEFMACRO, LET, BINDING(?) to make use of above
8
4
  - may be faster for general wrapper classes to use Struct?
@@ -11,7 +7,6 @@ miscellaeny
11
7
  -----------
12
8
  - MACROEXPAND
13
9
  - SPEED test. run core specs a few times and time.
14
- - everything in ::Rouge should be accessible via rouge.builtin
15
10
  - organise boot.rg
16
11
  - test the whole core
17
12
  - omit Ruby from tracebacks?
@@ -21,20 +16,22 @@ miscellaeny
21
16
  ruby interop
22
17
  ------------
23
18
  - accessing the scope/self (DSLs!)
24
- - proc or lambda? setting ARITY.
19
+ - proc or lambda? setting ARITY. May need to emulate with generated code.
25
20
  - DEFN/DEFMACRO/etc. should create strict lambdas, but FN/#() should not.
26
21
  Emulate by accepting |*a| and selecting ourselves how strict we want to be.
27
22
 
28
23
  "hard" tasks
29
24
  ------------
30
25
  - have a core "apply" function which can be used by eval, defmacro, etc.
26
+ - continue decruft Context, shift tests to Compiler as appropriate; revise most
27
+ specs.
31
28
 
32
29
  core lang
33
30
  ---------
34
31
  - NON-dynamic/special vars
35
32
  - INTERN
36
33
  - FOR
37
- - multi-form defn: (defn x ([a] ...) ([a b] ...))
34
+ - multi-form defn: (defn x ([a] ...) ([a b] ...)) (generalise defmacro's)
38
35
  - atoms (actually multithreaded), refs, agents
39
36
  - rest of the clojure core API (maybe even in clojure.core ns)
40
37
  - clojure-ish IO libraries which expose async IO
@@ -3,134 +3,139 @@ require 'spec_helper'
3
3
  require 'rouge'
4
4
 
5
5
  describe Rouge::Compiler do
6
- before do
7
- @ns = Rouge[:"user.spec"].clear
8
- @ns.refer Rouge[:"rouge.builtin"]
6
+ let(:ns) { Rouge[:"user.spec"].clear.refer(Rouge[:"rouge.builtin"]) }
9
7
 
10
- @read = lambda do |input|
11
- Rouge::Reader.new(@ns, input).lex
12
- end
8
+ let(:read) { lambda {|input|
9
+ Rouge::Reader.new(ns, input).lex
10
+ } }
13
11
 
14
- @compile = lambda do |input|
15
- form = @read.call(input)
16
- Rouge::Compiler.compile(@ns, Set.new, form)
17
- end
18
- end
12
+ let(:compile) { lambda {|input|
13
+ form = read.(input)
14
+ Rouge::Compiler.compile(ns, Set.new, form)
15
+ } }
19
16
 
20
17
  describe "lexical lookup" do
21
- it "should compile with respect to locals" do
22
- lambda {
23
- @compile.call("(fn [] a)")
24
- }.should raise_exception(Rouge::Namespace::VarNotFoundError)
25
-
26
- lambda {
27
- @compile.call("q")
28
- }.should raise_exception(Rouge::Namespace::VarNotFoundError)
29
-
30
- lambda {
31
- @compile.call("(let [x 8] x)").
32
- should eq @read.call("(let [x 8] x)")
33
- }.should_not raise_exception
34
-
35
- lambda {
36
- @compile.call("(let [x 8] y)")
37
- }.should raise_exception(Rouge::Namespace::VarNotFoundError)
38
-
39
- lambda {
40
- @compile.call("(let [x 8] ((fn [& b] (b)) | [e] e))")
41
- }.should_not raise_exception
42
-
43
- lambda {
44
- @compile.call("(let [x 8] ((fn [& b] (b)) | [e] f))")
45
- }.should raise_exception(Rouge::Namespace::VarNotFoundError)
46
- end
18
+ it { expect { compile.("(fn [] a)")
19
+ }.to raise_exception(Rouge::Namespace::VarNotFoundError) }
20
+
21
+ it { expect { compile.("q")
22
+ }.to raise_exception(Rouge::Namespace::VarNotFoundError) }
23
+
24
+ it { expect { compile.("(let [x 8] x)").should eq read.("(let [x 8] x)")
25
+ }.to_not raise_exception }
26
+
27
+ it { expect { compile.("(let [x 8] y)")
28
+ }.to raise_exception(Rouge::Namespace::VarNotFoundError) }
29
+
30
+ it { expect { compile.("(let [x 8] ((fn [& b] (b)) | [e] e))")
31
+ }.to_not raise_exception }
32
+
33
+ it { expect { compile.("(let [x 8] ((fn [& b] (b)) | [e] f))")
34
+ }.to raise_exception(Rouge::Namespace::VarNotFoundError) }
47
35
  end
48
36
 
49
37
  describe "macro behaviour" do
50
- it "should execute macro calls when compiling" do
51
- @ns.set_here :thingy, Rouge::Macro[lambda {|f|
38
+ before do
39
+ ns.set_here(:thingy, Rouge::Macro[lambda {|f|
52
40
  Rouge::Seq::Cons[Rouge::Symbol[:list], *f.to_a]
53
- }]
54
- @compile.call("(let [list 'thing] (thingy (1 2 3)))").
55
- should eq @read.call("(let [list 'thing] (list 1 2 3))")
41
+ }])
42
+ end
43
+
44
+ it do
45
+ compile.("(let [list 'thing] (thingy (1 2 3)))").
46
+ should eq read.("(let [list 'thing] (list 1 2 3))")
56
47
  end
57
48
  end
58
49
 
59
50
  describe "symbol lookup" do
60
- it "should compile X. symbols to procs which call X.new" do
61
- x = double("<class>")
51
+ it do
52
+ x = double("class")
62
53
  x.stub(:new => nil)
63
54
 
64
- @ns.set_here :x, x
65
- x_new = @compile.call("x.")
55
+ ns.set_here(:x, x)
56
+ x_new = compile.("x.")
66
57
  x_new.should be_an_instance_of Rouge::Compiler::Resolved
67
58
 
68
59
  x.should_receive(:new).with(1, :z)
69
60
  x_new.res.call(1, :z)
70
61
  end
71
62
 
72
- it "should find the var in our namespace for an unqualified symbol" do
73
- @ns.set_here :tiffany, "wha?"
74
- @compile.call("tiffany").res.
75
- should eq Rouge::Var.new(:"user.spec", :tiffany, "wha?")
63
+ context "var in context ns" do
64
+ before { ns.set_here(:tiffany, "wha?") }
65
+ it { compile.("tiffany").res.
66
+ should eq Rouge::Var.new(:"user.spec", :tiffany, "wha?") }
67
+ end
68
+
69
+ context "vars in referred ns" do
70
+ subject { compile.("def").res }
71
+ it { should be_an_instance_of Rouge::Var }
72
+ its(:ns) { should eq :"rouge.builtin" }
73
+ its(:name) { should eq :def }
74
+ its(:deref) { should be_an_instance_of(Rouge::Builtin) }
76
75
  end
77
76
 
78
- it "should find the var in a referred ns for an unqualified symbol" do
79
- v = @compile.call("def").res
80
- v.should be_an_instance_of(Rouge::Var)
81
- v.ns.should eq :"rouge.builtin"
82
- v.name.should eq :def
83
- v.deref.should be_an_instance_of(Rouge::Builtin)
77
+ context "var in qualified ns" do
78
+ subject { compile.("ruby/Kernel").res }
79
+ it { should be_an_instance_of Rouge::Var }
80
+ its(:ns) { should eq :ruby }
81
+ its(:name) { should eq :Kernel }
82
+ its(:deref) { should eq Kernel }
84
83
  end
85
84
 
86
- it "should find the var in any namespace for a qualified symbol" do
87
- v = @compile.call("ruby/Kernel").res
88
- v.should be_an_instance_of(Rouge::Var)
89
- v.ns.should eq :ruby
90
- v.name.should eq :Kernel
91
- v.deref.should eq Kernel
85
+ context "class instantiation" do
86
+ subject { compile.("ruby/String.").res }
87
+ it { should be_an_instance_of Method }
88
+ its(:receiver) { should eq String }
89
+ its(:name) { should eq :new }
92
90
  end
93
91
 
94
- it "should find the method for a new class instantiation" do
95
- m = @compile.call("ruby/String.").res
96
- m.should be_an_instance_of Method
97
- m.receiver.should eq String
98
- m.name.should eq :new
92
+ context "static method lookup" do
93
+ context "implied ns" do
94
+ before { ns.set_here(:String, String) }
95
+ subject { compile.("String/new").res }
96
+ it { should be_an_instance_of Method }
97
+ its(:receiver) { should eq String }
98
+ its(:name) { should eq :new }
99
+ end
100
+
101
+ context "fully-qualified" do
102
+ subject { compile.("ruby/String/new").res }
103
+ it { should be_an_instance_of Method }
104
+ its(:receiver) { should eq String }
105
+ its(:name) { should eq :new }
106
+ end
99
107
  end
100
108
  end
101
109
 
102
110
  describe "sub-compilation behaviour" do
103
- it "should compile Arrays and Hashes" do
104
- lambda {
105
- @compile.call("[a]")
106
- }.should raise_exception(Rouge::Namespace::VarNotFoundError)
107
-
108
- @ns.set_here :a, :a
109
- lambda {
110
- @compile.call("[a]")
111
- }.should_not raise_exception
112
-
113
- lambda {
114
- @compile.call("{b c}")
115
- }.should raise_exception(Rouge::Namespace::VarNotFoundError)
116
-
117
- @ns.set_here :b, :b
118
- lambda {
119
- @compile.call("{b c}")
120
- }.should raise_exception(Rouge::Namespace::VarNotFoundError)
121
-
122
- @ns.set_here :c, :c
123
- lambda {
124
- @compile.call("{b c}")
125
- }.should_not raise_exception
111
+ it { expect { compile.("[a]")
112
+ }.to raise_exception(Rouge::Namespace::VarNotFoundError) }
113
+
114
+ context do
115
+ before { ns.set_here(:a, :a) }
116
+ it { expect { compile.("[a]")
117
+ }.to_not raise_exception }
126
118
  end
127
119
 
128
- it "should compile inline blocks to fns" do
129
- @compile.call("(let [a 'thing] (a | [b] b))").
130
- should eq @read.call("(let [a 'thing] (a | (fn [b] b)))")
120
+ it { expect { compile.("{b c}")
121
+ }.to raise_exception(Rouge::Namespace::VarNotFoundError) }
122
+
123
+ context do
124
+ before { ns.set_here(:b, :b) }
125
+ it { expect { compile.("{b c}")
126
+ }.to raise_exception(Rouge::Namespace::VarNotFoundError) }
127
+
128
+ context do
129
+ before { ns.set_here(:c, :c) }
130
+ it { expect { compile.("{b c}")
131
+ }.to_not raise_exception }
132
+ end
131
133
  end
132
134
 
133
- it { @compile.call("()").should eq Rouge::Seq::Empty }
135
+ it { compile.("(let [a 'thing] (a | [b] b))").
136
+ should eq read.("(let [a 'thing] (a | (fn [b] b)))") }
137
+
138
+ it { compile.("()").should eq Rouge::Seq::Empty }
134
139
  end
135
140
  end
136
141
 
@@ -46,7 +46,7 @@ describe Rouge::Namespace do
46
46
  abc = Rouge::Namespace.new :abc
47
47
  xyz = Rouge::Namespace.new :xyz
48
48
 
49
- xyz.refer abc
49
+ xyz.refer(abc).should be xyz
50
50
 
51
51
  abc.set_here :hello, :wow
52
52
  xyz[:hello].deref.should eq :wow
data/spec/reader_spec.rb CHANGED
@@ -175,6 +175,32 @@ describe Rouge::Reader do
175
175
  end
176
176
  end
177
177
 
178
+ describe "sets" do
179
+ context "the empty set" do
180
+ it { @ns.read('#{}').should eq Set.new }
181
+ end
182
+
183
+ context "multiple-element sets" do
184
+ it { @ns.read('#{1 2 3}').should eq Set.new.add(1).add(2).add(3) }
185
+ it { @ns.read('#{true () [] "no"}').
186
+ should eq Set.new([Rouge::Symbol[:true],
187
+ Rouge::Seq::Cons[],
188
+ [],
189
+ "no"]) }
190
+ end
191
+
192
+ context "nested sets" do
193
+ it { @ns.read('#{#{1} #{2} #{3}}').
194
+ should eq Set.new([Set.new([1]), Set.new([2]), Set.new([3])]) }
195
+ end
196
+
197
+ context "read as frozen" do
198
+ it { @ns.read('#{}').should be_frozen }
199
+ it { @ns.read('#{1}').should be_frozen }
200
+ it { @ns.read('#{1 2}').should be_frozen }
201
+ end
202
+ end
203
+
178
204
  describe "quotations" do
179
205
  it { @ns.read("'x").
180
206
  should eq Rouge::Seq::Cons[Rouge::Symbol[:quote],
data/spec/seq_spec.rb CHANGED
@@ -13,7 +13,7 @@ describe Rouge::Seq::ASeq do
13
13
  describe "#seq" do
14
14
  it "should return the original object" do
15
15
  seq.seq.should be seq
16
- end
16
+ end
17
17
  end
18
18
 
19
19
  describe "the unimplemented methods" do
@@ -196,6 +196,30 @@ describe Rouge::Seq do
196
196
  let(:arrayseq) { Rouge::Seq::Array.new([:a], 0) }
197
197
  it { Rouge::Seq.seq(arrayseq).should be arrayseq }
198
198
  end
199
+
200
+ context Set do
201
+ subject { Rouge::Seq.seq(Set.new([1, 2, 3])) }
202
+ it { should be_an_instance_of Rouge::Seq::Array }
203
+ it { should eq Rouge::Seq::Array.new([1, 2, 3], 0) }
204
+ end
205
+
206
+ context Hash do
207
+ subject { Rouge::Seq.seq({:a => "a", :b => "b"}) }
208
+ it { should be_an_instance_of Rouge::Seq::Array }
209
+ it { should eq Rouge::Seq::Array.new([[:a, "a"], [:b, "b"]], 0) }
210
+ end
211
+
212
+ context String do
213
+ subject { Rouge::Seq.seq("foo") }
214
+ it { should be_an_instance_of Rouge::Seq::Array }
215
+ it { should eq Rouge::Seq::Array.new(['f', 'o', 'o'], 0) }
216
+ end
217
+
218
+ context Enumerator do
219
+ subject { Rouge::Seq.seq(1.upto(3)) }
220
+ it { should be_an_instance_of Rouge::Seq::Array }
221
+ it { should eq Rouge::Seq::Array.new([1, 2, 3], 0) }
222
+ end
199
223
  end
200
224
  end
201
225
 
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.6
4
+ version: 0.0.7
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 00:00:00.000000000 Z
12
+ date: 2012-12-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -186,15 +186,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
186
186
  - - ! '>='
187
187
  - !ruby/object:Gem::Version
188
188
  version: '0'
189
+ segments:
190
+ - 0
191
+ hash: -862515277
189
192
  required_rubygems_version: !ruby/object:Gem::Requirement
190
193
  none: false
191
194
  requirements:
192
195
  - - ! '>='
193
196
  - !ruby/object:Gem::Version
194
197
  version: '0'
198
+ segments:
199
+ - 0
200
+ hash: -862515277
195
201
  requirements: []
196
202
  rubyforge_project:
197
- rubygems_version: 1.8.23
203
+ rubygems_version: 1.8.24
198
204
  signing_key:
199
205
  specification_version: 3
200
206
  summary: An implementation of Clojure for Ruby.