Skip to content

Commit b604f0f

Browse files
author
hartsantler
committed
made rule that global lists can only contain a single type.
1 parent 5d25471 commit b604f0f

2 files changed

Lines changed: 53 additions & 9 deletions

File tree

pythonjs/python_to_pythonjs.py

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ def __init__(self):
5050
self.output = StringIO()
5151
self.with_javascript = False
5252

53+
def is_at_global_level(self):
54+
return self.level == 0
55+
5356
def push(self):
5457
self.level += 1
5558

@@ -178,6 +181,11 @@ def __init__(self, module=None, module_path=None):
178181
self._with_js = False
179182
self._typedefs = dict() ## class name : typedef (not pickled)
180183

184+
self._globals = dict()
185+
self._global_typed_lists = dict() ## global name : set (if len(set)==1 then we know it is a typed list)
186+
self._global_typed_dicts = dict()
187+
self._global_typed_tuples = dict()
188+
181189
self._custom_operators = {}
182190

183191
self.setup_builtins()
@@ -296,17 +304,20 @@ def visit_Dict(self, node):
296304
return 'get_attribute(dict, "__call__")([], JSObject(js_object=%s))' %b
297305

298306
def visit_Tuple(self, node):
307+
node.returns_type = 'tuple'
299308
a = '[%s]' % ', '.join(map(self.visit, node.elts))
300309
return 'get_attribute(tuple, "__call__")([], JSObject(js_object=%s))' %a
301310

302311
def visit_List(self, node):
312+
node.returns_type = 'list'
303313
a = '[%s]' % ', '.join(map(self.visit, node.elts))
304314
if self._with_js:
305315
return a
306316
else:
307317
return 'get_attribute(list, "__call__")([], JSObject(js_object=%s))' %a
308318

309319
def visit_ListComp(self, node):
320+
node.returns_type = 'list'
310321
writer.write('var(__comprehension__)')
311322
writer.write('__comprehension__ = JSArray()')
312323

@@ -802,7 +813,22 @@ def visit_Assign(self, node):
802813
elif target.id in self._instances:
803814
self._instances.pop( target.id )
804815

805-
writer.write('%s = %s' % (target.id, node_value))
816+
if target.id in self._instances:
817+
type = self._instances[ target.id ]
818+
if writer.is_at_global_level():
819+
self._globals[ target.id ] = type
820+
if type == 'list':
821+
self._global_typed_lists[ target.id ] = set()
822+
elif type == 'tuple':
823+
self._global_typed_tuples[ target.id ] = set()
824+
elif type == 'dict':
825+
self._global_typed_dicts[ target.id ] = set()
826+
827+
writer.write('%s = %s ## global type: %s' % (target.id, node_value, type))
828+
else:
829+
writer.write('%s = %s ## type: %s' % (target.id, node_value, type))
830+
else:
831+
writer.write('%s = %s' % (target.id, node_value))
806832

807833
else: # it's a Tuple
808834
id = self.identifier
@@ -860,6 +886,19 @@ def visit_Call(self, node):
860886
args = ', '.join(args)
861887
return '%s(%s)' % (node.func.id, args)
862888
else:
889+
890+
## check if pushing to a global typed list ##
891+
if isinstance(node.func, ast.Attribute) and isinstance(node.func.value, Name) and node.func.value.id in self._globals:
892+
gtype = self._globals[ node.func.value.id ]
893+
if gtype == 'list' and node.func.attr == 'append':
894+
if isinstance(node.args[0], Name):
895+
if node.args[0].id in self._instances:
896+
gset = self._global_typed_lists[ node.func.value.id ]
897+
gset.add( self._instances[node.args[0].id])
898+
assert len(gset) == 1
899+
else:
900+
raise SyntaxError('global lists can only contain one type: instance "%s" is unknown' %node.args[0].id)
901+
863902
call_has_args_only = len(node.args) and not (len(node.keywords) or node.starargs or node.kwargs)
864903
call_has_args = len(node.args) or len(node.keywords) or node.starargs or node.kwargs
865904
name = self.visit(node.func)
@@ -1085,7 +1124,12 @@ def visit_For(self, node):
10851124
map(self.visit, node.body)
10861125
writer.pull()
10871126
else:
1088-
self._for_iterator_target = node.target.id
1127+
1128+
## TODO else remove node.target.id from self._instances
1129+
if isinstance(node.iter, Name) and node.iter.id in self._global_typed_lists:
1130+
self._instances[ node.target.id ] = list( self._global_typed_lists[ node.iter.id ] )[0]
1131+
1132+
self._for_iterator_target = node.target.id ## this could break with nested for loops
10891133
writer.write('var(__iterator__, %s)' % node.target.id)
10901134
writer.write('__iterator__ = get_attribute(get_attribute(%s, "__iter__"), "__call__")(JSArray(), JSObject())' % self.visit(node.iter))
10911135
writer.write('try:')

tests/threejs_simple_geoms.html

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,13 @@
6464
def animate():
6565
requestAnimationFrame( animate )
6666

67-
for mesh in Meshes:
68-
mesh.rotation.x = mesh.rotation.x + 0.01
69-
mesh.rotation.y = mesh.rotation.y + 0.02
70-
x = mesh.quaternion.x
71-
y = mesh.quaternion.y
72-
z = mesh.quaternion.z
73-
mesh.material.color.setRGB( x,y,z )
67+
for m in Meshes:
68+
m.rotation.x = m.rotation.x + 0.01
69+
m.rotation.y = m.rotation.y + 0.02
70+
x = m.quaternion.x
71+
y = m.quaternion.y
72+
z = m.quaternion.z
73+
m.material.color.setRGB( x,y,z )
7474

7575
ren.render( scn, cam )
7676

0 commit comments

Comments
 (0)