Improve test coverage. One failing test.
Cat's Eye Technologies
9 years ago
18 | 18 | = NamedLocation Nothing "score": UpdatedWith A |
19 | 19 | |
20 | 20 | A routine cannot expect registers which a called routine does not |
21 | preserve, to be preserved. | |
21 | preserve, to be preserved. We say the called routine "poisons" those | |
22 | registers. | |
22 | 23 | |
23 | 24 | | assign byte border_colour 4000 |
24 | 25 | | reserve byte score |
34 | 35 | | } |
35 | 36 | ? routine 'main' does not preserve 'A' |
36 | 37 | |
37 | But if it does it can. | |
38 | But if a called routine does preserve those registers, the caller can | |
39 | continue to use them after calling the routine. | |
38 | 40 | |
39 | 41 | | assign byte border_colour 4000 |
40 | 42 | | reserve byte score |
59 | 61 | = X: UpdatedWith (Immediate 1) |
60 | 62 | = NamedLocation Nothing "score": UpdatedWith X |
61 | 63 | |
62 | We can't expect to stay named variables to stay unmodified either. | |
64 | Not only registers, but also named variables, can be poisoned by a called | |
65 | routine. | |
63 | 66 | |
64 | 67 | | reserve byte score |
65 | 68 | | routine update_score |
73 | 76 | | } |
74 | 77 | ? routine 'main' does not preserve 'NamedLocation Nothing "score"' |
75 | 78 | |
76 | What the solution to the above is to notate `update_score` as intentionally | |
77 | modifying score, as an "output" of the routine. | |
79 | Of course, the difference between poisoning and intentionally modifying a | |
80 | storage location is a matter of intent. The solution to the above is to | |
81 | explicitly notate `update_score` as an "output" of the routine. | |
78 | 82 | |
79 | 83 | | assign byte border_colour 4000 |
80 | 84 | | reserve byte score |
235 | 239 | | } |
236 | 240 | ? routine 'main' does not preserve 'NamedLocation Nothing "score"' |
237 | 241 | |
238 | | assign vector cinv 788 | |
239 | | reserve vector save_cinv | |
240 | | | |
242 | Some more tests... | |
243 | ||
241 | 244 | | assign word position $fb |
242 | | | |
243 | 245 | | reserve byte value |
244 | 246 | | |
245 | 247 | | routine reset_position { |
249 | 251 | | sta >position |
250 | 252 | | } |
251 | 253 | | |
252 | | routine our_cinv { | |
254 | | routine main { | |
253 | 255 | | inc value |
254 | 256 | | lda value |
255 | 257 | | ldy #0 |
258 | 260 | | jsr reset_position |
259 | 261 | | } else { |
260 | 262 | | } |
261 | | jmp (save_cinv) | |
262 | | } | |
263 | | | |
264 | | routine main { | |
265 | | jsr reset_position | |
266 | | sei { | |
267 | | copy cinv save_cinv | |
268 | | copy routine our_cinv to cinv | |
269 | | } | |
270 | | clc | |
271 | | repeat bcc { } | |
272 | | } | |
273 | = main ([]) | |
274 | = A: PoisonedWith (Immediate 4) | |
275 | = FlagC: UpdatedWith (Immediate 0) | |
276 | = NamedLocation Nothing "cinv": UpdatedWith (Immediate 7) | |
277 | = NamedLocation Nothing "position": PoisonedWith A | |
278 | = NamedLocation Nothing "save_cinv": UpdatedWith (NamedLocation Nothing "cinv") | |
279 | = | |
280 | = our_cinv ([]) | |
263 | | } | |
264 | = main ([]) | |
281 | 265 | = A: PoisonedWith (Immediate 4) |
282 | 266 | = Y: UpdatedWith (Immediate 0) |
283 | 267 | = IndirectIndexed (NamedLocation (Just Word) "position") Y: UpdatedWith A |
287 | 271 | = reset_position ([]) |
288 | 272 | = A: UpdatedWith (Immediate 4) |
289 | 273 | = NamedLocation Nothing "position": UpdatedWith A |
274 | ||
275 | | assign word position $fb | |
276 | | reserve byte value | |
277 | | | |
278 | | routine reset_position { | |
279 | | lda #$00 | |
280 | | sta <position | |
281 | | lda #$04 | |
282 | | sta >position | |
283 | | } | |
284 | | | |
285 | | routine main { | |
286 | | inc value | |
287 | | lda value | |
288 | | ldy #0 | |
289 | | sta (position), y | |
290 | | if beq { | |
291 | | jsr reset_position | |
292 | | } else { | |
293 | | } | |
294 | | sta value | |
295 | | } | |
296 | ? routine 'main' does not preserve 'A' | |
297 | ||
298 | | assign word position $fb | |
299 | | reserve byte value | |
300 | | | |
301 | | routine reset_position { | |
302 | | lda #$00 | |
303 | | sta <position | |
304 | | lda #$04 | |
305 | | sta >position | |
306 | | } | |
307 | | | |
308 | | routine main { | |
309 | | inc value | |
310 | | lda value | |
311 | | ldy #0 | |
312 | | sta (position), y | |
313 | | jsr reset_position | |
314 | | if beq { | |
315 | | } else { | |
316 | | sta value | |
317 | | } | |
318 | | } | |
319 | ? routine 'main' does not preserve 'A' |