rltk3 3.0.2
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.
- checksums.yaml +7 -0
- data/AUTHORS +1 -0
- data/LICENSE +27 -0
- data/README.md +852 -0
- data/Rakefile +197 -0
- data/lib/rltk/ast.rb +573 -0
- data/lib/rltk/cfg.rb +683 -0
- data/lib/rltk/cg/basic_block.rb +157 -0
- data/lib/rltk/cg/bindings.rb +151 -0
- data/lib/rltk/cg/builder.rb +1127 -0
- data/lib/rltk/cg/context.rb +48 -0
- data/lib/rltk/cg/contractor.rb +51 -0
- data/lib/rltk/cg/execution_engine.rb +194 -0
- data/lib/rltk/cg/function.rb +237 -0
- data/lib/rltk/cg/generated_bindings.rb +8118 -0
- data/lib/rltk/cg/generic_value.rb +95 -0
- data/lib/rltk/cg/instruction.rb +519 -0
- data/lib/rltk/cg/llvm.rb +150 -0
- data/lib/rltk/cg/memory_buffer.rb +75 -0
- data/lib/rltk/cg/module.rb +451 -0
- data/lib/rltk/cg/pass_manager.rb +252 -0
- data/lib/rltk/cg/support.rb +29 -0
- data/lib/rltk/cg/target.rb +230 -0
- data/lib/rltk/cg/triple.rb +58 -0
- data/lib/rltk/cg/type.rb +554 -0
- data/lib/rltk/cg/value.rb +1272 -0
- data/lib/rltk/cg.rb +32 -0
- data/lib/rltk/lexer.rb +372 -0
- data/lib/rltk/lexers/calculator.rb +44 -0
- data/lib/rltk/lexers/ebnf.rb +38 -0
- data/lib/rltk/parser.rb +1702 -0
- data/lib/rltk/parsers/infix_calc.rb +43 -0
- data/lib/rltk/parsers/postfix_calc.rb +34 -0
- data/lib/rltk/parsers/prefix_calc.rb +34 -0
- data/lib/rltk/token.rb +90 -0
- data/lib/rltk/version.rb +11 -0
- data/lib/rltk.rb +16 -0
- data/test/cg/tc_basic_block.rb +83 -0
- data/test/cg/tc_control_flow.rb +191 -0
- data/test/cg/tc_function.rb +54 -0
- data/test/cg/tc_generic_value.rb +33 -0
- data/test/cg/tc_instruction.rb +256 -0
- data/test/cg/tc_llvm.rb +25 -0
- data/test/cg/tc_math.rb +88 -0
- data/test/cg/tc_module.rb +89 -0
- data/test/cg/tc_transforms.rb +68 -0
- data/test/cg/tc_type.rb +69 -0
- data/test/cg/tc_value.rb +151 -0
- data/test/cg/ts_cg.rb +23 -0
- data/test/tc_ast.rb +332 -0
- data/test/tc_cfg.rb +164 -0
- data/test/tc_lexer.rb +216 -0
- data/test/tc_parser.rb +711 -0
- data/test/tc_token.rb +34 -0
- data/test/ts_rltk.rb +47 -0
- metadata +317 -0
data/test/cg/tc_value.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
# Author: Chris Wailes <chris.wailes@gmail.com>
|
2
|
+
# Project: Ruby Language Toolkit
|
3
|
+
# Date: 2012/05/09
|
4
|
+
# Description: This file contains unit tests for the RLTK::CG::Value class and
|
5
|
+
# its subclasses.
|
6
|
+
|
7
|
+
############
|
8
|
+
# Requires #
|
9
|
+
############
|
10
|
+
|
11
|
+
# Gems
|
12
|
+
require 'minitest/autorun'
|
13
|
+
|
14
|
+
# Ruby Language Toolkit
|
15
|
+
require 'rltk/cg/llvm'
|
16
|
+
require 'rltk/cg/module'
|
17
|
+
require 'rltk/cg/execution_engine'
|
18
|
+
require 'rltk/cg/type'
|
19
|
+
require 'rltk/cg/value'
|
20
|
+
|
21
|
+
class ValueTester < Minitest::Test
|
22
|
+
def setup
|
23
|
+
RLTK::CG::LLVM.init(:X86)
|
24
|
+
|
25
|
+
@mod = RLTK::CG::Module.new('Testing Module')
|
26
|
+
@jit = RLTK::CG::JITCompiler.new(@mod)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_array_values
|
30
|
+
fun = @mod.functions.add('array_function_tester', RLTK::CG::NativeIntType,
|
31
|
+
[RLTK::CG::NativeIntType, RLTK::CG::NativeIntType]) do |fun|
|
32
|
+
|
33
|
+
blocks.append do
|
34
|
+
ptr = alloca(RLTK::CG::ArrayType.new(RLTK::CG::NativeIntType, 2))
|
35
|
+
|
36
|
+
array = load(ptr)
|
37
|
+
array = insert_value(array, fun.params[0], 0)
|
38
|
+
array = insert_value(array, fun.params[1], 1)
|
39
|
+
|
40
|
+
ret(add(extract_value(array, 0), extract_value(array, 1)))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
assert_equal(5, @jit.run_function(fun, 2, 3).to_i)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_constant_array_from_array
|
48
|
+
array = RLTK::CG::ConstantArray.new(RLTK::CG::NativeIntType, [RLTK::CG::NativeInt.new(0), RLTK::CG::NativeInt.new(1)])
|
49
|
+
|
50
|
+
assert_instance_of(RLTK::CG::ConstantArray, array)
|
51
|
+
assert_equal(2, array.length)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_constant_array_from_size
|
55
|
+
array = RLTK::CG::ConstantArray.new(RLTK::CG::NativeIntType, 2) { |i| RLTK::CG::NativeInt.new(i) }
|
56
|
+
|
57
|
+
assert_instance_of(RLTK::CG::ConstantArray, array)
|
58
|
+
assert_equal(2, array.length)
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_constant_vector_elements
|
62
|
+
fun = @mod.functions.add('constant_vector_elements_tester', RLTK::CG::NativeIntType,
|
63
|
+
[RLTK::CG::NativeIntType, RLTK::CG::NativeIntType]) do |fun|
|
64
|
+
|
65
|
+
blocks.append do
|
66
|
+
ptr = alloca(RLTK::CG::VectorType.new(RLTK::CG::NativeIntType, 2))
|
67
|
+
|
68
|
+
vector = load(ptr)
|
69
|
+
vector = insert_element(vector, fun.params[0], RLTK::CG::NativeInt.new(0))
|
70
|
+
vector = insert_element(vector, fun.params[1], RLTK::CG::NativeInt.new(1))
|
71
|
+
|
72
|
+
ret(add(extract_element(vector, RLTK::CG::NativeInt.new(0)), extract_element(vector, RLTK::CG::NativeInt.new(1))))
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
assert_equal(5, @jit.run_function(fun, 2, 3).to_i)
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_constant_vector_from_array
|
80
|
+
vector = RLTK::CG::ConstantVector.new([RLTK::CG::NativeInt.new(0), RLTK::CG::NativeInt.new(1)])
|
81
|
+
|
82
|
+
assert_instance_of(RLTK::CG::ConstantVector, vector)
|
83
|
+
assert_equal(2, vector.size)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_constant_vector_from_size
|
87
|
+
vector = RLTK::CG::ConstantVector.new(2) { |i| RLTK::CG::NativeInt.new(i) }
|
88
|
+
|
89
|
+
assert_instance_of(RLTK::CG::ConstantVector, vector)
|
90
|
+
assert_equal(2, vector.size)
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_constant_vector_shuffle
|
94
|
+
fun = @mod.functions.add('constant_vector_shuffle_tester', RLTK::CG::NativeIntType, Array.new(4, RLTK::CG::NativeIntType)) do |fun|
|
95
|
+
blocks.append do
|
96
|
+
vec_type = RLTK::CG::VectorType.new(RLTK::CG::NativeIntType, 2)
|
97
|
+
|
98
|
+
v0 = load(alloca(vec_type))
|
99
|
+
v0 = insert_element(v0, fun.params[0], RLTK::CG::NativeInt.new(0))
|
100
|
+
v0 = insert_element(v0, fun.params[1], RLTK::CG::NativeInt.new(1))
|
101
|
+
|
102
|
+
v1 = load(alloca(vec_type))
|
103
|
+
v1 = insert_element(v1, fun.params[2], RLTK::CG::NativeInt.new(0))
|
104
|
+
v1 = insert_element(v1, fun.params[3], RLTK::CG::NativeInt.new(1))
|
105
|
+
|
106
|
+
v2 = shuffle_vector(v0, v1, RLTK::CG::ConstantVector.new([RLTK::CG::NativeInt.new(0), RLTK::CG::NativeInt.new(3)]))
|
107
|
+
|
108
|
+
ret(add(extract_element(v2, RLTK::CG::NativeInt.new(0)), extract_element(v2, RLTK::CG::NativeInt.new(1))))
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
assert_equal(5, @jit.run_function(fun, 1, 2, 3, 4).to_i)
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_constant_struct_from_size_packed
|
116
|
+
struct = RLTK::CG::ConstantStruct.new(2, true) { |i| RLTK::CG::NativeInt.new(i) }
|
117
|
+
|
118
|
+
assert_instance_of(RLTK::CG::ConstantStruct, struct)
|
119
|
+
assert_equal(2, struct.operands.size)
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_constant_struct_from_size_unpacked
|
123
|
+
struct = RLTK::CG::ConstantStruct.new(2, false) { |i| RLTK::CG::NativeInt.new(i) }
|
124
|
+
|
125
|
+
assert_instance_of(RLTK::CG::ConstantStruct, struct)
|
126
|
+
assert_equal(2, struct.operands.size)
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_constant_struct_from_values_packed
|
130
|
+
struct = RLTK::CG::ConstantStruct.new([RLTK::CG::NativeInt.new(0), RLTK::CG::NativeInt.new(1)], true)
|
131
|
+
|
132
|
+
assert_instance_of(RLTK::CG::ConstantStruct, struct)
|
133
|
+
assert_equal(2, struct.operands.size)
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_constant_struct_from_values_unpacked
|
137
|
+
struct = RLTK::CG::ConstantStruct.new([RLTK::CG::NativeInt.new(0), RLTK::CG::NativeInt.new(1)], false)
|
138
|
+
|
139
|
+
assert_instance_of(RLTK::CG::ConstantStruct, struct)
|
140
|
+
assert_equal(2, struct.operands.size)
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_equality
|
144
|
+
v0 = RLTK::CG::NativeInt.new(0)
|
145
|
+
v1 = RLTK::CG::NativeInt.new(1)
|
146
|
+
v2 = RLTK::CG::NativeInt.new(v0.ptr)
|
147
|
+
|
148
|
+
assert_equal(v0, v2)
|
149
|
+
refute_equal(v0, v1)
|
150
|
+
end
|
151
|
+
end
|
data/test/cg/ts_cg.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Author: Chris Wailes <chris.wailes@gmail.com>
|
2
|
+
# Project: Ruby Language Toolkit
|
3
|
+
# Date: 2012/05/04
|
4
|
+
# Description: This file contains test suit for the RLTK LLVM bindigns. It
|
5
|
+
# requires the individual tests from their respective files.
|
6
|
+
|
7
|
+
############
|
8
|
+
# Requires #
|
9
|
+
############
|
10
|
+
|
11
|
+
# Ruby Language Toolkit
|
12
|
+
require 'cg/tc_llvm'
|
13
|
+
require 'cg/tc_module'
|
14
|
+
|
15
|
+
require 'cg/tc_basic_block'
|
16
|
+
require 'cg/tc_control_flow'
|
17
|
+
require 'cg/tc_function'
|
18
|
+
require 'cg/tc_generic_value'
|
19
|
+
require 'cg/tc_instruction'
|
20
|
+
require 'cg/tc_math'
|
21
|
+
require 'cg/tc_transforms'
|
22
|
+
require 'cg/tc_type'
|
23
|
+
require 'cg/tc_value'
|
data/test/tc_ast.rb
ADDED
@@ -0,0 +1,332 @@
|
|
1
|
+
# Author: Chris Wailes <chris.wailes@gmail.com>
|
2
|
+
# Project: Ruby Language Toolkit
|
3
|
+
# Date: 2011/04/06
|
4
|
+
# Description: This file contains unit tests for the RLTK::ASTNode class.
|
5
|
+
|
6
|
+
############
|
7
|
+
# Requires #
|
8
|
+
############
|
9
|
+
|
10
|
+
# Gems
|
11
|
+
require 'minitest/autorun'
|
12
|
+
|
13
|
+
# Ruby Language Toolkit
|
14
|
+
require 'rltk/ast'
|
15
|
+
|
16
|
+
#######################
|
17
|
+
# Classes and Modules #
|
18
|
+
#######################
|
19
|
+
|
20
|
+
class ASTNodeTester < Minitest::Test
|
21
|
+
class ANode < RLTK::ASTNode
|
22
|
+
child :left, ANode
|
23
|
+
child :right, ANode
|
24
|
+
end
|
25
|
+
|
26
|
+
class BNode < ANode; end
|
27
|
+
class CNode < ANode; end
|
28
|
+
|
29
|
+
class DNode < RLTK::ASTNode; end
|
30
|
+
|
31
|
+
class ENode < RLTK::ASTNode
|
32
|
+
value :str, String
|
33
|
+
end
|
34
|
+
|
35
|
+
class FNode < ENode
|
36
|
+
child :c, [ENode]
|
37
|
+
end
|
38
|
+
|
39
|
+
class SNode < RLTK::ASTNode
|
40
|
+
value :string, String
|
41
|
+
|
42
|
+
child :left, SNode
|
43
|
+
child :right, SNode
|
44
|
+
end
|
45
|
+
|
46
|
+
class VNode < RLTK::ASTNode
|
47
|
+
value :a, Integer
|
48
|
+
value :b, Integer
|
49
|
+
end
|
50
|
+
|
51
|
+
class ONode < RLTK::ASTNode
|
52
|
+
value :a, Integer
|
53
|
+
value :b, Integer, true
|
54
|
+
value :c, Integer
|
55
|
+
end
|
56
|
+
|
57
|
+
class ValuesFirstNode < RLTK::ASTNode
|
58
|
+
child :b, ValuesFirstNode
|
59
|
+
value :a, Integer
|
60
|
+
end
|
61
|
+
|
62
|
+
class ChildrenFirstNode < RLTK::ASTNode
|
63
|
+
order :children
|
64
|
+
|
65
|
+
value :b, Integer
|
66
|
+
child :a, ChildrenFirstNode
|
67
|
+
end
|
68
|
+
|
69
|
+
class DefOrderNode < RLTK::ASTNode
|
70
|
+
order :def
|
71
|
+
|
72
|
+
value :a, Integer
|
73
|
+
child :b, DefOrderNode
|
74
|
+
value :c, Float
|
75
|
+
end
|
76
|
+
|
77
|
+
class CustomOrderNode < RLTK::ASTNode
|
78
|
+
custom_order :a, :b, :c, :d
|
79
|
+
|
80
|
+
child :b, CustomOrderNode
|
81
|
+
child :d, CustomOrderNode
|
82
|
+
|
83
|
+
value :a, Integer
|
84
|
+
value :c, String
|
85
|
+
end
|
86
|
+
|
87
|
+
def setup
|
88
|
+
@leaf0 = CNode.new
|
89
|
+
@tree0 = ANode.new(BNode.new(@leaf0), BNode.new)
|
90
|
+
|
91
|
+
@tree1 = ANode.new(BNode.new(CNode.new), BNode.new)
|
92
|
+
@tree2 = ANode.new(BNode.new, BNode.new(CNode.new))
|
93
|
+
@tree3 = ANode.new(CNode.new(BNode.new), CNode.new)
|
94
|
+
|
95
|
+
@tree4 = SNode.new('F',
|
96
|
+
SNode.new('B',
|
97
|
+
SNode.new('A'),
|
98
|
+
SNode.new('D',
|
99
|
+
SNode.new('C'),
|
100
|
+
SNode.new('E')
|
101
|
+
),
|
102
|
+
),
|
103
|
+
SNode.new('G',
|
104
|
+
nil,
|
105
|
+
SNode.new('I',
|
106
|
+
SNode.new('H')
|
107
|
+
)
|
108
|
+
)
|
109
|
+
)
|
110
|
+
|
111
|
+
@tree5 = FNode.new('one',
|
112
|
+
[FNode.new('two',
|
113
|
+
[ENode.new('three')]),
|
114
|
+
ENode.new('four')])
|
115
|
+
|
116
|
+
@tree6 = FNode.new('one',
|
117
|
+
[FNode.new('two',
|
118
|
+
[ENode.new('three')]),
|
119
|
+
ENode.new('four')])
|
120
|
+
|
121
|
+
@tree7 = FNode.new('one!',
|
122
|
+
[FNode.new('two!',
|
123
|
+
[ENode.new('three!')]),
|
124
|
+
ENode.new('four!')])
|
125
|
+
|
126
|
+
@bc_proc = Proc.new do |n|
|
127
|
+
case n
|
128
|
+
when BNode then CNode.new(n.left, n.right)
|
129
|
+
when CNode then BNode.new(n.left, n.right)
|
130
|
+
else n
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_children
|
136
|
+
node = ANode.new
|
137
|
+
|
138
|
+
assert_equal(node.children, [nil, nil])
|
139
|
+
|
140
|
+
node.children = (expected_children = [BNode.new, CNode.new])
|
141
|
+
|
142
|
+
assert_equal(node.children, expected_children)
|
143
|
+
|
144
|
+
node.children = (expected_children = {:left => CNode.new, :right => BNode.new})
|
145
|
+
|
146
|
+
assert_equal(node.children(Hash), expected_children)
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_copy
|
150
|
+
new_tree = @tree5.copy
|
151
|
+
|
152
|
+
assert_equal(@tree5, new_tree)
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_dump
|
156
|
+
tree0_string = @tree0.dump
|
157
|
+
|
158
|
+
reloaded_tree = Marshal.load(tree0_string)
|
159
|
+
|
160
|
+
assert_equal(@tree0, reloaded_tree)
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_each
|
164
|
+
# Test pre-order
|
165
|
+
nodes = []
|
166
|
+
expected = ['F', 'B', 'A', 'D', 'C', 'E', 'G', 'I', 'H']
|
167
|
+
@tree4.each(:pre) { |n| nodes << n.string }
|
168
|
+
|
169
|
+
assert_equal(expected, nodes)
|
170
|
+
|
171
|
+
# Test post-order
|
172
|
+
nodes = []
|
173
|
+
expected = ['A', 'C', 'E', 'D', 'B', 'H', 'I', 'G', 'F']
|
174
|
+
@tree4.each(:post) { |n| nodes << n.string }
|
175
|
+
|
176
|
+
assert_equal(expected, nodes)
|
177
|
+
|
178
|
+
# Test level-order
|
179
|
+
nodes = []
|
180
|
+
expected = ['F', 'B', 'G', 'A', 'D', 'I', 'C', 'E', 'H']
|
181
|
+
@tree4.each(:level) { |n| nodes << n.string }
|
182
|
+
|
183
|
+
assert_equal(expected, nodes)
|
184
|
+
|
185
|
+
# Test iteration with array children.
|
186
|
+
|
187
|
+
res = ''
|
188
|
+
@tree5.each(:pre) { |node| res += ' ' + node.str }
|
189
|
+
assert_equal(res, ' one two three four')
|
190
|
+
|
191
|
+
res = ''
|
192
|
+
@tree5.each(:post) { |node| res += ' ' + node.str }
|
193
|
+
assert_equal(res, ' three two four one')
|
194
|
+
|
195
|
+
res = ''
|
196
|
+
@tree5.each(:level) { |node| res += ' ' + node.str }
|
197
|
+
assert_equal(res, ' one two four three')
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_equal
|
201
|
+
assert_equal(@tree0, @tree1)
|
202
|
+
refute_equal(@tree0, @tree2)
|
203
|
+
end
|
204
|
+
|
205
|
+
def test_initialize
|
206
|
+
assert_raises(AbstractClassError) { RLTK::ASTNode.new }
|
207
|
+
|
208
|
+
node = ENode.new { self.str = 'hello world' }
|
209
|
+
assert_equal('hello world', node.str)
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_map
|
213
|
+
mapped_tree = @tree1.map(&@bc_proc)
|
214
|
+
|
215
|
+
assert_equal(@tree0, @tree1)
|
216
|
+
assert_equal(@tree3, mapped_tree)
|
217
|
+
|
218
|
+
mapped_tree = @tree5.map do |c|
|
219
|
+
c.str += '!'
|
220
|
+
|
221
|
+
c
|
222
|
+
end
|
223
|
+
|
224
|
+
assert_equal(@tree6, @tree5)
|
225
|
+
assert_equal(@tree7, mapped_tree)
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_map!
|
229
|
+
tree1_clone = @tree1.clone
|
230
|
+
tree1_clone.map!(&@bc_proc)
|
231
|
+
|
232
|
+
refute_equal(@tree1, tree1_clone)
|
233
|
+
assert_equal(@tree3, tree1_clone)
|
234
|
+
|
235
|
+
replace_node = BNode.new
|
236
|
+
replace_node = replace_node.map!(&@bc_proc)
|
237
|
+
|
238
|
+
assert_equal(CNode.new, replace_node)
|
239
|
+
|
240
|
+
@tree5.map! do |c|
|
241
|
+
c.str += '!'
|
242
|
+
|
243
|
+
c
|
244
|
+
end
|
245
|
+
|
246
|
+
refute_equal(@tree6, @tree5)
|
247
|
+
assert_equal(@tree7, @tree5)
|
248
|
+
end
|
249
|
+
|
250
|
+
def test_notes
|
251
|
+
node = ANode.new
|
252
|
+
|
253
|
+
assert_nil(node[:a])
|
254
|
+
assert_equal(node[:a] = :b, :b)
|
255
|
+
assert_equal(node.note?(:a), true)
|
256
|
+
assert_equal(node.note?(:b), false)
|
257
|
+
assert_equal(node.delete_note(:a), :b)
|
258
|
+
assert_nil(node[:a])
|
259
|
+
end
|
260
|
+
|
261
|
+
def test_omit
|
262
|
+
onode = ONode.new(1, 3)
|
263
|
+
|
264
|
+
assert_equal(1, onode.a)
|
265
|
+
assert_nil(onode.b)
|
266
|
+
assert_equal(3, onode.c)
|
267
|
+
end
|
268
|
+
|
269
|
+
def test_one_definition_rule
|
270
|
+
asserter = self
|
271
|
+
|
272
|
+
Class.new(ANode) do
|
273
|
+
asserter.assert_raises(ArgumentError) { child :left, ANode }
|
274
|
+
end
|
275
|
+
|
276
|
+
Class.new(ENode) do
|
277
|
+
asserter.assert_raises(ArgumentError) { value :str, String }
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
def test_ordering
|
282
|
+
vfn = ValuesFirstNode.new(42, ValuesFirstNode.new)
|
283
|
+
|
284
|
+
a, b = vfn.destructure(2)
|
285
|
+
|
286
|
+
assert_equal(42, a)
|
287
|
+
assert_instance_of(ValuesFirstNode, b)
|
288
|
+
|
289
|
+
cfn = ChildrenFirstNode.new(ChildrenFirstNode.new, 42)
|
290
|
+
|
291
|
+
a, b = cfn.destructure(2)
|
292
|
+
|
293
|
+
assert_instance_of(ChildrenFirstNode, a)
|
294
|
+
assert_equal(42, b)
|
295
|
+
|
296
|
+
dfn = DefOrderNode.new(4, DefOrderNode.new, 2.0)
|
297
|
+
|
298
|
+
a, b, c = dfn.destructure(3)
|
299
|
+
|
300
|
+
assert_equal(4, a)
|
301
|
+
assert_instance_of(DefOrderNode, b)
|
302
|
+
assert_equal(2.0, c)
|
303
|
+
|
304
|
+
con = CustomOrderNode.new(42, CustomOrderNode.new, 'foo')
|
305
|
+
|
306
|
+
a, b, c, d = con.destructure(4)
|
307
|
+
|
308
|
+
assert_equal(42, a)
|
309
|
+
assert_instance_of(CustomOrderNode, b)
|
310
|
+
assert_equal('foo', c)
|
311
|
+
assert_nil(d)
|
312
|
+
end
|
313
|
+
|
314
|
+
def test_root
|
315
|
+
assert_same(@tree0, @tree0.root)
|
316
|
+
assert_same(@tree0, @leaf0.root)
|
317
|
+
end
|
318
|
+
|
319
|
+
def test_value
|
320
|
+
node = VNode.new
|
321
|
+
|
322
|
+
assert_equal(node.values, [nil, nil])
|
323
|
+
|
324
|
+
node.values = (expected_values = [42, 1984])
|
325
|
+
|
326
|
+
assert_equal(node.values, expected_values)
|
327
|
+
|
328
|
+
node.values = (expected_values = {:a => 1984, :b => 42})
|
329
|
+
|
330
|
+
assert_equal(node.values(Hash), expected_values)
|
331
|
+
end
|
332
|
+
end
|
data/test/tc_cfg.rb
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
# Author: Chris Wailes <chris.wailes@gmail.com>
|
2
|
+
# Project: Ruby Language Toolkit
|
3
|
+
# Date: 2011/04/06
|
4
|
+
# Description: This file contains unit tests for the RLTK::CFG class.
|
5
|
+
|
6
|
+
############
|
7
|
+
# Requires #
|
8
|
+
############
|
9
|
+
|
10
|
+
# Gems
|
11
|
+
require 'minitest/autorun'
|
12
|
+
|
13
|
+
# Ruby Language Toolkit
|
14
|
+
require 'rltk/cfg'
|
15
|
+
|
16
|
+
#######################
|
17
|
+
# Classes and Modules #
|
18
|
+
#######################
|
19
|
+
|
20
|
+
class CFGTester < Minitest::Test
|
21
|
+
def setup
|
22
|
+
@grammar = RLTK::CFG.new
|
23
|
+
|
24
|
+
@grammar.production(:s) do
|
25
|
+
clause('A G D')
|
26
|
+
clause('A a C')
|
27
|
+
clause('B a D')
|
28
|
+
clause('B G C')
|
29
|
+
end
|
30
|
+
|
31
|
+
@grammar.production(:a, 'b')
|
32
|
+
@grammar.production(:b, 'G')
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_callback
|
36
|
+
grammar = RLTK::CFG.new
|
37
|
+
|
38
|
+
call_count = 0
|
39
|
+
grammar.callback do |type, which, p|
|
40
|
+
refute_nil(p)
|
41
|
+
assert_equal(type, :optional)
|
42
|
+
|
43
|
+
case call_count
|
44
|
+
when 0 then assert_equal(:empty, which)
|
45
|
+
when 1 then assert_equal(:nonempty, which)
|
46
|
+
end
|
47
|
+
|
48
|
+
call_count += 1
|
49
|
+
end
|
50
|
+
|
51
|
+
grammar.production(:a, 'A?') { |a| a }
|
52
|
+
assert_equal(2, call_count)
|
53
|
+
|
54
|
+
call_count = 0
|
55
|
+
grammar.callback do |type, which, p|
|
56
|
+
refute_nil(p)
|
57
|
+
|
58
|
+
case call_count
|
59
|
+
when 0
|
60
|
+
assert_equal(:elp, type)
|
61
|
+
assert_equal(:empty, which)
|
62
|
+
|
63
|
+
when 1
|
64
|
+
assert_equal(:elp, type)
|
65
|
+
assert_equal(:nonempty, which)
|
66
|
+
|
67
|
+
when 2
|
68
|
+
assert_equal(:nelp, type)
|
69
|
+
assert_equal(:single, which)
|
70
|
+
|
71
|
+
when 3
|
72
|
+
assert_equal(:nelp, type)
|
73
|
+
assert_equal(:multiple, which)
|
74
|
+
end
|
75
|
+
|
76
|
+
call_count += 1
|
77
|
+
end
|
78
|
+
|
79
|
+
grammar.production(:a, 'A*') { |a| a }
|
80
|
+
assert_equal(4, call_count)
|
81
|
+
|
82
|
+
call_count = 0
|
83
|
+
grammar.callback do |type, which, p|
|
84
|
+
refute_nil(p)
|
85
|
+
assert_equal(type, :nelp)
|
86
|
+
|
87
|
+
case call_count
|
88
|
+
when 0 then assert_equal(:single, which)
|
89
|
+
when 1 then assert_equal(:multiple, which)
|
90
|
+
end
|
91
|
+
|
92
|
+
call_count += 1
|
93
|
+
end
|
94
|
+
|
95
|
+
grammar.production(:a, 'A+') { |a| a }
|
96
|
+
assert_equal(2, call_count)
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_first_set
|
100
|
+
@grammar.first_set(:s).each do |sym|
|
101
|
+
assert_includes([:A, :B], sym)
|
102
|
+
end
|
103
|
+
|
104
|
+
assert_equal([:G], @grammar.first_set(:b))
|
105
|
+
assert_equal([:G], @grammar.first_set(:a))
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_follow_set
|
109
|
+
assert_equal(@grammar.follow_set(:s), [:EOS])
|
110
|
+
|
111
|
+
@grammar.follow_set(:a).each do |sym|
|
112
|
+
assert([:C, :D].include?(sym))
|
113
|
+
end
|
114
|
+
|
115
|
+
@grammar.follow_set(:b).each do |sym|
|
116
|
+
assert([:C, :D].include?(sym))
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_is_nonterminal
|
121
|
+
assert(RLTK::CFG::is_nonterminal?(:lowercase))
|
122
|
+
assert(!RLTK::CFG::is_nonterminal?(:UPERCASE))
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_is_terminal
|
126
|
+
assert(!RLTK::CFG::is_terminal?(:lowercase))
|
127
|
+
assert(RLTK::CFG::is_terminal?(:UPERCASE))
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_item
|
131
|
+
i0 = RLTK::CFG::Item.new(0, 0, :a, [:b, :C, :D, :e])
|
132
|
+
i1 = i0.copy
|
133
|
+
|
134
|
+
assert_equal(i0, i1)
|
135
|
+
assert(!i0.at_end?)
|
136
|
+
assert_equal(:b, i0.next_symbol)
|
137
|
+
|
138
|
+
i0.advance
|
139
|
+
|
140
|
+
refute_equal(i0, i1)
|
141
|
+
assert(!i0.at_end?)
|
142
|
+
assert_equal(:C, i0.next_symbol)
|
143
|
+
|
144
|
+
i0.advance
|
145
|
+
assert(!i0.at_end?)
|
146
|
+
assert_equal(:D, i0.next_symbol)
|
147
|
+
|
148
|
+
i0.advance
|
149
|
+
assert(!i0.at_end?)
|
150
|
+
assert_equal(:e, i0.next_symbol)
|
151
|
+
|
152
|
+
i0.advance
|
153
|
+
assert(i0.at_end?)
|
154
|
+
assert_nil(i0.next_symbol)
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_production
|
158
|
+
p0 = RLTK::CFG::Production.new(0, :a, [:b, :C, :D, :e])
|
159
|
+
p1 = p0.copy
|
160
|
+
|
161
|
+
assert_equal(p0, p1)
|
162
|
+
assert_equal(:D, p0.last_terminal)
|
163
|
+
end
|
164
|
+
end
|