(* :Title: PartialEvaluation *) (* :Author: Mark Fisher *) (* :Context: As currently implemented, the package does not set up its own Context. *) (* :Mathematica Version: 4.0 *) (* :Package Version: 1.0 September 2002 *) (* :Summary: A debugging tool. PartialEvaluation[f[args], n] evaluates the first n expressions in the "main" CompoundExpression in f[args]. (The position of the "main" CompoundExpression can be specified by an option.) An arbitrary expression can be appended as an optional third argument: PartialEvaluation[f[args], n, expr]. *) (* :Discussion: Here is the code without the error checking for PartialEvaluation[f[args], n, expr]: (* get the DownValues and "turn them off" *) dv = DownValues[f]; DownValues[f] = {}; (* find the rule that matches *) matches = Position[MatchQ[f[args], #]& /@ dv[[All, 1]], True]; match = dv[[ matches[[1, 1]] ]]; (* find the "main" CompoundExpression *) ppos = Position[match, HoldPattern[CompoundExpression[__]]]; pos = First[Sort[ppos]]; (* extract, truncate, append to, and reinsert it *) held = Extract[match, pos, Hold]; held = ReplacePart[held, Sequence, {1, 0}]; held = Take[held, n]; held = Join[held, Hold[expr]]; held = ReplacePart[Hold[Evaluate[held]], CompoundExpression, {1, 0}]; match = ReplacePart[match, held, pos, 1]; (* apply the modified rule and restore DownValues *) eval = f[args] /. match; DownValues[f] = dv; eval *) PartialEvaluation::usage = "PartialEvaluation[f[args], n] returns f[args] where only the first n expressions are evaluated in the \"main\" CompoundExpression in DownValues[f]. For example:\n\t Clear[f]\n\t f[x_] := Module[{a,b}, a=3; b=4; a b x]\n\t PartialEvaluation[f[10], 2]\n returns 4. PartialEvaluation takes an optional third argument, an expression that is appended to the truncated CompoundExpression and thus returned by f[args]. For example\n\t ParitalEvaluation[f[10], 2, {a, b, x}]\n returns {3, 4, 10}." PartialEvaluation::nomatch = "`1` does not match any of the rules in DownValues[`2`]." PartialEvaluation::noce = "There are no CompoundExpressions in ``." PartialEvaluation::badpos = "There is no CompoundExpression at the specified position." PartialEvaluation::toobig = "There are only `1` expressions in the CompoundExpression in `2`." SetAttributes[PartialEvaluation, HoldAll] Options[PartialEvaluation] = {Position -> Automatic} PartialEvaluation[f_[args__], n_Integer, expr_:Null, opts___?OptionQ] /; (!OptionQ[expr]) := Module[{dv, unprotected, result, matches, match, ppos, pos, held}, dv = DownValues[f]; unprotected = Unprotect[f]; DownValues[f] = {}; result = Catch[ (* for error checking *) matches = Position[MatchQ[f[args], #]& /@ dv[[All, 1]], True]; If[matches == {}, (* error checking *) Message[PartialEvaluation::nomatch, f[args], f]; Throw[HoldForm[f[args]]] ]; match = dv[[ matches[[1, 1]] ]]; ppos = Position[match, HoldPattern[CompoundExpression[__]]]; If[ppos == {}, (* error checking *) Message[PartialEvaluation::noce, f[args]]; Throw[HoldForm[f[args]]] ]; pos = Position /. {opts} /. Options[PartialEvaluation]; If[pos === Automatic, pos = First[Sort[ppos]]]; If[FreeQ[ppos, pos], (* error checking *) Message[PartialEvaluation::badpos]; Throw[HoldForm[f[args]]] ]; held = Extract[match, pos, Hold]; held = ReplacePart[held, Sequence, {1, 0}]; If[Abs[n] > Length[held], (* error checking *) Message[PartialEvaluation::toobig, Length[held], HoldForm[f[args]]]; Throw[HoldForm[f[args]]] ]; held = Take[held, n]; If[expr =!= Null, held = Join[held, Hold[expr]]]; held = ReplacePart[Hold[Evaluate[held]], CompoundExpression, {1, 0}]; match = ReplacePart[match, held, pos, 1]; f[args] /. match ]; (* end Catch *) DownValues[f] = dv; Protect[Evaluate[unprotected]]; result ] PossiblePositions::usage = "PossiblePositions[f] returns a list of positions of CompoundExpression[__] in DownValues[f]." PossiblePositions[f_Symbol] := Position[DownValues[f], HoldPattern[CompoundExpression[__]]]