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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 94983 - (show annotations)
Fri May 2 11:05:28 2014 UTC (5 years, 7 months ago) by jasonw
File size: 39152 byte(s)
<<Merged from trunk#94978.>>
1 note
2 description: "[
3 Set of types. This class encapsulates features to handle conformance and feature lookup on a set of types .
4 Refactoring:
5 TODO: This class could be made generic constrained to TYPE_A.
6 The issue is that the agent conformance does not allow it because some features become invalid.
7 TODO: feature_i_* and e_feature_* are very similar. Maybe get rid of e_feature_*?
8 ]"
9 author: ""
10 date: "$Date$"
11 revision: "$Revision$"
12
13 class
14 TYPE_SET_A
15
16 inherit
17 INTERNAL_COMPILER_STRING_EXPORTER
18 redefine
19 copy, is_equal
20 end
21
22 ITERABLE [RENAMED_TYPE_A]
23 redefine
24 copy, is_equal
25 end
26
27 COMPILER_EXPORTER
28 export
29 {NONE} all
30 redefine
31 copy, is_equal
32 end
33
34 SHARED_WORKBENCH
35 export
36 {NONE} all
37 redefine
38 copy, is_equal
39 end
40
41 SHARED_ERROR_HANDLER
42 export
43 {NONE} all
44 redefine
45 copy, is_equal
46 end
47
48 SHARED_NAMES_HEAP
49 export
50 {NONE} all
51 redefine
52 copy, is_equal
53 end
54
55 SHARED_ENCODING_CONVERTER
56 export
57 {NONE} all
58 redefine
59 copy, is_equal
60 end
61
62 create
63 make
64
65 feature {NONE} -- Initialization
66
67 make (n: INTEGER_32)
68 -- <Precursor>
69 do
70 create types.make (n)
71 types.compare_objects
72 end
73
74 feature -- Access
75
76 deferred_classes: ARRAYED_LIST [CLASS_C]
77 -- List of all classes that are deferred in the set.
78 do
79 create Result.make (types.count)
80 across types as l_renamed_type loop
81 if
82 attached l_renamed_type.item.base_class as l_class and then
83 l_class.is_deferred
84 then
85 Result.extend (l_class)
86 end
87 end
88 end
89
90 new_cursor: INDEXABLE_ITERATION_CURSOR [RENAMED_TYPE_A]
91 -- Fresh cursor associated with current structure
92 do
93 Result := types.new_cursor
94 end
95
96 instantiated_in (class_type: TYPE_A): TYPE_SET_A
97 local
98 l_instantiated_type, l_item_type: TYPE_A
99 i: INTEGER
100 do
101 from
102 start
103 i := 1
104 until
105 after
106 loop
107 l_item_type := item.type
108 l_instantiated_type := l_item_type.instantiated_in (class_type)
109 if l_instantiated_type /= l_item_type then
110 if Result = Void then
111 Result := twin
112 end
113 Result.put_i_th (create {RENAMED_TYPE_A}.make (l_instantiated_type, item.renaming), i)
114 end
115 i := i + 1
116 forth
117 end
118 if Result = Void then
119 Result := Current
120 end
121 end
122
123 feature_i_state_by_name_id (a_name_id: INTEGER): TUPLE [feature_item: FEATURE_I; class_type_of_feature: CL_TYPE_A; features_found_count: INTEGER; constraint_position: INTEGER]
124 -- Compute feature state.
125 --
126 -- `a_name_id': This is the `names_heap'-id of the feature name string.
127 -- Returns `feature_item' void if the feature cannot be found in the type set.
128 -- If there are multiple features found use `features_found_count' from the result tuple to find out how many.
129 -- Use features from the family `info_about_feature*' to get detailed information.
130 require
131 not_has_formal: not has_formal
132 local
133 l_last_feature, l_feature: FEATURE_I
134 l_class_type: CL_TYPE_A
135 l_last_class_type: CL_TYPE_A
136 l_features_found_count: INTEGER
137 l_renaming: RENAMING_A
138 l_constraint_position, i: INTEGER
139 l_feature_table: FEATURE_TABLE
140 l_item: RENAMED_TYPE_A
141 do
142 from
143 start
144 i := 1
145 until
146 after
147 loop
148 l_renaming := item.renaming
149 -- Example for comments: rename f as g end
150 -- `l_name_id' is the name id of `g'
151 l_item := item
152 if l_item.has_associated_class and then l_item.base_class.has_feature_table then
153 l_feature_table := l_item.base_class.feature_table
154 if l_renaming /= Void then
155 l_feature_table.search_id_under_renaming (a_name_id, l_renaming)
156 else
157 l_feature_table.search_id (a_name_id)
158 end
159
160 l_feature := l_feature_table.found_item
161 -- Duplicated code. Occurs also in `feature_i_state_by_rout_id'.
162 if
163 l_feature /= Void
164 then
165 l_class_type ?= l_item.type
166 -- This check is guaranteed by the precondition.
167 check l_class_type_not_void: l_class_type /= Void end
168 -- A "new" feature is found and we "count up" if...
169 if
170 -- we have not found anything so far,
171 l_last_class_type = Void or else
172 -- the class providing the feature changed or
173 not l_last_class_type.same_as (l_class_type) or else
174 -- the feature changed
175 not l_last_feature.equiv (l_feature)
176 then
177 -- Only if we found a true new static type we update our information.
178 l_last_class_type := l_class_type
179 l_constraint_position := i
180 l_last_feature := l_feature
181 l_features_found_count := l_features_found_count + 1
182 else
183 -- If it was the same static type that is ok because it does not change anything
184 -- regarding the dynamic binding.
185 -- G -> {COMPARABLE, COMPARABLE} is an example for such code.
186 -- There are more complex examples which lead to the same effect where it makes
187 -- more sense than this given example.
188 end
189 end
190
191 end
192 forth
193 i := i + 1
194 end
195 if l_features_found_count > 1 then
196 l_last_feature := Void
197 l_last_class_type := Void
198 end
199 Result := [l_last_feature, l_last_class_type, l_features_found_count, l_constraint_position]
200 ensure
201 -- It basically states that if there is exactly one feature you get the result, otherwise feature_item and class_of_feature are void.
202 result_not_void: Result /= Void
203 result_semantic_correct: Result.feature_item = Void implies (Result.class_type_of_feature = Void and Result.features_found_count /= 1)
204 result_semantic_correct: Result.features_found_count > 1 implies (Result.feature_item = Void and Result.class_type_of_feature = Void)
205 e_feature_relation: e_feature_state_by_name_id (a_name_id).features_found_count = Result.features_found_count
206 end
207
208 feature_i_list_by_rout_id (a_routine_id: INTEGER): ARRAYED_LIST [TUPLE[feature_item: FEATURE_I; class_type: RENAMED_TYPE_A]]
209 -- Builds a list of pairs of FEATURE_I and RENAMED_TYPE_A which all have a feature with routine id `a_routine_id'.
210 --
211 -- `a_routine_id' is the routine ID of the routine for which the list is built.
212 --| If you are just interested in any feature for a given routine id use `first_feature_i'
213 require
214 not_has_formal: not has_formal
215 local
216 l_class: CLASS_C
217 l_feat: FEATURE_I
218 l_item: RENAMED_TYPE_A
219 do
220 create Result.make (3)
221 from
222 start
223 until
224 after
225 loop
226 l_item := item
227 -- implied by precondition: not_loose
228 check has_associated_class: l_item.has_associated_class end
229 l_class := l_item.base_class
230 l_feat := l_class.feature_of_rout_id (a_routine_id)
231 if l_feat /= Void then
232 Result.extend ([l_feat, l_item])
233 end
234 forth
235 end
236 ensure
237 Result_not_void: Result /= Void
238 end
239
240 feature_i_state_by_alias_name_id (an_alias_name_id: INTEGER): like feature_i_state_by_alias_name
241 -- Compute feature state.
242 --
243 -- `an_alias' is a feature alias for which the state is computed.
244 -- Returns `feature_item' void if the feature cannot be found in the type set.
245 -- If there are multiple features found use `features_found_count' from the result tuple to find out how many.
246 -- Use features from the family `info_about_feature*' to get detailed information.
247 require
248 not_has_formal: not has_formal
249 local
250 l_last_feature, l_feature: FEATURE_I
251 l_class_c: CLASS_C
252 l_class_type, l_last_class_type: CL_TYPE_A
253 l_constraint_position, i: INTEGER
254 -- The Position at which the constraint where the feature was selected from is written.
255 l_features_found_count: INTEGER
256 l_item: RENAMED_TYPE_A
257 l_renaming: RENAMING_A
258 l_name_id: INTEGER
259 do
260 from
261 start
262 i := 1
263 until
264 after
265 loop
266 l_item := item
267 if l_item.has_associated_class then
268 l_renaming := l_item.renaming
269 l_class_c := l_item.base_class
270 if l_renaming = Void then
271 l_feature := l_class_c.feature_table.item_alias_id (an_alias_name_id)
272 else
273 l_name_id := l_renaming.renamed (an_alias_name_id)
274 if l_name_id > 0 then
275 if l_name_id = an_alias_name_id then
276 l_feature := l_class_c.feature_table.item_alias_id (l_name_id)
277 else
278 l_feature := l_class_c.feature_table.item_id (l_name_id)
279 end
280 else
281 l_feature := Void
282 end
283 end
284
285 if l_feature /= Void then
286 l_class_type ?= l_item.type
287 -- Precondition should ensure this.
288 check class_type_not_void: l_class_type /= Void end
289 -- A "new" feature is found and we "count up" if...
290 if
291 -- we have not found anything so far,
292 l_last_class_type = Void or else
293 -- the class providing the feature changed or
294 not l_last_class_type.same_as (l_class_type) or else
295 -- the feature changed
296 not l_last_feature.equiv (l_feature)
297 then
298 l_constraint_position := i
299 l_last_feature := l_feature
300 l_last_class_type := l_class_type
301 l_features_found_count := l_features_found_count + 1
302 else
303 -- See `feature_i_state_by_name_id' for more comments.
304 end
305
306 end
307 end
308 forth
309 i := i + 1
310 end
311 if l_features_found_count > 1 then
312 l_last_feature := Void
313 l_last_class_type := Void
314 end
315 Result := [l_last_feature, l_last_class_type, l_features_found_count, l_constraint_position]
316 ensure
317 -- It basically states that if there is exactly one feature you get the result, otherwise feature_item and class_of_feature are void.
318 result_not_void: Result /= Void
319 result_semantic_correct: Result.feature_item = Void implies (Result.class_type_of_feature = Void and Result.features_found_count /= 1)
320 result_semantic_correct: Result.features_found_count > 1 implies (Result.feature_item = Void and Result.class_type_of_feature = Void)
321 end
322
323 e_feature_state_by_name_32 (a_name: STRING_32): TUPLE [feature_item: E_FEATURE; class_type_of_feature: CL_TYPE_A; features_found_count: INTEGER; constraint_position: INTEGER]
324 -- Compute feature state.
325 --
326 -- `a_name' is the name of the feature.
327 -- Returns `feature_item' void if the feature cannot be found in the type set.
328 -- If there are multiple features found use `features_found_count' from the result tuple to find out how many.
329 -- Use features from the family `info_about_feature*' to get detailed information.
330 require
331 a_name_not_void: a_name /= Void
332 not_has_formal: not has_formal
333 do
334 Result := e_feature_state_by_name_id (names_heap.id_of (encoding_converter.utf32_to_utf8 (a_name)))
335 ensure
336 feature_i_relation: feature_i_state_by_name_id (names_heap.id_of (encoding_converter.utf32_to_utf8 (a_name))).features_found_count = Result.features_found_count
337 end
338
339 e_feature_state_by_name_id (a_name_id: INTEGER): TUPLE [feature_item: E_FEATURE; class_type_of_feature: CL_TYPE_A; features_found_count: INTEGER; constraint_position: INTEGER]
340 -- Compute feature state.
341 --
342 -- `a_name_id': It is the `names_heap'-id of the feature name string.
343 -- Returns `feature_item' void if the feature cannot be found in the type set.
344 -- If there are multiple features found use `features_found_count' from the result tuple to find out how many.
345 -- Use features from the family `info_about_feature*' to get detailed information.
346 require
347 not_has_formal: not has_formal
348 local
349 l_item: RENAMED_TYPE_A
350 l_last_feature: E_FEATURE
351 l_feature, l_last_feature_i: FEATURE_I
352 l_last_class_type: CL_TYPE_A
353 l_class_c: CLASS_C
354 l_features_found_count: INTEGER
355 l_renaming: RENAMING_A
356 l_constraint_position, i: INTEGER
357 l_feature_table: FEATURE_TABLE
358 l_class_type: CL_TYPE_A
359 do
360 from
361 start
362 i := 1
363 until
364 after
365 loop
366 l_item := item
367 l_renaming := l_item.renaming
368 -- Example for comments: rename f as g end
369 -- `l_name_id' is the name id of `g'
370 if l_item.has_associated_class then
371 l_class_c := l_item.base_class
372 if l_class_c.has_feature_table then
373 l_feature_table := l_class_c.feature_table
374 if l_renaming /= Void then
375 l_feature_table.search_id_under_renaming (a_name_id, l_renaming)
376 else
377 l_feature_table.search_id (a_name_id)
378 end
379
380 l_feature := l_feature_table.found_item
381
382 if
383 l_feature /= Void
384 then
385 l_class_type ?= item.type
386 -- This check is guaranteed by the precondition.
387 check l_class_type_not_void: l_class_type /= Void end
388 -- A "new" feature is found and we "count up" if...
389 if
390 -- we have not found anything so far,
391 l_last_class_type = Void or else
392 -- the class providing the feature changed or
393 not l_last_class_type.same_as (l_class_type) or else
394 -- the feature changed
395 not l_last_feature_i.equiv (l_feature)
396 then
397 l_constraint_position := i
398 l_last_feature_i := l_feature
399 l_last_feature := l_feature.api_feature (l_class_c.class_id)
400 l_last_class_type := l_class_type
401 l_features_found_count := l_features_found_count + 1
402 end
403 end
404 end
405 end
406 forth
407 i := i + 1
408 end
409 if l_features_found_count /= 1 then
410 l_last_feature := Void
411 l_last_class_type := Void
412 end
413 Result := [l_last_feature, l_last_class_type, l_features_found_count, l_constraint_position]
414 ensure
415 -- It basically states that if there is exactly one feature you get the result, otherwise feature_item and class_of_feature are void.
416 result_not_void: Result /= Void
417 result_semantic_correct: Result.feature_item = Void implies (Result.class_type_of_feature = Void and Result.features_found_count /= 1)
418 result_semantic_correct: Result.features_found_count > 1 implies (Result.feature_item = Void and Result.class_type_of_feature = Void)
419 feature_i_relation: feature_i_state_by_name_id (a_name_id).features_found_count = Result.features_found_count
420 end
421
422 e_feature_list_by_rout_id (a_routine_id: INTEGER): ARRAYED_LIST[TUPLE[feature_item: E_FEATURE; class_type: RENAMED_TYPE_A]]
423 --
424 require
425 not_has_formal: not has_formal
426 local
427 l_class: CLASS_C
428 l_feat: E_FEATURE
429 l_item: RENAMED_TYPE_A
430 do
431 create Result.make (3)
432 from
433 start
434 until
435 after
436 loop
437 l_item := item
438 -- implied by precondition: not_loose
439 check has_associated_class: l_item.has_associated_class end
440 l_class := l_item.base_class
441 l_feat := l_class.feature_with_rout_id (a_routine_id)
442 if l_feat /= Void then
443 Result.extend ([l_feat, l_item])
444 end
445 forth
446 end
447 ensure
448 Result_not_void: Result /= Void
449 end
450
451 associated_classes: ARRAYED_LIST [CLASS_C]
452 -- All associated classes of the current type set.
453 do
454 create Result.make (types.count)
455 across types as l_renamed_type loop
456 if l_renamed_type.item.has_associated_class then
457 Result.extend (l_renamed_type.item.base_class)
458 end
459 end
460 end
461
462 feature {INTERNAL_COMPILER_STRING_EXPORTER} -- Access
463
464 feature_i_state_by_alias_name (an_alias_name: STRING): TUPLE [feature_item: FEATURE_I; class_type_of_feature: CL_TYPE_A; features_found_count: INTEGER; constraint_position: INTEGER]
465 -- Compute feature state.
466 --
467 -- `an_alias_name': A feature alias for which the state is computed.
468 -- Returns `feature_item' void if the feature cannot be found in the type set.
469 -- If there are multiple features found use `features_found_count' from the result tuple to find out how many.
470 -- Use features from the family `info_about_feature*' to get detailed information.
471 require
472 an_alias_name_not_void: an_alias_name /= Void
473 not_has_formal: not has_formal
474 do
475 Result := feature_i_state_by_alias_name_id (names_heap.id_of (an_alias_name))
476 ensure
477 -- It basically states that if there is exactly one feature you get the result, otherwise feature_item and class_of_feature are void.
478 result_not_void: Result /= Void
479 result_semantic_correct: Result.feature_item = Void implies (Result.class_type_of_feature = Void and Result.features_found_count /= 1)
480 result_semantic_correct: Result.features_found_count > 1 implies (Result.feature_item = Void and Result.class_type_of_feature = Void)
481 end
482
483 feature -- Access for Error handling
484
485 info_about_feature_by_name_id (a_name_id: INTEGER; a_formal_position: INTEGER; a_context_class: CLASS_C): MC_FEATURE_INFO
486 -- Gathers information about a feature.
487 --
488 -- `a_name_id' is the name ID of the feature for which information is gatherd.
489 -- `a_formal_position' position of the formal to which this typeset belongs.
490 -- `a_context_class' is the class where the formal (denoted by `a_formal_position') has been defined.
491 require
492 a_name_id_valid: a_name_id > 0
493 a_context_class_not_void_if_needed: has_formal implies a_context_class /= Void
494 local
495 l_feature_agent: FUNCTION [ANY, TUPLE [RENAMED_TYPE_A], TUPLE [e_feature: E_FEATURE; feature_i: FEATURE_I]]
496 do
497 l_feature_agent :=
498 agent (g_name_id: INTEGER; a_ext_type: RENAMED_TYPE_A): TUPLE [E_FEATURE,FEATURE_I]
499 local
500 l_renamed_id: INTEGER
501 l_class: CLASS_C
502 do
503 if a_ext_type.has_associated_class then
504 l_class := a_ext_type.base_class
505 if l_class.has_feature_table then
506 if a_ext_type.has_renaming then
507 l_renamed_id := a_ext_type.renaming.renamed (g_name_id)
508 else
509 l_renamed_id := g_name_id
510 end
511 if l_renamed_id > 0 then
512 Result := [ l_class.feature_with_name_id (l_renamed_id),
513 l_class.feature_of_name_id (l_renamed_id)]
514 end
515 end
516 end
517 end (a_name_id, ?)
518 Result := info_about_feature_by_agent (l_feature_agent, a_formal_position, a_context_class, create {SEARCH_TABLE [INTEGER]}.make (3))
519 Result.set_data (names_heap.item (a_name_id), a_formal_position, a_context_class)
520 ensure
521 Result_not_void: Result /= Void
522 end
523
524 info_about_feature_by_alias_name_id (a_name_id: INTEGER; a_formal_position: INTEGER; a_context_class: CLASS_C): MC_FEATURE_INFO
525 -- Gathers information about a feature.
526 --
527 -- `a_name_id' is the name ID of the feature for which information is gatherd.
528 -- `a_formal_position' position of the formal to which this typeset belongs.
529 -- `a_context_class' is the class where the formal (denoted by `a_formal_position') has been defined.
530 require
531 a_name_id_valid: a_name_id > 0
532 a_context_class_not_void_if_needed: has_formal implies a_context_class /= Void
533 local
534 l_feature_agent: FUNCTION [ANY, TUPLE [RENAMED_TYPE_A], TUPLE [e_feature: E_FEATURE; feature_i: FEATURE_I]]
535 do
536 l_feature_agent :=
537 agent (g_name_id: INTEGER; a_ext_type: RENAMED_TYPE_A): TUPLE [E_FEATURE,FEATURE_I]
538 local
539 l_renamed_id: INTEGER
540 l_class: CLASS_C
541 l_feature: FEATURE_I
542 do
543 if a_ext_type.has_associated_class then
544 l_class := a_ext_type.base_class
545 if l_class.has_feature_table then
546 if a_ext_type.has_renaming then
547 l_renamed_id := a_ext_type.renaming.renamed (g_name_id)
548 if l_renamed_id > 0 then
549 if l_renamed_id = g_name_id then
550 l_feature := l_class.feature_table.item_alias_id (l_renamed_id)
551 else
552 l_feature := l_class.feature_table.item_id (l_renamed_id)
553 end
554 end
555 else
556 l_feature := l_class.feature_table.item_alias_id (g_name_id)
557 end
558 if l_feature /= Void then
559 Result := [l_feature.api_feature (l_class.class_id), l_feature]
560 end
561 end
562 end
563 end (a_name_id, ?)
564 Result := info_about_feature_by_agent (l_feature_agent, a_formal_position, a_context_class, create {SEARCH_TABLE [INTEGER]}.make (3))
565 Result.set_data (names_heap.item (a_name_id), a_formal_position, a_context_class)
566 ensure
567 Result_not_void: Result /= Void
568 end
569
570 info_about_feature_by_rout_id (a_routine_id: INTEGER; a_formal_position: INTEGER; a_context_class: CLASS_C): MC_FEATURE_INFO
571 -- Gathers information about a feature.
572 --
573 -- `a_routine_id' is the ID for the feature for which information is gatherd.
574 -- `a_formal_position' is used together with `a_context_class' to query the constraint list.
575 -- `a_context_class' is used together with `a_formal_position' to query the constraint list.
576 require
577 a_context_class_not_void_if_needed: has_formal implies a_context_class /= Void
578 local
579 l_feature_agent: FUNCTION[ANY,TUPLE [RENAMED_TYPE_A], TUPLE [e_feature: E_FEATURE; feature_i: FEATURE_I]]
580 do
581 l_feature_agent :=
582 agent (g_routine_id: INTEGER; l_ext_type: RENAMED_TYPE_A): TUPLE [E_FEATURE,FEATURE_I]
583 -- Note that `g_renaming' is not used for routine id.
584 local
585 l_class: CLASS_C
586 do
587 -- If somehow possible try to find the feature.
588 if l_ext_type.has_associated_class then
589 l_class := l_ext_type.base_class
590 if l_class.has_feature_table then
591 Result := [ l_class.feature_with_rout_id (g_routine_id),
592 l_class.feature_of_rout_id (g_routine_id)]
593 else
594 -- Result := Void
595 end
596 end
597 end (a_routine_id, ?)
598 Result := info_about_feature_by_agent (l_feature_agent, a_formal_position, a_context_class, create {SEARCH_TABLE [INTEGER]}.make (3))
599 Result.set_data (Void, a_formal_position, a_context_class)
600 ensure
601 Result_not_void: Result /= Void
602 end
603
604 feature {TYPE_SET_A} -- Access implementation
605
606 info_about_feature_by_agent (a_feature: FUNCTION [ANY, TUPLE [RENAMED_TYPE_A], TUPLE [e_feature: E_FEATURE; feature_i: FEATURE_I]]; a_formal_position: INTEGER; a_context_class: CLASS_C; a_visited_formals: SEARCH_TABLE [INTEGER]): like info_about_feature_by_rout_id
607 -- Gather information about feature
608 --
609 -- `a_feature' is an agent which returns information about a feature given a `CLASS_C' instance.
610 -- `a_formal_position' is the position of the formal to which this typeset belongs.
611 -- `a_context_class' is the context class where the formals are defined.
612 -- `a_visited_formals' used to break recursion. Simply pass an empty one if your start the recursion.
613 require
614 a_feature_not_void: a_feature /= Void
615 a_visited_formals_not_void: has_formal implies a_visited_formals /= Void
616 a_context_class_not_void_if_needed: has_formal implies a_context_class /= Void
617 local
618 l_item: RENAMED_TYPE_A
619 l_item_type: TYPE_A
620 l_formal: FORMAL_A
621 l_formal_position: INTEGER
622 l_query_result: TUPLE [e_feature: E_FEATURE; feature_i: FEATURE_I]
623 i: INTEGER
624 do
625 create Result.make
626
627 from
628 start
629 i := 1
630 until
631 after
632 loop
633 l_item := item
634 l_item_type := l_item.type
635 if l_item_type.is_formal then
636 l_formal ?= l_item_type
637 -- The precondition ensures this:
638 check a_context_class_not_void: a_context_class /= Void end
639 -- Recursion
640 l_formal_position := l_formal.position
641 if not a_visited_formals.has (l_formal_position) then
642 a_visited_formals.put (l_formal_position)
643 Result.merge_right (l_formal.constraints (a_context_class).info_about_feature_by_agent(a_feature, l_formal_position, a_context_class, a_visited_formals))
644 end
645 else
646 if l_item.has_associated_class then
647 l_query_result := a_feature.item ([l_item])
648 -- Check whether we found at least something useful and then insert an entry.
649 if l_query_result /= Void and then (l_query_result.e_feature /= Void or l_query_result.feature_i /= Void) then
650 Result.extend([l_query_result.feature_i, l_query_result.e_feature, l_item, a_formal_position, i])
651 end
652 end
653 end
654 i := i + 1
655 forth
656 end
657 ensure
658 Result_not_void: Result /= Void
659 end
660
661 feature -- Conversion
662
663 substitude_formals (a_generic_context_type: GEN_TYPE_A)
664 -- Replaces (!) formal types with their generic derivation.
665 --
666 -- `a_generic_context_type' is the supplier of the actual generics
667 require
668 a_generic_context_type_not_void: a_generic_context_type /= Void
669 local
670 l_formal: FORMAL_A
671 l_gen_type: GEN_TYPE_A
672 l_item_type: TYPE_A
673 do
674 from
675 start
676 until
677 after
678 loop
679 l_item_type := item.type
680 l_formal ?= l_item_type
681 if l_formal /= Void then
682 item.set_type (a_generic_context_type.generics [l_formal.position])
683 else
684 l_gen_type ?= l_item_type
685 if l_gen_type /= Void then
686 l_gen_type.substitute (a_generic_context_type.generics)
687 end
688 end
689 forth
690 end
691 end
692
693 feature -- Duplication
694
695 copy (other: like Current)
696 -- <Precursor>
697 do
698 if other /= Current then
699 if types = Void or else types = other.types then
700 types := other.types.twin
701 else
702 types.wipe_out
703 types.append (other.types)
704 end
705 end
706 end
707
708 feature -- Comparison
709
710 is_equal (other: like Current): BOOLEAN
711 -- <Precursor>
712 do
713 Result := types.is_equal (other.types)
714 end
715
716 conform_to (a_context_class: CLASS_C; a_other: like Current): BOOLEAN
717 -- Is `Current' conform to `a_other' in `a_context_class'?
718 -- `a_other' will be modified. Elements will be removed.
719 -- So pass a copy if you still need it after this call.
720 require
721 a_context_class_not_void: a_context_class /= Void
722 a_context_class_valid: a_context_class.is_valid
723 a_context_valid_for_current: is_valid_for_class (a_context_class)
724 a_other_not_void: a_other /= Void
725 do
726 -- Each element in `Current' must be conform to each other element in `a_other'
727 from
728 start
729 until
730 after or a_other.is_empty
731 loop
732 from
733 a_other.start
734 until
735 a_other.after
736 loop
737 if item.type.conform_to (a_context_class, a_other.item.type) then
738 a_other.remove
739 elseif not a_other.after then
740 a_other.forth
741 end
742 end
743 forth
744 end
745
746 if a_other.is_empty then
747 Result := True
748 end
749 a_other.wipe_out
750 -- This is not necessary but will hopefully prevent further usage
751 end
752
753 conform_to_type (a_context_class: CLASS_C; a_type: TYPE_SET_A): BOOLEAN
754 -- Is `Current' conform to `a_type' in `a_context_class'?
755 local
756 l_type: TYPE_A
757 do
758 if a_type.count > 1 then
759 Result := conform_to (a_context_class, a_type.twin)
760 else
761 -- If at least one element of `Current' conforms to `a_type' then the type set conforms to the type.
762 Result := False
763 l_type := a_type.first.type
764 from
765 start
766 until
767 after or Result
768 loop
769 Result := item.type.conform_to (a_context_class, l_type.conformance_type)
770 forth
771 end
772 end
773 end
774
775 feature -- Output
776
777 frozen append_to (a_text_formatter: TEXT_FORMATTER)
778 -- Append `Current' to `text'.
779 do
780 ext_append_to (a_text_formatter, Void)
781 end
782
783 ext_append_to (a_text_formatter: TEXT_FORMATTER; c: CLASS_C)
784 -- Append `Current' to `text'.
785 -- `c' is used to retreive the generic type or argument name as string.
786 do
787 check first /= Void end
788 if count > 1 then
789 a_text_formatter.add ("{" )
790 end
791 first.ext_append_to (a_text_formatter,c)
792 from
793 start
794 forth
795 until
796 after
797 loop
798 a_text_formatter.add ("," )
799 item.ext_append_to (a_text_formatter,c)
800 forth
801 end
802 if count > 1 then
803 a_text_formatter.add ("}" )
804 end
805 end
806
807 feature -- Status
808
809 has_expanded: BOOLEAN
810 -- Does the current type set contain the NONE type?
811 do
812 Result := across types as l_renamed_type some l_renamed_type.item.type.is_expanded end
813 end
814
815 has_none: BOOLEAN
816 -- Does the current type set contain the NONE type?
817 do
818 Result := across types as l_renamed_type some l_renamed_type.item.type.is_none end
819 end
820
821 is_class_valid: BOOLEAN
822 -- Is the type set valid, meaning that all items are valid items?
823 do
824 Result := across types as l_renamed_type all l_renamed_type.item.type.is_class_valid end
825 end
826
827 is_loose: BOOLEAN
828 -- Is at least one of the types om the type set a loose type (`is_loose')?
829 do
830 Result := across types as l_renamed_type some l_renamed_type.item.type.is_loose end
831 end
832
833 has_formal: BOOLEAN
834 -- Does the current set contain a formal type?
835 --| A generic (GEN_TYPE_A) which has a formal type parameter is not counted.
836 do
837 Result := across types as l_renamed_type some l_renamed_type.item.type.is_formal end
838 end
839
840 has_deferred: BOOLEAN
841 -- Does the current set contain a deferred class?
842 do
843 Result := across types as l_renamed_type some l_renamed_type.item.has_associated_class and then l_renamed_type.item.base_class.is_deferred end
844 end
845
846 is_attached: BOOLEAN
847 -- <Precursor>
848 do
849 Result := across types as l_renamed_type some l_renamed_type.item.type.is_attached end
850 end
851
852 is_expanded: BOOLEAN
853 -- Is the current actual type an expanded one ?
854 do
855 Result := across types as l_renamed_type all l_renamed_type.item.type.is_expanded end
856 end
857
858 frozen is_valid: BOOLEAN
859 -- Is current a valid declaration by itself?
860 do
861 Result := across types as l_renamed_type all l_renamed_type.item.type.is_valid end
862 ensure
863 true_implication: is_valid implies is_class_valid
864 false_implication: not is_class_valid implies not is_valid
865 end
866
867 frozen is_valid_for_class (a_class: CLASS_C): BOOLEAN
868 -- Is current valid for a declaration in `a_class'?
869 require
870 a_class_not_void: a_class /= Void
871 a_class_valid: a_class.is_valid
872 do
873 Result := across types as l_renamed_type all l_renamed_type.item.type.is_valid_for_class (a_class) end
874 end
875
876 feature -- Access
877
878 constraining_types (a_context_class: CLASS_C): TYPE_SET_A
879 -- Constraining types of `a_type'.
880 --| A generic (GEN_TYPE_A) which has a formal type parameter is not counted, but all chains of formals like [G->H, H->I,I->STRING] are resolved.
881 --| Recursive formals fall back to ANY.
882 --| This feature cannot be used straight forward for any kind of conformance checking, but certainly is well suited for things like looking up a feature.
883 --| You may run into troubles because we loose information if we delete the resursive chain like [G->H,H->G] we loose the fact that G and H actually are identical.
884 require
885 a_context_classt_not_void: a_context_class /= Void
886 local
887 l_type_set_item: TYPE_A
888 l_formal_type: FORMAL_A
889 do
890 if has_formal then
891 create Result.make (count +2)
892 from
893 start
894 until
895 after
896 loop
897 l_type_set_item := item.type
898
899 -- We have to get rid of all formals occurring somewhere (be it a generic type or a typeset)
900 -- `has_generic' is more expensive forTYPE_SET_A
901 if l_type_set_item.is_formal then
902 l_formal_type ?= l_type_set_item
903 -- An Item which has already been asked for but has not been resolved so far is a circle
904 -- We want to avoid inifinite recursion, therefore we break here and
905 -- fall back to ANY, which is the proper solution for a cycle in the constraints like [G->G], [G->H, H->G], ...
906 -- If we have something like G-> {G, STRING}, STRING will be returned as the constraint.
907 if not formal_resolution_stack.has (l_formal_type.position) then
908 -- Push the current item
909 formal_resolution_stack.put (l_formal_type.position)
910 Result.types.append (l_formal_type.constraints (a_context_class).constraining_types (a_context_class).types)
911 -- Pop the current item
912 formal_resolution_stack.remove
913 end
914 else
915 Result.extend (item)
916 end
917 forth
918 end
919 if Result.is_empty and formal_resolution_stack.is_empty then
920 -- if formal_resolution_stack.is_empty we are at the end of computation.
921 Result.extend (create {RENAMED_TYPE_A}.make (create {CL_TYPE_A}.make (system.any_id), Void))
922 end
923 --| Martins 1/23/07:
924 --| We do not remove duplicates as one can rename features differently.
925 --| G -> {H rename f as f_h1 end, H rename f as f_h2 end}
926 --| Martins 2/19/07:
927 --| There are no duplicates because it's not allowed anymore. This is ensured by special check feature.
928 else
929 Result := Current
930 end
931 ensure
932 result_not_void: Result /= Void
933 only_changed_if_necessary: not old has_formal implies Result = Current
934 not_has_formal: not Result.has_formal
935 end
936
937 constraining_types_if_possible (a_context_class: CLASS_C): TYPE_SET_A
938 -- Fault tolerant constraining types of `a_type'.
939 -- Use it for feature lookups in faulty systems.
940 --
941 -- `a_context_class' is the context in which the formals are evaluated.
942 --| A generic (GEN_TYPE_A) which has a formal type parameter is not counted, but all chains of formals like [G->H, H->I,I->STRING] are resolved.
943 --| Recursive formals fall back to ANY.
944 --| This feature cannot be used straight forward for any kind of conformance checking, but certainly is well suited for things like looking up a feature.
945 --| You may run into troubles because we loose information if we delete the resursive chain like [G->H,H->G] we loose the fact that G and H actually are identical.
946 require
947 a_context_classt_not_void: a_context_class /= Void
948 local
949 l_type_set_item: TYPE_A
950 l_formal_type: FORMAL_A
951 do
952 if has_formal then
953 create Result.make (count +2)
954 from
955 start
956 until
957 after
958 loop
959 l_type_set_item := item.type
960
961 -- We have to get rid of all formals occurring somewhere (be it a generic type or a typeset)
962 -- `has_generic' is more expensive for TYPE_SET_A
963 if l_type_set_item.is_formal then
964 l_formal_type ?= l_type_set_item
965 -- An Item which has already been asked for but has not been resolved so far is a circle
966 -- We want to avoid inifinite recursion, therefore we break here and
967 -- fall back to ANY, which is the proper solution for a cycle in the constraints like [G->G], [G->H, H->G], ...
968 -- If we have something like G-> {G, STRING}, STRING will be returned as the constraint.
969 if not formal_resolution_stack.has (l_formal_type.position) then
970 -- Push the current item
971 formal_resolution_stack.put (l_formal_type.position)
972 Result.types.append (l_formal_type.constraints_if_possible (a_context_class).constraining_types_if_possible (a_context_class).types)
973 -- Pop the current item
974 formal_resolution_stack.remove
975 end
976 end
977 forth
978 end
979 if Result.is_empty and formal_resolution_stack.is_empty then
980 -- if formal_resolution_stack.is_empty we are at the end of computation.
981 Result.extend (create {RENAMED_TYPE_A}.make (create {CL_TYPE_A}.make (system.any_id), Void))
982 end
983 --| Martins 1/23/07:
984 --| We do not remove duplicates as one can rename features differently.
985 --| G -> {H rename f as f_h1 end, H rename f as f_h2 end}
986 --| Martins 2/19/07:
987 --| There are no duplicates because it's not allowed anymore. This is ensured by a special check feature.
988 else
989 Result := Current
990 end
991 ensure
992 result_not_void: Result /= Void
993 only_changed_if_necessary: not old has_formal implies Result = Current
994 not_has_formal: not Result.has_formal
995 end
996
997 feature -- Attachment and separateness properties
998
999 to_other_attachment (other: TYPE_A): like Current
1000 -- Current type to which attachment status of `other' is applied
1001 local
1002 i: INTEGER
1003 r: RENAMED_TYPE_A
1004 t: TYPE_A
1005 a: TYPE_A
1006 do
1007 Result := Current
1008 from
1009 i := count
1010 until
1011 i <= 0
1012 loop
1013 r := types.i_th (i)
1014 t := r.type
1015 a := t.to_other_attachment (other)
1016 if a /= t then
1017 -- The type is different from what we have in the current one.
1018 r := r.twin
1019 r.set_type (a)
1020 if Result = Current then
1021 -- Avoid changing current type descriptor.
1022 Result := twin
1023 end
1024 Result.types.put_i_th (r, i)
1025 end
1026 i := i - 1
1027 end
1028 end
1029
1030 to_other_separateness (other: TYPE_A): like Current
1031 -- Current type to which separateness status of `other' is applied.
1032 local
1033 i: INTEGER
1034 r: RENAMED_TYPE_A
1035 t: TYPE_A
1036 a: TYPE_A
1037 do
1038 Result := Current
1039 from
1040 i := count
1041 until
1042 i <= 0
1043 loop
1044 r := types.i_th (i)
1045 t := r.type
1046 a := t.to_other_separateness (other)
1047 if a /= t then
1048 -- The type is different from what we have in the current one.
1049 r := r.twin
1050 r.set_type (a)
1051 if Result = Current then
1052 -- Avoid changing current type descriptor.
1053 Result := twin
1054 end
1055 Result.types.put_i_th (r, i)
1056 end
1057 i := i - 1
1058 end
1059 end
1060
1061 to_other_variant (other: TYPE_A): like Current
1062 -- Current type to which separateness status of `other' is applied.
1063 local
1064 i: INTEGER
1065 r: RENAMED_TYPE_A
1066 t: TYPE_A
1067 a: TYPE_A
1068 do
1069 Result := Current
1070 from
1071 i := count
1072 until
1073 i <= 0
1074 loop
1075 r := types.i_th (i)
1076 t := r.type
1077 a := t.to_other_variant (other)
1078 if a /= t then
1079 -- The type is different from what we have in the current one.
1080 r := r.twin
1081 r.set_type (a)
1082 if Result = Current then
1083 -- Avoid changing current type descriptor.
1084 Result := twin
1085 end
1086 Result.types.put_i_th (r, i)
1087 end
1088 i := i - 1
1089 end
1090 end
1091
1092 feature {NONE} -- Implementation
1093
1094 formal_resolution_stack: ARRAYED_STACK [INTEGER]
1095 -- A stack which is used to prohibit inifinite recursion while resolving a formal type to its constraining type set.
1096 once
1097 create Result.make (3)
1098 end
1099
1100 feature -- Convenience to be removed later
1101
1102 types: ARRAYED_LIST [RENAMED_TYPE_A]
1103
1104 renamed_types: ARRAYED_LIST [TYPE_A]
1105 do
1106 create Result.make (types.count)
1107 across types as l_renamed_type loop
1108 Result.extend (l_renamed_type.item.type)
1109 end
1110 end
1111 count: INTEGER
1112 do
1113 Result := types.count
1114 end
1115
1116 start
1117 do
1118 types.start
1119 end
1120
1121 after: BOOLEAN
1122 do
1123 Result := types.after
1124 end
1125
1126 forth
1127 do
1128 types.forth
1129 end
1130
1131 item: RENAMED_TYPE_A
1132 do
1133 Result := types.item
1134 end
1135
1136 extend (v: like item)
1137 do
1138 types.extend (v)
1139 end
1140
1141 is_empty: BOOLEAN
1142 do
1143 Result := types.is_empty
1144 end
1145
1146 first: like item
1147 do
1148 Result := types.first
1149 end
1150
1151 wipe_out
1152 do
1153 types.wipe_out
1154 end
1155
1156 i_th (i: INTEGER): like item
1157 do
1158 Result := types.i_th (i)
1159 end
1160
1161 put_i_th (v: like item; i: INTEGER)
1162 do
1163 types.put_i_th (v, i)
1164 end
1165
1166 remove
1167 do
1168 types.remove
1169 end
1170 note
1171 copyright: "Copyright (c) 1984-2014, Eiffel Software"
1172 license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)"
1173 licensing_options: "http://www.eiffel.com/licensing"
1174 copying: "[
1175 This file is part of Eiffel Software's Eiffel Development Environment.
1176
1177 Eiffel Software's Eiffel Development Environment is free
1178 software; you can redistribute it and/or modify it under
1179 the terms of the GNU General Public License as published
1180 by the Free Software Foundation, version 2 of the License
1181 (available at the URL listed under "license" above).
1182
1183 Eiffel Software's Eiffel Development Environment is
1184 distributed in the hope that it will be useful, but
1185 WITHOUT ANY WARRANTY; without even the implied warranty
1186 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1187 See the GNU General Public License for more details.
1188
1189 You should have received a copy of the GNU General Public
1190 License along with Eiffel Software's Eiffel Development
1191 Environment; if not, write to the Free Software Foundation,
1192 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1193 ]"
1194 source: "[
1195 Eiffel Software
1196 5949 Hollister Ave., Goleta, CA 93117 USA
1197 Telephone 805-685-1006, Fax 805-685-6869
1198 Website http://www.eiffel.com
1199 Customer support http://support.eiffel.com
1200 ]"
1201 end

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.23