2015-10-16 08:38:38 +00:00
|
|
|
|
SixtyPical Analysis
|
2015-10-16 08:30:24 +00:00
|
|
|
|
===================
|
|
|
|
|
|
2015-10-16 08:38:38 +00:00
|
|
|
|
This is a test suite, written in [Falderal][] format, for the SixtyPical
|
2015-10-16 08:30:24 +00:00
|
|
|
|
static analysis rules.
|
|
|
|
|
|
|
|
|
|
[Falderal]: http://catseye.tc/node/Falderal
|
|
|
|
|
|
2015-10-16 08:38:38 +00:00
|
|
|
|
-> Functionality "Analyze SixtyPical program" is implemented by
|
2015-10-18 16:23:01 +00:00
|
|
|
|
-> shell command "bin/sixtypical --analyze --traceback %(test-body-file) && echo ok"
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
2015-10-16 08:38:38 +00:00
|
|
|
|
-> Tests for functionality "Analyze SixtyPical program"
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
|
|
|
|
### Rudiments ###
|
|
|
|
|
|
|
|
|
|
Routines must declare their inputs, outputs, and memory locations they trash.
|
|
|
|
|
|
|
|
|
|
| routine up
|
|
|
|
|
| inputs a
|
|
|
|
|
| outputs a
|
|
|
|
|
| trashes c, z, v, n
|
|
|
|
|
| {
|
|
|
|
|
| st off, c
|
|
|
|
|
| add a, 1
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
Routines may not declare a memory location to be both an output and trashed.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs a
|
|
|
|
|
| trashes a
|
|
|
|
|
| {
|
|
|
|
|
| ld a, 0
|
|
|
|
|
| }
|
2015-10-22 08:48:26 +00:00
|
|
|
|
? InconsistentConstraintsError: a
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
|
|
|
|
If a routine declares it outputs a location, that location should be initialized.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs a, x, z, n
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| }
|
2015-10-22 08:48:26 +00:00
|
|
|
|
? UnmeaningfulOutputError: a in main
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| outputs a
|
|
|
|
|
| {
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
If a routine declares it outputs a location, that location may or may not have
|
|
|
|
|
been initialized. Trashing is mainly a signal to the caller.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| trashes x, z, n
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| trashes x, z, n
|
|
|
|
|
| {
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
If a routine modifies a location, it needs to either output it or trash it.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? ForbiddenWriteError: x in main
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs x, z, n
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| trashes x, z, n
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
### ld ###
|
|
|
|
|
|
|
|
|
|
Can't `ld` from a memory location that isn't initialized.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a, x
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| ld a, x
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| trashes a
|
|
|
|
|
| {
|
|
|
|
|
| ld a, x
|
|
|
|
|
| }
|
2015-10-22 08:48:26 +00:00
|
|
|
|
? UnmeaningfulReadError: x in main
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
|
|
|
|
Can't `ld` to a memory location that doesn't appear in (outputs ∪ trashes).
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| ld a, 0
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs a
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| ld a, 0
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs z, n
|
|
|
|
|
| trashes a
|
|
|
|
|
| {
|
|
|
|
|
| ld a, 0
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| ld a, 0
|
|
|
|
|
| }
|
2015-10-22 08:48:26 +00:00
|
|
|
|
? ForbiddenWriteError: a in main
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| trashes a, n
|
|
|
|
|
| {
|
|
|
|
|
| ld a, 0
|
|
|
|
|
| }
|
2015-10-22 08:48:26 +00:00
|
|
|
|
? ForbiddenWriteError: z in main
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
2016-06-16 16:08:57 +00:00
|
|
|
|
Can't `ld` a `word` type.
|
|
|
|
|
|
|
|
|
|
| word foo
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs foo
|
|
|
|
|
| trashes a, n, z
|
|
|
|
|
| {
|
|
|
|
|
| ld a, foo
|
|
|
|
|
| }
|
|
|
|
|
? TypeMismatchError: foo and a in main
|
|
|
|
|
|
2015-10-16 08:30:24 +00:00
|
|
|
|
### st ###
|
|
|
|
|
|
|
|
|
|
Can't `st` from a memory location that isn't initialized.
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs x
|
|
|
|
|
| trashes lives
|
|
|
|
|
| {
|
|
|
|
|
| st x, lives
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| trashes x, lives
|
|
|
|
|
| {
|
|
|
|
|
| st x, lives
|
|
|
|
|
| }
|
2015-10-22 08:48:26 +00:00
|
|
|
|
? UnmeaningfulReadError: x in main
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
|
|
|
|
Can't `st` to a memory location that doesn't appear in (outputs ∪ trashes).
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| trashes lives
|
|
|
|
|
| {
|
|
|
|
|
| st 0, lives
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs lives
|
|
|
|
|
| {
|
|
|
|
|
| st 0, lives
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs lives
|
|
|
|
|
| {
|
|
|
|
|
| st 0, lives
|
|
|
|
|
| }
|
2015-10-22 08:48:26 +00:00
|
|
|
|
? ForbiddenWriteError: lives in main
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
2015-10-18 17:12:47 +00:00
|
|
|
|
Storing to a table, you must use an index, and vice-versa.
|
|
|
|
|
|
|
|
|
|
| byte one
|
|
|
|
|
| byte table many
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs one
|
|
|
|
|
| trashes a, x, n, z
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| ld a, 0
|
|
|
|
|
| st a, one
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| byte one
|
|
|
|
|
| byte table many
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs many
|
|
|
|
|
| trashes a, x, n, z
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| ld a, 0
|
|
|
|
|
| st a, many
|
|
|
|
|
| }
|
|
|
|
|
? TypeMismatchError
|
|
|
|
|
|
|
|
|
|
| byte one
|
|
|
|
|
| byte table many
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs one
|
|
|
|
|
| trashes a, x, n, z
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| ld a, 0
|
|
|
|
|
| st a, one + x
|
|
|
|
|
| }
|
|
|
|
|
? TypeMismatchError
|
|
|
|
|
|
|
|
|
|
| byte one
|
|
|
|
|
| byte table many
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs many
|
|
|
|
|
| trashes a, x, n, z
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| ld a, 0
|
|
|
|
|
| st a, many + x
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
Reading from a table, you must use an index, and vice-versa.
|
|
|
|
|
|
|
|
|
|
| byte one
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs one
|
|
|
|
|
| trashes a, x, n, z
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| st x, one
|
|
|
|
|
| ld a, one
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| byte one
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs one
|
|
|
|
|
| trashes a, x, n, z
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| st x, one
|
|
|
|
|
| ld a, one + x
|
|
|
|
|
| }
|
|
|
|
|
? TypeMismatchError
|
|
|
|
|
|
|
|
|
|
| byte table many
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs many
|
|
|
|
|
| trashes a, x, n, z
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| ld a, 0
|
|
|
|
|
| st a, many + x
|
|
|
|
|
| ld a, many
|
|
|
|
|
| }
|
|
|
|
|
? TypeMismatchError
|
|
|
|
|
|
|
|
|
|
| byte table many
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs many
|
|
|
|
|
| trashes a, x, n, z
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| ld a, 0
|
|
|
|
|
| st a, many + x
|
|
|
|
|
| ld a, many + x
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
2016-06-16 16:08:57 +00:00
|
|
|
|
Can't `st` a `word` type.
|
|
|
|
|
|
|
|
|
|
| word foo
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs foo
|
|
|
|
|
| trashes a, n, z
|
|
|
|
|
| {
|
|
|
|
|
| ld a, 0
|
|
|
|
|
| st a, foo
|
|
|
|
|
| }
|
|
|
|
|
? TypeMismatchError: a and foo in main
|
|
|
|
|
|
2015-10-16 08:30:24 +00:00
|
|
|
|
### add ###
|
|
|
|
|
|
|
|
|
|
Can't `add` from or to a memory location that isn't initialized.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| outputs a
|
|
|
|
|
| trashes c, z, v, n
|
|
|
|
|
| {
|
|
|
|
|
| st off, c
|
|
|
|
|
| add a, 0
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| outputs a
|
|
|
|
|
| trashes c, z, v, n
|
|
|
|
|
| {
|
|
|
|
|
| st off, c
|
|
|
|
|
| add a, lives
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: lives in main
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs lives
|
|
|
|
|
| outputs a
|
|
|
|
|
| trashes c, z, v, n
|
|
|
|
|
| {
|
|
|
|
|
| st off, c
|
|
|
|
|
| add a, lives
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: a in main
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
|
|
|
|
Can't `add` to a memory location that isn't writeable.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| trashes c
|
|
|
|
|
| {
|
|
|
|
|
| st off, c
|
|
|
|
|
| add a, 0
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? ForbiddenWriteError: a in main
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
2015-10-16 18:15:01 +00:00
|
|
|
|
### sub ###
|
|
|
|
|
|
|
|
|
|
Can't `sub` from or to a memory location that isn't initialized.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| outputs a
|
|
|
|
|
| trashes c, z, v, n
|
|
|
|
|
| {
|
|
|
|
|
| st off, c
|
|
|
|
|
| sub a, 0
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| outputs a
|
|
|
|
|
| trashes c, z, v, n
|
|
|
|
|
| {
|
|
|
|
|
| st off, c
|
|
|
|
|
| sub a, lives
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: lives in main
|
2015-10-16 18:15:01 +00:00
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs lives
|
|
|
|
|
| outputs a
|
|
|
|
|
| trashes c, z, v, n
|
|
|
|
|
| {
|
|
|
|
|
| st off, c
|
|
|
|
|
| sub a, lives
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: a in main
|
2015-10-16 18:15:01 +00:00
|
|
|
|
|
|
|
|
|
Can't `sub` to a memory location that isn't writeable.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| trashes c
|
|
|
|
|
| {
|
|
|
|
|
| st off, c
|
|
|
|
|
| sub a, 0
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? ForbiddenWriteError: a in main
|
2015-10-16 18:15:01 +00:00
|
|
|
|
|
|
|
|
|
### inc ###
|
|
|
|
|
|
|
|
|
|
Location must be initialized and writeable.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| inc x
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: x in main
|
2015-10-16 18:15:01 +00:00
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| inc x
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? ForbiddenWriteError: x in main
|
2015-10-16 18:15:01 +00:00
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs x
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| inc x
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
2016-06-16 16:08:57 +00:00
|
|
|
|
Can't `inc` a `word` type.
|
|
|
|
|
|
|
|
|
|
| word foo
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs foo
|
|
|
|
|
| outputs foo
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| inc foo
|
|
|
|
|
| }
|
|
|
|
|
? TypeMismatchError: foo in main
|
|
|
|
|
|
2015-10-16 18:15:01 +00:00
|
|
|
|
### dec ###
|
|
|
|
|
|
|
|
|
|
Location must be initialized and writeable.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| dec x
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: x in main
|
2015-10-16 18:15:01 +00:00
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| dec x
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? ForbiddenWriteError: x in main
|
2015-10-16 18:15:01 +00:00
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs x
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| dec x
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
2016-06-16 16:08:57 +00:00
|
|
|
|
Can't `dec` a `word` type.
|
|
|
|
|
|
|
|
|
|
| word foo
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs foo
|
|
|
|
|
| outputs foo
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| dec foo
|
|
|
|
|
| }
|
|
|
|
|
? TypeMismatchError: foo in main
|
|
|
|
|
|
2015-10-16 18:15:01 +00:00
|
|
|
|
### cmp ###
|
|
|
|
|
|
2015-10-16 18:32:18 +00:00
|
|
|
|
Some rudimentary tests for cmp.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| trashes z, c, n
|
|
|
|
|
| {
|
|
|
|
|
| cmp a, 4
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| cmp a, 4
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? ForbiddenWriteError: c in main
|
2015-10-16 18:32:18 +00:00
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| trashes z, c, n
|
|
|
|
|
| {
|
|
|
|
|
| cmp a, 4
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: a in main
|
2015-10-16 18:15:01 +00:00
|
|
|
|
|
|
|
|
|
### and ###
|
|
|
|
|
|
2015-10-16 18:32:18 +00:00
|
|
|
|
Some rudimentary tests for and.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| outputs a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| and a, 4
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| and a, 4
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? ForbiddenWriteError: a in main
|
2015-10-16 18:32:18 +00:00
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| and a, 4
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: a in main
|
2015-10-16 18:15:01 +00:00
|
|
|
|
|
|
|
|
|
### or ###
|
|
|
|
|
|
2015-10-16 18:32:18 +00:00
|
|
|
|
Writing unit tests on a train. Wow.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| outputs a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| or a, 4
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| or a, 4
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? ForbiddenWriteError: a in main
|
2015-10-16 18:32:18 +00:00
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| or a, 4
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: a in main
|
2015-10-16 18:15:01 +00:00
|
|
|
|
|
|
|
|
|
### xor ###
|
|
|
|
|
|
2015-10-16 18:32:18 +00:00
|
|
|
|
Writing unit tests on a train. Wow.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| outputs a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| xor a, 4
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| xor a, 4
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? ForbiddenWriteError: a in main
|
2015-10-16 18:32:18 +00:00
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| xor a, 4
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: a in main
|
2015-10-16 18:15:01 +00:00
|
|
|
|
|
|
|
|
|
### shl ###
|
|
|
|
|
|
2015-10-16 18:32:18 +00:00
|
|
|
|
Some rudimentary tests for shl.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a, c
|
|
|
|
|
| outputs a, c, z, n
|
|
|
|
|
| {
|
|
|
|
|
| shl a
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a, c
|
|
|
|
|
| outputs c, z, n
|
|
|
|
|
| {
|
|
|
|
|
| shl a
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? ForbiddenWriteError: a in main
|
2015-10-16 18:32:18 +00:00
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| outputs a, c, z, n
|
|
|
|
|
| {
|
|
|
|
|
| shl a
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: c in main
|
2015-10-16 18:15:01 +00:00
|
|
|
|
|
|
|
|
|
### shr ###
|
|
|
|
|
|
2015-10-16 18:32:18 +00:00
|
|
|
|
Some rudimentary tests for shr.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a, c
|
|
|
|
|
| outputs a, c, z, n
|
|
|
|
|
| {
|
|
|
|
|
| shr a
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a, c
|
|
|
|
|
| outputs c, z, n
|
|
|
|
|
| {
|
|
|
|
|
| shr a
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? ForbiddenWriteError: a in main
|
2015-10-16 18:32:18 +00:00
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs a
|
|
|
|
|
| outputs a, c, z, n
|
|
|
|
|
| {
|
|
|
|
|
| shr a
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: c in main
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
|
|
|
|
### call ###
|
|
|
|
|
|
|
|
|
|
When calling a routine, all of the locations it lists as inputs must be
|
|
|
|
|
initialized.
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| inputs x
|
|
|
|
|
| trashes lives
|
|
|
|
|
| {
|
|
|
|
|
| st x, lives
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| {
|
|
|
|
|
| call foo
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: x in main
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
|
|
|
|
Note that if you call a routine that trashes a location, you also trash it.
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| inputs x
|
|
|
|
|
| trashes lives
|
|
|
|
|
| {
|
|
|
|
|
| st x, lives
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs x, z, n
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| call foo
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? ForbiddenWriteError: lives in main
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| inputs x
|
|
|
|
|
| trashes lives
|
|
|
|
|
| {
|
|
|
|
|
| st x, lives
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs x, z, n
|
|
|
|
|
| trashes lives
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| call foo
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
You can't output a value that the thing you called trashed.
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| inputs x
|
|
|
|
|
| trashes lives
|
|
|
|
|
| {
|
|
|
|
|
| st x, lives
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs x, z, n, lives
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| call foo
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulOutputError: lives in main
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
|
|
|
|
...unless you write to it yourself afterwards.
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| inputs x
|
|
|
|
|
| trashes lives
|
|
|
|
|
| {
|
|
|
|
|
| st x, lives
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs x, z, n, lives
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| call foo
|
|
|
|
|
| st x, lives
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
If a routine declares outputs, they are initialized in the caller after
|
|
|
|
|
calling it.
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| outputs x, z, n
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs a
|
|
|
|
|
| trashes x, z, n
|
|
|
|
|
| {
|
|
|
|
|
| call foo
|
|
|
|
|
| ld a, x
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| {
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs a
|
|
|
|
|
| trashes x
|
|
|
|
|
| {
|
|
|
|
|
| call foo
|
|
|
|
|
| ld a, x
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: x in main
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
|
|
|
|
If a routine trashes locations, they are uninitialized in the caller after
|
|
|
|
|
calling it.
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| trashes x, z, n
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| trashes x, z, n
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs a
|
|
|
|
|
| trashes x, z, n
|
|
|
|
|
| {
|
|
|
|
|
| call foo
|
|
|
|
|
| ld a, x
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: x in main
|
2015-10-16 08:30:24 +00:00
|
|
|
|
|
2015-10-17 13:54:28 +00:00
|
|
|
|
Calling an extern is just the same as calling a defined routine with the
|
|
|
|
|
same constraints.
|
|
|
|
|
|
|
|
|
|
| routine chrout
|
|
|
|
|
| inputs a
|
|
|
|
|
| trashes a
|
|
|
|
|
| @ 65490
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| ld a, 65
|
|
|
|
|
| call chrout
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine chrout
|
|
|
|
|
| inputs a
|
|
|
|
|
| trashes a
|
|
|
|
|
| @ 65490
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| call chrout
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: a in main
|
2015-10-17 13:54:28 +00:00
|
|
|
|
|
|
|
|
|
| routine chrout
|
|
|
|
|
| inputs a
|
|
|
|
|
| trashes a
|
|
|
|
|
| @ 65490
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| trashes a, x, z, n
|
|
|
|
|
| {
|
|
|
|
|
| ld a, 65
|
|
|
|
|
| call chrout
|
|
|
|
|
| ld x, a
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: a in main
|
2015-10-17 13:54:28 +00:00
|
|
|
|
|
2015-10-16 08:30:24 +00:00
|
|
|
|
### if ###
|
|
|
|
|
|
|
|
|
|
Both blocks of an `if` are analyzed.
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| inputs a
|
2015-10-16 08:38:38 +00:00
|
|
|
|
| outputs x
|
|
|
|
|
| trashes a, z, n, c
|
2015-10-16 08:30:24 +00:00
|
|
|
|
| {
|
|
|
|
|
| cmp a, 42
|
|
|
|
|
| if z {
|
2015-10-16 08:38:38 +00:00
|
|
|
|
| ld x, 7
|
2015-10-16 08:30:24 +00:00
|
|
|
|
| } else {
|
2015-10-16 08:38:38 +00:00
|
|
|
|
| ld x, 23
|
2015-10-16 08:30:24 +00:00
|
|
|
|
| }
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
2015-10-16 13:01:45 +00:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
2015-10-18 14:32:28 +00:00
|
|
|
|
| routine foo
|
|
|
|
|
| inputs a
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes a, z, n, c
|
|
|
|
|
| {
|
|
|
|
|
| cmp a, 42
|
|
|
|
|
| if not z {
|
|
|
|
|
| ld a, 6
|
|
|
|
|
| } else {
|
|
|
|
|
| ld x, 7
|
|
|
|
|
| }
|
|
|
|
|
| }
|
|
|
|
|
? InconsistentInitializationError: x
|
|
|
|
|
|
2015-10-16 13:01:45 +00:00
|
|
|
|
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
|
2015-10-18 12:37:35 +00:00
|
|
|
|
|
2015-10-18 14:32:28 +00:00
|
|
|
|
| routine foo
|
|
|
|
|
| inputs a
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes a, z, n, c
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| cmp a, 42
|
|
|
|
|
| if not z {
|
|
|
|
|
| ld x, 7
|
|
|
|
|
| }
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
2015-10-18 12:37:35 +00:00
|
|
|
|
### repeat ###
|
|
|
|
|
|
|
|
|
|
Repeat loop.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs x, y, n, z, c
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| ld y, 15
|
|
|
|
|
| repeat {
|
|
|
|
|
| inc x
|
|
|
|
|
| inc y
|
|
|
|
|
| cmp x, 10
|
|
|
|
|
| } until z
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
You can initialize something inside the loop that was uninitialized outside.
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs x, y, n, z, c
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| repeat {
|
|
|
|
|
| ld y, 15
|
|
|
|
|
| inc x
|
|
|
|
|
| cmp x, 10
|
|
|
|
|
| } until z
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
But you can't UNinitialize something at the end of the loop that you need
|
|
|
|
|
initialized at the start.
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| trashes y
|
|
|
|
|
| {
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs x, y, n, z, c
|
|
|
|
|
| {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| ld y, 15
|
|
|
|
|
| repeat {
|
|
|
|
|
| inc x
|
|
|
|
|
| inc y
|
|
|
|
|
| call foo
|
|
|
|
|
| cmp x, 10
|
|
|
|
|
| } until z
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: y in main
|
2015-10-18 19:16:14 +00:00
|
|
|
|
|
2017-11-20 16:39:39 +00:00
|
|
|
|
And if you trash the test expression (i.e. `z` in the below) inside the loop,
|
|
|
|
|
this is an error too.
|
|
|
|
|
|
|
|
|
|
| word one : 0
|
|
|
|
|
| word two : 0
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs one, two
|
|
|
|
|
| outputs two
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| repeat {
|
|
|
|
|
| copy one, two
|
|
|
|
|
| } until z
|
|
|
|
|
| }
|
|
|
|
|
? UnmeaningfulReadError: z in main
|
|
|
|
|
|
2015-10-18 19:16:14 +00:00
|
|
|
|
### copy ###
|
|
|
|
|
|
|
|
|
|
Can't `copy` from a memory location that isn't initialized.
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs x
|
|
|
|
|
| outputs lives
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| copy x, lives
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs lives
|
|
|
|
|
| trashes x, a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| copy x, lives
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulReadError: x in main
|
2015-10-18 19:16:14 +00:00
|
|
|
|
|
2015-10-19 12:04:08 +00:00
|
|
|
|
Can't `copy` to a memory location that doesn't appear in (outputs ∪ trashes).
|
2015-10-18 19:16:14 +00:00
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| trashes lives, a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| copy 0, lives
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs lives
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| copy 0, lives
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs lives
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| copy 0, lives
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? ForbiddenWriteError: lives in main
|
2015-10-18 19:16:14 +00:00
|
|
|
|
|
|
|
|
|
a, z, and n are trashed, and must be declared as such
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs lives
|
|
|
|
|
| {
|
|
|
|
|
| copy 0, lives
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? ForbiddenWriteError: a in main
|
2015-10-18 19:16:14 +00:00
|
|
|
|
|
|
|
|
|
a, z, and n are trashed, and must not be declared as outputs.
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs lives, a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| copy 0, lives
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulOutputError: a in main
|
2015-10-19 12:04:08 +00:00
|
|
|
|
|
|
|
|
|
Unless of course you subsequently initialize them.
|
|
|
|
|
|
|
|
|
|
| byte lives
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs lives, a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| copy 0, lives
|
|
|
|
|
| ld a, 0
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
2016-06-16 16:08:57 +00:00
|
|
|
|
Can `copy` from a `byte` to a `byte`.
|
|
|
|
|
|
|
|
|
|
| byte source : 0
|
|
|
|
|
| byte dest
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs source
|
|
|
|
|
| outputs dest
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| copy source, dest
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
Can `copy` from a `word` to a `word`.
|
|
|
|
|
|
|
|
|
|
| word source : 0
|
|
|
|
|
| word dest
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs source
|
|
|
|
|
| outputs dest
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| copy source, dest
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
Can't `copy` from a `byte` to a `word`.
|
|
|
|
|
|
|
|
|
|
| byte source : 0
|
|
|
|
|
| word dest
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs source
|
|
|
|
|
| outputs dest
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| copy source, dest
|
|
|
|
|
| }
|
|
|
|
|
? TypeMismatchError
|
|
|
|
|
|
|
|
|
|
Can't `copy` from a `word` to a `byte`.
|
|
|
|
|
|
|
|
|
|
| word source : 0
|
|
|
|
|
| byte dest
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs source
|
|
|
|
|
| outputs dest
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| copy source, dest
|
|
|
|
|
| }
|
|
|
|
|
? TypeMismatchError
|
|
|
|
|
|
2017-11-24 12:35:36 +00:00
|
|
|
|
### copy[] ###
|
|
|
|
|
|
|
|
|
|
Buffers and pointers.
|
|
|
|
|
|
|
|
|
|
Note that `copy buf, ptr` should probably be `copy ^buf, ptr` and `^buf` should not
|
|
|
|
|
be considered "reading" buf and should not require it in `inputs` for that reason.
|
|
|
|
|
|
|
|
|
|
| buffer[2048] buf
|
|
|
|
|
| pointer ptr
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs buf
|
|
|
|
|
| outputs buf, y
|
|
|
|
|
| trashes a, z, n, ptr
|
|
|
|
|
| {
|
|
|
|
|
| ld y, 0
|
|
|
|
|
| copy buf, ptr
|
|
|
|
|
| copy 123, [ptr] + y
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
It does use `y`.
|
|
|
|
|
|
|
|
|
|
| buffer[2048] buf
|
|
|
|
|
| pointer ptr
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs buf
|
|
|
|
|
| outputs buf
|
|
|
|
|
| trashes a, z, n, ptr
|
|
|
|
|
| {
|
|
|
|
|
| copy buf, ptr
|
|
|
|
|
| copy 123, [ptr] + y
|
|
|
|
|
| }
|
|
|
|
|
? UnmeaningfulReadError
|
|
|
|
|
|
2016-06-16 16:08:57 +00:00
|
|
|
|
### routines ###
|
|
|
|
|
|
2015-10-22 19:01:02 +00:00
|
|
|
|
Routines are constants. You need not, and in fact cannot, specify a constant
|
|
|
|
|
as an input to, an output of, or as a trashed value of a routine.
|
2015-10-19 12:04:08 +00:00
|
|
|
|
|
|
|
|
|
| vector vec
|
|
|
|
|
| inputs x
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| inputs x
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| inc x
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| inputs foo
|
|
|
|
|
| outputs vec
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| copy foo, vec
|
|
|
|
|
| }
|
2015-10-22 19:01:02 +00:00
|
|
|
|
? ConstantConstraintError: foo in main
|
|
|
|
|
|
|
|
|
|
| vector vec
|
|
|
|
|
| inputs x
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| inputs x
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| inc x
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs vec, foo
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| copy foo, vec
|
|
|
|
|
| }
|
|
|
|
|
? ConstantConstraintError: foo in main
|
|
|
|
|
|
|
|
|
|
| vector vec
|
|
|
|
|
| inputs x
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| inputs x
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| inc x
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs vec
|
|
|
|
|
| trashes a, z, n, foo
|
|
|
|
|
| {
|
|
|
|
|
| copy foo, vec
|
|
|
|
|
| }
|
|
|
|
|
? ConstantConstraintError: foo in main
|
|
|
|
|
|
|
|
|
|
You can copy the address of a routine into a vector, if that vector is
|
|
|
|
|
declared appropriately.
|
|
|
|
|
|
|
|
|
|
| vector vec
|
|
|
|
|
| inputs x
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| inputs x
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| inc x
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs vec
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| copy foo, vec
|
|
|
|
|
| }
|
2015-10-19 12:04:08 +00:00
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
But not if the vector is declared inappropriately.
|
|
|
|
|
|
|
|
|
|
| vector vec
|
|
|
|
|
| inputs y
|
|
|
|
|
| outputs y
|
|
|
|
|
| trashes z, n
|
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| inputs x
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| inc x
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs vec
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| copy foo, vec
|
|
|
|
|
| }
|
2015-10-19 18:17:27 +00:00
|
|
|
|
? IncompatibleConstraintsError
|
|
|
|
|
|
|
|
|
|
Routines are read-only.
|
|
|
|
|
|
|
|
|
|
| vector vec
|
|
|
|
|
| inputs x
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
|
|
|
|
|
|
| routine foo
|
|
|
|
|
| inputs x
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes z, n
|
|
|
|
|
| {
|
|
|
|
|
| inc x
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main
|
|
|
|
|
| outputs vec
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
| {
|
|
|
|
|
| copy vec, foo
|
|
|
|
|
| }
|
|
|
|
|
? TypeMismatchError
|
2015-10-20 12:15:21 +00:00
|
|
|
|
|
|
|
|
|
Indirect call.
|
|
|
|
|
|
|
|
|
|
| vector foo outputs x trashes z, n
|
|
|
|
|
|
|
|
|
|
|
| routine bar outputs x trashes z, n {
|
|
|
|
|
| ld x, 200
|
|
|
|
|
| }
|
|
|
|
|
|
|
2015-10-22 19:01:02 +00:00
|
|
|
|
| routine main outputs x, foo trashes a, z, n {
|
2015-10-20 12:15:21 +00:00
|
|
|
|
| copy bar, foo
|
|
|
|
|
| call foo
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
2015-10-21 16:05:49 +00:00
|
|
|
|
Calling the vector does indeed trash the things the vector says it does.
|
2015-10-20 12:15:21 +00:00
|
|
|
|
|
|
|
|
|
| vector foo trashes x, z, n
|
|
|
|
|
|
|
|
|
|
|
| routine bar trashes x, z, n {
|
|
|
|
|
| ld x, 200
|
|
|
|
|
| }
|
|
|
|
|
|
|
2015-10-22 19:01:02 +00:00
|
|
|
|
| routine main outputs x, foo trashes z, n {
|
2015-10-20 12:15:21 +00:00
|
|
|
|
| ld x, 0
|
|
|
|
|
| copy bar, foo
|
|
|
|
|
| call foo
|
|
|
|
|
| }
|
2015-10-21 18:43:44 +00:00
|
|
|
|
? UnmeaningfulOutputError: x in main
|
2015-10-21 10:41:52 +00:00
|
|
|
|
|
2015-10-21 14:45:14 +00:00
|
|
|
|
`goto`, if present, must be in tail position (the final instruction in a routine.)
|
2015-10-21 10:41:52 +00:00
|
|
|
|
|
|
|
|
|
| routine bar trashes x, z, n {
|
|
|
|
|
| ld x, 200
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main trashes x, z, n {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| goto bar
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine bar trashes x, z, n {
|
|
|
|
|
| ld x, 200
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main trashes x, z, n {
|
|
|
|
|
| goto bar
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| }
|
|
|
|
|
? IllegalJumpError
|
|
|
|
|
|
|
|
|
|
| routine bar trashes x, z, n {
|
|
|
|
|
| ld x, 200
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main trashes x, z, n {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| if z {
|
|
|
|
|
| ld x, 1
|
|
|
|
|
| goto bar
|
|
|
|
|
| }
|
|
|
|
|
| }
|
2015-10-21 14:45:14 +00:00
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
| routine bar trashes x, z, n {
|
|
|
|
|
| ld x, 200
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main trashes x, z, n {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| if z {
|
|
|
|
|
| ld x, 1
|
|
|
|
|
| goto bar
|
|
|
|
|
| }
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| }
|
2015-10-21 10:41:52 +00:00
|
|
|
|
? IllegalJumpError
|
|
|
|
|
|
|
|
|
|
Can't `goto` a routine that outputs or trashes more than the current routine.
|
|
|
|
|
|
|
|
|
|
| routine bar trashes x, y, z, n {
|
|
|
|
|
| ld x, 200
|
|
|
|
|
| ld y, 200
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main trashes x, z, n {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| goto bar
|
|
|
|
|
| }
|
2015-10-21 14:45:14 +00:00
|
|
|
|
? IncompatibleConstraintsError
|
2015-10-21 10:41:52 +00:00
|
|
|
|
|
|
|
|
|
| routine bar outputs y trashes z, n {
|
|
|
|
|
| ld y, 200
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main trashes x, z, n {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| goto bar
|
|
|
|
|
| }
|
2015-10-21 14:45:14 +00:00
|
|
|
|
? IncompatibleConstraintsError
|
2015-10-21 16:05:49 +00:00
|
|
|
|
|
|
|
|
|
Can `goto` a routine that outputs or trashes less than the current routine.
|
|
|
|
|
|
|
|
|
|
| routine bar trashes x, z, n {
|
|
|
|
|
| ld x, 1
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine main trashes a, x, z, n {
|
|
|
|
|
| ld a, 0
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| goto bar
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
|
|
|
|
Indirect goto.
|
|
|
|
|
|
|
|
|
|
| vector foo outputs x trashes a, z, n
|
|
|
|
|
|
|
|
|
|
|
| routine bar outputs x trashes a, z, n {
|
|
|
|
|
| ld x, 200
|
|
|
|
|
| }
|
|
|
|
|
|
|
2015-10-22 19:01:02 +00:00
|
|
|
|
| routine main outputs x trashes foo, a, z, n {
|
2015-10-21 16:05:49 +00:00
|
|
|
|
| copy bar, foo
|
|
|
|
|
| goto foo
|
|
|
|
|
| }
|
|
|
|
|
= ok
|
|
|
|
|
|
2015-10-22 08:54:11 +00:00
|
|
|
|
Jumping through the vector does indeed trash, or output, the things the
|
|
|
|
|
vector says it does.
|
2015-10-21 16:05:49 +00:00
|
|
|
|
|
2015-10-22 08:54:11 +00:00
|
|
|
|
| vector foo
|
|
|
|
|
| trashes a, x, z, n
|
2015-10-22 08:48:26 +00:00
|
|
|
|
|
|
2015-10-22 08:54:11 +00:00
|
|
|
|
| routine bar
|
|
|
|
|
| trashes a, x, z, n {
|
2015-10-22 08:48:26 +00:00
|
|
|
|
| ld x, 200
|
|
|
|
|
| }
|
|
|
|
|
|
|
2015-10-22 08:54:11 +00:00
|
|
|
|
| routine sub
|
|
|
|
|
| trashes foo, a, x, z, n {
|
2015-10-22 08:48:26 +00:00
|
|
|
|
| ld x, 0
|
|
|
|
|
| copy bar, foo
|
|
|
|
|
| goto foo
|
|
|
|
|
| }
|
|
|
|
|
|
|
2015-10-22 19:01:02 +00:00
|
|
|
|
| routine main
|
2015-10-22 08:54:11 +00:00
|
|
|
|
| outputs a
|
|
|
|
|
| trashes foo, x, z, n {
|
2015-10-22 08:48:26 +00:00
|
|
|
|
| call sub
|
|
|
|
|
| ld a, x
|
|
|
|
|
| }
|
|
|
|
|
? UnmeaningfulReadError: x in main
|
2015-10-21 16:05:49 +00:00
|
|
|
|
|
2015-10-22 08:54:11 +00:00
|
|
|
|
| vector foo
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes a, z, n
|
|
|
|
|
|
|
|
|
|
|
| routine bar
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes a, z, n {
|
|
|
|
|
| ld x, 200
|
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
|
|
| routine sub
|
|
|
|
|
| outputs x
|
|
|
|
|
| trashes foo, a, z, n {
|
|
|
|
|
| ld x, 0
|
|
|
|
|
| copy bar, foo
|
|
|
|
|
| goto foo
|
|
|
|
|
| }
|
|
|
|
|
|
|
2015-10-22 19:01:02 +00:00
|
|
|
|
| routine main
|
2015-10-22 08:54:11 +00:00
|
|
|
|
| outputs a
|
|
|
|
|
| trashes foo, x, z, n {
|
|
|
|
|
| call sub
|
|
|
|
|
| ld a, x
|
|
|
|
|
| }
|
|
|
|
|
= ok
|