diff --git a/bin/sixtypical b/bin/sixtypical index 4934005..9827d52 100755 --- a/bin/sixtypical +++ b/bin/sixtypical @@ -84,7 +84,7 @@ def process_input_files(filenames, options): fa.find_cycles() routines_list = fa.serialize() - #dump('serialization', routines_list) + dump('serialization', routines_list) if options.analyze_only: return diff --git a/src/sixtypical/fallthru.py b/src/sixtypical/fallthru.py index 00c147d..b6cc27c 100644 --- a/src/sixtypical/fallthru.py +++ b/src/sixtypical/fallthru.py @@ -18,6 +18,7 @@ class FallthruAnalyzer(object): self.debug = debug def analyze_program(self, program): + self.program = program fall_in_map = {} for routine in program.routines: encountered_gotos = list(routine.encountered_gotos) @@ -57,15 +58,25 @@ class FallthruAnalyzer(object): for value in values: assert value not in self.fall_out_map self.fall_out_map[value] = key + for routine in self.program.routines: + if routine.name not in self.fall_out_map: + self.fall_out_map[routine.name] = None routine_list = [] fall_out_map = copy(self.fall_out_map) while fall_out_map: key = fall_out_map.keys()[0] - # ... + in_set = self.fall_in_map.get(key, []) # Find the longest chain of routines r1,r2,...rn in R where out(r1) = {r2}, out(r2} = {r3}, ... out(rn-1) = {rn}, and rn = r. + # TODO implement this + routines = [key] + # Remove (r1,r2,...,rn) from R and append them to L in that order. Mark (r1,r2,...rn-1) as "will have their final goto removed." - # - del fall_out_map[key] + for r in routines: + del fall_out_map[r] + if r == routines[-1]: + routine_list.append(['retain', r]) + else: + routine_list.append(['fallthru', r]) return routine_list diff --git a/tests/SixtyPical Fallthru.md b/tests/SixtyPical Fallthru.md index 81d398a..f6b4ae9 100644 --- a/tests/SixtyPical Fallthru.md +++ b/tests/SixtyPical Fallthru.md @@ -70,6 +70,13 @@ through to it. | { | } = {} + = *** serialization: + = [ + = [ + = "retain", + = "main" + = ] + = ] If main does a `goto foo`, then it can fall through to `foo`. @@ -87,6 +94,17 @@ If main does a `goto foo`, then it can fall through to `foo`. = "main" = ] = } + = *** serialization: + = [ + = [ + = "fallthru", + = "main" + = ], + = [ + = "retain", + = "foo" + = ] + = ] More than one routine can fall through to a routine. @@ -113,6 +131,21 @@ If main does a `goto foo`, then it can fall through to `foo`. = "main" = ] = } + = *** serialization: + = [ + = [ + = "fallthru", + = "main" + = ], + = [ + = "retain", + = "foo" + = ], + = [ + = "retain", + = "bar" + = ] + = ] There is nothing stopping two routines from tail-calling each other, but we will only be able to make one of them, at most, @@ -152,6 +185,21 @@ fall through to the other. = "foo" = ] = } + = *** serialization: + = [ + = [ + = "retain", + = "main" + = ], + = [ + = "fallthru", + = "bar" + = ], + = [ + = "retain", + = "foo" + = ] + = ] If a routine does two tail calls (which is possible because they can be in different branches of an `if`) it cannot fall through to another @@ -176,6 +224,21 @@ routine. | } | } = {} + = *** serialization: + = [ + = [ + = "retain", + = "main" + = ], + = [ + = "retain", + = "bar" + = ], + = [ + = "retain", + = "foo" + = ] + = ] Similarly, a tail call to a vector can't be turned into a fallthru, because we don't necessarily know what actual routine the vector contains. @@ -199,3 +262,18 @@ because we don't necessarily know what actual routine the vector contains. | goto vec | } = {} + = *** serialization: + = [ + = [ + = "retain", + = "main" + = ], + = [ + = "retain", + = "bar" + = ], + = [ + = "retain", + = "foo" + = ] + = ]