Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Q: how to find all the renamed attributes of a (AST processed) class in the gec compiler ? #70

Open
mw66 opened this issue Feb 29, 2024 · 70 comments
Assignees

Comments

@mw66
Copy link

mw66 commented Feb 29, 2024

Hi,

I want to find all the renamed attributes of a (AST processed) class in the gec compiler:

I have checked et_class.e

and found this navigation:

ET_CLASS.queries: ET_QUERY_LIST

ET_QUERY.is_attribute

but where to find if the attribute is a renamed one?

Thanks.

@ebezault
Copy link
Collaborator

ebezault commented Feb 29, 2024

This needs to be double-checked in the code, but if I recall correctly you have to look at first_precursor and other_precursors. If they are not Void, then see whether their names are the same as in the current class or not.

@ebezault ebezault self-assigned this Feb 29, 2024
@mw66
Copy link
Author

mw66 commented Feb 29, 2024

Thanks. I also found this navigation:

pwd: /gobo/tool/gec

../../library/tools/src/eiffel/compilation/et_feature_flattener.e
flatten_inherited_feature (a_feature: ET_INHERITED_FEATURE)

../../library/tools/src/eiffel/ast/feature/et_inherited_feature.e
ET_INHERITED_FEATURE
flattened_parent: ET_PARENT_FEATURE
-- Parent feature from which `flattened_feature' is resulting

../../library/tools/src/eiffel/ast/feature/et_parent_feature.e
precursor_feature: ET_FEATURE
-- Feature inherited from `parent'

../../library/tools/src/eiffel/ast/feature/et_feature.e
is_attribute: BOOLEAN
-- Is feature an attribute?

