feature -- Access
integer: INTEGER
string: STRING
set: LINKED_SET [INTEGER]
other: detachable OTHER
feature -- Basic operations
test_all (a: ANY; b: like a; c: like a): BOOLEAN
local
i, j: INTEGER
do
set.extend (999)
i := 1
integer := 2
j := 3
create string.make (99)
i := 5
i := set.count
string := "Assignment to attribute"
string.left_adjust
create set.make
Result := a.is_equal (b)
(create {PERSISTENCE_FACILITIES}).persistence_manager.on_object_created (string, Current)
(create {PERSISTENCE_FACILITIES}).persistence_manager.on_object_created (set, Current)
(create {PERSISTENCE_FACILITIES}).persistence_manager.on_attribute_modified (integer, Current)
(create {PERSISTENCE_FACILITIES}).persistence_manager.on_attribute_modified (string, Current)
(create {PERSISTENCE_FACILITIES}).persistence_manager.on_feature_call (set)
(create {PERSISTENCE_FACILITIES}).persistence_manager.on_feature_call (string)
(create {PERSISTENCE_FACILITIES}).persistence_manager.on_feature_call (b)
end
All the inserted lines seem correct except the last one. The argument to `on_feature_call' should be `a' not `b'. This is caused by the order in which the SYNTAX_UPDATER_VISITOR calls `process_access_id_as' and the way in which I have redefined some features. My code is below. I'm sure there is a way to do this correctly, but I just can't see it. I would sure be grateful if someone could point it out.
In my code, I collect `created_objects', `modified_attributes', and `targets' [of qualified feature calls] and then insert corresponding code in feature `process_routine_as'. Here is the code that I add/modified in SYNTAX_UPDATER_VISITOR:
feature -- JJJ added
modified_attributes: LINKED_SET [STRING_8]
-- Names of attributes that were the target of an assignment statement
-- (i.e. modified) in a particular feature.
-- This is wiped out when `process_routine_as' finishes
created_objects: LINKED_SET [STRING_8]
-- Names of attributes that were the target of a creation routine
-- (i.e. created) in a particular feature.
-- This is wiped out when `process_routine_as' finishes
targets: LINKED_SET [STRING_8]
-- The names of attributes that are the targets of a feature call
routine: detachable ROUTINE_AS
-- The routine that is currently being processed if any
target: detachable ACCESS_ID_AS
-- Saves the target of a feature call being processed
process_create_creation_as (l_as: CREATE_CREATION_AS)
do
print ("processing CREATE_CREATION_AS " + l_as.target.access_name_8 + "%N")
is_updated := true
Precursor (l_as)
if not (is_local (l_as.target) ) then
created_objects.extend (l_as.target.access_name_8)
end
end
process_access_id_as (l_as: ACCESS_ID_AS)
-- Redefined to capture the `target' of a feature call for use
-- in `process_access_feat_as'.
do
print ("processing ACCESS_ID_AS " + l_as.access_name_8 + "%N")
is_updated := true
Precursor (l_as)
-- This could be in a feature call or in an assignment statement
target := l_as
end
process_access_feat_as (l_as: ACCESS_FEAT_AS)
-- Redefined to add code after a qualified feature call
do
is_updated := true
Precursor (l_as)
if l_as.is_qualified and attached target then
print ("processing ACCESS_FEAT_AS " + l_as.access_name_8 + "%N")--" target = " + target.access_name_8 + "%N")
targets.extend (target.access_name_8)
-- target := l_as
-- targets.extend (l_as.access_name_8)
end
target := Void
end
process_assign_as (l_as: ASSIGN_AS)
-- Process to add code after an assignment statement
do
print ("processing ASSIGN_AS " + l_as.target.access_name_8 + "%N")
is_updated := true
Precursor (l_as)
if attached routine as r then
if not (is_local (l_as.target) ) then
modified_attributes.extend (l_as.target.access_name_8)
end
end
end
process_routine_as (l_as: ROUTINE_AS)
-- Redefined to capture the routine that is being processed, then
-- process the routine, inserting code just after the body,
-- if required.
do
is_updated := true
routine := l_as -- used in `process_assign_as'
-- Precursor (l_as)
safe_process (l_as.obsolete_keyword (match_list))
safe_process (l_as.obsolete_message)
safe_process (l_as.precondition)
safe_process (l_as.internal_locals)
safe_process (l_as.routine_body)
print ("processing ROUTINE_AS %N")
-- Add code to tell the persistent manager that an attribute was created
from created_objects.start
until created_objects.after
loop
context.add_string ("%N")
context.add_string ("(create {PERSISTENCE_FACILITIES}).persistence_manager.on_object_created (")
context.add_string (created_objects.item)
context.add_string (", Current)")
created_objects.forth
end
created_objects.wipe_out
-- Add code to tell the persistent manager that an attribute has changed
from modified_attributes.start
until modified_attributes.after
loop
context.add_string ("%N")
context.add_string ("(create {PERSISTENCE_FACILITIES}).persistence_manager.on_attribute_modified (")
context.add_string (modified_attributes.item)
context.add_string (", Current)")
modified_attributes.forth
end
modified_attributes.wipe_out
-- Add code to tell the persistent manager about a qualified feature call
from targets.start
until targets.exhausted
loop
context.add_string (" %N")
context.add_string ("(create {PERSISTENCE_FACILITIES}).persistence_manager.on_feature_call (" + targets.item + ")")
targets.forth
end
safe_process (l_as.postcondition)
safe_process (l_as.rescue_keyword (match_list))
safe_process (l_as.rescue_clause)
safe_process (l_as.end_keyword)
end
is_local (a_target: ACCESS_AS):BOOLEAN
-- Is `a_target' [of an assignment] a local variable of `routine'?
local
idl: IDENTIFIER_LIST
n: STRING_8
i: INTEGER
do
check attached routine as r then
if a_target.access_name_8.as_lower ~ "result" then
Result := true
elseif attached r.locals as locs then
from locs.start
until locs.after or Result
loop
idl := locs.item.id_list
from i := 1
until i > idl.count or Result
loop
n := locs.item.item_name (i)
if a_target.access_name_8 ~ n then
Result := true
end
i := i + 1
end
locs.forth
end
end
end
end
-- end jjj added ----------------------------------------