| # Assertions |
| |
| Assertions are statements that introduce new compile-time |
| [facts](/doc/note/facts.md). They are not comments, as removing them can |
| prevent the code from compiling, but unlike other programming languages, Wuffs' |
| assertions have no run-time effect at all, not even in a "debug, not release" |
| configuration. Compiling an assert will fail unless it can be proven. |
| |
| The basic form is `assert some_boolean_expression`, which creates |
| `some_boolean_expression` as a fact. That expression must be free of |
| side-effects: any function calls within must be [pure](/doc/note/effects.md). |
| |
| Arithmetic inside assertions is performed in ideal integer math, working in the |
| integer ring ℤ. An expression like `x + y` in an assertion never overflows, |
| even if `x` and `y` have a realized (non-ideal) integer type like `u32`. |
| |
| Some assertions can be proven by the compiler with no further guidance. For |
| example, if `x == 1` is already a fact, then `x < 5` can be automatically |
| proved. Adding a seemingly redundant fact can be useful when reconciling |
| multiple arms of an if-else chain, as |
| [reconciliation](/doc/note/facts.md#situations-and-reconciliation) requires the |
| facts in each arm's final situation to match exactly: |
| |
| ``` |
| if x < 5 { |
| // No further action is required. "x < 5" is a fact in the 'if' arm. |
| |
| } else { |
| x = 1 |
| // At this point, "x == 1" is a fact, but "x < 5" is not. |
| |
| // This assertion creates the "x < 5" fact. |
| assert x < 5 |
| } |
| |
| // Here, "x < 5" is still a fact, since the exact boolean expression "x < 5" |
| // was a fact at the end of every arm of the if-else chain. |
| ``` |
| |
| TODO: specify what can be proved automatically, without naming an axiom. |
| |
| |
| ## Axioms |
| |
| Wuffs' assertion system is a proof checker, not an SMT solver or automated |
| theorem prover. It verifies explicit proof targets instead of the more |
| open-ended task of searching for implicit ones. This involves more explicit |
| work by the programmer, but compile times matter, so the Wuffs compiler is fast |
| (and dumb) instead of smart (and slow). |
| |
| The Wuffs syntax is regular (and unlike C++, does not require a symbol table to |
| parse), so it should be straightforward to transform Wuffs code to and from |
| file formats used by more sophisticated proof engines. Nonetheless, that is out |
| of scope of this respository and the Wuffs compiler per se. |
| |
| Again for compilation speed, not every inference rule is applied after every |
| line of code. Some assertions require explicit guidance, naming the rule that |
| proves the assertion. These names are simply strings that resemble mathematical |
| statements. They are axiomatic, in that these rules are assumed, not proved, by |
| the Wuffs toolchain. They are typically at a higher level than e.g. Peano |
| axioms, as Wuffs emphasizes practicality over theoretical minimalism. As they |
| are axiomatic, they endeavour to only encode 'obvious' mathematical rules. |
| |
| For example, the axiom named `"a < b: a < c; c <= b"` is about transitivity: |
| the assertion `a < b` is proved if both `a < c` and `c <= b` are true, for some |
| (pure) expression `c`. Terms like `a`, `b` and `c` here are all integers in ℤ, |
| they do not encompass floating point concepts like negative zero, `NaN`s or |
| rounding. The axiom is invoked by extending an `assert` with the `via` keyword: |
| |
| ``` |
| assert n_bits < 12 via "a < b: a < c; c <= b"(c: width) |
| ``` |
| |
| This proves `n_bits < 12` by applying that transitivity axiom, where `a` is |
| `n_bits`, `b` is `12` and `c` is `width`. Compiling this assertion requires |
| proving both `n_bits < width` and `width <= 12`, from existing facts or from |
| the type system, e.g. `width` is a `base.u32[..= 12]`. |
| |
| The trailing `(c: width)` syntax is deliberately similar to a function call |
| (recall that when calling a Wuffs function, each argument must be named), but |
| the `"a < b: a < c; c <= b"` named axiom is not a function-typed expression. |
| |
| The [compiler's built-in axioms](/lang/check/axioms.md) are listed separately. |