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

Contents of /branches/CAT_mono/Src/Eiffel/API/evaluated_type/gen_type_a.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 69687 - (show annotations)
Wed Jul 25 18:55:08 2007 UTC (12 years, 4 months ago) by martins
File size: 33434 byte(s)
* monomorph for formals
* covaraince for generics (syntax only)
1 indexing
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,
16 has_like, has_like_argument, is_loose, duplicate, type_i, good_generics,
17 error_generics, check_constraints, has_formal_generic, instantiated_in,
18 has_expanded, is_valid, expanded_deferred, valid_expanded_creation,
19 same_as, format, is_equivalent,
20 deep_actual_type, instantiation_in,
21 actual_argument_type, update_dependance, hash_code,
22 is_full_named_type, process, evaluated_type_in_descendant
23 end
24
25 create
26 make
27
28 feature {NONE} -- Initialization
29
30 make (a_class_id: INTEGER; g: like generics) is
31 -- Create Current with `g' types as generic parameter.
32 require
33 valid_class_id: a_class_id > 0
34 has_generics: g /= Void
35 do
36 generics := g
37 class_id := a_class_id
38 ensure
39 generics_set: generics = g
40 class_id_set: class_id = a_class_id
41 end
42
43 feature -- Visitor
44
45 process (v: TYPE_A_VISITOR) is
46 -- Process current element.
47 do
48 v.process_gen_type_a (Current)
49 end
50
51 feature -- Property
52
53 generics: ARRAY [TYPE_A]
54 -- Actual generical parameter
55
56 is_covariant (a_generic_position: INTEGER): BOOLEAN
57 -- Is generic at `a_generic_position' marked as covariant?
58 do
59 if covariance_flags /= Void then
60 Result := covariance_flags [a_generic_position]
61 end
62
63 end
64
65 feature -- Comparison
66
67 is_equivalent (other: like Current): BOOLEAN is
68 -- Is `other' equivalent to the current object ?
69 local
70 i, nb: INTEGER
71 other_generics: like generics
72 do
73 Result := Precursor {CL_TYPE_A} (other)
74 if Result then
75 from
76 i := 1
77 nb := generics.count
78 other_generics := other.generics
79 Result := nb = other_generics.count
80 until
81 i > nb or else not Result
82 loop
83 Result := equivalent (generics.item (i),
84 other_generics.item (i))
85 i := i + 1
86 end
87 end
88 end
89
90 feature -- Access
91
92 same_as (other: TYPE_A): BOOLEAN is
93 -- Is the current type the same as `other' ?
94 local
95 other_gen_type: like Current
96 i, nb: INTEGER
97 other_generics: like generics
98 do
99 other_gen_type ?= other
100 if
101 other_gen_type /= Void
102 and then other_gen_type.class_id = class_id
103 and then is_expanded = other_gen_type.is_expanded
104 and then is_separate = other_gen_type.is_separate
105 then
106 from
107 i := 1
108 nb := generics.count
109 other_generics := other_gen_type.generics
110 Result := nb = other_generics.count
111 until
112 i > nb or else not Result
113 loop
114 Result := generics.item (i).same_as (other_generics.item (i))
115 i := i + 1
116 end
117 end
118 end
119
120 hash_code: INTEGER is
121 -- Hash code value
122 local
123 i, nb: INTEGER
124 l_cl_type_a: CL_TYPE_A
125 do
126 Result := class_id
127 from
128 i := 1
129 nb := generics.count
130 until
131 i > nb
132 loop
133 l_cl_type_a ?= generics.item (i)
134 if l_cl_type_a /= Void then
135 Result := Result + l_cl_type_a.hash_code
136 end
137 i := i + 1
138 end
139 -- Clear sign if it becomes negative
140 Result := 0x7FFFFFFF & Result
141 end
142
143 feature -- Output
144
145 dump: STRING is
146 -- Dumped trace
147 local
148 i, count: INTEGER
149 do
150 Result := Precursor {CL_TYPE_A}
151
152 count := generics.count
153
154 -- TUPLE may have zero generic parameters
155
156 if count > 0 then
157 Result.append (" [")
158 from
159 i := 1
160 until
161 i > count
162 loop
163 Result.append (generics.item (i).dump)
164 if i /= count then
165 Result.append (", ")
166 end
167 i := i + 1
168 end
169 Result.append ("]")
170 end
171 end
172
173 ext_append_to (st: TEXT_FORMATTER; c: CLASS_C) is
174 local
175 i, count: INTEGER
176 do
177 -- Append classname "TUPLE"
178 Precursor {CL_TYPE_A} (st, c)
179
180 count := generics.count
181 -- TUPLE may have zero generic parameters
182 if count > 0 then
183 st.add_space
184 st.process_symbol_text (ti_L_bracket)
185 from
186 i := 1
187 until
188 i > count
189 loop
190 generics.item (i).ext_append_to (st, c)
191 if i /= count then
192 st.process_symbol_text (ti_Comma)
193 st.add_space
194 end
195 i := i + 1
196 end
197 st.process_symbol_text (ti_R_bracket)
198 end
199 end
200
201 feature {COMPILER_EXPORTER} -- Primitives
202
203 generate_error_from_creation_constraint_list (a_context_class: CLASS_C; a_context_feature: FEATURE_I; a_location_as: LOCATION_AS)
204 -- Generated a VTCG7 error if there are any constraint errors.
205 -- Otherwise it does nothing.
206 require
207 not_constraint_error_list_is_void: constraint_error_list /= Void
208 local
209 l_vtcg7: VTCG7
210 do
211 if not constraint_error_list.is_empty then
212 -- The feature listed in the creation constraint have
213 -- not been declared in the constraint class.
214 create l_vtcg7
215 l_vtcg7.set_location (a_location_as)
216 l_vtcg7.set_class (a_context_class)
217 l_vtcg7.set_error_list (constraint_error_list)
218 l_vtcg7.set_parent_type (Current)
219 if a_context_feature /= Void then
220 l_vtcg7.set_feature (a_context_feature)
221 end
222 Error_handler.insert_error (l_vtcg7)
223 end
224 end
225
226 update_dependance (feat_depend: FEATURE_DEPENDANCE) is
227 -- Update dependency for Dead Code Removal
228 local
229 i, count: INTEGER
230 do
231 from
232 i := 1
233 count := generics.count
234 until
235 i > count
236 loop
237 generics.item (i).update_dependance (feat_depend)
238 i := i + 1
239 end
240 end
241
242 set_generics (g: like generics) is
243 -- Assign `g' to `generics'.
244 require
245 g_not_void: g /= Void
246 do
247 generics := g
248 ensure
249 generics_set: generics = g
250 end
251
252 set_covariance_flags (a_flags: like covariance_flags) is
253 -- Assign `a_flags' to `covariance_flags'.
254 require
255 a_flags_not_void: a_flags /= Void
256 do
257 covariance_flags := a_flags
258 ensure
259 covariance_flags_set: covariance_flags = a_flags
260 end
261
262 has_expanded: BOOLEAN is
263 -- Are some expanded type in the current generic declaration ?
264 local
265 i, count: INTEGER
266 do
267 from
268 Result := is_expanded
269 i := 1
270 count := generics.count
271 until
272 i > count or else Result
273 loop
274 Result := generics.item (i).has_expanded
275 i := i + 1
276 end
277 end
278
279 is_valid: BOOLEAN is
280 local
281 i, count: INTEGER
282 do
283 from
284 Result := Precursor {CL_TYPE_A}
285 i := 1
286 count := generics.count
287 until
288 i > count or else not Result
289 loop
290 Result := generics.item (i).is_valid
291 i := i + 1
292 end
293 end
294
295 is_full_named_type: BOOLEAN is
296 -- Is Current a fully named type?
297 local
298 i, count: INTEGER
299 do
300 from
301 i := 1
302 count := generics.count
303 until
304 i > count or else Result
305 loop
306 Result := generics.item (i).is_full_named_type
307 i := i + 1
308 end
309 end
310
311 has_formal_generic: BOOLEAN is
312 -- Has type a formal generic parameter?
313 local
314 i, count: INTEGER
315 do
316 from
317 i := 1
318 count := generics.count
319 until
320 i > count or else Result
321 loop
322 Result := generics.item (i).has_formal_generic
323 i := i + 1
324 end
325 end
326
327 is_loose: BOOLEAN is
328 -- Does type depend on formal generic parameters and/or anchors?
329 local
330 g: like generics
331 i: INTEGER
332 do
333 from
334 g := generics
335 i := g.count
336 until
337 i <= 0 or else Result
338 loop
339 Result := g.item (i).is_loose
340 i := i - 1
341 end
342 end
343
344 type_i: GEN_TYPE_I is
345 -- Meta generic interpretation of the generic type
346 local
347 i, count: INTEGER
348 meta_generic: META_GENERIC
349 true_generics: ARRAY [TYPE_I]
350 gt:TYPE_A
351 do
352 from
353 i := 1
354 count := generics.count
355 create meta_generic.make (count)
356 create true_generics.make (1, count)
357 until
358 i > count
359 loop
360 gt := generics.item (i)
361 meta_generic.put (gt.meta_type, i)
362 true_generics.put (gt.type_i, i)
363 i := i + 1
364 end
365
366 create Result.make (class_id, meta_generic, true_generics)
367 Result.set_mark (declaration_mark)
368 end
369
370 deep_actual_type: like Current is
371 -- Actual type of Current; recursive version for generics
372 local
373 i: INTEGER
374 new_generics: like generics
375 do
376 if not has_like then
377 Result := Current
378 else
379 from
380 i := generics.count
381 create new_generics.make (1, i)
382 until
383 i <= 0
384 loop
385 new_generics.put (generics.item (i).deep_actual_type, i)
386 i := i - 1
387 end
388 Result := twin
389 Result.set_generics (new_generics)
390 end
391 end
392
393 actual_argument_type (a_arg_types: ARRAY [TYPE_A]): like Current is
394 local
395 i, count: INTEGER
396 new_generics: like generics
397 do
398 if not has_like then
399 Result := Current
400 else
401 from
402 i := 1
403 count := generics.count
404 create new_generics.make (1, count)
405 until
406 i > count
407 loop
408 new_generics.put (generics.item (i).actual_argument_type (a_arg_types), i)
409 i := i + 1
410 end
411 Result := twin
412 Result.set_generics (new_generics)
413 Result.set_mark (declaration_mark)
414 end
415 end
416
417 instantiation_in (type: TYPE_A; written_id: INTEGER): GEN_TYPE_A is
418 -- TODO: new comment
419 local
420 i: INTEGER
421 old_generics: like generics
422 new_generics: like generics
423 old_type: TYPE_A
424 new_type: TYPE_A
425 do
426 Result := Current
427 from
428 old_generics := Result.generics
429 i := old_generics.count
430 until
431 i <= 0
432 loop
433 old_type := old_generics.item (i)
434 new_type := old_type.instantiation_in (type, written_id)
435 if new_type /= old_type then
436 -- Record a new type of a generic parameter.
437 if new_generics = Void then
438 -- Avoid modifying original type descriptor.
439 Result := Result.duplicate
440 new_generics := Result.generics
441 end
442 new_generics.put (new_type, i)
443 end
444 i := i - 1
445 end
446 end
447
448 instantiated_in (class_type: TYPE_A): TYPE_A is
449 -- Instantiation of Current in the context of `class_type'
450 -- assuming that Current is written in the associated class
451 -- of `class_type'.
452 local
453 i, count: INTEGER
454 new_generics: like generics
455 do
456 from
457 Result := duplicate
458 i := 1
459 count := generics.count
460 new_generics := Result.generics
461 until
462 i > count
463 loop
464 new_generics.put
465 (generics.item (i).instantiated_in (class_type), i)
466 i := i + 1
467 end
468 end
469
470 evaluated_type_in_descendant (a_ancestor, a_descendant: CLASS_C; a_feature: FEATURE_I): like Current is
471 local
472 i, nb: INTEGER
473 new_generics: like generics
474 do
475 if a_ancestor /= a_descendant then
476 if is_loose then
477 from
478 nb := generics.count
479 create new_generics.make (1, nb)
480 i := 1
481 until
482 i > nb
483 loop
484 new_generics.put (
485 generics.item (i).evaluated_type_in_descendant (a_ancestor, a_descendant, a_feature),
486 i)
487 i := i + 1
488 end
489 Result := twin
490 Result.set_generics (new_generics)
491 else
492 Result := Current
493 end
494 else
495 Result := Current
496 end
497 end
498
499 valid_generic (type: CL_TYPE_A): BOOLEAN is
500 -- Check generic parameters
501 local
502 i, count: INTEGER
503 gen_type: GEN_TYPE_A
504 gen_type_generics: like generics
505 do
506 if class_id = type.class_id then
507 gen_type ?= type
508 if gen_type /= Void then
509 from
510 i := 1
511 gen_type_generics := gen_type.generics
512 count := generics.count
513 Result := count = gen_type_generics.count
514 until
515 i > count or else not Result
516 loop
517 Result := gen_type_generics.item (i).
518 conform_to (generics.item (i))
519 i := i + 1
520 end
521 end
522 else
523 -- `type' is a descendant type of Current: so we
524 -- have to check the current generic parameters
525 Result := type.generic_conform_to (Current)
526 end
527 end
528
529 parent_type (parent: CL_TYPE_A): TYPE_A is
530 -- Parent actual type in the current context
531 do
532 Result := instantiate (parent.duplicate)
533 end
534
535 instantiate (type: TYPE_A): TYPE_A is
536 -- Instantiates `type'. Given that `type' may hold
537 -- some formal generics, instantiate them with the
538 -- generics from Current.
539 require
540 good_argument: type /= Void
541 local
542 i, count: INTEGER
543 gen_type: GEN_TYPE_A
544 gen_type_generics: like generics
545 formal_type: FORMAL_A
546 l_like_type: LIKE_TYPE_A
547 do
548 formal_type ?= type
549 if formal_type /= Void then
550 -- Instantiation of a formal generic
551 Result := generics.item (formal_type.position).actual_type
552 elseif type.is_like then
553 -- We do not want to loose the fact that it is an anchor
554 -- as otherwise we would break eweasel test exec206, but we
555 -- still need to adapt its actual_type to the current context
556 -- otherwise we would break valid168.
557 l_like_type ?= type
558 check
559 l_like_type_not_void: l_like_type /= Void
560 end
561 l_like_type.set_actual_type (instantiate (l_like_type.conformance_type))
562 Result := l_like_type
563 elseif type.has_generics then
564 -- Instantiation of the generic parameter of `type'
565 gen_type ?= type
566 Result := gen_type.duplicate
567 from
568 i := 1
569 gen_type_generics := Result.generics
570 count := gen_type_generics.count
571 until
572 i > count
573 loop
574 gen_type_generics.put
575 (instantiate (gen_type_generics.item (i)), i)
576 i := i + 1
577 end
578 else
579 Result := type
580 end
581 end
582
583 has_like: BOOLEAN is
584 -- Has the type anchored type in its definition ?
585 local
586 i, count: INTEGER
587 do
588 from
589 i := 1
590 count := generics.count
591 until
592 i > count or else Result
593 loop
594 Result := generics.item (i).has_like
595 i := i + 1
596 end
597 end
598
599 has_like_argument: BOOLEAN is
600 -- Has the type like argument in its definition?
601 local
602 i, count: INTEGER
603 do
604 from
605 i := 1
606 count := generics.count
607 until
608 i > count or else Result
609 loop
610 Result := generics.item (i).has_like_argument
611 i := i + 1
612 end
613 end
614
615 duplicate: like Current is
616 -- Duplication
617 local
618 i, count: INTEGER
619 duplicate_generics: like generics
620 do
621 from
622 i := 1
623 count := generics.count
624 create duplicate_generics.make (1, count)
625 until
626 i > count
627 loop
628 duplicate_generics.put (generics.item (i).duplicate, i)
629 i := i + 1
630 end
631 Result := twin
632 Result.set_generics (duplicate_generics)
633 if covariance_flags /= Void then
634 Result.set_covariance_flags (covariance_flags.twin)
635 end
636 end
637
638 good_generics: BOOLEAN is
639 -- Has the base class exactly the same number of generic
640 -- parameters in its formal generic declarations?
641 local
642 base_generics: EIFFEL_LIST [FORMAL_DEC_AS]
643 i, generic_count: INTEGER
644 do
645 base_generics := associated_class.generics
646 if base_generics /= Void then
647 generic_count := base_generics.count
648 Result := generic_count = generics.count
649 from
650 i := 1
651 until
652 i > generic_count or else not Result
653 loop
654 Result := generics.item (i).good_generics
655 i := i + 1
656 end
657 end
658 end
659
660 error_generics: VTUG is
661 -- Returns the first error regarding the number of generic parameters
662 -- compared to the formal generic declarations.
663 --| Recursion is done to find all errors.
664 local
665 base_generics: EIFFEL_LIST [FORMAL_DEC_AS]
666 i, generic_count: INTEGER
667 do
668 base_generics := associated_class.generics
669 if base_generics /= Void then
670 generic_count := base_generics.count
671 if (generic_count = generics.count) then
672 from
673 i := 1
674 until
675 i > generic_count or else (Result /= Void)
676 loop
677 if not generics.item (i).good_generics then
678 Result := generics.item (i).error_generics
679 end
680 i := i + 1
681 end
682 end
683 end
684 if Result = Void then
685 if base_generics = Void then
686 create {VTUG1} Result
687 else
688 create {VTUG2} Result
689 end
690 Result.set_type (Current)
691 Result.set_base_class (associated_class)
692 end
693 end
694
695 check_constraints (a_type_context: CLASS_C; a_context_feature: FEATURE_I; a_check_creation_readiness: BOOLEAN) is
696 -- Check the constrained genericity validity rule
697 --| We check for all generic parameters whether they fullfill their constraints:
698 --| * conformance to all the constraining types
699 --| * providing creations routines to meet all creation constraints
700 local
701 i, l_count: INTEGER
702 l_class: CLASS_C
703 l_constraints: TYPE_SET_A
704 l_constraint_item: TYPE_A
705 l_formal_constraint: FORMAL_A
706 l_generic_constraint: GEN_TYPE_A
707 l_generic_parameters: ARRAY[TYPE_A]
708 l_formal_generic_parameter: FORMAL_A
709 l_generic_parameter: TYPE_A
710 l_conform: BOOLEAN
711 l_formal_dec_as: FORMAL_CONSTRAINT_AS
712 l_check_creation_readiness: BOOLEAN
713 do
714 l_conform := True
715 l_class := associated_class
716 l_generic_parameters := generics
717
718 -- Check all actual generic parameters against their constraining types.
719 from
720 l_count := l_generic_parameters.count
721 i := 1
722 until
723 i > l_count or not l_conform
724 loop
725 l_generic_parameter := l_generic_parameters.item(i)
726 l_constraints := l_class.constraints(i)
727 from
728 l_constraints.start
729 until
730 l_constraints.after
731 loop
732 l_constraint_item := l_constraints.item.type
733 if l_constraint_item.is_formal then
734 l_formal_constraint ?= l_constraint_item
735 check l_formal_constraint /= Void end
736 -- Replace the formal with its 'instantiation' of the current generic derivation.
737 --| `l_constraint_item' can indeed still be a formal, but now has to be resolved by using `a_type_context'
738 l_constraint_item := l_generic_parameters.item(l_formal_constraint.position)
739 elseif l_constraint_item.has_generics and then not l_constraint_item.generics.is_empty then
740 -- We substitude all occurences of formals in the constraint with the instantiation of the corresponding formal in our generic derivation.
741 l_generic_constraint ?= l_constraint_item.deep_twin
742 l_generic_constraint.substitute (l_generic_parameters)
743 l_constraint_item := l_generic_constraint
744 end
745 --| Knowing that formals (FORMAL_A) just take of their "layers" and fall back to their constraints and ask and ask again until they match.
746 --| Example: [G -> H, H -> I, I -> J] Question: Is G conform to J? Answer of `conform_to' is yes.
747 --| 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.
748 if l_generic_parameter.conformance_type.conform_to (l_constraint_item) then
749 -- Everything is fine, we conform
750 else
751 -- We do not conform, insert an error for this type.
752 l_conform := False
753 generate_constraint_error (Current, l_generic_parameter, l_constraint_item, i, Void)
754 end
755
756 l_constraints.forth
757 end
758 if l_conform then
759 -- Check now for the validity of the creation constraint clause if
760 -- there is one which can be checked, i.e. when `to_check' conforms
761 -- to `constraint_type'.
762 l_formal_dec_as ?= associated_class.generics.i_th (i)
763 check l_formal_dec_as_not_void: l_formal_dec_as /= Void end
764 if l_formal_dec_as.has_creation_constraint and (system.check_generic_creation_constraint and a_check_creation_readiness) then
765 -- If we are not in degree 3 (i.e. 4), we cannot have a
766 -- complete check since if we are currently checking an attribute
767 -- of TEST declared as A [TOTO], maybe TOTO has not yet been recompiled?
768 -- So we store all the needed information and we will do a check at the
769 -- end of the degree 4 (look at PASS2 for the code which does the checking).
770 l_formal_generic_parameter ?= l_generic_parameter.conformance_type
771 -- We have a creation constraint so in case a check was requested we have to continue checking it.
772 l_check_creation_readiness := a_check_creation_readiness
773 if System.in_pass3 then
774 creation_constraint_check (
775 l_formal_dec_as, l_constraints, a_type_context,
776 l_generic_parameter, i, l_formal_generic_parameter)
777 else
778 add_future_checking (a_type_context,
779 agent delayed_creation_constraint_check (a_type_context, a_context_feature,
780 l_generic_parameter, l_constraints, l_formal_dec_as, i, l_formal_generic_parameter))
781 end
782 else
783 -- We do not have a creation constraint, so stop checking for it.
784 l_check_creation_readiness := False
785 end
786 end
787 if l_generic_parameter.has_generics then
788 -- Recursion
789 l_generic_parameter.check_constraints (a_type_context, a_context_feature, l_check_creation_readiness)
790 end
791
792 i := i + 1
793 end
794 end
795
796 substitute (new_generics: ARRAY [TYPE_A]) is
797 -- Take the arguments from `new_generics' to create an
798 -- effective representation of the current GEN_TYPE
799 require
800 new_generics_not_void: new_generics /= Void
801 local
802 i, count, pos: INTEGER
803 constraint_type: TYPE_A
804 formal_type: FORMAL_A
805 gen_type: GEN_TYPE_A
806 do
807 from
808 i := 1
809 count := generics.count
810 until
811 i > count
812 loop
813 constraint_type := generics.item (i)
814
815 if constraint_type.is_formal then
816 formal_type ?= constraint_type
817 pos := formal_type.position
818 generics.force (new_generics.item (pos), i)
819 elseif constraint_type.generics /= Void then
820 gen_type ?= constraint_type
821 gen_type.substitute (new_generics)
822 end
823 i := i + 1
824 end
825 end
826
827 delayed_creation_constraint_check (
828 context_class: CLASS_C;
829 a_context_feature: FEATURE_I;
830 to_check: TYPE_A
831 constraint_type: TYPE_SET_A
832 formal_dec_as: FORMAL_CONSTRAINT_AS
833 i: INTEGER;
834 formal_type: FORMAL_A) is
835 -- Check that declaration of generic class is conform to
836 -- defined creation constraint in delayed mode.
837 require
838 formal_dec_as_not_void: formal_dec_as /= Void
839 creation_constraint_exists: formal_dec_as.has_creation_constraint
840 to_check_is_formal_implies_formal_type_not_void: to_check.conformance_type.is_formal implies formal_type /= Void
841 do
842 reset_constraint_error_list
843 -- We assume that we only get checks if the class is valid.
844 -- However, if contracts are disabled we catch the error also with the following if-statement.
845 check is_valid: is_valid end
846 if is_valid and then context_class.is_valid and then to_check /= Void and then to_check.is_valid then
847 creation_constraint_check (formal_dec_as, constraint_type, context_class, to_check, i, formal_type)
848 generate_error_from_creation_constraint_list (context_class, a_context_feature, formal_dec_as.start_location )
849 end
850 end
851
852 creation_constraint_check (
853 formal_dec_as: FORMAL_CONSTRAINT_AS
854 a_constraint_types: TYPE_SET_A;
855 context_class: CLASS_C;
856 to_check: TYPE_A;
857 i: INTEGER;
858 formal_type: FORMAL_A) is
859 -- Check that declaration of generic class is conform to
860 -- defined creation constraint.
861 require
862 formal_dec_as_not_void: formal_dec_as /= Void
863 creation_constraint_exists: formal_dec_as.has_creation_constraint
864 is_valid: is_valid
865 local
866 formal_type_dec_as: FORMAL_CONSTRAINT_AS
867 formal_crc_list, crc_list: LINKED_LIST [TUPLE [type_item: RENAMED_TYPE_A [TYPE_A]; feature_item: FEATURE_I]];
868 creators_table: HASH_TABLE [EXPORT_I, STRING]
869 matched: BOOLEAN
870 feat_tbl: FEATURE_TABLE
871 class_c: CLASS_C
872 other_feature_i, feature_i: FEATURE_I
873 l_unmatched_features: LIST [FEATURE_I]
874 do
875
876 -- If there is a creation constraint we are facing two different cases:
877 -- * case 1: the declaration is using a real type `to_check', we check that
878 -- the creation procedures listed in the constraint are indeed
879 -- creation procedures of `to_check'.
880 -- * case 2: the declaration is using a formal type. Let's take an example and
881 -- I will explain what we need to do:
882 -- we have:
883 -- A[G -> C create make_1, make_2,..., make_n end]
884 -- B [H, K -> MY_C create my_make_1, my_make_2,...my_make_m end]
885 -- MY_C inherits from C
886 -- In B, we have `a: A[K]', which is valid if:
887 -- * MY_C conforms to C (already established here)
888 -- * m >= n
889 -- * for each `make_i' where 1 <= i <= n, there is a `j' (1 <= j <= m)
890 -- where `my_make_k' is a redefined/renamed version of `make_i'.
891 crc_list := formal_dec_as.constraint_creation_list (associated_class)
892 if formal_type = Void then
893 -- We're in the case of a class type.
894
895 -- If it is a deferred class and the actual derivation uses like current
896 -- we move the duty to check the creation constraint to the full class check to check
897 -- the descendants of this deferred class, which can never be instantiated direclty.
898 -- See bug#12464 and test#valid208/test#valid209 for more information.
899 if to_check.is_like_current and context_class.is_deferred then
900 -- We simply accept it.
901 else
902
903 if to_check.has_associated_class then
904 -- `to_check' may not have an associated class if it represents NONE type, for
905 -- example in PROCEDURE [ANY, NONE], we will check NONE against
906 -- constraint of PROCEDURE which is `TUPLE create default_create end'.
907 class_c := to_check.associated_class
908 creators_table := class_c.creators
909 end
910
911 -- A creation procedure has to be specified, so if none is
912 -- specified or if there is no creation procedure in the class
913 -- corresponding to `to_check', this is not valid.
914 if
915 creators_table /= Void and then not creators_table.is_empty
916 then
917 from
918 crc_list.start
919 feat_tbl := class_c.feature_table
920 until
921 crc_list.after
922 loop
923 -- Let's take one of the creation procedure defined in the constraint.
924 feature_i := crc_list.item.feature_item
925
926 -- Take the redefined/renamed version of the previous version in the
927 -- descendant class `to_check'/`class_c'.
928 other_feature_i := feat_tbl.feature_of_rout_id (feature_i.rout_id_set.first)
929
930 -- Test if we found the specified feature name among the creation
931 -- procedures of `class_c' and that it is exported to Current, since it
932 -- it is Current that will create instances of the generic parameter.
933 creators_table.search (other_feature_i.feature_name)
934 if
935 not creators_table.found or else
936 not creators_table.found_item.valid_for (associated_class)
937 then
938 if l_unmatched_features = Void then
939 create {LINKED_LIST[FEATURE_I]} l_unmatched_features.make
940 end
941 l_unmatched_features.extend (feature_i)
942 end
943 crc_list.forth
944 end
945 else
946 -- The class type does not have a creation clause:
947 -- May be we are handling a case where the constraint only specfies
948 -- `default_create', so let's check that the constraint defines
949 -- `default_create' as creation procedure and that `creators_table'
950 -- is Void (as empty means there is no way to create an instance of this
951 -- class).
952 -- At last we check that this class is not deferred.
953 if
954 creators_table = Void and then
955 (crc_list.count = 1 and then formal_dec_as.has_default_create)
956 then
957 -- Ok, no error: We have no create clause which makes `default_create' available
958 -- and the constraint demands only `default_create'
959
960 -- But maybe it is a deferred class?
961 if class_c /= Void and then class_c.is_deferred then
962 if l_unmatched_features = Void then
963 create {LINKED_LIST[FEATURE_I]} l_unmatched_features.make
964 end
965 l_unmatched_features.extend (crc_list.first.feature_item)
966 end
967 else
968 -- Generate list of features not matching constraint.
969 from
970 create {LINKED_LIST[FEATURE_I]} l_unmatched_features.make
971 crc_list.start
972 until
973 crc_list.after
974 loop
975 -- If `creators_table' is not Void, it simply means we have an empty creation routine
976 -- and therefore all the creation constraints are not met.
977 -- If it is Void, then `{ANY}.default_create' is a valid creation routine, in that
978 -- case we should not list `default_create' has not beeing met if listed in the creation
979 -- constraint.
980 feature_i := crc_list.item.feature_item
981 if creators_table /= Void or else not feature_i.rout_id_set.has (system.default_create_id) then
982 l_unmatched_features.extend (feature_i)
983 end
984 crc_list.forth
985 end
986 end
987 end
988 -- We have an error if we have unmatched features.
989 if l_unmatched_features /= Void then
990 generate_constraint_error (Current, to_check, a_constraint_types, i, l_unmatched_features)
991 end
992 end
993 else
994 -- Check if there is a creation constraint clause
995 formal_type_dec_as ?= context_class.generics.i_th (formal_type.position)
996 if formal_type_dec_as /= Void and then formal_type_dec_as.has_creation_constraint then
997 -- Check if we have m >= n as specified above.
998 formal_crc_list := formal_type_dec_as.constraint_creation_list (context_class)
999 if formal_crc_list.count >= crc_list.count then
1000 from
1001 crc_list.start
1002 matched := True
1003 until
1004 crc_list.after
1005 loop
1006 feature_i := crc_list.item.feature_item
1007 -- Check that all the creation procedures defined in the creation
1008 -- constraint clause `crc_list' are indeed present under a
1009 -- redefined/renamed version in the creation constraint clause
1010 from
1011 matched := False
1012 formal_crc_list.start
1013 until
1014 matched or else formal_crc_list.after
1015 loop
1016 matched := formal_crc_list.item.feature_item.rout_id_set.has (
1017 feature_i.rout_id_set.first)
1018 formal_crc_list.forth
1019 end
1020 -- If not matched save the feature to report a proper error.
1021 if not matched then
1022 if l_unmatched_features = Void then
1023 create {LINKED_LIST[FEATURE_I]} l_unmatched_features.make
1024 end
1025 l_unmatched_features.extend (feature_i)
1026 end
1027 crc_list.forth
1028 end
1029 else
1030 matched := False
1031 end
1032 else
1033 matched := False
1034 end
1035
1036 if not matched then
1037 generate_constraint_error (Current, formal_type,a_constraint_types, i, l_unmatched_features)
1038 end
1039 end
1040 end
1041
1042 expanded_deferred: BOOLEAN is
1043 -- Are the expanded class types present in the current generic
1044 -- type not based on deferred classes ?
1045 local
1046 i, nb: INTEGER
1047 gen_param: TYPE_A
1048 do
1049 from
1050 Result := Precursor {CL_TYPE_A}
1051 i := 1
1052 nb := generics.count
1053 until
1054 i > nb or else Result
1055 loop
1056 gen_param := generics.item (i)
1057 if gen_param.has_expanded then
1058 Result := gen_param.expanded_deferred
1059 end
1060 i := i + 1
1061 end
1062 end
1063
1064 valid_expanded_creation (a_class: CLASS_C): BOOLEAN is
1065 -- Is the expanded type has an associated class with one
1066 -- creation routine with no arguments only ?
1067 local
1068 i, nb: INTEGER
1069 gen_param: TYPE_A
1070 do
1071 from
1072 Result := Precursor {CL_TYPE_A} (a_class)
1073 i := 1
1074 nb := generics.count
1075 until
1076 i > nb or else not Result
1077 loop
1078 gen_param := generics.item (i)
1079 if gen_param.has_expanded then
1080 Result := gen_param.valid_expanded_creation (a_class)
1081 end
1082 i := i + 1
1083 end
1084 end
1085
1086 format (ctxt: TEXT_FORMATTER_DECORATOR) is
1087 local
1088 i, count: INTEGER
1089 do
1090 ctxt.put_classi (associated_class.lace_class)
1091 count := generics.count
1092
1093 -- TUPLE may have zero generic parameters
1094 if count > 0 then
1095 ctxt.put_space
1096 ctxt.process_symbol_text (ti_L_bracket)
1097 from
1098 i := 1
1099 until
1100 i > count
1101 loop
1102 generics.item (i).format (ctxt)
1103 if i /= count then
1104 ctxt.process_symbol_text (ti_Comma)
1105 ctxt.put_space
1106 end
1107 i := i + 1
1108 end
1109 ctxt.process_symbol_text (ti_R_bracket)
1110 end
1111 end
1112
1113 feature {NONE} -- Implementation
1114
1115 covariance_flags: PACKED_BOOLEANS
1116 -- Stores whether a generic at a certain position is marked covariant or not.
1117
1118 invariant
1119
1120 -- A generic class always has generic parameters
1121 generics_not_void: generics /= Void
1122
1123 indexing
1124 copyright: "Copyright (c) 1984-2006, Eiffel Software"
1125 license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)"
1126 licensing_options: "http://www.eiffel.com/licensing"
1127 copying: "[
1128 This file is part of Eiffel Software's Eiffel Development Environment.
1129
1130 Eiffel Software's Eiffel Development Environment is free
1131 software; you can redistribute it and/or modify it under
1132 the terms of the GNU General Public License as published
1133 by the Free Software Foundation, version 2 of the License
1134 (available at the URL listed under "license" above).
1135
1136 Eiffel Software's Eiffel Development Environment is
1137 distributed in the hope that it will be useful, but
1138 WITHOUT ANY WARRANTY; without even the implied warranty
1139 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1140 See the GNU General Public License for more details.
1141
1142 You should have received a copy of the GNU General Public
1143 License along with Eiffel Software's Eiffel Development
1144 Environment; if not, write to the Free Software Foundation,
1145 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1146 ]"
1147 source: "[
1148 Eiffel Software
1149 356 Storke Road, Goleta, CA 93117 USA
1150 Telephone 805-685-1006, Fax 805-685-6869
1151 Website http://www.eiffel.com
1152 Customer support http://support.eiffel.com
1153 ]"
1154
1155 end -- class GEN_TYPE_A
1156

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.23