Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 85 additions & 14 deletions mathics/builtin/compilation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from types import FunctionType

from mathics.builtin.box.compilation import CompiledCodeBox
from mathics.core.atoms import Integer, String
from mathics.core.atoms import Complex, Integer, Rational, Real, String
from mathics.core.attributes import A_HOLD_ALL, A_PROTECTED
from mathics.core.builtin import Builtin
from mathics.core.convert.expression import to_mathics_list
Expand All @@ -33,6 +33,14 @@
sort_order = "mathics.builtin.code-compilation"


NAME_OF_TYPE = {
bool: String("True of False"),
int: String("integer"),
float: String("machine-size real number"),
complex: String("machine-size complex number"),
}


class Compile(Builtin):
"""
<url>:WMA link:https://reference.wolfram.com/language/ref/Compile.html</url>
Expand Down Expand Up @@ -83,7 +91,6 @@ class Compile(Builtin):

def eval(self, vars, expr, evaluation: Evaluation):
"Compile[vars_, expr_]"

if not vars.has_form("List", None):
evaluation.message("Compile", "invars")
return
Expand Down Expand Up @@ -167,7 +174,15 @@ def to_sympy(self, *args, **kwargs):
raise NotImplementedError

def __hash__(self):
return hash(("CompiledCode", ctypes.addressof(self.cfunc))) # XXX hack
try:
return hash(("CompiledCode", ctypes.addressof(self.cfunc))) # XXX hack
except TypeError:
return hash(
(
"CompiledCode",
self.cfunc,
)
) # XXX hack

def atom_to_boxes(self, f, evaluation: Evaluation):
return CompiledCodeBox(String(self.__str__()), evaluation=evaluation)
Expand All @@ -191,30 +206,86 @@ class CompiledFunction(Builtin):

"""

messages = {"argerr": "Invalid argument `1` should be Integer, Real or boolean."}
messages = {
"argerr": "Invalid argument `1` should be Integer, Real, Complex or boolean.",
"cfsa": "Argument `1` at position `2` should be a `3`.",
}
summary_text = "A CompiledFunction object."

def eval(self, argnames, expr, code, args, evaluation: Evaluation):
"CompiledFunction[argnames_, expr_, code_CompiledCode][args__]"

argseq = args.get_sequence()

if len(argseq) != len(code.args):
return

py_args = []
for arg in argseq:
if isinstance(arg, Integer):
py_args.append(arg.get_int_value())
elif arg.sameQ(SymbolTrue):
py_args.append(True)
elif arg.sameQ(SymbolFalse):
py_args.append(False)
else:
py_args.append(arg.round_to_float(evaluation))
args_spec = code.args or []
if len(args_spec) != len(argseq):
evaluation.mesage(
"CompiledFunction",
"cfct",
Integer(len(argseq)),
Integer(len(args_spec)),
)
return
for pos, (arg, spec) in enumerate(zip(argseq, args_spec)):
# TODO: check if the types are consistent.
# If not, show a message.
try:
spec_type = spec.type
if spec_type is float:
if isinstance(arg, (Integer, Rational, Real)):
val = spec_type(arg.value)
else:
raise TypeError
elif spec_type is int:
if isinstance(arg, (Integer, Rational, Real)):
val = spec_type(arg.value)
# If arg.value was not an integer, show a message but accept it:
if val != arg.value:
evaluation.message(
"CompiledFunction",
"cfsa",
arg,
Integer(pos + 1),
NAME_OF_TYPE[spec_type],
)
else:
raise TypeError
elif spec_type is bool:
if arg.sameQ(SymbolTrue):
val = True
elif arg.sameQ(SymbolFalse):
val = False
else:
raise TypeError
elif spec_type is complex:
if isinstance(arg, Complex):
value = arg.value
val = complex(value[0].value, value[1].value)
elif isinstance(arg, (Integer, Rational, Real)):
val = complex(arg.value)
else:
raise TypeError
else:
raise TypeError
except (ValueError, TypeError):
# Fallback by replace values in expr?
evaluation.message(
"CompiledFunction",
"cfsa",
arg,
Integer(pos + 1),
NAME_OF_TYPE[spec.type],
)
return
py_args.append(val)
try:
result = code.cfunc(*py_args)
except (TypeError, ctypes.ArgumentError):
evaluation.message("CompiledFunction", "argerr", args)
return
except Exception:
return
return from_python(result)
3 changes: 3 additions & 0 deletions mathics/compile/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ class CompileArg:
def __init__(self, name, type):
self.name = name
self.type = type

def __repr__(self):
return f"{self.name}:{self.type}"
2 changes: 1 addition & 1 deletion mathics/core/atoms.py
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ def element_order(self) -> tuple:
of an expression. The tuple is ultimately compared lexicographically.
"""

value = self._value
value: sympy.Float = self._value
value, prec = float(value), value._prec
# For large values, use the sympy.Float value...
if math.isinf(value):
Expand Down
Loading
Loading