1111from types import FunctionType
1212
1313from mathics .builtin .box .compilation import CompiledCodeBox
14- from mathics .core .atoms import Integer , String
14+ from mathics .core .atoms import Complex , Integer , Rational , Real , String
1515from mathics .core .attributes import A_HOLD_ALL , A_PROTECTED
1616from mathics .core .builtin import Builtin
1717from mathics .core .convert .expression import to_mathics_list
3333sort_order = "mathics.builtin.code-compilation"
3434
3535
36+ NAME_OF_TYPE = {
37+ bool : String ("True of False" ),
38+ int : String ("integer" ),
39+ float : String ("machine-size real number" ),
40+ complex : String ("machine-size complex number" ),
41+ }
42+
43+
3644class Compile (Builtin ):
3745 """
3846 <url>:WMA link:https://reference.wolfram.com/language/ref/Compile.html</url>
@@ -83,7 +91,6 @@ class Compile(Builtin):
8391
8492 def eval (self , vars , expr , evaluation : Evaluation ):
8593 "Compile[vars_, expr_]"
86-
8794 if not vars .has_form ("List" , None ):
8895 evaluation .message ("Compile" , "invars" )
8996 return
@@ -167,7 +174,15 @@ def to_sympy(self, *args, **kwargs):
167174 raise NotImplementedError
168175
169176 def __hash__ (self ):
170- return hash (("CompiledCode" , ctypes .addressof (self .cfunc ))) # XXX hack
177+ try :
178+ return hash (("CompiledCode" , ctypes .addressof (self .cfunc ))) # XXX hack
179+ except TypeError :
180+ return hash (
181+ (
182+ "CompiledCode" ,
183+ self .cfunc ,
184+ )
185+ ) # XXX hack
171186
172187 def atom_to_boxes (self , f , evaluation : Evaluation ):
173188 return CompiledCodeBox (String (self .__str__ ()), evaluation = evaluation )
@@ -191,30 +206,86 @@ class CompiledFunction(Builtin):
191206
192207 """
193208
194- messages = {"argerr" : "Invalid argument `1` should be Integer, Real or boolean." }
209+ messages = {
210+ "argerr" : "Invalid argument `1` should be Integer, Real, Complex or boolean." ,
211+ "cfsa" : "Argument `1` at position `2` should be a `3`." ,
212+ }
195213 summary_text = "A CompiledFunction object."
196214
197215 def eval (self , argnames , expr , code , args , evaluation : Evaluation ):
198216 "CompiledFunction[argnames_, expr_, code_CompiledCode][args__]"
199-
200217 argseq = args .get_sequence ()
201218
202219 if len (argseq ) != len (code .args ):
203220 return
204221
205222 py_args = []
206- for arg in argseq :
207- if isinstance (arg , Integer ):
208- py_args .append (arg .get_int_value ())
209- elif arg .sameQ (SymbolTrue ):
210- py_args .append (True )
211- elif arg .sameQ (SymbolFalse ):
212- py_args .append (False )
213- else :
214- py_args .append (arg .round_to_float (evaluation ))
223+ args_spec = code .args or []
224+ if len (args_spec ) != len (argseq ):
225+ evaluation .mesage (
226+ "CompiledFunction" ,
227+ "cfct" ,
228+ Integer (len (argseq )),
229+ Integer (len (args_spec )),
230+ )
231+ return
232+ for pos , (arg , spec ) in enumerate (zip (argseq , args_spec )):
233+ # TODO: check if the types are consistent.
234+ # If not, show a message.
235+ try :
236+ spec_type = spec .type
237+ if spec_type is float :
238+ if isinstance (arg , (Integer , Rational , Real )):
239+ val = spec_type (arg .value )
240+ else :
241+ raise TypeError
242+ elif spec_type is int :
243+ if isinstance (arg , (Integer , Rational , Real )):
244+ val = spec_type (arg .value )
245+ # If arg.value was not an integer, show a message but accept it:
246+ if val != arg .value :
247+ evaluation .message (
248+ "CompiledFunction" ,
249+ "cfsa" ,
250+ arg ,
251+ Integer (pos + 1 ),
252+ NAME_OF_TYPE [spec_type ],
253+ )
254+ else :
255+ raise TypeError
256+ elif spec_type is bool :
257+ if arg .sameQ (SymbolTrue ):
258+ val = True
259+ elif arg .sameQ (SymbolFalse ):
260+ val = False
261+ else :
262+ raise TypeError
263+ elif spec_type is complex :
264+ if isinstance (arg , Complex ):
265+ value = arg .value
266+ val = complex (value [0 ].value , value [1 ].value )
267+ elif isinstance (arg , (Integer , Rational , Real )):
268+ val = complex (arg .value )
269+ else :
270+ raise TypeError
271+ else :
272+ raise TypeError
273+ except (ValueError , TypeError ):
274+ # Fallback by replace values in expr?
275+ evaluation .message (
276+ "CompiledFunction" ,
277+ "cfsa" ,
278+ arg ,
279+ Integer (pos + 1 ),
280+ NAME_OF_TYPE [spec .type ],
281+ )
282+ return
283+ py_args .append (val )
215284 try :
216285 result = code .cfunc (* py_args )
217286 except (TypeError , ctypes .ArgumentError ):
218287 evaluation .message ("CompiledFunction" , "argerr" , args )
219288 return
289+ except Exception :
290+ return
220291 return from_python (result )
0 commit comments