Class: BinData::LazyEvalEnv
- Inherits:
-
Object
- Object
- BinData::LazyEvalEnv
- Defined in:
- lib/bindata/lazy.rb
Overview
The enviroment in which a lazily evaluated lamba is called. These lambdas are those that are passed to data objects as parameters. Each lambda has access to the following:
- parent
-
the environment of the parent data object
- params
-
any extra parameters that have been passed to the data object. The value of a parameter is either a lambda, a symbol or a literal value (such as a Fixnum).
Unknown methods are resolved in the context of the parent environment, first as keys in the extra parameters, and secondly as methods in the parent data object. This makes the lambda easier to read as we just write field
instead of obj.field
.
Constant Summary collapse
- @@empty_hash =
An empty hash shared by all instances
Hash.new.freeze
- @@variables_cache =
{}
Instance Attribute Summary collapse
-
#data_object ⇒ Object
writeonly
Sets the attribute data_object.
-
#params ⇒ Object
Returns the value of attribute params.
-
#parent ⇒ Object
readonly
Returns the value of attribute parent.
Instance Method Summary collapse
-
#add_variable(sym, value) ⇒ Object
Add a variable with a pre-assigned value to this environment.
-
#initialize(parent = nil) ⇒ LazyEvalEnv
constructor
Creates a new environment.
-
#lazy_eval(obj, overrides = nil) ⇒ Object
Evaluates
obj
in the context of this environment. - #method_missing(symbol, *args) ⇒ Object
-
#offset_of(sym) ⇒ Object
TODO: offset_of needs to be better thought out.
-
#parent_data_object ⇒ Object
Returns the data_object for the parent environment.
Constructor Details
#initialize(parent = nil) ⇒ LazyEvalEnv
Creates a new environment. parent
is the environment of the parent data object.
23 24 25 26 27 28 |
# File 'lib/bindata/lazy.rb', line 23 def initialize(parent = nil) @parent = parent @variables = @@empty_hash @overrides = @@empty_hash @params = @@empty_hash end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(symbol, *args) ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/bindata/lazy.rb', line 92 def method_missing(symbol, *args) if @overrides.include?(symbol) @overrides[symbol] elsif @variables.include?(symbol) @variables[symbol] elsif @parent obj = symbol if @parent.params and @parent.params.has_key?(symbol) obj = @parent.params[symbol] elsif @parent.data_object and @parent.data_object.respond_to?(symbol) obj = @parent.data_object.__send__(symbol, *args) end @parent.lazy_eval(obj) else super end end |
Instance Attribute Details
#data_object=(value) ⇒ Object
Sets the attribute data_object
30 31 32 |
# File 'lib/bindata/lazy.rb', line 30 def data_object=(value) @data_object = value end |
#params ⇒ Object
Returns the value of attribute params.
29 30 31 |
# File 'lib/bindata/lazy.rb', line 29 def params @params end |
#parent ⇒ Object (readonly)
Returns the value of attribute parent.
29 30 31 |
# File 'lib/bindata/lazy.rb', line 29 def parent @parent end |
Instance Method Details
#add_variable(sym, value) ⇒ Object
Add a variable with a pre-assigned value to this environment. sym
will be accessible as a variable for any lambda evaluated with #lazy_eval.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/bindata/lazy.rb', line 43 def add_variable(sym, value) sym = sym.to_sym if @variables.equal?(@@empty_hash) # optimise the case where only 1 variable is added as this # is the most common occurance (BinData::Arrays adding index) key = [sym, value] @variables = @@variables_cache[key] if @variables.nil? # cache this variable and value so it can be shared with # other LazyEvalEnvs to keep memory usage down @variables = {sym => value}.freeze @@variables_cache[key] = @variables end else if @variables.length == 1 key = @variables.keys[0] @variables = {key => @variables[key]} end @variables[sym] = value end end |
#lazy_eval(obj, overrides = nil) ⇒ Object
Evaluates obj
in the context of this environment. Evaluation recurses until it yields a value that is not a symbol or lambda. overrides
is an optional params
like hash
80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/bindata/lazy.rb', line 80 def lazy_eval(obj, overrides = nil) @overrides = overrides if overrides if obj.is_a? Symbol # treat :foo as lambda { foo } obj = __send__(obj) elsif obj.respond_to? :arity obj = instance_eval(&obj) end @overrides = @@empty_hash obj end |
#offset_of(sym) ⇒ Object
TODO: offset_of needs to be better thought out
66 67 68 69 70 |
# File 'lib/bindata/lazy.rb', line 66 def offset_of(sym) @parent.data_object.offset_of(sym) rescue nil end |
#parent_data_object ⇒ Object
Returns the data_object for the parent environment.
73 74 75 |
# File 'lib/bindata/lazy.rb', line 73 def parent_data_object @parent.nil? ? nil : @parent.data_object end |