Class: Laser::Analysis::Scope

Inherits:
Object
  • Object
show all
Defined in:
lib/laser/analysis/scope.rb

Overview

This class models a scope in Ruby. It has a constant table, a self pointer, and a parent pointer to the enclosing scope. It also has a local variable table.

Direct Known Subclasses

ClosedScope, OpenScope

Defined Under Namespace

Classes: ScopeLookupFailure

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Scope) initialize(parent, self_ptr, constants = {}, locals = {})

Returns a new instance of Scope



17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/laser/analysis/scope.rb', line 17

def initialize(parent, self_ptr, constants={}, locals={})
  unless respond_to?(:lookup_local)
    raise NotImplementedError.new(
        'must create OpenScope or ClosedScope. Not just Scope.')
  end
  @parent, @constants, @locals = parent, constants, locals
  @locals['self'] = Bindings::LocalVariableBinding.new('self', self_ptr)
  if self_ptr && Bindings::Base === self_ptr
    self_ptr.self_owner = self
  end
  @lexical_target = self_ptr
  @method = nil
end

Instance Attribute Details

- (Object) constants

lexical_target = cref in YARV terms



16
17
18
# File 'lib/laser/analysis/scope.rb', line 16

def constants
  @constants
end

- (Object) lexical_target

lexical_target = cref in YARV terms



16
17
18
# File 'lib/laser/analysis/scope.rb', line 16

def lexical_target
  @lexical_target
end

- (Object) locals

lexical_target = cref in YARV terms



16
17
18
# File 'lib/laser/analysis/scope.rb', line 16

def locals
  @locals
end

- (Object) method

lexical_target = cref in YARV terms



16
17
18
# File 'lib/laser/analysis/scope.rb', line 16

def method
  @method
end

- (Object) parent

lexical_target = cref in YARV terms



16
17
18
# File 'lib/laser/analysis/scope.rb', line 16

def parent
  @parent
end

Instance Method Details

- (Object) add_binding!(new_binding)



44
45
46
47
48
49
50
51
# File 'lib/laser/analysis/scope.rb', line 44

def add_binding!(new_binding)
  case new_binding.name[0,1]
  when /[A-Z]/
    constants[new_binding.name] = new_binding
  else
    locals[new_binding.name] = new_binding
  end
end

- (Object) initialize_copy(other)



31
32
33
34
# File 'lib/laser/analysis/scope.rb', line 31

def initialize_copy(other)
  @locals = other.locals.dup
  @constants = other.constants.dup
end

- (Object) lookup(str)

Proper variable lookup. The old ones were hacks.



66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/laser/analysis/scope.rb', line 66

def lookup(str)
  if str[0,2] == '::'
    Scope::GlobalScope.lookup(str[2..-1])
  elsif str.include?('::')
    parts = str.split('::')
    final_scope = parts[0..-2].inject(self) { |scope, part| scope.lookup(part).scope }
    final_scope.lookup(parts.last)
  elsif str =~ /^\$/ then lookup_global(str)
  elsif str =~ /^@/ then lookup_ivar(str)
  elsif str =~ /^@@/ then lookup_cvar(str)
  else lookup_local(str)
  end
end

- (Object) lookup_global(str)

Looks up a global binding. Defers to the global scope and creates on-demand.



81
82
83
84
# File 'lib/laser/analysis/scope.rb', line 81

def lookup_global(str)
  Scope::GlobalScope.locals[str] ||=
      Bindings::GlobalVariableBinding.new(str, nil)
end

- (Object) lookup_ivar(str)

Looks up an instance variable binding. Defers to the current value of self's class,



88
89
90
91
92
93
94
# File 'lib/laser/analysis/scope.rb', line 88

def lookup_ivar(str)
  unless (result = self_ptr.klass.instance_variables[str])
    result = Bindings::InstanceVariableBinding.new(str, LaserObject.new)
    self_ptr.klass.add_instance_variable!(result)
  end
  result
end

- (Object) lookup_or_create_local(var_name)



57
58
59
60
61
62
63
# File 'lib/laser/analysis/scope.rb', line 57

def lookup_or_create_local(var_name)
  lookup_local(var_name)
rescue ScopeLookupFailure
  binding = Bindings::LocalVariableBinding.new(var_name, nil)
  add_binding!(binding)
  binding
end

- (Object) path



53
54
55
# File 'lib/laser/analysis/scope.rb', line 53

def path
  self_ptr.path
end

- (Boolean) sees_var?(var)

Does this scope see the given variable name?

Returns:

  • (Boolean)


97
98
99
# File 'lib/laser/analysis/scope.rb', line 97

def sees_var?(var)
  lookup(var) rescue false
end

- (Object) self_ptr



36
37
38
# File 'lib/laser/analysis/scope.rb', line 36

def self_ptr
  @locals['self'].value
end

- (Object) self_ptr=(other)



40
41
42
# File 'lib/laser/analysis/scope.rb', line 40

def self_ptr=(other)
  @locals['self'] = Bindings::LocalVariableBinding.new('self', other)
end