Difference between revisions of "Eiffel Breaking Changes"
(→Library changes: Added 2 notes for issues involving TUPLE.) |
(→Void-safe copy) |
||
Line 31: | Line 31: | ||
A lot of code would not compile anymore by this change. Pretty much all libraries would have to be rewritten. | A lot of code would not compile anymore by this change. Pretty much all libraries would have to be rewritten. | ||
− | ==Void-safe copy== | + | ==Void-safe and invariant-safe copy== |
===Before=== | ===Before=== | ||
Whenever a user redefined copy, it was the assumption that argument's fields would be all set to their default value (case of '''copy''' called indirectly via '''twin''') or to some tangible value (normal case of doing '''x.copy (y)'''). | Whenever a user redefined copy, it was the assumption that argument's fields would be all set to their default value (case of '''copy''' called indirectly via '''twin''') or to some tangible value (normal case of doing '''x.copy (y)'''). | ||
===After=== | ===After=== | ||
− | Whenever a user redefines copy, all the fields are properly set to | + | Whenever a user redefines copy, all the fields are properly set to the fields of the original object which is either the object on which we call '''twin''' or the source being copied from. |
===Rationale=== | ===Rationale=== | ||
+ | This makes the code fully void-safe as we will never try to access fields that are declared attached but actually Void. | ||
+ | |||
+ | This removes the need to disable invariant checking in the implementation of '''twin'''. | ||
===Issues=== | ===Issues=== | ||
+ | Because '''copy''' can be called directly or indirectly, we used to perform the following test on a field that was supposedly attached at runtime: | ||
+ | |||
+ | <e> | ||
+ | if field = Void then | ||
+ | -- Called from `twin` | ||
+ | ... | ||
+ | else | ||
+ | -- Direct call to `copy' | ||
+ | ... | ||
+ | end | ||
+ | </e> | ||
+ | |||
+ | This kind of code won't work anymore. Instead one has to do | ||
+ | <e> | ||
+ | if Current = other then | ||
+ | -- Called from `twin` | ||
+ | ... | ||
+ | else | ||
+ | -- Direct call to `copy' | ||
+ | ... | ||
+ | end | ||
+ | </e> | ||
+ | |||
+ | but this is not ideal since we cannot distinguish between <e>a.twin</e> from <e>a.copy (a)</e>. Since calling the later is very rare, the above solution is a good one overall. | ||
==Restrict export to copy== | ==Restrict export to copy== |
Revision as of 05:08, 23 January 2016
Warning: Article under development
Contents
- 1 Introduction
- 2 Library changes
- 3 Language Change
Introduction
As of this writing, January 21st 2016, the Eiffel language has slowly evolved over the years and added numerous new facilities. Initially, the changes were done by Eiffel Software while maintaining backward compatibility. Then, a major work was done between 2001 and 2005 to standardize the language which became an ECMA standard in 2005 (ECMA-367) and an ISO standard in 2006 (ISO/IEC 25436:2006). That work established some constructs initially implemented in EiffelStudio and also introduced some new ones. Most of the changes introduced by the standardization have been implemented but there are quite a few remaining. In some cases, it is due to the ration cost/benefit of the implementation, in some others it is a breaking changes. In addition, since the standardization was completed, Eiffel Software kept adding new language features too.
This page is going to list all the changes that needs to be done by Eiffel Software to conform to the standard which cover both the language but also the library facilities required to support the language specification.
Library changes
Strings
Before
STRING maps to STRING_8 And we have STRING_32, IMMUTABLE_STRING_8 and IMMUTABLE_STRING_32
After
STRING should be the equivalent of what IMMUTABLE_STRING_32 was before. STRING_8 should be the equivalent of what IMMUTABLE_STRING_8 was before. MUTABLE_STRING_8 should be the equivalent of what STRING_8 was before. MUTABLE_STRING_32 should be the equivalent of what STRING_32 was before.
Rational
When STRING_32 was added, we did not want to break existing code if it became the default. For example, many Eiffel libraries having a binding with C, could directly use an Eiffel STRING object as argument to a C routines. Of course this is very dangerous and we have changed this over the year to introduce safer mechanism (such as C_STRING).
Now the world is Unicode, not using a Unicode string by default does not make sense. On top of that, string instances are rarely modified and we have seen over the year many bugs because users have a tendency to forget this important fact. Which caused a lot of code to duplicate strings just to be sure, making the code less efficient. This is why we want to map STRING to IMMUTABLE_STRING_32.
The end benefit is that we would have cleaner string manipulations and more importantly much more efficient string operations (search, string sharing, traversals, ...)
Issues
A lot of code would not compile anymore by this change. Pretty much all libraries would have to be rewritten.
Void-safe and invariant-safe copy
Before
Whenever a user redefined copy, it was the assumption that argument's fields would be all set to their default value (case of copy called indirectly via twin) or to some tangible value (normal case of doing x.copy (y)).
After
Whenever a user redefines copy, all the fields are properly set to the fields of the original object which is either the object on which we call twin or the source being copied from.
Rationale
This makes the code fully void-safe as we will never try to access fields that are declared attached but actually Void.
This removes the need to disable invariant checking in the implementation of twin.
Issues
Because copy can be called directly or indirectly, we used to perform the following test on a field that was supposedly attached at runtime:
if field = Void then -- Called from `twin` ... else -- Direct call to `copy' ... end
This kind of code won't work anymore. Instead one has to do
if Current = other then -- Called from `twin` ... else -- Direct call to `copy' ... end
but this is not ideal since we cannot distinguish between a.twin
from a.copy (a)
. Since calling the later is very rare, the above solution is a good one overall.
Restrict export to copy
Change dynamic type of objects
File operations
Remove explicit creation procedure from TUPLE
Scope: void-safety
Before
After
Rationale
Explicit creation of a TUPLE
with attached reference fields introduces objects that break void-safety rules and make a system void-unsafe.
Issues
Some code needs to be redesigned to remove explicit TUPLE
creation.
Impact
Low: explicit tuple creation can be flagged as obsolete by using regular Eiffel mechanism. After 1-2 releases the feature can be removed.
Make TUPLE
argument of features {ROUTINE}.call
and {FUNCTION}.item
attached
Scope: void-safety
Before
{ROUTINE}.call
and {FUNCTION}.item
take argument of a type detachable TUPLE
.
After
{ROUTINE}.call
and {FUNCTION}.item
take argument of a type TUPLE
.
Rationale
It is possible that an agent object expects some arguments, but if it is passed Void
, the compiler does not warn user about the issue.
Issues
All calls .call (Void)
and .item (Void)
need to be updated.
Impact
Very low: code can be updated by replacing .call (Void)
with .call
.