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

Don't automatically call attribute setters on mutable objects #3592

Merged
merged 5 commits into from
Aug 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions doc/ref/types.xml
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ except if the attribute had been specially constructed as
<Q>mutable attribute</Q>.
<P/>
It depends on the representation of an object (see&nbsp;<Ref Sect="Representation"/>)
which attribute values it stores. An object in the representation
which attribute values it stores. An immutable object in the representation
<C>IsAttributeStoringRep</C> stores <E>all</E> attribute values once they are
computed. Moreover, for an object in this representation, subsequent
calls to an attribute will return the <E>same</E> object; this is achieved
Expand All @@ -496,6 +496,13 @@ value. (These methods are called the <Q>system setter</Q> and the
<Q>system getter</Q> of the attribute, respectively.)<Index>system
getter</Index><Index>system setter</Index>
<P/>
Mutable objects in <C>IsAttributeStoringRep</C> are allowed, but
attribute values are not automatically stored in them. Such objects
are useful because values can be stored by explicitly calling the
relevant setter, and because they may later be made immutable using
<Ref Func="MakeImmutable"/>, at which point they will start storing
all attribute values.
<P/>
Note also that it is impossible to get rid of a stored attribute
value because the system may have drawn conclusions from the old
attribute value, and just removing the value might leave the data
Expand Down Expand Up @@ -568,7 +575,8 @@ of the object <A>obj</A> is known.
<Description>
For an attribute <A>attr</A>, <C>Setter(<A>attr</A>)</C>
is called automatically when the attribute value has been
computed for the first time.
computed for an immutable object which does not already have a
value stored for <A>attr</A>.
One can also call the setter explicitly,
for example, <C>Setter( Size )( <A>obj</A>, <A>val</A> )</C>
sets <A>val</A> as size of the
Expand Down
3 changes: 3 additions & 0 deletions lib/sgpres.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,9 @@ InstallGlobalFunction( PresentationAugmentedCosetTable,
# group generators.
SetPrimaryGeneratorWords(T,aug.primaryGeneratorWords);

# Since T is mutable, we must set this attribite "manually"
SetTzOptions(T, TzOptions(T));

# handle relators of length 1 or 2, but do not eliminate any primary
# generators.
TzOptions(T).protected := tree[TR_PRIMARY];
Expand Down
3 changes: 3 additions & 0 deletions lib/tietze.gi
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,9 @@ InstallGlobalFunction( PresentationFpGroup, function ( arg )
SetOne(T,Identity( F ));
T!.identity:=Identity( F );

# since T is mutable, we must set this attribute "manually"
SetTzOptions(T,TzOptions(T));

# initialize some Tietze options
TzOptions(T).protected := 0;
TzOptions(T).printLevel:=printlevel;
Expand Down
8 changes: 4 additions & 4 deletions src/opers.c
Original file line number Diff line number Diff line change
Expand Up @@ -2420,7 +2420,7 @@ Obj DoAttribute (
val = CopyObj( val, 0 );

/* set the value (but not for internal objects) */
if ( ENABLED_ATTR( self ) == 1 ) {
if ( ENABLED_ATTR( self ) == 1 && !IS_MUTABLE_OBJ( obj ) ) {
switch ( TNUM_OBJ( obj ) ) {
case T_COMOBJ:
case T_POSOBJ:
Expand Down Expand Up @@ -2471,7 +2471,7 @@ static Obj DoVerboseAttribute(Obj self, Obj obj)
val = CopyObj( val, 0 );

/* set the value (but not for internal objects) */
if ( ENABLED_ATTR( self ) == 1 ) {
if ( ENABLED_ATTR( self ) == 1 && !IS_MUTABLE_OBJ( obj ) ) {
switch ( TNUM_OBJ( obj ) ) {
case T_COMOBJ:
case T_POSOBJ:
Expand Down Expand Up @@ -2516,7 +2516,7 @@ static Obj DoMutableAttribute(Obj self, Obj obj)
val = DoOperation1Args( self, obj );

/* set the value (but not for internal objects) */
if ( ENABLED_ATTR( self ) == 1 ) {
if ( ENABLED_ATTR( self ) == 1 && !IS_MUTABLE_OBJ( obj ) ) {
switch ( TNUM_OBJ( obj ) ) {
case T_COMOBJ:
case T_POSOBJ:
Expand Down Expand Up @@ -2561,7 +2561,7 @@ static Obj DoVerboseMutableAttribute(Obj self, Obj obj)
val = DoVerboseOperation1Args( self, obj );

/* set the value (but not for internal objects) */
if ( ENABLED_ATTR( self ) == 1 ) {
if ( ENABLED_ATTR( self ) == 1 && !IS_MUTABLE_OBJ( obj ) ) {
switch ( TNUM_OBJ( obj ) ) {
case T_COMOBJ:
case T_POSOBJ:
Expand Down
29 changes: 27 additions & 2 deletions tst/testinstall/attribute.tst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,31 @@ gap> NewAttribute("IsBanana", IsGroup, true, 15);
<Attribute "IsBanana">
gap> NewAttribute("IsBanana", IsGroup, "mutable", 15, "Hello, world");
Error, Usage: NewAttribute( <name>, <filter>[, <mutable>][, <rank>] )

#
gap> DeclareAttribute("FavouriteFruit", IsObject);
gap> foo := rec();;
gap> fam := NewFamily("FruitFamily");
<Family: "FruitFamily">
gap> Objectify(NewType(fam, IsMutable and IsAttributeStoringRep), foo);
<object>
gap> InstallMethod(FavouriteFruit, [IsObject], x-> "apple");
gap> FavouriteFruit(foo);
"apple"
gap> HasFavouriteFruit(foo);
false
gap> SetSize(foo, 17);
gap> HasSize(foo);
true
gap> Size(foo);
17
gap> InstallMethod(FavouriteFruit, [HasSize], x-> "pear");
gap> FavouriteFruit(foo);
"pear"
#@if not IsHPCGAP
gap> MakeImmutable(foo);
<object>
gap> FavouriteFruit(foo);
"pear"
gap> HasFavouriteFruit(foo);
true
#@fi
gap> STOP_TEST("attribute.tst", 1);