Theory ListSpec

theory ListSpec
imports ICF_Spec_Base
header {* \isaheader{Specification of Sequences} *}
theory ListSpec 
imports ICF_Spec_Base
begin

(*@intf List
  @abstype 'a list
  This interface specifies sequences.
*)

subsection "Definition"
locale list =
  -- "Abstraction to HOL-lists"
  fixes α :: "'s => 'x list"
  -- "Invariant"
  fixes invar :: "'s => bool"

locale list_no_invar = list +
  assumes invar[simp, intro!]: "!!l. invar l"

subsection "Functions"

locale list_empty = list +
  constrains α :: "'s => 'x list"
  fixes empty :: "unit => 's"
  assumes empty_correct:
    "α (empty ()) = []"
    "invar (empty ())"


locale list_isEmpty = list +
  constrains α :: "'s => 'x list"
  fixes isEmpty :: "'s => bool"
  assumes isEmpty_correct:
    "invar s ==> isEmpty s <-> α s = []"

locale poly_list_iteratei = list +
  constrains α :: "'s => 'x list"
begin  
  definition iteratei where
    iteratei_correct[code_unfold]: "iteratei s ≡ foldli (α s)"
  definition iterate where
    iterate_correct[code_unfold]: "iterate s ≡ foldli (α s) (λ_. True)"
end

locale poly_list_rev_iteratei = list +
  constrains α :: "'s => 'x list"
begin  
  definition rev_iteratei where
    rev_iteratei_correct[code_unfold]: "rev_iteratei s ≡ foldri (α s)"
  definition rev_iterate where
    rev_iterate_correct[code_unfold]: "rev_iterate s ≡ foldri (α s) (λ_. True)"
end

(*
locale list_iteratei = list +
  constrains α :: "'s => 'x list"
  fixes iteratei :: "'s => ('x,'σ) set_iterator"
  assumes iteratei_correct:
    "invar s ==> iteratei s = foldli (α s)"
begin
  lemma iteratei_no_sel_rule:
    "invar s ==> distinct (α s) ==> set_iterator (iteratei s) (set (α s))"
    by (simp add: iteratei_correct set_iterator_foldli_correct)
end

lemma list_iteratei_iteratei_linord_rule:
  "list_iteratei α invar iteratei ==> invar s ==> distinct (α s) ==> sorted (α s) ==>
   set_iterator_linord (iteratei s) (set (α s))"
  by (simp add: list_iteratei_def set_iterator_linord_foldli_correct)

lemma list_iteratei_iteratei_rev_linord_rule:
  "list_iteratei α invar iteratei ==> invar s ==> distinct (α s) ==> sorted (rev (α s)) ==>
   set_iterator_rev_linord (iteratei s) (set (α s))"
  by (simp add: list_iteratei_def set_iterator_rev_linord_foldli_correct)


locale list_reverse_iteratei = list +
  constrains α :: "'s => 'x list"
  fixes reverse_iteratei :: "'s => ('x,'σ) set_iterator"
  assumes reverse_iteratei_correct:
    "invar s ==> reverse_iteratei s = foldri (α s)"
begin
  lemma reverse_iteratei_no_sel_rule:
    "invar s ==> distinct (α s) ==> set_iterator (reverse_iteratei s) (set (α s))"
    by (simp add: reverse_iteratei_correct set_iterator_foldri_correct)
end

lemma list_reverse_iteratei_iteratei_linord_rule:
  "list_reverse_iteratei α invar iteratei ==> invar s ==> distinct (α s) ==> sorted (rev (α s)) ==>
   set_iterator_linord (iteratei s) (set (α s))"
  by (simp add: list_reverse_iteratei_def set_iterator_linord_foldri_correct)

lemma list_reverse_iteratei_iteratei_rev_linord_rule:
  "list_reverse_iteratei α invar iteratei ==> invar s ==> distinct (α s) ==> sorted (α s) ==>
   set_iterator_rev_linord (iteratei s) (set (α s))"
  by (simp add: list_reverse_iteratei_def set_iterator_rev_linord_foldri_correct)
*)

locale list_size = list +
  constrains α :: "'s => 'x list"
  fixes size :: "'s => nat"
  assumes size_correct:
    "invar s ==> size s = length (α s)"
  
locale list_appendl = list +
  constrains α :: "'s => 'x list"
  fixes appendl :: "'x => 's => 's"
  assumes appendl_correct:
    "invar s ==> α (appendl x s) = x#α s"
    "invar s ==> invar (appendl x s)"
begin
  abbreviation (input) "push ≡ appendl" 
  lemmas push_correct = appendl_correct
end

locale list_removel = list +
  constrains α :: "'s => 'x list"
  fixes removel :: "'s => ('x × 's)"
  assumes removel_correct:
    "[|invar s; α s ≠ []|] ==> fst (removel s) = hd (α s)"
    "[|invar s; α s ≠ []|] ==> α (snd (removel s)) = tl (α s)"
    "[|invar s; α s ≠ []|] ==> invar (snd (removel s))"
