@@ -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:' )
0 commit comments