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

Reduce immutable/mutable diffs (UPDATE: now ready for merge) #1571

Merged
merged 11 commits into from
Apr 14, 2018
2 changes: 1 addition & 1 deletion doc/ref/create.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,7 @@ gap> l := [1,2,4];
gap> MakeImmutable(l);
[ 1, 2, 4 ]
gap> l[3] := 5;
Error, Lists Assignment: <list> must be a mutable list
Error, List Assignment: <list> must be a mutable list
]]></Example>
<P/>
For external objects, the situation is different. An external object which
Expand Down
2 changes: 1 addition & 1 deletion doc/tut/lists.xml
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ gap> list[3][5] := 'w';; list; copy;
[ 1, 2, "threw", [ 4 ] ]
[ 1, 2, "three", [ 4 ] ]
gap> copy[3][5] := 'w';
Lists Assignment: <list> must be a mutable list
List Assignment: <list> must be a mutable list
not in any function
Entering break read-eval-print loop ...
you can 'quit;' to quit to outer loop, or
Expand Down
121 changes: 25 additions & 96 deletions src/blister.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,69 +105,39 @@ Obj TYPE_BLIST_SSORT_IMM;
Obj TYPE_BLIST_EMPTY_MUT;
Obj TYPE_BLIST_EMPTY_IMM;

Obj TypeBlistMut (
Obj list )
{
/* special case for the empty blist */
if ( LEN_BLIST(list) == 0 ) {
return TYPE_BLIST_EMPTY_MUT;
} else {
return TYPE_BLIST_MUT;
}
}

Obj TypeBlistImm (
Obj list )
{
/* special case for the empty blist */
if ( LEN_BLIST(list) == 0 ) {
return TYPE_BLIST_EMPTY_IMM;
} else {
return TYPE_BLIST_IMM;
}
}

Obj TypeBlistNSortMut (
Obj list )
Obj TypeBlist(Obj list)
{
/* special case for the empty blist */
if ( LEN_BLIST(list) == 0 ) {
return TYPE_BLIST_EMPTY_MUT;
return IS_MUTABLE_PLAIN_OBJ(list) ? TYPE_BLIST_EMPTY_MUT
: TYPE_BLIST_EMPTY_IMM;
} else {
return TYPE_BLIST_NSORT_MUT;
return IS_MUTABLE_PLAIN_OBJ(list) ? TYPE_BLIST_MUT
: TYPE_BLIST_IMM;
}
}

Obj TypeBlistNSortImm (
Obj list )
Obj TypeBlistNSort(Obj list)
{
/* special case for the empty blist */
if ( LEN_BLIST(list) == 0 ) {
return TYPE_BLIST_EMPTY_IMM;
return IS_MUTABLE_PLAIN_OBJ(list) ? TYPE_BLIST_EMPTY_MUT
: TYPE_BLIST_EMPTY_IMM;
} else {
return TYPE_BLIST_NSORT_IMM;
return IS_MUTABLE_PLAIN_OBJ(list) ? TYPE_BLIST_NSORT_MUT
: TYPE_BLIST_NSORT_IMM;
}
}

Obj TypeBlistSSortMut (
Obj list )
Obj TypeBlistSSort(Obj list)
{
/* special case for the empty blist */
if ( LEN_BLIST(list) == 0 ) {
return TYPE_BLIST_EMPTY_MUT;
return IS_MUTABLE_PLAIN_OBJ(list) ? TYPE_BLIST_EMPTY_MUT
: TYPE_BLIST_EMPTY_IMM;
} else {
return TYPE_BLIST_SSORT_MUT;
}
}

Obj TypeBlistSSortImm (
Obj list )
{
/* special case for the empty blist */
if ( LEN_BLIST(list) == 0 ) {
return TYPE_BLIST_EMPTY_IMM;
} else {
return TYPE_BLIST_SSORT_IMM;
return IS_MUTABLE_PLAIN_OBJ(list) ? TYPE_BLIST_SSORT_MUT
: TYPE_BLIST_SSORT_IMM;
}
}

Expand Down Expand Up @@ -261,23 +231,16 @@ Obj DoCopyBlist(Obj list, Int mut)

#if !defined(USE_THREADSAFE_COPYING)

Obj CopyBlistImm(Obj list, Int mut)
{
GAP_ASSERT(!IS_MUTABLE_OBJ(list));
return list;
}

