/[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 69703 - (show annotations)
Thu Jul 26 22:37:19 2007 UTC (12 years, 4 months ago) by juliant
File size: 33733 byte(s)
warning only when conformance check results differ
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).conform_to (generics.item (i))
518 if Result and then not is_covariant (i) and then not equivalent (gen_type_generics.item (i).conformance_type, generics.item (i).conformance_type) then
519 -- It is not a covariant generic, and the types differ. This is a conformance mismatch
520 conformance_check.cat_result := False
521 end
522 i := i + 1
523 end
524 end
525 else
526 -- `type' is a descendant type of Current: so we
527 -- have to check the current generic parameters
528 Result := type.generic_conform_to (Current)
529 end
530 end
531
532 parent_type (parent: CL_TYPE_A): TYPE_A is
533 -- Parent actual type in the current context
534 do
535 Result := instantiate (parent.duplicate)
536 end
537
538 instantiate (type: TYPE_A): TYPE_A is
539 -- Instantiates `type'. Given that `type' may hold
540 -- some formal generics, instantiate them with the
541 -- generics from Current.
542 require
543 good_argument: type /= Void
544 local
545 i, count: INTEGER
546 gen_type: GEN_TYPE_A
547 gen_type_generics: like generics
548 formal_type: FORMAL_A
549 l_like_type: LIKE_TYPE_A
550 do
551 formal_type ?= type
552 if formal_type /= Void then
553 -- Instantiation of a formal generic
554 Result := generics.item (formal_type.position).actual_type
555 elseif type.is_like then
556 -- We do not want to loose the fact that it is an anchor
557 -- as otherwise we would break eweasel test exec206, but we
558 -- still need to adapt its actual_type to the current context
559 -- otherwise we would break valid168.
560 l_like_type ?= type
561 check
562 l_like_type_not_void: l_like_type /= Void
563 end
564 l_like_type.set_actual_type (instantiate (l_like_type.conformance_type))
565 Result := l_like_type
566 elseif type.has_generics then
567 -- Instantiation of the generic parameter of `type'
568 gen_type ?= type
569 Result := gen_type.duplicate
570 from
571 i := 1
572 gen_type_generics := Result.generics
573 count := gen_type_generics.count
574 until
575 i > count
576 loop
577 gen_type_generics.put
578 (instantiate (gen_type_generics.item (i)), i)
579 i := i + 1
580 end
581 else
582 Result := type
583 end
584 end
585
586 has_like: BOOLEAN is
587 -- Has the type anchored type in its definition ?
588 local
589 i, count: INTEGER
590 do
591 from
592 i := 1
593 count := generics.count
594 until
595 i > count or else Result
596 loop
597 Result := generics.item (i).has_like
598 i := i + 1
599 end
600 end
601
602 has_like_argument: BOOLEAN is
603 -- Has the type like argument in its definition?
604 local
605 i, count: INTEGER
606 do
607 from
608 i := 1
609 count := generics.count
610 until
611 i > count or else Result
612 loop
613 Result := generics.item (i).has_like_argument
614 i := i + 1
615 end
616 end
617
618 duplicate: like Current is
619 -- Duplication
620 local
621 i, count: INTEGER
622 duplicate_generics: like generics
623 do
624 from
625 i := 1
626 count := generics.count
627 create duplicate_generics.make (1, count)
628 until
629 i > count
630 loop
631 duplicate_generics.put (generics.item (i).duplicate, i)
632 i := i + 1
633 end
634 Result := twin
635 Result.set_generics (duplicate_generics)
636 if covariance_flags /= Void then
637 Result.set_covariance_flags (covariance_flags.twin)
638 end
639 end
640
641 good_generics: BOOLEAN is
642 -- Has the base class exactly the same number of generic
643 -- parameters in its formal generic declarations?
644 local
645 base_generics: EIFFEL_LIST [FORMAL_DEC_AS]
646 i, generic_count: INTEGER
647 do
648 base_generics := associated_class.generics
649 if base_generics /= Void then
650 generic_count := base_generics.count
651 Result := generic_count = generics.count
652 from
653 i := 1
654 until
655 i > generic_count or else not Result
656 loop
657 Result := generics.item (i).good_generics
658 i := i + 1
659 end
660 end
661 end
662
663 error_generics: VTUG is
664 -- Returns the first error regarding the number of generic parameters
665 -- compared to the formal generic declarations.
666 --| Recursion is done to find all errors.
667 local
668 base_generics: EIFFEL_LIST [FORMAL_DEC_AS]
669 i, generic_count: INTEGER
670 do
671 base_generics := associated_class.generics
672 if base_generics /= Void then
673 generic_count := base_generics.count
674 if (generic_count = generics.count) then
675 from
676 i := 1
677 until
678 i > generic_count or else (Result /= Void)
679 loop
680 if not generics.item (i).good_generics then
681 Result := generics.item (i).error_generics
682 end
683 i := i + 1
684 end
685 end
686 end
687 if Result = Void then
688 if base_generics = Void then
689 create {VTUG1} Result
690 else
691 create {VTUG2} Result
692 end
693 Result.set_type (Current)
694 Result.set_base_class (associated_class)
695 end
696 end
697
698 check_constraints (a_type_context: CLASS_C; a_context_feature: FEATURE_I; a_check_creation_readiness: BOOLEAN) is
699 -- Check the constrained genericity validity rule
700 --| We check for all generic parameters whether they fullfill their constraints:
701 --| * conformance to all the constraining types
702 --| * providing creations routines to meet all creation constraints
703 local
704 i, l_count: INTEGER
705 l_class: CLASS_C
706 l_constraints: TYPE_SET_A
707 l_constraint_item: TYPE_A
708 l_formal_constraint: FORMAL_A
709 l_generic_constraint: GEN_TYPE_A
710 l_generic_parameters: ARRAY[TYPE_A]
711 l_formal_generic_parameter: FORMAL_A
712 l_generic_parameter: TYPE_A
713 l_conform: BOOLEAN
714 l_formal_dec_as: FORMAL_CONSTRAINT_AS
715 l_check_creation_readiness: BOOLEAN
716 do
717 l_conform := True
718 l_class := associated_class
719 l_generic_parameters := generics
720
721 -- Check all actual generic parameters against their constraining types.
722 from
723 l_count := l_generic_parameters.count
724 i := 1
725 until
726 i > l_count or not l_conform
727 loop
728 l_generic_parameter := l_generic_parameters.item(i)
729 l_constraints := l_class.constraints(i)
730 from
731 l_constraints.start
732 until
733 l_constraints.after
734 loop
735 l_constraint_item := l_constraints.item.type
736 if l_constraint_item.is_formal then
737 l_formal_constraint ?= l_constraint_item
738 check l_formal_constraint /= Void end
739 -- Replace the formal with its 'instantiation' of the current generic derivation.
740 --| `l_constraint_item' can indeed still be a formal, but now has to be resolved by using `a_type_context'
741 l_constraint_item := l_generic_parameters.item(l_formal_constraint.position)
742 elseif l_constraint_item.has_generics and then not l_constraint_item.generics.is_empty then
743 -- We substitude all occurences of formals in the constraint with the instantiation of the corresponding formal in our generic derivation.
744 l_generic_constraint ?= l_constraint_item.deep_twin
745 l_generic_constraint.substitute (l_generic_parameters)
746 l_constraint_item := l_generic_constraint
747 end
748 --| Knowing that formals (FORMAL_A) just take of their "layers" and fall back to their constraints and ask and ask again until they match.
749 --| Example: [G -> H, H -> I, I -> J] Question: Is G conform to J? Answer of `conform_to' is yes.
750 --| 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.
751 if l_generic_parameter.conformance_type.conform_to (l_constraint_item) then
752 -- Everything is fine, we conform
753 else
754 -- We do not conform, insert an error for this type.
755 l_conform := False
756 generate_constraint_error (Current, l_generic_parameter, l_constraint_item, i, Void)
757 end
758
759 l_constraints.forth
760 end
761 if l_conform then
762 -- Check now for the validity of the creation constraint clause if
763 -- there is one which can be checked, i.e. when `to_check' conforms
764 -- to `constraint_type'.
765 l_formal_dec_as ?= associated_class.generics.i_th (i)
766 check l_formal_dec_as_not_void: l_formal_dec_as /= Void end
767 if l_formal_dec_as.has_creation_constraint and (system.check_generic_creation_constraint and a_check_creation_readiness) then
768 -- If we are not in degree 3 (i.e. 4), we cannot have a
769 -- complete check since if we are currently checking an attribute
770 -- of TEST declared as A [TOTO], maybe TOTO has not yet been recompiled?
771 -- So we store all the needed information and we will do a check at the
772 -- end of the degree 4 (look at PASS2 for the code which does the checking).
773 l_formal_generic_parameter ?= l_generic_parameter.conformance_type
774 -- We have a creation constraint so in case a check was requested we have to continue checking it.
775 l_check_creation_readiness := a_check_creation_readiness
776 if System.in_pass3 then
777 creation_constraint_check (
778 l_formal_dec_as, l_constraints, a_type_context,
779 l_generic_parameter, i, l_formal_generic_parameter)
780 else
781 add_future_checking (a_type_context,
782 agent delayed_creation_constraint_check (a_type_context, a_context_feature,
783 l_generic_parameter, l_constraints, l_formal_dec_as, i, l_formal_generic_parameter))
784 end
785 else
786 -- We do not have a creation constraint, so stop checking for it.
787 l_check_creation_readiness := False
788 end
789 end
790 if l_generic_parameter.has_generics then
791 -- Recursion
792 l_generic_parameter.check_constraints (a_type_context, a_context_feature, l_check_creation_readiness)
793 end
794
795 i := i + 1
796 end
797 end
798
799 substitute (new_generics: ARRAY [TYPE_A]) is
800 -- Take the arguments from `new_generics' to create an
801 -- effective representation of the current GEN_TYPE
802 require
803 new_generics_not_void: new_generics /= Void
804 local
805 i, count, pos: INTEGER
806 constraint_type: TYPE_A
807 formal_type: FORMAL_A
808 gen_type: GEN_TYPE_A
809 do
810 from
811 i := 1
812 count := generics.count
813 until
814 i > count
815 loop
816 constraint_type := generics.item (i)
817
818 if constraint_type.is_formal then
819 formal_type ?= constraint_type
820 pos := formal_type.position
821 generics.force (new_generics.item (pos), i)
822 elseif constraint_type.generics /= Void then
823 gen_type ?= constraint_type
824 gen_type.substitute (new_generics)
825 end
826 i := i + 1
827 end
828 end
829
830 delayed_creation_constraint_check (
831 context_class: CLASS_C;
832 a_context_feature: FEATURE_I;
833 to_check: TYPE_A
834 constraint_type: TYPE_SET_A
835 formal_dec_as: FORMAL_CONSTRAINT_AS
836 i: INTEGER;
837 formal_type: FORMAL_A) is
838 -- Check that declaration of generic class is conform to
839 -- defined creation constraint in delayed mode.
840 require
841 formal_dec_as_not_void: formal_dec_as /= Void
842 creation_constraint_exists: formal_dec_as.has_creation_constraint
843 to_check_is_formal_implies_formal_type_not_void: to_check.conformance_type.is_formal implies formal_type /= Void
844 do
845 reset_constraint_error_list
846 -- We assume that we only get checks if the class is valid.
847 -- However, if contracts are disabled we catch the error also with the following if-statement.
848 check is_valid: is_valid end
849 if is_valid and then context_class.is_valid and then to_check /= Void and then to_check.is_valid then
850 creation_constraint_check (formal_dec_as, constraint_type, context_class, to_check, i, formal_type)
851 generate_error_from_creation_constraint_list (context_class, a_context_feature, formal_dec_as.start_location )
852 end
853 end
854
855 creation_constraint_check (
856 formal_dec_as: FORMAL_CONSTRAINT_AS
857 a_constraint_types: TYPE_SET_A;
858 context_class: CLASS_C;
859 to_check: TYPE_A;
860 i: INTEGER;
861 formal_type: FORMAL_A) is
862 -- Check that declaration of generic class is conform to
863 -- defined creation constraint.
864 require
865 formal_dec_as_not_void: formal_dec_as /= Void
866 creation_constraint_exists: formal_dec_as.has_creation_constraint
867 is_valid: is_valid
868 local
869 formal_type_dec_as: FORMAL_CONSTRAINT_AS
870 formal_crc_list, crc_list: LINKED_LIST [TUPLE [type_item: RENAMED_TYPE_A [TYPE_A]; feature_item: FEATURE_I]];
871 creators_table: HASH_TABLE [EXPORT_I, STRING]
872 matched: BOOLEAN
873 feat_tbl: FEATURE_TABLE
874 class_c: CLASS_C
875 other_feature_i, feature_i: FEATURE_I
876 l_unmatched_features: LIST [FEATURE_I]
877 do
878
879 -- If there is a creation constraint we are facing two different cases:
880 -- * case 1: the declaration is using a real type `to_check', we check that
881 -- the creation procedures listed in the constraint are indeed
882 -- creation procedures of `to_check'.
883 -- * case 2: the declaration is using a formal type. Let's take an example and
884 -- I will explain what we need to do:
885 -- we have:
886 -- A[G -> C create make_1, make_2,..., make_n end]
887 -- B [H, K -> MY_C create my_make_1, my_make_2,...my_make_m end]
888 -- MY_C inherits from C
889 -- In B, we have `a: A[K]', which is valid if:
890 -- * MY_C conforms to C (already established here)
891 -- * m >= n
892 -- * for each `make_i' where 1 <= i <= n, there is a `j' (1 <= j <= m)
893 -- where `my_make_k' is a redefined/renamed version of `make_i'.
894 crc_list := formal_dec_as.constraint_creation_list (associated_class)
895 if formal_type = Void then
896 -- We're in the case of a class type.
897
898 -- If it is a deferred class and the actual derivation uses like current
899 -- we move the duty to check the creation constraint to the full class check to check
900 -- the descendants of this deferred class, which can never be instantiated direclty.
901 -- See bug#12464 and test#valid208/test#valid209 for more information.
902 if to_check.is_like_current and context_class.is_deferred then
903 -- We simply accept it.
904 else
905
906 if to_check.has_associated_class then
907 -- `to_check' may not have an associated class if it represents NONE type, for
908 -- example in PROCEDURE [ANY, NONE], we will check NONE against
909 -- constraint of PROCEDURE which is `TUPLE create default_create end'.
910 class_c := to_check.associated_class
911 creators_table := class_c.creators
912 end
913
914 -- A creation procedure has to be specified, so if none is
915 -- specified or if there is no creation procedure in the class
916 -- corresponding to `to_check', this is not valid.
917 if
918 creators_table /= Void and then not creators_table.is_empty
919 then
920 from
921 crc_list.start
922 feat_tbl := class_c.feature_table
923 until
924 crc_list.after
925 loop
926 -- Let's take one of the creation procedure defined in the constraint.
927 feature_i := crc_list.item.feature_item
928
929 -- Take the redefined/renamed version of the previous version in the
930 -- descendant class `to_check'/`class_c'.
931 other_feature_i := feat_tbl.feature_of_rout_id (feature_i.rout_id_set.first)
932
933 -- Test if we found the specified feature name among the creation
934 -- procedures of `class_c' and that it is exported to Current, since it
935 -- it is Current that will create instances of the generic parameter.
936 creators_table.search (other_feature_i.feature_name)
937 if
938 not creators_table.found or else
939 not creators_table.found_item.valid_for (associated_class)
940 then
941 if l_unmatched_features = Void then
942 create {LINKED_LIST[FEATURE_I]} l_unmatched_features.make
943 end
944 l_unmatched_features.extend (feature_i)
945 end
946 crc_list.forth
947 end
948 else
949 -- The class type does not have a creation clause:
950 -- May be we are handling a case where the constraint only specfies
951 -- `default_create', so let's check that the constraint defines
952 -- `default_create' as creation procedure and that `creators_table'
953 -- is Void (as empty means there is no way to create an instance of this
954 -- class).
955 -- At last we check that this class is not deferred.
956 if
957 creators_table = Void and then
958 (crc_list.count = 1 and then formal_dec_as.has_default_create)
959 then
960 -- Ok, no error: We have no create clause which makes `default_create' available
961 -- and the constraint demands only `default_create'
962
963 -- But maybe it is a deferred class?
964 if class_c /= Void and then class_c.is_deferred then
965 if l_unmatched_features = Void then
966 create {LINKED_LIST[FEATURE_I]} l_unmatched_features.make
967 end
968 l_unmatched_features.extend (crc_list.first.feature_item)
969 end
970 else
971 -- Generate list of features not matching constraint.
972 from
973 create {LINKED_LIST[FEATURE_I]} l_unmatched_features.make
974 crc_list.start
975 until
976 crc_list.after
977 loop
978 -- If `creators_table' is not Void, it simply means we have an empty creation routine
979 -- and therefore all the creation constraints are not met.
980 -- If it is Void, then `{ANY}.default_create' is a valid creation routine, in that
981 -- case we should not list `default_create' has not beeing met if listed in the creation
982 -- constraint.
983 feature_i := crc_list.item.feature_item
984 if creators_table /= Void or else not feature_i.rout_id_set.has (system.default_create_id) then
985 l_unmatched_features.extend (feature_i)
986 end
987 crc_list.forth
988 end
989 end
990 end
991 -- We have an error if we have unmatched features.
992 if l_unmatched_features /= Void then
993 generate_constraint_error (Current, to_check, a_constraint_types, i, l_unmatched_features)
994 end
995 end
996 else
997 -- Check if there is a creation constraint clause
998 formal_type_dec_as ?= context_class.generics.i_th (formal_type.position)
999 if formal_type_dec_as /= Void and then formal_type_dec_as.has_creation_constraint then
1000 -- Check if we have m >= n as specified above.
1001 formal_crc_list := formal_type_dec_as.constraint_creation_list (context_class)
1002 if formal_crc_list.count >= crc_list.count then
1003 from
1004 crc_list.start
1005 matched := True
1006 until
1007 crc_list.after
1008 loop
1009 feature_i := crc_list.item.feature_item
1010 -- Check that all the creation procedures defined in the creation
1011 -- constraint clause `crc_list' are indeed present under a
1012 -- redefined/renamed version in the creation constraint clause
1013 from
1014 matched := False
1015 formal_crc_list.start
1016 until
1017 matched or else formal_crc_list.after
1018 loop
1019 matched := formal_crc_list.item.feature_item.rout_id_set.has (
1020 feature_i.rout_id_set.first)
1021 formal_crc_list.forth
1022 end
1023 -- If not matched save the feature to report a proper error.
1024 if not matched then
1025 if l_unmatched_features = Void then
1026 create {LINKED_LIST[FEATURE_I]} l_unmatched_features.make
1027 end
1028 l_unmatched_features.extend (feature_i)
1029 end
1030 crc_list.forth
1031 end
1032 else
1033 matched := False
1034 end
1035 else
1036 matched := False
1037 end
1038
1039 if not matched then
1040 generate_constraint_error (Current, formal_type,a_constraint_types, i, l_unmatched_features)
1041 end
1042 end
1043 end
1044
1045 expanded_deferred: BOOLEAN is
1046 -- Are the expanded class types present in the current generic
1047 -- type not based on deferred classes ?
1048 local
1049 i, nb: INTEGER
1050 gen_param: TYPE_A
1051 do
1052 from
1053 Result := Precursor {CL_TYPE_A}
1054 i := 1
1055 nb := generics.count
1056 until
1057 i > nb or else Result
1058 loop
1059 gen_param := generics.item (i)
1060 if gen_param.has_expanded then
1061 Result := gen_param.expanded_deferred
1062 end
1063 i := i + 1
1064 end
1065 end
1066
1067 valid_expanded_creation (a_class: CLASS_C): BOOLEAN is
1068 -- Is the expanded type has an associated class with one
1069 -- creation routine with no arguments only ?
1070 local
1071 i, nb: INTEGER
1072 gen_param: TYPE_A
1073 do
1074 from
1075 Result := Precursor {CL_TYPE_A} (a_class)
1076 i := 1
1077 nb := generics.count
1078 until
1079 i > nb or else not Result
1080 loop
1081 gen_param := generics.item (i)
1082 if gen_param.has_expanded then
1083 Result := gen_param.valid_expanded_creation (a_class)
1084 end
1085 i := i + 1
1086 end
1087 end
1088
1089 format (ctxt: TEXT_FORMATTER_DECORATOR) is
1090 local
1091 i, count: INTEGER
1092 do
1093 ctxt.put_classi (associated_class.lace_class)
1094 count := generics.count
1095
1096 -- TUPLE may have zero generic parameters
1097 if count > 0 then
1098 ctxt.put_space
1099 ctxt.process_symbol_text (ti_L_bracket)
1100 from
1101 i := 1
1102 until
1103 i > count
1104 loop
1105 generics.item (i).format (ctxt)
1106 if i /= count then
1107 ctxt.process_symbol_text (ti_Comma)
1108 ctxt.put_space
1109 end
1110 i := i + 1
1111 end
1112 ctxt.process_symbol_text (ti_R_bracket)
1113 end
1114 end
1115
1116 feature {NONE} -- Implementation
1117
1118 covariance_flags: PACKED_BOOLEANS
1119 -- Stores whether a generic at a certain position is marked covariant or not.
1120
1121 invariant
1122
1123 -- A generic class always has generic parameters
1124 generics_not_void: generics /= Void
1125
1126 indexing
1127 copyright: "Copyright (c) 1984-2006, Eiffel Software"
1128 license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)"
1129 licensing_options: "http://www.eiffel.com/licensing"
1130 copying: "[
1131 This file is part of Eiffel Software's Eiffel Development Environment.
1132
1133 Eiffel Software's Eiffel Development Environment is free
1134 software; you can redistribute it and/or modify it under
1135 the terms of the GNU General Public License as published
1136 by the Free Software Foundation, version 2 of the License
1137 (available at the URL listed under "license" above).
1138
1139 Eiffel Software's Eiffel Development Environment is
1140 distributed in the hope that it will be useful, but
1141 WITHOUT ANY WARRANTY; without even the implied warranty
1142 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1143 See the GNU General Public License for more details.
1144
1145 You should have received a copy of the GNU General Public
1146 License along with Eiffel Software's Eiffel Development
1147 Environment; if not, write to the Free Software Foundation,
1148 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1149 ]"
1150 source: "[
1151 Eiffel Software
1152 356 Storke Road, Goleta, CA 93117 USA
1153 Telephone 805-685-1006, Fax 805-685-6869
1154 Website http://www.eiffel.com
1155 Customer support http://support.eiffel.com
1156 ]"
1157
1158 end -- class GEN_TYPE_A
1159

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.23