11from __future__ import unicode_literals
22
3+ from functools import update_wrapper
34import itertools
45import json
56import math
2324)
2425
2526
27+ def wraps_op (op ):
28+
29+ def update_and_rename_wrapper (w ):
30+ f = update_wrapper (w , op )
31+ # fn names are str in both Py 2/3
32+ f .__name__ = str ('JS_' ) + f .__name__
33+ return f
34+
35+ return update_and_rename_wrapper
36+
37+
2638def _js_bit_op (op ):
2739
2840 def zeroise (x ):
2941 return 0 if x in (None , JS_Undefined ) else x
3042
43+ @wraps_op (op )
3144 def wrapped (a , b ):
3245 return op (zeroise (a ), zeroise (b )) & 0xffffffff
3346
@@ -36,6 +49,7 @@ def wrapped(a, b):
3649
3750def _js_arith_op (op ):
3851
52+ @wraps_op (op )
3953 def wrapped (a , b ):
4054 if JS_Undefined in (a , b ):
4155 return float ('nan' )
@@ -66,6 +80,7 @@ def _js_exp(a, b):
6680
6781def _js_eq_op (op ):
6882
83+ @wraps_op (op )
6984 def wrapped (a , b ):
7085 if set ((a , b )) <= set ((None , JS_Undefined )):
7186 return op (a , a )
@@ -76,6 +91,7 @@ def wrapped(a, b):
7691
7792def _js_comp_op (op ):
7893
94+ @wraps_op (op )
7995 def wrapped (a , b ):
8096 if JS_Undefined in (a , b ):
8197 return False
@@ -356,6 +372,7 @@ def _operator(self, op, left_val, right_expr, expr, local_vars, allow_recursion)
356372 return right_val
357373
358374 try :
375+ # print('Eval:', opfunc.__name__, left_val, right_val)
359376 return opfunc (left_val , right_val )
360377 except Exception as e :
361378 raise self .Exception ('Failed to evaluate {left_val!r:.50} {op} {right_val!r:.50}' .format (** locals ()), expr , cause = e )
@@ -395,6 +412,7 @@ def interpret_statement(self, stmt, local_vars, allow_recursion=100):
395412 raise self .Exception ('Recursion limit reached' )
396413 allow_recursion -= 1
397414
415+ # print('At: ' + stmt[:60])
398416 should_return = False
399417 # fails on (eg) if (...) stmt1; else stmt2;
400418 sub_statements = list (self ._separate (stmt , ';' )) or ['' ]
@@ -702,9 +720,24 @@ def interpret_statement(self, stmt, local_vars, allow_recursion=100):
702720 continue
703721
704722 right_expr = separated .pop ()
705- while op == '-' and len (separated ) > 1 and not separated [- 1 ].strip ():
706- right_expr = '-' + right_expr
707- separated .pop ()
723+ # handle operators that are both unary and binary, minimal BODMAS
724+ if op in ('+' , '-' ):
725+ undone = 0
726+ while len (separated ) > 1 and not separated [- 1 ].strip ():
727+ undone += 1
728+ separated .pop ()
729+ if op == '-' and undone % 2 != 0 :
730+ right_expr = op + right_expr
731+ left_val = separated [- 1 ]
732+ for dm_op in ('*' , '%' , '/' , '**' ):
733+ bodmas = tuple (self ._separate (left_val , dm_op , skip_delims = skip_delim ))
734+ if len (bodmas ) > 1 and not bodmas [- 1 ].strip ():
735+ expr = op .join (separated ) + op + right_expr
736+ right_expr = None
737+ break
738+ if right_expr is None :
739+ continue
740+
708741 left_val = self .interpret_expression (op .join (separated ), local_vars , allow_recursion )
709742 return self ._operator (op , left_val , right_expr , expr , local_vars , allow_recursion ), should_return
710743
@@ -955,6 +988,7 @@ def valid_arg(y):
955988 def build_function (self , argnames , code , * global_stack ):
956989 global_stack = list (global_stack ) or [{}]
957990 argnames = tuple (argnames )
991+ # import pdb; pdb.set_trace()
958992
959993 def resf (args , kwargs = {}, allow_recursion = 100 ):
960994 global_stack [0 ].update (
0 commit comments