This repository has been archived by the owner on Sep 12, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vargraph.py
205 lines (152 loc) · 5.27 KB
/
vargraph.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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#!/usr/bin/python
from enum import Enum
import json
import networkx as nx
import matplotlib.pyplot as plt
class VarType(Enum):
V = 1,
T = 2
class Variable:
def __init__(self, index, var_type: VarType):
self.__name = str(var_type.name) + str(index)
self.__type = var_type
self.__index = index
def __hash__(self):
return hash((self.__name, self.__type))
def __eq__(self, other):
if other is None:
return False
return self.__name == other.__name and self.__type == other.__type
def __str__(self):
return self.__name
def get_index(self):
return self.__index
def get_type(self) -> VarType:
return self.__type
def get_name(self) -> str:
return self.__name
def is_of_type(self, var_type: VarType) -> bool:
return self.__type == var_type
def __parse_assignment(graph, op, level):
level = op[1]
conditional_path = op[2]
index = op[3]
left = op[4][0]
right = op[4][1]
res_node = Variable(index, VarType.V)
res_node_temp = Variable(index, VarType.T)
left_op, left_nodes, left_top = __parse_default(graph, left, level)
right_op, right_nodes, right_top = __parse_default(graph, right, level)
left_nodes.extend(right_nodes)
nodes = list(set(left_nodes))
if res_node_temp in nodes:
res_node = res_node_temp
if left_top is not None and left_top != res_node and left_top != res_node_temp:
graph.add_edge(left_top, res_node, weight=level)
if right_top is not None and right_top != res_node and right_top != res_node_temp:
graph.add_edge(right_top, res_node, weight=level)
return op[0], nodes, res_node
def __parse_expression(graph, op, level):
op_type = op[1]
conditional_path = op[2]
index = op[2]
left = op[3]
right = None
if 5 == len(op):
right = op[4]
res_node = Variable(index, VarType.V)
res_node_temp = Variable(index, VarType.T)
left_op, left_nodes, left_top = __parse_default(graph, left, level)
right_op, right_nodes, right_top = __parse_default(graph, right, level)
left_nodes.extend(right_nodes)
nodes = list(set(left_nodes))
if res_node not in nodes and res_node_temp not in nodes:
nodes.append(res_node)
graph.add_node(res_node)
if res_node_temp in nodes:
res_node = res_node_temp
if left_top is not None and left_top != res_node and left_top != res_node_temp:
graph.add_edge(left_top, res_node, weight=level)
if right_top is not None and right_top != res_node and right_top != res_node_temp:
graph.add_edge(right_top, res_node, weight=level)
return op[0], nodes, res_node
def __parse_conditional_exp(graph, op, level):
level = op[1]
conditional_path = op[2]
op_type = op[3]
index = op[4]
left = op[5][0]
right = op[5][1]
node = Variable(index, VarType.V)
return op[0], [], node
def __parse_primitive(graph, op, level):
op_type = op[1]
return op[0], [], None
def __parse_var(graph, op, level):
node = Variable(op[1], VarType.V)
if node not in graph.nodes():
graph.add_node(node)
return op[0], [node], node
def __parse_temp(graph, op, level):
content = op[2]
node = Variable(op[1], VarType.T)
if node not in graph.nodes():
graph.add_node(node)
nodes = [node]
cast_op, cast_nodes, _ = __parse_default(graph, content, level)
nodes.extend(cast_nodes)
if cast_op in ['VV', 'V', 'F', 'E']:
for n in cast_nodes:
graph.add_edge(n, node, weight=level)
nodes.remove(n)
nodes = list(set(nodes))
return op[0], nodes, node
def __parse_function(graph, op, level):
return_type = op[1]
_, nodes, top_node = __parse_default(graph, return_type, level)
return op[0], nodes, top_node
def __parse_constant(graph, op, level):
const_type = op[1]
value = op[2]
return op[0], [], None
__parser = {
'A': __parse_assignment,
'R': __parse_conditional_exp,
'P': __parse_primitive,
'V': __parse_var,
'E': __parse_expression,
'T': __parse_temp,
'F': __parse_function,
'C': __parse_constant
}
def __parse_default(graph, op, level):
if op is None or op[0] is None:
return 'VV', [], None
if 1 == len(op):
op = op[0]
return __parser[op[0]](graph, op, level)
def parse_vars_file(file: str) -> nx.DiGraph:
with open(file) as jfile:
data = json.load(jfile)
graph = nx.DiGraph()
for op in data:
__parse_default(graph, op, 0)
return graph
def plot(graph: nx.DiGraph):
# Creates the figure the draw call will use
fig = plt.figure()
nx.draw_kamada_kawai(graph, with_labels=True, node_size=512, alpha=1, font_weight='bold')
plt.show()
def extract_leq_relations(graph: nx.DiGraph, only_temp: bool = False) -> list:
rels = []
for n in graph.nodes:
for nn in graph.successors(n):
if not only_temp or n.is_of_type(VarType.T) or nn.is_of_type(VarType.T):
rels.append((n, nn))
return rels
def extract_cast_to_temp_relations(graph: nx.DiGraph) -> list:
rels = []
for n in graph.nodes:
if n.is_of_type(VarType.T) and 1 < len(list(graph.predecessors(n))):
rels.append((n, list(graph.predecessors(n))))
return rels