lshifr
3/26/2015 - 6:37 PM

Simple debugging utility for Mathematica programs

Simple debugging utility for Mathematica programs

ClearAll[openerDress];
SetAttributes[openerDress, HoldAll];
openerDress[f_[args___]]:=
  OpenerView[{
    HoldForm[f],
    HoldForm[f]@@Map[openerDress,Unevaluated[{args}]]
  }];
openerDress[x_]:=HoldForm[x];

ClearAll[stackPrettify];
stackPrettify[stack : {__HoldForm}] :=
  Column @ {
    Replace[stack, HoldForm[f_[x___]] :> openerDress[f[x]], 1],
    Style[Map[Short, Last[stack], {2}], Red]
  };
stackPrettify[___] := Null;

ClearAll[withRedefined];
withRedefined[f_Symbol, extraCondition_, beforeF_, afterF_]:=
  Function[
    code
    ,
    Internal`InheritedBlock[{f},
      Module[{inF, dv = DownValues[f]},
        Unprotect[f];
        DownValues[f]={};
        (call:f[args___]) /; extraCondition[args] && !TrueQ[inF]:=
          Block[{inF = True},
            beforeF[args];
            call;
            afterF[args]
          ];
        DownValues[f] = Join[DownValues[f],dv];
        Protect[f];
      ];
      code
    ]
    ,
    HoldAll
  ];
  
ClearAll[printStack];
printStack[start_, end_]:=Print[stackPrettify[Take[Stack[_], {start, end}]]];

ClearAll[heldF];
SetAttributes[heldF,  HoldAll];
heldF[body_]:=Function[Null, body, HoldAll];

ClearAll[debug];                        
debug[debugSymbol_Symbol:Message, failConditionFunction_:heldF[True]]:=
  Function[
    code
    ,
    Module[{tag},
      withRedefined[
        debugSymbol,
        heldF[!MatchQ[First[Hold[##]],_$Off]],
            heldF[If[failConditionFunction[##],printStack[6, -9]]],
            heldF[If[failConditionFunction[##], Throw[$Failed,tag]]]
      ][Catch[StackComplete[code],tag]]
    ]
    ,
    HoldAll
  ];