Skip to content

Commit

Permalink
Handle lists being modified by use of ~
Browse files Browse the repository at this point in the history
Adjust how lists are built when ~ is used, so we do not crash
even if the list is modified as it is being constructed.

This also makes the behaviour of GAP consistent between bytecode
and immediate code.
  • Loading branch information
ChrisJefferson committed May 24, 2018
1 parent d6d1b20 commit e4c2711
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 17 deletions.
53 changes: 36 additions & 17 deletions src/exprs.c
Original file line number Diff line number Diff line change
Expand Up @@ -919,9 +919,19 @@ Obj EvalPermExpr (
**
** 'EvalListExpr' just calls 'ListExpr1' and 'ListExpr2' to evaluate the
** list expression.
**
** The 'safe' argument to ListExpr1 and ListExpr2 should be set to 1 when
** the list expression may be modified when its elements are being
** constructed. This can occur when an element of the list refers to ~.
**
** When 'safe' is 1, we use a slower code path which ensures the list is
** in a valid state after each element is added, and we don't crash if the
** size or TNUM of the list is changed during the construction of elements
** in the list.
**
*/
Obj ListExpr1 ( Expr expr );
void ListExpr2 ( Obj list, Expr expr );
Obj ListExpr1(Expr expr, Int safe);
void ListExpr2(Obj list, Expr expr, Int safe);
Obj RecExpr1 ( Expr expr );
void RecExpr2 ( Obj rec, Expr expr );

Expand All @@ -931,8 +941,8 @@ Obj EvalListExpr (
Obj list; /* list value, result */

/* evaluate the list expression */
list = ListExpr1( expr );
ListExpr2( list, expr );
list = ListExpr1(expr, 0);
ListExpr2(list, expr, 0);

/* return the result */
return list;
Expand Down Expand Up @@ -964,13 +974,13 @@ Obj EvalListTildeExpr (
tilde = STATE( Tilde );

/* create the list value */
list = ListExpr1( expr );
list = ListExpr1(expr, 1);

/* assign the list to '~' */
STATE(Tilde) = list;

/* evaluate the subexpressions into the list value */
ListExpr2( list, expr );
ListExpr2(list, expr, 1);

/* restore old value of '~' */
STATE(Tilde) = tilde;
Expand Down Expand Up @@ -999,8 +1009,7 @@ Obj EvalListTildeExpr (
** '[ [1], ~[1] ]' requires that the value of one subexpression is entered
** into the list value before the next subexpression is evaluated.
*/
Obj ListExpr1 (
Expr expr )
ALWAYS_INLINE Obj ListExpr1(Expr expr, Int safe)
{
Obj list; /* list value, result */
Int len; /* logical length of the list */
Expand All @@ -1015,15 +1024,18 @@ Obj ListExpr1 (
else {
list = NEW_PLIST( T_PLIST, len );
}
SET_LEN_PLIST( list, len );
if (safe) {
SET_LEN_PLIST(list, 0);
}
else {
SET_LEN_PLIST(list, len);
}

/* return the list */
return list;
}

void ListExpr2 (
Obj list,
Expr expr )
ALWAYS_INLINE void ListExpr2(Obj list, Expr expr, Int safe)
{
Obj sub; /* value of a subexpression */
Int len; /* logical length of the list */
Expand Down Expand Up @@ -1053,18 +1065,25 @@ void ListExpr2 (
{
if (posshole == 1)
{
SET_FILT_LIST(list, FN_IS_NDENSE);
if (!safe || TNUM_OBJ(list) == T_PLIST) {
SET_FILT_LIST(list, FN_IS_NDENSE);
}
posshole = 2;
}
sub = EVAL_EXPR( ADDR_EXPR(expr)[i-1] );
SET_ELM_PLIST( list, i, sub );
if (safe) {
ASS_LIST(list, i, sub);
}
else {
SET_ELM_PLIST(list, i, sub);
}
CHANGED_BAG( list );
}

}
if (!posshole)
SET_FILT_LIST(list, FN_IS_DENSE);

if (!posshole && !safe) {
SET_FILT_LIST(list, FN_IS_DENSE);
}
}


Expand Down
11 changes: 11 additions & 0 deletions tst/testinstall/tilde.tst
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,15 @@ true
gap> i := InputTextString( "local a; a := 10; return rec(a := a*10, b := ~);" );;
gap> r := rec(a := ~, b := ReadAsFunction(i)(), c := ~.b.a);
rec( a := ~, b := rec( a := 100, b := ~.b ), c := 100 )
gap> [Length(~),Length(~),Length(~)];
[ 0, 1, 2 ]
gap> (function() return [Length(~),Length(~),Length(~)]; end)();
[ 0, 1, 2 ]
gap> rem := function(l) Remove(l); return 1; end;;
gap> [2,rem(~),rem(~),rem(~)];
[ ,,, 1 ]
gap> [2,rem(~),3,4,rem(~),5,6,rem(~)];
[ , 1, 3,, 1, 5,, 1 ]
gap> (function() return [2,rem(~),3,4,rem(~),5,6,rem(~)]; end)();
[ , 1, 3,, 1, 5,, 1 ]
gap> STOP_TEST( "tilde.tst", 1);

0 comments on commit e4c2711

Please sign in to comment.