Theory HOL-Hoare.Hoare_Syntax
section ‹Concrete syntax for Hoare logic, with translations for variables›
theory Hoare_Syntax
  imports Main
begin
syntax
  "_assign" :: "idt ⇒ 'b ⇒ 'com"
    (‹(‹indent notation=‹infix Hoare assignment››_ :=/ _)› [70, 65] 61)
  "_Seq" :: "'com ⇒ 'com ⇒ 'com"
    (‹(‹notation=‹infix Hoare sequential composition››_;/ _)› [61, 60] 60)
  "_Cond" :: "'bexp ⇒ 'com ⇒ 'com ⇒ 'com"
    (‹(‹notation=‹mixfix Hoare if expression››IF _/ THEN _ / ELSE _/ FI)› [0, 0, 0] 61)
  "_While" :: "'bexp ⇒ 'assn ⇒ 'var ⇒ 'com ⇒ 'com"
    (‹(‹notation=‹mixfix Hoare while expression››WHILE _/ INV {(_)} / VAR {(_)} //DO _ /OD)› [0, 0, 0, 0] 61)
text ‹The ‹VAR {_}› syntax supports two variants:
▪ ‹VAR {x = t}› where ‹t::nat› is the decreasing expression,
  the variant, and ‹x› a variable that can be referred to from inner annotations.
  The ‹x› can be necessary for nested loops, e.g. to prove that the inner loops do not mess with ‹t›.
▪ ‹VAR {t}› where the variable is omitted because it is not needed.
›
syntax
  "_While0" :: "'bexp ⇒ 'assn ⇒ 'com ⇒ 'com"
    (‹(‹indent=1 notation=‹mixfix Hoare while expression››WHILE _/ INV (‹open_block notation=‹mixfix Hoare invariant››{_}) //DO _ /OD)› [0, 0, 0] 61)
text ‹The ‹_While0› syntax is translated into the ‹_While› syntax with the trivial variant 0.
This is ok because partial correctness proofs do not make use of the variant.›
syntax
  "_hoare_vars" :: "[idts, 'assn,'com, 'assn] ⇒ bool"
    (‹(‹open_block notation=‹mixfix Hoare triple››VARS _// (‹open_block notation=‹mixfix Hoare precondition››{_}) // _ // (‹open_block notation=‹mixfix Hoare postcondition››{_}))› [0, 0, 55, 0] 50)
  "_hoare_vars_tc" :: "[idts, 'assn, 'com, 'assn] ⇒ bool"
    (‹(‹open_block notation=‹mixfix Hoare triple››VARS _// (‹open_block notation=‹mixfix Hoare precondition››[_]) // _ // (‹open_block notation=‹mixfix Hoare postcondition››[_]))› [0, 0, 55, 0] 50)
syntax (output)
  "_hoare" :: "['assn, 'com, 'assn] ⇒ bool"
    (‹(‹notation=‹mixfix Hoare triple››(‹open_block notation=‹mixfix Hoare precondition››{_})//_//(‹open_block notation=‹mixfix Hoare postcondition››{_}))› [0, 55, 0] 50)
  "_hoare_tc" :: "['assn, 'com, 'assn] ⇒ bool"
    (‹(‹notation=‹mixfix Hoare triple››(‹open_block notation=‹mixfix Hoare precondition››[_])//_//(‹open_block notation=‹mixfix Hoare postcondition››[_]))› [0, 55, 0] 50)
text ‹Completeness requires(?) the ability to refer to an outer variant in an inner invariant.
Thus we need to abstract over a variable equated with the variant, the ‹x› in ‹VAR {x = t}›.
But the ‹x› should only occur in invariants. To enforce this, syntax translations in 🗏‹hoare_syntax.ML›
separate the program from its annotations and only the latter are abstracted over over ‹x›.
(Thus ‹x› can also occur in inner variants, but that neither helps nor hurts.)›