11import ctypes
22
33from mathics .builtin .base import Builtin , BoxConstruct
4+ from mathics .core .evaluation import Evaluation
45from mathics .core .expression import (
56 Atom ,
67 Expression ,
@@ -41,8 +42,7 @@ class Compile(Builtin):
4142 : Duplicate parameter x found in {{x, _Real}, {x, _Integer}}.
4243 = Compile[{{x, _Real}, {x, _Integer}}, Sin[x + y]]
4344 #> cf = Compile[{{x, _Real}, {y, _Integer}}, Sin[x + z]]
44- : Expression Sin[x + z] could not be compiled.
45- = Function[{Global`x, Global`y}, Sin[x + z]]
45+ = CompiledFunction[{x, y}, Sin[x + z], -CompiledCode-]
4646 #> cf = Compile[{{x, _Real}, {y, _Integer}}, Sin[x + y]]
4747 = CompiledFunction[{x, y}, Sin[x + y], -CompiledCode-]
4848 #> cf[1, 2]
@@ -58,10 +58,10 @@ class Compile(Builtin):
5858 #> cf[0, -2]
5959 = 0.5
6060
61- Loops and variable assignments are not yet supported
61+ Loops and variable assignments are supported as python (not llvmlite)
62+ functions
6263 >> Compile[{{a, _Integer}, {b, _Integer}}, While[b != 0, {a, b} = {b, Mod[a, b]}]; a] (* GCD of a, b *)
63- : Expression While[b != 0, {a, b} = {b, Mod[a, b]}] ; a could not be compiled.
64- = Function[{Global`a, Global`b}, While[b != 0, {a, b} = {b, Mod[a, b]}] ; a]
64+ = CompiledFunction[{a, b}, a, -CompiledCode-]
6565 """
6666
6767 requires = ("llvmlite" ,)
@@ -123,9 +123,29 @@ def apply(self, vars, expr, evaluation):
123123 try :
124124 cfunc = _compile (expr , args )
125125 except CompileError :
126+ cfunc = None
127+
128+ if cfunc is None :
129+ try :
130+
131+ def _pythonized_mathics_expr (* x ):
132+ inner_evaluation = Evaluation (definitions = evaluation .definitions )
133+ vars = dict (list (zip (names , x [: len (names )])))
134+ pyexpr = expr .replace_vars (vars )
135+ pyexpr = Expression ("N" , pyexpr ).evaluate (inner_evaluation )
136+ res = pyexpr .to_python (n_evaluation = inner_evaluation )
137+ return res
138+
139+ # TODO: check if we can use numba to compile this...
140+ cfunc = _pythonized_mathics_expr
141+ except Exception as e :
142+ cfunc = None
143+
144+ if cfunc is None :
126145 evaluation .message ("Compile" , "comperr" , expr )
127146 args = Expression ("List" , * names )
128147 return Expression ("Function" , args , expr )
148+
129149 code = CompiledCode (cfunc , args )
130150 arg_names = Expression ("List" , * (Symbol (arg .name ) for arg in args ))
131151 return Expression ("CompiledFunction" , arg_names , expr , code )
0 commit comments