|
20 | 20 | from collections import defaultdict |
21 | 21 | from io import StringIO |
22 | 22 | from time import time |
23 | | -from typing import Callable |
| 23 | +from typing import Callable, Optional |
24 | 24 |
|
25 | 25 | import mathics_scanner.location |
26 | 26 |
|
@@ -199,8 +199,11 @@ class TraceBuiltins(_TraceBase): |
199 | 199 | = x ^ 2 |
200 | 200 | """ |
201 | 201 |
|
202 | | - definitions_copy: Definitions |
203 | | - apply_function_copy: Callable |
| 202 | + # None if normal evaluation, the main definition object |
| 203 | + # if TraceBuiltin is activated. |
| 204 | + definitions_copy: Optional[Definitions] = None |
| 205 | + # Saves the default apply_function method. |
| 206 | + _default_apply_function: Callable = FunctionApplyRule.apply_function |
204 | 207 |
|
205 | 208 | function_stats: "defaultdict" = defaultdict( |
206 | 209 | lambda: {"count": 0, "elapsed_milliseconds": 0.0} |
@@ -245,28 +248,30 @@ def sort_by_name(tup: tuple): |
245 | 248 | key=sort_fn, |
246 | 249 | reverse=inverse, |
247 | 250 | ): |
| 251 | + # TODO: show a table through a message... |
248 | 252 | print( |
249 | 253 | "%5d %6g %s" |
250 | 254 | % (statistic["count"], int(statistic["elapsed_milliseconds"]), name) |
251 | 255 | ) |
252 | 256 |
|
253 | 257 | @staticmethod |
254 | 258 | def enable_trace(evaluation) -> None: |
255 | | - if TraceBuiltins.traced_definitions is None: |
256 | | - TraceBuiltins.apply_function_copy = FunctionApplyRule.apply_function |
257 | | - TraceBuiltins.definitions_copy = evaluation.definitions |
258 | | - |
259 | | - # Replaces apply_function by the custom one |
260 | | - FunctionApplyRule.apply_function = traced_apply_function |
261 | | - # Create new definitions uses the new apply_function |
262 | | - evaluation.definitions = Definitions(add_builtin=True) |
263 | | - else: |
264 | | - evaluation.definitions = TraceBuiltins.definitions_copy |
| 259 | + if TraceBuiltins.definitions_copy: |
| 260 | + # Trace already enabled. Do nothing. |
| 261 | + return |
| 262 | + TraceBuiltins.definitions_copy = evaluation.definitions |
| 263 | + # Replaces apply_function by the custom one |
| 264 | + FunctionApplyRule.apply_function = traced_apply_function |
| 265 | + # Create new definitions uses the new apply_function |
| 266 | + evaluation.definitions = Definitions(add_builtin=True) |
265 | 267 |
|
266 | 268 | @staticmethod |
267 | 269 | def disable_trace(evaluation) -> None: |
268 | | - FunctionApplyRule.apply_function = TraceBuiltins.apply_function_copy |
269 | | - evaluation.definitions = TraceBuiltins.definitions_copy |
| 270 | + # Disable tracebuiltin mode just if it was previously enabled: |
| 271 | + if TraceBuiltins.definitions_copy: |
| 272 | + FunctionApplyRule.apply_function = TraceBuiltins._default_apply_function |
| 273 | + evaluation.definitions = TraceBuiltins.definitions_copy |
| 274 | + TraceBuiltins.definitions_copy = None |
270 | 275 |
|
271 | 276 | def eval(self, expr, evaluation, options={}): |
272 | 277 | "%(name)s[expr_, OptionsPattern[%(name)s]]" |
@@ -334,23 +339,19 @@ class TraceBuiltinsVariable(Builtin): |
334 | 339 |
|
335 | 340 | messages = {"bool": "`1` should be True or False."} |
336 | 341 |
|
337 | | - value = SymbolFalse |
338 | | - |
339 | 342 | summary_text = "enable or disable Built-in function evaluation statistics" |
340 | 343 |
|
341 | 344 | def eval_get(self, evaluation: Evaluation): |
342 | 345 | "%(name)s" |
343 | 346 |
|
344 | | - return self.value |
| 347 | + return SymbolTrue if TraceBuiltins.definitions_copy else SymbolFalse |
345 | 348 |
|
346 | 349 | def eval_set(self, value, evaluation: Evaluation): |
347 | 350 | "%(name)s = value_" |
348 | 351 |
|
349 | 352 | if value is SymbolTrue: |
350 | | - self.value = SymbolTrue |
351 | 353 | TraceBuiltins.enable_trace(evaluation) |
352 | 354 | elif value is SymbolFalse: |
353 | | - self.value = SymbolFalse |
354 | 355 | TraceBuiltins.disable_trace(evaluation) |
355 | 356 | else: |
356 | 357 | evaluation.message("$TraceBuiltins", "bool", value) |
|
0 commit comments