Skip to content

Commit 19872d3

Browse files
author
hartsantler
committed
more operator overloading support, and inplace overloading operators: +=, -=, *=
1 parent 2dfaac7 commit 19872d3

3 files changed

Lines changed: 85 additions & 12 deletions

File tree

bindings/three.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ def add(self, other):
6464
self.set( self.x+other.x, self.y+other.y, self.z+other.z )
6565
return self
6666

67-
#def __iadd__(self, other):
67+
def __add__(self, other):
68+
assert isinstance(other, Vector3)
69+
return Vector3( self.x+other.x, self.y+other.y, self.z+other.z )
6870

6971
def addScalar(self, s):
7072
self.set( self.x+s, self.y+s, self.z+s )
@@ -80,6 +82,10 @@ def sub(self, other):
8082
self.set( self.x-other.x, self.y-other.y, self.z-other.z )
8183
return self
8284

85+
def __sub__(self, other):
86+
assert isinstance(other, Vector3)
87+
return Vector3( self.x-other.x, self.y-other.y, self.z-other.z )
88+
8389
def subVectors(self, a,b):
8490
var( a=Vector3, b=Vector3 )
8591
self.set( a.x-b.x, a.y-b.y, a.z-b.z )
@@ -94,6 +100,9 @@ def __mul__(self, other):
94100
assert isinstance(other, Vector3)
95101
return Vector3( self.x*other.x, self.y*other.y, self.z*other.z )
96102

103+
def __imul__(self, s):
104+
self.multiplyScalar(s)
105+
97106
def multiplyScalar(self, s):
98107
self.set( self.x*s, self.y*s, self.z*s )
99108
return self

pythonscript/python_to_pythonjs.py

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
6794
class 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):

tests/threejs_vector3.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@
4646
print( v.y )
4747
print( v.z )
4848

49+
w = v1 + v4
50+
print( w.x )
51+
print( w.y )
52+
print( w.z )
53+
54+
w *= 10.0
55+
print( w.x )
56+
print( w.y )
57+
print( w.z )
58+
4959
</script>
5060
</head>
5161

0 commit comments

Comments
 (0)