src/HOL/Hoare/Hoare.thy
author clasohm
Wed, 29 Nov 1995 17:01:41 +0100
changeset 1374 5e407f2a3323
parent 1335 5e1c0540f285
child 1384 007ad29ce6ca
permissions -rw-r--r--
removed quotes from consts and syntax sections
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1335
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
     1
(*  Title: 	HOL/Hoare/Hoare.thy
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
     2
    ID:         $Id$
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
     3
    Author: 	Norbert Galm & Tobias Nipkow
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
     4
    Copyright   1995 TUM
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
     5
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
     6
Sugared semantic embedding of Hoare logic.
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
     7
*)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
     8
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
     9
Hoare = Arith +
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    10
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    11
types
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    12
  'a prog			(* program syntax *)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    13
  pvar = "nat"			(* encoding of program variables ( < 26! ) *)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    14
  'a state = "pvar => 'a"	(* program state *)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    15
  'a exp ="'a state => 'a"	(* denotation of expressions *)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    16
  'a bexp = "'a state => bool"  (* denotation of boolean expressions *)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    17
  'a com = "'a state => 'a state => bool" (* denotation of programs *)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    18
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    19
syntax
1374
5e407f2a3323 removed quotes from consts and syntax sections
clasohm
parents: 1335
diff changeset
    20
  "@Skip"       :: 'a prog				("SKIP")
