diff --git a/HISTORY.md b/HISTORY.md index 8d00f67..70a9244 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -7,6 +7,7 @@ History of SixtyPical * `copy` is now understood to trash `a`, thus `copy ..., a` is not valid. Indirect addressing is supported in `ld`, as in `ld a, [ptr] + y`, to compensate. * Implements the "union rule for trashes" when analyzing `if` blocks. +* Even if we `goto` another routine, we can't trash an output. * Fixed bug where `trash` was not marking the location as being virtually altered. 0.11 diff --git a/eg/proto-game.60p b/eg/proto-game.60p index eca054d..3eeb21d 100644 --- a/eg/proto-game.60p +++ b/eg/proto-game.60p @@ -35,9 +35,9 @@ typedef routine actor_pos, actor_delta, actor_logic, screen, screen1, screen2, screen3, screen4, colormap1, colormap2, colormap3, colormap4 outputs button_down, dispatch_game_state, - actor_pos, pos, new_pos, actor_delta, delta, actor_logic, + actor_pos, actor_delta, actor_logic, screen, screen1, screen2, screen3, screen4, colormap1, colormap2, colormap3, colormap4 - trashes a, x, y, c, z, n, v, ptr, save_x, compare_target, dispatch_logic + trashes a, x, y, c, z, n, v, pos, new_pos, delta, ptr, save_x, compare_target, dispatch_logic game_state_routine // @@ -402,12 +402,7 @@ define game_state_title_screen game_state_routine if c { call clear_screen - - // FIXME: this seems wrong and we need to investigate it. - // init_game trashes `pos` (this is reasonable.) But pos is declared - // as an output to `game_state_routine`. This should be an error... call init_game - copy forward game_state_play, dispatch_game_state } diff --git a/src/sixtypical/analyzer.py b/src/sixtypical/analyzer.py index c90c2e7..fc3f2f6 100644 --- a/src/sixtypical/analyzer.py +++ b/src/sixtypical/analyzer.py @@ -202,13 +202,31 @@ class Analyzer(object): return type_ = routine.location.type context = Context(self.routines, routine, type_.inputs, type_.outputs, type_.trashes) + if self.debug: print "at start of routine `{}`:".format(routine.name) print context + self.analyze_block(routine.block, context) + trashed = set(context.each_touched()) - context._meaningful + if self.debug: print "at end of routine `{}`:".format(routine.name) print context + print "trashed: ", LocationRef.format_set(trashed) + print "outputs: ", LocationRef.format_set(type_.outputs) + trashed_outputs = type_.outputs & trashed + if trashed_outputs: + print "TRASHED OUTPUTS: ", LocationRef.format_set(trashed_outputs) + print '' + print '-' * 79 + print '' + + # even if we goto another routine, we can't trash an output. + for ref in trashed: + if ref in type_.outputs: + raise UnmeaningfulOutputError('%s in %s' % (ref.name, routine.name)) + if not self.has_encountered_goto: for ref in type_.outputs: context.assert_meaningful(ref, exception_class=UnmeaningfulOutputError)