@@ -64,6 +64,33 @@ def getvalue(self):
6464 'random' : 'var random = Math.random'
6565 }
6666}
67+
68+ class Typedef (object ):
69+ # http://docs.python.org/2/reference/datamodel.html#emulating-numeric-types
70+ _opmap = dict (
71+ __add__ = '+' ,
72+ __iadd__ = '+=' ,
73+ __sub__ = '-' ,
74+ __isub__ = '-=' ,
75+ __mul__ = '*' ,
76+ __imul__ = '*=' ,
77+ )
78+
79+ def __init__ (self , ** kwargs ):
80+ for name in kwargs .keys ():
81+ setattr ( self , name , kwargs [name ] )
82+
83+ self .operators = dict ()
84+ for name in self .methods :
85+ if name in self ._opmap :
86+ op = self ._opmap [ name ]
87+ self .operators [ op ] = self .get_pythonjs_function_name ( name )
88+
89+ def get_pythonjs_function_name (self , name ):
90+ assert name in self .methods
91+ return '__%s_%s' % (self .name , name ) ## class name
92+
93+
6794class PythonToPythonJS (NodeVisitor ):
6895
6996 identifier = 0
@@ -73,15 +100,26 @@ def __init__(self, module=None, module_path=None):
73100 self ._classes = dict () ## class name : [method names]
74101 self ._inline_classes = dict () ## class name : [attribute names]
75102 self ._catch_attributes = None
76- self ._names = set ()
103+ self ._names = set () ## not used?
77104 self ._instances = dict () ## instance name : class name
78105 self ._decorator_properties = dict ()
79106 self ._decorator_class_props = dict ()
80107 self ._function_return_types = dict ()
81108 self ._return_type = None
82109 self ._module = module
83110 self ._module_path = module_path
84- assert os .path .isdir ( module_path )
111+
112+ def get_typedef (self , node ):
113+ assert isinstance (node , Name )
114+ if node .id in self ._instances :
115+ klass = self ._instances [ node .id ]
116+ typedef = Typedef (
117+ name = klass ,
118+ methods = self ._classes [ klass ],
119+ properties = self ._decorator_class_props [ klass ],
120+ #compiler = self,
121+ )
122+ return typedef
85123
86124 def save_module (self ):
87125 if self ._module and self ._module_path :
@@ -125,8 +163,18 @@ def visit_In(self, node):
125163 return ' in '
126164
127165 def visit_AugAssign (self , node ):
128- a = '%s %s= %s' % (self .visit (node .target ), self .visit (node .op ), self .visit (node .value ))
129- writer .write (a )
166+ target = self .visit ( node .target )
167+ op = '%s=' % self .visit ( node .op )
168+
169+ typedef = self .get_typedef ( node .target )
170+ if typedef and op in typedef .operators :
171+ func = typedef .operators [ op ]
172+ a = '%s( [%s, %s] )' % (func , target , self .visit (node .value ))
173+ writer .write ( a )
174+ else :
175+ ## TODO extra checks to make sure the operator type is valid in this context
176+ a = '%s %s= %s' % (target , op , self .visit (node .value ))
177+ writer .write (a )
130178
131179 def visit_Yield (self , node ):
132180 return 'yield %s' % self .visit (node .value )
@@ -254,16 +302,22 @@ def visit_Return(self, node):
254302 raise RuntimeError
255303
256304 def visit_BinOp (self , node ):
257- node .operator_overloading = 'undefined'
258305 left = self .visit (node .left )
259306 op = self .visit (node .op )
260307 right = self .visit (node .right )
261- if isinstance (node .left , Name ) and node .left .id in self ._instances :
262- klass = self ._instances [ node .left .id ]
263- if op == '*' and '__mul__' in self ._classes [klass ]:
264- node .operator_overloading = '__%s___mul__' % klass
265- assert node .operator_overloading
266- return '''JS('__%s___mul__( [%s, %s] )')''' % (klass , left , right )
308+ #if isinstance(node.left, Name) and node.left.id in self._instances:
309+ # klass = self._instances[ node.left.id ]
310+ # if op == '*' and '__mul__' in self._classes[klass]:
311+ # node.operator_overloading = '__%s___mul__' %klass
312+ # assert node.operator_overloading
313+ # return '''JS('__%s___mul__( [%s, %s] )')''' %(klass, left, right)
314+ if isinstance (node .left , Name ):
315+ typedef = self .get_typedef ( node .left )
316+ if typedef and op in typedef .operators :
317+ func = typedef .operators [ op ]
318+ node .operator_overloading = func
319+ return '''JS('%s( [%s, %s] )')''' % (func , left , right )
320+
267321 return '%s %s %s' % (left , op , right )
268322
269323 def visit_Eq (self , node ):
0 commit comments