class BinData::LazyEvaluator
field
instead of obj.field
.
This resolution process makes the lambda easier to read as we just write
a lambda or a symbol.
An evaluation will recurse until it returns a result that is not
resolution propagates up the chain of parent data objects.
in #parameters, and secondly as methods in this parent. This
parent of the bound data object. Resolution is attempted firstly as keys
When evaluating lambdas, unknown methods are resolved in the context of the
As a shortcut, :foo is the equivalent of lambda { foo }.
BinData::String.new(:value => lambda { %w{a test message}.join(“ ”) })
are those that are passed to data objects as parameters, e.g.:
lambdas in the context of this data object. These lambdas
A LazyEvaluator is bound to a data object. The evaluator will evaluate
def eval_symbol_in_parent_context(symbol, args)
def eval_symbol_in_parent_context(symbol, args) result = resolve_symbol_in_parent_context(symbol, args) recursively_eval(result, args) end
def index
Returns the index of this data object inside it's nearest container
def index return @overrides[:index] if @overrides and @overrides.has_key?(:index) child = @obj parent = @obj.parent while parent if parent.respond_to?(:find_index_of) return parent.find_index_of(child) end child = parent parent = parent.parent end raise NoMethodError, "no index found" end
def initialize(obj)
Creates a new evaluator. All lazy evaluation is performed in the
def initialize(obj) @obj = obj end
def lazy_eval(val, overrides = nil)
def lazy_eval(val, overrides = nil) @overrides = overrides if overrides if val.is_a? Symbol __send__(val) elsif val.respond_to? :arity instance_exec(&val) else val end end
def method_missing(symbol, *args)
def method_missing(symbol, *args) return @overrides[symbol] if defined? @overrides and @overrides.has_key?(symbol) if @obj.parent eval_symbol_in_parent_context(symbol, args) else super end end
def parent
def parent if @obj.parent @obj.parent.lazy_evaluator else nil end end
def recursively_eval(val, args)
def recursively_eval(val, args) if val.is_a?(Symbol) parent.__send__(val, *args) elsif val.respond_to?(:arity) parent.instance_exec(&val) else val end end
def resolve_symbol_in_parent_context(symbol, args)
def resolve_symbol_in_parent_context(symbol, args) obj_parent = @obj.parent if obj_parent.has_parameter?(symbol) result = obj_parent.get_parameter(symbol) elsif obj_parent.safe_respond_to?(symbol) result = obj_parent.__send__(symbol, *args) else result = symbol end end