forked from rubinius/rubinius
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathautoload.rb
119 lines (98 loc) · 2.72 KB
/
autoload.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
##
# Used to implement Module#autoload.
class Autoload
attr_reader :name
attr_reader :scope
attr_reader :path
attr_reader :constant
attr_accessor :loaded
attr_accessor :loading
def self.allocate
Rubinius.primitive :autoload_allocate
raise PrimtiveFailure, "Autoload.allocate primitive failed"
end
def initialize(name, scope, path)
@name = name
@scope = scope
@path = path
@constant = undefined
@loading = false
@loaded = false
end
private :initialize
def inspect
"#<#{self.class.name}:0x#{object_id.to_s(16)} name=#{@name} scope=#{@scope}" \
" path=#{@path} constant=#{@constant} loading=#{@loading} loaded=#{@loaded}>"
end
alias_method :to_s, :inspect
def loading?
Rubinius.synchronize(self) { @loading }
end
##
#
# Change the file to autoload. Used by Module#autoload
def set_path(path)
@path = path
@loading = false
end
##
# When any code that finds a constant sees an instance of Autoload as its match,
# it calls this method on us
def call(under, honor_require=false)
return constant unless undefined.equal? constant
if resolve or not honor_require
find_const under
end
end
def resolve
# The protocol that MRI defines for resolving an Autoload instance
# requires that the constant table entry be removed _during_ the load so
# that Module#const_defined? returns false and defined?() returns nil for
# the constant that triggered the load.
Rubinius.synchronize(self) do
unless @loaded or @loading
@loading = true
result = Rubinius::CodeLoader.new(@path).require
@loaded = true if result
@loading = false
result
end
end
end
def find_const(under)
current = under
constant = undefined
while current
if entry = current.constant_table.lookup(name)
constant = entry.constant
if constant.equal? self
if undefined.equal?(constant.constant)
unless Object.constant_table.lookup(name)
return under.const_missing(name)
end
else
entry.constant = constant.constant
return constant.constant
end
end
return constant
end
current = current.direct_superclass
end
if instance_of?(Module)
if entry = Object.constant_table.lookup(name)
constant = entry.constant
if constant.equal? self
if undefined.equal?(constant.constant)
return under.const_missing(name)
else
entry.constant = constant.constant
return constant.constant
end
end
return constant
end
end
under.const_missing(name)
end
end