SYNTAX_UPDATER_VISITOR questions

9 views
Skip to first unread message

Jimmy Johnson

unread,
May 12, 2015, 8:29:37 PM5/12/15
to eiffelst...@googlegroups.com
Sorry for the long message but don't know how to show the problem without sending the class texts.

I modified the syntax updater program to insert code after a creation instruction, an assignment, and a qualified feature call.  Here is a feature after it is updated.  The the lines beginning with "(create {..." were inserted by the updater.

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 ----------------------------------------


Reply all
Reply to author
Forward
0 new messages