Skip to content

Commit

Permalink
Add WhereWithVars
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisJefferson authored and fingolfin committed Jul 16, 2019
1 parent ac5c014 commit b5373a3
Show file tree
Hide file tree
Showing 5 changed files with 269 additions and 21 deletions.
3 changes: 2 additions & 1 deletion doc/ref/debug.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ Probably the most important debugging tool in ⪆ is the break loop
an <Ref Func="Error"/> statement into your code or by hitting Control-C.
In the break loop one can inspect variables, stack traces and issue
commands as usual in an interactive &GAP; session. See also the
<Ref Func="DownEnv"/>, <Ref Func="UpEnv"/> and <Ref Func="Where"/>
<Ref Func="DownEnv"/>, <Ref Func="UpEnv"/>, <Ref Func="Where"/> and
<Ref Func="WhereWithVars"/>
functions.
<P/>
Sections&nbsp;<Ref Sect="sect:ApplicableMethod"/>
Expand Down
6 changes: 4 additions & 2 deletions doc/ref/mloop.xml
Original file line number Diff line number Diff line change
Expand Up @@ -739,14 +739,16 @@ is an example in the &GAP; code where the idea is actually used.
<P/>
<ManSection>
<Func Name="Where" Arg='nr'/>

<Func Name="WhereWithVars" Arg='nr'/>
<Description>
<Index Subkey="GAP3 name for Where">Backtrace</Index>
<Index>Stack trace</Index>
shows the last <A>nr</A> commands on the execution stack during whose execution
the error occurred. If not given, <A>nr</A> defaults to 5. (Assume, for the
following example, that after the last example <Ref Func="OnBreak"/>
has been set back to its default value.)
has been set back to its default value.). <Ref Func="WhereWithVars"/> acts the
same as <Ref Func="Where"/> while also showing the arguments and local
variables of each function.
<P/>
<Log><![CDATA[
gap> StabChain(SymmetricGroup(100)); # After this we typed ^C
Expand Down
77 changes: 69 additions & 8 deletions lib/error.g
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,60 @@ end);

ErrorLVars := fail;

BIND_GLOBAL("WHERE", function( context, depth, outercontext)
local bottom, lastcontext, f;
# In this method the line hint changes in every PrintTo are balanced, because at the moment
# PrintTo(ERROR_OUTPUT,...) resets the indentation level every time it is called.
# If/when this is fixed, the indendation in this function could be simplified
BIND_GLOBAL("PRETTY_PRINT_VARS", function(context)
local vars, i, argcount, val;
vars := ContentsLVars(context);
if not IsRecord(vars) then
return;
fi;

argcount := ABS_RAT(NumberArgumentsFunction(vars.func));
PrintTo(ERROR_OUTPUT, "\>\>\n\<\<arguments:");
if argcount = 0 then
PrintTo(ERROR_OUTPUT, " <none>");
else
for i in [1..argcount] do
if IsBound(vars.values[i]) then
val := vars.values[i];
else
val := "<unassigned>";
fi;
PrintTo(ERROR_OUTPUT, "\>\>\>\>\n", vars.names[i], " :=\>\> ", val, "\<\<\<\<\<\<");
od;
fi;

PrintTo(ERROR_OUTPUT, "\>\>\n\<\<local variables:");
if argcount = Length(vars.names) then
PrintTo(ERROR_OUTPUT, " <none>");
else
for i in [argcount+1..Length(vars.names)] do
if IsBound(vars.values[i]) then
val := vars.values[i];
else
val := "<unassigned>";
fi;
PrintTo(ERROR_OUTPUT, "\>\>\>\>\n", vars.names[i], " :=\>\> ", val, "\<\<\<\<\<\<");
od;
fi;
PrintTo(ERROR_OUTPUT,"\n");
end);

BIND_GLOBAL("WHERE", function(context, depth, outercontext, showlocals)
local bottom, lastcontext, f, args;
if depth <= 0 then
return;
fi;
bottom := GetBottomLVars();
lastcontext := outercontext;
while depth > 0 and context <> bottom do
PRINT_CURRENT_STATEMENT(ERROR_OUTPUT, context);
if showlocals then
PRETTY_PRINT_VARS(context);
fi;

PrintTo(ERROR_OUTPUT, " called from\n");
lastcontext := context;
context := ParentLVars(context);
Expand All @@ -83,22 +128,38 @@ BIND_GLOBAL("WHERE", function( context, depth, outercontext)
end);


BIND_GLOBAL("Where", function(arg)
BIND_GLOBAL("WHERE_INTERNAL", function(depth, showlocals)
if ErrorLVars = fail or ErrorLVars = GetBottomLVars() then
PrintTo(ERROR_OUTPUT, "not in any function ");
else
WHERE(ParentLVars(ErrorLVars), depth, ErrorLVars, showlocals);
fi;
PrintTo(ERROR_OUTPUT, "at ", INPUT_FILENAME(), ":", INPUT_LINENUMBER(), "\n");
end);

BIND_GLOBAL("WhereWithVars", function(arg)
local depth;
if LEN_LIST(arg) = 0 then
depth := 5;
else
depth := arg[1];
fi;

if ErrorLVars = fail or ErrorLVars = GetBottomLVars() then
PrintTo(ERROR_OUTPUT, "not in any function ");

WHERE_INTERNAL(depth, true);
end);

BIND_GLOBAL("Where", function(arg)
local depth;
if LEN_LIST(arg) = 0 then
depth := 5;
else
WHERE(ParentLVars(ErrorLVars),depth, ErrorLVars);
depth := arg[1];
fi;
PrintTo(ERROR_OUTPUT, "at ",INPUT_FILENAME(),":",INPUT_LINENUMBER(),"\n");

WHERE_INTERNAL(depth, false);
end);


OnBreak := Where;

#OnBreak := function()
Expand Down
29 changes: 29 additions & 0 deletions tst/testspecial/backtrace.g
Original file line number Diff line number Diff line change
Expand Up @@ -5,72 +5,101 @@ f := function()
end;
f();
Where();
WhereWithVars();
quit;


f:=function() if true = 1/0 then return 1; fi; return 2; end;;
f();
Where();
WhereWithVars();
quit;


f:=function() local x; if x then return 1; fi; return 2; end;;
f();
Where();
WhereWithVars();
quit;


f:=function() if 1 then return 1; fi; return 2; end;;
f();
Where();
WhereWithVars();
quit;


f:=function() if 1 < 0 then return 1; elif 1 then return 2; fi; return 3; end;;
f();
Where();
WhereWithVars();
quit;


f:=function() while 1 do return 1; od; return 2; end;;
f();
Where();
WhereWithVars();
quit;


f:=function() local i; for i in 1 do return 1; od; return 2; end;;
f();
Where();
WhereWithVars();
quit;


f:=function() local i; for i in true do return 1; od; return 2; end;;
f();
Where();
WhereWithVars();
quit;

f:=function(x) local i,j; for i in true do return 1; od; return 2; end;;
f([1,2,3]);
Where();
WhereWithVars();
quit;

f:=function(x) local i,j; Unbind(x); for i in true do return 1; od; return 2; end;;
f([1,2,3]);
Where();
WhereWithVars();
quit;

f:=function(x) local i,j; Unbind(x); j := 4; for i in true do return 1; od; return 2; end;;
f([1,2,3]);
Where();
WhereWithVars();
quit;

f:=function() local x; repeat x:=1; until 1; return 2; end;;
f();
Where();
WhereWithVars();
quit;


f:=function() local x; Assert(0, 1); return 2; end;;
f();
Where();
WhereWithVars();
quit;


f:=function() local x; Assert(0, 1, "hello"); return 2; end;;
f();
Where();
WhereWithVars();
quit;

# Verify issue #2656 is fixed
l := [[1]];; f := {} -> l[2,1];;
f();
Where();
WhereWithVars();
quit;

# verify issue #1373 is fixed
Expand Down
Loading

0 comments on commit b5373a3

Please sign in to comment.