mirror of
https://github.com/catseye/SixtyPical.git
synced 2024-11-25 23:49:17 +00:00
865 lines
15 KiB
Markdown
865 lines
15 KiB
Markdown
SixtyPical Analysis
|
|
===================
|
|
|
|
This is a test suite, written in [Falderal][] format, for the SixtyPical
|
|
static analysis rules.
|
|
|
|
This file mostly contains tests for operations.
|
|
For rudiments and storage, see [SixtyPical Storage](SixtyPical%20Storage.md).
|
|
For control flow, see [SixtyPical Control Flow](SixtyPical%20Control%20Flow.md).
|
|
|
|
[Falderal]: http://catseye.tc/node/Falderal
|
|
|
|
-> Tests for functionality "Analyze SixtyPical program"
|
|
|
|
### add ###
|
|
|
|
Can't `add` from or to a memory location that isn't initialized.
|
|
|
|
| define main routine
|
|
| inputs a
|
|
| outputs a
|
|
| trashes c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| add a, 0
|
|
| }
|
|
= ok
|
|
|
|
| byte lives
|
|
| define main routine
|
|
| inputs a
|
|
| outputs a
|
|
| trashes c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| add a, lives
|
|
| }
|
|
? UnmeaningfulReadError: lives
|
|
|
|
| byte lives
|
|
| define main routine
|
|
| inputs lives
|
|
| outputs a
|
|
| trashes c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| add a, lives
|
|
| }
|
|
? UnmeaningfulReadError: a
|
|
|
|
Can't `add` to a memory location that isn't writeable.
|
|
|
|
| define main routine
|
|
| inputs a
|
|
| trashes c
|
|
| {
|
|
| st off, c
|
|
| add a, 0
|
|
| }
|
|
? ForbiddenWriteError: a
|
|
|
|
You can `add` a byte constant to a byte memory location.
|
|
|
|
| byte lives
|
|
| define main routine
|
|
| inputs a, lives
|
|
| outputs lives
|
|
| trashes a, c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| add lives, 3
|
|
| }
|
|
= ok
|
|
|
|
`add`ing a byte constant to a byte memory location trashes `a`.
|
|
|
|
| byte lives
|
|
| define main routine
|
|
| inputs a, lives
|
|
| outputs a, lives
|
|
| trashes c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| add lives, 3
|
|
| }
|
|
? UnmeaningfulOutputError: a
|
|
|
|
You can `add` a byte memory location to another byte memory location.
|
|
This trashes `a`.
|
|
|
|
| byte lives
|
|
| byte extra
|
|
| define main routine
|
|
| inputs a, lives, extra
|
|
| outputs lives
|
|
| trashes a, c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| add lives, extra
|
|
| }
|
|
= ok
|
|
|
|
| byte lives
|
|
| byte extra
|
|
| define main routine
|
|
| inputs a, lives, extra
|
|
| outputs a, lives
|
|
| trashes c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| add lives, extra
|
|
| }
|
|
? UnmeaningfulOutputError: a
|
|
|
|
You can `add` a word constant to a word memory location.
|
|
|
|
| word score
|
|
| define main routine
|
|
| inputs a, score
|
|
| outputs score
|
|
| trashes a, c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| add score, 1999
|
|
| }
|
|
= ok
|
|
|
|
`add`ing a word constant to a word memory location trashes `a`.
|
|
|
|
| word score
|
|
| define main routine
|
|
| inputs a, score
|
|
| outputs score, a
|
|
| trashes c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| add score, 1999
|
|
| }
|
|
? UnmeaningfulOutputError: a
|
|
|
|
To be sure, `add`ing a word constant to a word memory location trashes `a`.
|
|
|
|
| word score
|
|
| define main routine
|
|
| inputs score
|
|
| outputs score
|
|
| trashes c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| add score, 1999
|
|
| }
|
|
? ForbiddenWriteError: a
|
|
|
|
You can `add` a word memory location to another word memory location.
|
|
|
|
| word score
|
|
| word delta
|
|
| define main routine
|
|
| inputs score, delta
|
|
| outputs score
|
|
| trashes a, c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| add score, delta
|
|
| }
|
|
= ok
|
|
|
|
`add`ing a word memory location to a word memory location trashes `a`.
|
|
|
|
| word score
|
|
| word delta
|
|
| define main routine
|
|
| inputs score, delta
|
|
| outputs score
|
|
| trashes c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| add score, delta
|
|
| }
|
|
? ForbiddenWriteError: a
|
|
|
|
You can `add` a word memory location, or a constant, to a pointer.
|
|
|
|
| pointer ptr
|
|
| word delta
|
|
| define main routine
|
|
| inputs ptr, delta
|
|
| outputs ptr
|
|
| trashes a, c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| add ptr, delta
|
|
| add ptr, word 1
|
|
| }
|
|
= ok
|
|
|
|
`add`ing a word memory location, or a constant, to a pointer, trashes `a`.
|
|
|
|
| pointer ptr
|
|
| word delta
|
|
| define main routine
|
|
| inputs ptr, delta
|
|
| outputs ptr
|
|
| trashes c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| add ptr, delta
|
|
| add ptr, word 1
|
|
| }
|
|
? ForbiddenWriteError: a
|
|
|
|
### sub ###
|
|
|
|
Can't `sub` from or to a memory location that isn't initialized.
|
|
|
|
| define main routine
|
|
| inputs a
|
|
| outputs a
|
|
| trashes c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| sub a, 0
|
|
| }
|
|
= ok
|
|
|
|
| byte lives
|
|
| define main routine
|
|
| inputs a
|
|
| outputs a
|
|
| trashes c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| sub a, lives
|
|
| }
|
|
? UnmeaningfulReadError: lives
|
|
|
|
| byte lives
|
|
| define main routine
|
|
| inputs lives
|
|
| outputs a
|
|
| trashes c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| sub a, lives
|
|
| }
|
|
? UnmeaningfulReadError: a
|
|
|
|
Can't `sub` to a memory location that isn't writeable.
|
|
|
|
| define main routine
|
|
| inputs a
|
|
| trashes c
|
|
| {
|
|
| st off, c
|
|
| sub a, 0
|
|
| }
|
|
? ForbiddenWriteError: a
|
|
|
|
You can `sub` a byte constant from a byte memory location.
|
|
|
|
| byte lives
|
|
| define main routine
|
|
| inputs a, lives
|
|
| outputs lives
|
|
| trashes a, c, z, v, n
|
|
| {
|
|
| st on, c
|
|
| sub lives, 3
|
|
| }
|
|
= ok
|
|
|
|
`sub`ing a byte constant from a byte memory location trashes `a`.
|
|
|
|
| byte lives
|
|
| define main routine
|
|
| inputs a, lives
|
|
| outputs a, lives
|
|
| trashes c, z, v, n
|
|
| {
|
|
| st on, c
|
|
| sub lives, 3
|
|
| }
|
|
? UnmeaningfulOutputError: a
|
|
|
|
You can `sub` a byte memory location from another byte memory location.
|
|
This trashes `a`.
|
|
|
|
| byte lives
|
|
| byte extra
|
|
| define main routine
|
|
| inputs a, lives, extra
|
|
| outputs lives
|
|
| trashes a, c, z, v, n
|
|
| {
|
|
| st on, c
|
|
| sub lives, extra
|
|
| }
|
|
= ok
|
|
|
|
| byte lives
|
|
| byte extra
|
|
| define main routine
|
|
| inputs a, lives, extra
|
|
| outputs a, lives
|
|
| trashes c, z, v, n
|
|
| {
|
|
| st on, c
|
|
| sub lives, extra
|
|
| }
|
|
? UnmeaningfulOutputError: a
|
|
|
|
You can `sub` a word constant from a word memory location.
|
|
|
|
| word score
|
|
| define main routine
|
|
| inputs a, score
|
|
| outputs score
|
|
| trashes a, c, z, v, n
|
|
| {
|
|
| st on, c
|
|
| sub score, 1999
|
|
| }
|
|
= ok
|
|
|
|
`sub`ing a word constant from a word memory location trashes `a`.
|
|
|
|
| word score
|
|
| define main routine
|
|
| inputs a, score
|
|
| outputs score, a
|
|
| trashes c, z, v, n
|
|
| {
|
|
| st on, c
|
|
| sub score, 1999
|
|
| }
|
|
? UnmeaningfulOutputError: a
|
|
|
|
You can `sub` a word memory location from another word memory location.
|
|
|
|
| word score
|
|
| word delta
|
|
| define main routine
|
|
| inputs score, delta
|
|
| outputs score
|
|
| trashes a, c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| sub score, delta
|
|
| }
|
|
= ok
|
|
|
|
`sub`ing a word memory location from a word memory location trashes `a`.
|
|
|
|
| word score
|
|
| word delta
|
|
| define main routine
|
|
| inputs score, delta
|
|
| outputs score
|
|
| trashes c, z, v, n
|
|
| {
|
|
| st off, c
|
|
| sub score, delta
|
|
| }
|
|
? ForbiddenWriteError: a
|
|
|
|
### inc ###
|
|
|
|
Location must be initialized and writeable.
|
|
|
|
| define main routine
|
|
| outputs x
|
|
| trashes z, n
|
|
| {
|
|
| inc x
|
|
| }
|
|
? UnmeaningfulReadError: x
|
|
|
|
| define main routine
|
|
| inputs x
|
|
| trashes z, n
|
|
| {
|
|
| inc x
|
|
| }
|
|
? ForbiddenWriteError: x
|
|
|
|
| define main routine
|
|
| inputs x
|
|
| outputs x
|
|
| trashes z, n
|
|
| {
|
|
| inc x
|
|
| }
|
|
= ok
|
|
|
|
Can't `inc` a `word` type.
|
|
|
|
| word foo
|
|
|
|
|
| define main routine
|
|
| inputs foo
|
|
| outputs foo
|
|
| trashes z, n
|
|
| {
|
|
| inc foo
|
|
| }
|
|
? TypeMismatchError: foo
|
|
|
|
### dec ###
|
|
|
|
Location must be initialized and writeable.
|
|
|
|
| define main routine
|
|
| outputs x
|
|
| trashes z, n
|
|
| {
|
|
| dec x
|
|
| }
|
|
? UnmeaningfulReadError: x
|
|
|
|
| define main routine
|
|
| inputs x
|
|
| trashes z, n
|
|
| {
|
|
| dec x
|
|
| }
|
|
? ForbiddenWriteError: x
|
|
|
|
| define main routine
|
|
| inputs x
|
|
| outputs x
|
|
| trashes z, n
|
|
| {
|
|
| dec x
|
|
| }
|
|
= ok
|
|
|
|
Can't `dec` a `word` type.
|
|
|
|
| word foo
|
|
|
|
|
| define main routine
|
|
| inputs foo
|
|
| outputs foo
|
|
| trashes z, n
|
|
| {
|
|
| dec foo
|
|
| }
|
|
? TypeMismatchError: foo
|
|
|
|
### cmp ###
|
|
|
|
Some rudimentary tests for `cmp`.
|
|
|
|
| define main routine
|
|
| inputs a
|
|
| trashes z, c, n
|
|
| {
|
|
| cmp a, 4
|
|
| }
|
|
= ok
|
|
|
|
| define main routine
|
|
| inputs a
|
|
| trashes z, n
|
|
| {
|
|
| cmp a, 4
|
|
| }
|
|
? ForbiddenWriteError: c
|
|
|
|
| define main routine
|
|
| trashes z, c, n
|
|
| {
|
|
| cmp a, 4
|
|
| }
|
|
? UnmeaningfulReadError: a
|
|
|
|
`cmp` can work on words. In this case, it trashes `a`.
|
|
|
|
| word za
|
|
| word zb
|
|
|
|
|
| define main routine
|
|
| inputs za, zb
|
|
| trashes a, z, c, n
|
|
| {
|
|
| cmp za, zb
|
|
| }
|
|
= ok
|
|
|
|
| word za
|
|
| word zb
|
|
|
|
|
| define main routine
|
|
| inputs za, zb
|
|
| trashes a, z, n
|
|
| {
|
|
| cmp za, zb
|
|
| }
|
|
? ForbiddenWriteError: c
|
|
|
|
| word za
|
|
| word zb
|
|
|
|
|
| define main routine
|
|
| inputs za, zb
|
|
| trashes z, c, n
|
|
| {
|
|
| cmp za, zb
|
|
| }
|
|
? ForbiddenWriteError: a
|
|
|
|
| word za
|
|
| word zb
|
|
|
|
|
| define main routine
|
|
| inputs za
|
|
| trashes z, c, n
|
|
| {
|
|
| cmp za, zb
|
|
| }
|
|
? UnmeaningfulReadError: zb
|
|
|
|
`cmp` can compare against a literal word.
|
|
|
|
| word za
|
|
|
|
|
| define main routine
|
|
| inputs za
|
|
| trashes a, z, c, n
|
|
| {
|
|
| cmp za, 4000
|
|
| }
|
|
= ok
|
|
|
|
| word za
|
|
|
|
|
| define main routine
|
|
| inputs za
|
|
| trashes z, c, n
|
|
| {
|
|
| cmp za, 4000
|
|
| }
|
|
? ForbiddenWriteError: a
|
|
|
|
### and ###
|
|
|
|
Some rudimentary tests for `and`.
|
|
|
|
| define main routine
|
|
| inputs a
|
|
| outputs a, z, n
|
|
| {
|
|
| and a, 4
|
|
| }
|
|
= ok
|
|
|
|
| define main routine
|
|
| inputs a
|
|
| trashes z, n
|
|
| {
|
|
| and a, 4
|
|
| }
|
|
? ForbiddenWriteError: a
|
|
|
|
| define main routine
|
|
| trashes z, n
|
|
| {
|
|
| and a, 4
|
|
| }
|
|
? UnmeaningfulReadError: a
|
|
|
|
### or ###
|
|
|
|
Some rudimentary tests for `or`.
|
|
|
|
| define main routine
|
|
| inputs a
|
|
| outputs a, z, n
|
|
| {
|
|
| or a, 4
|
|
| }
|
|
= ok
|
|
|
|
| define main routine
|
|
| inputs a
|
|
| trashes z, n
|
|
| {
|
|
| or a, 4
|
|
| }
|
|
? ForbiddenWriteError: a
|
|
|
|
| define main routine
|
|
| trashes z, n
|
|
| {
|
|
| or a, 4
|
|
| }
|
|
? UnmeaningfulReadError: a
|
|
|
|
### xor ###
|
|
|
|
Some rudimentary tests for `xor`.
|
|
|
|
| define main routine
|
|
| inputs a
|
|
| outputs a, z, n
|
|
| {
|
|
| xor a, 4
|
|
| }
|
|
= ok
|
|
|
|
| define main routine
|
|
| inputs a
|
|
| trashes z, n
|
|
| {
|
|
| xor a, 4
|
|
| }
|
|
? ForbiddenWriteError: a
|
|
|
|
| define main routine
|
|
| trashes z, n
|
|
| {
|
|
| xor a, 4
|
|
| }
|
|
? UnmeaningfulReadError: a
|
|
|
|
### shl ###
|
|
|
|
Some rudimentary tests for `shl`.
|
|
|
|
| byte foo
|
|
| define main routine
|
|
| inputs foo, a, c
|
|
| outputs foo, a, c, z, n
|
|
| {
|
|
| shl a
|
|
| shl foo
|
|
| }
|
|
= ok
|
|
|
|
| define main routine
|
|
| inputs a, c
|
|
| outputs c, z, n
|
|
| {
|
|
| shl a
|
|
| }
|
|
? ForbiddenWriteError: a
|
|
|
|
| define main routine
|
|
| inputs a
|
|
| outputs a, c, z, n
|
|
| {
|
|
| shl a
|
|
| }
|
|
? UnmeaningfulReadError: c
|
|
|
|
### shr ###
|
|
|
|
Some rudimentary tests for `shr`.
|
|
|
|
| byte foo
|
|
| define main routine
|
|
| inputs foo, a, c
|
|
| outputs foo, a, c, z, n
|
|
| {
|
|
| shr a
|
|
| shr foo
|
|
| }
|
|
= ok
|
|
|
|
| define main routine
|
|
| inputs a, c
|
|
| outputs c, z, n
|
|
| {
|
|
| shr a
|
|
| }
|
|
? ForbiddenWriteError: a
|
|
|
|
| define main routine
|
|
| inputs a
|
|
| outputs a, c, z, n
|
|
| {
|
|
| shr a
|
|
| }
|
|
? UnmeaningfulReadError: c
|
|
|
|
### nop ###
|
|
|
|
Some rudimentary tests for `nop`.
|
|
|
|
| define main routine
|
|
| {
|
|
| nop
|
|
| }
|
|
= ok
|
|
|
|
### with interrupts ###
|
|
|
|
| vector routine
|
|
| inputs x
|
|
| outputs x
|
|
| trashes z, n
|
|
| bar
|
|
|
|
|
| define foo routine
|
|
| inputs x
|
|
| outputs x
|
|
| trashes z, n
|
|
| {
|
|
| inc x
|
|
| }
|
|
|
|
|
| define main routine
|
|
| outputs bar
|
|
| trashes a, n, z
|
|
| {
|
|
| with interrupts off {
|
|
| copy foo, bar
|
|
| }
|
|
| }
|
|
= ok
|
|
|
|
A `goto` cannot appear within a `with interrupts` block.
|
|
|
|
| vector routine
|
|
| inputs x
|
|
| outputs x
|
|
| trashes z, n
|
|
| bar
|
|
|
|
|
| define foo routine
|
|
| inputs x
|
|
| outputs x
|
|
| trashes z, n
|
|
| {
|
|
| inc x
|
|
| }
|
|
|
|
|
| define other routine
|
|
| trashes bar, a, n, z
|
|
| {
|
|
| ld a, 0
|
|
| }
|
|
|
|
|
| define main routine
|
|
| trashes bar, a, n, z
|
|
| {
|
|
| with interrupts off {
|
|
| copy foo, bar
|
|
| goto other
|
|
| }
|
|
| }
|
|
? IllegalJumpError
|
|
|
|
A `call` cannot appear within a `with interrupts` block.
|
|
|
|
| vector routine
|
|
| inputs x
|
|
| outputs x
|
|
| trashes z, n
|
|
| bar
|
|
|
|
|
| define foo routine
|
|
| inputs x
|
|
| outputs x
|
|
| trashes z, n
|
|
| {
|
|
| inc x
|
|
| }
|
|
|
|
|
| define other routine
|
|
| trashes bar, a, n, z
|
|
| {
|
|
| ld a, 0
|
|
| }
|
|
|
|
|
| define main routine
|
|
| trashes bar, a, n, z
|
|
| {
|
|
| with interrupts off {
|
|
| copy foo, bar
|
|
| call other
|
|
| }
|
|
| }
|
|
? IllegalJumpError
|
|
|
|
A `with interrupts` block cannot appear within a `with interrupts` block.
|
|
|
|
| vector routine
|
|
| inputs x
|
|
| outputs x
|
|
| trashes z, n
|
|
| bar
|
|
|
|
|
| define foo routine
|
|
| inputs x
|
|
| outputs x
|
|
| trashes z, n
|
|
| {
|
|
| inc x
|
|
| }
|
|
|
|
|
| define main routine
|
|
| trashes bar, a, n, z
|
|
| {
|
|
| with interrupts off {
|
|
| copy foo, bar
|
|
| with interrupts off {
|
|
| copy foo, bar
|
|
| }
|
|
| }
|
|
| }
|
|
? IllegalJumpError
|
|
|
|
### typedef ###
|
|
|
|
A typedef is a more-readable alias for a type. "Alias" means
|
|
that types have structural equivalence, not name equivalence.
|
|
|
|
| typedef routine
|
|
| inputs x
|
|
| outputs x
|
|
| trashes z, n
|
|
| routine_type
|
|
|
|
|
| vector routine_type vec
|
|
|
|
|
| define foo routine
|
|
| inputs x
|
|
| outputs x
|
|
| trashes z, n
|
|
| {
|
|
| inc x
|
|
| }
|
|
|
|
|
| define main routine
|
|
| outputs vec
|
|
| trashes a, z, n
|
|
| {
|
|
| copy foo, vec
|
|
| }
|
|
= ok
|
|
|
|
The new style routine definitions support typedefs.
|
|
|
|
| typedef routine
|
|
| inputs x
|
|
| outputs x
|
|
| trashes z, n
|
|
| routine_type
|
|
|
|
|
| vector routine_type vec
|
|
|
|
|
| define foo routine_type
|
|
| {
|
|
| inc x
|
|
| }
|
|
|
|
|
| define main routine
|
|
| outputs vec
|
|
| trashes a, z, n
|
|
| {
|
|
| copy foo, vec
|
|
| }
|
|
= ok
|