Skip to content

Commit 2dfaac7

Browse files
author
hartsantler
committed
testing support for "*" __mul__ operator overloading
also changed visit_Return to try to detect the return type of a function, operator overloading needs this.
1 parent 223b0bb commit 2dfaac7

3 files changed

Lines changed: 47 additions & 7 deletions

File tree

bindings/three.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ def multiply(self, other):
9090
self.set( self.x*other.x, self.y*other.y, self.z*other.z )
9191
return self
9292

93+
def __mul__(self, other):
94+
assert isinstance(other, Vector3)
95+
return Vector3( self.x*other.x, self.y*other.y, self.z*other.z )
96+
9397
def multiplyScalar(self, s):
9498
self.set( self.x*s, self.y*s, self.z*s )
9599
return self

pythonscript/python_to_pythonjs.py

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from ast import Subscript
1212
from ast import Attribute
1313
from ast import FunctionDef
14+
from ast import BinOp
1415

1516
from ast import parse
1617
from ast import NodeVisitor
@@ -76,7 +77,8 @@ def __init__(self, module=None, module_path=None):
7677
self._instances = dict() ## instance name : class name
7778
self._decorator_properties = dict()
7879
self._decorator_class_props = dict()
79-
80+
self._function_return_types = dict()
81+
self._return_type = None
8082
self._module = module
8183
self._module_path = module_path
8284
assert os.path.isdir( module_path )
@@ -87,6 +89,7 @@ def save_module(self):
8789
classes = self._classes,
8890
inline_classes = self._inline_classes,
8991
decorator_class_props = self._decorator_class_props,
92+
function_return_types = self._function_return_types,
9093
)
9194
pickle.dump( a, open(os.path.join(self._module_path, self._module+'.module'), 'wb') )
9295

@@ -102,6 +105,7 @@ def visit_ImportFrom(self, node):
102105
self._classes.update( a['classes'] )
103106
self._inline_classes.update( a['inline_classes'] )
104107
self._decorator_class_props.update( a['decorator_class_props'] )
108+
self._function_return_types.update( a['function_return_types'] )
105109

106110
def visit_Assert(self, node):
107111
## hijacking "assert isinstance(a,A)" as a type system ##
@@ -239,13 +243,27 @@ def visit_Num(self, node):
239243

240244
def visit_Return(self, node):
241245
if node.value:
242-
return writer.write('return %s' % self.visit(node.value))
243-
return writer.write('return undefined')
246+
if isinstance(node.value, Call) and isinstance(node.value.func, Name) and node.value.func.id in self._classes:
247+
self._return_type = node.value.func.id
248+
elif isinstance(node.value, Name) and node.value.id == 'self' and 'self' in self._instances:
249+
self._return_type = self._instances['self']
250+
251+
writer.write('return %s' % self.visit(node.value))
252+
253+
else:
254+
raise RuntimeError
244255

245256
def visit_BinOp(self, node):
257+
node.operator_overloading = 'undefined'
246258
left = self.visit(node.left)
247259
op = self.visit(node.op)
248260
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)
249267
return '%s %s %s' % (left, op, right)
250268

251269
def visit_Eq(self, node):
@@ -385,18 +403,25 @@ def visit_Assign(self, node):
385403
writer.write(code)
386404

387405
elif isinstance(target, Name):
406+
node_value = self.visit( node.value ) ## node.value may have extra attributes after being visited
388407

389408
if isinstance(node.value, Call) and hasattr(node.value.func, 'id') and node.value.func.id in self._classes:
390409
self._instances[ target.id ] = node.value.func.id ## keep track of instances
410+
elif isinstance(node.value, Call) and isinstance(node.value.func, Name) and node.value.func.id in self._function_return_types:
411+
self._instances[ target.id ] = self._function_return_types[ node.value.func.id ]
391412
elif target.id in self._instances:
392-
self._instances.pop( target.id )
413+
self._instances.pop( target.id ) ## TODO is this correct?
393414

394-
if isinstance(node.value, Name):
415+
if isinstance(node.value, Name): ## if this is a simple copy: "a = b" and "b" is known to be of some class
395416
name = self.visit(node.value)
396417
if name in self._instances: self._instances[ target.id ] = self._instances[ name ]
397418
writer.write('%s = %s' % (target.id, name))
398-
else:
399-
writer.write('%s = %s' % (target.id, self.visit(node.value)))
419+
elif isinstance(node.value, BinOp) and hasattr(node.value, 'operator_overloading') and node.value.operator_overloading in self._function_return_types:
420+
self._instances[ target.id ] = self._function_return_types[ node.value.operator_overloading ]
421+
writer.write('%s = %s' % (target.id, node_value))
422+
423+
else: ## blind assignment
424+
writer.write('%s = %s' % (target.id, node_value))
400425

401426
else: # it's a Tuple
402427
id = self.identifier
@@ -545,6 +570,7 @@ def visit_FunctionDef(self, node):
545570
expr = expr % (node.args.kwarg, node.args.kwarg)
546571
writer.write(expr)
547572

573+
self._return_type = None
548574
#map(self.visit, node.body)
549575
for child in node.body:
550576
# simple test to drop triple quote comments
@@ -557,6 +583,12 @@ def visit_FunctionDef(self, node):
557583
else:
558584
self.visit(child)
559585

586+
if self._return_type:
587+
#if hasattr(node, 'original_name'):
588+
# self._function_return_types[ node.original_name ] = self._return_type
589+
#else:
590+
self._function_return_types[ node.name ] = self._return_type
591+
560592
writer.pull()
561593

562594
# apply decorators

tests/threejs_vector3.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@
4141
print( v1.y )
4242
print( v1.z )
4343

44+
v = v1 * v4
45+
print( v.x )
46+
print( v.y )
47+
print( v.z )
4448

4549
</script>
4650
</head>

0 commit comments

Comments
 (0)