-
Notifications
You must be signed in to change notification settings - Fork 608
/
constant_scope.rb
150 lines (120 loc) · 3.18 KB
/
constant_scope.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# -*- encoding: us-ascii -*-
##
# A linked list that details the static, lexical scope the method was created
# in.
#
# TODO: document
module Rubinius
class ConstantScope
#
# @todo Verify the recursion here does not cause problems. --rue
#
def initialize(mod, par = nil)
@module = mod
@parent = par
end
# Source code of this scope.
attr_accessor :script
# Module or class this lexical scope enclosed into.
attr_reader :module
# Constant scope object this scope enclosed into.
attr_reader :parent
# Module or class representing the 'current class'. MRI manipulates
# this outside of the lexical scope and uses it for undef and method
# definition.
attr_accessor :current_module
# Set to indicate that no methods may be add to this scope
attr_accessor :disabled_for_methods
# Lazy initialized hash map used for flip-flops
attr_accessor :flip_flops
def inspect
"#<#{self.class.name}:0x#{self.object_id.to_s(16)} parent=#{@parent.inspect} module=#{@module}>"
end
def to_s
inspect
end
# Indicates if this is a toplevel/default scope
def top_level?
!@parent
end
# Use the same info as the current ConstantScope, but set current_module to
# +mod+. Chains off the current ConstantScope.
def using_current_as(mod)
if top_level?
# Don't chain up if this is a toplevel, create a new one.
cs = dup
else
cs = ConstantScope.new @module, self
end
cs.current_module = mod
return cs
end
def using_disabled_scope
cs = using_current_as(@module)
cs.disabled_for_methods = true
return cs
end
def for_method_definition
if @disabled_for_methods
raise TypeError, "unable to create methods in this scope"
end
return @current_module if @current_module
return @module
end
def alias_method(name, original)
Rubinius.privately do
for_method_definition.alias_method name, original
end
end
def __undef_method__(name)
Rubinius.privately do
for_method_definition.undef_method name
end
end
def active_path
script = current_script
if script
if path = script.file_path
return path.dup
end
end
return "__unknown__.rb"
end
def absolute_active_path
script = current_script
if script
if path = script.data_path
return path.dup
end
end
return nil
end
def data_path
script = current_script
if script and script.main?
if path = script.data_path
return path.dup
end
end
return nil
end
def current_script
scope = self
while scope and !scope.script
scope = scope.parent
end
return scope && scope.script
end
def const_set(name, value)
@module.const_set name, value
end
def const_defined?(name)
scope = self
while scope and scope.module != Object
return true if scope.module.const_defined?(name)
scope = scope.parent
end
return Object.const_defined?(name)
end
end
end