git @ Cat's Eye Technologies SixtyPical / 50433ac
Find cycles in fallthru map. Try to break them; not right, yet. Chris Pressey 7 years ago
3 changed file(s) with 65 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
5858 analyzer.analyze_program(program)
5959
6060 if options.optimize_fallthru:
61 import json
6162 from sixtypical.fallthru import FallthruAnalyzer
6263
6364 fa = FallthruAnalyzer(debug=options.debug)
6465 fa.analyze_program(program)
6566
6667 if options.dump_fallthru_info:
67 import json
68 sys.stdout.write(json.dumps(fa.fallthru_map, indent=4, sort_keys=True))
68 fallthru_map = dict(fa.fallthru_map)
69 sys.stdout.write(json.dumps(fallthru_map, indent=4, sort_keys=True))
6970 sys.stdout.write("\n")
71
72 fa.find_ancestors()
73
74 if options.debug and options.dump_fallthru_info:
75 sys.stdout.write("*** ancestors:\n")
76 sys.stdout.write(json.dumps(fa.ancestor_map, indent=4, sort_keys=True))
77 sys.stdout.write("\n")
78
79 fa.find_cycles()
80
81 if fa.cycles_found:
82 if options.dump_fallthru_info:
83 sys.stdout.write("*** cycles found:\n")
84 sys.stdout.write(json.dumps(sorted(fa.cycles_found), indent=4, sort_keys=True))
85 sys.stdout.write("\n")
86
87 fa.break_cycles()
88
89 if options.dump_fallthru_info and fallthru_map != fa.fallthru_map:
90 sys.stdout.write("*** after breaking cycles:\n")
91 sys.stdout.write(json.dumps(fa.fallthru_map, indent=4, sort_keys=True))
92 sys.stdout.write("\n")
7093
7194 if options.analyze_only:
7295 return
00 # encoding: UTF-8
11
22 from sixtypical.model import RoutineType
3
4
5 def make_transitive_closure(d, key, s):
6 for sub in d.get(key, []):
7 if sub not in s:
8 s.add(sub)
9 make_transitive_closure(d, sub, s)
310
411
512 class FallthruAnalyzer(object):
1421 if len(encountered_gotos) == 1 and isinstance(encountered_gotos[0].type, RoutineType):
1522 fallthru_map.setdefault(encountered_gotos[0].name, set()).add(routine.name)
1623 self.fallthru_map = dict([(k, sorted(v)) for k, v in fallthru_map.iteritems()])
24 return self.fallthru_map
25
26 def find_ancestors(self):
27 self.ancestor_map = {}
28 for key in self.fallthru_map:
29 ancestors = set()
30 make_transitive_closure(self.fallthru_map, key, ancestors)
31 self.ancestor_map[key] = sorted(ancestors)
32 return self.ancestor_map
33
34 def find_cycles(self):
35 self.cycles_found = set()
36 for key in self.ancestor_map:
37 if key in self.ancestor_map[key]:
38 self.cycles_found.add(key)
39 return self.cycles_found
1740
1841 def break_cycles(self):
19 raise NotImplementedError
42 new_fallthru_map = {}
43 for key in self.fallthru_map:
44 values = set(self.fallthru_map[key]) - self.cycles_found
45 if values:
46 new_fallthru_map[key] = sorted(values)
47 self.fallthru_map = new_fallthru_map
2048
2149 def serialize(self):
2250 raise NotImplementedError
133133 = "bar"
134134 = ]
135135 = }
136 = *** cycles found:
137 = [
138 = "bar",
139 = "foo"
140 = ]
141 = *** after breaking cycles:
142 = {
143 = "bar": [
144 = "foo"
145 = ]
146 = }
136147
137148 If a routine does two tail calls (which is possible because they
138149 can be in different branches of an `if`) it cannot fall through to another