1 |
indexing |
2 |
description: "[ |
3 |
Table of inherited features indexed by name ID: feature `pass2' is |
4 |
second pass of compiler. |
5 |
]" |
6 |
legal: "See notice at end of class." |
7 |
status: "See notice at end of class." |
8 |
date: "$Date$" |
9 |
revision: "$Revision$" |
10 |
|
11 |
class |
12 |
INHERIT_TABLE |
13 |
|
14 |
inherit |
15 |
HASH_TABLE [INHERIT_FEAT, INTEGER] |
16 |
rename |
17 |
make as extend_tbl_make, |
18 |
merge as extend_table_merge |
19 |
end |
20 |
|
21 |
SHARED_SERVER |
22 |
export |
23 |
{ANY} all |
24 |
undefine |
25 |
copy, is_equal |
26 |
end |
27 |
|
28 |
SHARED_SELECTED |
29 |
undefine |
30 |
copy, is_equal |
31 |
end |
32 |
|
33 |
SHARED_ERROR_HANDLER |
34 |
export |
35 |
{ANY} error_handler |
36 |
undefine |
37 |
copy, is_equal |
38 |
end |
39 |
|
40 |
SHARED_INST_CONTEXT |
41 |
undefine |
42 |
copy, is_equal |
43 |
end |
44 |
|
45 |
SHARED_ORIGIN_TABLE |
46 |
undefine |
47 |
copy, is_equal |
48 |
end |
49 |
|
50 |
SHARED_ID_TABLES |
51 |
undefine |
52 |
copy, is_equal |
53 |
end |
54 |
|
55 |
SHARED_DEGREES |
56 |
undefine |
57 |
copy, is_equal |
58 |
end |
59 |
|
60 |
SHARED_RESCUE_STATUS |
61 |
undefine |
62 |
copy, is_equal |
63 |
end |
64 |
|
65 |
SHARED_STATELESS_VISITOR |
66 |
export |
67 |
{NONE} all |
68 |
undefine |
69 |
copy, is_equal |
70 |
end |
71 |
|
72 |
SHARED_IL_CASING |
73 |
export |
74 |
{NONE} all |
75 |
undefine |
76 |
copy, is_equal |
77 |
end |
78 |
|
79 |
SHARED_NAMES_HEAP |
80 |
export |
81 |
{NONE} all |
82 |
undefine |
83 |
copy, is_equal |
84 |
end |
85 |
|
86 |
COMPILER_EXPORTER |
87 |
undefine |
88 |
copy, is_equal |
89 |
end |
90 |
|
91 |
create |
92 |
make |
93 |
|
94 |
feature {NONE} -- Initialization |
95 |
|
96 |
make (n: INTEGER) is |
97 |
-- Hash table creation |
98 |
do |
99 |
default_size := n |
100 |
extend_tbl_make (n) |
101 |
create inherited_features.make (n) |
102 |
create changed_features.make (100) |
103 |
create origins.make (100) |
104 |
end |
105 |
|
106 |
feature |
107 |
|
108 |
default_size: INTEGER |
109 |
-- Default size for `inherited_features'. |
110 |
|
111 |
inherited_features: FEATURE_TABLE; |
112 |
-- Table of inherited features. |
113 |
-- It is calculated by feature `analyse'. |
114 |
|
115 |
a_class: CLASS_C; |
116 |
-- Current class to analyze |
117 |
|
118 |
feature_table: FEATURE_TABLE; |
119 |
-- Previous feature table of the class `a_class': processed |
120 |
-- by feature `analyze_declarations'; if the class has never |
121 |
-- been compiled before, this attribute will be created |
122 |
-- and empty before the analysis of the local declarations |
123 |
|
124 |
previous_feature_table: FEATURE_TABLE; |
125 |
-- Previous feature table processed during a second pass, |
126 |
-- and put in the temporary server only. |
127 |
--| Useful for the processing of feature ids |
128 |
|
129 |
class_info: CLASS_INFO; |
130 |
-- Information about current class analyzed: it contains |
131 |
-- a compild form of parents, a reference on the feature |
132 |
-- list produced by the first pass and indexes left by |
133 |
-- the temporary AST server (`Tmp_ast_server') when the |
134 |
-- abstract syntax tree of the current analyzed class |
135 |
-- has been put in it. |
136 |
-- (actually we have here the offsets in the (future) file |
137 |
-- ".AST" of the abstract represention of the features). |
138 |
|
139 |
parents: PARENT_LIST; |
140 |
-- Compiled form of the parents of the current analyzed class |
141 |
|
142 |
changed_features: ARRAYED_LIST [INTEGER]; |
143 |
-- Changed features of `a_class'. |
144 |
|
145 |
invariant_changed: BOOLEAN; |
146 |
-- Did the invariant clause changed ? |
147 |
|
148 |
invariant_removed: BOOLEAN; |
149 |
-- Is the invariant clause removed ? |
150 |
|
151 |
origins: ARRAYED_LIST [INTEGER]; |
152 |
-- Origin features name list for pattern processing |
153 |
|
154 |
supplier_status_modified: BOOLEAN; |
155 |
-- The status (expanded, deferred) of a supplier has changed |
156 |
|
157 |
assert_prop_list: LINKED_LIST [INTEGER]; |
158 |
-- List of routine ids for assertion modifications |
159 |
|
160 |
adaptations: LINKED_LIST [FEATURE_ADAPTATION] is |
161 |
-- List of redefinitions and joins |
162 |
once |
163 |
create Result.make |
164 |
end; |
165 |
|
166 |
pass2_control: PASS2_CONTROL |
167 |
-- Second pass controler, needs to be an attribute since |
168 |
-- used by `pass2' and `feature_unit'. |
169 |
|
170 |
pass2 (pass_c: CLASS_C; is_supplier_status_modified: BOOLEAN) is |
171 |
-- Second pass of the compiler on class `cl'. The ultimate |
172 |
-- goal here is to calculate the feature table `inherited_features'. |
173 |
require |
174 |
pass_c_not_void: pass_c /= Void |
175 |
class_info_exists: Class_info_server.has (pass_c.class_id); |
176 |
local |
177 |
class_id: INTEGER; |
178 |
resulting_table: like inherited_features; |
179 |
pass3_control: PASS3_CONTROL; |
180 |
depend_unit: DEPEND_UNIT; |
181 |
old_creators, new_creators: HASH_TABLE [EXPORT_I, STRING]; |
182 |
old_convert_to, old_convert_from: DS_HASH_TABLE [INTEGER, NAMED_TYPE_A] |
183 |
creation_name: STRING; |
184 |
equiv_tables: BOOLEAN; |
185 |
do |
186 |
a_class := pass_c |
187 |
-- Store previous data |
188 |
old_creators := a_class.creators |
189 |
old_convert_to := a_class.convert_to |
190 |
old_convert_from := a_class.convert_from |
191 |
|
192 |
create pass2_control.make |
193 |
|
194 |
if System.il_generation then |
195 |
a_class.init_class_interface |
196 |
end |
197 |
|
198 |
supplier_status_modified := is_supplier_status_modified; |
199 |
|
200 |
-- Initialization of the context for evaluation of actual |
201 |
-- types |
202 |
Inst_context.set_group (a_class.group) |
203 |
|
204 |
-- Empty the selection control list |
205 |
Selected.wipe_out; |
206 |
class_id := a_class.class_id; |
207 |
|
208 |
-- Look for the interpreted class information left |
209 |
-- by the first pass if the class has syntactically changed. |
210 |
class_info := Class_info_server.item (class_id) |
211 |
|
212 |
-- Extract `computed_parents' from current class an reset |
213 |
-- it as it is not needed that we store this information |
214 |
-- since it is only used in `pass2'. |
215 |
parents := a_class.computed_parents |
216 |
|
217 |
-- Compute attribute `feature_table'. |
218 |
compute_feature_table; |
219 |
|
220 |
-- Check generic parents of the class |
221 |
a_class.check_parents |
222 |
|
223 |
-- Merge parents table: the topological sort and the |
224 |
-- sort of list `changed_classes' of the system ensures |
225 |
-- that the second pass has been applied to the parents |
226 |
-- of class `cl' before. |
227 |
-- We also check if renamed features are available |
228 |
parents.merge_and_check_renamings (Current) |
229 |
|
230 |
Error_handler.checksum; |
231 |
-- Treat the renamings |
232 |
--| Needs to be done twice |
233 |
--| a is processed |
234 |
--| if `rename b as a' is done afterwards, we need to |
235 |
--| reprocess the inherit_feat for a again. |
236 |
check_renamings; |
237 |
check_renamings; |
238 |
-- Analyze features inherited under the same final name |
239 |
analyze; |
240 |
-- Check adaptation clauses of parents |
241 |
parents.check_validity2; |
242 |
-- Check-sum error after analysis fo the inherited |
243 |
-- features |
244 |
Error_handler.checksum; |
245 |
|
246 |
-- Analyze local features |
247 |
if a_class.changed then |
248 |
-- Remove all changed features if any |
249 |
a_class.changed_features.clear_all; |
250 |
-- Class `a_class' is syntactically changed |
251 |
analyze_declarations; |
252 |
-- No update of `Instantiator' if there is an error |
253 |
Error_handler.checksum; |
254 |
-- Look for generic types in the inheritance clause |
255 |
-- of a syntactically changed class |
256 |
a_class.update_instantiator1; |
257 |
else |
258 |
-- The class didn't syntactically changed but, one |
259 |
-- or more ancestor has a new feature table. |
260 |
recompute_declarations; |
261 |
end; |
262 |
|
263 |
-- Check the redefine and select clause, and kepp track |
264 |
-- of possible joins between deferred features |
265 |
check_validity2; |
266 |
|
267 |
-- Computes a good size for the feature table |
268 |
resulting_table := inherited_features.twin |
269 |
|
270 |
-- Check redeclarations into an attribute |
271 |
check_redeclarations (resulting_table); |
272 |
|
273 |
-- Check sum |
274 |
Error_handler.checksum; |
275 |
|
276 |
-- Compute selection table |
277 |
Origin_table.compute_feature_table (parents, feature_table, resulting_table); |
278 |
resulting_table.set_origin_table (Origin_table.computed); |
279 |
-- Check sum error: because of possible bad selections, |
280 |
-- anchored types on features could not be evaluated here. |
281 |
Error_handler.checksum; |
282 |
|
283 |
-- Check types in the feature table |
284 |
resulting_table.check_table; |
285 |
-- Check the adaptations |
286 |
check_validity3 (resulting_table); |
287 |
-- Check useless selections |
288 |
parents.check_validity4; |
289 |
|
290 |
-- Creators processing |
291 |
a_class.set_creators (class_info.creation_table (resulting_table)); |
292 |
-- No update of `Instantiator' if there is an error |
293 |
Error_handler.checksum; |
294 |
|
295 |
-- Convertibility processing |
296 |
-- Note: Manu 04/23/2003: Do we need to make a once of `CONVERTIBILITY_CHECKER'? |
297 |
-- At the moment no as it does not seem expensive to create it all the time. |
298 |
(create {CONVERTIBILITY_CHECKER}).init_and_check_convert_tables ( |
299 |
a_class, resulting_table, class_info.convertors) |
300 |
Error_handler.checksum |
301 |
|
302 |
-- Track generic types in the result and arguments of |
303 |
-- features of a changed class |
304 |
if a_class.changed then |
305 |
-- Generic types tracking |
306 |
resulting_table.update_instantiator2; |
307 |
-- Compute invariant clause |
308 |
compute_invariant; |
309 |
end; |
310 |
|
311 |
-- Check sum error |
312 |
Error_handler.checksum; |
313 |
check |
314 |
No_error: not Error_handler.has_error; |
315 |
end; |
316 |
|
317 |
-- Pass2 controler evaluation |
318 |
feature_table.fill_pass2_control (pass2_control, resulting_table); |
319 |
if previous_feature_table /= Void then |
320 |
-- Add the modifications done since the last unsuccessful compilation |
321 |
previous_feature_table.fill_pass2_control (pass2_control, resulting_table); |
322 |
end; |
323 |
|
324 |
-- Process externals |
325 |
if a_class.changed then |
326 |
pass2_control.process_externals |
327 |
end; |
328 |
|
329 |
-- Insert the changed creators in the propagators list |
330 |
new_creators := a_class.creators; |
331 |
if old_creators = Void then |
332 |
if |
333 |
new_creators /= Void |
334 |
or else (a_class.is_deferred and then pass_c.deferred_modified) |
335 |
then |
336 |
-- the clients using !! without a creation routine |
337 |
-- must be recompiled |
338 |
debug ("ACTIVITY") |
339 |
io.error.put_string ("Insert -1 in the propagators%N"); |
340 |
if new_creators /= Void then |
341 |
io.error.put_string ("Creators have been added"); |
342 |
else |
343 |
io.error.put_string ("The class is now deferred%N"); |
344 |
end; |
345 |
end; |
346 |
if a_class.is_used_as_expanded then |
347 |
create depend_unit.make_expanded_unit (a_class.class_id); |
348 |
pass2_control.propagators.extend (depend_unit) |
349 |
end; |
350 |
create depend_unit.make_creation_unit (a_class.class_id); |
351 |
pass2_control.propagators.extend (depend_unit) |
352 |
end; |
353 |
else |
354 |
from |
355 |
old_creators.start |
356 |
until |
357 |
old_creators.after |
358 |
loop |
359 |
creation_name := old_creators.key_for_iteration; |
360 |
if |
361 |
new_creators = Void |
362 |
or else |
363 |
not new_creators.has (creation_name) |
364 |
or else |
365 |
-- The new export status is more restrictive than the old one |
366 |
not old_creators.item_for_iteration.equiv (new_creators.item (creation_name)) |
367 |
then |
368 |
if resulting_table.has (creation_name) then |
369 |
-- The routine is not a creation routine any more |
370 |
-- or the export status has changed |
371 |
debug ("ACTIVITY") |
372 |
io.error.put_string ("Creators: "); |
373 |
io.error.put_string (creation_name); |
374 |
io.error.put_string (" inserted in pass2_control.propagators%N"); |
375 |
end; |
376 |
create depend_unit.make (a_class.class_id, resulting_table.found_item); |
377 |
pass2_control.propagators.extend (depend_unit); |
378 |
end; |
379 |
end; |
380 |
old_creators.forth |
381 |
end; |
382 |
if a_class.is_used_as_expanded and then |
383 |
(new_creators = Void or else new_creators.count > 1) |
384 |
then |
385 |
create depend_unit.make_expanded_unit (a_class.class_id); |
386 |
pass2_control.propagators.extend (depend_unit) |
387 |
end; |
388 |
old_creators := Void |
389 |
end; |
390 |
|
391 |
-- Insert removed routines from convert clauses into propagators list. |
392 |
if old_convert_to /= Void then |
393 |
update_convert_clause (old_convert_to, a_class.convert_to, resulting_table) |
394 |
end |
395 |
if old_convert_from /= Void then |
396 |
update_convert_clause (old_convert_from, a_class.convert_from, resulting_table) |
397 |
end |
398 |
|
399 |
-- Remember the removed features written in `a_class' |
400 |
pass3_control := a_class.propagators; |
401 |
pass3_control.set_removed_features (pass2_control.removed_features); |
402 |
pass3_control.set_invariant_changed (invariant_changed); |
403 |
pass3_control.set_invariant_removed (invariant_removed); |
404 |
|
405 |
-- Update the assert_id_set of redefined features. |
406 |
update_inherited_assertions; |
407 |
|
408 |
if previous_feature_table /= Void then |
409 |
-- If there is a table in the tmp server, |
410 |
-- the propagation is done again only if the new |
411 |
-- table is different. |
412 |
equiv_tables := resulting_table.equiv (previous_feature_table, pass2_control) |
413 |
else |
414 |
-- There is no table in the tmp server, see if the |
415 |
-- new feature table is equivalent to the old one |
416 |
equiv_tables := resulting_table.equiv (feature_table, pass2_control); |
417 |
end; |
418 |
|
419 |
-- Propagation |
420 |
Degree_4.propagate (pass_c, resulting_table, equiv_tables, |
421 |
pass2_control, assert_prop_list); |
422 |
assert_prop_list := Void; |
423 |
|
424 |
-- Process paterns of origin features |
425 |
process_pattern (resulting_table); |
426 |
|
427 |
-- Ensure a wrapper is generated for attributes of a formal generic type. |
428 |
mark_generic_attribute_seeds (resulting_table) |
429 |
|
430 |
-- Line removed by Frederic Deramat 15/04/92. |
431 |
-- |
432 |
-- *** resulting_table.process_polymorphism (feature_table); *** |
433 |
-- |
434 |
-- The "polymorphical tables" are not generated in workbench mode |
435 |
-- anymore (replaced by "offset descriptors"). Nevertheless, the |
436 |
-- facility is still used to produce finalized code, but |
437 |
-- "polymorphical tables" are in no case stored to disk (only |
438 |
-- generated temporarily in final mode in order to generate the |
439 |
-- static C routine tables. |
440 |
|
441 |
if System.il_generation then -- and then not a_class.is_external then |
442 |
a_class.class_interface.process_features (resulting_table) |
443 |
end |
444 |
|
445 |
-- Instantiate generic parameter in context of current |
446 |
-- class. |
447 |
a_class.update_generic_features |
448 |
|
449 |
-- Find main_parent of current class. |
450 |
if System.il_generation then |
451 |
compute_main_parent (resulting_table) |
452 |
end |
453 |
|
454 |
-- Put the resulting table in the temporary feature table |
455 |
-- server. |
456 |
Tmp_feat_tbl_server.put (resulting_table); |
457 |
debug ("HAS_CALLS", "TRACE_TABLE") |
458 |
resulting_table.trace_replications; |
459 |
resulting_table.trace; |
460 |
end; |
461 |
-- Update table `changed_features' of `a_class'. |
462 |
update_changed_features; |
463 |
clear; |
464 |
ensure |
465 |
No_error: not Error_handler.has_error; |
466 |
rescue |
467 |
if Rescue_status.is_error_exception then |
468 |
-- Error happened during second pass: clear the |
469 |
-- structure |
470 |
clear; |
471 |
if a_class.changed then |
472 |
-- Reset the old creation table |
473 |
a_class.set_creators (old_creators); |
474 |
end; |
475 |
end; |
476 |
end; |
477 |
|
478 |
compute_feature_table is |
479 |
-- Compute attribute `feature_table'. Look for a previous |
480 |
-- feature table. |
481 |
require |
482 |
a_class /= Void |
483 |
local |
484 |
id: INTEGER; |
485 |
do |
486 |
id := a_class.class_id; |
487 |
-- Look for a previous feature table in server `Feat_tbl_server' |
488 |
-- nb: we don't have to look for it in the temporary server |
489 |
-- for feature table here, that's why we are using feature |
490 |
-- `server_item' of class FEAT_TBL_SERVER. |
491 |
if Feat_tbl_server.server_has (id) then |
492 |
-- We have a previous compiled class |
493 |
feature_table := Feat_tbl_server.server_item (id); |
494 |
feature_table.update_table; |
495 |
else |
496 |
-- No previous compilation |
497 |
feature_table := Empty_table; |
498 |
end; |
499 |
-- Prepare `inherited_features'. |
500 |
inherited_features.set_feat_tbl_id (id); |
501 |
-- Compute `previous_feature_table'. |
502 |
if Tmp_feat_tbl_server.has (id) then |
503 |
-- There was an error and a feature table has been already |
504 |
-- computed for this class. |
505 |
previous_feature_table := Tmp_feat_tbl_server.item (id); |
506 |
previous_feature_table.update_table; |
507 |
end; |
508 |
end; |
509 |
|
510 |
Empty_table: FEATURE_TABLE is |
511 |
-- Empty feature table |
512 |
local |
513 |
select_table: SELECT_TABLE; |
514 |
once |
515 |
create select_table.make (1); |
516 |
create Result.make (1); |
517 |
Result.set_origin_table (select_table); |
518 |
end; |
519 |
|
520 |
merge (parent_c: PARENT_C) is |
521 |
-- Merge feature table of parent `cl' into |
522 |
-- a data structure to analyse. |
523 |
local |
524 |
parent: CLASS_C |
525 |
-- Parent class |
526 |
parent_table: FEATURE_TABLE; |
527 |
-- Feature table of the parent `parent_c' |
528 |
info: INHERIT_INFO |
529 |
-- Information on one inherited feature |
530 |
feature_i: FEATURE_I |
531 |
-- Inherited feature |
532 |
parent_type: LIKE_CURRENT |
533 |
-- "like Current" type of `parent_c' |
534 |
do |
535 |
from |
536 |
parent := parent_c.parent |
537 |
create parent_type |
538 |
parent_type.set_actual_type (parent_c.parent_type) |
539 |
-- Look for the parent table on the disk |
540 |
parent_table := Feat_tbl_server.item (parent.class_id) |
541 |
check |
542 |
parent_table_exists: parent_table /= Void; |
543 |
-- Because of topological sort, the parents are |
544 |
-- necessary analyzed (if needed) before class |
545 |
-- `a_class'. Redefinition of feature `item' in |
546 |
-- class FEAT_TBL_SERVER will look for the table |
547 |
-- in the file `Tmp_feat_tbl_file' and then |
548 |
-- in the file `Feat_tbl_file'. |
549 |
end; |
550 |
|
551 |
-- Iteration on the parent feature table |
552 |
parent_table.start; |
553 |
until |
554 |
parent_table.after |
555 |
loop |
556 |
-- Take one feature |
557 |
feature_i := parent_table.item_for_iteration.duplicate |
558 |
|
559 |
-- Instantiation of the feature in its parent |
560 |
feature_i.instantiate (parent_type) |
561 |
|
562 |
-- Creation of an inherited feature information unit |
563 |
create info.make (feature_i) |
564 |
info.set_parent (parent_c) |
565 |
|
566 |
-- Add the information to the concerned instance of |
567 |
-- INHERIT_FEAT |
568 |
add_inherited_feature (info, feature_i.feature_name_id) |
569 |
parent_table.forth |
570 |
end |
571 |
end |
572 |
|
573 |
add_inherited_feature (info: INHERIT_INFO; feature_name_id: INTEGER) is |
574 |
-- Add an inherited feature in the table. |
575 |
local |
576 |
l: INHERIT_FEAT |
577 |
do |
578 |
l := item (feature_name_id) |
579 |
if l = Void then |
580 |
-- Take a new object from the free list |
581 |
create l.make |
582 |
put (l, feature_name_id) |
583 |
end |
584 |
-- Add the information to the concerned instance of |
585 |
-- INHERIT_FEAT |
586 |
l.insert (info) |
587 |
end |
588 |
|
589 |
check_renamings is |
590 |
-- Check all the renamings made in the table of |
591 |
-- inherited features |
592 |
local |
593 |
l: like linear_representation |
594 |
do |
595 |
from |
596 |
l := linear_representation |
597 |
l.start |
598 |
until |
599 |
l.after |
600 |
loop |
601 |
-- Check the renamings on one name |
602 |
l.item.check_renamings |
603 |
l.forth |
604 |
end |
605 |
end |
606 |
|
607 |
analyze is |
608 |
-- Analyze inherited features: the renamings must have |
609 |
-- been treated before |
610 |
require |
611 |
a_class /= Void; |
612 |
feature_table /= Void; |
613 |
local |
614 |
feature_name_id: INTEGER; |
615 |
inherit_feat: INHERIT_FEAT; |
616 |
inherited_info: INHERIT_INFO; |
617 |
feature_i: FEATURE_I; |
618 |
def: DEFINITION; |
619 |
do |
620 |
from |
621 |
-- Iteration on the structure |
622 |
start |
623 |
until |
624 |
after |
625 |
loop |
626 |
-- Calculates an inherited feature: instance of |
627 |
-- FEATURE_I |
628 |
inherit_feat := item_for_iteration; |
629 |
feature_name_id := key_for_iteration; |
630 |
|
631 |
-- Calculates attribute `inherited_feature' of |
632 |
-- instance `inherit_feat'. |
633 |
inherit_feat.process (a_class, feature_name_id) |
634 |
inherited_info := inherit_feat.inherited_info; |
635 |
if inherited_info /= Void then |
636 |
-- Class inherit from a feature coming from one |
637 |
-- parent. |
638 |
feature_i := inherited_info.a_feature; |
639 |
-- Feature name |
640 |
feature_i.set_feature_name_id (feature_name_id, feature_i.alias_name_id) |
641 |
-- initialization of an inherited feature |
642 |
init_inherited_feature (feature_i, inherit_feat); |
643 |
-- Insertion in the origin table |
644 |
inherited_info.set_a_feature (feature_i); |
645 |
if not feature_i.is_deferred |
646 |
and then |
647 |
inherit_feat.nb_deferred > 0 |
648 |
then |
649 |
-- Case of an implementation of inherited deferred |
650 |
-- features by an inherited non-deferred feature |
651 |
create def.make (inherit_feat, feature_i); |
652 |
-- Reset assertions of `feature_i' |
653 |
adaptations.put_front (def); |
654 |
else |
655 |
Origin_table.insert (inherited_info); |
656 |
end; |
657 |
end; |
658 |
forth |
659 |
end; |
660 |
end; |
661 |
|
662 |
analyze_declarations is |
663 |
-- Analyze local declarations written in the class for a |
664 |
-- syntactically changed class. |
665 |
local |
666 |
feature_clause: FEATURE_CLAUSE_AS; |
667 |
features: EIFFEL_LIST [FEATURE_AS]; |
668 |
-- Reference on the feature list produced by the first pass |
669 |
single_feature: FEATURE_AS; |
670 |
-- Single standard Eiffel feature |
671 |
name_list: EIFFEL_LIST [FEATURE_NAME]; |
672 |
-- Attribute list names |
673 |
feature_i: FEATURE_I; |
674 |
feat_name: FEATURE_NAME; |
675 |
clauses: EIFFEL_LIST [FEATURE_CLAUSE_AS]; |
676 |
l_export_status: EXPORT_I; |
677 |
property_name: STRING |
678 |
property_names: HASH_TABLE [FEATURE_I, STRING] |
679 |
do |
680 |
clauses := class_info.features; |
681 |
if clauses /= Void then |
682 |
if system.il_generation then |
683 |
create property_names.make (0) |
684 |
end |
685 |
from |
686 |
clauses.start |
687 |
until |
688 |
clauses.after |
689 |
loop |
690 |
feature_clause := clauses.item; |
691 |
-- Evaluation of the export status |
692 |
l_export_status := export_status_generator. |
693 |
feature_clause_export_status (a_class, feature_clause) |
694 |
from |
695 |
-- Iteration of the feature written in class |
696 |
-- `a_class'. |
697 |
features := feature_clause.features; |
698 |
features.start; |
699 |
until |
700 |
features.after |
701 |
loop |
702 |
single_feature := features.item; |
703 |
from |
704 |
name_list := single_feature.feature_names; |
705 |
name_list.start; |
706 |
until |
707 |
name_list.after |
708 |
loop |
709 |
feat_name := name_list.item; |
710 |
-- Computes an internal name for the feature |
711 |
-- taking care of prefix/infix notations |
712 |
feature_i := feature_unit (single_feature, feat_name); |
713 |
-- Attributes `body_index', `feature_name' and |
714 |
-- `written_in' are ok now. If it is an old |
715 |
-- instance of FEATURE_I from a previous |
716 |
-- compilation, we know if it was an origin. |
717 |
analyze_local (feature_i, feature_i.feature_name_id) |
718 |
-- Set the export status |
719 |
feature_i.set_export_status (l_export_status); |
720 |
if property_names /= Void then |
721 |
-- Check that there are no property name clashes |
722 |
if feature_i.has_property then |
723 |
property_name := single_feature.property_name |
724 |
if property_name = Void or else property_name.is_empty then |
725 |
-- Use implicit property name. |
726 |
property_name := il_casing.pascal_casing |
727 |
(system.dotnet_naming_convention, feature_i.feature_name, {IL_CASING_CONVERSION}.lower_case) |
728 |
end |
729 |
if property_names.has (property_name) then |
730 |
error_handler.insert_error (create {VIPM}.make |
731 |
(a_class, feature_i, property_names.item (property_name), property_name)) |
732 |
else |
733 |
property_names.put (feature_i, property_name) |
734 |
end |
735 |
-- Check that there are no property setters with |
736 |
-- several arguments as order of the arguments is |
737 |
-- different in Eiffel and IL. |
738 |
if feature_i.has_property_setter and then |
739 |
(feature_i.type.is_void and then feature_i.argument_count /= 1 or else |
740 |
not feature_i.type.is_void and then feature_i.argument_count > 0) |
741 |
then |
742 |
error_handler.insert_error (create {VIPS}.make (a_class, feature_i)) |
743 |
end |
744 |
end |
745 |
end |
746 |
name_list.forth; |
747 |
end; |
748 |
|
749 |
features.forth; |
750 |
end; |
751 |
clauses.forth; |
752 |
end; |
753 |
end; |
754 |
end; |
755 |
|
756 |
recompute_declarations is |
757 |
-- Recompute local declarations for a non-syntactically changed |
758 |
-- class. |
759 |
require |
760 |
good_class: a_class /= Void; |
761 |
non_syntactically_changed: a_class.changed2; |
762 |
local |
763 |
feature_i: FEATURE_I; |
764 |
feature_name_id: INTEGER; |
765 |
id: INTEGER; |
766 |
do |
767 |
from |
768 |
id := a_class.class_id; |
769 |
feature_table.start; |
770 |
until |
771 |
feature_table.after |
772 |
loop |
773 |
feature_i := feature_table.item_for_iteration; |
774 |
if feature_i.written_in = id then |
775 |
feature_name_id := feature_table.key_for_iteration; |
776 |
-- recompute a former local declaration |
777 |
analyze_local (feature_i.duplicate, feature_name_id); |
778 |
end; |
779 |
feature_table.forth; |
780 |
end; |
781 |
end; |
782 |
|
783 |
analyze_local (feature_i: FEATURE_I; feature_name_id: INTEGER) is |
784 |
-- Analyze local declaration of class `a_class' named |
785 |
-- `feat_name' which abstract representation is `yacc_feature'. |
786 |
require |
787 |
good_feature: feature_i /= Void; |
788 |
good_feature_name_id: feature_name_id > 0 |
789 |
local |
790 |
inherit_feat: INHERIT_FEAT; |
791 |
-- Possible inherited features |
792 |
old_feature: FEATURE_I; |
793 |
new_rout_id: INTEGER; |
794 |
new_rout_id_set: ROUT_ID_SET; |
795 |
redef: REDEFINITION; |
796 |
info, inherited_info: INHERIT_INFO; |
797 |
vmfn: VMFN; |
798 |
vmfn1: VMFN1; |
799 |
compute_new_rout_id: BOOLEAN; |
800 |
do |
801 |
-- Now, compute the routine id set of the feature. |
802 |
inherit_feat := item (feature_name_id); |
803 |
|
804 |
-- Find out if there previously was a feature with name |
805 |
-- `feature_name' |
806 |
old_feature := feature_table.item_id (feature_name_id); |
807 |
|
808 |
if inherit_feat = Void then |
809 |
-- No feature inherited under name `feature_name'. This |
810 |
-- deserves a brand new origin. |
811 |
if feature_i.is_origin then |
812 |
-- An old feature from a previous compilation was |
813 |
-- an origin. Keep the current routine id. |
814 |
new_rout_id_set := feature_i.rout_id_set; |
815 |
check |
816 |
rout_id_set_exists: new_rout_id_set /= Void; |
817 |
has_only_one: new_rout_id_set.count = 1; |
818 |
end; |
819 |
new_rout_id := new_rout_id_set.first; |
820 |
if feature_i.is_attribute then |
821 |
compute_new_rout_id := not Routine_id_counter.is_attribute (new_rout_id) |
822 |
else |
823 |
compute_new_rout_id := Routine_id_counter.is_attribute (new_rout_id) |
824 |
end; |
825 |
else |
826 |
if |
827 |
old_feature /= Void and then not old_feature.is_origin |
828 |
then |
829 |
-- We changed the origin of the feature, we need to |
830 |
-- mark the feature as changed since its assertions |
831 |
-- could have been changed even though its body did |
832 |
-- not changed |
833 |
changed_features.extend (feature_name_id) |
834 |
end |
835 |
feature_i.set_is_origin (True); |
836 |
compute_new_rout_id := True; |
837 |
end; |
838 |
if compute_new_rout_id then |
839 |
create new_rout_id_set.make |
840 |
new_rout_id := feature_i.new_rout_id; |
841 |
new_rout_id_set.put (new_rout_id); |
842 |
feature_i.set_rout_id_set (new_rout_id_set); |
843 |
end; |
844 |
-- Insertion into the system routine info table. |
845 |
System.rout_info_table.put (new_rout_id, a_class); |
846 |
create info.make (feature_i) |
847 |
else |
848 |
-- This is either an explicit redefinition through |
849 |
-- the redefine clause or an implicit redefinition like |
850 |
-- an implementation of deferred features |
851 |
inherited_info := inherit_feat.inherited_info; |
852 |
if inherited_info = Void then |
853 |
-- Implicit or explicit redefinition |
854 |
new_rout_id_set := inherit_feat.rout_id_set.twin |
855 |
-- This is not an origin. |
856 |
feature_i.set_is_origin (False); |
857 |
if |
858 |
old_feature /= Void and then old_feature.is_origin |
859 |
then |
860 |
-- We changed the origin of the feature, we need to |
861 |
-- mark the feature as changed since its assertions |
862 |
-- could have been changed even though its body did |
863 |
-- not change. |
864 |
changed_features.extend (feature_name_id) |
865 |
end |
866 |
-- Routine id set for the redefinition |
867 |
feature_i.set_rout_id_set (new_rout_id_set); |
868 |
-- Mark the redefinition to be done. |
869 |
-- We pass `feature_i' as creation routine to |
870 |
-- satisfy INHERIT_INFO invariant, but this is |
871 |
-- not the correct value. The correct one will |
872 |
-- will be set later by one of the routine that |
873 |
-- calls `set_a_feature' from INHERIT_INFO. |
874 |
create info.make (feature_i) |
875 |
inherit_feat.set_inherited_info (info); |
876 |
-- Store the redefintion for later |
877 |
create redef.make (inherit_feat, feature_i); |
878 |
adaptations.put_front (redef); |
879 |
elseif inherited_info.parent = Void then |
880 |
-- The feature has two implementations in the class |
881 |
create vmfn; |
882 |
vmfn.set_class (a_class); |
883 |
vmfn.set_a_feature (feature_i); |
884 |
vmfn.set_inherited_feature (inherited_features.item_id (feature_name_id)); |
885 |
Error_handler.insert_error (vmfn); |
886 |
else |
887 |
-- Name clash: a non-deferred feature is inherited |
888 |
create vmfn1; |
889 |
vmfn1.set_class (a_class); |
890 |
vmfn1.set_a_feature (feature_i); |
891 |
vmfn1.set_inherited_feature (inherited_info.a_feature); |
892 |
vmfn1.set_parent (inherited_info.parent.parent); |
893 |
Error_handler.insert_error (vmfn1); |
894 |
end; |
895 |
end; |
896 |
if info /= Void then |
897 |
if old_feature = Void then |
898 |
-- Since the old feature table hasn't a feature named |
899 |
-- `feature_name', new feature id for the feature |
900 |
give_new_feature_id (feature_i); |
901 |
else |
902 |
-- Take the previous feature id |
903 |
feature_i.set_feature_id (old_feature.feature_id); |
904 |
if old_feature.written_in = a_class.class_id then |
905 |
if |
906 |
(feature_i.is_attribute and not old_feature.is_attribute) or else |
907 |
(feature_i.is_deferred and then not old_feature.is_deferred) or else |
908 |
(feature_i.is_attribute and old_feature.is_attribute and |
909 |
feature_i.is_origin /= old_feature.is_origin) |
910 |
then |
911 |
System.execution_table.add_dead_function (old_feature.body_index) |
912 |
end |
913 |
end; |
914 |
end; |
915 |
-- Put new feature in `inherited_features'. |
916 |
insert_feature (feature_i); |
917 |
-- Put the new feature written in the current class |
918 |
-- in the origin table |
919 |
if redef = Void then |
920 |
info.set_a_feature (feature_i); |
921 |
Origin_table.insert (info); |
922 |
end; |
923 |
end; |
924 |
-- Keep track of the origin features for pattern |
925 |
-- processing |
926 |
origins.extend (feature_i.feature_name_id); |
927 |
end; |
928 |
|
929 |
feature_unit (yacc_feature: FEATURE_AS; feat: FEATURE_NAME): FEATURE_I is |
930 |
-- Feature correponding to declaration `yacc_feature'. |
931 |
-- If we found a feature named `feature_name' in a previous |
932 |
-- feature table, don't change of feature id. If this previous |
933 |
-- feature didn't change, keep the body id, otherwise compute |
934 |
-- a new body id. |
935 |
require |
936 |
syntactically_changed: a_class.changed; |
937 |
local |
938 |
feature_i: FEATURE_I; |
939 |
unique_feature: UNIQUE_I; |
940 |
-- Feature coming from a previous recompilation |
941 |
body_index: INTEGER; |
942 |
-- Body index of a previous compiled feature |
943 |
old_description, old_tmp_description: FEATURE_AS; |
944 |
-- Abstract representation of a previous compiled feature |
945 |
is_the_same: BOOLEAN; |
946 |
-- Is the parsed feature the same than a previous |
947 |
-- compiled one ? |
948 |
feature_name_id: INTEGER; |
949 |
integer_value: INTEGER_CONSTANT; |
950 |
-- Internal name of the feature |
951 |
vffd4: VFFD4; |
952 |
external_i: EXTERNAL_I; |
953 |
do |
954 |
feature_name_id := feat.internal_name.name_id |
955 |
debug ("ACTIVITY") |
956 |
io.error.put_string ("FEATURE_UNIT on "); |
957 |
io.error.put_string (feat.internal_name.name); |
958 |
io.error.put_new_line; |
959 |
end; |
960 |
|
961 |
Result := feature_i_generator.new_feature (yacc_feature, feature_name_id, a_class) |
962 |
Result.set_feature_name_id (feature_name_id, feat.internal_alias_name_id) |
963 |
Result.set_written_in (a_class.class_id) |
964 |
Result.set_is_frozen (feat.is_frozen) |
965 |
Result.set_is_infix (feat.is_infix) |
966 |
Result.set_is_prefix (feat.is_prefix) |
967 |
Result.set_is_bracket (feat.is_bracket) |
968 |
Result.set_is_binary (feat.is_binary) |
969 |
Result.set_is_unary (feat.is_unary) |
970 |
Result.set_has_convert_mark (feat.has_convert_mark) |
971 |
|
972 |
if Result.is_unique then |
973 |
-- Unique value processing |
974 |
unique_feature ?= Result; |
975 |
create integer_value.make_with_value ( |
976 |
Tmp_ast_server.unique_values_item (a_class.class_id).item (Result.feature_name.string_representation)) |
977 |
if integer_value.valid_type (unique_feature.type) then |
978 |
integer_value.set_real_type (unique_feature.type) |
979 |
else |
980 |
-- The value cannot be represented using specified integer type. |
981 |
error_handler.insert_error (create {VQUI2}.make (a_class, Result.feature_name, Result.type)) |
982 |
end |
983 |
unique_feature.set_value (integer_value) |
984 |
elseif Result.is_c_external then |
985 |
-- Track new externals introduced in the class. Freeze is taken care by |
986 |
-- EXTERNALS.is_equivalent queried by SYSTEM_I. |
987 |
external_i ?= Result |
988 |
pass2_control.add_external (external_i) |
989 |
end |
990 |
|
991 |
-- Look for a previous definition of the feature |
992 |
feature_i := feature_table.item_id (feature_name_id); |
993 |
|
994 |
if feature_i /= Void then |
995 |
if feature_i.written_in = a_class.class_id then |
996 |
-- same feature, reuse body_index |
997 |
body_index := feature_i.body_index |
998 |
|
999 |
-- Found a feature of same name and written in the |
1000 |
-- same class. |
1001 |
check |
1002 |
has_body: body_server.server_has (body_index) |
1003 |
end |
1004 |
old_description := Body_server.server_item (body_index) |
1005 |
if old_description = Void then |
1006 |
-- This should not happen, but if it does. |
1007 |
is_the_same := False |
1008 |
else |
1009 |
if Tmp_ast_server.body_has (body_index) then |
1010 |
old_tmp_description := Tmp_ast_server.body_item (body_index) |
1011 |
end |
1012 |
|
1013 |
-- Incrementality of the workbench is here: we |
1014 |
-- compare the content of a new feature and the |
1015 |
-- one of an old feature. |
1016 |
is_the_same := old_description.is_assertion_equiv (yacc_feature) and |
1017 |
(old_tmp_description /= Void implies old_tmp_description.is_assertion_equiv (yacc_feature)) |
1018 |
end |
1019 |
|
1020 |
if not is_the_same then |
1021 |
-- assertions have changed |
1022 |
create assert_prop_list.make; |
1023 |
assert_prop_list.compare_objects; |
1024 |
assert_prop_list.extend (feature_i.rout_id_set.first) |
1025 |
|
1026 |
-- FIXME: Manu 08/05/2004: It is a pain to have to freeze each |
1027 |
-- time you change an assertion from an external routine, but |
1028 |
-- this is required for the moment (as call to external routine |
1029 |
-- is not done in generated byte code). |
1030 |
-- The solution is to separate the Eiffel encapsulation from |
1031 |
-- the external encapsulation and have the melted code call the |
1032 |
-- tiny external encapsulation. |
1033 |
if feature_i.is_external then |
1034 |
System.request_freeze |
1035 |
end |
1036 |
else |
1037 |
is_the_same := old_description.is_body_equiv (yacc_feature) and |
1038 |
(old_tmp_description /= Void implies old_tmp_description.is_body_equiv (yacc_feature)) |
1039 |
-- Same interface does NOT work: the types must be resolved first |
1040 |
-- The check is done later anyway |
1041 |
|
1042 |
--and then Result.same_interface (feature_i); |
1043 |
if is_the_same and unique_feature /= Void then |
1044 |
is_the_same := feature_i.is_unique and then |
1045 |
unique_feature.same_value (feature_i) |
1046 |
end; |
1047 |
end; |
1048 |
|
1049 |
-- If old representation written in the class, |
1050 |
-- keep the fact the old feature from a previous |
1051 |
-- is an origin or not. |
1052 |
Result.set_is_origin (feature_i.is_origin); |
1053 |
Result.set_rout_id_set (feature_i.rout_id_set.twin) |
1054 |
Result.set_is_selected (feature_i.is_selected); |
1055 |
else |
1056 |
-- new feature => new body_index |
1057 |
body_index := Body_index_counter.next_id |
1058 |
end |
1059 |
|
1060 |
Result.set_body_index (body_index) |
1061 |
if |
1062 |
not is_the_same or else |
1063 |
(supplier_status_modified and then |
1064 |
not Degree_4.changed_status.disjoint (feature_i.suppliers)) |
1065 |
-- The status of one of the suppliers of the feature has changed |
1066 |
then |
1067 |
debug ("ACTIVITY") |
1068 |
io.error.put_string ("Is the same "); |
1069 |
io.error.put_boolean (is_the_same); |
1070 |
io.error.put_string ("%Nsupplier_status_modified "); |
1071 |
io.error.put_boolean (supplier_status_modified); |
1072 |
io.error.put_string ("%Nchanged status "); |
1073 |
io.error.put_boolean (not Degree_4.changed_status.disjoint (feature_i.suppliers)); |
1074 |
io.error.put_string ("%Nold_feature_in_class "); |
1075 |
io.error.put_new_line; |
1076 |
end; |
1077 |
|
1078 |
-- Update `read_info' in BODY_SERVER |
1079 |
if body_index > 0 then |
1080 |
Tmp_ast_server.body_force (yacc_feature, body_index) |
1081 |
Tmp_ast_server.reactivate (body_index) |
1082 |
else |
1083 |
check |
1084 |
feature_is_il_external: feature_i.extension /= Void |
1085 |
and then feature_i.extension.is_il |
1086 |
end |
1087 |
Tmp_ast_server.body_force (yacc_feature, external_body_index) |
1088 |
end |
1089 |
|
1090 |
-- Insert the changed feature in the table of |
1091 |
-- changed features of class `a_class'. |
1092 |
changed_features.extend (feature_name_id); |
1093 |
else |
1094 |
-- Update `read_info' in BODY_SERVER |
1095 |
Tmp_ast_server.body_force (yacc_feature, body_index) |
1096 |
Tmp_ast_server.reactivate (body_index) |
1097 |
end; |
1098 |
else |
1099 |
Result.set_body_index (Body_index_counter.next_id) |
1100 |
Tmp_ast_server.body_force (yacc_feature, Result.body_index) |
1101 |
|
1102 |
-- Insert the changed feature in the table of changed |
1103 |
-- features of `a_class'. |
1104 |
changed_features.extend (feature_name_id); |
1105 |
end; |
1106 |
|
1107 |
-- Check incompatibily between `frozen' and `deferred' |
1108 |
if Result.is_frozen and then Result.is_deferred then |
1109 |
-- A deferred feature cannot be frozen |
1110 |
create vffd4; |
1111 |
vffd4.set_class (Result.written_class); |
1112 |
vffd4.set_feature_name (Result.feature_name); |
1113 |
Error_handler.insert_error (vffd4); |
1114 |
end; |
1115 |
end; |
1116 |
|
1117 |
clear is |
1118 |
-- Clear the second pass processor |
1119 |
do |
1120 |
previous_feature_table := Void; |
1121 |
feature_table := Void; |
1122 |
parents := Void; |
1123 |
Origin_table.clear_all; |
1124 |
adaptations.wipe_out; |
1125 |
changed_features.wipe_out; |
1126 |
origins.wipe_out; |
1127 |
invariant_changed := False; |
1128 |
invariant_removed := False; |
1129 |
assert_prop_list := Void; |
1130 |
|
1131 |
clear_all |
1132 |
if capacity > 200 then |
1133 |
extend_tbl_make (default_size) |
1134 |
end |
1135 |
create inherited_features.make (default_size) |
1136 |
end; |
1137 |
|
1138 |
process_pattern (resulting_table: FEATURE_TABLE) is |
1139 |
-- Process pattern of features listed in `origins'. |
1140 |
-- [We just have to compute pattern ids for origin features |
1141 |
-- since for inherited features it is transmitted automatically |
1142 |
-- by duplication of instances of FEATURE_I. For redeclarations, |
1143 |
-- Through redeclarations, the pattern id cannot change: so |
1144 |
-- the pattern id is updated in descendants of FEATURE_ADAPTATION] |
1145 |
require |
1146 |
good_argument: resulting_table /= Void; |
1147 |
local |
1148 |
a_feature: FEATURE_I; |
1149 |
sys: SYSTEM_I |
1150 |
l_origins: like origins |
1151 |
do |
1152 |
from |
1153 |
sys := System |
1154 |
l_origins := origins |
1155 |
l_origins.start |
1156 |
until |
1157 |
l_origins.after |
1158 |
loop |
1159 |
a_feature := resulting_table.item_id (l_origins.item); |
1160 |
a_feature.process_pattern; |
1161 |
l_origins.forth; |
1162 |
end; |
1163 |
end; |
1164 |
|
1165 |
update_inherited_assertions is |
1166 |
-- Update assert_id_set for redefined or merged routines |
1167 |
-- in adaptations. |
1168 |
local |
1169 |
redefined_features: REDEF_FEAT; |
1170 |
do |
1171 |
create redefined_features; |
1172 |
redefined_features.process (adaptations); |
1173 |
end; |
1174 |
|
1175 |
update_changed_features is |
1176 |
-- Update table `changed_features' of `a_class' after a |
1177 |
-- successful second pass |
1178 |
require |
1179 |
no_error: not Error_handler.has_error; |
1180 |
local |
1181 |
feature_name_id: INTEGER |
1182 |
class_id: INTEGER |
1183 |
do |
1184 |
from |
1185 |
class_id := a_class.class_id |
1186 |
changed_features.start |
1187 |
until |
1188 |
changed_features.after |
1189 |
loop |
1190 |
feature_name_id := changed_features.item; |
1191 |
a_class.insert_changed_feature (feature_name_id); |
1192 |
changed_features.forth; |
1193 |
end; |
1194 |
end; |
1195 |
|
1196 |
update_convert_clause ( |
1197 |
a_old_convert, a_new_convert: DS_HASH_TABLE [INTEGER, NAMED_TYPE_A]; |
1198 |
a_resulting_table: FEATURE_TABLE) |
1199 |
is |
1200 |
-- Take into account incremental changes in `convert' clauses. |
1201 |
require |
1202 |
a_class_not_void: a_class /= Void |
1203 |
a_old_convert_not_void: a_old_convert /= Void |
1204 |
a_resulting_table_not_void: a_resulting_table /= Void |
1205 |
local |
1206 |
l_feat_name_id: INTEGER |
1207 |
l_depend_unit: DEPEND_UNIT |
1208 |
do |
1209 |
if a_new_convert = Void or else not a_old_convert.is_equal (a_new_convert) then |
1210 |
-- Old convert clause is different from new one. For each routines previously |
1211 |
-- specified in `a_old_convert' and not specified in `a_new_convert', |
1212 |
-- we need to progagate to the classes that were using those routines |
1213 |
-- so that the code is recompiled at degree 3 (for type checking purpose only). |
1214 |
from |
1215 |
a_old_convert.start |
1216 |
until |
1217 |
a_old_convert.after |
1218 |
loop |
1219 |
l_feat_name_id := a_old_convert.item_for_iteration |
1220 |
a_resulting_table.search_id (l_feat_name_id) |
1221 |
if |
1222 |
a_resulting_table.found and |
1223 |
(a_new_convert = Void or else not a_new_convert.has_item (l_feat_name_id)) |
1224 |
then |
1225 |
create l_depend_unit.make (a_class.class_id, a_resulting_table.found_item) |
1226 |
pass2_control.propagators.extend (l_depend_unit) |
1227 |
end |
1228 |
a_old_convert.forth |
1229 |
end |
1230 |
end |
1231 |
end |
1232 |
|
1233 |
Routine_id_counter: ROUTINE_COUNTER is |
1234 |
-- Counter for routine ids |
1235 |
once |
1236 |
Result := System.routine_id_counter; |
1237 |
end; |
1238 |
|
1239 |
Body_index_counter: BODY_INDEX_COUNTER is |
1240 |
-- Counter for bodies index |
1241 |
once |
1242 |
Result := System.body_index_counter; |
1243 |
end; |
1244 |
|
1245 |
check_validity2 is |
1246 |
-- Check if redefinitions are effectively done and does |
1247 |
-- joins an deferred features if needed |
1248 |
require |
1249 |
inherited_features /= Void; |
1250 |
local |
1251 |
inherited_feature: FEATURE_I; |
1252 |
deferred_info, inherited_info: INHERIT_INFO; |
1253 |
inherit_feat: INHERIT_FEAT; |
1254 |
feature_name_id: INTEGER; |
1255 |
join: JOIN; |
1256 |
vdrs4: VDRS4; |
1257 |
do |
1258 |
from |
1259 |
start |
1260 |
until |
1261 |
after |
1262 |
loop |
1263 |
inherit_feat := item_for_iteration; |
1264 |
inherited_info := inherit_feat.inherited_info; |
1265 |
if inherited_info = Void then |
1266 |
if inherit_feat.nb_features > 0 then |
1267 |
-- Cannot find a redefinition |
1268 |
create vdrs4; |
1269 |
vdrs4.set_class (a_class); |
1270 |
vdrs4.set_feature_name (Names_heap.item (key_for_iteration)) |
1271 |
Error_handler.insert_error (vdrs4); |
1272 |
else |
1273 |
-- Case of deferred features only |
1274 |
check |
1275 |
not inherit_feat.is_empty; |
1276 |
end; |
1277 |
feature_name_id := key_for_iteration; |
1278 |
deferred_info := inherit_feat.deferred_features.first; |
1279 |
-- New inherited feature |
1280 |
inherited_feature := deferred_info.a_feature |
1281 |
inherited_feature.set_feature_name_id (feature_name_id, inherited_feature.alias_name_id) |
1282 |
-- Initialization of an inherited feature |
1283 |
init_inherited_feature (inherited_feature, inherit_feat); |
1284 |
-- Insertion in the origin table |
1285 |
inherited_info := deferred_info.twin |
1286 |
inherited_info.set_a_feature (inherited_feature); |
1287 |
Origin_table.insert (inherited_info); |
1288 |
if inherit_feat.nb_deferred > 1 then |
1289 |
-- Keep track of the feature adaptation. |
1290 |
-- The deferred features must have the same |
1291 |
-- signature |
1292 |
create join.make (inherit_feat, inherited_feature); |
1293 |
adaptations.put_front (join); |
1294 |
debug ("ACTIVITY") |
1295 |
io.put_string ("joining feature: "); |
1296 |
io.put_string (inherited_feature.feature_name); |
1297 |
io.put_string ("%N%Tfrom class: "); |
1298 |
io.put_string (inherited_feature.written_class.name); |
1299 |
io.put_new_line; |
1300 |
end; |
1301 |
end; |
1302 |
end; |
1303 |
end; |
1304 |
forth; |
1305 |
end; |
1306 |
end; |
1307 |
|
1308 |
init_inherited_feature (f: FEATURE_I; inherit_feat: INHERIT_FEAT) is |
1309 |
-- Initialization of an inherited feature |
1310 |
require |
1311 |
f_not_void: f /= Void |
1312 |
inherit_feat_not_void: inherit_feat /= Void |
1313 |
local |
1314 |
inherit_info: INHERIT_INFO |
1315 |
rout_ids: ROUT_ID_SET |
1316 |
old_feature: FEATURE_I |
1317 |
feature_name_id: INTEGER |
1318 |
do |
1319 |
-- It is no more an origin |
1320 |
f.set_is_origin (False) |
1321 |
f.set_has_property (False) |
1322 |
if a_class.is_single then |
1323 |
-- Feature getters and setters may have been generated. |
1324 |
inherit_info := inherit_feat.inherited_info |
1325 |
if inherit_info /= Void and then inherit_info.parent.parent.is_single then |
1326 |
f.set_has_property_getter (False) |
1327 |
f.set_has_property_setter (False) |
1328 |
end |
1329 |
end |
1330 |
|
1331 |
-- Check the routine table ids |
1332 |
rout_ids := inherit_feat.rout_id_set |
1333 |
f.set_rout_id_set (rout_ids.twin) |
1334 |
-- Process feature id |
1335 |
feature_name_id := f.feature_name_id |
1336 |
old_feature := feature_table.item_id (feature_name_id) |
1337 |
if old_feature = Void then |
1338 |
-- New feature id since the old feature table |
1339 |
-- doesn't have an entry `feature_name' |
1340 |
give_new_feature_id (f) |
1341 |
|
1342 |
-- We reactivate `body_index' in case `old_feature' is Void because |
1343 |
-- it was removed in `compute_feature_table' as it was not valid |
1344 |
-- anymore (Most likely because its signature had some classes |
1345 |
-- which have been moved to a different location and those |
1346 |
-- classes have now a different `class_id' which makes it not a |
1347 |
-- valid feature anymore). |
1348 |
--| The only issue when performing this call is that in a compilation |
1349 |
--| from scratch it is useless, but we do not have much choice in |
1350 |
--| case of incremental compilation. |
1351 |
Tmp_ast_server.reactivate (f.body_index) |
1352 |
else |
1353 |
-- Take the old feature id |
1354 |
f.set_feature_id (old_feature.feature_id) |
1355 |
if |
1356 |
old_feature.can_be_encapsulated and then |
1357 |
old_feature.to_generate_in (a_class) |
1358 |
then |
1359 |
-- If it is an attribute that was generated in `a_class', |
1360 |
-- we have to redo mark it dead as an encapsulation. `is_valid' |
1361 |
-- on its execution unit will tell us if we still need the |
1362 |
-- encapsulation or not. |
1363 |
system.execution_table.add_dead_function (old_feature.body_index) |
1364 |
end |
1365 |
end |
1366 |
-- Concatenation of the export statuses of all the |
1367 |
-- precursors of the inherited feature: take care of new |
1368 |
-- adapted export status specified in inheritance clause |
1369 |
f.set_export_status (inherit_feat.exports (feature_name_id)) |
1370 |
-- Insert it in the table `inherited_features'. |
1371 |
inherited_features.put (f, feature_name_id) |
1372 |
check_alias_name_conflict (f) |
1373 |
end |
1374 |
|
1375 |
give_new_feature_id (f: FEATURE_I) is |
1376 |
-- Give a new feature id to `f'. |
1377 |
require |
1378 |
good_argument: f /= Void; |
1379 |
has_a_new_name: not feature_table.has_id (f.feature_name_id); |
1380 |
local |
1381 |
new_feature_id: INTEGER; |
1382 |
old_feature: FEATURE_I; |
1383 |
do |
1384 |
if previous_feature_table /= Void then |
1385 |
old_feature := previous_feature_table.item_id (f.feature_name_id); |
1386 |
if old_feature /= Void then |
1387 |
-- Keep the feature id, because byte code for client |
1388 |
-- features using this new feature name could have been |
1389 |
-- already computed. |
1390 |
new_feature_id := old_feature.feature_id |
1391 |
else |
1392 |
new_feature_id := a_class.feature_id_counter.next; |
1393 |
end |
1394 |
else |
1395 |
new_feature_id := a_class.feature_id_counter.next; |
1396 |
end; |
1397 |
f.set_feature_id (new_feature_id); |
1398 |
end; |
1399 |
|
1400 |
check_validity3 (resulting_table: FEATURE_TABLE) is |
1401 |
-- Check the signature conformance of the redefinitions and |
1402 |
-- validity of joins; check assigner command validity. |
1403 |
local |
1404 |
f: FEATURE_I |
1405 |
l_args: FEAT_ARG |
1406 |
l_type: TYPE_A |
1407 |
do |
1408 |
from |
1409 |
adaptations.start |
1410 |
until |
1411 |
adaptations.after |
1412 |
loop |
1413 |
adaptations.item.check_adaptation (resulting_table) |
1414 |
adaptations.forth |
1415 |
end |
1416 |
from |
1417 |
resulting_table.start |
1418 |
until |
1419 |
resulting_table.after |
1420 |
loop |
1421 |
f := resulting_table.item_for_iteration |
1422 |
if f.assigner_name_id /= 0 then |
1423 |
f.check_assigner (resulting_table) |
1424 |
end |
1425 |
l_args := f.arguments |
1426 |
if l_args /= Void then |
1427 |
from |
1428 |
l_args.start |
1429 |
until |
1430 |
l_args.after |
1431 |
loop |
1432 |
l_type := l_args.item |
1433 |
if l_type.is_like_current then |
1434 |
system.set_routine_covariantly_redefined (f.rout_id_set, True) |
1435 |
elseif l_type.is_formal or else l_type.conformance_type.is_formal then |
1436 |
system.set_routine_has_formal (f.rout_id_set, True) |
1437 |
elseif l_type.is_like then |
1438 |
|
1439 |
end |
1440 |
l_args.forth |
1441 |
end |
1442 |
end |
1443 |
resulting_table.forth |
1444 |
end |
1445 |
end |
1446 |
|
1447 |
check_redeclarations (resulting_table: FEATURE_TABLE) is |
1448 |
-- Check redeclarations into an attribute. |
1449 |
do |
1450 |
from |
1451 |
adaptations.start; |
1452 |
until |
1453 |
adaptations.after |
1454 |
loop |
1455 |
adaptations.item.check_redeclaration |
1456 |
(resulting_table, feature_table, origins, Origin_table); |
1457 |
adaptations.forth; |
1458 |
end; |
1459 |
end; |
1460 |
|
1461 |
insert_feature (f: FEATURE_I) is |
1462 |
-- Insert `f' in `inherited_feature' |
1463 |
require |
1464 |
good_argument: f /= Void |
1465 |
local |
1466 |
feature_name_id: INTEGER |
1467 |
vmfn: VMFN |
1468 |
do |
1469 |
feature_name_id := f.feature_name_id |
1470 |
inherited_features.put (f, feature_name_id) |
1471 |
if inherited_features.conflict then |
1472 |
create vmfn |
1473 |
vmfn.set_class (a_class) |
1474 |
vmfn.set_a_feature (f) |
1475 |
vmfn.set_inherited_feature (inherited_features.item_id (feature_name_id)) |
1476 |
Error_handler.insert_error (vmfn) |
1477 |
else |
1478 |
check_alias_name_conflict (f) |
1479 |
end |
1480 |
end |
1481 |
|
1482 |
compute_invariant is |
1483 |
-- Compute invariant clause |
1484 |
require |
1485 |
good_context: not (a_class = Void or else class_info = Void); |
1486 |
changed: a_class.changed; |
1487 |
local |
1488 |
class_id: INTEGER; |
1489 |
-- information left by the temporary server `Tmp_ast_server' |
1490 |
-- and stored in `class_info' |
1491 |
old_invar_clause, invar_clause: INVARIANT_AS; |
1492 |
old_clause_exists, clause_exists: BOOLEAN; |
1493 |
do |
1494 |
-- First: check is the invariant clause of the current |
1495 |
-- class has syntactically changed. If yes, flag |
1496 |
-- `changed5' of `a_class' is set to True. |
1497 |
class_id := a_class.class_id; |
1498 |
-- Look in the non-temporary invariant AST server for |
1499 |
-- for an old invariant clause |
1500 |
old_clause_exists := Inv_ast_server.server_has (class_id); |
1501 |
clause_exists := Tmp_ast_server.invariant_has (class_id) |
1502 |
if clause_exists then |
1503 |
-- The changed class `a_class' has an invariant clause |
1504 |
if old_clause_exists then |
1505 |
-- Evaluation of an old invariant clause in order |
1506 |
-- to see if it has changed |
1507 |
old_invar_clause := Inv_ast_server.server_item (class_id); |
1508 |
invar_clause := Tmp_ast_server.invariant_item (class_id); |
1509 |
|
1510 |
-- Incrementality test on invariant clause |
1511 |
if invar_clause = Void then |
1512 |
invariant_changed := old_invar_clause /= Void |
1513 |
else |
1514 |
invariant_changed := not ( |
1515 |
old_invar_clause /= Void and then |
1516 |
invar_clause.is_equivalent (old_invar_clause)) |
1517 |
end |
1518 |
else |
1519 |
invariant_changed := True; |
1520 |
end; |
1521 |
elseif old_clause_exists or a_class.has_invariant then |
1522 |
invariant_removed := True; |
1523 |
tmp_ast_server.invariant_remove (class_id) |
1524 |
end; |
1525 |
end; |
1526 |
|
1527 |
feature {NONE} -- Implementation |
1528 |
|
1529 |
compute_main_parent (a_feat_tbl: FEATURE_TABLE) is |
1530 |
-- Set `number_of_features' and `main_parent' of `a_class' |
1531 |
require |
1532 |
a_feat_tbl_not_void: a_feat_tbl /= Void |
1533 |
il_generation: System.il_generation |
1534 |
local |
1535 |
l_parent, l_main_parent: CLASS_C |
1536 |
l_number_of_features, l_max: INTEGER |
1537 |
do |
1538 |
from |
1539 |
parents.start |
1540 |
until |
1541 |
parents.after |
1542 |
loop |
1543 |
l_parent := parents.item.parent |
1544 |
if l_parent.is_single or (l_parent.is_external and not l_parent.is_interface) then |
1545 |
-- We cannot optimize here, we have to take it |
1546 |
-- as main parent even if there is no feature in it. |
1547 |
l_main_parent := l_parent |
1548 |
parents.finish |
1549 |
else |
1550 |
l_number_of_features := l_parent.feature_table.count |
1551 |
if l_number_of_features > l_max then |
1552 |
l_main_parent := parents.item.parent |
1553 |
l_max := l_number_of_features |
1554 |
end |
1555 |
end |
1556 |
parents.forth |
1557 |
end |
1558 |
if l_main_parent = Void then |
1559 |
-- No parents, means that we are handling ANY. |
1560 |
l_main_parent := a_class |
1561 |
end |
1562 |
a_class.set_main_parent (l_main_parent) |
1563 |
a_class.set_number_of_features (a_feat_tbl.count) |
1564 |
ensure |
1565 |
main_parent_set: a_class.main_parent /= Void |
1566 |
nb_features_set: a_class.number_of_features = a_feat_tbl.count |
1567 |
end |
1568 |
|
1569 |
check_alias_name_conflict (f: FEATURE_I) is |
1570 |
-- Check if feature `f' has an alias name and that after adding it to `inherited_features' |
1571 |
-- `inherited_features.is_alias_conflict' is set to `true'. Report error in this case. |
1572 |
local |
1573 |
alias_name_id: INTEGER |
1574 |
vfav: VFAV |
1575 |
do |
1576 |
alias_name_id := f.alias_name_id |
1577 |
if alias_name_id > 0 and then inherited_features.is_alias_conflict then |
1578 |
if f.is_bracket then |
1579 |
create {VFAV2} vfav |
1580 |
else |
1581 |
create {VFAV1} vfav |
1582 |
end |
1583 |
vfav.set_class (a_class) |
1584 |
vfav.set_a_feature (f) |
1585 |
vfav.set_inherited_feature (inherited_features.item_alias_id (alias_name_id)) |
1586 |
Error_handler.insert_error (vfav) |
1587 |
end |
1588 |
end |
1589 |
|
1590 |
mark_generic_attribute_seeds (resulting_table: FEATURE_TABLE) is |
1591 |
-- Mark attributes that are seeds of generic types to generate |
1592 |
-- wrappers for them. |
1593 |
require |
1594 |
resulting_table_attached: resulting_table /= Void |
1595 |
local |
1596 |
f: FEATURE_I |
1597 |
a: ATTRIBUTE_I |
1598 |
do |
1599 |
from |
1600 |
resulting_table.start |
1601 |
until |
1602 |
resulting_table.after |
1603 |
loop |
1604 |
f := resulting_table.item_for_iteration |
1605 |
if f.is_attribute and then f.is_origin and then f.rout_id_set.count = 1 and then f.has_formal then |
1606 |
a ?= f |
1607 |
check |
1608 |
a_attached: a /= Void |
1609 |
end |
1610 |
a.set_generate_in (f.written_in) |
1611 |
end |
1612 |
resulting_table.forth |
1613 |
end |
1614 |
end |
1615 |
|
1616 |
feature {NONE} -- Temporary body index |
1617 |
|
1618 |
external_body_index: INTEGER is |
1619 |
-- Dummy body index to be used when someone redefine an external feature |
1620 |
-- with no body (i.e. an IL external). |
1621 |
once |
1622 |
Result := Body_index_counter.next_id |
1623 |
ensure |
1624 |
external_body_index_positive: Result > 0 |
1625 |
end |
1626 |
|
1627 |
indexing |
1628 |
copyright: "Copyright (c) 1984-2007, Eiffel Software" |
1629 |
license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)" |
1630 |
licensing_options: "http://www.eiffel.com/licensing" |
1631 |
copying: "[ |
1632 |
This file is part of Eiffel Software's Eiffel Development Environment. |
1633 |
|
1634 |
Eiffel Software's Eiffel Development Environment is free |
1635 |
software; you can redistribute it and/or modify it under |
1636 |
the terms of the GNU General Public License as published |
1637 |
by the Free Software Foundation, version 2 of the License |
1638 |
(available at the URL listed under "license" above). |
1639 |
|
1640 |
Eiffel Software's Eiffel Development Environment is |
1641 |
distributed in the hope that it will be useful, but |
1642 |
WITHOUT ANY WARRANTY; without even the implied warranty |
1643 |
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
1644 |
See the GNU General Public License for more details. |
1645 |
|
1646 |
You should have received a copy of the GNU General Public |
1647 |
License along with Eiffel Software's Eiffel Development |
1648 |
Environment; if not, write to the Free Software Foundation, |
1649 |
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
1650 |
]" |
1651 |
source: "[ |
1652 |
Eiffel Software |
1653 |
356 Storke Road, Goleta, CA 93117 USA |
1654 |
Telephone 805-685-1006, Fax 805-685-6869 |
1655 |
Website http://www.eiffel.com |
1656 |
Customer support http://support.eiffel.com |
1657 |
]" |
1658 |
|
1659 |
end |
1660 |
|