-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathsnippet.py
169 lines (145 loc) · 4.13 KB
/
snippet.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
"""
Update note: Never use this module to test your emit functions.
Use the file `auto_test.py` in the same directory instead.
"""
import ast
import sys
import types
from astpretty import pprint
from yapypy.extended_python.parser import parse
from yapypy.extended_python.symbol_analyzer import ASTTagger, SymTable, to_tagged_ast, Tag
from yapypy.extended_python.py_compile import py_compile
from bytecode import Bytecode
import dis
def parse_expr(expr_code):
return parse(expr_code).result.body[0].value
ctx = {}
exec(
r"""
from asyncio import sleep, get_event_loop
class S:
def __init__(self): self.i = 0
def __aiter__(self): return self
async def __anext__(self):
if self.i < 10:
self.i += 1
await sleep(0.1)
return self.i
raise StopAsyncIteration
def to_t(aiter):
async def _():
d = []
async for each in aiter:
d.append(each)
return tuple(d)
return get_event_loop().run_until_complete(_())
""", ctx)
def show_code(code: types.CodeType, f, contains=()):
if code in contains:
return
f.write('\n\n\n')
f.write(code.co_name)
f.write(':\n\n')
dis.show_code(code, file=f)
for each in code.co_consts:
if isinstance(each, types.CodeType):
show_code(each, f, (*contains, code))
def dis_code(code: types.CodeType, f):
f.write(code.co_name)
f.write('\n')
# def print(*args):
# for each in args:
# f.write(str(each))
# f.write(' ')
# f.write('\n')
dis.dis(code, file=f)
if sys.version_info < (3, 7):
# dump_bytecode(Bytecode.from_code(code), print=print)
for each in code.co_consts:
if isinstance(each, types.CodeType):
dis_code(each, f)
def case(code, ctx, debug=False, cpython_compat=True):
stmt = parse(code).result
code_obj = py_compile(stmt, is_entrypoint=False)
if debug:
with open('out_yapypy_bc.log', 'w') as yapypy_bc, open('out_yapypy_info.log',
'w') as yapypy_info:
dis_code(code_obj, yapypy_bc)
show_code(code_obj, yapypy_info)
if cpython_compat:
code_obj2 = compile(code, "", "exec")
with open('out_cpy_bc.log', 'w') as cpy_bc, open('out_cpy_info.log',
'w') as cpy_info:
dis_code(code_obj2, cpy_bc)
show_code(code_obj2, cpy_info)
print('python:')
exec(Bytecode.from_code(code_obj2).to_code(), ctx or {})
print('yapypy')
exec(Bytecode.from_code(code_obj).to_code(), ctx or {})
else:
exec(code_obj, ctx)
case(
"""
(a := 1)
a := 1
print(a)
def maybe_odd(i):
if i % 2:
return i
if a := maybe_odd(2):
print(a)
if a := maybe_odd(3):
print(a)
""",
ctx,
debug=True,
cpython_compat=False)
# case(
# """
# async def f():
# return (i % 5 async for i in S())
# print(to_t(get_event_loop().run_until_complete(f())))
# """,
# ctx,
# debug=False)
#
# case(
# """
# async def f():
# return {i % 5: i for k in range(2) async for i in S()}
# print(get_event_loop().run_until_complete(f()))
# """,
# ctx,
# debug=True)
# exec(code, ctx)
# dis.dis(code.co_consts[0])
# dis.dis(code.co_consts[1])
# try:
# parse_expr('f(a=1, b)\n')
# except SyntaxError:
# print('good')
#
# from bytecode import Bytecode, Instr, Label
# bc = Bytecode()
# bc.append(Instr("BUILD_MAP", 0))
# bc.append(Instr("LOAD_GLOBAL", "range"))
# bc.append(Instr("LOAD_CONST", 2))
# bc.append(Instr("CALL_FUNCTION", 1, lineno=2))
#
# l1 = Label()
# l2 = Label()
# bc.append(Instr("GET_ITER"))
# bc.append(l1)
# bc.append(Instr("FOR_ITER", l2))
# bc.append(Instr("STORE_FAST", "i"))
# bc.append(Instr("LOAD_CONST", 2))
# bc.append(Instr("LOAD_CONST", 1, lineno=1))
# bc.append(Instr("MAP_ADD", 2))
# bc.append(Instr("JUMP_ABSOLUTE", l1))
# bc.append(l2)
# bc.append(Instr("RETURN_VALUE", ))
#
# code = bc.to_code()
# print(eval(code))
# dis.show_code(code)
# dis.dis(code)