-
Notifications
You must be signed in to change notification settings - Fork 30
/
loop_filter.rb
95 lines (86 loc) · 2.37 KB
/
loop_filter.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
module Pacer
module Core
module Route
def loop(&block)
chain_route :filter => :loop, :looping_route => block
end
# Apply the given path fragment multiple times in succession. If a Range
# or Array of numbers is given, the results are a combination of the
# results from all of the specified repetition levels. That is useful if
# a pattern may be nested to varying depths.
def repeat(arg, &block)
case arg
when Fixnum
range = arg..arg
arg.to_enum(:times).inject(self) do |route_end, count|
yield route_end
end
when Range
if arg.exclude_end?
range = arg.begin..(arg.end - 1)
else
range = arg
end
r = self.loop(&block).while do |e, depth, p|
if depth < range.begin
:loop
elsif depth < range.end
:loop_and_emit
elsif depth == range.end
:emit
else
false
end
end
r.while_description = "repeat #{ arg.inspect }"
r
else
raise "Invalid repeat range"
end
end
end
end
module ElementMixin
def loop(&block)
chain_route :filter => :loop, :looping_route => block
end
end
module Filter
module LoopFilter
attr_reader :looping_route
attr_accessor :while_description
def looping_route=(route)
if route.is_a? Proc
@looping_route = Pacer::Route.block_branch(self, route)
else
@looping_route = route
end
end
def while(yield_paths = false, &block)
@yield_paths = yield_paths
@control_block = block
self
end
protected
def attach_pipe(end_pipe)
unless @control_block
raise 'No loop control block specified. Use either #while or #until after #loop.'
end
pipe = Pacer::Pipes::LoopPipe.new(graph, looping_pipe, @control_block)
pipe.setStarts(end_pipe) if end_pipe
pipe
end
def looping_pipe
Pacer::Route.pipeline(looping_route)
end
def inspect_string
s = "#{ inspect_class_name }(#{ @looping_route.inspect })"
if while_description
"#{ s }(#{ while_description })"
else
s
end
end
end
end
end