sbyc 0.1.0
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/LICENCE.textile +12 -0
- data/README.textile +44 -0
- data/lib/sbyc.rb +14 -0
- data/lib/sbyc/codetree.rb +82 -0
- data/lib/sbyc/codetree/ast_node.rb +101 -0
- data/lib/sbyc/codetree/eval.rb +3 -0
- data/lib/sbyc/codetree/eval/ast_node_ext.rb +38 -0
- data/lib/sbyc/codetree/eval/functional_eval.rb +36 -0
- data/lib/sbyc/codetree/eval/object_eval.rb +36 -0
- data/lib/sbyc/codetree/matching.rb +3 -0
- data/lib/sbyc/codetree/matching/ast_node_ext.rb +14 -0
- data/lib/sbyc/codetree/matching/match_data.rb +30 -0
- data/lib/sbyc/codetree/matching/matcher.rb +83 -0
- data/lib/sbyc/codetree/proc_parser.rb +91 -0
- data/lib/sbyc/codetree/producing.rb +1 -0
- data/lib/sbyc/codetree/producing/producer.rb +68 -0
- data/lib/sbyc/codetree/rewriting.rb +4 -0
- data/lib/sbyc/codetree/rewriting/class_methods.rb +15 -0
- data/lib/sbyc/codetree/rewriting/compiler.rb +28 -0
- data/lib/sbyc/codetree/rewriting/instance_methods.rb +92 -0
- data/lib/sbyc/codetree/rewriting/match.rb +59 -0
- data/test/spec/documentation/codetree/production.spec +59 -0
- data/test/spec/documentation/readme/assumptions.spec +33 -0
- data/test/spec/documentation/readme/functional_evaluation.spec +29 -0
- data/test/spec/documentation/readme/object_evaluation.spec +17 -0
- data/test/spec/documentation/readme/rewriting.spec +60 -0
- data/test/spec/documentation/readme/semantics.spec +21 -0
- data/test/spec/documentation/readme/synopsis.spec +27 -0
- data/test/spec/documentation/readme/syntax.spec +26 -0
- data/test/spec/spec_helper.rb +13 -0
- data/test/spec/test_all.rb +6 -0
- data/test/spec/unit/sbyc/codetree/ast_node/coerce.spec +60 -0
- data/test/spec/unit/sbyc/codetree/ast_node/equality.spec +75 -0
- data/test/spec/unit/sbyc/codetree/ast_node/inspect.spec +23 -0
- data/test/spec/unit/sbyc/codetree/ast_node/literal.spec +15 -0
- data/test/spec/unit/sbyc/codetree/ast_node/to_a.spec +27 -0
- data/test/spec/unit/sbyc/codetree/ast_node/to_s.spec +23 -0
- data/test/spec/unit/sbyc/codetree/ast_node/visit.spec +34 -0
- data/test/spec/unit/sbyc/codetree/eval/functional_compile.spec +30 -0
- data/test/spec/unit/sbyc/codetree/eval/functional_eval.spec +34 -0
- data/test/spec/unit/sbyc/codetree/eval/functional_proc.spec +36 -0
- data/test/spec/unit/sbyc/codetree/eval/object_compile.spec +36 -0
- data/test/spec/unit/sbyc/codetree/eval/object_eval.spec +38 -0
- data/test/spec/unit/sbyc/codetree/eval/object_proc.spec +36 -0
- data/test/spec/unit/sbyc/codetree/matching/matcher/args_match.spec +91 -0
- data/test/spec/unit/sbyc/codetree/matching/matcher/do_match.spec +39 -0
- data/test/spec/unit/sbyc/codetree/matching/matcher/function_match.spec +45 -0
- data/test/spec/unit/sbyc/codetree/matching/matcher/match.spec +64 -0
- data/test/spec/unit/sbyc/codetree/proc_parser/expr.spec +20 -0
- data/test/spec/unit/sbyc/codetree/proc_parser/parse.spec +83 -0
- data/test/spec/unit/sbyc/codetree/producing/producer.spec +31 -0
- data/test/spec/unit/sbyc/codetree/producing/producer/apply_args_conventions.spec +60 -0
- data/test/spec/unit/sbyc/codetree/rewriting/instance_methods/apply_args_conventions.spec +60 -0
- data/test/spec/unit/sbyc/codetree/rewriting/instance_methods/node.spec +19 -0
- data/test/spec/unit/sbyc/codetree/rewriting/instance_methods/rewrite.spec +76 -0
- data/test/spec/unit/sbyc/codetree/rewriting/match/apply.spec +23 -0
- data/test/spec/unit/sbyc/codetree/rewriting/match/coerce.spec +48 -0
- data/test/spec/unit/sbyc/codetree/rewriting/match/matches.spec +27 -0
- metadata +129 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "README # object-evaluation section" do
|
4
|
+
|
5
|
+
let(:expr){ ::CodeTree::parse{ (display (concat x, y)) } }
|
6
|
+
|
7
|
+
describe('what is said about the ast') do
|
8
|
+
subject{ expr.to_s }
|
9
|
+
it { should == "(display (concat x, y))" }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe("what is said about apply") do
|
13
|
+
let(:receiver) {
|
14
|
+
r = Object.new
|
15
|
+
r.instance_eval <<-EOF
|
16
|
+
def concat(*args)
|
17
|
+
args.join
|
18
|
+
end
|
19
|
+
def display(arg)
|
20
|
+
arg
|
21
|
+
end
|
22
|
+
EOF
|
23
|
+
r
|
24
|
+
}
|
25
|
+
subject{ expr.apply(receiver, :x => 3, :y => 25) }
|
26
|
+
it { should == "325" }
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "README # object-evaluation section" do
|
4
|
+
|
5
|
+
let(:expr){ CodeTree::parse{ (x + y).to_s } }
|
6
|
+
|
7
|
+
describe('what is said about the ast') do
|
8
|
+
subject{ expr.to_s }
|
9
|
+
it { should == "(to_s (+ x, y))" }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe("what is said about eval") do
|
13
|
+
subject{ expr.eval(:x => 3, :y => 25) }
|
14
|
+
it { should == "28" }
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "README # rewriting section" do
|
4
|
+
|
5
|
+
let(:code) { lambda{ (concat "hello ", who, (times "!", 3)) } }
|
6
|
+
let(:ast) { CodeTree::parse(code) }
|
7
|
+
|
8
|
+
describe('What is said about the ast') do
|
9
|
+
subject{ ast.inspect }
|
10
|
+
it { should == '(concat (_ "hello "), (? (_ :who)), (times (_ "!"), (_ 3)))' }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe("What is said about the evaluation") do
|
14
|
+
let(:rewriter) { CodeTree::rewriter {|r|
|
15
|
+
r.rule(:concat) {|r, node, *children| r.apply(children).join("") }
|
16
|
+
r.rule(:capitalize) {|r, node, who| r.apply(who).capitalize }
|
17
|
+
r.rule(:times) {|r, node, who, times| r.apply(who) * r.apply(times) }
|
18
|
+
r.rule(:'?') {|r, node, what| r.scope[r.apply(what)] }
|
19
|
+
r.rule(:'_') {|r, node, literal| literal }
|
20
|
+
}}
|
21
|
+
|
22
|
+
subject { rewriter.rewrite(ast, :who => "You") }
|
23
|
+
|
24
|
+
it { should == "hello You!!!" }
|
25
|
+
end
|
26
|
+
|
27
|
+
describe("What is said about the code generation") do
|
28
|
+
let(:rewriter) { CodeTree::rewriter {|r|
|
29
|
+
r.rule(:concat) {|r, node, *children| r.apply(children).join(" + ") }
|
30
|
+
r.rule(:capitalize) {|r, node, who| "#{r.apply(who)}.capitalize()" }
|
31
|
+
r.rule(:times) {|r, node, who, times| "(#{r.apply(who)} * #{r.apply(times)})" }
|
32
|
+
r.rule(:'?') {|r, node, what| "scope[#{r.apply(what)}]" }
|
33
|
+
r.rule(:'_') {|r, node, literal| literal.inspect }
|
34
|
+
}}
|
35
|
+
|
36
|
+
subject { rewriter.rewrite(ast) }
|
37
|
+
|
38
|
+
it { should == '"hello " + scope[:who] + ("!" * 3)' }
|
39
|
+
end
|
40
|
+
|
41
|
+
describe("What is said about the code tree rewriting") do
|
42
|
+
let(:rewriter) { CodeTree::rewriter {|r|
|
43
|
+
r.rule(:concat) {|r, node, left, right, *residual|
|
44
|
+
rewrited = r.node(:+, r.apply(left), r.apply(right))
|
45
|
+
if residual.empty?
|
46
|
+
rewrited
|
47
|
+
else
|
48
|
+
r.apply(r.node(:concat, [ rewrited ] + residual))
|
49
|
+
end
|
50
|
+
}
|
51
|
+
r.rule(:times) {|r, node, *children| r.node(:*, r.apply(children)) }
|
52
|
+
r.rule(r.ANY) {|r, node, *children| r.node(node.function, children) }
|
53
|
+
}}
|
54
|
+
|
55
|
+
subject { rewriter.rewrite(ast).to_s }
|
56
|
+
|
57
|
+
it { should == '(+ (+ "hello ", who), (* "!", 3))' }
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "README # semantics section" do
|
4
|
+
|
5
|
+
[
|
6
|
+
[ lambda { 12 }, "(_ 12)" ],
|
7
|
+
[ lambda { :x }, "(_ :x)" ],
|
8
|
+
[ lambda { x }, "(? (_ :x))" ]
|
9
|
+
].each do |expr, expected|
|
10
|
+
specify { CodeTree::parse(expr).inspect.should == expected }
|
11
|
+
end
|
12
|
+
|
13
|
+
[
|
14
|
+
[ lambda { x + 12 }, :inspect, "(+ (? (_ :x)), (_ 12))" ],
|
15
|
+
[ lambda { x + 12 }, :to_s, "(+ x, 12)" ],
|
16
|
+
].each do |expr, meth, expected|
|
17
|
+
specify { CodeTree::parse(expr).send(meth).should == expected }
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "README # synopsis section" do
|
4
|
+
|
5
|
+
let(:expr){ CodeTree::expr{ x > y } }
|
6
|
+
|
7
|
+
specify {
|
8
|
+
expr.to_s.should == "(> x, y)"
|
9
|
+
}
|
10
|
+
|
11
|
+
specify {
|
12
|
+
expr.inspect.should == "(> (? (_ :x)), (? (_ :y)))"
|
13
|
+
}
|
14
|
+
|
15
|
+
specify {
|
16
|
+
expr.eval(:x => 5, :y => 2).should == true
|
17
|
+
}
|
18
|
+
|
19
|
+
describe "what is said about marshalling" do
|
20
|
+
let(:marshaled) { Marshal::dump(expr) }
|
21
|
+
let(:unmarshaled) { Marshal::load(marshaled) }
|
22
|
+
subject { unmarshaled }
|
23
|
+
it { should == expr }
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "README # syntax section" do
|
4
|
+
|
5
|
+
describe "what is said about imperative styles" do
|
6
|
+
let(:expected) { "(& (> x, 5), (<= z, 10))" }
|
7
|
+
|
8
|
+
let(:hash_style) { lambda{|t| (t[:x] > 5) & (t[:z] <= 10) } }
|
9
|
+
let(:object_style) { lambda{|t| (t.x > 5) & (t.z <= 10) } }
|
10
|
+
let(:context_style) { lambda{ (x > 5) & (z <= 10) } }
|
11
|
+
let(:tested) { [hash_style, object_style, context_style] }
|
12
|
+
|
13
|
+
subject{ tested.collect{|t| CodeTree::parse(t) } }
|
14
|
+
|
15
|
+
specify{ subject.collect{|c| c.to_s}.uniq.should == [ expected ] }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "what is said about functional style" do
|
19
|
+
let(:functional) { lambda{ (both (gt x, 5), (lte y, 10)) } }
|
20
|
+
|
21
|
+
subject { CodeTree::parse(functional) }
|
22
|
+
|
23
|
+
specify{ subject.to_s.should == "(both (gt x, 5), (lte y, 10))" }
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path('../', __FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'sbyc'
|
6
|
+
require 'spec'
|
7
|
+
require 'spec/autorun'
|
8
|
+
|
9
|
+
# require spec support files
|
10
|
+
Dir[File.expand_path('../support/**/*.spec', __FILE__)].each { |f| require f }
|
11
|
+
|
12
|
+
Spec::Runner.configure do |config|
|
13
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require File.expand_path('../../../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "CodeTree::AstNode#coerce" do
|
4
|
+
|
5
|
+
context("with a literal") do
|
6
|
+
subject { CodeTree::AstNode.coerce(12) }
|
7
|
+
|
8
|
+
it { should be_kind_of(CodeTree::AstNode) }
|
9
|
+
|
10
|
+
specify {
|
11
|
+
subject.literal.should == 12
|
12
|
+
subject.children.should == [ 12 ]
|
13
|
+
subject.to_s.should == "12"
|
14
|
+
subject.inspect.should == "(_ 12)"
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
context("with a literal in array form") do
|
19
|
+
subject { CodeTree::AstNode.coerce([:_, [ 12 ]]) }
|
20
|
+
it { should be_kind_of(CodeTree::AstNode) }
|
21
|
+
specify { subject.inspect.should == "(_ 12)" }
|
22
|
+
end
|
23
|
+
|
24
|
+
context("without children") do
|
25
|
+
subject { CodeTree::AstNode.coerce([:plus, []]) }
|
26
|
+
|
27
|
+
it { should be_kind_of(CodeTree::AstNode) }
|
28
|
+
|
29
|
+
specify {
|
30
|
+
subject.name.should == :plus
|
31
|
+
subject.children.should be_empty
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
context("with literal children") do
|
36
|
+
subject { CodeTree::AstNode.coerce([ :plus, [ 12, 15 ] ]) }
|
37
|
+
|
38
|
+
it { should be_kind_of(CodeTree::AstNode) }
|
39
|
+
|
40
|
+
specify {
|
41
|
+
subject.name.should == :plus
|
42
|
+
subject.children.collect{|a| a.literal}.should == [ 12, 15 ]
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
context("with complex structure") do
|
47
|
+
subject { CodeTree::AstNode.coerce([ :plus, [ [ :minus, [12, 15] ] ] ]) }
|
48
|
+
|
49
|
+
it { should be_kind_of(CodeTree::AstNode) }
|
50
|
+
|
51
|
+
specify {
|
52
|
+
subject.name.should == :plus
|
53
|
+
subject.children.size.should == 1
|
54
|
+
subject.children[0].name.should == :minus
|
55
|
+
subject.children[0].children.should be_kind_of(Array)
|
56
|
+
subject.children[0].children.collect{|a| a.literal}.should == [12, 15]
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require File.expand_path('../../../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "CodeTree::AstNode#==" do
|
4
|
+
|
5
|
+
context "when applied on equal literal nodes" do
|
6
|
+
let(:n1) { CodeTree::parse{ 12 } }
|
7
|
+
let(:n2) { CodeTree::parse{ 12 } }
|
8
|
+
subject { (n1 == n2) and (n2 == n1) }
|
9
|
+
it { should be_true }
|
10
|
+
end
|
11
|
+
|
12
|
+
context "when applied on itself with a literal node" do
|
13
|
+
let(:n1) { CodeTree::parse{ 12 } }
|
14
|
+
let(:n2) { n1 }
|
15
|
+
subject { (n1 == n2) and (n2 == n1) }
|
16
|
+
it { should be_true }
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when applied on non equal literal nodes" do
|
20
|
+
let(:n1) { CodeTree::parse{ 12 } }
|
21
|
+
let(:n2) { CodeTree::parse{ 13 } }
|
22
|
+
subject { (n1 == n2) or (n2 == n1) }
|
23
|
+
it { should be_false }
|
24
|
+
end
|
25
|
+
|
26
|
+
context "when applied on itself with a tree" do
|
27
|
+
let(:n1) { CodeTree::parse{ (concat (say "hello"), "world") } }
|
28
|
+
let(:n2) { n1 }
|
29
|
+
subject { (n1 == n2) and (n2 == n1) }
|
30
|
+
it { should be_true }
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when applied on equal trees" do
|
34
|
+
let(:n1) { CodeTree::parse{ (concat (say "hello"), "world") } }
|
35
|
+
let(:n2) { CodeTree::parse{ (concat (say "hello"), "world") } }
|
36
|
+
subject { (n1 == n2) and (n2 == n1) }
|
37
|
+
it { should be_true }
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when applied on non equal trees (with one being a literal)" do
|
41
|
+
let(:n1) { CodeTree::parse{ (concat (say "hello"), "world") } }
|
42
|
+
let(:n2) { 12 }
|
43
|
+
subject { (n1 == n2) or (n2 == n1) }
|
44
|
+
it { should be_false }
|
45
|
+
end
|
46
|
+
|
47
|
+
context "when applied on non equal trees (none being a literal)" do
|
48
|
+
let(:n1) { CodeTree::parse{ (concat (say "hello"), "world") } }
|
49
|
+
let(:n2) { CodeTree::parse{ (concat "hello", "world") } }
|
50
|
+
subject { (n1 == n2) or (n2 == n1) }
|
51
|
+
it { should be_false }
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when applied on non equal trees (with a literal difference)" do
|
55
|
+
let(:n1) { CodeTree::parse{ (concat (say "hello"), "world") } }
|
56
|
+
let(:n2) { CodeTree::parse{ (concat (say "hello"), "world2") } }
|
57
|
+
subject { (n1 == n2) or (n2 == n1) }
|
58
|
+
it { should be_false }
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when applied on non equal trees (with a function difference)" do
|
62
|
+
let(:n1) { CodeTree::parse{ (concat (say "hello"), "world") } }
|
63
|
+
let(:n2) { CodeTree::parse{ (concat (say2 "hello"), "world") } }
|
64
|
+
subject { (n1 == n2) or (n2 == n1) }
|
65
|
+
it { should be_false }
|
66
|
+
end
|
67
|
+
|
68
|
+
context "when applied on non equal trees (order difference)" do
|
69
|
+
let(:n1) { CodeTree::parse{ (concat (say "hello"), "world") } }
|
70
|
+
let(:n2) { CodeTree::parse{ (concat "world", (say "hello")) } }
|
71
|
+
subject { (n1 == n2) or (n2 == n1) }
|
72
|
+
it { should be_false }
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path('../../../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "CodeTree::AstNode#inspect" do
|
4
|
+
|
5
|
+
subject{ node.inspect }
|
6
|
+
|
7
|
+
context('when called on a leaf node, through coercion') do
|
8
|
+
let(:node) { CodeTree::AstNode.coerce(12) }
|
9
|
+
it { should == "(_ 12)" }
|
10
|
+
end
|
11
|
+
|
12
|
+
context('when called on a ?') do
|
13
|
+
let(:node) { CodeTree::AstNode.coerce([:'?', [:x]]) }
|
14
|
+
it { should == "(? (_ :x))" }
|
15
|
+
end
|
16
|
+
|
17
|
+
context('when called on a object-like expression') do
|
18
|
+
let(:node) { CodeTree::parse{ (say x, "Hello") } }
|
19
|
+
it { subject.should == '(say (? (_ :x)), (_ "Hello"))' }
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.expand_path('../../../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "CodeTree::AstNode#literal" do
|
4
|
+
|
5
|
+
context "when called on a leaf node" do
|
6
|
+
subject{ CodeTree::parse{ 12 }.literal }
|
7
|
+
it { should == 12 }
|
8
|
+
end
|
9
|
+
|
10
|
+
context "when called on a branch node" do
|
11
|
+
subject{ CodeTree::parse{ ~(~(12)) }.literal }
|
12
|
+
it { should == 12 }
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.expand_path('../../../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "CodeTree::AstNode#to_a" do
|
4
|
+
|
5
|
+
context("with a _") do
|
6
|
+
subject { CodeTree::AstNode.coerce(12).to_a }
|
7
|
+
it { should == [:_, [ 12 ]] }
|
8
|
+
end
|
9
|
+
|
10
|
+
context("without children") do
|
11
|
+
subject { CodeTree::AstNode.coerce([ :plus, [ ] ]).to_a }
|
12
|
+
it { should == [ :plus, [ ] ] }
|
13
|
+
end
|
14
|
+
|
15
|
+
context("with _ children") do
|
16
|
+
let(:expected) { [ :plus, [ [:_, [12]], [:_, [15]] ] ] }
|
17
|
+
subject { CodeTree::parse{ (plus 12, 15) }.to_a }
|
18
|
+
it { should == expected }
|
19
|
+
end
|
20
|
+
|
21
|
+
context("with variables") do
|
22
|
+
let(:expected) { [ :plus, [ [:'?', [ [:_, [ :x ] ] ] ] ] ] }
|
23
|
+
subject { CodeTree::parse{ (plus x) }.to_a }
|
24
|
+
it { should == expected }
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path('../../../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "CodeTree::AstNode#inspect" do
|
4
|
+
|
5
|
+
subject{ node.to_s }
|
6
|
+
|
7
|
+
context('when called on a leaf node, through coercion') do
|
8
|
+
let(:node) { CodeTree::AstNode.coerce(12) }
|
9
|
+
it { should == "12" }
|
10
|
+
end
|
11
|
+
|
12
|
+
context('when called on a ?') do
|
13
|
+
let(:node) { CodeTree::AstNode.coerce([:'?', [:x]]) }
|
14
|
+
it { should == "x" }
|
15
|
+
end
|
16
|
+
|
17
|
+
context('when called on a object-like expression') do
|
18
|
+
let(:node) { CodeTree::parse{ (say x, "Hello") } }
|
19
|
+
it { subject.should == '(say x, "Hello")' }
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.expand_path('../../../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "CodeTree::AstNode#functional_eval" do
|
4
|
+
|
5
|
+
context('when called on a leaf node, through coercion') do
|
6
|
+
let(:node) { CodeTree::AstNode.coerce(12) }
|
7
|
+
subject{ node.visit{|node, collected| [node, collected]} }
|
8
|
+
it { should == [node, [12]] }
|
9
|
+
end
|
10
|
+
|
11
|
+
context('when called on a object-like expression') do
|
12
|
+
let(:node) { CodeTree::parse{ (say x, "Hello") } }
|
13
|
+
subject{ node.visit{|node, collected| [node.name, collected]} }
|
14
|
+
it { subject.should == [:say, [ [ :'?', [ [ :_, [ :x ] ] ] ], [ :_, [ "Hello" ] ] ] ] }
|
15
|
+
end
|
16
|
+
|
17
|
+
context('when called for productions') do
|
18
|
+
let(:node) { CodeTree::parse{ (say x, "Hello") } }
|
19
|
+
subject {
|
20
|
+
node.produce{|n, collected|
|
21
|
+
case n.function
|
22
|
+
when :'_'
|
23
|
+
collected.first.inspect
|
24
|
+
when :'?'
|
25
|
+
"scope[#{collected.join(', ')}]"
|
26
|
+
else
|
27
|
+
"#{collected.shift}.#{n.function}(#{collected.join(', ')})"
|
28
|
+
end
|
29
|
+
}
|
30
|
+
}
|
31
|
+
it { should == 'scope[:x].say("Hello")' }
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|