Obj CopyBlist (
Obj list,
Int mut )
{
Obj copy;
Obj tmp;

/* immutable objects should never end up here, because
* they have their own handler defined above
*/
GAP_ASSERT(IS_MUTABLE_OBJ(list));
if (!IS_MUTABLE_OBJ(list)) {
return list;
}

copy = DoCopyBlist(list, mut);
/* leave a forwarding pointer */
Expand Down Expand Up @@ -689,22 +652,6 @@ void AssBlist (
}


/****************************************************************************
**
*F AssBlistImm( <list>, <pos>, <val> ) . assign to an immutable boolean list
*/
void AssBlistImm (
Obj list,
Int pos,
Obj val )
{
ErrorReturnVoid(
"Lists Assignment: <list> must be a mutable list",
0L, 0L,
"you can 'return;' and ignore the assignment" );
}


/****************************************************************************
**
*F AsssBlist( <list>, <poss>, <vals> ) . assign several elements to a blist
Expand Down Expand Up @@ -738,22 +685,6 @@ void AsssBlist ( /* currently not used */
}


/****************************************************************************
**
*F AsssBlistImm( <list>, <poss>, <vals> ) . . assign to an immutable blist
*/
void AsssBlistImm (
Obj list,
Obj poss,
Obj val )
{
ErrorReturnVoid(
"Lists Assignments: <list> must be a mutable list",
0L, 0L,
"you can 'return;' and ignore the assignment" );
}


/****************************************************************************
**
*F PosBlist( <list>, <val>, <start> ) position of an elm in a boolean list
Expand Down Expand Up @@ -2452,12 +2383,12 @@ static Int InitKernel (
}

/* install the type methods */
TypeObjFuncs[ T_BLIST ] = TypeBlistMut;
TypeObjFuncs[ T_BLIST +IMMUTABLE ] = TypeBlistImm;
TypeObjFuncs[ T_BLIST_NSORT ] = TypeBlistNSortMut;
TypeObjFuncs[ T_BLIST_NSORT +IMMUTABLE ] = TypeBlistNSortImm;
TypeObjFuncs[ T_BLIST_SSORT ] = TypeBlistSSortMut;
TypeObjFuncs[ T_BLIST_SSORT +IMMUTABLE ] = TypeBlistSSortImm;
TypeObjFuncs[ T_BLIST ] = TypeBlist;
TypeObjFuncs[ T_BLIST +IMMUTABLE ] = TypeBlist;
TypeObjFuncs[ T_BLIST_NSORT ] = TypeBlistNSort;
TypeObjFuncs[ T_BLIST_NSORT +IMMUTABLE ] = TypeBlistNSort;
TypeObjFuncs[ T_BLIST_SSORT ] = TypeBlistSSort;
TypeObjFuncs[ T_BLIST_SSORT +IMMUTABLE ] = TypeBlistSSort;

