Class: Reduxco::Context::CallableTable

Inherits:
Object
  • Object
show all
Defined in:
lib/reduxco/context/callable_table.rb

Overview

CallableTable is a ‘private’ helper class to Context which handles resolving CallableRef instances to their appropriate callables. This should not be used directly.

Constant Summary collapse

RESOLUTION_FAILURE =

The constant returned by resolve when resolution failure occurs. This constant can be multiply assigned to the same pattern as a normal resolution, but will assign nil into each value.

[nil,nil]

Instance Method Summary collapse

Constructor Details

#initialize(callable_map_list) ⇒ CallableTable

Instantiate with list of callable maps.



16
17
18
# File 'lib/reduxco/context/callable_table.rb', line 16

def initialize(callable_map_list)
  @table = Hash[flatten(callable_map_list).sort.reverse]
end

Instance Method Details

#include?(callref) ⇒ Boolean

Returns true if the call with teh given callref exists.

Returns:

  • (Boolean)


37
38
39
# File 'lib/reduxco/context/callable_table.rb', line 37

def include?(callref)
  !resolve(callref).last.nil?
end

#resolve(callref) ⇒ Object Also known as: []

Resolves the given callref. The return value usually takes advantage of multiple assignment to dissect the return into the matching callref and found callable. however one can check for failed resolution simply by comparing the result to RESOLUTION_FAILURE.

Note that if resolution fails, each value in the multiple assignment is given the value nil.



27
28
29
30
31
32
33
# File 'lib/reduxco/context/callable_table.rb', line 27

def resolve(callref)
  if( callref.static? )
    @table.include?(callref) ? [callref, @table[callref]] : RESOLUTION_FAILURE
  else
    @table.find(->{RESOLUTION_FAILURE}) {|refkey, callable| callref.include?(refkey)}
  end
end

#resolve_super(callref) ⇒ Object

Given a static callref, resolves the next available shadowed callable above it. If the callref is dynamic, then an exception is thrown.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/reduxco/context/callable_table.rb', line 43

def resolve_super(callref)
  if( callref.dynamic? )
    raise ArgumentError, "Cannot resolve the 'super' of a dyanmic CallableReference.", caller
  else
    # This is really nice, but runs in O(n):
    #   @table.find(->{RESOLUTION_FAILURE}) {|refkey, callable| refkey.name == callref.name && refkey.depth < callref.depth}
    # This is more performant on large tables O(1) but has the potential for a lot of recursion depth:
    #   if( callref.depth <= CallableRef::MIN_DEPTH )
    #     RESOLUTION_FAILURE
    #   else
    #     resolution = resolve(callref.pred)
    #     resolution == RESOLUTION_FAILURE ? resolve_super(callref.pred) : resolution
    #   end
    # So we go for this imperative C-style flat iteration for O(1) and no recursion.
    ref = callref
    while( ref.depth > CallableRef::MIN_DEPTH )
      ref = ref.pred
      resolution = resolve(ref)
      return resolution if(resolution != RESOLUTION_FAILURE)
    end
    RESOLUTION_FAILURE
  end
end