1 # coding: utf-8
2 # frozen_string_literal: true
3
4
5
6 module Umu
7
8 module Environment
9
10 module Context
11
12 module Type
13
14 module Signature
15
16 module Class
17
18 class Abstract
19 def symbol
20 raise X::InternalSubclassResponsibility
21 end
22
23
24 def ==(other)
25 other.kind_of?(Abstract) && self.symbol == other.symbol
26 end
27 alias eql? ==
28
29
30 def hash
31 self.symbol.hash
32 end
33
34
35 def lookup_instance_method(_sym, _loc, _env)
36 raise X::InternalSubclassResponsibility
37 end
38 end
39
40
41
42 class Base < Abstract
43 attr_reader :klass
44 attr_reader :symbol
45 attr_reader :class_method_info_of_mess_sym
46 attr_reader :instance_method_info_of_mess_sym
47
48 alias to_sym symbol
49 alias type_sym symbol
50
51
52 def initialize(
53 klass,
54 symbol,
55 class_method_info_of_mess_sym,
56 instance_method_info_of_mess_sym
57 )
58 ASSERT.subclass_of klass, VC::Top
59 ASSERT.kind_of symbol, ::Symbol
60 ASSERT.kind_of class_method_info_of_mess_sym, ::Hash
61 ASSERT.kind_of instance_method_info_of_mess_sym, ::Hash
62
63 @klass = klass
64 @symbol = symbol
65 @class_method_info_of_mess_sym = class_method_info_of_mess_sym
66 @instance_method_info_of_mess_sym = instance_method_info_of_mess_sym
67 end
68
69
70 def to_s
71 self.symbol.to_s
72 end
73
74
75 def <=>(other)
76 ASSERT.kind_of other, Abstract
77
78 self.symbol <=> other.symbol
79 end
80
81
82 def abstract_class?
83 not self.subclasses.empty?
84 end
85
86
87 def num_of_class_messages
88 self.class_method_info_of_mess_sym.size
89 end
90
91
92 def each_class_method(env)
93 ASSERT.kind_of env, E::Entry
94
95 return enum_for(__method__, env) unless block_given?
96
97 self.class_method_info_of_mess_sym.each_value do |info|
98 yield info.to_signat(env)
99 end
100 end
101
102
103 def lookup_class_method(mess_sym, loc, env)
104 ASSERT.kind_of mess_sym, ::Symbol
105 ASSERT.kind_of loc, LOC::Entry
106 ASSERT.kind_of env, E::Entry
107
108 info = self.class_method_info_of_mess_sym[mess_sym]
109 unless info
110 raise X::NoMessageError.new(
111 loc,
112 env,
113 "For class: %s, unknown class message: '%s'",
114 self.symbol, mess_sym.to_s
115 )
116 end
117 ASSERT.kind_of info, ECTSM::Info
118
119 info.to_signat(env)
120 end
121
122
123 def num_of_instance_messages
124 self.instance_method_info_of_mess_sym.size
125 end
126
127
128 def each_instance_method(env)
129 ASSERT.kind_of env, E::Entry
130
131 return enum_for(__method__, env) unless block_given?
132
133 self.instance_method_info_of_mess_sym.each_value do |info|
134 yield info.to_signat(env)
135 end
136 end
137
138
139 def lookup_instance_method(mess_sym, loc, env)
140 ASSERT.kind_of mess_sym, ::Symbol
141 ASSERT.kind_of loc, LOC::Entry
142 ASSERT.kind_of env, E::Entry
143
144 info = self.instance_method_info_of_mess_sym[mess_sym]
145 unless info
146 raise X::NoMessageError.new(
147 loc,
148 env,
149 "For class: %s, unknown instance message: '%s'",
150 self.symbol, mess_sym.to_s
151 )
152 end
153 ASSERT.kind_of info, ECTSM::Info
154
155 info.to_signat(env)
156 end
157
158
159 def opt_superclass
160 ASSERT.opt_kind_of SUPERCLASS_OF_SUBCLASS[self], ECTSC::Base
161 end
162
163
164 def subclasses
165 opt_subclasses = SUBCLASSES_OF_SUPERCLASS[self]
166 subclasses = if opt_subclasses
167 opt_subclasses
168 else
169 ECTS::EMPTY_SET
170 end
171
172 ASSERT.kind_of subclasses, ECTS::SetOfClass
173 end
174
175
176 def ancestors
177 opt_ancestors = ANCESTORS_OF_DESCENDANT[self]
178 ancestors = if opt_ancestors
179 opt_ancestors
180 else
181 ECTS::EMPTY_SET
182 end
183
184 ASSERT.kind_of ancestors, ECTS::SetOfClass
185 end
186
187
188 def descendants
189 opt_descendants = DESCENDANTS_OF_ANCESTOR[self]
190 descendants = if opt_descendants
191 opt_descendants
192 else
193 ECTS::EMPTY_SET
194 end
195
196 ASSERT.kind_of descendants, ECTS::SetOfClass
197 end
198 end
199
200
201
202 class Meta < Abstract
203 attr_reader :base_class_signat
204
205
206 def initialize(base_class_signat)
207 ASSERT.kind_of base_class_signat, Base
208
209 @base_class_signat = base_class_signat
210 end
211
212
213 def symbol
214 :Class
215 end
216
217
218 def lookup_instance_method(sym, loc, env)
219 ASSERT.kind_of sym, ::Symbol
220 ASSERT.kind_of loc, LOC::Entry
221 ASSERT.kind_of env, E::Entry
222
223 method = self.base_class_signat.lookup_class_method(sym, loc, env)
224
225 ASSERT.kind_of method, ECTSM::Entry
226 end
227 end
228
229 end # Umu::Environment::Context::Type::Signature::Class
230
231
232
233 module_function
234
235 def make_class(
236 klass,
237 symbol,
238 class_method_info_of_mess_sym,
239 instance_method_info_of_mess_sym
240 )
241 ASSERT.subclass_of klass, VC::Top
242 ASSERT.kind_of symbol, ::Symbol
243 ASSERT.kind_of class_method_info_of_mess_sym, ::Hash
244 ASSERT.kind_of instance_method_info_of_mess_sym, ::Hash
245
246 Class::Base.new(
247 klass,
248 symbol,
249 class_method_info_of_mess_sym.freeze,
250 instance_method_info_of_mess_sym.freeze
251 ).freeze
252 end
253
254
255 def make_metaclass(base_class_signat)
256 ASSERT.kind_of base_class_signat, Class::Base
257
258 Class::Meta.new(base_class_signat).freeze
259 end
260
261 end # Umu::Environment::Context::Type::Signature
262
263 end # Umu::Environment::Context::Type
264
265 end # Umu::Environment::Context
266
267 end # Umu::Environment
268
269 end # Umu