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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 94740 - (show annotations)
Fri Mar 28 09:42:08 2014 UTC (5 years, 8 months ago) by jasonw
File size: 12510 byte(s)
<<Merged from trunk#94739.>>
1 ´╗┐note
2 description: "Unknown type of a local variable."
3
4 class
5 LOCAL_TYPE_A
6
7 inherit
8 UNKNOWN_TYPE_A
9 redefine
10 backward_conform_to,
11 dump,
12 ext_append_to,
13 hash_code,
14 internal_conform_to,
15 is_computable,
16 is_equivalent,
17 process,
18 same_as
19 end
20
21 SHARED_TYPES
22
23 create
24 make
25
26 feature {NONE} -- Initialization
27
28 make (p: like position; any_type: TYPE_A; context_class: CLASS_C)
29 -- Initialize a type for a local at position `p'.
30 do
31 create lower_bound.make (1)
32 create upper_bound.make (1)
33 position := p
34 is_computable := True
35 lower_bound.extend (Void, [context_class, none_type.as_attached_type, False])
36 upper_bound.extend (Void, [context_class, any_type, False])
37 ensure
38 position_set: position = p
39 end
40
41 feature -- Status report
42
43 is_computable: BOOLEAN
44 -- <Precursor>
45 -- This is set to `False' when type computation depends on types that were not computed yet or when associated type set changes.
46
47 feature -- Status setting
48
49 reset
50 -- Prepare this object to a new cycle of type information collection.
51 do
52 -- Assume that the type information collected so far is stable.
53 is_computable := True
54 end
55
56 feature -- Access
57
58 hash_code: INTEGER
59 -- <Precursor>
60 do
61 -- Avoid collisions with `{FORMAL_A}.hash_code'.
62 Result := ({SHARED_HASH_CODE}.other_code - position).abs
63 end
64
65 feature -- Comparison
66
67 is_equivalent (other: like Current): BOOLEAN
68 -- Is `other' equivalent to the current object ?
69 do
70 Result := position = other.position
71 end
72
73 backward_conform_to (a_context_class: CLASS_C; other: TYPE_A): BOOLEAN
74 -- <Precursor>
75 do
76 -- `Result = true', but type information may be recorded by this call.
77 Precursor (a_context_class, other).do_nothing
78 -- Collect type information.
79 add_lower_bound (a_context_class, other, False)
80 -- Assume that the code is correct.
81 Result := True
82 end
83
84 feature -- Access
85
86 position: INTEGER
87 -- Position in the local list.
88
89 feature -- Comparison
90
91 same_as (other: TYPE_A): BOOLEAN
92 -- Is the current type the same as `other' ?
93 do
94 Result := attached {LOCAL_TYPE_A} other as t and then is_equivalent (t)
95 end
96
97 feature -- Visitor
98
99 process (v: TYPE_A_VISITOR)
100 -- <Precursor>
101 do
102 v.process_local (Current)
103 end
104
105 process_lower (v: TYPE_A_VISITOR)
106 -- Process all lower bounds with `v'.
107 do
108 across
109 lower_bound as i
110 loop
111 i.key.type.process (v)
112 end
113 end
114
115 feature -- Type inference
116
117 minimum: detachable TYPE_A
118 -- Minimum type that can replace this type declaration.
119 do
120 -- Return non-void result only when the type is computable.
121 if is_computable then
122 -- If upper bound is expanded, it should be used.
123 if attached upper_approximation as u and then u.is_expanded then
124 Result := u
125 else
126 Result := lower_approximation
127 end
128 end
129 end
130
131 maximum: detachable TYPE_A
132 -- Maximum type that can replace this type declaration.
133 do
134 -- Return non-void result only when the type is computable.
135 if is_computable then
136 Result := upper_approximation
137 end
138 end
139
140 lower_approximation: detachable TYPE_A
141 -- Approximate type that can replace this type declaration.
142 -- Contrary to `minimum' does not take into account `is_computable' flag.
143 do
144 Result := approximation (lower_bound, upper_bound, conform_to_agent)
145 end
146
147 upper_approximation: detachable TYPE_A
148 -- Approximate type that can replace this type declaration.
149 -- Contrary to `maximum' does not take into account `is_computable' flag.
150 do
151 Result := approximation (upper_bound, lower_bound, reverse_conform_to_agent)
152 end
153
154 approximation (target_bound: like lower_bound; constraint_bound: like lower_bound; is_conforming: like conform_to_agent): detachable TYPE_A
155 -- Approximate type that can replace this type declaration that is the closest one to `target_bound' and matches `constraint_bound'
156 -- using `is_conforming' to check that the types conform.
157 require
158 not target_bound.is_empty
159 do
160 if target_bound.count = 1 then
161 -- All assignments to variables of this type use the same source type.
162 -- Check that this type conforms to all types from `upper_bound'.
163 target_bound.start
164 Result := target_bound.key_for_iteration.type
165 if not across constraint_bound as c all is_conforming (Result, c.key.type, c.key.context) end then
166 -- There are types to which found type does not conform.
167 Result := unknown_type
168 end
169 else
170 -- TODO: Find a target bound to which all known target bounds conform.
171 -- TODO: Check that all target bounds conform to all constraint bounds.
172 end
173 end
174
175 feature_call (name_id: like {FEATURE_I}.feature_name_id; context_class: CLASS_C): detachable TUPLE [descriptor: FEATURE_I; site: CL_TYPE_A; target: TYPE_A]
176 -- Information about a call to a feature with the name correponding to `name_id' called on the current type in `context_class':
177 -- descriptor: feature descriptor
178 -- site: class type with the feature
179 -- target: target type (may be different from "site" if it is a formal generic, acnhored type, etc.)
180 do
181 if attached lower_approximation as t then
182 feature_finder.find (name_id, t, context_class)
183 if attached feature_finder.found_feature as f then
184 Result := [f, feature_finder.found_site, t]
185 end
186 end
187 end
188
189 operator_call (name_id: like {FEATURE_I}.alias_name_id; context_class: CLASS_C): detachable TUPLE [descriptor: FEATURE_I; site: TYPE_A; target: TYPE_A]
190 -- Information about an operator call with the operator name correponding to `name_id' called on the current type in `context_class':
191 -- descriptor: feature descriptor
192 -- site: class type with the feature
193 -- target: target type (may be different from "site" if it is a formal generic, acnhored type, etc.)
194 do
195 if attached lower_approximation as t then
196 feature_finder.find_by_alias (name_id, t, context_class)
197 if attached feature_finder.found_feature as f then
198 Result := [f, feature_finder.found_site, t]
199 end
200 end
201 end
202
203 feature -- Output
204
205 dump: STRING
206 -- <Precursor>
207 do
208 Result := "like local#"
209 Result.append_integer (position)
210 end
211
212 ext_append_to (a_text_formatter: TEXT_FORMATTER; a_context_class: CLASS_C)
213 -- <Precursor>
214 do
215 a_text_formatter.process_keyword_text ({SHARED_TEXT_ITEMS}.ti_Like_keyword, Void)
216 a_text_formatter.add_space
217 a_text_formatter.add (once "local#")
218 a_text_formatter.add_int (position)
219 end
220
221 feature {TYPE_A} -- Helpers
222
223 internal_conform_to (a_context_class: CLASS_C; other: TYPE_A; a_in_generic: BOOLEAN): BOOLEAN
224 -- <Precursor>
225 do
226 -- Assume that the code is correct.
227 Result := True
228 -- Record information about conforming types.
229 add_upper_bound (a_context_class, other, a_in_generic)
230 end
231
232 feature {LOCAL_TYPE_A} -- Type bounds
233
234 lower_bound: HASH_TABLE [NONE, TUPLE [context: CLASS_C; type: TYPE_A; in_generic: BOOLEAN]]
235 -- Lower bounds of the type.
236 attribute
237 ensure
238 not Result.is_empty
239 end
240
241 upper_bound: like lower_bound
242 -- Upper bounds of the type.
243 attribute
244 ensure
245 not Result.is_empty
246 end
247
248 feature {NONE} -- Modification
249
250 add_lower_bound (context_class: CLASS_C; other: TYPE_A; in_generic: BOOLEAN)
251 -- Add type `other' as a lower bound of the type in `context_class'.
252 -- `in_generic' tells whether the type appears in a generic type.
253 do
254 add_bound (lower_bound, context_class, other, in_generic, conform_to_agent, agent (t: LOCAL_TYPE_A): like lower_bound do Result := t.lower_bound end)
255 end
256
257 add_upper_bound (context_class: CLASS_C; other: TYPE_A; in_generic: BOOLEAN)
258 -- Add type `other' as a upper bound of the type in `context_class'.
259 -- `in_generic' tells whether the type appears in a generic type.
260 do
261 add_bound (upper_bound, context_class, other, in_generic, reverse_conform_to_agent, agent (t: LOCAL_TYPE_A): like lower_bound do Result := t.upper_bound end)
262 end
263
264 add_bound (bound: like lower_bound;
265 context_class: CLASS_C;
266 other: TYPE_A;
267 in_generic: BOOLEAN;
268 is_conforming: like conform_to_agent;
269 other_bound: FUNCTION [ANY, TUPLE [LOCAL_TYPE_A], like lower_bound])
270 -- Add type `other' as a bound of the type in `context_class' to `bound'
271 -- using `is_conforming' to check that one type conforms to another one
272 -- and a function `other_bound' to access the corresponding bound of `other'
273 -- if it appears to be of type `{LOCAL_TYPE_A}'.
274 -- `in_generic' tells whether the type appears in a generic type.
275 local
276 new_bound: like lower_bound.key_for_iteration
277 is_new_bound_inserted: BOOLEAN
278 is_old_bound_removed: BOOLEAN
279 do
280 if same_as (other) then
281 -- Nothing to do.
282 elseif attached {LOCAL_TYPE_A} other as t then
283 -- Add bounds from `other'.
284 across
285 other_bound (t) as b
286 loop
287 add_bound (bound, context_class, b.key.type, in_generic, is_conforming, other_bound)
288 end
289 elseif attached {UNKNOWN_TYPE_A} other then
290 -- Record that the type is not computable.
291 is_computable := False
292 else
293 -- Remove any existing bound that conforms to the new one.
294 from
295 -- Check from the beginning of the type list.
296 bound.start
297 -- Insert a new bound if there are none.
298 is_new_bound_inserted := bound.after
299 until
300 bound.after
301 loop
302 if is_conforming (other, bound.key_for_iteration.type, context_class) then
303 -- `other' conforms to one of the existing types, so no changes to the `bound' are required.
304 -- But `other' may be more precise, so use it instead of existing same type (if any).
305 is_old_bound_removed := other.same_as (bound.key_for_iteration.type)
306 else
307 -- This is a new known bound.
308 -- Record that the type is not computable.
309 is_computable := False
310 is_old_bound_removed := is_conforming (bound.key_for_iteration.type, other, context_class)
311 end
312 if is_old_bound_removed then
313 -- Existing lower bound is replaced with a new one.
314 is_new_bound_inserted := True
315 -- Remove old bound.
316 bound.remove (bound.key_for_iteration)
317 else
318 -- Advance to next bound.
319 bound.forth
320 end
321 end
322 -- Add a new bound if required.
323 if is_new_bound_inserted then
324 -- Prepare a new dependency tuple.
325 new_bound := [context_class, other, in_generic]
326 new_bound.compare_objects
327 -- Record new information about the conforming type.
328 bound.force (Void, new_bound)
329 end
330 end
331 end
332
333 feature {NONE} -- Helper
334
335 conform_to_agent: PREDICATE [ANY, TUPLE [s: TYPE_A; t: TYPE_A; c: CLASS_C]]
336 -- A predicate to check that `s' conforms to `t' in class `c'?
337 once
338 Result :=
339 agent (s, t: TYPE_A; c: CLASS_C): BOOLEAN
340 do
341 Result := s.conform_to (c, t)
342 end
343 end
344
345 reverse_conform_to_agent: PREDICATE [ANY, TUPLE [s: TYPE_A; t: TYPE_A; c: CLASS_C]]
346 -- A predicate to check that `t' conforms to `s' in class `c'?
347 once
348 Result :=
349 agent (s, t: TYPE_A; c: CLASS_C): BOOLEAN
350 do
351 Result := t.conform_to (c, s)
352 end
353 end
354
355 feature_finder: TYPE_A_FEATURE_FINDER
356 -- Facility to lookup for a feature in a given type.
357 once
358 create Result
359 end
360
361 note
362 date: "$Date$"
363 revision: "$Revision$"
364 copyright: "Copyright (c) 1984-2014, Eiffel Software"
365 license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)"
366 licensing_options: "http://www.eiffel.com/licensing"
367 copying: "[
368 This file is part of Eiffel Software's Eiffel Development Environment.
369
370 Eiffel Software's Eiffel Development Environment is free
371 software; you can redistribute it and/or modify it under
372 the terms of the GNU General Public License as published
373 by the Free Software Foundation, version 2 of the License
374 (available at the URL listed under "license" above).
375
376 Eiffel Software's Eiffel Development Environment is
377 distributed in the hope that it will be useful, but
378 WITHOUT ANY WARRANTY; without even the implied warranty
379 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
380 See the GNU General Public License for more details.
381
382 You should have received a copy of the GNU General Public
383 License along with Eiffel Software's Eiffel Development
384 Environment; if not, write to the Free Software Foundation,
385 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
386 ]"
387 source: "[
388 Eiffel Software
389 5949 Hollister Ave., Goleta, CA 93117 USA
390 Telephone 805-685-1006, Fax 805-685-6869
391 Website http://www.eiffel.com
392 Customer support http://support.eiffel.com
393 ]"
394
395 end

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.23