Skip to content

Commit 620049d

Browse files
authored
Adjust trace API to be able to set expr values (#1411)
When tracing an evaluation, allow the wrapper function to replace or alter the function retutn value. This is used in the Trepan DebugEvaluate debugger, but it can be used by other tracing tools as well.
1 parent 0c1e8c1 commit 620049d

2 files changed

Lines changed: 27 additions & 9 deletions

File tree

mathics/eval/tracing.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,11 @@ def trace_evaluate(func: Callable) -> Callable:
114114
def wrapper(expr, evaluation) -> Any:
115115
from mathics.core.symbols import SymbolConstant
116116

117-
skip_call = False
117+
# trace_evaluate_action allows for trace_evaluate_on_call()
118+
# and trace_evaluate_return() to set the value of the
119+
# expression instead of calling the function or replacing
120+
# of return value of a Mathics3 function call.
121+
trace_evaluate_action: Optional[Any] = None
118122
result = None
119123
was_boxing = evaluation.is_boxing
120124
if (
@@ -125,19 +129,33 @@ def wrapper(expr, evaluation) -> Any:
125129
# We may use boxing in print_evaluate_fn(). So turn off
126130
# boxing temporarily.
127131
evaluation.is_boxing = True
128-
skip_call = trace_evaluate_on_call(expr, evaluation, "Evaluating", func)
132+
trace_evaluate_action = trace_evaluate_on_call(
133+
expr, evaluation, "Evaluating", func
134+
)
129135
evaluation.is_boxing = was_boxing
130-
if not skip_call:
136+
if trace_evaluate_action is None:
131137
result = func(expr, evaluation)
132138
if trace_evaluate_on_return is not None and not was_boxing:
133-
trace_evaluate_on_return(
139+
trace_evaluate_action = trace_evaluate_on_return(
134140
expr=result,
135141
evaluation=evaluation,
136142
status="Returning",
137143
fn=expr,
138144
orig_expr=expr,
139145
)
146+
if trace_evaluate_action is not None:
147+
result = (
148+
(trace_evaluate_action, False)
149+
if func.__name__ == "rewrite_apply_eval_step"
150+
else trace_evaluate_action
151+
)
140152
evaluation.is_boxing = was_boxing
153+
else:
154+
result = (
155+
(trace_evaluate_action, False)
156+
if func.__name__ == "rewrite_apply_eval_step"
157+
else trace_evaluate_action
158+
)
141159
return result
142160

143161
return wrapper

test/builtin/test_trace.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"""
55
from inspect import isfunction, ismethod
66
from test.helper import evaluate, session
7-
from typing import Any, Callable
7+
from typing import Any, Callable, Optional
88

99
import pytest
1010

@@ -26,7 +26,7 @@ def test_TraceEvaluation():
2626

2727
def counting_print_evaluate(
2828
expr, evaluation: Evaluation, status: str, fn: Callable, orig_expr=None
29-
) -> bool:
29+
) -> Optional[Any]:
3030
"""
3131
A replacement for mathics.eval.tracing.print_evaluate() that counts the
3232
number of evaluation calls.
@@ -36,7 +36,7 @@ def counting_print_evaluate(
3636
assert status in ("Evaluating", "Returning")
3737
if "cython" not in version_info:
3838
assert isfunction(fn), "Expecting 4th argument to be a function"
39-
return False
39+
return None
4040

4141
try:
4242
# Set a small recursion limit,
@@ -83,7 +83,7 @@ def empty_queue():
8383
global event_queue
8484
event_queue = []
8585

86-
def call_event_func(event: TraceEvent, fn: Callable, *args) -> bool:
86+
def call_event_func(event: TraceEvent, fn: Callable, *args) -> Optional[Any]:
8787
"""
8888
Capture filtered calls in event_queue.
8989
"""
@@ -92,7 +92,7 @@ def call_event_func(event: TraceEvent, fn: Callable, *args) -> bool:
9292
else:
9393
name = str(fn)
9494
event_queue.append(f"{event.name} call : {name}{args[:3]}")
95-
return False
95+
return None
9696

9797
def return_event_func(event: TraceEvent, result: Any) -> Any:
9898
"""

0 commit comments

Comments
 (0)