Class: Xampl::Iterator

Inherits:
Object
  • Object
show all
Defined in:
lib/xamplr/iterator.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ Iterator

Returns a new instance of Iterator.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/xamplr/iterator.rb', line 19

def initialize(options)
  case options[:cycle]
    when :stop, :error, :ignore, :notify, :notify_then_stop
      @on_cycle = options[:cycle]
    else
      @on_cycle = :notify_then_stop
  end

  case options[:seen]
    when :stop, :error, :ignore, :notify, :notify_then_stop
      @on_seen = options[:seen]
    else
      @on_seen = :notify_then_stop
  end

  @exhausted = false
  @visiting = Hash.new 0
  @visited = Set.new
  @alive = true
end

Instance Attribute Details

#aliveObject

Returns the value of attribute alive.



6
7
8
# File 'lib/xamplr/iterator.rb', line 6

def alive
  @alive
end

#exhaustedObject

Returns the value of attribute exhausted.



6
7
8
# File 'lib/xamplr/iterator.rb', line 6

def exhausted
  @exhausted
end

#on_cycleObject

Returns the value of attribute on_cycle.



6
7
8
# File 'lib/xamplr/iterator.rb', line 6

def on_cycle
  @on_cycle
end

#on_seenObject

Returns the value of attribute on_seen.



6
7
8
# File 'lib/xamplr/iterator.rb', line 6

def on_seen
  @on_seen
end

Class Method Details

.create(xampl, options = {}) ⇒ Object



8
9
10
11
12
13
14
15
16
17
# File 'lib/xamplr/iterator.rb', line 8

def Iterator.create(xampl, options={})
  iterator = Iterator.new(options)
  fib = Fiber.new do
    iterator.consider(xampl)
    iterator.alive = false
    iterator.set_fiber(nil)
  end
  iterator.set_fiber(fib)
  iterator
end

Instance Method Details

#consider(xampl) ⇒ Object



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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/xamplr/iterator.rb', line 70

def consider(xampl)
  stop_after_reporting = false
  notices={}

  cycle = (1 < (@visiting[xampl] += 1))
  if cycle then
    case on_cycle
      when :stop
        return
      when :ignore
      when :notify, :notify_then_stop
        stop_after_reporting = true
        notices[:cycling] = true
      when :error
        throw "cycle on :#{ xampl }"
    end
  else
    if @visited.member?(xampl) then
      case on_seen
        when :stop
          return
        when :ignore
        when :notify, :notify_then_stop
          stop_after_reporting = true
          notices[:seen] = true
        when :error
          throw "aleady seen :#{ xampl }"
      end
    end
  end

  @visited << xampl

  notices[:opening] = true
  notices[:closing] = false

  control = (Fiber.yield(xampl, notices) || {})

  notify_on_close = control[:notify_on_close]

  if !control[:continue] && !control[:ignore] && (control[:stop] || control[:no_children] || stop_after_reporting)
    Fiber.yield(xampl, { opening: false, closing: true }) if notify_on_close
    return
  end

  xampl.children.each do | child |
    consider(child)
  end

  Fiber.yield(xampl, { opening: false, closing: true }) if notify_on_close
end

#ignoreObject



59
60
61
62
# File 'lib/xamplr/iterator.rb', line 59

def ignore
  return nil, { :done => true } unless alive
  @fib.resume(:ignore => true)
end

#next(control = {}) ⇒ Object



44
45
46
47
# File 'lib/xamplr/iterator.rb', line 44

def next(control={})
  return nil, { :done => true } unless alive
  @fib.resume(control)
end

#no_childrenObject



49
50
51
52
# File 'lib/xamplr/iterator.rb', line 49

def no_children
  return nil, { :done => true } unless alive
  @fib.resume(:no_children => true)
end

#set_fiber(fib) ⇒ Object



40
41
42
# File 'lib/xamplr/iterator.rb', line 40

def set_fiber(fib)
  @fib = fib
end

#stopObject



54
55
56
57
# File 'lib/xamplr/iterator.rb', line 54

def stop
  return nil, { :done => true } unless alive
  @fib.resume(:stop => true)
end

#terminateObject



64
65
66
67
68
# File 'lib/xamplr/iterator.rb', line 64

def terminate
  @alive = false
  @fib = nil
  return nil, { :done => true }
end