rouge-lang 0.0.6 → 0.0.7

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