Skip to content

Commit 4f6b0e4

Browse files
committed
Add prepend to ast method
1 parent b0be90a commit 4f6b0e4

4 files changed

Lines changed: 282 additions & 82 deletions

File tree

lib/filterly/node_builder.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,28 @@ def self.build_equality_node(attr_name:, attr_value:)
1515
)
1616
end
1717

18+
def self.build_not_equality_node(attr_name:, attr_value:)
19+
Filterly::Node.new(
20+
:expression,
21+
[
22+
:op_not_equal,
23+
Filterly::Node.new(:attr_name, [attr_name, nil, nil]),
24+
Filterly::Node.new(:attr_value, [attr_value, nil, nil])
25+
]
26+
)
27+
end
28+
29+
def self.build_exists_node(attr_name:, attr_value:)
30+
Filterly::Node.new(
31+
:expression,
32+
[
33+
:op_exists,
34+
Filterly::Node.new(:attr_name, [attr_name, nil, nil]),
35+
Filterly::Node.new(:attr_value, [attr_value, nil, nil])
36+
]
37+
)
38+
end
39+
1840
def self.build_array_values_node(attr_name:, array_of_values:)
1941
Filterly::Node.new(
2042
:expression,

lib/filterly/tree.rb

Lines changed: 76 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,20 @@ def initialize(ast_node)
1010
@ast_node = ast_node
1111
end
1212

13+
def self.new(ast_node)
14+
ensure_ast_node!(ast_node)
15+
16+
super(ast_node)
17+
end
18+
1319
def extend_ast(node_attr_name, new_node, stmt_type)
14-
return if ast_node.nil?
15-
if ast_node.attr_name_equal?(node_attr_name)
16-
create_node(
17-
:statement,
18-
[
19-
stmt_type,
20-
new_node,
21-
ast_node
22-
]
23-
)
24-
else
25-
recreate_node(node_attr_name, new_node, stmt_type)
26-
end
20+
TreeTraverser.new(ast_node).extend_ast(node_attr_name, new_node, stmt_type)
2721
end
2822

29-
def recreate_node(node_attr_name, new_node, stmt_type)
30-
create_node(
31-
ast_node.type,
32-
[
33-
ast_node.value,
34-
self.class.new(ast_node.left).extend_ast(node_attr_name, new_node, stmt_type),
35-
self.class.new(ast_node.right).extend_ast(node_attr_name, new_node, stmt_type)
36-
]
37-
)
23+
def prepend_ast(new_node, stmt_type)
24+
ensure_ast_root!
25+
26+
TreeTraverser.new(ast_node).prepend_ast(new_node, stmt_type)
3827
end
3928

4029
def to_ast
@@ -45,9 +34,72 @@ def to_s
4534
ast_node.to_s
4635
end
4736

37+
# @apir private
38+
def ensure_ast_root!
39+
raise 'Not a tree root!' if ast_node.type != :root
40+
end
41+
4842
# @api private
49-
def create_node(*args)
50-
Filterly::Node.new(*args)
43+
def self.ensure_ast_node!(ast_node)
44+
raise 'Not a Filterfly:Node!' if ast_node.nil? || !ast_node.is_a?(Filterly::Node)
45+
end
46+
47+
class TreeTraverser
48+
attr_reader :ast_node
49+
50+
def initialize(ast_node)
51+
@ast_node = ast_node
52+
end
53+
54+
def extend_ast(node_attr_name, new_node, stmt_type)
55+
return if ast_node.nil?
56+
if ast_node.attr_name_equal?(node_attr_name)
57+
create_node(
58+
:statement,
59+
[
60+
stmt_type,
61+
new_node,
62+
ast_node
63+
]
64+
)
65+
else
66+
recreate_node(node_attr_name, new_node, stmt_type)
67+
end
68+
end
69+
70+
def recreate_node(node_attr_name, new_node, stmt_type)
71+
create_node(
72+
ast_node.type,
73+
[
74+
ast_node.value,
75+
self.class
76+
.new(ast_node.left)
77+
.extend_ast(node_attr_name, new_node, stmt_type),
78+
self.class
79+
.new(ast_node.right)
80+
.extend_ast(node_attr_name, new_node, stmt_type)
81+
]
82+
)
83+
end
84+
85+
def prepend_ast(new_node, stmt_type)
86+
create_node(
87+
ast_node.type,
88+
[
89+
ast_node.value,
90+
create_node(
91+
:statement,
92+
[stmt_type, new_node, ast_node.left]
93+
),
94+
nil
95+
]
96+
)
97+
end
98+
99+
# @api private
100+
def create_node(*args)
101+
Filterly::Node.new(*args)
102+
end
51103
end
52104
end
53105
end

spec/unit/node_builder_spec.rb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,54 @@
3939
end
4040
end
4141

42+
describe '#self.build_not_equality_node' do
43+
it 'returns requested ast node' do
44+
result = subject.build_not_equality_node(attr_name: 'course_id', attr_value: 12)
45+
46+
expect(result.to_a).to match_array(
47+
[
48+
:expression,
49+
[
50+
:op_not_equal,
51+
[
52+
:attr_name,
53+
[
54+
'course_id',
55+
[],
56+
[]
57+
]
58+
],
59+
[
60+
:attr_value,
61+
[
62+
12,
63+
[],
64+
[]
65+
]
66+
]
67+
]
68+
]
69+
)
70+
end
71+
end
72+
73+
describe '#self.build_exists_node' do
74+
it 'returns requested ast node' do
75+
result = subject.build_exists_node(attr_name: 'course_id', attr_value: 12)
76+
77+
expect(result.to_a).to match_array(
78+
[
79+
:expression,
80+
[
81+
:op_exists,
82+
[:attr_name, ['course_id', [], []]],
83+
[:attr_value, [12, [], []]]
84+
]
85+
]
86+
)
87+
end
88+
end
89+
4290
describe '#self.build_array_values_node' do
4391
it 'returns requested ast node' do
4492
result = subject.build_array_values_node(

0 commit comments

Comments
 (0)