1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2025-02-16 15:30:26 +00:00

Write sufficient tests (I think) for analysis of ifs.

This commit is contained in:
Chris Pressey 2015-10-16 14:01:45 +01:00
parent d22edc52a9
commit c3a0659058
4 changed files with 66 additions and 3 deletions

View File

@ -31,7 +31,7 @@ TODO
For 0.2:
* analyze `if` correctly.
* write a few more tests and clean up spec a bit.
For 0.3:

View File

@ -22,6 +22,10 @@ class UninitializedOutputError(StaticAnalysisError):
pass
class InconsistentInitializationError(StaticAnalysisError):
pass
class IllegalWriteError(StaticAnalysisError):
pass
@ -173,9 +177,9 @@ def analyze_instr(instr, context, routines):
analyze_block(instr.block1, context1, routines)
analyze_block(instr.block2, context2, routines)
for ref in context1.each_initialized():
context2.assert_initialized(ref)
context2.assert_initialized(ref, exception_class=InconsistentInitializationError)
for ref in context2.each_initialized():
context1.assert_initialized(ref)
context1.assert_initialized(ref, exception_class=InconsistentInitializationError)
context.set_from(context1)
else:
raise NotImplementedError(opcode)

View File

@ -165,6 +165,8 @@ class Parser(object):
block2 = None
if self.scanner.consume('else'):
block2 = self.block()
else:
block2 = Block(instrs=[])
return Instr(opcode='if', dest=None, src=src, block1=block1, block2=block2)
elif self.scanner.token in ("ld", "add", "sub", "cmp", "and", "or", "xor"):
opcode = self.scanner.token

View File

@ -413,3 +413,60 @@ Both blocks of an `if` are analyzed.
| }
| }
= ok
If a location is initialized in one block, is must be initialized in the other as well.
| routine foo
| inputs a
| outputs x
| trashes a, z, n, c
| {
| cmp a, 42
| if z {
| ld x, 7
| } else {
| ld a, 23
| }
| }
? InconsistentInitializationError: x
| routine foo
| inputs a
| outputs x
| trashes a, z, n, c
| {
| cmp a, 42
| if z {
| ld a, 6
| } else {
| ld x, 7
| }
| }
? InconsistentInitializationError: x
An `if` with a single block is analyzed as if it had an empty `else` block.
| routine foo
| inputs a
| outputs x
| trashes a, z, n, c
| {
| cmp a, 42
| if z {
| ld x, 7
| }
| }
? InconsistentInitializationError: x
| routine foo
| inputs a
| outputs x
| trashes a, z, n, c
| {
| ld x, 0
| cmp a, 42
| if z {
| ld x, 7
| }
| }
= ok