https://github.com/loonwerks/splat
Tip revision: 65329ada84fa10bf35a2101931d4418c98fc2372 authored by Karl Hoech on 09 June 2021, 10:42:19 UTC
Fix parse error in HAMR version
Fix parse error in HAMR version
Tip revision: 65329ad
abscontigScript.sml
open HolKernel Parse boolLib bossLib BasicProvers
pred_setLib stringLib regexpLib ASCIInumbersLib;
open pairTheory arithmeticTheory listTheory rich_listTheory pred_setTheory
stringTheory combinTheory optionTheory numposrepTheory FormalLangTheory;
open finite_mapTheory bagTheory; (* For termination of predFn, need to use mlt_list *)
open concatPartialTheory;
(*---------------------------------------------------------------------------*)
(* Setup basic proof support *)
(*---------------------------------------------------------------------------*)
val _ = numLib.prefer_num();
val _ = overload_on ("++", ``list$APPEND``);
infix byA;
val op byA = BasicProvers.byA;
val decide = bossLib.DECIDE;
val qdecide = decide o Parse.Term;
val sym = SYM;
val subst_all_tac = SUBST_ALL_TAC;
val popk_tac = pop_assum kall_tac;
val pop_subst_tac = pop_assum subst_all_tac;
val pop_sym_subst_tac = pop_assum (subst_all_tac o sym);
val qpat_k_assum = C qpat_x_assum kall_tac;
val var_eq_tac = rpt BasicProvers.VAR_EQ_TAC;
fun qspec q th = th |> Q.SPEC q
fun qspec_arith q th = qspec q th |> SIMP_RULE arith_ss [];
fun simpCases_on q = Cases_on q >> fs [] >> rw[];
Triviality IS_SOME_NEG :
IS_SOME = \x. ~(x=NONE)
Proof
rw [FUN_EQ_THM] >> metis_tac [NOT_IS_SOME_EQ_NONE]
QED
val _ = new_theory "abscontig";
(*---------------------------------------------------------------------------*)
(* The types of interest: lvals, arithmetic expressions over rvals, boolean *)
(* expressions, atomic types, and contiguity types. *)
(*---------------------------------------------------------------------------*)
Datatype:
lval = VarName string
| RecdProj lval string
| ArraySub lval exp
;
exp = Loc lval
| numLit num
| Add exp exp
End
Datatype:
bexp = boolLit bool
| BLoc lval
| Bnot bexp
| Bor bexp bexp
| Band bexp bexp
| Beq exp exp
| Blt exp exp
End
Datatype:
atom = Bool
| Char
| U8
| U16
| U32
End
Datatype:
contig = Basic atom
| Void
| Assert bexp
| Recd ((string # contig) list)
| Array contig exp
| List contig
| Alt bexp contig contig
End
val contig_size_def = fetch "-" "contig_size_def";
(*---------------------------------------------------------------------------*)
(* Expression evaluation. Looking up lvals is partial, which infects evalExp *)
(*---------------------------------------------------------------------------*)
(* LSB with padding to width *)
Definition layout_def :
layout b n width = PAD_RIGHT 0n width (n2l b n)
End
Definition repFn_def :
repFn w n = MAP CHR (layout 256 n w)
End
Definition valFn_def :
valFn s = if s = "" then NONE else SOME (l2n 256 (MAP ORD s))
End
Definition evalExp_def :
evalExp theta (Loc lval) =
(case FLOOKUP theta lval
of SOME s => valFn s
| NONE => NONE) /\
evalExp theta (numLit n) = SOME n /\
evalExp theta (Add e1 e2) =
(case evalExp theta e1
of NONE => NONE
| SOME n1 =>
case evalExp theta e2
of NONE => NONE
| SOME n2 => SOME (n1+n2))
End
(*---------------------------------------------------------------------------*)
(* Boolean expression evaluation. Also partial *)
(*---------------------------------------------------------------------------*)
Definition evalBexp_def :
(evalBexp theta (boolLit b) = SOME b) /\
(evalBexp theta (BLoc lval) =
case FLOOKUP theta lval
of NONE => NONE
| SOME s =>
case valFn s
of NONE => NONE
| SOME n => SOME (~(n = 0n))) /\
(evalBexp theta (Bnot b) =
case evalBexp theta b
of NONE => NONE
| SOME bval => SOME (~bval)) /\
(evalBexp theta (Bor b1 b2) =
case evalBexp theta b1
of NONE => NONE
| SOME bv1 =>
case evalBexp theta b2
of NONE => NONE
| SOME bv2 => SOME (bv1 \/ bv2)) /\
(evalBexp theta (Band b1 b2) =
case evalBexp theta b1
of NONE => NONE
| SOME bv1 =>
case evalBexp theta b2
of NONE => NONE
| SOME bv2 => SOME (bv1 /\ bv2)) /\
(evalBexp theta (Beq e1 e2) =
case evalExp theta e1
of NONE => NONE
| SOME n1 =>
case evalExp theta e2
of NONE => NONE
| SOME n2 => SOME (n1 = n2)) /\
(evalBexp theta (Blt e1 e2) =
case evalExp theta e1
of NONE => NONE
| SOME n1 =>
case evalExp theta e2
of NONE => NONE
| SOME n2 => SOME (n1 < n2))
End
Definition atomWidth_def:
atomWidth Bool = 1 /\
atomWidth Char = 1 /\
atomWidth U8 = 1 /\
atomWidth U16 = 2 /\
atomWidth U32 = 4
End
(*---------------------------------------------------------------------------*)
(* Size of a contig. The system-generated contig_size goes through a lot of *)
(* other types, including field names, and those shouldn't be counted because*)
(* field name size shouldn't count in the size of the expression. *)
(*---------------------------------------------------------------------------*)
Theorem contig_size_lem:
!plist p. MEM p plist ==> contig_size (SND p) < contig1_size plist
Proof
simp_tac list_ss [FORALL_PROD]
>> Induct
>> rw_tac list_ss [contig_size_def]
>- rw_tac list_ss [contig_size_def]
>- (‘contig_size p_2 < contig1_size plist’ by metis_tac[] >> decide_tac)
QED
val _ = DefnBase.add_cong list_size_cong;
Definition csize_def :
(csize (Basic a) = 0) /\
(csize Void = 0) /\
(csize (Assert b) = 0) /\
(csize (Recd fields) = 1 + list_size (\(a,c). csize c) fields) /\
(csize (Array c dim) = 1 + csize c) /\
(csize (List c) = 1 + csize c) /\
(csize (Alt b c1 c2) = 1 + csize c1 + csize c2)
Termination
WF_REL_TAC `measure contig_size`
>> rw_tac list_ss [contig_size_def]
>- (Induct_on `fields`
>> rw_tac list_ss [contig_size_def]
>> full_simp_tac list_ss [contig_size_def])
End
(*---------------------------------------------------------------------------*)
(* Size of an lval. Needed in termination proof of substFn. *)
(*---------------------------------------------------------------------------*)
Definition lvsize_def :
lvsize (VarName s) = 1 /\
lvsize (RecdProj lv s) = 1 + lvsize lv /\
lvsize (ArraySub lv e) = 1 + lvsize lv
End
Definition lvprefixes_def :
lvprefixes (VarName s) = {VarName s} /\
lvprefixes (RecdProj lv s) = (RecdProj lv s INSERT lvprefixes lv) /\
lvprefixes (ArraySub lv e) = (ArraySub lv e INSERT lvprefixes lv)
End
Theorem lvprefixes_refl :
∀lval. lval IN lvprefixes lval
Proof
Induct >> rw[lvprefixes_def]
QED
Theorem lvprefixes_Recd_downclosed :
∀x lval fld. RecdProj lval fld IN lvprefixes x ⇒ lval IN lvprefixes x
Proof
Induct
>> rw [lvprefixes_def]
>> metis_tac [lvprefixes_refl]
QED
Theorem lvsize_lvprefixes :
∀lval lv. lv IN lvprefixes lval ⇒ lvsize lv < lvsize lval ∨ lv = lval
Proof
Induct
>> rw[lvprefixes_def,lvsize_def]
>> res_tac
>> rw[]
QED
Definition lvdescendants_def :
lvdescendants theta lval = {path | path IN FDOM theta ∧ lval IN lvprefixes path}
End
Definition NilTag_def :
NilTag = CHR 0
End
Definition ConsTag_def :
ConsTag = CHR 1
End
(*---------------------------------------------------------------------------*)
(* Semantics (formal language style) *)
(*---------------------------------------------------------------------------*)
Definition Contig_Lang_def:
Contig_Lang theta (Basic a) = {s | LENGTH s = atomWidth a} /\
Contig_Lang theta Void = {} /\
Contig_Lang theta (Assert b) =
(case evalBexp theta b
of NONE => {}
| SOME T => {""}
| SOME F => {}) /\
Contig_Lang theta (Recd fields) =
{CONCAT slist
| LIST_REL (\s contig. s IN Contig_Lang theta contig) slist (MAP SND fields)} /\
Contig_Lang theta (Array c e) =
(case evalExp theta e
of NONE => {}
| SOME n =>
{CONCAT slist
| (LENGTH slist = n) /\ EVERY (Contig_Lang theta c) slist}) /\
Contig_Lang theta (List c) =
(KSTAR ({[ConsTag]} dot (Contig_Lang theta c)) dot {[NilTag]}) /\
Contig_Lang theta (Alt bexp c1 c2) =
(case evalBexp theta bexp
of NONE => {}
| SOME T => Contig_Lang theta c1
| SOME F => Contig_Lang theta c2)
Termination
WF_REL_TAC ‘measure (contig_size o SND)’
>> rw [contig_size_def,MEM_MAP]
>> imp_res_tac contig_size_lem
>> decide_tac
End
(*---------------------------------------------------------------------------*)
(* Assert derivable. Complicates termination proof for Contig_Lang, so *)
(* expanded form used in Contig_Lang_def above. *)
(*---------------------------------------------------------------------------*)
Theorem Assert_Alt :
Contig_Lang theta (Assert b) = Contig_Lang theta (Alt b (Recd []) Void)
Proof
rw[Contig_Lang_def]
>> every_case_tac
>> rw[EXTENSION]
QED
Theorem IN_Contig_Lang :
∀s.
(s IN Contig_Lang theta (Basic a) ⇔ LENGTH s = atomWidth a) ∧
(s IN Contig_Lang theta Void ⇔ F) ∧
(s IN Contig_Lang theta (Assert b) ⇔ (s = "" ∧ evalBexp theta b = SOME T)) ∧
(s IN Contig_Lang theta (Recd fields) ⇔
∃slist. s = CONCAT slist ∧
LIST_REL (\s contig. s IN Contig_Lang theta contig) slist (MAP SND fields)) /\
(s IN Contig_Lang theta (Array c e) ⇔
∃slist.
evalExp theta e = SOME (LENGTH slist) ∧
s = CONCAT slist ∧
EVERY (Contig_Lang theta c) slist) ∧
(s IN Contig_Lang theta (List c) ⇔
∃slist.
s = STRCAT (CONCAT slist) [NilTag] ∧
EVERY (\plist. ∃elt. plist = ConsTag::elt ∧ elt IN Contig_Lang theta c) slist) ∧
(s IN Contig_Lang theta (Alt bexp c1 c2) ⇔
∃b. evalBexp theta bexp = SOME b ∧
if b then s IN Contig_Lang theta c1
else s IN Contig_Lang theta c2)
Proof
rw [Contig_Lang_def,EXTENSION]
>> every_case_tac
>> rw [IN_dot,IN_KSTAR_LIST]
>> metis_tac[]
QED
(*---------------------------------------------------------------------------*)
(* break off a prefix of a string *)
(*---------------------------------------------------------------------------*)
Definition tdrop_def:
tdrop 0 list acc = SOME (REVERSE acc, list) /\
tdrop n [] acc = NONE /\
tdrop (SUC n) (h::t) acc = tdrop n t (h::acc)
End
Theorem tdrop_thm :
∀n list acc acc'.
tdrop n list acc = SOME (acc',suf)
⇒ (acc' ++ suf = REVERSE acc ++ list) /\
(LENGTH acc' = n + LENGTH acc)
Proof
recInduct tdrop_ind >> rw [tdrop_def] >> metis_tac [LENGTH_REVERSE]
QED
Definition take_drop_def :
take_drop n list = tdrop n list []
End
Theorem take_drop_thm :
∀n list.
take_drop n list = SOME (pref,suf) ⇒ pref ++ suf = list /\ (n = LENGTH pref)
Proof
rw_tac list_ss [take_drop_def] >> imp_res_tac tdrop_thm >> fs []
QED
Definition upto_def:
upto lo hi = if lo > hi then [] else lo::upto (lo+1) hi
Termination
WF_REL_TAC ‘measure (\(a,b). b+1n - a)’
End
Theorem upto_interval_thm :
!lo hi. set(upto lo hi) = {n | lo <= n /\ n <= hi}
Proof
recInduct upto_ind
>> rw_tac list_ss []
>> rw_tac list_ss [Once upto_def]
>> fs[]
>> rw [pred_setTheory.EXTENSION]
QED
Theorem length_upto :
!lo hi. lo <= hi ==> LENGTH(upto lo hi) = (hi-lo) + 1
Proof
recInduct upto_ind
>> rw_tac list_ss []
>> rw_tac list_ss [Once upto_def]
>> fs[]
>> ‘lo=hi \/ lo+1 <= hi’ by decide_tac
>- rw[Once upto_def]
>- fs[]
QED
Triviality list_size_append :
!L1 L2 f. list_size f (L1 ++ L2) = (list_size f L1 + list_size f L2)
Proof
Induct_on ‘L1’ >> rw_tac list_ss [list_size_def]
QED
Triviality strlen_eq_1 :
!L. (STRLEN L = 1) ⇔ ∃n. n < 256 ∧ L = [CHR n]
Proof
Cases_on ‘L’
>> rw_tac list_ss [STRLEN_DEF,EQ_IMP_THM]
>> metis_tac[CHR_ONTO]
QED
Theorem atomWidth_pos :
!b. 0 < atomWidth b
Proof
Cases >> rw [atomWidth_def]
QED
Definition choiceFn_def :
choiceFn theta bexp =
case evalBexp theta bexp
of NONE => F
| SOME bval => bval
End
Definition indexFn_def :
indexFn lval c n = (ArraySub lval (numLit n),c)
End
Definition fieldFn_def :
fieldFn lval (fName,c) = (RecdProj lval fName,c)
End
Definition ListRecd_def :
ListRecd lval c =
(lval,
Alt (Beq (Loc (RecdProj lval "tag")) (numLit 0)) (Recd [])
(Alt (Beq (Loc (RecdProj lval "tag")) (numLit 1))
(Recd [("hd",c); ("tl", List c)])
Void))
End
(*---------------------------------------------------------------------------*)
(* contig-specified predicate on strings. *)
(*---------------------------------------------------------------------------*)
Definition predFn_def :
predFn (worklist,s,theta) =
case worklist
of [] => T
| (lval,Basic a)::t =>
(case take_drop (atomWidth a) s
of NONE => F
| SOME (segment,rst) =>
predFn (t, rst, theta |+ (lval,segment)))
| (lval,Void)::t => F
| (lval,Assert b)::t =>
(case evalBexp theta b
of NONE => F
| SOME F => F
| SOME T => predFn (t,s,theta))
| (lval,Recd fields)::t =>
predFn (MAP (fieldFn lval) fields ++ t,s,theta)
| (lval,Array c exp)::t =>
(case evalExp theta exp
of NONE => F
| SOME dim =>
predFn (MAP (indexFn lval c) (COUNT_LIST dim) ++ t,s,theta))
| (lval, List c)::t =>
(case take_drop 1 s
of NONE => F
| SOME (segment,rst) =>
predFn (ListRecd lval c::t, rst, theta |+ (RecdProj lval "tag",segment)))
| (lval,Alt bexp c1 c2)::t =>
case evalBexp theta bexp
of NONE => F
| SOME T => predFn ((lval,c1)::t,s,theta)
| SOME F => predFn ((lval,c2)::t,s,theta)
Termination
WF_REL_TAC ‘inv_image
(measure LENGTH
LEX
mlt_list (measure (csize o SND)))
(\(b,c,d). (c,b))’
>> rw [APPEND_EQ_SELF]
>> rw [csize_def]
>> fs [MEM_MAP,MEM_SPLIT]
>- (imp_res_tac take_drop_thm >> rw [] >> metis_tac [atomWidth_pos])
>- (imp_res_tac take_drop_thm >> rw [] >> metis_tac [atomWidth_pos])
>- (Cases_on `y` >> fs[list_size_append,list_size_def,fieldFn_def])
>- (Cases_on `y` >> fs[list_size_append,list_size_def,indexFn_def])
End
(*---------------------------------------------------------------------------*)
(* Worklist-based matcher. When it comes to add a new (lval |-> string) *)
(* element to theta, it first checks that lval is not in FDOM(theta). *)
(*---------------------------------------------------------------------------*)
Definition matchFn_def :
matchFn (worklist,s,theta) =
case worklist
of [] => SOME (s,theta)
| (lval,Basic a)::t =>
(case take_drop (atomWidth a) s
of NONE => NONE
| SOME (segment,rst) =>
if lval IN FDOM theta then
NONE
else matchFn (t, rst, theta |+ (lval,segment)))
| (lval,Void)::t => NONE
| (lval,Assert b)::t =>
(case evalBexp theta b
of NONE => NONE
| SOME F => NONE
| SOME T => matchFn (t,s,theta))
| (lval,Recd fields)::t =>
matchFn (MAP (fieldFn lval) fields ++ t,s,theta)
| (lval,Array c exp)::t =>
(case evalExp theta exp
of NONE => NONE
| SOME dim =>
matchFn (MAP (indexFn lval c) (COUNT_LIST dim) ++ t,s,theta))
| (lval, List c)::t =>
(case take_drop 1 s
of NONE => NONE
| SOME (segment,rst) =>
if RecdProj lval "tag" IN FDOM theta then
NONE
else
matchFn (ListRecd lval c::t, rst, theta |+ (RecdProj lval "tag",segment)))
| (lval,Alt bexp c1 c2)::t =>
case evalBexp theta bexp
of NONE => NONE
| SOME T => matchFn ((lval,c1)::t,s,theta)
| SOME F => matchFn ((lval,c2)::t,s,theta)
Termination
WF_REL_TAC ‘inv_image
(measure LENGTH
LEX
mlt_list (measure (csize o SND)))
(\(b,c,d). (c,b))’
>> rw [APPEND_EQ_SELF]
>> rw [csize_def]
>> fs [MEM_MAP,MEM_SPLIT]
>- (imp_res_tac take_drop_thm >> rw [] >> metis_tac [atomWidth_pos])
>- (imp_res_tac take_drop_thm >> rw [] >> metis_tac [atomWidth_pos])
>- (Cases_on `y` >> fs[list_size_append,list_size_def,fieldFn_def])
>- (Cases_on `y` >> fs[list_size_append,list_size_def,indexFn_def])
End
(*---------------------------------------------------------------------------*)
(* Apply a substitution to a contig. *)
(*---------------------------------------------------------------------------*)
Definition remaining_lvals_def :
remaining_lvals(theta,lval) = CARD(lvdescendants theta lval)
End
Definition substFn_def :
substFn theta (lval,contig) =
case contig
of Basic _ => FLOOKUP theta lval
| Void => NONE
| Assert b =>
(case evalBexp theta b
of NONE => NONE
| SOME F => NONE
| SOME T => SOME "")
| Recd fields =>
concatPartial
(MAP (\(fName,c). substFn theta (RecdProj lval fName,c)) fields)
| Array c exp =>
(case evalExp theta exp
of NONE => NONE
| SOME dim =>
concatPartial
(MAP (\i. substFn theta (ArraySub lval (numLit i), c))
(COUNT_LIST dim)))
| List c =>
(case FLOOKUP theta (RecdProj lval "tag")
of NONE => NONE
| SOME segment =>
if segment = [NilTag] then
SOME [NilTag]
else
if segment = [ConsTag] then
concatPartial
[SOME [ConsTag];
substFn theta (RecdProj lval "hd",c);
substFn theta (RecdProj lval "tl",List c)]
else NONE)
| Alt bexp c1 c2 =>
(case evalBexp theta bexp
of NONE => NONE
| SOME T => substFn theta (lval,c1)
| SOME F => substFn theta (lval,c2))
Termination
WF_REL_TAC ‘inv_image
(measure csize LEX measure remaining_lvals)
(\(b,c,d). (d,(b,c)))’
>> rw [csize_def]
>- (fs [remaining_lvals_def,ConsTag_def, NilTag_def]
>> rw[]
>> irule CARD_PSUBSET >> conj_tac
>- (rw [lvdescendants_def]
>> irule SUBSET_FINITE
>> qexists_tac ‘FDOM theta’
>> rw[SUBSET_DEF])
>- (rw[PSUBSET_MEMBER,SUBSET_DEF,lvdescendants_def]
>- metis_tac [lvprefixes_Recd_downclosed]
>- (qexists_tac ‘RecdProj lval "tag"’
>> rw[]
>- metis_tac [flookup_thm]
>- rw [lvprefixes_def,lvprefixes_refl]
>- (disj2_tac >> disch_tac
>> imp_res_tac lvsize_lvprefixes
>> fs [lvsize_def]))))
>- (disj1_tac >> Induct_on `fields` >> rw[list_size_def] >> rw[] >> fs[])
End
(*---------------------------------------------------------------------------*)
(* Successful evaluation is stable. *)
(*---------------------------------------------------------------------------*)
Theorem evalExp_submap :
∀e theta1 theta2 v.
theta1 SUBMAP theta2 ∧
evalExp theta1 e = SOME v
⇒
evalExp theta2 e = SOME v
Proof
Induct
>> rw [evalExp_def]
>> every_case_tac >> fs []
>> metis_tac[FLOOKUP_SUBMAP,NOT_SOME_NONE,SOME_11]
QED
Theorem evalBexp_submap :
∀bexp theta1 theta2 v.
theta1 SUBMAP theta2 ∧
evalBexp theta1 bexp = SOME v
⇒
evalBexp theta2 bexp = SOME v
Proof
Induct
>> rw [evalBexp_def]
>> every_case_tac
>> fs []
>> metis_tac[FLOOKUP_SUBMAP,NOT_SOME_NONE,SOME_11,evalExp_submap]
QED
(*---------------------------------------------------------------------------*)
(* The matcher only adds new bindings to theta. *)
(*---------------------------------------------------------------------------*)
Theorem match_submap :
!wklist s theta s2 theta'.
matchFn (wklist,s,theta) = SOME (s2, theta')
==>
finite_map$SUBMAP theta theta'
Proof
recInduct matchFn_ind
>> rpt gen_tac >> strip_tac
>> rw_tac list_ss [Once matchFn_def]
>> every_case_tac
>> rw[]
>> fs [SUBMAP_FUPDATE]
>> rfs[]
>> rw[]
>> metis_tac [SUBMAP_DOMSUB_gen,DOMSUB_NOT_IN_DOM]
QED
(*---------------------------------------------------------------------------*)
(* Apply a substitution to a worklist *)
(*---------------------------------------------------------------------------*)
Definition substWk_def :
substWk theta wklist = concatPartial (MAP (substFn theta) wklist)
End
(*---------------------------------------------------------------------------*)
(* The substitution computed by matchFn is correctly applied by substWk *)
(*---------------------------------------------------------------------------*)
Theorem match_lem :
!wklist (s:string) theta s2 theta'.
matchFn (wklist,s,theta) = SOME (s2, theta')
==>
?s1. substWk theta' wklist = SOME s1 /\ s1 ++ s2 = s
Proof
simp_tac list_ss [substWk_def]
>> recInduct matchFn_ind
>> rpt gen_tac
>> strip_tac
>> rw_tac list_ss [Once matchFn_def]
>> simpCases_on ‘worklist’
>> TRY (Cases_on ‘h’ >> simpCases_on ‘r’)
>- rw[concatPartial_thm]
>- (simpCases_on ‘take_drop (atomWidth a) s’
>> simpCases_on ‘x’
>> qexists_tac ‘q' ++ s1’
>> ‘s = STRCAT q' (STRCAT s1 s2)’ by metis_tac [take_drop_thm]
>> rw []
>> rw [Once substFn_def]
>> ‘(theta |+ (q,q')) SUBMAP theta'’ by metis_tac [match_submap]
>> ‘FLOOKUP (theta |+ (q,q')) q = SOME q'’ by metis_tac [FLOOKUP_UPDATE]
>> ‘FLOOKUP theta' q = SOME q'’ by metis_tac [FLOOKUP_SUBMAP]
>> rw[]
>> fs [concatPartial_thm])
>- (simpCases_on ‘evalBexp theta b’
>> ‘theta SUBMAP theta'’ by metis_tac [match_submap]
>> ‘evalBexp theta' b = SOME T’ by metis_tac [evalBexp_submap]
>> rw[Once substFn_def]
>> fs [concatPartial_thm])
>- (rw[Once substFn_def]
>> fs [concatPartial_thm,MAP_MAP_o, combinTheory.o_DEF,fieldFn_def,LAMBDA_PROD,IS_SOME_NEG]
>> rw []
>> fs [GSYM (SIMP_RULE std_ss [o_DEF] NOT_EXISTS)]
>> metis_tac [NOT_EXISTS])
>- (simpCases_on ‘evalExp theta e’
>> ‘theta SUBMAP theta'’ by metis_tac [match_submap]
>> ‘evalExp theta' e = SOME x’ by metis_tac [evalExp_submap]
>> rw[Once substFn_def]
>> fs [concatPartial_thm,MAP_MAP_o, combinTheory.o_DEF,indexFn_def,LAMBDA_PROD,IS_SOME_NEG]
>> rw []
>> fs [GSYM (SIMP_RULE std_ss [o_DEF] NOT_EXISTS)]
>> metis_tac [NOT_EXISTS])
>- (simpCases_on ‘take_drop 1 s’
>> simpCases_on ‘x’
>> ‘∃tag lval. q' = tag ∧ q = lval’ by metis_tac[] >> ntac 2 (pop_subst_tac)
>> qexists_tac ‘tag ++ s1’
>> ‘s = STRCAT tag (STRCAT s1 s2)’ by metis_tac [take_drop_thm]
>> ‘(theta |+ (RecdProj lval "tag", tag)) SUBMAP theta'’ by metis_tac [match_submap]
>> ‘FLOOKUP (theta |+ (RecdProj lval "tag",tag))
(RecdProj lval "tag") = SOME tag’ by metis_tac [FLOOKUP_UPDATE]
>> ‘FLOOKUP theta' (RecdProj lval "tag") = SOME tag’ by metis_tac [FLOOKUP_SUBMAP]
>> pop_assum (fn th => popk_tac >> assume_tac th)
>> rw[Once substFn_def]
>- (fs [concatPartial_thm,MAP_MAP_o, combinTheory.o_DEF,LAMBDA_PROD,IS_SOME_NEG]
>> rw []
>> fs [GSYM (SIMP_RULE std_ss [o_DEF] NOT_EXISTS)]
>> rw [Once substFn_def,ListRecd_def,evalBexp_def,evalExp_def,NilTag_def,valFn_def]
>> rw [Once substFn_def,concatPartial_nil])
>- (fs [ConsTag_def, NilTag_def] >> rw[]
>> qpat_x_assum ‘matchFn _ = _’ kall_tac
>> qpat_x_assum ‘take_drop _ _ = _’ kall_tac
>> qpat_x_assum ‘~(_ IN _)’ kall_tac
>> qpat_x_assum ‘_ SUBMAP _’ kall_tac
>> fs [concatPartial_thm,MAP_MAP_o, combinTheory.o_DEF,LAMBDA_PROD,IS_SOME_NEG]
>> rw []
>> qpat_x_assum ‘EVERY _ _’ kall_tac
>> qpat_x_assum ‘~(substFn _ _ = NONE)’
(mp_tac o SIMP_RULE (srw_ss()) [Once substFn_def,ListRecd_def])
>> rw [evalBexp_def,evalExp_def,NilTag_def,ConsTag_def,valFn_def]
>> qpat_x_assum ‘~(substFn _ _ = NONE)’
(mp_tac o SIMP_RULE (srw_ss()) [Once substFn_def])
>> rw [evalBexp_def,evalExp_def,NilTag_def,ConsTag_def,valFn_def]
>> qpat_x_assum ‘~(substFn _ _ = NONE)’
(mp_tac o SIMP_RULE (srw_ss()) [Once substFn_def])
>> rw [concatPartial_thm]
(* last clause *)
>> rw [SimpRHS, Once substFn_def,ListRecd_def]
>> rw [evalBexp_def,evalExp_def,NilTag_def,ConsTag_def,valFn_def]
>> rw [SimpRHS, Once substFn_def]
>> rw [evalBexp_def,evalExp_def,NilTag_def,ConsTag_def,valFn_def]
>> rw [SimpRHS, Once substFn_def]
>> rw [concatPartial_thm])
>- (qpat_x_assum ‘concatPartial _ = _ ’ mp_tac
>> rw [Once substFn_def,ListRecd_def,evalBexp_def,evalExp_def,NilTag_def]
>> ‘∃n. valFn tag = SOME n ∧ ~(n=0) ∧ ~(n=1)’
by (‘STRLEN tag = 1’ by metis_tac [take_drop_thm]
>> fs [strlen_eq_1,NilTag_def,ConsTag_def]
>> rw[]
>> ntac 2 (pop_assum mp_tac)
>> rw [CHR_11]
>> qexists_tac ‘n’
>> rw[valFn_def,l2n_def])
>> full_case_tac >> fs[] >> rw[] >> rfs[]
>> rw [concatPartial_thm]
>> pop_assum mp_tac
>> rw [Once substFn_def,ListRecd_def,evalBexp_def,evalExp_def,ConsTag_def]
>> rw [Once substFn_def,concatPartial_thm]))
>- (simpCases_on ‘evalBexp theta b’
>> simpCases_on ‘x’
>> ‘theta SUBMAP theta'’ by metis_tac [match_submap]
>> ‘∃lval bexp. lval = q ∧ bexp = q'’ by metis_tac[]
>> rw[]
>- (‘evalBexp theta' b = SOME T’ by metis_tac [evalBexp_submap]
>> rw[Once substFn_def]
>> every_case_tac
>> rw [])
>- (‘evalBexp theta' b = SOME F’ by metis_tac [evalBexp_submap]
>> rw[Once substFn_def]
>> every_case_tac
>> rw []))
QED
Theorem match_subst_thm :
!vFn wklist (s:string) theta s2 theta'.
matchFn (wklist,s,theta) = SOME (s2, theta')
==>
THE (substWk theta' wklist) ++ s2 = s
Proof
metis_tac [match_lem,optionTheory.THE_DEF]
QED
Definition arb_label_recd_def:
arb_label_recd clist = Recd (MAP (\c. (ARB, c)) clist)
End
Theorem field_names_ignored:
∀plist1 plist2 theta.
(MAP SND plist1 = MAP SND plist2)
⇒
Contig_Lang theta (Recd plist1) = Contig_Lang theta (Recd plist2)
Proof
fs [Contig_Lang_def]
QED
Triviality map_snd_fieldFn :
∀plist x. MAP SND (MAP (fieldFn x) plist) = MAP SND plist
Proof
Induct >> fs [fieldFn_def,FORALL_PROD]
QED
Triviality snd_indexFn :
!n q c. (SND o indexFn q c) n = c
Proof
rw[combinTheory.o_DEF, indexFn_def]
QED
Triviality map_snd_indexFn :
∀n q c. MAP SND (MAP (indexFn q c) (COUNT_LIST n)) = REPLICATE n c
Proof
fs [MAP_MAP_o,MAP_COUNT_LIST,REPLICATE_GENLIST,GENLIST_FUN_EQ,snd_indexFn]
QED
Theorem every_list_rel_replicate :
!list a R.
EVERY (R a) list <=> LIST_REL (\x y. R y x) list (REPLICATE (LENGTH list) a)
Proof
Induct >> rw[]
QED
Triviality map_snd_lem :
∀list x. MAP SND (MAP (\c. (x,c)) list) = list
Proof
Induct >> fs []
QED
Theorem Recd_flatA :
∀s plist1 plist2 theta fName.
s IN Contig_Lang theta (Recd ((fName,Recd plist1)::plist2)) ==>
s IN Contig_Lang theta (Recd (plist1 ++ plist2))
Proof
rw [Contig_Lang_def]
>> qexists_tac ‘slist' ++ xs’
>> rw[] >> metis_tac [LIST_REL_APPEND_suff]
QED
Theorem Recd_flatB :
∀s fields1 fields2 theta fName.
s IN Contig_Lang theta (Recd (fields1 ++ fields2))
==>
s IN Contig_Lang theta (Recd ((fName,Recd fields1)::fields2))
Proof
rw [Contig_Lang_def]
>> fs [LIST_REL_SPLIT2]
>> rw[PULL_EXISTS]
>> metis_tac []
QED
Theorem Recd_flat :
∀s plist1 plist2 theta fName.
s IN Contig_Lang theta (Recd ((fName,Recd plist1)::plist2)) <=>
s IN Contig_Lang theta (Recd (plist1 ++ plist2))
Proof
metis_tac [Recd_flatA,Recd_flatB]
QED
Theorem Recd_Array_flat :
∀s e n c clist theta.
evalExp theta e = SOME n
==>
(s IN Contig_Lang theta (arb_label_recd (Array c e::clist))
<=>
s IN Contig_Lang theta (arb_label_recd (REPLICATE n c ⧺ clist)))
Proof
rw[IN_Contig_Lang,arb_label_recd_def,EQ_IMP_THM,PULL_EXISTS]
>- (qexists_tac ‘slist' ++ xs’
>> fs[map_snd_lem]
>> match_mp_tac LIST_REL_APPEND_suff
>> rw[]
>> imp_res_tac every_list_rel_replicate
>> fs [IN_DEF])
>- (fs[map_snd_lem,LIST_REL_SPLIT2]
>> rw[]
>> qexists_tac ‘ys2’
>> qexists_tac ‘ys1’
>> rw[]
>- metis_tac [LENGTH_REPLICATE,LIST_REL_LENGTH]
>- (rw[every_list_rel_replicate]
>> ‘LENGTH ys1 = LENGTH (REPLICATE n c)’ by metis_tac [LIST_REL_LENGTH]
>> fs [LENGTH_REPLICATE,IN_DEF]))
QED
Theorem Recd_Alt_flatA :
∀s b c1 c2 clist theta.
evalBexp theta b = SOME T
==>
(s IN Contig_Lang theta (arb_label_recd (Alt b c1 c2::clist))
<=>
s IN Contig_Lang theta (arb_label_recd (c1::clist)))
Proof
rw[IN_Contig_Lang,arb_label_recd_def,EQ_IMP_THM,PULL_EXISTS]
QED
Theorem Recd_Alt_flatB :
∀s b c1 c2 clist theta.
evalBexp theta b = SOME F
==>
(s IN Contig_Lang theta (arb_label_recd (Alt b c1 c2::clist))
<=>
s IN Contig_Lang theta (arb_label_recd (c2::clist)))
Proof
rw[IN_Contig_Lang,arb_label_recd_def,EQ_IMP_THM,PULL_EXISTS]
QED
Theorem Contig_Singleton_Recd :
!s theta contig fName.
s IN Contig_Lang theta (Recd [(fName,contig)])
<=>
s IN Contig_Lang theta contig
Proof
rw [IN_Contig_Lang,PULL_EXISTS]
QED
Theorem matchFn_wklist_sound :
!wklist s fmap suffix theta.
matchFn (wklist,s,fmap) = SOME (suffix, theta)
==>
∃prefix. (s = prefix ++ suffix) ∧
prefix IN Contig_Lang theta (arb_label_recd (MAP SND wklist))
Proof
recInduct matchFn_ind
>> simp_tac list_ss []
>> rpt gen_tac
>> strip_tac
>> simp_tac list_ss [Once matchFn_def]
>> simpCases_on ‘worklist’
>> TRY (Cases_on ‘h’ >> simpCases_on ‘r’)
>- rw [IN_Contig_Lang,arb_label_recd_def]
>- (simpCases_on ‘take_drop (atomWidth a) s’
>> simpCases_on ‘x’
>> qexists_tac ‘q' ++ prefix’
>> rw [IN_Contig_Lang,arb_label_recd_def,PULL_EXISTS]
>- (imp_res_tac take_drop_thm >> fs [])
>- (imp_res_tac take_drop_thm
>> fs [IN_Contig_Lang,arb_label_recd_def,PULL_EXISTS,map_snd_lem]
>> rw[]
>> metis_tac[]))
>- (simpCases_on ‘evalBexp theta b’
>> ‘theta SUBMAP theta'’ by metis_tac [match_submap]
>> ‘evalBexp theta' b = SOME T’ by metis_tac [evalBexp_submap]
>> fs[IN_Contig_Lang,arb_label_recd_def,PULL_EXISTS,map_snd_lem]
>> metis_tac[])
>- (fs[map_snd_fieldFn]
>> ‘Contig_Lang theta' (arb_label_recd (MAP SND l ⧺ MAP SND t)) =
Contig_Lang theta' (arb_label_recd (Recd l::MAP SND t))’
by (rw [arb_label_recd_def,Recd_flat,EXTENSION]
>> AP_TERM_TAC
>> match_mp_tac field_names_ignored
>> rw[map_snd_lem])
>> metis_tac[])
>- (simpCases_on ‘evalExp theta e’
>> fs[map_snd_indexFn]
>> ‘theta SUBMAP theta'’ by metis_tac [match_submap]
>> ‘evalExp theta' e = SOME x’ by metis_tac [evalExp_submap]
>> ‘Contig_Lang theta' (arb_label_recd (Array c e::MAP SND t)) =
Contig_Lang theta' (arb_label_recd (REPLICATE x c ⧺ MAP SND t))’
by rw [EXTENSION,GSYM Recd_Array_flat]
>> metis_tac [map_snd_indexFn])
>- (simpCases_on ‘take_drop 1 s’
>> simpCases_on ‘x’
>> ‘∃tag lval. q' = tag ∧ q = lval’ by metis_tac[] >> ntac 2 (pop_subst_tac)
>> qexists_tac ‘tag ++ prefix’
>> ‘s = STRCAT tag (STRCAT prefix suffix)’ by metis_tac [take_drop_thm]
>> rw[]
>> ‘(theta |+ (RecdProj lval "tag", tag)) SUBMAP theta'’ by metis_tac [match_submap]
>> ‘FLOOKUP (theta |+ (RecdProj lval "tag",tag))
(RecdProj lval "tag") = SOME tag’ by metis_tac [FLOOKUP_UPDATE]
>> ‘FLOOKUP theta' (RecdProj lval "tag") = SOME tag’ by metis_tac [FLOOKUP_SUBMAP]
>> pop_assum (fn th => popk_tac >> assume_tac th)
>> qpat_x_assum ‘matchFn _ = _’ kall_tac
>> ‘STRLEN tag = 1’ by metis_tac [take_drop_thm]
>> qpat_x_assum ‘take_drop _ _ = _’ kall_tac
>> qpat_x_assum ‘~(_ IN _)’ kall_tac
>> qpat_x_assum ‘_ SUBMAP _’ kall_tac
>> qpat_x_assum ‘prefix IN Contig_Lang _ _’
(strip_assume_tac o SIMP_RULE (srw_ss())
[IN_Contig_Lang,arb_label_recd_def,ListRecd_def,PULL_EXISTS,map_snd_lem,
evalExp_def, evalBexp_def])
>> rw[] >> rfs[option_case_eq] >> fs [] >> rw[]
>> simpCases_on ‘n1’
>- (‘tag = [NilTag]’
by (fs [strlen_eq_1,NilTag_def]
>> rw[]
>> fs[valFn_def,l2n_def]
>> qpat_x_assum ‘_ = 0’ mp_tac
>> rw [ORD_CHR_RWT])
>> rw [IN_Contig_Lang,arb_label_recd_def,PULL_EXISTS,map_snd_lem]
>> qexists_tac ‘xs’
>> qexists_tac ‘[]’
>> rw [])
>- (‘tag = [ConsTag]’
by (fs [strlen_eq_1,ConsTag_def]
>> rw[]
>> fs[valFn_def,l2n_def]
>> qpat_x_assum ‘_ = 1’ mp_tac
>> rw [ORD_CHR_RWT])
>> qpat_x_assum ‘valFn tag = _’ kall_tac
>> qpat_x_assum ‘valFn tag = _’ kall_tac
>> qpat_x_assum ‘STRLEN tag = _’ kall_tac
>> rw [IN_Contig_Lang,arb_label_recd_def,PULL_EXISTS,map_snd_lem]
>> qexists_tac ‘xs’
>> qexists_tac ‘STRCAT [ConsTag] s' :: slist'’
>> rpt conj_tac
>- rw []
>- rw []
>- metis_tac[]))
>- (simpCases_on ‘evalBexp theta b’
>> simpCases_on ‘x’
>> ‘theta SUBMAP theta'’ by metis_tac [match_submap]
>- (‘evalBexp theta' b = SOME T’ by metis_tac [evalBexp_submap]
>> rw [Recd_Alt_flatA])
>- (‘evalBexp theta' b = SOME F’ by metis_tac [evalBexp_submap]
>> rw [Recd_Alt_flatB]))
QED
Theorem matchFn_sound :
!contig s theta.
matchFn ([(VarName"root",contig)],s,FEMPTY) = SOME ("", theta)
==>
s IN Contig_Lang theta contig
Proof
rw[]
>> imp_res_tac (matchFn_wklist_sound |> SIMP_RULE std_ss [])
>> rw []
>> fs [arb_label_recd_def,Contig_Singleton_Recd]
QED
val _ = export_theory();