/
ast_optimiser.py
117 lines (96 loc) · 4.62 KB
/
ast_optimiser.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
import ast
from astmonkey import visitors
class Optimizer(ast.NodeTransformer):
# optimising nodes with Binary operation type
def visit_BinOp(self, node):
node = Optimizer.generic_visit(self, node)
# Addition
if isinstance(node.op, ast.Add):
# zero case (num + 0 = num, a + 0 = a)
if isinstance(node.left, ast.Constant) and node.left.value == 0:
return node.right
if isinstance(node.right, ast.Constant) and node.right.value == 0:
return node.left
# general case
if isinstance(node.left, ast.Constant) and isinstance(node.right, ast.Constant):
if type(node.left.value) == type(node.right.value):
return ast.Constant(
value=node.left.value + node.right.value
)
# Subtraction
if isinstance(node.op, ast.Sub):
# zero case (num - 0 = num, a - 0 = a)
if isinstance(node.left, ast.Constant) and node.left.value == 0:
return node.right
if isinstance(node.right, ast.Constant) and node.right.value == 0:
return node.left
#general case
if isinstance(node.left, ast.Constant) and isinstance(node.right, ast.Constant):
if isinstance(node.right.value, (int, float)) and isinstance(node.left.value, (int, float)):
return ast.Constant(
value=node.left.value - node.right.value
)
# Multiplication
if isinstance(node.op, ast.Mult):
# zero case (num*0 = 0, a*0 = 0)
if isinstance(node.left, ast.Constant) and node.left.value == 0 or \
isinstance(node.right, ast.Constant) and node.right.value == 0:
return ast.Constant(
value=0
)
#general case
if isinstance(node.left, ast.Constant) and isinstance(node.right, ast.Constant):
if isinstance(node.right.value, (int, float)) and isinstance(node.left.value, (int, float)):
return ast.Constant(
value=node.left.value * node.right.value
)
# Division
if isinstance(node.op, ast.Div):
#zero case (a / 0)
if isinstance(node.right, ast.Constant) and node.right.value == 0:
print("Zero division error")
return node
# zero case (0/a = 0)
if isinstance(node.left, ast.Constant) and node.left.value == 0:
return ast.Constant(
value=0
)
#general case
if isinstance(node.left, ast.Constant) and isinstance(node.right, ast.Constant):
if isinstance(node.right.value, (int, float)) and isinstance(node.left.value, (int, float)):
return ast.Constant(
value=node.left.value / node.right.value
)
# Mod
if isinstance(node.op, ast.Mod):
if isinstance(node.left, ast.Constant) and isinstance(node.right, ast.Constant):
if isinstance(node.right.value, (int, float)) and isinstance(node.left.value, (int, float)):
try:
return ast.Constant(
value=node.left.value % node.right.value
)
except ZeroDivisionError:
print("Zero division error")
# Power
if isinstance(node.op, ast.Pow):
if isinstance(node.left, ast.Constant) and isinstance(node.right, ast.Constant):
if isinstance(node.right.value, (int, float)) and isinstance(node.left.value, (int, float)):
return ast.Constant(
value=node.left.value**node.right.value
)
return node
print("enter your line")
code = input()
tree = ast.parse(code)
new_tree = ast.fix_missing_locations(Optimizer().visit(tree))
generated_code = visitors.to_source(new_tree)
print(generated_code)
"""
Написана оптимизация для:
1) случая сложения констант. Рассмотрено сложение с 0.
2) случая вычитания констант и рассмотрен случай ноля
3) умножения констант и 0
4) деления и случаи с 0
5) взятия остатка
6) возведения в степень
"""