forked from gython/Gython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinline_function.py
More file actions
88 lines (71 loc) · 2.19 KB
/
inline_function.py
File metadata and controls
88 lines (71 loc) · 2.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# AST Function Inliner
# by Brett Hartshorn - copyright 2013
# License: "New BSD"
import ast, copy
from ast_utils import *
class Inliner:
def setup_inliner(self, writer):
self.writer = writer
self._with_inline = False
self._inline = []
self._inline_ids = 0
self._inline_breakout = False
def inline_helper_remap_names(self, remap):
return "JS('var %s')" %','.join(remap.values())
def inline_helper_return_id(self, return_id):
return "JS('var __returns__%s = null')"%return_id
def inline_function(self, node):
name = self.visit(node.func)
fnode = self._global_functions[ name ]
fnode = copy.deepcopy( fnode )
finfo = inspect_function( fnode )
remap = {}
for n in finfo['name_nodes']:
if n.id not in finfo['locals']: continue
if isinstance(n.id, ast.Name):
raise RuntimeError
if n.id not in remap:
new_name = n.id + '_%s'%self._inline_ids
remap[ n.id ] = new_name
self._inline_ids += 1
n.id = remap[ n.id ]
if remap:
self.writer.write( self.inline_helper_remap_names(remap) )
for n in remap:
if n in finfo['typedefs']:
self._func_typedefs[ remap[n] ] = finfo['typedefs'][n]
offset = len(fnode.args.args) - len(fnode.args.defaults)
for i,ad in enumerate(fnode.args.args):
if i < len(node.args):
ac = self.visit( node.args[i] )
else:
assert fnode.args.defaults
dindex = i - offset
ac = self.visit( fnode.args.defaults[dindex] )
ad = remap[ self.visit(ad) ]
self.writer.write( "%s = %s" %(ad, ac) )
return_id = name + str(self._inline_ids)
self._inline.append( return_id )
self.writer.write( self.inline_helper_return_id( return_id ))
#if len( finfo['return_nodes'] ) > 1: ## TODO fix me
if True:
self._inline_breakout = True
self.writer.write('while True:')
self.writer.push()
for b in fnode.body:
self.visit(b)
if not len( finfo['return_nodes'] ):
self.writer.write('break')
self.writer.pull()
#self._inline_breakout = False
else:
for b in fnode.body:
self.visit(b)
if self._inline.pop() != return_id:
raise RuntimeError
for n in remap:
gname = remap[n]
for n in finfo['name_nodes']:
if n.id == gname:
n.id = n
return '__returns__%s' %return_id