5e407f2a3323 removed quotes from consts and syntax sections
clasohm
parents: 1335
diff changeset
    21
  "@Assign"	:: [id, 'a] => 'a prog		("_ := _")
5e407f2a3323 removed quotes from consts and syntax sections
clasohm
parents: 1335
diff changeset
    22
  "@Seq"	:: ['a prog, 'a prog] => 'a prog	("_;//_" [0,1000] 999)
5e407f2a3323 removed quotes from consts and syntax sections
clasohm
parents: 1335
diff changeset
    23
  "@If"		:: [bool, 'a prog, 'a prog] => 'a prog
1335
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    24
                   ("IF _//THEN//  (_)//ELSE//  (_)//END")
1374
5e407f2a3323 removed quotes from consts and syntax sections
clasohm
parents: 1335
diff changeset
    25
  "@While"	:: [bool, bool, 'a prog] => 'a prog
1335
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    26
                   ("WHILE _//DO {_}//  (_)//END")
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    27
1374
5e407f2a3323 removed quotes from consts and syntax sections
clasohm
parents: 1335
diff changeset
    28
  "@Spec"	:: [bool, 'a prog, bool] => bool	("{_}//_//{_}")
1335
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    29
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    30
consts
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    31
  (* semantics *)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    32
1374
5e407f2a3323 removed quotes from consts and syntax sections
clasohm
parents: 1335
diff changeset
    33
  Skip		:: 'a com
5e407f2a3323 removed quotes from consts and syntax sections
clasohm
parents: 1335
diff changeset
    34
  Assign	:: [pvar, 'a exp] => 'a com
5e407f2a3323 removed quotes from consts and syntax sections
clasohm
parents: 1335
diff changeset
    35
  Seq		:: ['a com, 'a com] => 'a com
5e407f2a3323 removed quotes from consts and syntax sections
clasohm
parents: 1335
diff changeset
    36
  Cond		:: ['a bexp, 'a com, 'a com] => 'a com
5e407f2a3323 removed quotes from consts and syntax sections
clasohm
parents: 1335
diff changeset
    37
  While		:: ['a bexp, 'a bexp, 'a com] => 'a com
5e407f2a3323 removed quotes from consts and syntax sections
clasohm
parents: 1335
diff changeset
    38
  Iter		:: [nat, 'a bexp, 'a com] => 'a com
1335
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    39
1374
5e407f2a3323 removed quotes from consts and syntax sections
clasohm
parents: 1335
diff changeset
    40
  Spec		:: ['a bexp, 'a com, 'a bexp] => bool
1335
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    41
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    42
defs
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    43
  (* denotational semantics *)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    44
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    45
  SkipDef	"Skip s s' == (s=s')"
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    46
  AssignDef	"Assign v e s s' == (s' = (%x.if x=v then e(s) else s(x)))"
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    47
  SeqDef	"Seq c c' s s' == ? s''. c s s'' & c' s'' s'"
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    48
  CondDef	"Cond b c c' s s' == (b(s) --> c s s') & (~b s --> c' s s')"
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    49
  WhileDef	"While b inv c s s' == ? n. Iter n b c s s'"
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    50
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    51
  IterDef	"Iter n b c == nat_rec n (%s s'.~b(s) & (s=s'))
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    52
		           (%n_rec iter_rec.%s s'.b(s) & Seq c iter_rec s s')"
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    53
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    54
  SpecDef	"Spec p c q == !s s'. c s s' --> p s --> q s'"
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    55
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    56
end
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    57
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    58
ML
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    59
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    60
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    61
(*** term manipulation ***)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    62
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    63
(* name_in_term:bool (name:string,trm:term) bestimmt, ob in trm der Name name als Konstante,
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    64
   freie Var., scheme-Variable oder als Name fuer eine Lambda-Abstraktion vorkommt *)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    65
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    66
fun name_in_term (name,Const (s,t))	=(name=s)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    67
  | name_in_term (name,Free (s,t))	=(name=s)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    68
  | name_in_term (name,Var ((s,i),t))	=(name=s ^ makestring i)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    69
  | name_in_term (name,Abs (s,t,trm))	=(name=s) orelse (name_in_term (name,trm))
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    70
  | name_in_term (name,trm1 $ trm2)	=(name_in_term (name,trm1)) orelse (name_in_term (name,trm2))
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    71
  | name_in_term (_,_)			=false;
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    72
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    73
(* variant_name:string (name:string,trm:term) liefert einen von name abgewandelten Namen (durch Anhaengen
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    74
   von genuegend vielen "_"), der nicht in trm vorkommt. Im Gegensatz zu variant_abs beruecktsichtigt es
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    75
   auch Namen von scheme-Variablen und von Lambda-Abstraktionen in trm *)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    76
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    77
fun variant_name (name,trm)	=if name_in_term (name,trm)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    78
					then variant_name (name ^ "_",trm)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    79
					else name;
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    80
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    81
(* subst_term:term (von:term,nach:term,trm:term) liefert den Term, der aus
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    82
trm entsteht, wenn alle Teilterme, die gleich von sind, durch nach ersetzt
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    83
wurden *)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    84
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    85
fun subst_term (von,nach,Abs (s,t,trm))	=if von=Abs (s,t,trm)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    86
						then nach
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    87
						else Abs (s,t,subst_term (von,nach,trm))
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    88
  | subst_term (von,nach,trm1 $ trm2)	=if von=trm1 $ trm2
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    89
						then nach
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    90
						else subst_term (von,nach,trm1) $ subst_term (von,nach,trm2)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    91
  | subst_term (von,nach,trm)		=if von=trm
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    92
						then nach
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    93
						else trm;
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    94
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    95
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    96
(* Translation between program vars ("a" - "z") and their encoding as
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    97
   natural numbers: "a" <==> 0, "b" <==> Suc(0), ..., "z" <==> 25 *)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    98
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
    99
fun is_pvarID s	= size s=1 andalso "a"<=s andalso s<="z";
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   100
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   101
fun pvarID2pvar s =
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   102
  let fun rest2pvar (i,arg) =
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   103
            if i=0 then arg else rest2pvar(i-1, Syntax.const "Suc" $ arg)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   104
  in rest2pvar(ord s - ord "a", Syntax.const "0") end;
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   105
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   106
fun pvar2pvarID trm	=
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   107
	let
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   108
		fun rest2pvarID (Const("0",_),i)		=chr (i + ord "a")
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   109
		  | rest2pvarID (Const("Suc",_) $ trm,i)	=rest2pvarID (trm,i+1)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   110
	in
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   111
		rest2pvarID (trm,0)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   112
	end;
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   113
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   114
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   115
(*** parse translations: syntax -> semantics ***)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   116
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   117
(* term_tr:term (name:string,trm:term) ersetzt in trm alle freien Variablen, die eine pvarID
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   118
   darstellen, durch name $ pvarID2pvar(pvarID). Beispiel:
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   119
   bei name="s" und dem Term "a=b & a=X" wird der Term "s(0)=s(Suc(0)) & s(0)=X" geliefert *)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   120
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   121
fun term_tr (name,Free (s,t)) = if is_pvarID s
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   122
				then Syntax.free name $ pvarID2pvar s
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   123
				else Free (s,t)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   124
  | term_tr (name,Abs (s,t,trm)) = Abs (s,t,term_tr (name,trm))
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   125
  | term_tr (name,trm1 $ trm2)	= term_tr (name,trm1) $ term_tr (name,trm2)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   126
  | term_tr (name,trm) = trm;
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   127
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   128
fun bool_tr B =
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   129
  let val name = variant_name("s",B)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   130
  in Abs (name,dummyT,abstract_over (Syntax.free name,term_tr (name,B))) end;
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   131
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   132
fun exp_tr E =
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   133
  let val name = variant_name("s",E)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   134
  in Abs (name,dummyT,abstract_over (Syntax.free name,term_tr (name,E))) end;
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   135
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   136
fun prog_tr (Const ("@Skip",_))	= Syntax.const "Skip"
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   137
  | prog_tr (Const ("@Assign",_) $ Free (V,_) $ E) =
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   138
      if is_pvarID V
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   139
      then Syntax.const "Assign" $ pvarID2pvar V $ exp_tr E
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   140
      else error("Not a valid program variable: " ^ quote V)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   141
  | prog_tr (Const ("@Seq",_) $ C $ C')	=
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   142
      Syntax.const "Seq" $ prog_tr C $ prog_tr C'
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   143
  | prog_tr (Const ("@If",_) $ B $ C $ C') =
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   144
      Syntax.const "Cond" $ bool_tr B $ prog_tr C $ prog_tr C'
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   145
  | prog_tr (Const ("@While",_) $ B $ INV $ C) =
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   146
      Syntax.const "While" $ bool_tr B $ bool_tr INV $ prog_tr C;
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   147
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   148
fun spec_tr [P,C,Q] = Syntax.const "Spec" $ bool_tr P $ prog_tr C $ bool_tr Q;
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   149
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   150
val parse_translation = [("@Spec",spec_tr)];
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   151
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   152
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   153
(*** print translations: semantics -> syntax ***)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   154
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   155
(* term_tr':term (name:string,trm:term) ersetzt in trm alle Vorkommen von name $ pvar durch
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   156
   entsprechende freie Variablen, welche die pvarID zu pvar darstellen. Beispiel:
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   157
	bei name="s" und dem Term "s(0)=s(Suc(0)) & s(0)=X" wird der Term "a=b & a=X" geliefert *)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   158
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   159
fun term_tr' (name,Free (s,t) $ trm)	=if name=s
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   160
						then Syntax.free (pvar2pvarID trm)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   161
						else Free (s,t) $ term_tr' (name,trm)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   162
  | term_tr' (name,Abs (s,t,trm))	=Abs (s,t,term_tr' (name,trm))
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   163
  | term_tr' (name,trm1 $ trm2)		=term_tr' (name,trm1) $ term_tr' (name,trm2)
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   164
  | term_tr' (name,trm)			=trm;
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   165
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   166
fun bexp_tr' (Abs(_,_,b))	=term_tr' (variant_abs ("s",dummyT,b));
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   167
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   168
fun exp_tr' (Abs(_,_,e))	=term_tr' (variant_abs ("s",dummyT,e));
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   169
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   170
fun com_tr' (Const ("Skip",_))			=Syntax.const "@Skip"
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   171
  | com_tr' (Const ("Assign",_) $ v $ e)		=Syntax.const "@Assign" $ Syntax.free (pvar2pvarID v) $ exp_tr' e
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   172
  | com_tr' (Const ("Seq",_) $ c $ c')		=Syntax.const "@Seq" $ com_tr' c $ com_tr' c'
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   173
  | com_tr' (Const ("Cond",_) $ b $ c $ c')		=Syntax.const "@If" $ bexp_tr' b $ com_tr' c $ com_tr' c'
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   174
  | com_tr' (Const ("While",_) $ b $ inv $ c)	=Syntax.const "@While" $ bexp_tr' b $ bexp_tr' inv $ com_tr' c;
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   175
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   176
fun spec_tr' [p,c,q]		=Syntax.const "@Spec" $ bexp_tr' p $ com_tr' c $ bexp_tr' q;
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   177
5e1c0540f285 New directory.
nipkow
parents:
diff changeset
   178
val print_translation	=[("Spec",spec_tr')];