/* initialise list tables */
InitClearFiltsTNumsFromTable ( ClearFiltsTab );
Expand All @@ -2477,7 +2408,7 @@ static Int InitKernel (
for ( t1 = T_BLIST; t1 <= T_BLIST_SSORT; t1 += 2 ) {
#if !defined(USE_THREADSAFE_COPYING)
CopyObjFuncs [ t1 ] = CopyBlist;
CopyObjFuncs [ t1 +IMMUTABLE ] = CopyBlistImm;
CopyObjFuncs [ t1 +IMMUTABLE ] = CopyBlist;
CopyObjFuncs [ t1 +COPYING ] = CopyBlistCopy;
CopyObjFuncs [ t1 +IMMUTABLE +COPYING ] = CopyBlistCopy;
CleanObjFuncs[ t1 ] = CleanBlist;
Expand Down Expand Up @@ -2515,9 +2446,7 @@ static Int InitKernel (
ElmsListFuncs [ t1 ] = ElmsBlist;
ElmsListFuncs [ t1 +IMMUTABLE ] = ElmsBlist;
AssListFuncs [ t1 ] = AssBlist;
AssListFuncs [ t1 +IMMUTABLE ] = AssBlistImm;
AsssListFuncs [ t1 ] = AsssListDefault;
AsssListFuncs [ t1 +IMMUTABLE ] = AsssBlistImm;
IsDenseListFuncs[ t1 ] = AlwaysYes;
IsDenseListFuncs[ t1 +IMMUTABLE ] = AlwaysYes;
IsHomogListFuncs[ t1 ] = IsHomogBlist;
Expand Down
2 changes: 1 addition & 1 deletion src/listfunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ void AddPlist3 (

if ( ! IS_MUTABLE_PLIST(list) ) {
list = ErrorReturnObj(
"Lists Assignment: <list> must be a mutable list",
"List Assignment: <list> must be a mutable list",
0L, 0L,
"you may replace <list> via 'return <list>;'" );
FuncADD_LIST( 0, list, obj );
Expand Down
4 changes: 1 addition & 3 deletions src/lists.c
Original file line number Diff line number Diff line change
Expand Up @@ -2613,10 +2613,8 @@ static Int InitKernel (
}


/* install the generic mutability test function */
/* install tests for being copyable */
for ( type = FIRST_LIST_TNUM; type <= LAST_LIST_TNUM; type += 2 ) {
IsMutableObjFuncs[ type ] = AlwaysYes;
IsMutableObjFuncs[ type+IMMUTABLE ] = AlwaysNo;
IsCopyableObjFuncs[ type ] = AlwaysYes;
IsCopyableObjFuncs[ type+IMMUTABLE ] = AlwaysYes;
}
Expand Down
13 changes: 13 additions & 0 deletions src/lists.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#ifndef GAP_LISTS_H
#define GAP_LISTS_H

#include <src/error.h>
#include <src/objects.h>

/****************************************************************************
Expand Down Expand Up @@ -510,6 +511,12 @@ static inline void ASS_LIST(Obj list, Int pos, Obj obj)
{
GAP_ASSERT(pos > 0);
GAP_ASSERT(obj != 0);
UInt tnum = TNUM_OBJ(list);
if (FIRST_LIST_TNUM <= tnum && tnum <= LAST_IMM_MUT_TNUM &&
(tnum & IMMUTABLE)) {
ErrorReturnVoid("List Assignment: <list> must be a mutable list", 0,
0, "you can 'return;' and ignore the assignment");
}
(*AssListFuncs[TNUM_OBJ(list)])(list, pos, obj);
}

Expand Down Expand Up @@ -556,6 +563,12 @@ static inline void ASSS_LIST(Obj list, Obj poss, Obj objs)
GAP_ASSERT(IS_POSS_LIST(poss));
GAP_ASSERT(IS_DENSE_LIST(objs));
GAP_ASSERT(LEN_LIST(poss) == LEN_LIST(objs));
UInt tnum = TNUM_OBJ(list);
if (FIRST_LIST_TNUM <= tnum && tnum <= LAST_IMM_MUT_TNUM &&
(tnum & IMMUTABLE)) {
ErrorReturnVoid("List Assignments: <list> must be a mutable list", 0,
0, "you can 'return;' and ignore the assignment");
}
(*AsssListFuncs[TNUM_OBJ(list)])(list, poss, objs);
}

Expand Down
29 changes: 26 additions & 3 deletions src/objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -518,10 +518,33 @@ extern void CheckedMakeImmutable( Obj obj );
** 'IS_MUTABLE_OBJ' returns 1 if the object <obj> is mutable (i.e., can
** change due to assignments), and 0 otherwise.
*/
#define IS_MUTABLE_OBJ(obj) \
((*IsMutableObjFuncs[ TNUM_OBJ(obj) ])( obj ))

extern Int (*IsMutableObjFuncs[LAST_REAL_TNUM+1]) ( Obj obj );
static inline Int IS_MUTABLE_OBJ(Obj obj)
{
UInt tnum = TNUM_OBJ(obj);
if (/*FIRST_CONSTANT_TNUM <= tnum &&*/ tnum <= LAST_CONSTANT_TNUM)
return 0;
if (FIRST_IMM_MUT_TNUM <= tnum && tnum <= LAST_IMM_MUT_TNUM)
return !(tnum & IMMUTABLE);
return ((*IsMutableObjFuncs[tnum])(obj));
}


/****************************************************************************
**
*F IS_MUTABLE_PLAIN_OBJ( <obj> ) . . . . . . is an object plain and mutable
**
** 'IS_MUTABLE_PLAIN_OBJ' returns 1 if the object <obj> is a plain object
** (i.e., built into GAP), and mutable (i.e., can change due to assignments),
** and 0 otherwise.
*/
static inline Int IS_MUTABLE_PLAIN_OBJ(Obj obj)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function IS_MUTABLE_PLAIN_OBJ was meant to be kind of an optimization, but of course it's mostly redundant with the changes to IS_MUTABLE_OBJ in PR #1563.

{
UInt type = TNUM_OBJ(obj);
return (FIRST_IMM_MUT_TNUM <= type) && (type <= LAST_IMM_MUT_TNUM)
&& !(type & IMMUTABLE);
}


/****************************************************************************
**
Expand Down
5 changes: 0 additions & 5 deletions src/objset.c
Original file line number Diff line number Diff line change
Expand Up @@ -1037,11 +1037,6 @@ static Int InitKernel (
PrintObjFuncs[ T_OBJSET+IMMUTABLE ] = PrintObjSet;
PrintObjFuncs[ T_OBJMAP ] = PrintObjMap;
PrintObjFuncs[ T_OBJMAP+IMMUTABLE ] = PrintObjMap;
/* install mutability functions */
IsMutableObjFuncs [ T_OBJSET ] = AlwaysYes;
IsMutableObjFuncs [ T_OBJSET+IMMUTABLE ] = AlwaysNo;
IsMutableObjFuncs [ T_OBJMAP ] = AlwaysYes;
IsMutableObjFuncs [ T_OBJMAP+IMMUTABLE ] = AlwaysNo;

#ifdef USE_THREADSAFE_COPYING
SetTraversalMethod(T_OBJSET, TRAVERSE_BY_FUNCTION, TraverseObjSet, CopyObjSet);
Expand Down
Loading