Skip to content

Commit

Permalink
Fixing time constrained more (#1165)
Browse files Browse the repository at this point in the history
  • Loading branch information
rocky authored Nov 12, 2024
1 parent 0f99352 commit 0010488
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 55 deletions.
44 changes: 2 additions & 42 deletions mathics/builtin/datentime.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@
)
from mathics.core.expression import Expression
from mathics.core.list import ListExpression
from mathics.core.symbols import Symbol, SymbolNull
from mathics.core.symbols import Symbol
from mathics.core.systemsymbols import (
SymbolAborted,
SymbolAbsoluteTime,
SymbolAutomatic,
SymbolInfinity,
SymbolRowBox,
Expand Down Expand Up @@ -109,11 +110,9 @@ def total_seconds(td):
else:
total_seconds = timedelta.total_seconds

SymbolAbsoluteTime = Symbol("AbsoluteTime")
SymbolDateObject = Symbol("DateObject")
SymbolDateString = Symbol("DateString")
SymbolGregorian = Symbol("Gregorian")
SymbolPause = Symbol("Pause")


class _Date:
Expand Down Expand Up @@ -1026,45 +1025,6 @@ def eval(self, year, evaluation):
return ListExpression(year, Integer(month), Integer(day))


class Pause(Builtin):
"""
<url>:WMA link:https://reference.wolfram.com/language/ref/Pause.html</url>
<dl>
<dt>'Pause[n]'
<dd>pauses for $n$ seconds.
</dl>
>> Pause[0.5]
"""

messages = {
"numnm": (
"Non-negative machine-sized number expected at " "position 1 in `1`."
),
}

summary_text = "pause for a number of seconds"

def eval(self, n, evaluation):
"Pause[n_]"
sleeptime = n.to_python()
if not isinstance(sleeptime, (int, float)) or sleeptime < 0:
evaluation.message(
"Pause", "numnm", Expression(SymbolPause, from_python(n))
)
return

steps = int(1000 * sleeptime)
while steps > 0:
time.sleep(0.001)
if evaluation.timeout:
return SymbolNull
steps = steps - 1

return SymbolNull


class SystemTimeZone(Predefined):
"""
<url>
Expand Down
46 changes: 45 additions & 1 deletion mathics/builtin/procedural.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
environment.
"""

import time

from mathics.core.attributes import (
A_HOLD_ALL,
Expand All @@ -24,6 +25,7 @@
A_READ_PROTECTED,
)
from mathics.core.builtin import BinaryOperator, Builtin, IterationFunction
from mathics.core.convert.python import from_python
from mathics.core.evaluation import Evaluation
from mathics.core.expression import Expression
from mathics.core.interrupt import (
Expand All @@ -34,7 +36,7 @@
WLThrowInterrupt,
)
from mathics.core.symbols import Symbol, SymbolFalse, SymbolNull, SymbolTrue
from mathics.core.systemsymbols import SymbolMatchQ
from mathics.core.systemsymbols import SymbolMatchQ, SymbolPause
from mathics.eval.patterns import match

SymbolWhich = Symbol("Which")
Expand Down Expand Up @@ -438,6 +440,48 @@ def eval(self, evaluation: Evaluation):
raise AbortInterrupt


class Pause(Builtin):
"""
<url>:WMA link:https://reference.wolfram.com/language/ref/Pause.html</url>
<dl>
<dt>'Pause[n]'
<dd>pauses for at least $n$ seconds.
</dl>
>> Pause[0.5]
"""

messages = {
"numnm": (
"Non-negative machine-sized number expected at " "position 1 in `1`."
),
}

summary_text = "pause for a number of seconds"

# Number of timeout polls per second that we perform in looking
# for a timeout.
PAUSE_TICKS_PER_SECOND = 1000

def eval(self, n, evaluation: Evaluation):
"Pause[n_]"
sleeptime = n.to_python()
if not isinstance(sleeptime, (int, float)) or sleeptime < 0:
evaluation.message(
"Pause", "numnm", Expression(SymbolPause, from_python(n))
)
return

steps = int(self.PAUSE_TICKS_PER_SECOND * sleeptime)
for _ in range(steps):
time.sleep(1 / self.PAUSE_TICKS_PER_SECOND)
if evaluation.timeout:
return SymbolNull

return SymbolNull


class Return(Builtin):
"""
<url>:WMA link:
Expand Down
2 changes: 1 addition & 1 deletion mathics/core/evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def run_with_timeout_and_stack(request, timeout, evaluation):
if success:
return result
else:
raise result[1].with_traceback(result[1], result[2])
raise result[1].with_traceback(result[2])


class _Out(KeyComparable):
Expand Down
1 change: 1 addition & 0 deletions mathics/core/systemsymbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@
SymbolPath = Symbol("System`$Path")
SymbolPattern = Symbol("System`Pattern")
SymbolPatternTest = Symbol("System`PatternTest")
SymbolPause = Symbol("System`Pause")
SymbolPi = Symbol("System`Pi")
SymbolPiecewise = Symbol("System`Piecewise")
SymbolPlot = Symbol("System`Plot")
Expand Down
33 changes: 22 additions & 11 deletions mathics/eval/sympy.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
"""
Evaluation of sympy functions
Evaluation of SymPy functions
"""

import sys
from queue import Queue
from threading import Thread
from typing import Optional

import sympy

import mathics.eval.tracing as tracing
from mathics.core.convert.sympy import from_sympy, to_numeric_sympy_args
from mathics.core.element import BaseElement
from mathics.core.evaluation import Evaluation


def eval_sympy_unconstrained(self, z, evaluation):
def eval_sympy_unconstrained(
self, z: BaseElement, evaluation: Evaluation
) -> Optional[BaseElement]:
"""
Evaluate an expression converting it to Sympy
and back to Mathics.
Evaluate element `z` converting it to SymPy and back to Mathics3.
If an exception is raised we return None.
This version is called not-wrapped in a thread on systems like
emscripten that do not support Python-style threading.
"""
sympy_args = to_numeric_sympy_args(z, evaluation)
if self.sympy_name is None:
Expand All @@ -27,13 +35,15 @@ def eval_sympy_unconstrained(self, z, evaluation):
return


def eval_sympy_with_timeout(self, z, evaluation):
def eval_sympy_with_timeout(
self, z: BaseElement, evaluation: Evaluation
) -> Optional[BaseElement]:
"""
Evaluate an expression converting it to Sympy,
and back to Mathics.
This version put the evaluation in a thread,
and check each some time if the evaluation
reached a timeout.
Evaluate an element `z` converting it to SymPy,
and back to Mathics3.
If an exception is raised we return None.
This version is run in a thread, and checked for evaluation timeout.
"""

if evaluation.timeout is None:
Expand Down Expand Up @@ -66,9 +76,10 @@ def evaluate():
if success:
return result
else:
raise result[0].with_traceback(result[1], result[2])
raise result[1].with_traceback(result[2])


# Common top-level evaluation SymPy "eval" function:
eval_sympy = (
eval_sympy_unconstrained
if sys.platform in ("emscripten",)
Expand Down

0 comments on commit 0010488

Please sign in to comment.