theory CSLSemantics imports Main Real Log Ln Taylor -- "the imports taken from Complex_Main"
begin

(* A Remark on deep embeddings:

The key-point is how binders and bound or free variables are represented.

In different papers there are different approaches:

*** Proving the Completeness Theorem within Isabelle/HOL (2004):
Variables are integers, binders use a deBruijn-Index style without mentioning the bound variable
(least variable is bound by a binder, e.g., All (All ((Var 1) = 2*(Var 2))) = !x. !y. y=2*x)



*** Implementing Z in Isabelle (1995):
Z is deeply embedded in a logic based on Isabelle/Pure (not HOL!).

Looks for me rather shallow than deep (apparently Jigsaw is a deeper embedding,
simulating also the substitution machinery, see p.18(371)).

From p.3(356):
"Variable binding is expressed using higher-order abstract syntax.
This enables us to express inference rules involving substitution
for bound variables in such a way that the usual side conditions are automatically respected.
Thus, for instance, the inference rule ForallIntro: P ==> forall x. P
with the side condition that x does not occur free in the assumptions, can be formalized
in Isabelle as:
!! x. Trueprop(P(x)) ==> Trueprop(forall(%x.P(x))) .
"


* A simple setting to reason about

program: "y := x ^ 2"

program-property to prove: "y >= 0"

*)


(**********************  Toy development 1  **********************)

types State = "int => real"

datatype Term = Const int | Num real | Mult Term Term | Add Term Term

fun iTerm :: "State => Term => real" where
"iTerm _ (Num r) = r" |
"iTerm s (Mult t u) = (iTerm s t) * (iTerm s u)" |
"iTerm s (Add t u) = (iTerm s t) + (iTerm s u)" |
"iTerm s (Const i) = s i"

datatype Command = Assign int Term | Seq Command Command

fun iCommand :: "State => Command => State" where
"iCommand s (Assign i t) = (%x . if x = i then iTerm s t else s x)" |
"iCommand s (Seq c1 c2) = (let s' = iCommand s c1 in iCommand s' c2)"

datatype ProgCond = Ge Term Term | Gt Term Term


fun iProgCond :: "State => ProgCond => bool" where
"iProgCond s (Ge t u) = (iTerm s t >= iTerm s u)" |
"iProgCond s (Gt t u) = (iTerm s t > iTerm s u)"

constdefs c1 :: Command -- "The command for  y := x * x"
         "c1 == Assign 2 (Mult (Const 1) (Const 1))"

constdefs p1 :: ProgCond -- "The property for  y >= 0"
         "p1 == Ge (Const 2) (Num 0)"


lemma soundProg:
  "!! s :: State . 
   let s' = iCommand s c1
   in iProgCond s' p1"

apply (subst Let_def, subst c1_def, subst p1_def)
apply (simp only: iCommand.simps)
apply (simp only: iProgCond.simps)
apply (simp only: iTerm.simps)
apply (simp only: if_P)
by simp
(*

by (simp add: c1_def p1_def iCommand.simps iProgCond.simps)
*)

constdefs c2 :: Command -- "The command for  x := x * x"
         "c2 == Assign 1 (Mult (Const 1) (Const 1))"

constdefs p2 :: ProgCond -- "The property for  x >= 0"
         "p2 == Ge (Const 1) (Num 0)"

lemma soundProg2:
  "!! s :: State . 
   let s' = iCommand s c2
   in iProgCond s' p2"
by (simp add: c2_def p2_def iCommand.simps iProgCond.simps)

constdefs c3 :: Command -- "The command for  x := 0; x := x + 1"
         "c3 == Seq (Assign 1 (Num 0)) (Assign 1 (Add (Const 1) (Num 1)))"

constdefs p3 :: ProgCond -- "The property for  x > 0"
         "p3 == Gt (Const 1) (Num 0)"

lemma soundProg3:
  "!! s :: State . 
   let s' = iCommand s c3
   in iProgCond s' p3"

apply (subst Let_def, subst c3_def, subst p3_def)
apply (simp only: iCommand.simps)
apply (subst Let_def)
apply (simp only: iProgCond.simps)
apply (simp only: iTerm.simps)
by (simp only: if_P)


