Module: Eymiha::ForwardReferencing

Included in:
ForwardReferencer
Defined in:
lib/eymiha/util/forward_referencing.rb

Overview

The ForwardReferencing module can be mixed into a class to allow it to capture and resolve ForwardReferences.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#forward_referencesObject (readonly)

An array containing the set of unresolved forward references.



16
17
18
# File 'lib/eymiha/util/forward_referencing.rb', line 16

def forward_references
  @forward_references
end

Instance Method Details

#continue_forward_reference_resolutionObject

To be called at the end of a section of code that could contain a forward reference, it will continue during normal processing and jump back to the resolve_forward_references method during resolution.



74
75
76
# File 'lib/eymiha/util/forward_referencing.rb', line 74

def continue_forward_reference_resolution
  @forward_reference_resolver.call if @forward_reference_resolver
end

#create_forward_reference(dependency = nil, context = nil) ⇒ Object

To be called when a section of code that could contain a forward reference is entered. The method returns a newly created ForwardReference with the given dependency that can be jumped to during resolution.



29
30
31
32
33
# File 'lib/eymiha/util/forward_referencing.rb', line 29

def create_forward_reference(dependency=nil,context=nil)
  forward_reference = ForwardReference.new(dependency,context)
  @forward_references << forward_reference
  forward_reference
end

#forward_reference_dependenciesObject

Returns a hash of dependencies to arrays of the ForwardReferences that have them as dependencies.



80
81
82
83
84
85
86
87
88
89
# File 'lib/eymiha/util/forward_referencing.rb', line 80

def forward_reference_dependencies
  dependencies = {}
  @forward_references.each { |forward_reference|
    dependency = forward_reference.dependency || "nil"
    forward_references = dependencies[dependency]
    dependencies[dependency] = [] if forward_references == nil
    dependencies[dependency] << forward_reference
  }
  dependencies
end

#forward_references_clearObject

Remove the remaining unresolved forward references.



102
103
104
# File 'lib/eymiha/util/forward_referencing.rb', line 102

def forward_references_clear
  @forward_references = []
end

#forward_references_remainingObject

Returns the number of unresolved forward references.



97
98
99
# File 'lib/eymiha/util/forward_referencing.rb', line 97

def forward_references_remaining
  @forward_references.size
end

#forward_references_to_sObject

Returns a string indicating the current state of ForwardReferencing.



92
93
94
# File 'lib/eymiha/util/forward_referencing.rb', line 92

def forward_references_to_s
  "#{class_name}  #{forward_references_remaining} unresolved"
end

#remove_forward_reference(forward_reference = nil) ⇒ Object

To be called when a section of code that could contain a forward reference has successfully been reached. It is used to remove the ForwardReference that was created at the start of the section, and asserts that a resolution was made.



39
40
41
42
43
# File 'lib/eymiha/util/forward_referencing.rb', line 39

def remove_forward_reference(forward_reference=nil)
  @forward_references.delete forward_reference if
    (forward_reference.kind_of? ForwardReference)
  @had_forward_reference_resolution = true
end

#resolve_forward_referencesObject

To be called to try to resolve any unresolved ForwardReferences by jumping to each in turn and retrying the code that caused it. This method repeats until nothing more is resolved. At that point unresolved forward reference may still exist, to be possibly resolved by another call to this method downstream. Prior to continuing to a forward reference, the establish_forward_reference context method is called with the context that was provided at the time the forward reference was created to give the receiver a chance to reset any transcient infromation.



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/eymiha/util/forward_referencing.rb', line 53

def resolve_forward_references
  forward_references = @forward_references
  forward_references_clear
  @had_forward_reference_resolution = false
  if forward_references.size > 0
    @forward_reference_resolver ||= callcc {|cont| cont} while
      (@forward_reference_resolver == nil)
    forward_reference = forward_references.shift
    if forward_reference != nil
      establish_forward_reference_context(forward_reference.context) if
        respond_to?(:establish_forward_reference_context,true)
      forward_reference.continuation.call
    end
  end
  @forward_reference_resolver = nil
  resolve_forward_references if @had_forward_reference_resolution
end

#start_forward_referencingObject

To be called from the initializer of the includer, this sets up the forward reference capture and resolution mechanisms.



20
21
22
23
24
# File 'lib/eymiha/util/forward_referencing.rb', line 20

def start_forward_referencing
  forward_references_clear
  @had_forward_reference_resolution = false
  @forward_reference_resolver = nil
end