def visit_yields(node): p = node while not null_node(p) and type(p) != FunctionNode: p = p.parent if null_node(p): typespace.error("yield keyword only valid within functions") p.is_generator = True
def visit(n): if type(n.parent) == TryNode: return sl = n.parent i = sl.children.index(n) i -= 1 #we remove n here, since we may have to ascend through #several layers of StatementList nodes sl.children.remove(n) while 1: while i >= 0: if type(sl[i]) == TryNode: break i -= 1 if i >= 0 or null_node(sl.parent): break i = sl.parent.children.index(sl) sl = sl.parent if i < 0: sys.stderr.write("%s:(%d): error: orphaned catch block\n" % (n.file, n.line)) sys.exit(-1) tn = sl[i] tn.add(n)
def visit(n): if type(n.parent) == TryNode: return sl = n.parent i = sl.children.index(n) i -= 1 # we remove n here, since we may have to ascend through # several layers of StatementList nodes sl.children.remove(n) while 1: while i >= 0: if type(sl[i]) == TryNode: break i -= 1 if i >= 0 or null_node(sl.parent): break i = sl.parent.children.index(sl) sl = sl.parent if i < 0: sys.stderr.write("%s:(%d): error: orphaned catch block\n" % (n.file, n.line)) sys.exit(-1) tn = sl[i] tn.add(n)
def visit_rets3(n2): p = n2.parent while not null_node(p) and p != f.subnode: p = p.parent if p != f.subnode and not null_node(p): return #continue corresponds to a loop internal to this frame p = f.parent while p != None: if type(p.node) in [WhileNode, DoWhileNode, ForLoopNode]: break; p = p.parent if p == None: typespace.error("Invalid continue statement") n3 = js_parse("return [$i, undefined];", [p.label], start_node=ReturnNode); n2.parent.replace(n2, n3)
def visit_rets3(n2): p = n2.parent while not null_node(p) and p != f.subnode: if type(p) in [WhileNode, DoWhileNode, ForLoopNode]: break p = p.parent if p != f.subnode and not null_node(p): return #break corresponds to a loop internal to this frame p = find_parent_frame(f, [WhileNode, DoWhileNode, ForLoopNode], True) if p == None: typespace.error("Invalid break statement (switches within generators aren't supported yet)", n2) f2 = f_next(p) n3 = js_parse("return [$i, undefined];", [f2.label], start_node=ReturnNode); n2.parent.replace(n2, n3)
def apply_frame_scope(n, scope, frames): if type(n) == IdentNode: if n.val in scope: n.val = "scope.%s_%d" % (n.val, scope[n.val]) else: p = n.parent n2 = n #check for implicit declarations within catch and loop nodes while not null_node(p): if type(p) in [CatchNode, WhileNode, ForLoopNode]: break n2 = p p = p.parent if not null_node(p) and n2 == p[0]: scope[n.val] = frames.label n.val = "scope.%s_%d" % (n.val, scope[n.val]) elif type(n) == VarDeclNode: n.local = False if "local" in n.modifiers: n.modifiers.remove("local") if hasattr(n.parent, "_c_loop_node"): frames = n.parent._c_loop_node.frame #print("yay", n.parent._c_loop_node.frame.label) if n.val not in scope: scope[n.val] = frames.label if n.val in scope: n.val = "scope.%s_%d" % (n.val, scope[n.val]) for c in n.children: #ignore expr functions, but not nested functions? if type(c) == FunctionNode and type(c.parent) == AssignNode: continue if type(n) == BinOpNode and n.op == "." and c == n[1] and type( c) == IdentNode: continue if type(n) == FuncCallNode and type(c) == IdentNode and c == n[0]: continue apply_frame_scope(c, scope, frames)
def apply_frame_scope(n, scope, frames): if type(n) == IdentNode: if n.val in scope: n.val = "scope.%s_%d" % (n.val, scope[n.val]) else: p = n.parent n2 = n #check for implicit declarations within catch and loop nodes while not null_node(p): if type(p) in [CatchNode, WhileNode, ForLoopNode]: break n2 = p p = p.parent if not null_node(p) and n2 == p[0]: scope[n.val] = frames.label n.val = "scope.%s_%d" % (n.val, scope[n.val]) elif type(n) == VarDeclNode: n.local = False; if "local" in n.modifiers: n.modifiers.remove("local") if hasattr(n.parent, "_c_loop_node"): frames = n.parent._c_loop_node.frame #print("yay", n.parent._c_loop_node.frame.label) if n.val not in scope: scope[n.val] = frames.label if n.val in scope: n.val = "scope.%s_%d" % (n.val, scope[n.val]) for c in n.children: #ignore expr functions, but not nested functions? if type(c) == FunctionNode and type(c.parent) == AssignNode: continue if type(n) == BinOpNode and n.op == "." and c == n[1] and type(c) == IdentNode: continue if type(n) == FuncCallNode and type(c) == IdentNode and c == n[0]: continue apply_frame_scope(c, scope, frames)
def is_stype(n): ret = type(n) in stypes # and (n._has_yield or n.parent._has_yield) return ret if type(n) == CatchNode: ret |= prior_try(n)._has_yield if type(n) == ElseNode: ret |= prior_if(n)._has_yield if type(n) in [IfNode, ElseNode]: p5 = n.parent while not null_node(p5): if hasattr(p5, "_has_yield") and p5._has_yield: ret = True; break p5 = p5.parent return ret
def is_stype(n): ret = type(n) in stypes # and (n._has_yield or n.parent._has_yield) return ret if type(n) == CatchNode: ret |= prior_try(n)._has_yield if type(n) == ElseNode: ret |= prior_if(n)._has_yield if type(n) in [IfNode, ElseNode]: p5 = n.parent while not null_node(p5): if hasattr(p5, "_has_yield") and p5._has_yield: ret = True break p5 = p5.parent return ret
def visit(n): if type(n.parent) == IfNode: return if n in vset: return vset.add(n) sl = n.parent i = sl.children.index(n) # i -= 1 # we remove n here, since we may have to ascend through # several layers of StatementList nodes sl.children.remove(n) # clamp i i = max(min(i, len(sl) - 1), 0) # print(len(sl), i) while 1: while i >= 0 and i < len(sl): if type(sl[i]) == IfNode: break i -= 1 if i >= 0 or null_node(sl.parent): break i = sl.parent.children.index(sl) sl = sl.parent if i < 0: sys.stderr.write("%s:(%d): error: orphaned else block\n" % (n.file, n.line)) sys.exit(-1) tn = sl[i] while len(tn) > 2: tn = tn[2][0] tn.add(n) found[0] = True
def visit(n): if type(n.parent) == IfNode: return if n in vset: return vset.add(n) sl = n.parent i = sl.children.index(n) #i -= 1 #we remove n here, since we may have to ascend through #several layers of StatementList nodes sl.children.remove(n) #clamp i i = max(min(i, len(sl) - 1), 0) #print(len(sl), i) while 1: while i >= 0 and i < len(sl): if type(sl[i]) == IfNode: break i -= 1 if i >= 0 or null_node(sl.parent): break i = sl.parent.children.index(sl) sl = sl.parent if i < 0: sys.stderr.write("%s:(%d): error: orphaned else block\n" % (n.file, n.line)) sys.exit(-1) tn = sl[i] while len(tn) > 2: tn = tn[2][0] tn.add(n) found[0] = True
def prior_try(n): if n.parent == None: return None sl = n.parent i = sl.children.index(n)-1 while 1: while i >= 0: if type(sl[i]) == TryNode: break i -= 1 if i >= 0 or null_node(n.parent): break i = sl.parent.children.index(sl); sl = sl.parent; if i < 0: typespace.error("Orphaned catch node", n) sys.exit(-1) return sl[i]
def prior_try(n): if n.parent == None: return None sl = n.parent i = sl.children.index(n) - 1 while 1: while i >= 0: if type(sl[i]) == TryNode: break i -= 1 if i >= 0 or null_node(n.parent): break i = sl.parent.children.index(sl) sl = sl.parent if i < 0: typespace.error("Orphaned catch node", n) sys.exit(-1) return sl[i]
def expand_mozilla_forloops_new(node, scope): if node.of_keyword == "in": typespace.warning("Temporary warning: detected for-in usage", node) return func = node.parent while not null_node(func) and type(func) != FunctionNode: func = func.parent if not null_node(func): if func.name in forloop_expansion_exclude: return def prop_ident_change(node, oldid, newid): if type(node) in [IdentNode, VarDeclNode] and node.val == oldid: if type(node.parent) == BinOpNode and node.parent.op == ".": if node != node.parent[1]: node.val = newid else: node.val = newid for c in node.children: if type(c) == FunctionNode: continue prop_ident_change(c, oldid, newid) # for-in-loops don't seem to behave like for-C-loops, # the iteration variable is in it's own scope, and # doesn't seem to affect the parent scope. val = node[0].val di = 0 while node[0].val in scope: node[0].val = "%s_%d" % (val, di) di += 1 # print(node[0].val) if node[0].val != val: scope[node[0].val] = node[0] prop_ident_change(node.parent, val, node[0].val) slist = node.parent.children[1] if type(slist) != StatementList: s = StatementList() s.add(slist) slist = s itername = node[0].val objname = node[1].gen_js(0) if glob.g_log_forloops: n2 = js_parse( """ var __iter_$s1 = __get_iter($s2, $s3, $s4, $s5); var $s1; while (1) { var __ival_$s1 = __iter_$s1.next(); if (__ival_$s1.done) { break; } $s1 = __ival_$s1.value; } """, (itername, objname, "'" + node[0].file + "'", node[0].line, "'" + node.of_keyword + "'"), ) else: n2 = js_parse( """ var __iter_$s1 = __get_iter($s2); var $s1; while (1) { var __ival_$s1 = __iter_$s1.next(); if (__ival_$s1.done) { break; } $s1 = __ival_$s1.value; } """, (itername, objname), ) def set_line(n, slist, line, lexpos): n.line = line n.lexpos = lexpos for c in n.children: set_line(c, slist, line, lexpos) # preserving line info is a bit tricky. # slist goes through a js->gen_js->js cycle, # so make sure we still have it (and its # line/lexpos information). set_line(n2, slist, node.line, node.lexpos) for c in slist: n2[2][1].add(c) node.parent.parent.replace(node.parent, n2)
def expand_mozilla_forloops_new(node, scope): use_in_iter = False if (node.of_keyword == "in"): use_in_iter = True typespace.warning("Temporary warning: detected for-in usage", node) if not inside_generator(node): return func = node.parent while not null_node(func) and type(func) != FunctionNode: func = func.parent if not null_node(func): if func.name in forloop_expansion_exclude: return def prop_ident_change(node, oldid, newid): if type(node) in [IdentNode, VarDeclNode] and node.val == oldid: if type(node.parent) == BinOpNode and node.parent.op == ".": if node != node.parent[1]: node.val = newid else: node.val = newid for c in node.children: if type(c) == FunctionNode: continue prop_ident_change(c, oldid, newid) #for-in-loops don't seem to behave like for-C-loops, #the iteration variable is in it's own scope, and #doesn't seem to affect the parent scope. val = node[0].val di = 0 while node[0].val in scope: node[0].val = "%s_%d" % (val, di) di += 1 #print(node[0].val) if node[0].val != val: scope[node[0].val] = node[0] prop_ident_change(node.parent, val, node[0].val) slist = node.parent.children[1] if type(slist) != StatementList: s = StatementList() s.add(slist) slist = s getiter = "__get_in_iter" if use_in_iter else "__get_iter" itername = node[0].val objname = node[1].gen_js(0) if glob.g_log_forloops: n2 = js_parse( """ var __iter_$s1 = __get_iter($s2, $s3, $s4, $s5); var $s1; while (1) { var __ival_$s1 = __iter_$s1.next(); if (__ival_$s1.done) { break; } $s1 = __ival_$s1.value; } """.replace("__get_iter", getiter), (itername, GETITER, objname, "'" + node[0].file + "'", node[0].line, "'" + node.of_keyword + "'")) else: n2 = js_parse( """ var __iter_$s1 = __get_iter($s2); var $s1; while (1) { var __ival_$s1 = __iter_$s1.next(); if (__ival_$s1.done) { break; } $s1 = __ival_$s1.value; } """.replace("__get_iter", getiter), (itername, objname)) def set_line(n, slist, line, lexpos): n.line = line n.lexpos = lexpos for c in n.children: set_line(c, slist, line, lexpos) #preserving line info is a bit tricky. #slist goes through a js->gen_js->js cycle, #so make sure we still have it (and its #line/lexpos information). set_line(n2, slist, node.line, node.lexpos) for c in slist: n2[2][1].add(c) node.parent.parent.replace(node.parent, n2)