lemma soundProgExplicit:
  "!! (s :: State) (x :: real) (y :: real). 
   let s' = (%z . if z = 1 then x else if z = 2 then y else s z);
       s'' = iCommand s' c1
   in iProgCond s'' p1"

apply (simp only: Let_def c1_def p1_def iCommand.simps iProgCond.simps iTerm.simps if_P)
by simp

(**********************  Toy development with Assignment store  **********************)

fun dependsOn :: "Term => int set" where
"dependsOn (Num n) = {}" |
"dependsOn (Mult t u) = dependsOn t Un dependsOn u" |
"dependsOn (Add t u) = dependsOn t Un dependsOn u" |
"dependsOn (Const i) = {i}"


types ConstantTermAssignments = "int ~=> Term"

constdefs
  -- "flat dependency for the given constant when lookuped in the CTA"
  dependsOnWithCTALookup :: "ConstantTermAssignments => int => int set"
 "dependsOnWithCTALookup f i == (case f i of
                            Some t => dependsOn t |
                            _ => {})"

  -- "flat dependency relation, not transitive by construction"
  depOrder1 :: "ConstantTermAssignments => (int*int) set"
 "depOrder1 f == {(x, y) | x y . y: dependsOnWithCTALookup f x}"

  -- "transitive closure of depOrder1"
  depOrder :: "ConstantTermAssignments => (int*int) set"
 "depOrder f == (depOrder1 f)^+"

  -- "set of constants the current term (recursively) depends on"
  dependsOnWithCTA :: "ConstantTermAssignments => Term => int set"
 "dependsOnWithCTA f t == Image (depOrder f) (dependsOn t)"

-- "An AssignmentStore is a finite ConstantTermAssignments without cycles"
constdefs AS_set :: "ConstantTermAssignments set"
         "AS_set == {f. let ord = depOrder f in wf ord & finite ord}"

lemma emptyAS_has_empty_dep_order : "depOrder empty == {}"
  by (simp add: depOrder1_def depOrder_def dependsOnWithCTALookup_def)

lemma emptyAS_in_AS': "empty : AS_set"
  by (simp add: emptyAS_has_empty_dep_order AS_set_def)

