gxg-web-client/gxg/core/binding.rb
2021-11-16 08:58:51 -08:00

116 lines
2.9 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class Binding
attr_accessor :variables
attr_accessor :compiled_code
attr_accessor :lexical_scope
attr_accessor :proc_environment
attr_accessor :location
attr_accessor :receiver
def from_proc?
@proc_environment
end
def self.self_context(recv, variables)
Rubinius::Type.object_equal(recv, Kernel) ? recv : variables.self
end
private :self_context
# Create a new Binding object. MRI does not allow .new to be called, so
# we used .setup(). Any code can use this as they wish, provided they have
# all the right arguments.
#
# +variables+ is a Rubinius::VariableScope object
# +code+ is a Rubinius::CompiledCode object
# +lexical_scope+ is a Rubinius::LexicalScope object
#
# See Kernel#binding in core/eval.rb for a simple example of creating a
# Binding object.
#
def self.setup(variables, code, lexical_scope, recv=nil, location=nil)
bind = allocate()
bind.receiver = self_context(recv, variables)
bind.variables = variables
bind.compiled_code = code
bind.lexical_scope = lexical_scope
bind.location = location
return bind
end
def line_number
if proc_environment
proc_environment.line
else
location ? location.line : 1
end
end
# Evaluates the Ruby expression(s) in string, in the bindings context.
# If the optional filename and lineno parameters are present,
# they will be used when reporting syntax errors.
def eval(expr, filename=nil, lineno=nil)
lineno ||= filename ? 1 : line_number
Kernel.eval(expr, self, filename, lineno)
end
def local_variables
variables.local_variables
end
def local_variable_set(name, value)
unless name.is_a?(Symbol)
name = Rubinius::Type.coerce_to(name, String, :to_str).to_sym
end
vars = variables
# If a local variable is defined in a parent scope we should update the
# variable in said scope and all child scopes, instead of _only_ setting it
# in the current scope.
while vars
meth = vars.method
if meth.local_names.include?(name)
return vars.set_local(meth.local_slot(name), value)
elsif vars.eval_local_defined?(name)
return vars.set_eval_local(name, value)
end
vars = vars.parent
end
variables.set_eval_local(name, value)
end
def local_variable_get(name)
unless name.is_a?(Symbol)
name = Rubinius::Type.coerce_to(name, String, :to_str).to_sym
end
vars = variables
while vars
meth = vars.method
if meth.local_names.include?(name)
return vars.locals[meth.local_slot(name)]
elsif vars.eval_local_defined?(name)
return vars.get_eval_local(name)
end
vars = vars.parent
end
raise NameErrror, "local variable #{name.inspect} not defined for #{inspect}"
end
def local_variable_defined?(name)
unless name.is_a?(Symbol)
name = Rubinius::Type.coerce_to(name, String, :to_str).to_sym
end
variables.local_defined?(name)
end
end