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

#initialize(parent, self_ptr, constants = {}, locals = {}) ⇒ 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

#constantsObject

lexical_target = cref in YARV terms



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

def constants
  @constants
end

#lexical_targetObject

lexical_target = cref in YARV terms



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

def lexical_target
  @lexical_target
end

#localsObject

lexical_target = cref in YARV terms



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

def locals
  @locals
end

#methodObject

lexical_target = cref in YARV terms



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

def method
  @method
end

#parentObject

lexical_target = cref in YARV terms



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

def parent
  @parent
end

Instance Method Details

#add_binding!(new_binding) ⇒ Object



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

#initialize_copy(other) ⇒ Object



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

#lookup(str) ⇒ Object

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

#lookup_global(str) ⇒ Object

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

#lookup_ivar(str) ⇒ Object

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

#lookup_or_create_local(var_name) ⇒ Object



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

#pathObject



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

def path
  self_ptr.path
end

#sees_var?(var) ⇒ Boolean

Does this scope see the given variable name?



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

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

#self_ptrObject



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

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

#self_ptr=(other) ⇒ Object



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

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