typedef (AS) AssignmentStore = AS_set
  morphisms asCTA toAS
  by (rule exI[of _ empty], simp only: emptyAS_in_AS')

lemma emptyAS_in_AS: "empty : AS"
  by (simp add: emptyAS_in_AS' AS_def)


function fullexpand :: "AssignmentStore => Term => Term" where
"fullexpand _ (Num r) = Num r" |
"fullexpand as (Mult t u) = Mult (fullexpand as t) (fullexpand as u)" |
"fullexpand as (Add t u) = Add (fullexpand as t) (fullexpand as u)" |
"fullexpand as (Const i) = (case (asCTA as) i of
                              Some y => fullexpand as y
                            | None => Const i)"
  by (auto, case_tac "b", auto)

(* 
 fullexpand is total essentially because the lookup in the
 Const-case is terminating because of the wellfoundness of "as" and
 the recursion on the structure of Term also terminates
 *)
lemma fullexpand_is_total : "!! as t . fullexpand_dom (as, t)"
  sorry

(* arg_cong and fun_cong are the crucial axioms
lemma T1:
  assumes H0: "f x = g"
  shows "!!i. f x i = g i"
by (rule arg_cong, simp add: H0)
by (rule fun_cong, simp add: H0)
*)

lemma "!!t . fullexpand (toAS empty) t = t"
proof (induct_tac "t", auto)
  fix i
  have H0: "asCTA (toAS empty) = empty" 
    by (simp only: emptyAS_in_AS toAS_inverse)
  have H1: "asCTA (toAS empty) i = empty i"
    by (rule arg_cong, simp add: H0)
  have H2: "asCTA (toAS empty) i = None" by (simp only: H1)
  hence "(case (asCTA (toAS empty) i) of Some y => fullexpand (toAS empty) y | None => Const i) = Const i" by simp
  thus "fullexpand (toAS empty) (Const i) = Const i"
    by(simp add: fullexpand_is_total fullexpand.psimps)
next
  fix r
  show "fullexpand (toAS empty) (Num r) = Num r"
    by (simp add: fullexpand_is_total fullexpand.psimps)
next
  fix t1 t2
  assume "fullexpand (toAS empty) t1 = t1" and "fullexpand (toAS empty) t2 = t2"
  thus "fullexpand (toAS empty) (Mult t1 t2) = (Mult t1 t2)"
    by (simp add: fullexpand_is_total fullexpand.psimps)
next
  fix t1 t2
  assume "fullexpand (toAS empty) t1 = t1" and "fullexpand (toAS empty) t2 = t2"
  thus "fullexpand (toAS empty) (Add t1 t2) = (Add t1 t2)"
    by (simp add: fullexpand_is_total fullexpand.psimps)
qed

nonterminals
  updbinds2 updbind2
syntax
  "_updbind2" :: "['a, 'a] => updbind2"             ("(2_ ::=/ _)")
  ""         :: "updbind2 => updbinds2"             ("_")
  "_updbinds2":: "[updbind2, updbinds2] => updbinds2" ("_,/ _")
  "_Update2"  :: "['a, updbinds2] => 'a"            ("_/'((_)')" [1000,0] 900)

translations
  "_Update2 f (_updbinds2 b bs)"  == "_Update2 (_Update2 f b) bs"
  "f(x::=y)"                     == "toAS ((asCTA f)(x |-> y))"


-- "If we encounter a cycle in an assignment we return None"
fun iProg :: "AssignmentStore => Command ~=> AssignmentStore" where
   "iProg as (Assign i t) = (let t' = fullexpand as t
                             in if i : dependsOn t then None else Some (as(i ::= t')))" |
   "iProg as (Seq c c') = (case iProg as c of
                             Some as' => iProg as' c'
                           | None => None)"

(**********************  Respectful States  **********************)

constdefs respectsAS :: "State => AssignmentStore => bool" (infixl "resp" 50)
         "s resp as == !x t . (asCTA as) x = Some t --> s x = iTerm s t"

theorem State_AssertionStore_interpretation_respect_preserving:
  "[|s resp as; iProg as p = Some as'|] ==> (iCommand s p) resp as'"
  sorry

theorem iTerm_invariant_under_full_expansion:
  "s resp as ==> !t. iTerm s t = iTerm s (fullexpand as t)"
proof-
  fix s as
  assume H0: "s resp as"
  show ?thesis
    apply (rule allI, induct_tac "t")
    apply(simp add: fullexpand_is_total fullexpand.psimps)
    apply (case_tac "asCTA as int")
    proof-
      fix i
      assume H1: "asCTA as i = None"
      hence H2: "(case (asCTA as) i of
                   Some y => fullexpand as y
                 | None => Const i)=Const i" (is "?cc = ?ci")
	by simp
      have "s i = iTerm s (Const i)" by simp
      also have "... = iTerm s ?cc" by (simp add: H2)

      -- "TODO: show macht probleme!"
      finally show "s i = iTerm s ?cc"
	

(*
      show " s i =
           iTerm s
            (option_case (Const i)
              (fullexpand as) (asCTA as i))"

*)




(**********************  Test stuff  **********************)

-- "just for testing"

lemma "!!v x y z. (empty(v |-> x)) y = Some z ==> y = v & z = x"
  by (case_tac "y=v", simp+)



-- "TODO: ins wiki stellen"
lemma "(EX y. ALL x. P x y) --> (ALL x. EX y. P x y)" 
  apply rule
  apply rule
  apply (erule exE)
  (* Geht nicht: x als gebundene Variable kann nicht referenziert werden
  apply (drule spec[where x=x])
    *)
  apply (drule_tac x=x in spec)
  apply (erule exI)
  done

term The
term Some
term "THE x. False"
ML {* @{term "THE x. False"} *}
ML {* the_context() *}
-- "old command print_syntax, what is the new one?"
ML {* print_syntax (theory "Main") *}
