-
Notifications
You must be signed in to change notification settings - Fork 610
/
module19.rb
156 lines (122 loc) · 4.13 KB
/
module19.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
150
151
152
153
154
155
156
# -*- encoding: us-ascii -*-
class Module
def const_get(name, inherit = true)
name = Rubinius::Type.coerce_to_constant_name name
current, constant = self, undefined
while current
constant = current.constant_table.fetch name, undefined
unless constant.equal?(undefined)
constant = constant.call(current) if constant.kind_of?(Autoload)
return constant
end
unless inherit
return const_missing(name)
end
current = current.direct_superclass
end
if instance_of?(Module)
constant = Object.constant_table.fetch name, undefined
unless constant.equal?(undefined)
constant = constant.call(current) if constant.kind_of?(Autoload)
return constant
end
end
const_missing(name)
end
def const_defined?(name, search_parents=true)
name = Rubinius::Type.coerce_to_constant_name name
return true if @constant_table.has_key? name
# a silly special case
if self.equal? Object
mod = direct_superclass
while mod.kind_of? Rubinius::IncludedModule
return true if mod.constant_table.has_key? name
mod = mod.direct_superclass
end
end
if search_parents
current = self.direct_superclass
while current
return true if current.constant_table.has_key? name
current = current.direct_superclass
end
if instance_of?(Module)
return true if Object.constant_table.has_key? name
end
end
return false
end
def attr(*attributes)
vis = Rubinius::VariableScope.of_sender.method_visibility
if attributes.size == 2 && (attributes.last.is_a?(TrueClass) || attributes.last.is_a?(FalseClass))
name = attributes.first
Rubinius.add_reader name, self, vis
Rubinius.add_writer name, self, vis if attributes.last
else
attributes.each do |name|
if name.is_a?(Symbol) || (name.respond_to?(:to_str) && name.to_str.is_a?(String) && !name.to_str.empty?)
Rubinius.add_reader(name, self, vis)
else
raise TypeError, "#{name.inspect} is not a symbol"
end
end
end
return nil
end
private :attr
# Install a new Autoload object into the constants table
# See kernel/common/autoload.rb
def autoload(name, path)
path = Rubinius::Type.coerce_to_path(path)
raise ArgumentError, "empty file name" if path.empty?
return if Rubinius::CodeLoader.feature_provided?(path)
name = Rubinius::Type.coerce_to_constant_name name
if existing = @constant_table[name]
if existing.kind_of? Autoload
# If there is already an Autoload here, just change the path to
# autoload!
existing.set_path(path)
else
# Trying to register an autoload for a constant that already exists,
# ignore the request entirely.
end
return
end
constant_table[name] = Autoload.new(name, self, path)
Rubinius.inc_global_serial
return nil
end
def constants(all=undefined)
tbl = Rubinius::LookupTable.new
# When calling `constants` on "normal" classes the result does not include
# their own class name. BasicObject is a special case in this regard.
tbl[:BasicObject] = true if self == BasicObject
@constant_table.each do |name, val|
tbl[name] = true
end
if all
current = self.direct_superclass
while current and current != Object
current.constant_table.each do |name, val|
tbl[name] = true unless tbl.has_key? name
end
current = current.direct_superclass
end
end
# special case: Module.constants returns Object's constants
if self.equal?(Module) && all.equal?(undefined)
Object.constant_table.each do |name, val|
tbl[name] = true unless tbl.has_key? name
end
end
Rubinius.convert_to_names tbl.keys
end
def private_constant(*names)
end
def public_constant(*names)
unknown_constants = names - @constant_table.keys
if unknown_constants.size > 0
raise NameError, "#{unknown_constants.size > 1 ? 'Constants' : 'Constant'} #{unknown_constants.map{|e| "#{name}::#{e}"}.join(', ')} undefined"
end
end
end