-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlet.py
85 lines (81 loc) · 3.18 KB
/
let.py
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
#coding=utf-8
import dis
import opcode
from types import CodeType
from types import FunctionType
# co_varnames ( first argument , other local name
# co_nlocals ( length co_varnames
def showCodeInfo(co):
print( " --------start------- ")
for i in dir(co):
if i.startswith('co'):
t = getattr(co,i)
print( ' ',repr(t),'\t: (',i,':',type(t).__name__,')' )
print( " ---------end--------- ")
class let(object):
def __init__(self,env):
self.env = env
def genCode(self,old_const,old_varnames):
length_c = len(list(old_const))
length_v = len(list(old_varnames))
code = [ ]
keys = list(self.env.keys())
for i in range(len(keys)):
code += [opcode.opmap["LOAD_CONST"],length_c + i,
opcode.opmap["STORE_FAST"],length_v + i]
return code
def processGlobals(self,lst,names,varnames):
#print( lst ) # LOAD_GLOBAL => 116
#print( names )
ts = list(filter( lambda i: lst[i] == opcode.opmap["LOAD_GLOBAL"] ,range(len(lst))))
#print( ts )
#print( t!=None )
for t in ts:
i = lst[t+1]
#print(i)
if self.env.get(names[i]) :
if lst[t] == opcode.opmap["LOAD_GLOBAL"]:
lst[t] = opcode.opmap["LOAD_FAST"]
lst[t+1] = varnames.index(names[i])
return lst
def __call__(self,func):
self.func = func
_globals_ = func.__globals__
_code_ = func.__code__
varnames = list(_code_.co_varnames) + [v for v in self.env.keys()]
nlocals = len(varnames)
binlst = list(_code_.co_code)
lstbin = self.processGlobals(binlst,_code_.co_names,varnames)
genCo = self.genCode(_code_.co_consts,_code_.co_varnames)
lstbin = genCo + lstbin
consts = list(_code_.co_consts) + [v for v in self.env.values()]
code = CodeType(_code_.co_argcount, # argcount
_code_.co_kwonlyargcount, # kwonlyargcount
nlocals, # nlocals
_code_.co_stacksize, # stacksize
_code_.co_flags, # flags
bytes(lstbin), # codestring
tuple(consts), # consts
_code_.co_names, # names
tuple(varnames), # varnames
_code_.co_filename, # filename
_code_.co_name, # name
_code_.co_firstlineno, # firstlineno
_code_.co_lnotab, # lnotab
_code_.co_freevars, # freevars
_code_.co_cellvars, # cellvars
)
#_globals_.update(self.env)
function = FunctionType(code,_globals_)
return function
def __repr__(self):
return "Where ({}) => {}".format(self.env,self.func)
def example():
@let({'a':666})
def test():
return a
dis.dis(test)
showCodeInfo(test.__code__)
print( test )
print( test() )
__all__ = ["let"]