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 +1 -0
- data/lib/rouge.rb +1 -0
- data/lib/rouge/compiler.rb +19 -0
- data/lib/rouge/context.rb +12 -0
- data/lib/rouge/namespace.rb +5 -0
- data/lib/rouge/printer.rb +7 -0
- data/lib/rouge/reader.rb +30 -13
- data/lib/rouge/seq.rb +4 -0
- data/lib/rouge/version.rb +1 -1
- data/misc/TODO +4 -7
- data/spec/compiler_spec.rb +99 -94
- data/spec/namespace_spec.rb +1 -1
- data/spec/reader_spec.rb +26 -0
- data/spec/seq_spec.rb +25 -1
- metadata +9 -3
data/bin/rouge
CHANGED
data/lib/rouge.rb
CHANGED
data/lib/rouge/compiler.rb
CHANGED
@@ -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
|
data/lib/rouge/namespace.rb
CHANGED
@@ -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
|
-
|
251
|
-
|
249
|
+
expression = ""
|
250
|
+
terminator = '"'
|
251
|
+
|
252
252
|
while true
|
253
|
-
|
253
|
+
char = @src[@n]
|
254
254
|
|
255
|
-
if
|
256
|
-
reader_raise EndOfDataError, "in regexp, got: #{
|
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
|
261
|
+
if char == terminator
|
262
262
|
break
|
263
263
|
end
|
264
264
|
|
265
|
-
if
|
266
|
-
|
267
|
-
|
268
|
-
|
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
|
-
|
274
|
+
expression << char
|
273
275
|
end
|
274
276
|
|
275
|
-
Regexp.new(
|
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
data/lib/rouge/version.rb
CHANGED
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
|
data/spec/compiler_spec.rb
CHANGED
@@ -3,134 +3,139 @@ require 'spec_helper'
|
|
3
3
|
require 'rouge'
|
4
4
|
|
5
5
|
describe Rouge::Compiler do
|
6
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
8
|
+
let(:read) { lambda {|input|
|
9
|
+
Rouge::Reader.new(ns, input).lex
|
10
|
+
} }
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
51
|
-
|
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
|
-
|
55
|
-
|
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
|
61
|
-
x = double("
|
51
|
+
it do
|
52
|
+
x = double("class")
|
62
53
|
x.stub(:new => nil)
|
63
54
|
|
64
|
-
|
65
|
-
x_new =
|
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
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
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
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
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
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
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
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
129
|
-
|
130
|
-
|
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 {
|
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
|
|
data/spec/namespace_spec.rb
CHANGED
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.
|
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
|
+
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.
|
203
|
+
rubygems_version: 1.8.24
|
198
204
|
signing_key:
|
199
205
|
specification_version: 3
|
200
206
|
summary: An implementation of Clojure for Ruby.
|