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