2018-04-04 10:09:39 +00:00
|
|
|
# encoding: UTF-8
|
|
|
|
|
2018-04-04 14:09:48 +00:00
|
|
|
from copy import copy
|
|
|
|
|
2018-04-04 10:09:39 +00:00
|
|
|
from sixtypical.model import RoutineType
|
|
|
|
|
|
|
|
|
|
|
|
class FallthruAnalyzer(object):
|
|
|
|
|
|
|
|
def __init__(self, debug=False):
|
|
|
|
self.debug = debug
|
|
|
|
|
|
|
|
def analyze_program(self, program):
|
2018-04-04 15:22:14 +00:00
|
|
|
self.program = program
|
2018-04-05 08:57:14 +00:00
|
|
|
|
|
|
|
self.fallthru_map = {}
|
2018-04-04 10:09:39 +00:00
|
|
|
for routine in program.routines:
|
|
|
|
encountered_gotos = list(routine.encountered_gotos)
|
|
|
|
if len(encountered_gotos) == 1 and isinstance(encountered_gotos[0].type, RoutineType):
|
2018-04-05 08:57:14 +00:00
|
|
|
self.fallthru_map[routine.name] = encountered_gotos[0].name
|
|
|
|
else:
|
|
|
|
self.fallthru_map[routine.name] = None
|
|
|
|
|
|
|
|
def find_chain(self, routine_name, available):
|
|
|
|
chain = [routine_name]
|
|
|
|
seen = set(chain)
|
|
|
|
while True:
|
|
|
|
next = self.fallthru_map.get(routine_name)
|
|
|
|
if next is None or next in seen or next not in available:
|
|
|
|
return chain
|
|
|
|
seen.add(next)
|
|
|
|
chain.append(next)
|
2018-04-06 12:27:40 +00:00
|
|
|
routine_name = next
|
2018-04-04 10:09:39 +00:00
|
|
|
|
|
|
|
def serialize(self):
|
2018-04-05 08:57:14 +00:00
|
|
|
pending_routines = copy(self.fallthru_map)
|
2018-04-04 16:05:48 +00:00
|
|
|
roster = []
|
2018-04-04 15:54:12 +00:00
|
|
|
|
2018-04-05 08:57:14 +00:00
|
|
|
main_chain = self.find_chain('main', pending_routines)
|
|
|
|
roster.append(main_chain)
|
|
|
|
for k in main_chain:
|
|
|
|
del pending_routines[k]
|
2018-04-04 15:22:14 +00:00
|
|
|
|
2018-04-05 08:57:14 +00:00
|
|
|
while pending_routines:
|
|
|
|
chains = [self.find_chain(k, pending_routines) for k in pending_routines.keys()]
|
2018-09-06 16:15:10 +00:00
|
|
|
chains.sort(key=lambda x: (len(x), str(x)), reverse=True)
|
2018-04-05 08:57:14 +00:00
|
|
|
c = chains[0]
|
|
|
|
roster.append(c)
|
|
|
|
for k in c:
|
|
|
|
del pending_routines[k]
|
2018-04-04 14:09:48 +00:00
|
|
|
|
2018-04-04 16:05:48 +00:00
|
|
|
return roster
|