diff --git a/doc/ref/debug.xml b/doc/ref/debug.xml index a8f1c9abd4..a13a747892 100644 --- a/doc/ref/debug.xml +++ b/doc/ref/debug.xml @@ -876,20 +876,35 @@ brk> return; gap> ]]>

-This behaviour can be controlled using the following procedure. + +This behaviour can be controlled using the following procedures. + -interval must be a non-negative small integer (between 0 and -2^{28}). An interval of 0 suppresses the monitoring of recursion + returns the nesting level of the GAP +interpreter. This is reset to 0 every time the break loop is entered. + sets the depth of the stack at which +GAP will enter the Break loop. interval must be a non-negative small +integer (between 0 and 2^{28}). +An interval of 0 suppresses the monitoring of recursion altogether. In this case excessive recursion may cause ⪆ to crash.

dive:= function(depth) if depth>1 then dive(depth-1); fi; return; end; -function( depth ) ... end +gap> GetRecursionDepth(); +0 +gap> dive := function(depth) +> if depth>1 then +> dive(depth-1); +> else +> Print("Depth ", GetRecursionDepth()); +> fi; +> end;; gap> SetRecursionTrapInterval(1000); +gap> dive(100); +Depth 100 gap> dive(2500); recursion depth trap (1000) at @@ -910,6 +925,8 @@ dive( depth - 1 ); called from Entering break read-eval-print loop ... you can 'quit;' to quit to outer loop, or you may 'return;' to continue +brk> GetRecursionDepth(); +0 brk> return; gap> SetRecursionTrapInterval(-1); SetRecursionTrapInterval( ): must be a non-negative smal\ @@ -918,19 +935,15 @@ not in any function Entering break read-eval-print loop ... you can 'quit;' to quit to outer loop, or you can replace via 'return ;' to continue -brk> return (); -SetRecursionTrapInterval( ): must be a non-negative smal\ -l integer -not in any function -Entering break read-eval-print loop ... -you can 'quit;' to quit to outer loop, or -you can replace via 'return ;' to continue brk> return 0; gap> dive(20000); +Depth 20000 gap> dive(2000000); Segmentation fault ]]> + + diff --git a/src/funcs.c b/src/funcs.c index a715c2c951..bd1831065a 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -1718,6 +1718,10 @@ Obj FuncSetRecursionTrapInterval( Obj self, Obj interval ) return 0; } +Obj FuncGetRecursionDepth( Obj self ) +{ + return INTOBJ_INT(STATE(RecursionDepth)); +} /**************************************************************************** ** @@ -1731,8 +1735,10 @@ Obj FuncSetRecursionTrapInterval( Obj self, Obj interval ) static StructGVarFunc GVarFuncs [] = { GVAR_FUNC(SetRecursionTrapInterval, 1, "interval"), + GVAR_FUNC(GetRecursionDepth, 0, ""), { 0, 0, 0, 0, 0 } + }; /**************************************************************************** diff --git a/src/read.h b/src/read.h index acbde6633f..e32b05de70 100644 --- a/src/read.h +++ b/src/read.h @@ -46,7 +46,9 @@ #define TRY_READ \ if (!STATE(NrError)) { \ + volatile Int recursionDepth = STATE(RecursionDepth); \ if (sySetjmp(STATE(ReadJmpError))) { \ + STATE(RecursionDepth) = recursionDepth; \ STATE(NrError)++; \ }\ }\ diff --git a/tst/testinstall/depth.tst b/tst/testinstall/depth.tst new file mode 100644 index 0000000000..4dd7829e4f --- /dev/null +++ b/tst/testinstall/depth.tst @@ -0,0 +1,32 @@ +gap> START_TEST("depth.tst"); + +# We don't know what the recursion depth will be when the test starts, +# so do relative comparisons. +gap> curdepth := GetRecursionDepth();; +gap> GetRecursionDepth() - curdepth; +0 +gap> dive := function(depth) +> if depth>1 then +> dive(depth-1); +> else +> Print("Depth ", GetRecursionDepth() - curdepth, "\n"); +> fi; +> end;; +gap> dive(10); +Depth 10 +gap> dive(80); +Depth 80 +gap> SetRecursionTrapInterval(50); +gap> dive(80); +Error, recursion depth trap (50) +gap> SetRecursionTrapInterval(5000); +gap> dive(80); +Depth 80 + +# Just want an error to occur to check the depth is reset correctly +gap> IsAbelian(2); +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `IsCommutative' on 1 arguments +gap> dive(80); +Depth 80 +gap> STOP_TEST( "depth.tst", 1);