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 ROOT_CLASS = VC::Top
15 META_CLASS = VC::Class
16
17
18 CLASSES = ::ObjectSpace.each_object(::Class).select {
19 |klass|
20
21 klass <= ROOT_CLASS
22 }.sort { |a, b|
23 a.to_s <=> b.to_s
24 }.each_with_index.sort { |(a, ord_a), (b, ord_b)|
25 result = a <=> b
26
27 if result
28 result * -1
29 else
30 ord_a <=> ord_b
31 end
32 }.map { |a, _ord|
33 ASSERT.subclass_of a, VC::Top
34 }.freeze
35
36
37 def update_method_info_of_mess_sym(info_of_symbol, infos, klass)
38 ASSERT.kind_of info_of_symbol, ::Hash
39 ASSERT.kind_of infos, ::Array
40 ASSERT.subclass_of klass, VC::Top
41
42 info_of_symbol.merge(
43 infos.inject({}) { |hash, info|
44 ASSERT.kind_of info, ECTSM::Info
45
46 hash.merge(info.mess_sym => info) {
47 ASSERT.abort(
48 "In class: %s, " +
49 "duplicated a message symbol: %s",
50 klass.type_sym, info.mess_sym
51 )
52 }
53 }
54 ) { |mess_sym, sub_info, sup_info|
55 ASSERT.assert(
56 sub_info.meth_sym == sup_info.meth_sym,
57 {
58 klass:klass,
59 mess:mess_sym,
60 sup_meth:sup_info.meth_sym,
61 sub_meth:sub_info.meth_sym
62 }.inspect
63 )
64
65 ASSERT.assert(
66 sub_info.param_classes.size == sup_info.param_classes.size
67 )
68
69 sub_info.param_classes.zip(sup_info.param_classes).each do
70 |sub_param_class, sup_param_class|
71 ASSERT.subclass_of sub_param_class, VC::Top
72 ASSERT.subclass_of sup_param_class, VC::Top
73
74 ASSERT.assert(
75 sub_param_class <= sup_param_class
76 )
77 end
78
79 ASSERT.assert(
80 sub_info.ret_class <= sup_info.ret_class,
81
82 [
83 format("Class: %s", klass.inspect),
84 format(" Message: %s", mess_sym),
85 format(" Super:"),
86 format(" Return: %s", sup_info.ret_class),
87 format(" Param: [%s]",
88 sup_info.param_classes.map(
89 &:inspect
90 ).join(', ')
91 ),
92 format(" Sub:"),
93 format(" Return: %s", sub_info.ret_class),
94 format(" Param: [%s]",
95 sub_info.param_classes.map(
96 &:inspect
97 ).join(', ')
98 ),
99 ].join("\n")
100 )
101
102 sub_info
103 }
104 end
105
106 module_function :update_method_info_of_mess_sym
107
108
109 CLASS_SIGNATS = CLASSES.map { |klass|
110 ASSERT.subclass_of klass, VC::Top
111
112 class_method_info_of_mess_sym,
113 instance_method_info_of_mess_sym = if klass <= META_CLASS
114 [{}, {}]
115 else
116 loop.inject(
117 [{}, {}, klass]
118 ) {
119 |(cmeth_info_of_sym, imeth_info_of_sym, k), _|
120
121 unless k <= ROOT_CLASS
122 break [cmeth_info_of_sym, imeth_info_of_sym]
123 end
124
125 [
126 update_method_info_of_mess_sym(
127 cmeth_info_of_sym, k.class_method_infos, k
128 ),
129
130 update_method_info_of_mess_sym(
131 imeth_info_of_sym, k.instance_method_infos, k
132 ),
133
134 k.superclass
135 ]
136 }
137 end
138
139 ECTS.make_class(
140 klass,
141 klass.type_sym,
142 class_method_info_of_mess_sym,
143 instance_method_info_of_mess_sym
144 )
145 }
146 CLASS_SIGNATS.freeze
147
148
149 =begin
150 CLASS_SIGNATS.each do |signat|
151 printf "==== %s : %s ====\n", signat.symbol, signat.klass
152 p signat
153 puts
154 end
155 exit
156 =end
157
158 SIGNAT_OF_CLASS, SIGNAT_OF_CLASS_SYM = CLASS_SIGNATS.inject(
159 [{}, {}]
160 ) {
161 |(signat_of_class, signat_of_class_sym), signat|
162 ASSERT.kind_of signat_of_class, ::Hash
163 ASSERT.kind_of signat_of_class_sym, ::Hash
164 ASSERT.kind_of signat, ECTSC::Base
165
166 [
167 signat_of_class.merge(signat.klass => signat) {
168 ASSERT.abort "Duplicated a class: %s", signat.klass.to_s
169 },
170
171 signat_of_class_sym.merge(signat.symbol => signat) {
172 ASSERT.abort "Duplicated a symbol: %s", signat.symbol.to_s
173 }
174 ]
175 }
176 SIGNAT_OF_CLASS.freeze
177 SIGNAT_OF_CLASS_SYM.freeze
178
179
180 SUPERCLASS_OF_SUBCLASS, SUBCLASSES_OF_SUPERCLASS = CLASSES.inject(
181 [{}, {}]
182 ) {
183 |(supsignat_of_subsignat, subsignats_of_supsignat), subclass|
184 ASSERT.kind_of supsignat_of_subsignat, ::Hash
185 ASSERT.kind_of subsignats_of_supsignat, ::Hash
186 ASSERT.subclass_of subclass, VC::Top
187
188 if subclass < ROOT_CLASS
189 subsignat = SIGNAT_OF_CLASS[subclass]
190 supsignat = SIGNAT_OF_CLASS[subclass.superclass]
191 ASSERT.kind_of subsignat, ECTSC::Base
192 ASSERT.kind_of supsignat, ECTSC::Base
193
194 [
195 supsignat_of_subsignat.merge(subsignat => supsignat) {
196 |signat, _, _|
197
198 ASSERT.abort(
199 "Duplicated a class signature: %s", signat.inspect
200 )
201 },
202
203 subsignats_of_supsignat.merge(
204 supsignat => ECTS.make_set([subsignat])
205 ) {
206 |_, old_set_of_signat, new_set_of_signat|
207
208 old_set_of_signat.union new_set_of_signat
209 }
210 ]
211 else
212 [
213 supsignat_of_subsignat,
214
215 subsignats_of_supsignat
216 ]
217 end
218 }.freeze
219 SUPERCLASS_OF_SUBCLASS.freeze
220 SUBCLASSES_OF_SUPERCLASS.freeze
221
222
223 ANCESTORS_OF_DESCENDANT, DESCENDANTS_OF_ANCESTOR = CLASS_SIGNATS.inject(
224 [{}, {}]
225 ) {
226 |(ancestors_of_descendant, descendants_of_ancestor), descendant|
227 ASSERT.kind_of ancestors_of_descendant, ::Hash
228 ASSERT.kind_of descendants_of_ancestor, ::Hash
229 ASSERT.kind_of descendant, ECTSC::Base
230
231 ancestors, _ = loop.inject([[], descendant]) { |(signats, signat), _|
232 ASSERT.kind_of signats, ::Array
233 ASSERT.kind_of signat, ECTSC::Base
234
235 opt_supsignat = SUPERCLASS_OF_SUBCLASS[signat]
236 ASSERT.opt_kind_of opt_supsignat, ECTSC::Base
237
238 if opt_supsignat
239 [signats + [opt_supsignat], opt_supsignat]
240 else
241 break [signats, nil]
242 end
243 }
244
245 [
246 ancestors_of_descendant.merge(
247 descendant => ECTS.make_set(ancestors)
248 ) { |signat, _, _|
249
250 ASSERT.abort(
251 "Duplicated a class signature: %s", signat.inspect
252 )
253 },
254
255 descendants_of_ancestor.merge(
256 ancestors.inject({}) { |hash, ancestor|
257 hash.merge(ancestor => ECTS.make_set([descendant])) {
258 |signat, _, _|
259
260 ASSERT.abort("Duplicated a class signature: %s",
261 signat.inspect
262 )
263 }
264 }
265 ) { |_, old_set_of_signat, new_set_of_signat|
266 old_set_of_signat.union new_set_of_signat
267 }
268 ]
269 }.freeze
270 ANCESTORS_OF_DESCENDANT.freeze
271 DESCENDANTS_OF_ANCESTOR.freeze
272
273
274
275 class Entry
276 def classes
277 CLASSES
278 end
279
280
281 def class_signats
282 CLASS_SIGNATS
283 end
284
285
286 def class_signat_of(value)
287 ASSERT.kind_of value, VC::Top
288
289 signat = if value.kind_of?(META_CLASS)
290 ECTS.make_metaclass value.class_signat
291 else
292 self.signat_of_class value.class
293 end
294
295 ASSERT.kind_of signat, ECTSC::Abstract
296 end
297
298
299 def signat_of_class(klass)
300 ASSERT.subclass_of klass, VC::Top
301
302 ASSERT.kind_of SIGNAT_OF_CLASS[klass], ECTSC::Base
303 end
304
305
306 def root_class_signat
307 ASSERT.kind_of self.signat_of_class(ROOT_CLASS), ECTSC::Base
308 end
309
310
311 def lookup(class_sym, loc, env)
312 ASSERT.kind_of class_sym, ::Symbol
313 ASSERT.kind_of loc, LOC::Entry
314 ASSERT.kind_of env, E::Entry
315
316 class_signat = SIGNAT_OF_CLASS_SYM[class_sym]
317
318 unless class_signat
319 raise X::NameError.new(
320 loc,
321 env,
322 "Unbound type identifier: '%s'", class_sym.to_s
323 )
324 end
325
326 ASSERT.kind_of class_signat, ECTSC::Base
327 end
328
329
330 def test_kind_of?(lhs_value, rhs_signat)
331 ASSERT.kind_of lhs_value, VC::Top
332 ASSERT.kind_of rhs_signat, ECTSC::Base
333
334 lhs_signat = self.class_signat_of lhs_value
335 ASSERT.kind_of lhs_signat, ECTSC::Abstract
336
337 result = if lhs_signat == rhs_signat
338 true
339 else
340 rhs_signats = self.descendants_of rhs_signat
341 ASSERT.kind_of rhs_signats, ECTS::SetOfClass
342
343 rhs_signats.member? lhs_signat
344 end
345 ASSERT.bool result
346 end
347
348
349 def opt_superclass_of(subclass)
350 ASSERT.kind_of subclass, ECTSC::Base
351
352 ASSERT.opt_kind_of subclass.opt_superclass, ECTSC::Base
353 end
354
355
356 def subclasses_of(superclass)
357 ASSERT.kind_of superclass, ECTSC::Base
358
359 ASSERT.kind_of superclass.subclasses, ECTS::SetOfClass
360 end
361
362
363 def ancestors_of(descendant)
364 ASSERT.kind_of descendant, ECTSC::Base
365
366 ASSERT.kind_of descendant.ancestors, ECTS::SetOfClass
367 end
368
369
370 def descendants_of(ancestor)
371 ASSERT.kind_of ancestor, ECTSC::Base
372
373 ASSERT.kind_of ancestor.descendants, ECTS::SetOfClass
374 end
375 end
376
377
378 BUILTIN = Entry.new.freeze
379
380 # BUILTIN.root_class_signat.print_class_tree
381
382
383
384 module_function
385
386 def make
387 BUILTIN
388 end
389
390 end # Umu::Environment::Context::Type
391
392 end # Umu::Environment::Context
393
394 end # Umu::Environment
395
396 end # Umu