Do you think this is good enough to scan all the renamed attribute (I don't care about methods)?

@ebezault
Copy link
Collaborator

I think it would work, except that ET_INHERITED_FEATURE objects are intermediate objects only used in the feature flattener. They are not kept in the AST objects.

So with the former solution, you can call the code of gec up to Degree 4 included, and then write your own code (without having to modify any line of code in the Gobo library) to navigate through the resulting AST (ET_CLASS.queries.item(...).first_precursor).

With the latter solution, you would probably have to modify the feature flattener class to intercept the ET_INHERITED_FEATURE objects on the fly when they are processed. Because they are thrown away after being processed.

@mw66
Copy link
Author

mw66 commented Feb 29, 2024

Which solution is easiest to implement in your estimate?

(You know: "There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies.")

I want to take the simple way 🙂

@ebezault
Copy link
Collaborator

Simplest way is the former solution: no need to modify Gobo's code, so no risk to break it. Just call the Gobo code from your code to generate the AST, and then traverse the AST (ET_CLASS, ET_FEATURE, precursors, ...) still from your code.

@mw66
Copy link
Author

mw66 commented Mar 1, 2024

Thanks.

I will use tool/gedoc/src/gedoc_implicit_converts_format.e as a template for quick start.

@mw66
Copy link
Author

mw66 commented Mar 1, 2024

Hi @ebezault

I did a quick experiment using tool/gedoc/src/gedoc_implicit_converts_format.e as a template:

https://github.com/joortcom/gobo/blob/eiffel_rename/tool/gedoc/src/gedoc_field_rename_format.e#L119-L176

only two new methods:

process_et_feature

process_implicit_converts

Since gec cannot build this project (ref #71), I added a Makefile to build using ISE's ec:

https://github.com/joortcom/gobo/blob/eiffel_rename/tool/gedoc/Makefile

$ cd /gobo/tool/gedoc
$ make ise  # build gedoc

$ cd test/rename/

$ make demo  # try the new build
../../gedoc --format=field_rename app.ecf
Degree 6: 0/0/0 0:0:0.149
Degree 5: 0/0/0 0:0:7.063
Degree 4: 0/0/0 0:0:2.403
[renamed field] READABLE_INDEXABLE.upper => STRING_8.count

[renamed field] READABLE_INDEXABLE.upper => READABLE_STRING_8.count

[renamed field] READABLE_INDEXABLE.upper => STRING_32.count

[renamed field] TWO_WAY_LIST.first_element => TWO_WAY_TREE.first_child

[renamed field] TWO_WAY_LIST.last_element => TWO_WAY_TREE.last_child

[renamed field] LINKED_LIST.after => TWO_WAY_TREE.child_after

[renamed field] LINKED_LIST.first_element => LINKED_TREE.first_child

[renamed field] LINKED_LIST.before => TWO_WAY_TREE.child_before

[renamed field] LINKED_LIST.count => TWO_WAY_TREE.arity

[renamed field] LINKABLE.right => TWO_WAY_TREE.right_sibling

[renamed field] LINKED_LIST.after => LINKED_TREE.child_after

[renamed field] BI_LINKABLE.left => TWO_WAY_TREE.left_sibling

[renamed field] LINKED_LIST.active => TWO_WAY_TREE.child

[renamed field] LINKED_LIST.before => LINKED_TREE.child_before

[renamed field] LINKED_LIST.count => LINKED_TREE.arity

[renamed field] TWO_WAY_LIST_ITERATION_CURSOR.active => TWO_WAY_TREE_ITERATION_CURSOR.node

[renamed field] LINKABLE.right => LINKED_TREE.right_sibling

[renamed field] LINKED_LIST_ITERATION_CURSOR.active => LINKED_TREE_ITERATION_CURSOR.node

[renamed field] GENERAL_SPECIAL_ITERATION_CURSOR.area => SPECIAL_ITERATION_CURSOR.target

[renamed field] LINKED_LIST.active => LINKED_TREE.child

[renamed field] INDEXABLE_ITERATION_CURSOR.target_index => HASH_TABLE_ITERATION_CURSOR.iteration_position

[renamed field] READABLE_INDEXABLE.upper => DIRECTORY_NAME.count

[renamed field] IO_MEDIUM.handle_available => PLAIN_TEXT_FILE.descriptor_available

[renamed field] IO_MEDIUM.handle_available => RAW_FILE.descriptor_available

[renamed field] READABLE_INDEXABLE.upper => FILE_NAME.count

[renamed field] IO_MEDIUM.handle_available => FILE.descriptor_available

[renamed field] IO_MEDIUM.handle_available => CONSOLE.descriptor_available

[renamed field] READABLE_INDEXABLE.upper => PATH_NAME.count

[renamed field] READABLE_INDEXABLE.upper => READABLE_STRING_32.count

[renamed field] HASH_TABLE.count => SED_OBJECTS_TABLE.capacity

Total Time: 0/0/0 0:0:10.252

However in the test file research_assistant.e has two fields addr renames, but why it's not reported in the above output?

BTW:

$ cd test/rename/
$ make gobo  # the test app program can be compiled by gec, and executed fine.

So what's going wrong? why some of the class / queries not visited?

Can you help me to make this output research_assistant.e's renamed fields?

Thanks.

@mw66
Copy link
Author

mw66 commented Mar 1, 2024

In particular: looks like it does not scan from the <root class="APP" feature="make"/> class?

https://github.com/joortcom/gobo/blob/eiffel_rename/tool/gedoc/test/rename/app.ecf#L4

@ebezault
Copy link
Collaborator

ebezault commented Mar 1, 2024

Before looking at the rename issue, I have a couple of remarks:

  • See my comment in the other thread about gec and CAT-calls. You should be able to adapt your code so that it does not report a CAT-call.
  • In your Makefile, you can replace:
	ec  -config src/system.ecf
	cd EIFGENs/gedoc/$(DIR)/ && finish_freezing

with:

	ec  -c_compile -config src/system.ecf

@ebezault
Copy link
Collaborator

ebezault commented Mar 1, 2024

For class RESEARCH_ASSISTANT, assuming that this is this code:

class RESEARCH_ASSISTANT
inherit
	STUDENT rename addr as student_addr end  -- field student_addr inherit the dorm semantics
	FACULTY rename addr as faculty_addr end  -- field faculty_addr inherit the lab  semantics
	-- then select, NOTE: not needed by SmartEiffel, but needed by GOBO and ISE compiler
	PERSON  select addr end

I can see that there are replications. It means that from 1 attribute addr, you created 2 new attributes (student_addr and faculty_addr) to end up with 3 attributes in class RESEARCH_ASSISTANT. The attributes student_addr and faculty_addr have no precursors (at least not in the internals of the compiler) because the selected version is the one inherited from PERSON. It's as if two new attributes had been created in class RESEARCH_ASSISTANT. So using first_precursor and other_precursors will not help in this case because it will not catch renaming occurring on a replicated attribute.

Another solution could be to traverse ET_CLASS.parent_clauses, go down to the rename clauses (ET_PARENT.renames), look at the new name (ET_RENAME.new_name.feature_name) and see whether it is an attribute in the current class (ET_CLASS.named_query (...).is_attribute).

This should compile with no CAT-call warnings with gec :-)

@mw66
Copy link
Author

mw66 commented Mar 1, 2024

with:

	ec  -c_compile -config src/system.ecf

I tried this, the command runs fine without any error, but the executable EIFGENs/gedoc/W_code/gedoc is not updated.

@mw66
Copy link
Author

mw66 commented Mar 1, 2024

Another solution could be to traverse ET_CLASS.parent_clauses, go down to the rename clauses (ET_PARENT.renames), look at the new name (ET_RENAME.new_name.feature_name) and see whether it is an attribute in the current class (ET_CLASS.named_query (...).is_attribute).

Thanks, the navigation from ET_CLASS.parent_clauses worked:

[renamed field] STUDENT.addr => RESEARCH_ASSISTANT.student_addr
[renamed field] FACULTY.addr => RESEARCH_ASSISTANT.faculty_addr

@mw66
Copy link
Author

mw66 commented Mar 1, 2024

I've got the renamed fields path. Now, how do I get inherited (instead of self-declared) fields path? i.e.

PERSON.addr => STUDENT.addr  (since STUDENT does not declare .addr in itself, but inherited from PERSON)
PERSON.addr => FACULTY.addr  (same as above)

@ebezault
Copy link
Collaborator

ebezault commented Mar 1, 2024

with:

	ec  -c_compile -config src/system.ecf

I tried this, the command runs fine without any error, but the executable EIFGENs/gedoc/W_code/gedoc is not updated.

Forcing the C compilation by calling finish_freezing will regenerate the same executable. What is updated after an incremental compilation is the .melted file, not the C files. If you want the C files to be updated, add the command-line option -freeze.

@ebezault
Copy link
Collaborator

ebezault commented Mar 1, 2024

I got the renamed fields path. Now, how do I get inherited (instead of self-declared) fields path? i.e.

PERSON.addr => STUDENT.addr  (since STUDENT does not declare .addr in itself, but inherited from PERSON)
PERSON.addr => FACULTY.addr  (same as above)

OK, so you are not just interested in renamed attributes anymore, but in all inherited attributes! Perhaps you should combine the two implementations (traversing the parent clauses for the renamings, and the first and other precursors to detect those which are not renamed). If it has a precursor, it means that it is inherited. The reverse is not true as we could see in case of replication.

Otherwise, in ET_CLASS.queries, the queries between 1 and `declared_count' are declared in the current class, and above they are inherited. But be careful, declared in the current class does not mean that they have been introduced in this class. It can also mean that they are inherited and redefined.

@ebezault
Copy link
Collaborator

ebezault commented Mar 1, 2024

I'm sorry that the solution is not as easy as it could be. This code has been written for the specific needs of gec, so it might be missing some metadata which were not needed by gec. But hopefully it should be possible to reconstruct what you need by combining several approaches, as suggested above.

@mw66
Copy link
Author

mw66 commented Mar 1, 2024

I'm still interested in renamed attributes, but need to dig deeper: basically I want to detect renamed attributes that coming from the same origin (e.g. in the case of diamond problem).

So:

[renamed field] STUDENT.addr => RESEARCH_ASSISTANT.student_addr
[renamed field] FACULTY.addr => RESEARCH_ASSISTANT.faculty_addr

I need to dig deeper:

PERSON.addr => STUDENT.addr  (since STUDENT does not declare .addr in itself, but inherited from PERSON)
PERSON.addr => FACULTY.addr  (same as above)

and find out RESEARCH_ASSISTANT.student_addr and RESEARCH_ASSISTANT.faculty_addr are both originated from the same PERSON.addr. This is the goal I want to detect.

Sounds like I need to take this 1st approach:

Perhaps you should combine the two implementations (traversing the parent clauses for the renamings, and the first and other precursors to detect those which are not renamed). If it has a precursor, it means that it is inherited. The reverse is not true as we could see in case of replication.

I will give it a try.

@ebezault
Copy link
Collaborator

ebezault commented Mar 1, 2024

I just remembered that there is another data at your disposal (which you can use in combination with all the above):

  • ET_FEATURE.implementation_class tells you where the current feature was written,
  • ET_FEATURE.implementation_feature is the object of this feature in ET_FEATURE.implementation_class (which might be different from the object of this feature in the current class, in case of renaming for example, but it can also be when joining or when changing the export status among other things).

@mw66
Copy link
Author

mw66 commented Mar 1, 2024

  • ET_FEATURE.implementation_class tells you where the current feature was written,

what does "where the current feature was written" esp "written" mean? first time introduced? or last time (final)?

@ebezault
Copy link
Collaborator

ebezault commented Mar 1, 2024

  • ET_FEATURE.implementation_class tells you where the current feature was written,

what does "where the current feature was written" esp "written" mean? first time introduced? or last time (final)?

Last time. "Written" means in which class file can I find its text. So if I have:

class A
feature
     f
          do
                ...
          end
end

class B
inherit
      A
             redefine
                    f
             end
feature
      f
          do
                ...
          end
end

class C
inherit
       B
end      

then feature C.f is written in class B.

And a more complicated example:

class D
feature
     f
          do
                ...
          end
end

class E
inherit
       D
            undefine
                  f
           end
       C
end

then E.f is written in class B (because the version from D is undefined).

@mw66
Copy link
Author

mw66 commented Mar 1, 2024

Tried this, but it's not working for PERSON.addr:

If it has a precursor, it means that it is inherited.

My code is here:
https://github.com/joortcom/gobo/blob/eiffel_rename/tool/gedoc/src/gedoc_field_rename_format.e#L125-L136

output is here:
https://github.com/joortcom/gobo/blob/eiffel_rename/tool/gedoc/test/rename/inherited_fields.path

it worked for things like this one:

https://github.com/joortcom/gobo/blob/a3af3982a213fdbf3886d1e4c52a505f2697be9b/tool/gedoc/test/rename/inherited_fields.path#L43

but not for PERSON.addr => FACULTY.addr.

Will continue try the other method ET_FEATURE.implementation_class.

@ebezault
Copy link
Collaborator

ebezault commented Mar 1, 2024

If it has a precursor, it means that it is inherited. The reverse is not true

So we are unfortunately in the case where "the reverse is not true" (no precursor does not mean that it is not inherited).

@ebezault
Copy link
Collaborator

ebezault commented Mar 1, 2024

Looking at your code, I still recommend using:

if l_first_precursor.name.same_feature_name(query.name) then

instead of:

if l_lower_name.is_equal(query.lower_name) then

It's CAT-call free.

@mw66
Copy link
Author

mw66 commented Mar 1, 2024

I just remembered that there is another data at your disposal (which you can use in combination with all the above):

  • ET_FEATURE.implementation_class tells you where the current feature was written,
  • ET_FEATURE.implementation_feature is the object of this feature in ET_FEATURE.implementation_class (which might be different from the object of this feature in the current class, in case of renaming for example, but it can also be when joining or when changing the export status among other things).

This approach worked:

??? field: PERSON.addr => FACULTY.addr
[renamed field] STUDENT.addr => RESEARCH_ASSISTANT.student_addr
??? field: PERSON.addr => STUDENT.addr
[renamed field] FACULTY.addr => RESEARCH_ASSISTANT.faculty_addr
??? field: PERSON.addr => RESEARCH_ASSISTANT.student_addr
??? field: PERSON.addr => RESEARCH_ASSISTANT.faculty_addr
??? field: PERSON.addr => RESEARCH_ASSISTANT.addr

But now, I want to filter out non-direct super-sub-class relationship, i.e filter out:

??? field: PERSON.addr => RESEARCH_ASSISTANT.student_addr
??? field: PERSON.addr => RESEARCH_ASSISTANT.faculty_addr

So how to get a ET_CLASS's direct super-classes / sub-classes?

@ebezault
Copy link
Collaborator

ebezault commented Mar 1, 2024

So how to get a ET_CLASS's direct super-classes / sub-classes?

You get the direct super-classes with ET_CLASS.parent_clauses.
For the direct sub-classes, you will have to build them yourself. You can have a look at ET_CLASS.descendants which builds all sub-classes (direct and indirect).

@mw66
Copy link
Author

mw66 commented Mar 1, 2024

Is there a way to get rid of this: is_equal for class name:

https://github.com/joortcom/gobo/blob/eiffel_rename/tool/gedoc/src/gedoc_field_rename_format.e#L124

			if not query.implementation_class.upper_name.is_equal(a_class.upper_name) then

@ebezault
Copy link
Collaborator

ebezault commented Mar 1, 2024

if not query.implementation_class.name.same_class_name (a_class.name) then

@ebezault
Copy link
Collaborator

ebezault commented Mar 1, 2024

You can also write:

if query.implementation_class /= a_class then

which is probably better because it is possible to have two classes with the same name from different libraries.

@mw66
Copy link
Author

mw66 commented Mar 1, 2024

And how about compare:

a ET_CLASS and a parent.type is the same class?

@ebezault
Copy link
Collaborator

ebezault commented Mar 3, 2024

I don't know if it can compile everything in EiffelVision2, but I have an application which uses some parts of it and I managed to compile and run it under Windows. I can see that you are under Linux (I guess). I never tried to compile an application using EiffelVision2 on this platform.

@mw66
Copy link
Author

mw66 commented Mar 4, 2024

FYI: I found a potential problem here:

/Eiffel_23.09/examples/docking/simple

======================================== docking_simple.ecf total fields:  3240
diamond:  EV_SENSITIVE.implementation  =>  SD_PLACE_HOLDER_ZONE
   implementation {('EV_SENSITIVE.implementation', 'EV_WIDGET.implementation', 'EV_CONTAINER.implementation', 'SD_PLACE_HOLDER_ZONE.implementation')}
   implementation_upper_zone {('EV_SENSITIVE.implementation', 'EV_WIDGET.implementation', 'SD_PLACE_HOLDER_ZONE.implementation_upper_zone')}
=============================

I'm manually checking the source code right now:

This navigation verified the 2nd renamed path:

SD_PLACE_HOLDER_ZONE inherit SD_UPPER_ZONE

SD_UPPER_ZONE inherit EV_CONTAINER rename implementation as implementation_upper_zone

EV_CONTAINER inherit EV_WIDGET redefine implementation

And the 1st un-renamed path is:

SD_PLACE_HOLDER_ZONE inherit SD_DOCKING_ZONE

SD_DOCKING_ZONE inherit EV_CELL

EV_CELL inherit EV_CONTAINER

@ebezault while the updated gedoc reported the correct diamond path, but it did not report the direct step-wise edge.

attached if the generated file:

inherited_fields.path.txt
diamond.txt

you can also run

/gobo/tool/gedoc/detect_diamond.py > diamond.txt

to generate them yourself.

@ebezault
Copy link
Collaborator

ebezault commented Mar 4, 2024

while the updated gedoc reported the correct diamond path, but it did not report the direct step-wise edge.

It's probably time to try to implement the alternative implementation that I had suggested:

  • For a given class:
    • Traverse the parents:
      • For a given parent:
        • Get all attributes of its base_class (traverse ET_CLASS.queries and check is_attribute)
        • Check whether these attributes appear in the rename clause (you might want to store the content of the rename clause in a hash-table indexed by old_names for easier access).
        • Check whether these attributes appear in the redefine clause.
        • At this stage you should have all inherited attributes from the parent:
          • B.foo -> C.foo <- no renaming
          • B.apple -> C.orange <- renaming
          • You can add a + sign to indicate whether the attribute is redefined in the current class (if you are interested in this information)
    • Traverse the attributes of the current class (traverse ET_CLASS.queries and check is_attribute)
      • If they are not in the list above it means that they have been introduced in the current class.

@mw66
Copy link
Author

mw66 commented Mar 4, 2024

I don't know if it can compile everything in EiffelVision2, but I have an application which uses some parts of it and I managed to compile and run it under Windows. I can see that you are under Linux (I guess). I never tried to compile an application using EiffelVision2 on this platform.

Can you let me know which part of EiffelVision2 you can build on Windows? I will give it a try with gec.

I have scanned all the Eiffel_23.09 dir, looks like all the diamonds reported are in EV_ library, so if gec can build any of the /Eiffel_23.09/examples/ that uses EV_ library, we can compare the result of gec and ec.

@ebezault
Copy link
Collaborator

ebezault commented Mar 4, 2024

If you want to compare the result of gec and ec, you can build your own (non-GUI) small example (like RESEARCH STUDENT).

@mw66
Copy link
Author

mw66 commented Mar 4, 2024

If you want to compare the result of gec and ec, you can build your own (non-GUI) small example (like RESEARCH STUDENT).

I want to build on the real code in Eiffel_23.09 distributed files.

@mw66
Copy link
Author

mw66 commented Mar 7, 2024

It's probably time to try to implement the alternative implementation that I had suggested:

@ebezault Now, I want your opinion on this:

Ultimately I want this functionality to be contributed back to the GOBO toolchain, but what's the best place to put it?

  1. in the gec compiler (diamond field rename warning message), or
  2. separate tool like gedoc, or even geck (means checker)
  3. both 1) and 2)
  4. both 1) and 2), and even like gedoc tool's --force option to auto-transform the code as the first method in the paper, and overwrite user's source code.

For me, I can do a prototype for option 2).

For other options 1), 3), 4) probably you want do it since no one knows the interals of the GOBO compiler better than you.

What do you think?

@ebezault
Copy link
Collaborator

ebezault commented Mar 7, 2024

You will have to let me a few days to think about it. I still did not have time to read your paper.
There is a 5th solution:

  1. in gedoc, both to generate the warning, and an option to auto-transform the code.

As for gec, I would rather change it to behave like ISE Eiffel. The idea is that code which compiles and works with ISE Eiffel should compile and behave the same with Gobo Eiffel, and vice-versa.

@mw66
Copy link
Author

mw66 commented Mar 7, 2024

The essence of that paper is: ECMA Eiffel standard 8.16.2, and 8.6.16 are actually in conflict as demonstrated in this diamond field renaming example:

  1. by 8.16.2 “Any two of these features inherited under a different name yield two features of D”, which means replicated (i.e. separated copies) features in the diamond bottom class D;
  2. while by 8.6.16 “Semantics: Renaming principle”: “Renaming does not affect the semantics of an inherited feature”, which implies access via separated copies (i.e. via different names in the sub-classes) still end up to the same (shared) inherited feature of the super-classes when applied to the diamond problem of multiple inheritance. (This is how ISE compiler implemented it).

This is why SmartEiffel and GOBO implementations are different from ISE Eiffel: basically ISE did both 1) and 2) (which is wrong); while SmartEiffel and GOBO only did 1) (which is also wrong).

(The correct implementation of 2) while honoring 1) is what have been proposed in the paper; and the ECMA Eiffel standard
need to be revised.)

While both the current compiler implementation approaches are wrong, if I have to choose, I'd say ISE's implementation is more wrong: because it also defeats the original purpose of renaming to have separate features. I understand your goal to keep gec work with ISE Eiffel code, but I think if one compiler have to change, that should be the ISE compiler, not the GOBO compiler. NOTE: No matter which compiler will eventually change, this will be a breaking change, will affect (I don't know how) many existing customers' code.

Regardless of the final outcome, a checker to detect the renamed fields in diamond inheritance and give warning messages to the programmers is always needed.

@ebezault
Copy link
Collaborator

ebezault commented Mar 7, 2024

I'd say ISE's implementation is more wrong: because it also defeats the original purpose of renaming to have separate features.

Are we sure of that? There could be two attributes pointing to the same object.

@ebezault
Copy link
Collaborator

ebezault commented Mar 7, 2024

From this line:

“Renaming does not affect the semantics of an inherited feature”

you infer that:

which implies access via separated copies (i.e. via different names in the sub-classes) still end up to the same (shared) inherited feature of the super-classes

But "same semantics" does not mean "identifical features", does it?

@mw66
Copy link
Author

mw66 commented Mar 7, 2024

Are we sure of that? There could be two attributes pointing to the same object.

and

From this line:

“Renaming does not affect the semantics of an inherited feature”

you infer that:

which implies access via separated copies (i.e. via different names in the sub-classes) still end up to the same (shared) inherited feature of the super-classes

But "same semantics" does not mean "identifical features", does it?

This what Bertrand said "ambiguity": it's not made very precise in the ECMA standard what it supposed to mean. And in practice, SmartEiffel and GOBO completely ignored this rule; while ISE compiler implement it as reference identity.

That's how ISE compiler implemented it, you can check and run the example code of RESEARCH_ASSISTANT example.

@ebezault
Copy link
Collaborator

ebezault commented Mar 7, 2024

That's how ISE compiler implement it, you can check and run the example code of RESEARCH_ASSISTANT example.

This is what I get when compiled with ISE Eiffel:

ResAssis has 3 addresses: <home, dorm, lab>
PERSON  size: 32
STUDENT size: 32
FACULTY size: 32
RESEARCH_ASSISTANT size: 48
ResAssisdo_benchwork in thehome
ResAssis take_rest in the: home
-- print_student|faculty_addr_direct_field
ResAssis as STUDENT.addr: home
ResAssis as FACULTY.addr: home
-- print_student|faculty_addr_via_accessor
ResAssis as STUDENT.addr: home
ResAssis as FACULTY.addr: home
-- check reference identity
ra.addr != ra.faculty_addr
ra.addr != ra.student_addr
ra.student_addr != ra.faculty_addr
-- test some assignment: suppose ra moved both lab2 and dorm2
ResAssis has 3 addresses: <lab2, dorm, lab>
ResAssis has 3 addresses: <dorm2, dorm, lab>

Apparently the RESEARCH_ASSISTANT class has 3 address attributes, not just one.

@mw66
Copy link
Author

mw66 commented Mar 7, 2024

Apparently the RESEARCH_ASSISTANT class has 3 address attributes, not just one.

Ah? which version of ISE compiler you are using? on Windows? Linux?

here is my result on Linux:

$ ec -version
ISE EiffelStudio version 23.09.10.7341 - linux-x86-64

$ ./app
ResAssis has 3 addresses: <home, home, home>
PERSON  size: 32
STUDENT size: 32
FACULTY size: 32
RESEARCH_ASSISTANT size: 48
ResAssis do_benchwork in the: home
ResAssis take_rest in the: home
-- print_student|faculty_addr_direct_field
ResAssis as STUDENT.addr: home
ResAssis as FACULTY.addr: home
-- print_student|faculty_addr_via_accessor
ResAssis as STUDENT.addr: home
ResAssis as FACULTY.addr: home
-- check reference identity
ra.addr  = ra.faculty_addr
ra.addr  = ra.student_addr
ra.student_addr  = ra.faculty_addr
-- test some assignment: suppose ra moved both lab2 and dorm2
ResAssis has 3 addresses: <lab2, lab2, lab2>
ResAssis has 3 addresses: <dorm2, dorm2, dorm2>

@mw66
Copy link
Author

mw66 commented Mar 7, 2024

-- test some assignment: suppose ra moved both lab2 and dorm2
ResAssis has 3 addresses: <lab2, dorm, lab>
ResAssis has 3 addresses: <dorm2, dorm, lab>

And regardless of 3 or 1 field, these last 2 lines of output are wrong in both GOBO and ISE compiler with respect to the programmer's intended application semantics.

@ebezault
Copy link
Collaborator

ebezault commented Mar 7, 2024

Ah? which version of ISE compiler you are using? on Windows? Linux?

PS C:\> ec -version
ISE EiffelStudio version 23.09.10.7341 - win64

@mw66
Copy link
Author

mw66 commented Mar 7, 2024

Ah? which version of ISE compiler you are using? on Windows? Linux?

PS C:\> ec -version
ISE EiffelStudio version 23.09.10.7341 - win64

Are you using this Makefile:

https://github.com/joortcom/eiffel_rename/blob/77ffe635b98256783aca35652995979b8b6bd16b/eiffel_bug/Makefile#L15

and

make ise

Let's try all the different platform and (non-)finalized mode.

@ebezault
Copy link
Collaborator

ebezault commented Mar 7, 2024

It's in finalized mode. I guess that you are in workbench (i.e. non-finalized mode). It's more likely to be the problem that the different of platform.

@ebezault
Copy link
Collaborator

ebezault commented Mar 7, 2024

I'm not using any Makefile.

@mw66
Copy link
Author

mw66 commented Mar 7, 2024

Let's try all the different platform and (non-)finalized mode.

@ebezault
Copy link
Collaborator

ebezault commented Mar 7, 2024

I get the same output as you in workbench mode under Windows.

@mw66
Copy link
Author

mw66 commented Mar 7, 2024

OK, I tried, (non-)finalized and finalized mode are different. This is an ISE compiler bug.

@ebezault
Copy link
Collaborator

ebezault commented Mar 7, 2024

So ISE Eiffel does not agree with itself between workbench and finalized mode! Interesting!

@mw66
Copy link
Author

mw66 commented Mar 7, 2024

-- test some assignment: suppose ra moved both lab2 and dorm2
ResAssis has 3 addresses: <lab2, dorm, lab>
ResAssis has 3 addresses: <dorm2, dorm, lab>

And regardless of 3 or 1 field, these last 2 lines of output are wrong in both GOBO and ISE compiler with respect to the programmer's intended application semantics.

But regardless of which finalized mode, these outputs are all wrong in both GOBO and ISE compiler.

@mw66
Copy link
Author

mw66 commented Mar 7, 2024

So ISE Eiffel does not agree with itself between workbench and finalized mode! Interesting!

Even ISE Eiffel itself implemented two different field renaming semantics.

@mw66
Copy link
Author

mw66 commented Mar 7, 2024

So ISE Eiffel does not agree with itself between workbench and finalized mode! Interesting!

Even ISE Eiffel itself implemented two different field renaming semantics.

BTW, @ebezault have you checked your @gobosoft.com email :-)

@ebezault
Copy link
Collaborator

ebezault commented Mar 7, 2024

BTW, @ebezault have you checked your @gobosoft.com email :-)

Yes, but I still did not have time to review all your work.
I have a real job when I'm not playing with Gobo Eiffel! :-)

@mw66
Copy link
Author

mw66 commented Mar 7, 2024

I'd say ISE's implementation is more wrong: because it also defeats the original purpose of renaming to have separate features.

Are we sure of that? There could be two attributes pointing to the same object.

Now we can read my sentence as: I'd say ISE's workbench mode implementation is more wrong (than the finalized mode): because it also defeats the original purpose of renaming to have separate features.

And it's been proven by their actual output behavior :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants