Static assertions
Some facts about a program are known before it runs: the value of a constant,
the size of a type. #assert checks one of them while the program is being
compiled, and refuses to build it if the fact is false.
'' #assert is checked while the program is compiled.
const SLOTS = 12
const SLOT_BYTES = 64
type Header
as uint32 magic
as uint16 version, flags
end type
#assert SLOTS mod 4 = 0 '' the table is read in fours
#assert SLOTS * SLOT_BYTES <= 1024 '' it fits in one page
#assert sizeof( Header ) = 8 '' the file format says so
print "slots:"; SLOTS; ", bytes:"; SLOTS * SLOT_BYTES
Output
slots: 12, bytes: 768
Each #assert takes an expression the compiler can evaluate: constants,
arithmetic on them, and sizeof. All three hold here, so the program builds,
and the checks leave nothing behind in it: they cost nothing at run time.
Change a constant so that one no longer holds, and the build stops at that line:
const SLOTS = 20
const SLOT_BYTES = 64
#assert SLOTS mod 4 = 0 '' holds
#assert SLOTS * SLOT_BYTES <= 1024 '' 1280: refused
print "built"
staticfail.tiko(5,1): error TKO0604: #assert condition failed
|
5 | #assert SLOTS * SLOT_BYTES <= 1024 '' 1280: refused
| ^
The message does not say why the condition matters, so put that in a comment on the same line, as these do: the comment is what the reader sees next to the error.
Use #assert for decisions made in the source that other code depends on,
such as a table size that must be a multiple of four or a record that must
match a file format byte for byte. Facts known only at run time are checked
with assert.
Activities
- Add a
uint8field toHeader. Which assertion fails? - Assert that
SLOTSis a power of two, usingand.