Skip to content

Commit aecf355

Browse files
committed
merge
2 parents 125849f + 9e54dee commit aecf355

3 files changed

Lines changed: 37 additions & 12 deletions

File tree

mathics/builtin/compilation.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from mathics.builtin.base import Builtin, BoxConstruct
44
from mathics.core.expression import Atom, Expression, Symbol, String, from_python, Integer, Real
5-
5+
from mathics.core.evaluation import Evaluation
66

77
class Compile(Builtin):
88
'''
@@ -33,8 +33,7 @@ class Compile(Builtin):
3333
: Duplicate parameter x found in {{x, _Real}, {x, _Integer}}.
3434
= Compile[{{x, _Real}, {x, _Integer}}, Sin[x + y]]
3535
#> cf = Compile[{{x, _Real}, {y, _Integer}}, Sin[x + z]]
36-
: Expression Sin[x + z] could not be compiled.
37-
= Function[{Global`x, Global`y}, Sin[x + z]]
36+
= CompiledFunction[{x, y}, Sin[x + z], -CompiledCode-]
3837
#> cf = Compile[{{x, _Real}, {y, _Integer}}, Sin[x + y]]
3938
= CompiledFunction[{x, y}, Sin[x + y], -CompiledCode-]
4039
#> cf[1, 2]
@@ -50,10 +49,10 @@ class Compile(Builtin):
5049
#> cf[0, -2]
5150
= 0.5
5251
53-
Loops and variable assignments are not yet supported
52+
Loops and variable assignments are supported as python (not llvmlite)
53+
functions
5454
>> Compile[{{a, _Integer}, {b, _Integer}}, While[b != 0, {a, b} = {b, Mod[a, b]}]; a] (* GCD of a, b *)
55-
: Expression While[b != 0, {a, b} = {b, Mod[a, b]}] ; a could not be compiled.
56-
= Function[{Global`a, Global`b}, While[b != 0, {a, b} = {b, Mod[a, b]}] ; a]
55+
= CompiledFunction[{a, b}, a, -CompiledCode-]
5756
'''
5857

5958
requires = (
@@ -110,9 +109,27 @@ def apply(self, vars, expr, evaluation):
110109
try:
111110
cfunc = _compile(expr, args)
112111
except CompileError:
112+
cfunc = None
113+
114+
if cfunc is None:
115+
try:
116+
def _pythonized_mathics_expr(*x):
117+
inner_evaluation = Evaluation(definitions=evaluation.definitions)
118+
vars = dict(list(zip(names, x[:len(names)])))
119+
pyexpr = expr.replace_vars(vars)
120+
pyexpr = Expression("N", pyexpr).evaluate(inner_evaluation)
121+
res = pyexpr.to_python(n_evaluation=inner_evaluation)
122+
return res
123+
#TODO: check if we can use numba to compile this...
124+
cfunc = _pythonized_mathics_expr
125+
except Exception as e:
126+
cfunc = None
127+
128+
if cfunc is None:
113129
evaluation.message('Compile', 'comperr', expr)
114-
args = Expression("List",*names)
130+
args = Expression("List", *names)
115131
return Expression("Function", args, expr)
132+
116133
code = CompiledCode(cfunc, args)
117134
arg_names = Expression('List', *(Symbol(arg.name) for arg in args))
118135
return Expression('CompiledFunction', arg_names, expr, code)
@@ -206,5 +223,6 @@ def apply(self, argnames, expr, code, args, evaluation):
206223
try:
207224
result = code.cfunc(*py_args)
208225
except (TypeError, ctypes.ArgumentError):
209-
return evaluation.message('CompiledFunction', 'argerr', args)
226+
evaluation.message('CompiledFunction', 'argerr', args)
227+
return
210228
return from_python(result)

mathics/builtin/functional.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def apply_named(self, vars, body, args, evaluation):
8686
# print([v.get_head_name()=="System`Pattern" or v.is_symbol() for v in vars])
8787
args = args.get_sequence()
8888
if len(vars) > len(args):
89-
evaluation.message('Function', 'fpct', )
89+
evaluation.message('Function', 'fpct')
9090
else:
9191
# Allows to use both symbols or Blank patterns (z_Complex) to state the symbol.
9292
# this is not included in WL, and here does not have any impact, but it is needed for
@@ -109,7 +109,7 @@ def apply_named_attr(self, vars, body, attr, args, evaluation):
109109

110110
args = args.get_sequence()
111111
if len(vars) > len(args):
112-
evaluation.message('Function', 'fpct', )
112+
evaluation.message('Function', 'fpct')
113113
else:
114114
vars = dict(list(zip((
115115
var.get_name() for var in vars), args[:len(vars)])))

mathics/core/expression.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -984,16 +984,22 @@ def to_python(self, *args, **kwargs):
984984
Null -> None
985985
Symbol -> '...'
986986
String -> '"..."'
987+
Function -> python function
987988
numbers -> Python number
988989
If kwarg n_evaluation is given, apply N first to the expression.
989990
"""
990991
from mathics.builtin.base import mathics_to_python
991-
992992
n_evaluation = kwargs.get('n_evaluation')
993+
head_name = self._head.get_name()
993994
if n_evaluation is not None:
995+
if head_name == 'System`Function':
996+
compiled = Expression("System`Compile", *(self._leaves))
997+
compiled = compiled.evaluate(n_evaluation)
998+
if compiled.get_head_name() == "System`CompiledFunction":
999+
return compiled.leaves[2].cfunc
9941000
value = Expression('N', self).evaluate(n_evaluation)
9951001
return value.to_python()
996-
head_name = self._head.get_name()
1002+
9971003
if head_name == 'System`DirectedInfinity' and len(self._leaves) == 1:
9981004
direction = self._leaves[0].get_int_value()
9991005
if direction == 1:
@@ -1002,6 +1008,7 @@ def to_python(self, *args, **kwargs):
10021008
return -math.inf
10031009
elif head_name == 'System`List':
10041010
return [leaf.to_python(*args, **kwargs) for leaf in self._leaves]
1011+
10051012
if head_name in mathics_to_python:
10061013
py_obj = mathics_to_python[head_name]
10071014
# Start here

0 commit comments

Comments
 (0)