/[eiffelstudio]/branches/eth/eve/Src/Eiffel/API/evaluated_type/gen_type_a.e
ViewVC logotype

Contents of /branches/eth/eve/Src/Eiffel/API/evaluated_type/gen_type_a.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 94740 - (show annotations)
Fri Mar 28 09:42:08 2014 UTC (5 years, 8 months ago) by jasonw
File size: 57736 byte(s)
<<Merged from trunk#94739.>>
1 note
2 description: "Descritpion of an actual generical type."
3 legal: "See notice at end of class."
4 status: "See notice at end of class."
5 date: "$Date$"
6 revision: "$Revision$"
7
8 class GEN_TYPE_A
9
10 inherit
11 CL_TYPE_A
12 rename
13 make as cl_make
14 redefine
15 generics, valid_generic, parent_type, dump, ext_append_to, formal_instantiation_in,
16 has_like, has_like_argument, has_like_current, is_loose, duplicate, good_generics,
17 error_generics, check_constraints, has_formal_generic, formal_instantiated_in,
18 instantiated_in,
19 has_expanded, internal_is_valid_for_class, expanded_deferred, valid_expanded_creation,
20 same_as, is_equivalent, description, description_with_detachable_type, instantiated_description, is_explicit,
21 deep_actual_type, context_free_type, instantiation_in, has_actual,
22 actual_argument_type, update_dependance, hash_code,
23 is_full_named_type, is_known, process, evaluated_type_in_descendant,
24 generate_cid, generate_cid_array, generate_cid_init,
25 make_type_byte_code, il_type_name, generic_il_type_name,
26 generate_gen_type_il, adapted_in, internal_generic_derivation,
27 internal_same_generic_derivation_as, is_class_valid,
28 is_valid_generic_derivation, skeleton_adapted_in, dispatch_anchors,
29 check_labels, duplicate_for_instantiation
30 end
31
32 INTERNAL_COMPILER_STRING_EXPORTER
33
34 create
35 make
36
37 feature {NONE} -- Initialization
38
39 make (a_class_id: INTEGER; g: like generics)
40 -- Create Current with `g' types as generic parameter.
41 require
42 valid_class_id: a_class_id > 0
43 has_generics: g /= Void
44 do
45 generics := g
46 cl_make (a_class_id)
47 ensure
48 generics_set: generics = g
49 class_id_set: class_id = a_class_id
50 end
51
52 feature -- Visitor
53
54 process (v: TYPE_A_VISITOR)
55 -- Process current element.
56 do
57 v.process_gen_type_a (Current)
58 end
59
60 feature -- Properties
61
62 has_actual (type: CL_TYPE_A): BOOLEAN
63 -- Is `type' an (possibly nested) actual parameter of this type?
64 local
65 i, nb: INTEGER
66 l_generics: like generics
67 l_cl_type: CL_TYPE_A
68 do
69 from
70 l_generics := generics
71 i := l_generics.lower
72 nb := l_generics.upper
73 until
74 i > nb
75 loop
76 l_cl_type ?= l_generics.i_th (i)
77 if l_cl_type /= Void and then (l_cl_type.same_as (type) or else l_cl_type.has_actual (type)) then
78 Result := True
79 i := nb + 1
80 else
81 i := i + 1
82 end
83 end
84 end
85
86 feature -- Comparison
87
88 is_equivalent (other: like Current): BOOLEAN
89 -- Is `other' equivalent to the current object ?
90 local
91 i, nb: INTEGER
92 other_generics: like generics
93 do
94 Result := Precursor {CL_TYPE_A} (other)
95 if Result then
96 from
97 i := 1
98 nb := generics.count
99 other_generics := other.generics
100 Result := nb = other_generics.count
101 until
102 i > nb or else not Result
103 loop
104 Result := equivalent (generics.i_th (i),
105 other_generics.i_th (i))
106 i := i + 1
107 end
108 end
109 end
110
111 same_as (other: TYPE_A): BOOLEAN
112 -- Is the current type the same as `other' ?
113 local
114 other_gen_type: like Current
115 i, nb: INTEGER
116 other_generics: like generics
117 do
118 other_gen_type ?= other
119 if
120 other_gen_type /= Void
121 and then other_gen_type.class_id = class_id
122 and then is_expanded = other_gen_type.is_expanded
123 and then has_same_marks (other_gen_type)
124 then
125 from
126 i := 1
127 nb := generics.count
128 other_generics := other_gen_type.generics
129 Result := nb = other_generics.count
130 until
131 i > nb or else not Result
132 loop
133 Result := generics.i_th (i).same_as (other_generics.i_th (i))
134 i := i + 1
135 end
136 end
137 end
138
139 feature -- Access
140
141 generics: ARRAYED_LIST [TYPE_A]
142 -- Actual generical parameter
143
144 hash_code: INTEGER
145 local
146 l_rotate, l_bytes, i: INTEGER
147 l_generics: like generics
148 do
149 Result := Precursor
150 l_generics := generics
151 i := l_generics.count
152 if i >= 0 then
153 from
154 until
155 i = 0
156 loop
157 l_rotate := l_generics.i_th (i).hash_code
158 l_bytes := 4 * (1 + i \\ 8)
159 l_rotate := (l_rotate |<< l_bytes) | (l_rotate |>> (32 - l_bytes))
160 Result := Result.bit_xor (l_generics.i_th (i).hash_code)
161 i := i - 1
162 end
163 -- To prevent negative values.
164 Result := Result.hash_code
165 end
166 end
167
168 description: ATTR_DESC
169 -- Descritpion of type for skeletons.
170 local
171 gen_desc: GENERIC_DESC
172 do
173 if is_loose then
174 create gen_desc
175 gen_desc.set_type_i (Current)
176 Result := gen_desc
177 else
178 Result := Precursor {CL_TYPE_A}
179 end
180 end
181
182 description_with_detachable_type: ATTR_DESC
183 local
184 gen_desc: GENERIC_DESC
185 do
186 if is_loose then
187 create gen_desc
188 gen_desc.set_type_i (as_detachable_type)
189 Result := gen_desc
190 else
191 Result := Precursor {CL_TYPE_A}
192 end
193 end
194
195 instantiated_description: ATTR_DESC
196 local
197 exp: EXPANDED_DESC
198 l_ref: REFERENCE_DESC
199 do
200 if is_expanded then
201 create exp
202 exp.set_type_i (Current)
203 Result := exp
204 else
205 create l_ref
206 l_ref.set_type_i (Current)
207 Result := l_ref
208 end
209 end
210
211 feature -- Status Report
212
213 is_explicit: BOOLEAN
214 -- Is type fixed at compile time without anchors or formals?
215 local
216 i, nb: INTEGER
217 l_generics: like generics
218 do
219 from
220 i := 1
221 l_generics := generics
222 nb := l_generics.count
223 Result := True
224 until
225 i > nb
226 loop
227 if not l_generics.i_th (i).is_explicit then
228 Result := False
229 i := nb + 1
230 else
231 i := i + 1
232 end
233 end
234 end
235
236 is_class_valid: BOOLEAN
237 local
238 i, nb: INTEGER
239 l_generics: like generics
240 do
241 if base_class /= Void then
242 from
243 i := 1
244 l_generics := generics
245 nb := l_generics.count
246 Result := True
247 until
248 i > nb
249 loop
250 if not l_generics.i_th (i).is_class_valid then
251 Result := False
252 i := nb + 1
253 else
254 i := i + 1
255 end
256 end
257 end
258 end
259
260 is_valid_generic_derivation: BOOLEAN
261 -- A generic type is a valid derivation if and only if the class type
262 -- being referenced are still expanded.
263 --| This can happen when a generic class which was expanded and used in
264 --| another generic class is not expanded anymore.
265 local
266 i, nb: INTEGER
267 l_generics: like generics
268 l_type: CL_TYPE_A
269 do
270 from
271 i := 1
272 l_generics := generics
273 nb := l_generics.count
274 Result := True
275 until
276 i > nb
277 loop
278 l_type ?= l_generics.i_th (i)
279 -- If type is still expanded, we do the recursion in case it has a generic parameter which is
280 -- itself generic and needs to be checked as well.
281 if l_type /= Void and then (not l_type.is_expanded or else not l_type.has_associated_class_type (Void)) then
282 Result := False
283 i := nb + 1
284 else
285 i := i + 1
286 end
287 end
288 end
289
290 feature -- Output
291
292 dump: STRING
293 -- Dumped trace
294 local
295 i, count: INTEGER
296 do
297 Result := Precursor {CL_TYPE_A}
298
299 count := generics.count
300
301 -- TUPLE may have zero generic parameters
302
303 if count > 0 then
304 Result.append_character (' ')
305 Result.append_character ('[')
306 from
307 i := 1
308 until
309 i > count
310 loop
311 Result.append (generics.i_th (i).dump)
312 if i /= count then
313 Result.append_character (',')
314 Result.append_character (' ')
315 end
316 i := i + 1
317 end
318 Result.append_character (']')
319 end
320 end
321
322 ext_append_to (a_text_formatter: TEXT_FORMATTER; a_context_class: CLASS_C)
323 -- <Precursor>
324 local
325 i, count: INTEGER
326 do
327 -- Append classname "TUPLE"
328 Precursor {CL_TYPE_A} (a_text_formatter, a_context_class)
329
330 count := generics.count
331 -- TUPLE may have zero generic parameters
332 if count > 0 then
333 a_text_formatter.add_space
334 a_text_formatter.process_symbol_text ({SHARED_TEXT_ITEMS}.ti_L_bracket)
335 from
336 i := 1
337 until
338 i > count
339 loop
340 generics.i_th (i).ext_append_to (a_text_formatter, a_context_class)
341 if i /= count then
342 a_text_formatter.process_symbol_text ({SHARED_TEXT_ITEMS}.ti_Comma)
343 a_text_formatter.add_space
344 end
345 i := i + 1
346 end
347 a_text_formatter.process_symbol_text ({SHARED_TEXT_ITEMS}.ti_R_bracket)
348 end
349 end
350
351 feature -- Generic conformance
352
353 generate_cid (buffer : GENERATION_BUFFER; final_mode, use_info : BOOLEAN; a_context_type: TYPE_A)
354 local
355 i, nb: INTEGER
356 l_generics: like generics
357 do
358 Precursor (buffer, final_mode, use_info, a_context_type)
359 from
360 l_generics := generics
361 i := l_generics.lower
362 nb := l_generics.upper
363 until
364 i > nb
365 loop
366 l_generics.i_th (i).generate_cid (buffer, final_mode, use_info, a_context_type)
367 i := i + 1
368 end
369 end
370
371 generate_cid_array (buffer: GENERATION_BUFFER; final_mode, use_info: BOOLEAN; idx_cnt: COUNTER; a_context_type: TYPE_A)
372 local
373 i, nb: INTEGER
374 l_generics: like generics
375 do
376 Precursor (buffer, final_mode, use_info, idx_cnt, a_context_type)
377
378 from
379 l_generics := generics
380 i := l_generics.lower
381 nb := l_generics.upper
382 until
383 i > nb
384 loop
385 l_generics.i_th (i).generate_cid_array (buffer, final_mode, use_info, idx_cnt, a_context_type)
386 i := i + 1
387 end
388 end
389
390 generate_cid_init (buffer: GENERATION_BUFFER; final_mode, use_info: BOOLEAN; idx_cnt: COUNTER; a_context_type: TYPE_A; a_level: NATURAL)
391 local
392 i, nb: INTEGER
393 l_generics: like generics
394 do
395 Precursor (buffer, final_mode, use_info, idx_cnt, a_context_type, a_level)
396
397 from
398 l_generics := generics
399 i := l_generics.lower
400 nb := l_generics.upper
401 until
402 i > nb
403 loop
404 l_generics.i_th (i).generate_cid_init (buffer, final_mode, use_info, idx_cnt, a_context_type, a_level)
405 i := i + 1
406 end
407 end
408
409 make_type_byte_code (ba: BYTE_ARRAY; use_info : BOOLEAN; a_context_type: TYPE_A)
410 -- Put type id's in byte array.
411 -- `use_info' is true iff we generate code for a
412 -- creation instruction.
413 local
414 i, nb: INTEGER
415 l_generics: like generics
416 do
417 Precursor (ba, use_info, a_context_type)
418
419 from
420 l_generics := generics
421 i := l_generics.lower
422 nb := l_generics.upper
423 until
424 i > nb
425 loop
426 l_generics.i_th (i).make_type_byte_code (ba, use_info, a_context_type)
427 i := i + 1
428 end
429 end
430
431 generate_gen_type_il (il_generator: IL_CODE_GENERATOR; use_info : BOOLEAN)
432 -- `use_info' is true iff we generate code for a
433 -- creation instruction.
434 local
435 i, nb : INTEGER
436 l_generics: like generics
437 do
438 l_generics := generics
439
440 generate_gen_type_instance (il_generator, l_generics.count)
441
442 from
443 i := l_generics.lower
444 check
445 i_start_at_one: i = 1
446 end
447 nb := l_generics.upper
448 until
449 i > nb
450 loop
451 il_generator.duplicate_top
452 il_generator.put_integer_32_constant (i - 1)
453 l_generics.i_th (i).generate_gen_type_il (il_generator, use_info)
454 il_generator.generate_array_write ({IL_CONST}.il_ref, 0)
455 i := i + 1
456 end
457
458 il_generator.generate_generic_type_settings (Current)
459 end
460
461 generate_gen_type_instance (il_generator: IL_CODE_GENERATOR; n: INTEGER)
462 -- Generic runtime instance for Current
463 require
464 il_generator_not_void: il_generator /= Void
465 n_non_negative: n >= 0
466 do
467 il_generator.generate_generic_type_instance (n)
468 end
469
470 frozen enumerate_interfaces (processor: PROCEDURE [ANY, TUPLE [CLASS_TYPE]])
471 -- Enumerate all class types for which an object of this type can be attached to.
472 -- FIXME: To be put in GEN_TYPE_A when refactoring complete.
473 require
474 processor_attached: processor /= Void
475 do
476 -- TODO:
477 -- 1. Rule out generic types with too many generic parameters to
478 -- avoid explosure of artificially introduced types.
479 -- 2. Ensure generated code works as expected.
480 -- 3. Remove validity rule that prevents reattaching derivations
481 -- with expanded parameters to derivations with reference parameters.
482 enumerate_interfaces_recursively (processor, generics.count)
483 end
484
485 feature -- CECIL code generation
486
487 generate_cecil_values (buffer: GENERATION_BUFFER; a_context_type: TYPE_A)
488 -- Generate CECIL metatypes for current generic derivation
489 require
490 buffer_not_void: buffer /= Void
491 context_type_valid: a_context_type /= Void implies
492 a_context_type.generic_derivation.same_as (a_context_type)
493 context_type_class_valid: a_context_type /= Void implies
494 (a_context_type.has_associated_class and then
495 is_valid_for_class (a_context_type.base_class))
496 has_associated_class_type: has_associated_class_type (a_context_type)
497 local
498 i, nb: INTEGER
499 l_generics: like generics
500 do
501 from
502 l_generics := generics
503 i := l_generics.lower
504 nb := l_generics.upper
505 until
506 i > nb
507 loop
508 l_generics.i_th (i).generate_cecil_value (buffer, a_context_type)
509 buffer.put_two_character (',', '%N')
510 i := i + 1
511 end
512 end
513
514 make_cecil_values (ba: BYTE_ARRAY; a_context_type: TYPE_A)
515 -- Make byte code for cecil values
516 require
517 ba_not_void: ba /= Void
518 context_type_valid: a_context_type /= Void implies
519 a_context_type.generic_derivation.same_as (a_context_type)
520 context_type_class_valid: a_context_type /= Void implies
521 (a_context_type.has_associated_class and then
522 is_valid_for_class (a_context_type.base_class))
523 has_associated_class_type: has_associated_class_type (a_context_type)
524 local
525 i, nb: INTEGER
526 l_generics: like generics
527 do
528 from
529 l_generics := generics
530 i := l_generics.lower
531 nb := l_generics.upper
532 until
533 i > nb
534 loop
535 ba.append_natural_32 (l_generics.i_th (i).sk_value (a_context_type))
536 i := i + 1
537 end
538 end
539
540 feature -- IL code generation
541
542 il_type_name (a_prefix: STRING; a_context_type: TYPE_A): STRING
543 -- Name of current class
544 local
545 i, count: INTEGER
546 sep, tmp: STRING
547 l_generics: like generics
548 l_class_c: like base_class
549 l_is_precompiled: BOOLEAN
550 l_cl_type: like associated_class_type
551 do
552 l_class_c := base_class
553 l_is_precompiled := l_class_c.is_precompiled
554 if l_is_precompiled then
555 l_cl_type := associated_class_type (a_context_type)
556 l_is_precompiled := l_cl_type.is_precompiled
557 if l_is_precompiled then
558 Result := l_cl_type.il_type_name (a_prefix)
559 end
560 end
561 if not l_is_precompiled then
562 Result := l_class_c.name.twin
563
564 l_generics := generics
565
566 -- Append generic information.
567 count := l_generics.count
568 if count > 0 then
569 from
570 i := 1
571 sep := "_"
572 until
573 i > count
574 loop
575 Result.append (sep)
576 tmp := l_generics.i_th (i).generic_il_type_name (a_context_type).twin
577 tmp.remove_head (tmp.last_index_of ('.', tmp.count))
578 Result.append (tmp)
579 i := i + 1
580 end
581 end
582
583 Result := internal_il_type_name (Result, a_prefix)
584 end
585 end
586
587 generic_il_type_name (a_context_type: TYPE_A): STRING
588 -- Associated name to for naming in generic derivation.
589 do
590 Result := il_type_name (Void, a_context_type)
591 end
592
593 dispatch_anchors (a_context_class: CLASS_C)
594 -- <Original>
595 local
596 i, count: INTEGER
597 do
598 from
599 i := 1
600 count := generics.count
601 until
602 i > count
603 loop
604 generics.i_th (i).dispatch_anchors (a_context_class)
605 i := i + 1
606 end
607 end
608
609 feature {TYPE_A} -- Helpers
610
611 valid_generic (a_context_class: CLASS_C; type: CL_TYPE_A; a_in_generic: BOOLEAN): BOOLEAN
612 -- Check generic parameters
613 local
614 i, count: INTEGER
615 gen_type: GEN_TYPE_A
616 gen_type_generics: like generics
617 do
618 if class_id = type.class_id then
619 gen_type ?= type
620 if gen_type /= Void then
621 from
622 i := 1
623 gen_type_generics := gen_type.generics
624 count := generics.count
625 Result := count = gen_type_generics.count
626 until
627 i > count or else not Result
628 loop
629 Result := gen_type_generics.i_th (i).
630 internal_conform_to (a_context_class, generics.i_th (i), True)
631 i := i + 1
632 end
633 end
634 else
635 -- `type' is a descendant type of Current: so we
636 -- have to check the current generic parameters
637 Result := type.generic_conform_to (a_context_class, Current, a_in_generic)
638 end
639 end
640
641 internal_is_valid_for_class (a_class: CLASS_C): BOOLEAN
642 local
643 l_class: like base_class
644 l_generics: like generics
645 i, nb: INTEGER
646 do
647 l_class := base_class
648 l_generics := generics
649 nb := l_generics.count
650 if
651 l_class /= Void and then l_class.is_valid and then
652 (l_class.is_expanded = (class_declaration_mark = expanded_mark)) and then
653 ((l_class.generics /= Void and then l_class.generics.count = nb) or is_tuple)
654 then
655 from
656 Result := True
657 i := 1
658 nb := generics.count
659 until
660 i > nb
661 loop
662 if not generics.i_th (i).internal_is_valid_for_class (a_class) then
663 Result := False
664 i := nb + 1
665 else
666 i := i + 1
667 end
668 end
669 end
670 end
671
672 enumerate_interfaces_recursively (processor: PROCEDURE [ANY, TUPLE [CLASS_TYPE]]; n: INTEGER)
673 -- Enumerate all class types for which an object of this type can be attached to
674 -- using `n' as an upper bound for generic parameters that can be changed.
675 require
676 processor_attached: processor /= Void
677 valid_n: 1 <= n and n <= generics.count
678 local
679 gen_type: GEN_TYPE_A
680 parameter: TYPE_A
681 other_parameter: TYPE_A
682 cl_type: CL_TYPE_A
683 l_types: TYPE_LIST
684 cursor: ARRAYED_LIST_CURSOR
685 i: INTEGER
686 do
687 -- Enumerate types where expanded parameters are replaced with reference ones.
688 -- Take into account only registered generic derivations.
689 if n > 4 then
690 -- It's faster to scan registered class types rather than to generate conforming ones.
691 from
692 l_types := base_class.types
693 cursor := l_types.cursor
694 l_types.start
695 until
696 l_types.after
697 loop
698 cl_type := l_types.item.type
699 -- Check only types that differ from current one.
700 if cl_type /= Current then
701 gen_type ?= cl_type
702 check
703 gen_type_attached: gen_type /= Void
704 end
705 -- Ensure the type is reference.
706 if gen_type.is_reference then
707 from
708 i := generics.count
709 until
710 i <= 0
711 loop
712 parameter := generics.i_th (i)
713 other_parameter := gen_type.generics.i_th (i)
714 if
715 parameter.same_as (other_parameter) or else
716 parameter.is_expanded and then other_parameter.is_formal
717 then
718 -- Continue processing.
719 else
720 -- Types differ. Stop processing.
721 i := 0
722 end
723 i := i - 1
724 end
725 if i = 0 then
726 processor.call ([l_types.item])
727 end
728 end
729 end
730 l_types.forth
731 end
732 l_types.go_to (cursor)
733 else
734 from
735 i := n
736 until
737 i <= 0
738 loop
739 parameter := generics [i]
740 if parameter.is_expanded then
741 gen_type := duplicate_for_instantiation
742 gen_type.set_reference_mark
743 -- We replace the generics at position `i' by a FORMAL_A which simply
744 -- states that this is the generic derivation with reference in it.
745 gen_type.generics [i] := create {FORMAL_A}.make (False, False, i)
746 if base_class.types.has_type (Void, gen_type) then
747 processor.call ([gen_type.associated_class_type (Void)])
748 end
749 if i > 1 then
750 gen_type.enumerate_interfaces_recursively (processor, i - 1)
751 end
752 end
753 i := i - 1
754 end
755 end
756 end
757
758 internal_generic_derivation (a_level: INTEGER): like Current
759 -- Precise generic derivation of current type.
760 local
761 i, count: INTEGER
762 l_generics, l_new_generics: like generics
763 l_attachment_bits: like attachment_bits
764 l_variant_bits: like variant_bits
765 s: like has_separate_mark
766 l_type: TYPE_A
767 do
768 from
769 -- Duplicate current without the attachment and separateness information
770 -- since it does not matter for a generic derivation.
771 l_attachment_bits := attachment_bits
772 l_variant_bits := variant_bits
773 attachment_bits := 0
774 variant_bits := 0
775 s := has_separate_mark
776 has_separate_mark := False
777 Result := duplicate_for_instantiation
778 has_separate_mark := s
779 attachment_bits := l_attachment_bits
780 variant_bits := l_variant_bits
781
782 l_generics := generics
783 l_new_generics := Result.generics
784 i := 1
785 count := l_generics.count
786 until
787 i > count
788 loop
789 l_type := l_generics.i_th (i)
790 if l_type.actual_type.is_formal or l_type.is_reference then
791 if a_level = 0 then
792 -- We are now analyzing the B part in A [B]
793 l_new_generics.put_i_th (create {FORMAL_A}.make (False, False, i), i)
794 else
795 -- We are now analyzing the X part in A [B [X]]
796 -- which can only happen if B [X] is expanded. In that case, we
797 -- cannot store the formal if there is one, we will simply use
798 -- the constraint instead. If the constraint is a multi-constraint
799 -- we put the first constraint in the list as we use this for sorting
800 -- the CLASS_TYPE for code generation (See eweasel test#multicon060).
801 if base_class.generics.i_th (i).is_multi_constrained (base_class.generics) then
802 l_new_generics.put_i_th (base_class.constrained_types (i).first.type, i)
803 else
804 l_new_generics.put_i_th (base_class.constrained_type (i).as_marks_free, i)
805 end
806 end
807 else
808 -- We have a basic type, as an optimization, we
809 -- store the basic type data, rather than a formal
810 -- generic paramter to save some time at run-time
811 -- when computing the dynamic type.
812 l_new_generics.put_i_th (l_type.internal_generic_derivation (a_level + 1), i)
813 end
814 i := i + 1
815 end
816 end
817
818 internal_same_generic_derivation_as (current_type, other: TYPE_A; a_level: INTEGER): BOOLEAN
819 local
820 i, nb: INTEGER
821 l_generics, l_other_generics: like generics
822 l_type: TYPE_A
823 l_formal: FORMAL_A
824 do
825 if
826 same_type (other) and then attached {like Current} other as l_gen_type_i and then
827 l_gen_type_i.class_id = class_id and then
828 -- 'class_id' is the same therefore we can compare 'declaration_mark'.
829 -- If 'declaration_mark' is not the same for both then we have to make sure
830 -- that both expanded and separate states are identical.
831 (l_gen_type_i.declaration_mark /= declaration_mark implies
832 l_gen_type_i.is_expanded = is_expanded)
833 then
834 from
835 i := 1
836 l_generics := generics
837 nb := l_generics.count
838 l_other_generics := l_gen_type_i.generics
839 Result := nb = l_other_generics.count
840 until
841 i > nb or else not Result
842 loop
843 l_type := l_generics.i_th (i)
844 -- We use `actual_type' here because if this is an anchor, then we need to know
845 -- if the anchor is a formal since it is crucial for the comparison.
846 if l_type.actual_type.is_formal and current_type /= Void then
847 -- It is a formal, so we need to instantiate the formal in the
848 -- context of the current type. For example, we are looking for
849 -- the class type of A [G] in the context of B [INTEGER], thus
850 -- G is INTEGER. If we were not doing that, we would have to
851 -- create additional objects.
852 l_formal ?= l_type.actual_type
853 l_type := current_type.generics.i_th (l_formal.position)
854 end
855 if current_type /= Void and then attached {LIKE_CURRENT} l_type.actual_type as l_like_current then
856 -- If actual generic parameter is `like Current' and that we have a context type, then
857 -- its type is clearly the context type `current_type'.
858 l_type := current_type
859 end
860 if l_type.actual_type.is_formal or l_type.is_reference then
861 if a_level = 0 then
862 -- We are now comparing the B part in A [B]
863 l_formal ?= l_other_generics.i_th (i)
864 Result := l_formal /= Void and then l_formal.position = i
865 else
866 -- We are now analyzing the X part in A [B [X]]
867 -- which can only happen if B [X] is expanded. In that case
868 -- we just check that for X the corresponding actual in `other' is
869 -- also a reference.
870 Result := l_other_generics.i_th (i).is_reference
871 end
872 else
873 Result := l_type.internal_same_generic_derivation_as (current_type, l_other_generics.i_th (i), a_level + 1)
874 end
875 i := i + 1
876 end
877 end
878 end
879
880 feature -- Primitives
881
882 generate_error_from_creation_constraint_list (a_context_class: CLASS_C; a_context_feature: FEATURE_I; a_location_as: LOCATION_AS)
883 -- Generated a VTCG7 error if there are any constraint errors.
884 -- Otherwise it does nothing.
885 require
886 not_constraint_error_list_is_void: constraint_error_list /= Void
887 local
888 l_vtcg7: VTCG7
889 do
890 if not constraint_error_list.is_empty then
891 -- The feature listed in the creation constraint have
892 -- not been declared in the constraint class.
893 create l_vtcg7
894 if a_location_as /= Void then
895 l_vtcg7.set_location (a_location_as)
896 end
897 if a_context_class /= Void then
898 l_vtcg7.set_class (a_context_class)
899 end
900 l_vtcg7.set_error_list (constraint_error_list)
901 l_vtcg7.set_parent_type (Current)
902 if a_context_feature /= Void then
903 l_vtcg7.set_feature (a_context_feature)
904 l_vtcg7.set_written_class (a_context_feature.written_class)
905 end
906 Error_handler.insert_error (l_vtcg7)
907 end
908 end
909
910 update_dependance (feat_depend: FEATURE_DEPENDANCE)
911 -- Update dependency for Dead Code Removal
912 local
913 i, count: INTEGER
914 do
915 from
916 i := 1
917 count := generics.count
918 until
919 i > count
920 loop
921 generics.i_th (i).update_dependance (feat_depend)
922 i := i + 1
923 end
924 end
925
926 set_generics (g: like generics)
927 -- Assign `g' to `generics'.
928 require
929 g_not_void: g /= Void
930 do
931 generics := g
932 ensure
933 generics_set: generics = g
934 end
935
936 has_expanded: BOOLEAN
937 -- Are some expanded type in the current generic declaration ?
938 local
939 i, count: INTEGER
940 do
941 from
942 Result := is_expanded
943 i := 1
944 count := generics.count
945 until
946 i > count or else Result
947 loop
948 Result := generics.i_th (i).has_expanded
949 i := i + 1
950 end
951 end
952
953 is_full_named_type: BOOLEAN
954 -- Is Current a fully named type?
955 local
956 i, nb: INTEGER
957 do
958 from
959 i := 1
960 nb := generics.count + 1
961 Result := True
962 until
963 i = nb
964 loop
965 if not generics.i_th (i).is_full_named_type then
966 Result := False
967 i := nb - 1
968 end
969 i := i + 1
970 end
971 end
972
973 has_formal_generic: BOOLEAN
974 -- Has type a formal generic parameter?
975 local
976 i, count: INTEGER
977 do
978 from
979 i := 1
980 count := generics.count
981 until
982 i > count or else Result
983 loop
984 Result := generics.i_th (i).has_formal_generic
985 i := i + 1
986 end
987 end
988
989 is_loose: BOOLEAN
990 -- Does type depend on formal generic parameters and/or anchors?
991 local
992 g: like generics
993 i: INTEGER
994 do
995 from
996 g := generics
997 i := g.count
998 until
999 i <= 0 or else Result
1000 loop
1001 Result := g.i_th (i).is_loose
1002 i := i - 1
1003 end
1004 end
1005
1006 deep_actual_type: like Current
1007 -- Actual type of Current; recursive version for generics
1008 local
1009 i: INTEGER
1010 l_old_generics, l_new_generics: like generics
1011 l_prev_type, l_new_type: TYPE_A
1012 do
1013 Result := Current
1014 from
1015 l_old_generics := Result.generics
1016 i := l_old_generics.count
1017 until
1018 i <= 0
1019 loop
1020 l_prev_type := l_old_generics.i_th (i)
1021 l_new_type := l_prev_type.deep_actual_type
1022 if l_prev_type /= l_new_type then
1023 if l_new_generics = Void then
1024 -- Void modifying original type.
1025 Result := Result.duplicate_for_instantiation
1026 l_new_generics := Result.generics
1027 end
1028 l_new_generics.put_i_th (l_new_type, i)
1029 end
1030 i := i - 1
1031 end
1032 end
1033
1034 context_free_type: like Current
1035 -- Actual type of Current; recursive version for generics
1036 local
1037 i: INTEGER
1038 l_old_generics, l_new_generics: like generics
1039 l_prev_type, l_new_type: TYPE_A
1040 do
1041 Result := Current
1042 from
1043 l_old_generics := Result.generics
1044 i := l_old_generics.count
1045 until
1046 i <= 0
1047 loop
1048 l_prev_type := l_old_generics.i_th (i)
1049 l_new_type := l_prev_type.context_free_type
1050 if l_prev_type /= l_new_type then
1051 if l_new_generics = Void then
1052 -- Void modifying original type.
1053 Result := Result.duplicate_for_instantiation
1054 l_new_generics := Result.generics
1055 end
1056 l_new_generics.put_i_th (l_new_type, i)
1057 end
1058 i := i - 1
1059 end
1060 end
1061
1062 actual_argument_type (a_arg_types: ARRAYED_LIST [TYPE_A]): like Current
1063 local
1064 i: INTEGER
1065 l_old_generics, l_new_generics: like generics
1066 l_prev_type, l_new_type: TYPE_A
1067 do
1068 Result := Current
1069 from
1070 l_old_generics := Result.generics
1071 i := l_old_generics.count
1072 until
1073 i <= 0
1074 loop
1075 l_prev_type := l_old_generics.i_th (i)
1076 l_new_type := l_prev_type.actual_argument_type (a_arg_types)
1077 if l_prev_type /= l_new_type then
1078 if l_new_generics = Void then
1079 -- Void modifying original type.
1080 Result := Result.duplicate_for_instantiation
1081 l_new_generics := Result.generics
1082 end
1083 l_new_generics.put_i_th (l_new_type, i)
1084 end
1085 i := i - 1
1086 end
1087 end
1088
1089 formal_instantiation_in (type: TYPE_A; constraint: TYPE_A; written_id: INTEGER): GEN_TYPE_A
1090 -- <Precursor>
1091 local
1092 i: INTEGER
1093 old_generics: like generics
1094 new_generics: like generics
1095 old_type: TYPE_A
1096 new_type: TYPE_A
1097 do
1098 Result := Current
1099 from
1100 old_generics := Result.generics
1101 i := old_generics.count
1102 until
1103 i <= 0
1104 loop
1105 old_type := old_generics.i_th (i)
1106 new_type := old_type.formal_instantiation_in (type, constraint, written_id)
1107 if new_type /= old_type then
1108 -- Record a new type of a generic parameter.
1109 if new_generics = Void then
1110 -- Avoid modifying original type descriptor.
1111 Result := Result.duplicate_for_instantiation
1112 new_generics := Result.generics
1113 end
1114 new_generics.put_i_th (new_type, i)
1115 end
1116 i := i - 1
1117 end
1118 end
1119
1120 instantiation_in (type: TYPE_A; written_id: INTEGER): GEN_TYPE_A
1121 -- TODO: new comment
1122 local
1123 i: INTEGER
1124 old_generics: like generics
1125 new_generics: like generics
1126 old_type: TYPE_A
1127 new_type: TYPE_A
1128 do
1129 Result := Current
1130 from
1131 old_generics := Result.generics
1132 i := old_generics.count
1133 until
1134 i <= 0
1135 loop
1136 old_type := old_generics.i_th (i)
1137 new_type := old_type.instantiation_in (type, written_id)
1138 if new_type /= old_type then
1139 -- Record a new type of a generic parameter.
1140 if new_generics = Void then
1141 -- Avoid modifying original type descriptor.
1142 Result := Result.duplicate_for_instantiation
1143 new_generics := Result.generics
1144 end
1145 new_generics.put_i_th (new_type, i)
1146 end
1147 i := i - 1
1148 end
1149 end
1150
1151 adapted_in (a_class_type: CLASS_TYPE): GEN_TYPE_A
1152 local
1153 i, nb: INTEGER
1154 l_generics, l_new_generics: like generics
1155 l_old_generic, l_new_generic: TYPE_A
1156 do
1157 from
1158 l_generics := generics
1159 i := 1
1160 nb := l_generics.count
1161 until
1162 i > nb
1163 loop
1164 l_old_generic := l_generics.i_th (i)
1165 l_new_generic := l_old_generic.adapted_in (a_class_type)
1166 if l_old_generic /= l_new_generic then
1167 if Result = Void then
1168 Result := duplicate_for_instantiation
1169 l_new_generics := Result.generics
1170 end
1171 l_new_generics.put_i_th (l_new_generic, i)
1172 end
1173 i := i + 1
1174 end
1175 if Result = Void then
1176 Result := Current
1177 end
1178 end
1179
1180 skeleton_adapted_in (a_class_type: CLASS_TYPE): GEN_TYPE_A
1181 local
1182 i, nb: INTEGER
1183 l_generics, l_new_generics: like generics
1184 l_old_generic, l_new_generic: TYPE_A
1185 do
1186 from
1187 l_generics := generics
1188 i := 1
1189 nb := l_generics.count
1190 until
1191 i > nb
1192 loop
1193 l_old_generic := l_generics.i_th (i)
1194 l_new_generic := l_old_generic.skeleton_adapted_in (a_class_type)
1195 if l_old_generic /= l_new_generic then
1196 if Result = Void then
1197 Result := duplicate_for_instantiation
1198 l_new_generics := Result.generics
1199 end
1200 l_new_generics.put_i_th (l_new_generic, i)
1201 end
1202 i := i + 1
1203 end
1204 if Result = Void then
1205 Result := Current
1206 end
1207 end
1208
1209 formal_instantiated_in (class_type: TYPE_A): GEN_TYPE_A
1210 -- Instantiation of Current in the context of `class_type'
1211 -- assuming that Current is written in the associated class
1212 -- of `class_type'.
1213 local
1214 i, nb: INTEGER
1215 l_generics, l_new_generics: like generics
1216 l_old_generic, l_new_generic: TYPE_A
1217 do
1218 from
1219 l_generics := generics
1220 i := 1
1221 nb := l_generics.count
1222 until
1223 i > nb
1224 loop
1225 l_old_generic := l_generics.i_th (i)
1226 l_new_generic := l_old_generic.formal_instantiated_in (class_type)
1227 if l_old_generic /= l_new_generic then
1228 if Result = Void then
1229 Result := duplicate_for_instantiation
1230 l_new_generics := Result.generics
1231 end
1232 l_new_generics.put_i_th (l_new_generic, i)
1233 end
1234 i := i + 1
1235 end
1236 if Result = Void then
1237 Result := Current
1238 end
1239 end
1240
1241 instantiated_in (class_type: TYPE_A): GEN_TYPE_A
1242 -- Instantiation of Current in the context of `class_type'
1243 -- assuming that Current is written in the associated class
1244 -- of `class_type'.
1245 local
1246 i, nb: INTEGER
1247 l_generics, l_new_generics: like generics
1248 l_old_generic, l_new_generic: TYPE_A
1249 do
1250 from
1251 l_generics := generics
1252 i := 1
1253 nb := l_generics.count
1254 until
1255 i > nb
1256 loop
1257 l_old_generic := l_generics.i_th (i)
1258 l_new_generic := l_old_generic.instantiated_in (class_type)
1259 if l_old_generic /= l_new_generic then
1260 if Result = Void then
1261 Result := duplicate_for_instantiation
1262 l_new_generics := Result.generics
1263 end
1264 l_new_generics.put_i_th (l_new_generic, i)
1265 end
1266 i := i + 1
1267 end
1268 if Result = Void then
1269 Result := Current
1270 end
1271 end
1272
1273 evaluated_type_in_descendant (a_ancestor, a_descendant: CLASS_C; a_feature: FEATURE_I): like Current
1274 local
1275 i, nb: INTEGER
1276 l_generics, l_new_generics: like generics
1277 l_old_generic, l_new_generic: TYPE_A
1278 do
1279 if a_ancestor /= a_descendant then
1280 if is_loose then
1281 from
1282 l_generics := generics
1283 nb := l_generics.count
1284 i := 1
1285 until
1286 i > nb
1287 loop
1288 l_old_generic := l_generics.i_th (i)
1289 l_new_generic := l_old_generic.evaluated_type_in_descendant (a_ancestor, a_descendant, a_feature)
1290 if l_old_generic /= l_new_generic then
1291 if Result = Void then
1292 Result := duplicate_for_instantiation
1293 l_new_generics := Result.generics
1294 end
1295 l_new_generics.put_i_th (l_new_generic, i)
1296 end
1297 i := i + 1
1298 end
1299 if Result = Void then
1300 Result := Current
1301 end
1302 else
1303 Result := Current
1304 end
1305 else
1306 Result := Current
1307 end
1308 end
1309
1310 parent_type (parent: CL_TYPE_A): TYPE_A
1311 -- Parent actual type in the current context
1312 do
1313 Result := instantiate (parent)
1314 end
1315
1316 instantiate (type: TYPE_A): TYPE_A
1317 -- Instantiates `type'. Given that `type' may hold
1318 -- some formal generics, instantiate them with the
1319 -- generics from Current.
1320 require
1321 good_argument: type /= Void
1322 local
1323 i, count: INTEGER
1324 gen_type: GEN_TYPE_A
1325 gen_type_generics: like generics
1326 l_old_generic, l_new_generic: TYPE_A
1327 formal_type: FORMAL_A
1328 l_like_type: LIKE_TYPE_A
1329 do
1330 formal_type ?= type
1331 if formal_type /= Void then
1332 -- Instantiation of a formal generic
1333 Result := generics.i_th (formal_type.position).actual_type
1334 elseif type.is_like then
1335 -- We do not want to loose the fact that it is an anchor
1336 -- as otherwise we would break eweasel test exec206, but we
1337 -- still need to adapt its actual_type to the current context
1338 -- otherwise we would break valid168.
1339 l_like_type ?= type.duplicate
1340 check
1341 l_like_type_not_void: l_like_type /= Void
1342 end
1343 l_like_type.set_actual_type (instantiate (l_like_type.conformance_type))
1344 Result := l_like_type
1345 elseif type.has_generics then
1346 -- Instantiation of the generic parameter of `type'
1347 gen_type ?= type
1348 from
1349 i := 1
1350 gen_type_generics := gen_type.generics
1351 count := gen_type_generics.count
1352 until
1353 i > count
1354 loop
1355 l_old_generic := gen_type_generics [i]
1356 l_new_generic := instantiate (l_old_generic)
1357 if l_old_generic /= l_new_generic then
1358 -- If a new object is generated as a result of the generic type instantiation
1359 -- then we need to duplicate `gen_type'.
1360 if Result = Void then
1361 Result := gen_type.duplicate_for_instantiation
1362 gen_type_generics := Result.generics
1363 end
1364 gen_type_generics [i] := l_new_generic
1365 end
1366 i := i + 1
1367 end
1368 end
1369 if Result = Void then
1370 Result := type
1371 end
1372 end
1373
1374 has_like: BOOLEAN
1375 -- Has the type anchored type in its definition ?
1376 local
1377 i, count: INTEGER
1378 do
1379 from
1380 i := 1
1381 count := generics.count
1382 until
1383 i > count or else Result
1384 loop
1385 Result := generics.i_th (i).has_like
1386 i := i + 1
1387 end
1388 end
1389
1390 has_like_argument: BOOLEAN
1391 -- Has the type like argument in its definition?
1392 local
1393 i, count: INTEGER
1394 do
1395 from
1396 i := 1
1397 count := generics.count
1398 until
1399 i > count or else Result
1400 loop
1401 Result := generics.i_th (i).has_like_argument
1402 i := i + 1
1403 end
1404 end
1405
1406 has_like_Current: BOOLEAN
1407 -- <Precursor>
1408 local
1409 i, count: INTEGER
1410 do
1411 from
1412 i := 1
1413 count := generics.count
1414 until
1415 i > count or else Result
1416 loop
1417 Result := generics.i_th (i).has_like_current
1418 i := i + 1
1419 end
1420 end
1421
1422 is_known: BOOLEAN
1423 -- <Precursor>
1424 local
1425 i, count: INTEGER
1426 do
1427 from
1428 i := 1
1429 count := generics.count
1430 Result := True
1431 until
1432 i > count or else not Result
1433 loop
1434 Result := generics.i_th (i).is_known
1435 i := i + 1
1436 end
1437 end
1438
1439 duplicate: like Current
1440 -- Duplication
1441 local
1442 i, count: INTEGER
1443 duplicate_generics: like generics
1444 do
1445 from
1446 i := 1
1447 count := generics.count
1448 create duplicate_generics.make (count)
1449 until
1450 i > count
1451 loop
1452 duplicate_generics.extend (generics.i_th (i).duplicate)
1453 i := i + 1
1454 end
1455 Result := twin
1456 Result.set_generics (duplicate_generics)
1457 end
1458
1459 duplicate_for_instantiation: like Current
1460 -- Duplication for instantiation routines.
1461 do
1462 Result := twin
1463 -- We do not need to duplicate types in generics as this is handled
1464 -- by the instantiation routines.
1465 Result.set_generics (generics.twin)
1466 end
1467
1468 good_generics: BOOLEAN
1469 -- Has the base class exactly the same number of generic
1470 -- parameters in its formal generic declarations?
1471 local
1472 base_generics: EIFFEL_LIST [FORMAL_DEC_AS]
1473 i, generic_count: INTEGER
1474 do
1475 base_generics := base_class.generics
1476 if base_generics /= Void then
1477 generic_count := base_generics.count
1478 Result := generic_count = generics.count
1479 from
1480 i := 1
1481 until
1482 i > generic_count or else not Result
1483 loop
1484 Result := generics.i_th (i).good_generics
1485 i := i + 1
1486 end
1487 end
1488 end
1489
1490 check_labels (a_context_class: CLASS_C; a_node: TYPE_AS)
1491 -- <Precursor>
1492 local
1493 i, nb: INTEGER
1494 l_generics: like generics
1495 do
1496 from
1497 l_generics := generics
1498 i := l_generics.lower
1499 nb := l_generics.upper
1500 until
1501 i > nb
1502 loop
1503 l_generics.i_th (i).check_labels (a_context_class, a_node)
1504 i := i + 1
1505 end
1506 end
1507
1508 error_generics: VTUG
1509 -- Returns the first error regarding the number of generic parameters
1510 -- compared to the formal generic declarations.
1511 --| Recursion is done to find all errors.
1512 local
1513 base_generics: EIFFEL_LIST [FORMAL_DEC_AS]
1514 i, generic_count: INTEGER
1515 do
1516 -- We could avoid having this check but the precondition does not tell us
1517 -- we can.
1518 if base_class /= Void then
1519 base_generics := base_class.generics
1520 if base_generics /= Void then
1521 generic_count := base_generics.count
1522 if (generic_count = generics.count) then
1523 from
1524 i := 1
1525 until
1526 i > generic_count or else (Result /= Void)
1527 loop
1528 if not generics.i_th (i).good_generics then
1529 Result := generics.i_th (i).error_generics
1530 end
1531 i := i + 1
1532 end
1533 end
1534 end
1535 if Result = Void then
1536 if base_generics = Void then
1537 create {VTUG1} Result
1538 else
1539 create {VTUG2} Result
1540 end
1541 Result.set_type (Current)
1542 Result.set_base_class (base_class)
1543 end
1544 end
1545 end
1546
1547 check_constraints (a_type_context: CLASS_C; a_context_feature: FEATURE_I; a_check_creation_readiness: BOOLEAN)
1548 -- Check the constrained genericity validity rule
1549 --| We check for all generic parameters whether they fullfill their constraints:
1550 --| * conformance to all the constraining types
1551 --| * providing creations routines to meet all creation constraints
1552 local
1553 i, nb: INTEGER
1554 do
1555 -- Check all actual generic parameters against their constraining types.
1556 from
1557 i := 1
1558 nb := generics.count
1559 until
1560 i > nb
1561 loop
1562 check_one_constraint (a_type_context, a_context_feature, a_check_creation_readiness, i)
1563 i := i + 1
1564 end
1565 end
1566
1567 check_one_constraint (a_type_context: CLASS_C; a_context_feature: FEATURE_I; a_check_creation_readiness: BOOLEAN; i: INTEGER)
1568 -- Check the constrained genericity validity rule for the `i'-th generic paramenter.
1569 --| We check that it fullfills its constraints:
1570 --| * conformance to all the constraining types
1571 --| * providing creations routines to meet all creation constraints
1572 local
1573 l_class: CLASS_C
1574 l_constraints: TYPE_SET_A
1575 l_constraint_item: TYPE_A
1576 l_formal_constraint: FORMAL_A
1577 l_generic_constraint: GEN_TYPE_A
1578 l_generic_parameters: like generics
1579 l_formal_generic_parameter: FORMAL_A
1580 l_generic_parameter: TYPE_A
1581 l_conform: BOOLEAN
1582 l_formal_as: FORMAL_AS
1583 l_formal_dec_as: FORMAL_CONSTRAINT_AS
1584 l_check_creation_readiness: BOOLEAN
1585 do
1586 l_conform := True
1587 l_class := base_class
1588 l_generic_parameters := generics
1589
1590 l_generic_parameter := l_generic_parameters.i_th(i)
1591 l_constraints := l_class.constraints (i)
1592 from
1593 l_constraints.start
1594 until
1595 l_constraints.after
1596 loop
1597 l_constraint_item := l_constraints.item.type
1598 if l_constraint_item.is_formal then
1599 l_formal_constraint ?= l_constraint_item
1600 check l_formal_constraint /= Void end
1601 -- Replace the formal with its 'instantiation' of the current generic derivation.
1602 --| `l_constraint_item' can indeed still be a formal, but now has to be resolved by using `a_type_context'
1603 l_constraint_item := l_generic_parameters.i_th (l_formal_constraint.position)
1604 elseif l_constraint_item.has_generics and then not l_constraint_item.generics.is_empty then
1605 -- We substitude all occurrences of formals in the constraint with the instantiation of the corresponding formal in our generic derivation.
1606 l_generic_constraint ?= l_constraint_item.deep_twin
1607 l_generic_constraint.substitute (l_generic_parameters)
1608 l_constraint_item := l_generic_constraint
1609 end
1610 --| Knowing that formals (FORMAL_A) just take of their "layers" and fall back to their constraints and ask and ask again until they match.
1611 --| Example: [G -> H, H -> I, I -> J] Question: Is G conform to J? Answer of `conform_to' is yes.
1612 --| Knowing that there is no recursion in such a case: X -> LIST[X] because either the input really matches LIST and then we _have_ to continue or then it does not and we stop.
1613 l_formal_as := l_class.generics.i_th (i).formal
1614 if l_generic_parameter.conformance_type.internal_conform_to (a_type_context, l_constraint_item, False) and then
1615 (l_formal_as.is_expanded implies l_generic_parameter.is_expanded) and then
1616 (l_formal_as.is_reference implies l_generic_parameter.is_reference) and then
1617 (l_formal_as.has_frozen_mark implies l_generic_parameter.is_frozen)
1618 then
1619 -- Everything is fine, we conform
1620 else
1621 -- We do not conform, insert an error for this type.
1622 l_conform := False
1623 generate_constraint_error (Current, l_generic_parameter.to_type_set, l_constraint_item.to_type_set, i, Void)
1624 end
1625
1626 l_constraints.forth
1627 end
1628 if l_conform then
1629 -- Check now for the validity of the creation constraint clause if
1630 -- there is one which can be checked, i.e. when `to_check' conforms
1631 -- to `constraint_type'.
1632 l_formal_dec_as ?= l_class.generics.i_th (i)
1633 check l_formal_dec_as_not_void: l_formal_dec_as /= Void end
1634 if l_formal_dec_as.has_creation_constraint and (system.check_generic_creation_constraint and a_check_creation_readiness) then
1635 -- If we are not in degree 3 (i.e. 4), we cannot have a
1636 -- complete check since if we are currently checking an attribute
1637 -- of TEST declared as A [TOTO], maybe TOTO has not yet been recompiled?
1638 -- So we store all the needed information and we will do a check at the
1639 -- end of the degree 4 (look at PASS2 for the code which does the checking).
1640 l_formal_generic_parameter ?= l_generic_parameter.conformance_type
1641 -- We have a creation constraint so in case a check was requested we have to continue checking it.
1642 l_check_creation_readiness := a_check_creation_readiness
1643 if System.in_pass3 then
1644 creation_constraint_check (
1645 l_formal_dec_as, l_constraints, a_type_context,
1646 l_generic_parameter, i, l_formal_generic_parameter)
1647 else
1648 add_future_checking (a_type_context,
1649 agent delayed_creation_constraint_check (a_type_context, a_context_feature,
1650 l_generic_parameter, l_constraints, i, l_formal_generic_parameter))
1651 end
1652 else
1653 -- We do not have a creation constraint, so stop checking for it.
1654 l_check_creation_readiness := False
1655 end
1656 end
1657 if l_generic_parameter.has_generics then
1658 -- Recursion
1659 l_generic_parameter.check_constraints (a_type_context, a_context_feature, l_check_creation_readiness)
1660 end
1661 end
1662
1663 substitute (new_generics: like generics)
1664 -- Take the arguments from `new_generics' to create an
1665 -- effective representation of the current GEN_TYPE
1666 require
1667 new_generics_not_void: new_generics /= Void
1668 local
1669 i, count, pos: INTEGER
1670 constraint_type: TYPE_A
1671 formal_type: FORMAL_A
1672 gen_type: GEN_TYPE_A
1673 do
1674 from
1675 i := 1
1676 count := generics.count
1677 until
1678 i > count
1679 loop
1680 constraint_type := generics.i_th (i)
1681
1682 if constraint_type.is_formal then
1683 formal_type ?= constraint_type
1684 pos := formal_type.position
1685 generics.put_i_th (new_generics.i_th (pos), i)
1686 elseif constraint_type.generics /= Void then
1687 gen_type ?= constraint_type
1688 gen_type.substitute (new_generics)
1689 end
1690 i := i + 1
1691 end
1692 end
1693
1694 delayed_creation_constraint_check (
1695 context_class: CLASS_C;
1696 a_context_feature: FEATURE_I;
1697 to_check: TYPE_A
1698 constraint_type: TYPE_SET_A
1699 i: INTEGER;
1700 formal_type: FORMAL_A)
1701 -- Check that declaration of generic class is conform to
1702 -- defined creation constraint in delayed mode.
1703 require
1704 to_check_is_formal_implies_formal_type_not_void: to_check.conformance_type.is_formal implies formal_type /= Void
1705 local
1706 l_formal_dec_as: FORMAL_CONSTRAINT_AS
1707 do
1708 reset_constraint_error_list
1709 -- Some delay checks involves classes that are not in the system anymore,
1710 -- in that case there is nothing to check.
1711 if
1712 is_valid and then context_class.is_valid and then to_check /= Void and then to_check.is_valid and then
1713 base_class.generics.valid_index (i)
1714 then
1715 l_formal_dec_as ?= base_class.generics.i_th (i)
1716 check l_formal_dec_as_not_void: l_formal_dec_as /= Void end
1717 if l_formal_dec_as.has_creation_constraint then
1718 creation_constraint_check (l_formal_dec_as, constraint_type, context_class, to_check, i, formal_type)
1719 generate_error_from_creation_constraint_list (context_class, a_context_feature, l_formal_dec_as.start_location )
1720 end
1721 end
1722 end
1723
1724 creation_constraint_check (
1725 formal_dec_as: FORMAL_CONSTRAINT_AS
1726 a_constraint_types: TYPE_SET_A;
1727 context_class: CLASS_C;
1728 to_check: TYPE_A;
1729 i: INTEGER;
1730 formal_type: FORMAL_A)
1731 -- Check that declaration of generic class is conform to
1732 -- defined creation constraint.
1733 require
1734 formal_dec_as_not_void: formal_dec_as /= Void
1735 creation_constraint_exists: formal_dec_as.has_creation_constraint
1736 is_valid: is_valid
1737 local
1738 formal_type_dec_as: FORMAL_CONSTRAINT_AS
1739 formal_crc_list, crc_list: LINKED_LIST [TUPLE [type_item: RENAMED_TYPE_A; feature_item: FEATURE_I]];
1740 creators_table: HASH_TABLE [EXPORT_I, STRING]
1741 matched: BOOLEAN
1742 feat_tbl: FEATURE_TABLE
1743 class_c: CLASS_C
1744 other_feature_i, feature_i: FEATURE_I
1745 l_unmatched_features: LIST [FEATURE_I]
1746 do
1747
1748 -- If there is a creation constraint we are facing two different cases:
1749 -- * case 1: the declaration is using a real type `to_check', we check that
1750 -- the creation procedures listed in the constraint are indeed
1751 -- creation procedures of `to_check'.
1752 -- * case 2: the declaration is using a formal type. Let's take an example and
1753 -- I will explain what we need to do:
1754 -- we have:
1755 -- A[G -> C create make_1, make_2,..., make_n end]
1756 -- B [H, K -> MY_C create my_make_1, my_make_2,...my_make_m end]
1757 -- MY_C inherits from C
1758 -- In B, we have `a: A[K]', which is valid if:
1759 -- * MY_C conforms to C (already established here)
1760 -- * m >= n
1761 -- * for each `make_i' where 1 <= i <= n, there is a `j' (1 <= j <= m)
1762 -- where `my_make_k' is a redefined/renamed version of `make_i'.
1763 crc_list := formal_dec_as.constraint_creation_list (base_class)
1764 if formal_type = Void then
1765 -- We're in the case of a class type.
1766
1767 -- If it is a deferred class and the actual derivation uses like current
1768 -- we move the duty to check the creation constraint to the full class check to check
1769 -- the descendants of this deferred class, which can never be instantiated direclty.
1770 -- See bug#12464 and test#valid208/test#valid209 for more information.
1771 if to_check.is_like_current and context_class.is_deferred then
1772 -- We simply accept it.
1773 else
1774
1775 if to_check.has_associated_class then
1776 -- `to_check' may not have an associated class if it represents NONE type, for
1777 -- example in PROCEDURE [ANY, NONE], we will check NONE against
1778 -- constraint of PROCEDURE which is `TUPLE create default_create end'.
1779 class_c := to_check.base_class
1780 creators_table := class_c.creators
1781 end
1782
1783 -- A creation procedure has to be specified, so if none is
1784 -- specified or if there is no creation procedure in the class
1785 -- corresponding to `to_check', this is not valid.
1786 if
1787 creators_table /= Void and then not creators_table.is_empty
1788 then
1789 from
1790 crc_list.start
1791 feat_tbl := class_c.feature_table
1792 until
1793 crc_list.after
1794 loop
1795 -- Let's take one of the creation procedure defined in the constraint.
1796 feature_i := crc_list.item.feature_item
1797
1798 -- Take the redefined/renamed version of the previous version in the
1799 -- descendant class `to_check'/`class_c'.
1800 other_feature_i := feat_tbl.feature_of_rout_id (feature_i.rout_id_set.first)
1801
1802 -- Test if we found the specified feature name among the creation
1803 -- procedures of `class_c' and that it is exported to Current, since it
1804 -- it is Current that will create instances of the generic parameter.
1805 creators_table.search (other_feature_i.feature_name)
1806 if
1807 not creators_table.found or else
1808 not creators_table.found_item.valid_for (base_class)
1809 then
1810 if l_unmatched_features = Void then
1811 create {LINKED_LIST[FEATURE_I]} l_unmatched_features.make
1812 end
1813 l_unmatched_features.extend (feature_i)
1814 end
1815 crc_list.forth
1816 end
1817 else
1818 -- The class type does not have a creation clause:
1819 -- May be we are handling a case where the constraint only specfies
1820 -- `default_create', so let's check that the constraint defines
1821 -- `default_create' as creation procedure and that `creators_table'
1822 -- is Void (as empty means there is no way to create an instance of this
1823 -- class).
1824 -- At last we check that this class is not deferred.
1825 if
1826 creators_table = Void and then
1827 (crc_list.count = 1 and then formal_dec_as.has_default_create)
1828 then
1829 -- Ok, no error: We have no create clause which makes `default_create' available
1830 -- and the constraint demands only `default_create'
1831
1832 -- But maybe it is a deferred class?
1833 if class_c /= Void and then class_c.is_deferred then
1834 if l_unmatched_features = Void then
1835 create {LINKED_LIST[FEATURE_I]} l_unmatched_features.make
1836 end
1837 l_unmatched_features.extend (crc_list.first.feature_item)
1838 end
1839 else
1840 -- Generate list of features not matching constraint.
1841 from
1842 create {LINKED_LIST[FEATURE_I]} l_unmatched_features.make
1843 crc_list.start
1844 until
1845 crc_list.after
1846 loop
1847 -- If `creators_table' is not Void, it simply means we have an empty creation routine
1848 -- and therefore all the creation constraints are not met.
1849 -- If it is Void, then `{ANY}.default_create' is a valid creation routine, in that
1850 -- case we should not list `default_create' has not beeing met if listed in the creation
1851 -- constraint.
1852 feature_i := crc_list.item.feature_item
1853 if creators_table /= Void or else not feature_i.rout_id_set.has (system.default_create_rout_id) then
1854 l_unmatched_features.extend (feature_i)
1855 end
1856 crc_list.forth
1857 end
1858 end
1859 end
1860 -- We have an error if we have unmatched features.
1861 if l_unmatched_features /= Void then
1862 generate_constraint_error (Current, to_check.to_type_set, a_constraint_types, i, l_unmatched_features)
1863 end
1864 end
1865 else
1866 -- Check if there is a creation constraint clause
1867 formal_type_dec_as ?= context_class.generics.i_th (formal_type.position)
1868 if formal_type_dec_as /= Void and then formal_type_dec_as.has_creation_constraint then
1869 -- Check if we have m >= n as specified above.
1870 formal_crc_list := formal_type_dec_as.constraint_creation_list (context_class)
1871 if formal_crc_list.count >= crc_list.count then
1872 from
1873 crc_list.start
1874 matched := True
1875 until
1876 crc_list.after
1877 loop
1878 feature_i := crc_list.item.feature_item
1879 -- Check that all the creation procedures defined in the creation
1880 -- constraint clause `crc_list' are indeed present under a
1881 -- redefined/renamed version in the creation constraint clause
1882 from
1883 matched := False
1884 formal_crc_list.start
1885 until
1886 matched or else formal_crc_list.after
1887 loop
1888 matched := formal_crc_list.item.feature_item.rout_id_set.has (
1889 feature_i.rout_id_set.first)
1890 formal_crc_list.forth
1891 end
1892 -- If not matched save the feature to report a proper error.
1893 if not matched then
1894 if l_unmatched_features = Void then
1895 create {LINKED_LIST[FEATURE_I]} l_unmatched_features.make
1896 end
1897 l_unmatched_features.extend (feature_i)
1898 end
1899 crc_list.forth
1900 end
1901 else
1902 matched := False
1903 end
1904 else
1905 matched := False
1906 end
1907
1908 if not matched then
1909 generate_constraint_error (Current, formal_type.to_type_set, a_constraint_types, i, l_unmatched_features)
1910 end
1911 end
1912 end
1913
1914 expanded_deferred: BOOLEAN
1915 -- Are the expanded class types present in the current generic
1916 -- type not based on deferred classes ?
1917 local
1918 i, nb: INTEGER
1919 gen_param: TYPE_A
1920 do
1921 from
1922 Result := Precursor {CL_TYPE_A}
1923 i := 1
1924 nb := generics.count
1925 until
1926 i > nb or else Result
1927 loop
1928 gen_param := generics.i_th (i)
1929 if gen_param.has_expanded then
1930 Result := gen_param.expanded_deferred
1931 end
1932 i := i + 1
1933 end
1934 end
1935
1936 valid_expanded_creation (a_class: CLASS_C): BOOLEAN
1937 -- Is the expanded type has an associated class with one
1938 -- creation routine with no arguments only ?
1939 local
1940 i, nb: INTEGER
1941 gen_param: TYPE_A
1942 do
1943 from
1944 Result := Precursor {CL_TYPE_A} (a_class)
1945 i := 1
1946 nb := generics.count
1947 until
1948 i > nb or else not Result
1949 loop
1950 gen_param := generics.i_th (i)
1951 if gen_param.has_expanded then
1952 Result := gen_param.valid_expanded_creation (a_class)
1953 end
1954 i := i + 1
1955 end
1956 end
1957
1958 invariant
1959
1960 -- A generic class always has generic parameters
1961 generics_not_void: generics /= Void
1962
1963 note
1964 copyright: "Copyright (c) 1984-2014, Eiffel Software"
1965 license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)"
1966 licensing_options: "http://www.eiffel.com/licensing"
1967 copying: "[
1968 This file is part of Eiffel Software's Eiffel Development Environment.
1969
1970 Eiffel Software's Eiffel Development Environment is free
1971 software; you can redistribute it and/or modify it under
1972 the terms of the GNU General Public License as published
1973 by the Free Software Foundation, version 2 of the License
1974 (available at the URL listed under "license" above).
1975
1976 Eiffel Software's Eiffel Development Environment is
1977 distributed in the hope that it will be useful, but
1978 WITHOUT ANY WARRANTY; without even the implied warranty
1979 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1980 See the GNU General Public License for more details.
1981
1982 You should have received a copy of the GNU General Public
1983 License along with Eiffel Software's Eiffel Development
1984 Environment; if not, write to the Free Software Foundation,
1985 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1986 ]"
1987 source: "[
1988 Eiffel Software
1989 5949 Hollister Ave., Goleta, CA 93117 USA
1990 Telephone 805-685-1006, Fax 805-685-6869
1991 Website http://www.eiffel.com
1992 Customer support http://support.eiffel.com
1993 ]"
1994
1995 end -- class GEN_TYPE_A

Properties

Name Value
svn:eol-style native
svn:keywords Author Date ID Revision

  ViewVC Help
Powered by ViewVC 1.1.23