Transformation and Verification
The ability to verify and reason about programs was one of the main goals behind the design and development of Lucid. In fact, from its very inception Lucid was intended to be not just a programming language, but also a formal system in which program specifications and correctness proofs could be expressed as well. Our goal was a formal programming system in which programs for “realistically” complicated problems could be proved correct with only a realistic amount of effort. The nonprocedural nature of Lucid and its mathematical semantics led naturally to a reasoning technique where properties proved of variables and functions (assertions) are true throughout the where clauses in which the variables and functions are defined, and are not just thought of as being true at particular points where they are “attached” (as would be the case in the usual verification technique for procedural programs). In that respect, Lucid verification is like verification of functional programs. The assertions proved for Lucid, however, have the basic simplicity of the assertions proved in the procedural case, and the proofs are very similar. We will illustrate the differences by using a very simple program for computing integer square roots. We will express it in an imperative language, in a functional language, and in Lucid and show how verification would be performed for each language using the different techniques. In all three techniques, we will use the following terminology from the procedural approach, namely that the precondition is a restriction on the inputs of a program and the postcondition is a desired property of the outputs of the program, assuming that the inputs satisfied the precondition.