Theory utp_state_parser
section ‹ State Variable Declaration Parser ›
theory utp_state_parser
  imports "utp_rel"
begin
text ‹ This theory sets up a parser for state blocks, as an alternative way of providing lenses to
  a predicate. A program with local variables can be represented by a predicate indexed by a tuple
  of lenses, where each lens represents a variable. These lenses must then be supplied with respect
  to a suitable state space. Instead of creating a type to represent this alphabet, we can create
  a product type for the state space, with an entry for each variable. Then each variable becomes
  a composition of the @{term fst⇩L} and @{term snd⇩L} lenses to index the correct position in the
  variable vector. 
  We first creation a vacuous definition that will mark when an indexed predicate denotes a state
  block. ›
definition state_block :: "('v ⇒ 'p) ⇒ 'v ⇒ 'p" where
[upred_defs]: "state_block f x = f x"
text ‹ We declare a number of syntax translations to produce lens and product types, to obtain
  a type for the overall state space, to construct a tuple that denotes the lens vector parameter, 
  to construct the vector itself, and finally to construct the state declaration. ›
syntax
  "_lensT" :: "type ⇒ type ⇒ type" (‹LENSTYPE'(_, _')›)
  "_pairT" :: "type ⇒ type ⇒ type" (‹PAIRTYPE'(_, _')›)
  "_state_type" :: "pttrn ⇒ type"
  "_state_tuple" :: "type ⇒ pttrn ⇒ logic"
  "_state_lenses" :: "pttrn ⇒ logic"
  "_state_decl" :: "pttrn ⇒ logic ⇒ logic" (‹LOCAL _ ∙ _› [0, 10] 10) 
syntax_types
  "_lensT" ⇌ lens and
  "_pairT" ⇌ prod
translations
  (type) "PAIRTYPE('a, 'b)" => (type) "'a × 'b"
  (type) "LENSTYPE('a, 'b)" => (type) "'a ⟹ 'b"
  "_state_type (_constrain x t)" => "t"
  "_state_type (CONST Pair (_constrain x t) vs)" => "_pairT t (_state_type vs)"
  "_state_tuple st (_constrain x t)" => "_constrain x (_lensT t st)"
  "_state_tuple st (CONST Pair (_constrain x t) vs)" =>
    "CONST Product_Type.Pair (_constrain x (_lensT t st)) (_state_tuple st vs)"
  "_state_decl vs P" =>
    "CONST state_block (_abs (_state_tuple (_state_type vs) vs) P) (_state_lenses vs)"
  "_state_decl vs P" <= "CONST state_block (_abs vs P) k"
parse_translation ‹
  let
    open HOLogic;
    val lens_comp = Const (@{const_syntax "lens_comp"}, dummyT);
    val fst_lens = Const (@{const_syntax "fst_lens"}, dummyT);
    val snd_lens = Const (@{const_syntax "snd_lens"}, dummyT);
    val id_lens = Const (@{const_syntax "id_lens"}, dummyT);
    
    fun 
      state_lenses n st = 
        if (n = 1) 
          then st
          else pair_const dummyT dummyT $ (lens_comp $ fst_lens $ st) $ (state_lenses (n - 1) (lens_comp $ snd_lens $ st));
    fun
      
      var_decl_num (Const (@{const_syntax "Product_Type.Pair"},_) $ _ $ vs) = var_decl_num vs + 1 |
      var_decl_num _ = 1;
    
    fun state_lens ctxt [vs] = state_lenses (var_decl_num vs) id_lens ;
  in
  [("_state_lenses", state_lens)]
  end
›
subsection ‹ Examples ›
term  "LOCAL (x::int, y::real, z::int) ∙ x := (&x + &z)"
lemma "LOCAL p ∙ II = II"
  by (rel_auto)
end