Even if we `goto` another routine, we can't trash an output.
Chris Pressey
7 years ago
6 | 6 | * `copy` is now understood to trash `a`, thus `copy ..., a` is not valid. |
7 | 7 | Indirect addressing is supported in `ld`, as in `ld a, [ptr] + y`, to compensate. |
8 | 8 | * Implements the "union rule for trashes" when analyzing `if` blocks. |
9 | * Even if we `goto` another routine, we can't trash an output. | |
9 | 10 | * Fixed bug where `trash` was not marking the location as being virtually altered. |
10 | 11 | |
11 | 12 | 0.11 |
34 | 34 | actor_pos, actor_delta, actor_logic, |
35 | 35 | screen, screen1, screen2, screen3, screen4, colormap1, colormap2, colormap3, colormap4 |
36 | 36 | outputs button_down, dispatch_game_state, |
37 | actor_pos, pos, new_pos, actor_delta, delta, actor_logic, | |
37 | actor_pos, actor_delta, actor_logic, | |
38 | 38 | screen, screen1, screen2, screen3, screen4, colormap1, colormap2, colormap3, colormap4 |
39 | trashes a, x, y, c, z, n, v, ptr, save_x, compare_target, dispatch_logic | |
39 | trashes a, x, y, c, z, n, v, pos, new_pos, delta, ptr, save_x, compare_target, dispatch_logic | |
40 | 40 | game_state_routine |
41 | 41 | |
42 | 42 | // |
401 | 401 | |
402 | 402 | if c { |
403 | 403 | call clear_screen |
404 | ||
405 | // FIXME: this seems wrong and we need to investigate it. | |
406 | // init_game trashes `pos` (this is reasonable.) But pos is declared | |
407 | // as an output to `game_state_routine`. This should be an error... | |
408 | 404 | call init_game |
409 | ||
410 | 405 | copy forward game_state_play, dispatch_game_state |
411 | 406 | } |
412 | 407 |
201 | 201 | return |
202 | 202 | type_ = routine.location.type |
203 | 203 | context = Context(self.routines, routine, type_.inputs, type_.outputs, type_.trashes) |
204 | ||
204 | 205 | if self.debug: |
205 | 206 | print "at start of routine `{}`:".format(routine.name) |
206 | 207 | print context |
208 | ||
207 | 209 | self.analyze_block(routine.block, context) |
210 | trashed = set(context.each_touched()) - context._meaningful | |
211 | ||
208 | 212 | if self.debug: |
209 | 213 | print "at end of routine `{}`:".format(routine.name) |
210 | 214 | print context |
215 | print "trashed: ", LocationRef.format_set(trashed) | |
216 | print "outputs: ", LocationRef.format_set(type_.outputs) | |
217 | trashed_outputs = type_.outputs & trashed | |
218 | if trashed_outputs: | |
219 | print "TRASHED OUTPUTS: ", LocationRef.format_set(trashed_outputs) | |
220 | print '' | |
221 | print '-' * 79 | |
222 | print '' | |
223 | ||
224 | # even if we goto another routine, we can't trash an output. | |
225 | for ref in trashed: | |
226 | if ref in type_.outputs: | |
227 | raise UnmeaningfulOutputError('%s in %s' % (ref.name, routine.name)) | |
228 | ||
211 | 229 | if not self.has_encountered_goto: |
212 | 230 | for ref in type_.outputs: |
213 | 231 | context.assert_meaningful(ref, exception_class=UnmeaningfulOutputError) |