begin
  lemma removelE: 
    assumes I: "invar s" "α s ≠ []" 
    obtains s' where "removel s = (hd (α s), s')" "invar s'" "α s' = tl (α s)"
  proof -
    from removel_correct(1,2,3)[OF I] have 
      C: "fst (removel s) = hd (α s)"
         "α (snd (removel s)) = tl (α s)"
         "invar (snd (removel s))" .
    from that[of "snd (removel s)", OF _ C(3,2), folded C(1)] show thesis
      by simp
  qed


  text {* The following shortcut notations are not meant for generating efficient code,
    but solely to simplify reasoning *}
  (* TODO: Is this actually used somewhere ? *)
  (*
  definition "head s == fst (removef s)"
  definition "tail s == snd (removef s)"

  lemma tail_correct: "[|invar F; α F ≠ []|] ==> α (tail F) = tl (α F)"
    by (simp add: tail_def removef_correct)

  lemma head_correct: "[|invar F; α F ≠ []|] ==> (head F) = hd (α F)"
    by (simp add: head_def removef_correct)

  lemma removef_split: "removef F = (head F, tail F)"
    apply (cases "removef F")
    apply (simp add: head_def tail_def)
    done
    *)
      
  abbreviation (input) "pop ≡ removel"
  lemmas pop_correct = removel_correct

  abbreviation (input) "dequeue ≡ removel"
  lemmas dequeue_correct = removel_correct
end

locale list_leftmost = list +
  constrains α :: "'s => 'x list"
  fixes leftmost :: "'s => 'x"
  assumes leftmost_correct:
    "[|invar s; α s ≠ []|] ==> leftmost s = hd (α s)"
begin
  abbreviation (input) top where "top ≡ leftmost"
  lemmas top_correct = leftmost_correct
end

locale list_appendr = list +
  constrains α :: "'s => 'x list"
  fixes appendr :: "'x => 's => 's"
  assumes appendr_correct: 
    "invar s ==> α (appendr x s) = α s @ [x]"
    "invar s ==> invar (appendr x s)"
begin
  abbreviation (input) "enqueue ≡ appendr"
  lemmas enqueue_correct = appendr_correct
end

locale list_remover = list +
  constrains α :: "'s => 'x list"
  fixes remover :: "'s => 's × 'x"
  assumes remover_correct: 
    "[|invar s; α s ≠ []|] ==> α (fst (remover s)) = butlast (α s)"
    "[|invar s; α s ≠ []|] ==> snd (remover s) = last (α s)"
    "[|invar s; α s ≠ []|] ==> invar (fst (remover s))"

locale list_rightmost = list +
  constrains α :: "'s => 'x list"
  fixes rightmost :: "'s => 'x"
  assumes rightmost_correct:
    "[|invar s; α s ≠ []|] ==> rightmost s = List.last (α s)"
begin
  abbreviation (input) bot where "bot ≡ rightmost"
  lemmas bot_correct = rightmost_correct
end

subsubsection "Indexing"
locale list_get = list +
  constrains α :: "'s => 'x list"
  fixes get :: "'s => nat => 'x"
  assumes get_correct:
    "[|invar s; i<length (α s)|] ==> get s i = α s ! i"

locale list_set = list +
  constrains α :: "'s => 'x list"
  fixes set :: "'s => nat => 'x => 's"
  assumes set_correct:
    "[|invar s; i<length (α s)|] ==> α (set s i x) = α s [i := x]"
    "[|invar s; i<length (α s)|] ==> invar (set s i x)"

record ('a,'s) list_ops = 
  list_op_α :: "'s => 'a list"
  list_op_invar :: "'s => bool"
  list_op_empty :: "unit => 's"
  list_op_isEmpty :: "'s => bool"
  list_op_size :: "'s => nat"
  list_op_appendl :: "'a => 's => 's"
  list_op_removel :: "'s => 'a × 's"
  list_op_leftmost :: "'s => 'a"
  list_op_appendr :: "'a => 's => 's"
  list_op_remover :: "'s => 's × 'a"
  list_op_rightmost :: "'s => 'a"
  list_op_get :: "'s => nat => 'a"
  list_op_set :: "'s => nat => 'a => 's"

locale StdListDefs = 
  poly_list_iteratei "list_op_α ops" "list_op_invar ops"
  + poly_list_rev_iteratei "list_op_α ops" "list_op_invar ops"
  for ops :: "('a,'s,'more) list_ops_scheme"
begin
  abbreviation α where "α ≡ list_op_α ops"
  abbreviation invar where "invar ≡ list_op_invar ops"
  abbreviation empty where "empty ≡ list_op_empty ops"
  abbreviation isEmpty where "isEmpty ≡ list_op_isEmpty ops"
  abbreviation size where "size ≡ list_op_size ops"
  abbreviation appendl where "appendl ≡ list_op_appendl ops"
  abbreviation removel where "removel ≡ list_op_removel ops"
  abbreviation leftmost where "leftmost ≡ list_op_leftmost ops"
  abbreviation appendr where "appendr ≡ list_op_appendr ops"
  abbreviation remover where "remover ≡ list_op_remover ops"
  abbreviation rightmost where "rightmost ≡ list_op_rightmost ops"
  abbreviation get where "get ≡ list_op_get ops"
  abbreviation set where "set ≡ list_op_set ops"
end

locale StdList = StdListDefs ops
  + list α invar
  + list_empty α invar empty 
  + list_isEmpty α invar isEmpty 
  + list_size α invar size 
  + list_appendl α invar appendl 
  + list_removel α invar removel 
  + list_leftmost α invar leftmost 
  + list_appendr α invar appendr 
  + list_remover α invar remover 
  + list_rightmost α invar rightmost 
  + list_get α invar get 
  + list_set α invar set 
  for ops :: "('a,'s,'more) list_ops_scheme"
begin
  lemmas correct = 
    empty_correct
    isEmpty_correct
    size_correct
    appendl_correct
    removel_correct
    leftmost_correct
    appendr_correct
    remover_correct
    rightmost_correct
    get_correct
    set_correct

end

locale StdList_no_invar = StdList + list_no_invar α invar
    
end