Theory Wasm_Ast
section ‹WebAssembly Core AST›
theory Wasm_Ast
imports
Main
"Native_Word.Uint8"
"Word_Lib.Reversed_Bit_Lists"
begin
type_synonym
i = nat
type_synonym
off = nat
type_synonym
a = nat
typedecl i32
typedecl i64
typedecl f32
typedecl f64
type_synonym byte = uint8
typedef bytes = "UNIV :: (byte list) set" ..
setup_lifting type_definition_bytes
declare Quotient_bytes[transfer_rule]
lift_definition bytes_takefill :: "byte ⇒ nat ⇒ bytes ⇒ bytes" is "(λa n as. takefill (Abs_uint8 a) n as)" .
lift_definition bytes_replicate :: "nat ⇒ byte ⇒ bytes" is "(λn b. replicate n (Abs_uint8 b))" .
definition msbyte :: "bytes ⇒ byte" where
"msbyte bs = last (Rep_bytes bs)"
typedef mem = "UNIV :: (byte list) set" ..
setup_lifting type_definition_mem
declare Quotient_mem[transfer_rule]
lift_definition read_bytes :: "mem ⇒ nat ⇒ nat ⇒ bytes" is "(λm n l. take l (drop n m))" .
lift_definition write_bytes :: "mem ⇒ nat ⇒ bytes ⇒ mem" is "(λm n bs. (take n m) @ bs @ (drop (n + length bs) m))" .
lift_definition mem_append :: "mem ⇒ bytes ⇒ mem" is append .
typedecl host
typedecl host_state
datatype
t = T_i32 | T_i64 | T_f32 | T_f64
datatype
tp = Tp_i8 | Tp_i16 | Tp_i32
datatype
mut = T_immut | T_mut
record tg =
tg_mut :: mut
tg_t :: t
datatype
tf = Tf "t list" "t list" ("_ '_> _" 60)
record t_context =
types_t :: "tf list"
func_t :: "tf list"
global :: "tg list"
table :: "nat option"
memory :: "nat option"
local :: "t list"
label :: "(t list) list"
return :: "(t list) option"
record s_context =
s_inst :: "t_context list"
s_funcs :: "tf list"
s_tab :: "nat list"
s_mem :: "nat list"
s_globs :: "tg list"
datatype
sx = S | U
datatype
unop_i = Clz | Ctz | Popcnt
datatype
unop_f = Neg | Abs | Ceil | Floor | Trunc | Nearest | Sqrt
datatype
binop_i = Add | Sub | Mul | Div sx | Rem sx | And | Or | Xor | Shl | Shr sx | Rotl | Rotr
datatype
binop_f = Addf | Subf | Mulf | Divf | Min | Max | Copysign
datatype
testop = Eqz
datatype
relop_i = Eq | Ne | Lt sx | Gt sx | Le sx | Ge sx
datatype
relop_f = Eqf | Nef | Ltf | Gtf | Lef | Gef
datatype
cvtop = Convert | Reinterpret
datatype
v =
ConstInt32 i32
| ConstInt64 i64
| ConstFloat32 f32
| ConstFloat64 f64
datatype
b_e =
Unreachable
| Nop
| Drop
| Select
| Block tf "b_e list"
| Loop tf "b_e list"
| If tf "b_e list" "b_e list"
| Br i
| Br_if i
| Br_table "i list" i
| Return
| Call i
| Call_indirect i
| Get_local i
| Set_local i
| Tee_local i
| Get_global i
| Set_global i
| Load t "(tp × sx) option" a off
| Store t "tp option" a off
| Current_memory
| Grow_memory
| EConst v ("C _" 60)
| Unop_i t unop_i
| Unop_f t unop_f
| Binop_i t binop_i
| Binop_f t binop_f
| Testop t testop
| Relop_i t relop_i
| Relop_f t relop_f
| Cvtop t cvtop t "sx option"
datatype cl =
Func_native i tf "t list" "b_e list"
| Func_host tf host
record inst =
types :: "tf list"
funcs :: "i list"
tab :: "i option"
mem :: "i option"
globs :: "i list"
type_synonym tabinst = "(cl option) list"
record global =
g_mut :: mut
g_val :: v
record s =
inst :: "inst list"
funcs :: "cl list"
tab :: "tabinst list"
mem :: "mem list"
globs :: "global list"
datatype e =
Basic b_e ("$_" 60)
| Trap
| Callcl cl
| Label nat "e list" "e list"
| Local nat i "v list" "e list"
datatype Lholed =
LBase "e list" "e list"
| LRec "e list" nat "e list" Lholed "e list"
end
Theory Wasm_Type_Abs
section ‹Syntactic Typeclasses›
theory Wasm_Type_Abs imports Main begin
class wasm_base = zero
class wasm_int = wasm_base +
fixes int_clz :: "'a ⇒ 'a"
fixes int_ctz :: "'a ⇒ 'a"
fixes int_popcnt :: "'a ⇒ 'a"
fixes int_add :: "'a ⇒ 'a ⇒ 'a"
fixes int_sub :: "'a ⇒ 'a ⇒ 'a"
fixes int_mul :: "'a ⇒ 'a ⇒ 'a"
fixes int_div_u :: "'a ⇒ 'a ⇒ 'a option"
fixes int_div_s :: "'a ⇒ 'a ⇒ 'a option"
fixes int_rem_u :: "'a ⇒ 'a ⇒ 'a option"
fixes int_rem_s :: "'a ⇒ 'a ⇒ 'a option"
fixes int_and :: "'a ⇒ 'a ⇒ 'a"
fixes int_or :: "'a ⇒ 'a ⇒ 'a"
fixes int_xor :: "'a ⇒ 'a ⇒ 'a"
fixes int_shl :: "'a ⇒ 'a ⇒ 'a"
fixes int_shr_u :: "'a ⇒ 'a ⇒ 'a"
fixes int_shr_s :: "'a ⇒ 'a ⇒ 'a"
fixes int_rotl :: "'a ⇒ 'a ⇒ 'a"
fixes int_rotr :: "'a ⇒ 'a ⇒ 'a"
fixes int_eqz :: "'a ⇒ bool"
fixes int_eq :: "'a ⇒ 'a ⇒ bool"
fixes int_lt_u :: "'a ⇒ 'a ⇒ bool"
fixes int_lt_s :: "'a ⇒ 'a ⇒ bool"
fixes int_gt_u :: "'a ⇒ 'a ⇒ bool"
fixes int_gt_s :: "'a ⇒ 'a ⇒ bool"
fixes int_le_u :: "'a ⇒ 'a ⇒ bool"
fixes int_le_s :: "'a ⇒ 'a ⇒ bool"
fixes int_ge_u :: "'a ⇒ 'a ⇒ bool"
fixes int_ge_s :: "'a ⇒ 'a ⇒ bool"
fixes int_of_nat :: "nat ⇒ 'a"
fixes nat_of_int :: "'a ⇒ nat"
begin
abbreviation (input)
int_ne where
"int_ne x y ≡ ¬ (int_eq x y)"
end
class wasm_float = wasm_base +
fixes float_neg :: "'a ⇒ 'a"
fixes float_abs :: "'a ⇒ 'a"
fixes float_ceil :: "'a ⇒ 'a"
fixes float_floor :: "'a ⇒ 'a"
fixes float_trunc :: "'a ⇒ 'a"
fixes float_nearest :: "'a ⇒ 'a"
fixes float_sqrt :: "'a ⇒ 'a"
fixes float_add :: "'a ⇒ 'a ⇒ 'a"
fixes float_sub :: "'a ⇒ 'a ⇒ 'a"
fixes float_mul :: "'a ⇒ 'a ⇒ 'a"
fixes float_div :: "'a ⇒ 'a ⇒ 'a"
fixes float_min :: "'a ⇒ 'a ⇒ 'a"
fixes float_max :: "'a ⇒ 'a ⇒ 'a"
fixes float_copysign :: "'a ⇒ 'a ⇒ 'a"
fixes float_eq :: "'a ⇒ 'a ⇒ bool"
fixes float_lt :: "'a ⇒ 'a ⇒ bool"
fixes float_gt :: "'a ⇒ 'a ⇒ bool"
fixes float_le :: "'a ⇒ 'a ⇒ bool"
fixes float_ge :: "'a ⇒ 'a ⇒ bool"
begin
abbreviation (input)
float_ne where
"float_ne x y ≡ ¬ (float_eq x y)"
end
end
Theory Wasm_Base_Defs
section ‹WebAssembly Base Definitions›
theory Wasm_Base_Defs imports Wasm_Ast Wasm_Type_Abs begin
instantiation i32 :: wasm_int begin instance .. end
instantiation i64 :: wasm_int begin instance .. end
instantiation f32 :: wasm_float begin instance .. end
instantiation f64 :: wasm_float begin instance .. end
consts
ui32_trunc_f32 :: "f32 ⇒ i32 option"
si32_trunc_f32 :: "f32 ⇒ i32 option"
ui32_trunc_f64 :: "f64 ⇒ i32 option"
si32_trunc_f64 :: "f64 ⇒ i32 option"
ui64_trunc_f32 :: "f32 ⇒ i64 option"
si64_trunc_f32 :: "f32 ⇒ i64 option"
ui64_trunc_f64 :: "f64 ⇒ i64 option"
si64_trunc_f64 :: "f64 ⇒ i64 option"
f32_convert_ui32 :: "i32 ⇒ f32"
f32_convert_si32 :: "i32 ⇒ f32"
f32_convert_ui64 :: "i64 ⇒ f32"
f32_convert_si64 :: "i64 ⇒ f32"
f64_convert_ui32 :: "i32 ⇒ f64"
f64_convert_si32 :: "i32 ⇒ f64"
f64_convert_ui64 :: "i64 ⇒ f64"
f64_convert_si64 :: "i64 ⇒ f64"
wasm_wrap :: "i64 ⇒ i32"
wasm_extend_u :: "i32 ⇒ i64"
wasm_extend_s :: "i32 ⇒ i64"
wasm_demote :: "f64 ⇒ f32"
wasm_promote :: "f32 ⇒ f64"
serialise_i32 :: "i32 ⇒ bytes"
serialise_i64 :: "i64 ⇒ bytes"
serialise_f32 :: "f32 ⇒ bytes"
serialise_f64 :: "f64 ⇒ bytes"
wasm_bool :: "bool ⇒ i32"
int32_minus_one :: i32
definition mem_size :: "mem ⇒ nat" where
"mem_size m = length (Rep_mem m)"
definition mem_grow :: "mem ⇒ nat ⇒ mem" where
"mem_grow m n = mem_append m (bytes_replicate (n * 64000) 0)"
definition load :: "mem ⇒ nat ⇒ off ⇒ nat ⇒ bytes option" where
"load m n off l = (if (mem_size m ≥ (n+off+l))
then Some (read_bytes m (n+off) l)
else None)"
definition sign_extend :: "sx ⇒ nat ⇒ bytes ⇒ bytes" where
"sign_extend sx l bytes = (let msb = msb (msbyte bytes) in
let byte = (case sx of U ⇒ 0 | S ⇒ if msb then -1 else 0) in
bytes_takefill byte l bytes)"
definition load_packed :: "sx ⇒ mem ⇒ nat ⇒ off ⇒ nat ⇒ nat ⇒ bytes option" where
"load_packed sx m n off lp l = map_option (sign_extend sx l) (load m n off lp)"
definition store :: "mem ⇒ nat ⇒ off ⇒ bytes ⇒ nat ⇒ mem option" where
"store m n off bs l = (if (mem_size m ≥ (n+off+l))
then Some (write_bytes m (n+off) (bytes_takefill 0 l bs))
else None)"
definition store_packed :: "mem ⇒ nat ⇒ off ⇒ bytes ⇒ nat ⇒ mem option" where
"store_packed = store"
consts
wasm_deserialise :: "bytes ⇒ t ⇒ v"
host_apply :: "s ⇒ tf ⇒ host ⇒ v list ⇒ host_state ⇒ (s × v list) option"
definition typeof :: " v ⇒ t" where
"typeof v = (case v of
ConstInt32 _ ⇒ T_i32
| ConstInt64 _ ⇒ T_i64
| ConstFloat32 _ ⇒ T_f32
| ConstFloat64 _ ⇒ T_f64)"
definition option_projl :: "('a × 'b) option ⇒ 'a option" where
"option_projl x = map_option fst x"
definition option_projr :: "('a × 'b) option ⇒ 'b option" where
"option_projr x = map_option snd x"
definition t_length :: "t ⇒ nat" where
"t_length t = (case t of
T_i32 ⇒ 4
| T_i64 ⇒ 8
| T_f32 ⇒ 4
| T_f64 ⇒ 8)"
definition tp_length :: "tp ⇒ nat" where
"tp_length tp = (case tp of
Tp_i8 ⇒ 1
| Tp_i16 ⇒ 2
| Tp_i32 ⇒ 4)"
definition is_int_t :: "t ⇒ bool" where
"is_int_t t = (case t of
T_i32 ⇒ True
| T_i64 ⇒ True
| T_f32 ⇒ False
| T_f64 ⇒ False)"
definition is_float_t :: "t ⇒ bool" where
"is_float_t t = (case t of
T_i32 ⇒ False
| T_i64 ⇒ False
| T_f32 ⇒ True
| T_f64 ⇒ True)"
definition is_mut :: "tg ⇒ bool" where
"is_mut tg = (tg_mut tg = T_mut)"
definition app_unop_i :: "unop_i ⇒ 'i::wasm_int ⇒ 'i::wasm_int" where
"app_unop_i iop c =
(case iop of
Ctz ⇒ int_ctz c
| Clz ⇒ int_clz c
| Popcnt ⇒ int_popcnt c)"
definition app_unop_f :: "unop_f ⇒ 'f::wasm_float ⇒ 'f::wasm_float" where
"app_unop_f fop c =
(case fop of
Neg ⇒ float_neg c
| Abs ⇒ float_abs c
| Ceil ⇒ float_ceil c
| Floor ⇒ float_floor c
| Trunc ⇒ float_trunc c
| Nearest ⇒ float_nearest c
| Sqrt ⇒ float_sqrt c)"
definition app_binop_i :: "binop_i ⇒ 'i::wasm_int ⇒ 'i::wasm_int ⇒ ('i::wasm_int) option" where
"app_binop_i iop c1 c2 = (case iop of
Add ⇒ Some (int_add c1 c2)
| Sub ⇒ Some (int_sub c1 c2)
| Mul ⇒ Some (int_mul c1 c2)
| Div U ⇒ int_div_u c1 c2
| Div S ⇒ int_div_s c1 c2
| Rem U ⇒ int_rem_u c1 c2
| Rem S ⇒ int_rem_s c1 c2
| And ⇒ Some (int_and c1 c2)
| Or ⇒ Some (int_or c1 c2)
| Xor ⇒ Some (int_xor c1 c2)
| Shl ⇒ Some (int_shl c1 c2)
| Shr U ⇒ Some (int_shr_u c1 c2)
| Shr S ⇒ Some (int_shr_s c1 c2)
| Rotl ⇒ Some (int_rotl c1 c2)
| Rotr ⇒ Some (int_rotr c1 c2))"
definition app_binop_f :: "binop_f ⇒ 'f::wasm_float ⇒ 'f::wasm_float ⇒ ('f::wasm_float) option" where
"app_binop_f fop c1 c2 = (case fop of
Addf ⇒ Some (float_add c1 c2)
| Subf ⇒ Some (float_sub c1 c2)
| Mulf ⇒ Some (float_mul c1 c2)
| Divf ⇒ Some (float_div c1 c2)
| Min ⇒ Some (float_min c1 c2)
| Max ⇒ Some (float_max c1 c2)
| Copysign ⇒ Some (float_copysign c1 c2))"
definition app_testop_i :: "testop ⇒ 'i::wasm_int ⇒ bool" where
"app_testop_i testop c = (case testop of Eqz ⇒ int_eqz c)"
definition app_relop_i :: "relop_i ⇒ 'i::wasm_int ⇒ 'i::wasm_int ⇒ bool" where
"app_relop_i rop c1 c2 = (case rop of
Eq ⇒ int_eq c1 c2
| Ne ⇒ int_ne c1 c2
| Lt U ⇒ int_lt_u c1 c2
| Lt S ⇒ int_lt_s c1 c2
| Gt U ⇒ int_gt_u c1 c2
| Gt S ⇒ int_gt_s c1 c2
| Le U ⇒ int_le_u c1 c2
| Le S ⇒ int_le_s c1 c2
| Ge U ⇒ int_ge_u c1 c2
| Ge S ⇒ int_ge_s c1 c2)"
definition app_relop_f :: "relop_f ⇒ 'f::wasm_float ⇒ 'f::wasm_float ⇒ bool" where
"app_relop_f rop c1 c2 = (case rop of
Eqf ⇒ float_eq c1 c2
| Nef ⇒ float_ne c1 c2
| Ltf ⇒ float_lt c1 c2
| Gtf ⇒ float_gt c1 c2
| Lef ⇒ float_le c1 c2
| Gef ⇒ float_ge c1 c2)"
definition types_agree :: "t ⇒ v ⇒ bool" where
"types_agree t v = (typeof v = t)"
definition cl_type :: "cl ⇒ tf" where
"cl_type cl = (case cl of Func_native _ tf _ _ ⇒ tf | Func_host tf _ ⇒ tf)"
definition rglob_is_mut :: "global ⇒ bool" where
"rglob_is_mut g = (g_mut g = T_mut)"
definition stypes :: "s ⇒ nat ⇒ nat ⇒ tf" where
"stypes s i j = ((types ((inst s)!i))!j)"
definition sfunc_ind :: "s ⇒ nat ⇒ nat ⇒ nat" where
"sfunc_ind s i j = ((inst.funcs ((inst s)!i))!j)"
definition sfunc :: "s ⇒ nat ⇒ nat ⇒ cl" where
"sfunc s i j = (funcs s)!(sfunc_ind s i j)"
definition sglob_ind :: "s ⇒ nat ⇒ nat ⇒ nat" where
"sglob_ind s i j = ((inst.globs ((inst s)!i))!j)"
definition sglob :: "s ⇒ nat ⇒ nat ⇒ global" where
"sglob s i j = (globs s)!(sglob_ind s i j)"
definition sglob_val :: "s ⇒ nat ⇒ nat ⇒ v" where
"sglob_val s i j = g_val (sglob s i j)"
definition smem_ind :: "s ⇒ nat ⇒ nat option" where
"smem_ind s i = (inst.mem ((inst s)!i))"
definition stab_s :: "s ⇒ nat ⇒ nat ⇒ cl option" where
"stab_s s i j = (let stabinst = ((tab s)!i) in (if (length (stabinst) > j) then (stabinst!j) else None))"
definition stab :: "s ⇒ nat ⇒ nat ⇒ cl option" where
"stab s i j = (case (inst.tab ((inst s)!i)) of Some k => stab_s s k j | None => None)"
definition supdate_glob_s :: "s ⇒ nat ⇒ v ⇒ s" where
"supdate_glob_s s k v = s⦇globs := (globs s)[k:=((globs s)!k)⦇g_val := v⦈]⦈"
definition supdate_glob :: "s ⇒ nat ⇒ nat ⇒ v ⇒ s" where
"supdate_glob s i j v = (let k = sglob_ind s i j in supdate_glob_s s k v)"
definition is_const :: "e ⇒ bool" where
"is_const e = (case e of Basic (C _) ⇒ True | _ ⇒ False)"
definition const_list :: "e list ⇒ bool" where
"const_list xs = list_all is_const xs"
inductive store_extension :: "s ⇒ s ⇒ bool" where
"⟦insts = insts'; fs = fs'; tclss = tclss'; list_all2 (λbs bs'. mem_size bs ≤ mem_size bs') bss bss'; gs = gs'⟧ ⟹
store_extension ⦇s.inst = insts, s.funcs = fs, s.tab = tclss, s.mem = bss, s.globs = gs⦈
⦇s.inst = insts', s.funcs = fs', s.tab = tclss', s.mem = bss', s.globs = gs'⦈"
abbreviation to_e_list :: "b_e list ⇒ e list" ("$* _" 60) where
"to_e_list b_es ≡ map Basic b_es"
abbreviation v_to_e_list :: "v list ⇒ e list" ("$$* _" 60) where
"v_to_e_list ves ≡ map (λv. $C v) ves"
inductive Lfilled :: "nat ⇒ Lholed ⇒ e list ⇒ e list ⇒ bool" where
L0:"⟦const_list vs; lholed = (LBase vs es')⟧ ⟹ Lfilled 0 lholed es (vs @ es @ es')"
| LN:"⟦const_list vs; lholed = (LRec vs n es' l es''); Lfilled k l es lfilledk⟧ ⟹ Lfilled (k+1) lholed es (vs @ [Label n es' lfilledk] @ es'')"
inductive Lfilled_exact :: "nat ⇒ Lholed ⇒ e list ⇒ e list ⇒ bool" where
L0:"⟦lholed = (LBase [] [])⟧ ⟹ Lfilled_exact 0 lholed es es"
| LN:"⟦const_list vs; lholed = (LRec vs n es' l es''); Lfilled_exact k l es lfilledk⟧ ⟹ Lfilled_exact (k+1) lholed es (vs @ [Label n es' lfilledk] @ es'')"
definition load_store_t_bounds :: "a ⇒ tp option ⇒ t ⇒ bool" where
"load_store_t_bounds a tp t = (case tp of
None ⇒ 2^a ≤ t_length t
| Some tp ⇒ 2^a ≤ tp_length tp ∧ tp_length tp < t_length t ∧ is_int_t t)"
definition cvt_i32 :: "sx option ⇒ v ⇒ i32 option" where
"cvt_i32 sx v = (case v of
ConstInt32 c ⇒ None
| ConstInt64 c ⇒ Some (wasm_wrap c)
| ConstFloat32 c ⇒ (case sx of
Some U ⇒ ui32_trunc_f32 c
| Some S ⇒ si32_trunc_f32 c
| None ⇒ None)
| ConstFloat64 c ⇒ (case sx of
Some U ⇒ ui32_trunc_f64 c
| Some S ⇒ si32_trunc_f64 c
| None ⇒ None))"
definition cvt_i64 :: "sx option ⇒ v ⇒ i64 option" where
"cvt_i64 sx v = (case v of
ConstInt32 c ⇒ (case sx of
Some U ⇒ Some (wasm_extend_u c)
| Some S ⇒ Some (wasm_extend_s c)
| None ⇒ None)
| ConstInt64 c ⇒ None
| ConstFloat32 c ⇒ (case sx of
Some U ⇒ ui64_trunc_f32 c
| Some S ⇒ si64_trunc_f32 c
| None ⇒ None)
| ConstFloat64 c ⇒ (case sx of
Some U ⇒ ui64_trunc_f64 c
| Some S ⇒ si64_trunc_f64 c
| None ⇒ None))"
definition cvt_f32 :: "sx option ⇒ v ⇒ f32 option" where
"cvt_f32 sx v = (case v of
ConstInt32 c ⇒ (case sx of
Some U ⇒ Some (f32_convert_ui32 c)
| Some S ⇒ Some (f32_convert_si32 c)
| _ ⇒ None)
| ConstInt64 c ⇒ (case sx of
Some U ⇒ Some (f32_convert_ui64 c)
| Some S ⇒ Some (f32_convert_si64 c)
| _ ⇒ None)
| ConstFloat32 c ⇒ None
| ConstFloat64 c ⇒ Some (wasm_demote c))"
definition cvt_f64 :: "sx option ⇒ v ⇒ f64 option" where
"cvt_f64 sx v = (case v of
ConstInt32 c ⇒ (case sx of
Some U ⇒ Some (f64_convert_ui32 c)
| Some S ⇒ Some (f64_convert_si32 c)
| _ ⇒ None)
| ConstInt64 c ⇒ (case sx of
Some U ⇒ Some (f64_convert_ui64 c)
| Some S ⇒ Some (f64_convert_si64 c)
| _ ⇒ None)
| ConstFloat32 c ⇒ Some (wasm_promote c)
| ConstFloat64 c ⇒ None)"
definition cvt :: "t ⇒ sx option ⇒ v ⇒ v option" where
"cvt t sx v = (case t of
T_i32 ⇒ (case (cvt_i32 sx v) of Some c ⇒ Some (ConstInt32 c) | None ⇒ None)
| T_i64 ⇒ (case (cvt_i64 sx v) of Some c ⇒ Some (ConstInt64 c) | None ⇒ None)
| T_f32 ⇒ (case (cvt_f32 sx v) of Some c ⇒ Some (ConstFloat32 c) | None ⇒ None)
| T_f64 ⇒ (case (cvt_f64 sx v) of Some c ⇒ Some (ConstFloat64 c) | None ⇒ None))"
definition bits :: "v ⇒ bytes" where
"bits v = (case v of
ConstInt32 c ⇒ (serialise_i32 c)
| ConstInt64 c ⇒ (serialise_i64 c)
| ConstFloat32 c ⇒ (serialise_f32 c)
| ConstFloat64 c ⇒ (serialise_f64 c))"
definition bitzero :: "t ⇒ v" where
"bitzero t = (case t of
T_i32 ⇒ ConstInt32 0
| T_i64 ⇒ ConstInt64 0
| T_f32 ⇒ ConstFloat32 0
| T_f64 ⇒ ConstFloat64 0)"
definition n_zeros :: "t list ⇒ v list" where
"n_zeros ts = (map (λt. bitzero t) ts)"
lemma is_int_t_exists:
assumes "is_int_t t"
shows "t = T_i32 ∨ t = T_i64"
using assms
by (cases t) (auto simp add: is_int_t_def)
lemma is_float_t_exists:
assumes "is_float_t t"
shows "t = T_f32 ∨ t = T_f64"
using assms
by (cases t) (auto simp add: is_float_t_def)
lemma int_float_disjoint: "is_int_t t = -(is_float_t t)"
by simp (metis is_float_t_def is_int_t_def t.exhaust t.simps(13-16))
lemma stab_unfold:
assumes "stab s i j = Some cl"
shows "∃k. inst.tab ((inst s)!i) = Some k ∧ length ((tab s)!k) > j ∧((tab s)!k)!j = Some cl"
proof -
obtain k where have_k:"(inst.tab ((inst s)!i)) = Some k"
using assms
unfolding stab_def
by fastforce
hence s_o:"stab s i j = stab_s s k j"
using assms
unfolding stab_def
by simp
then obtain stabinst where stabinst_def:"stabinst = ((tab s)!k)"
by blast
hence "stab_s s k j = (stabinst!j) ∧ (length stabinst > j)"
using assms s_o
unfolding stab_s_def
by (cases "(length stabinst > j)", auto)
thus ?thesis
using have_k stabinst_def assms s_o
by auto
qed
lemma inj_basic: "inj Basic"
by (meson e.inject(1) injI)
lemma inj_basic_econst: "inj (λv. $C v)"
by (meson b_e.inject(16) e.inject(1) injI)
lemma to_e_list_1:"[$ a] = $* [a]"
by simp
lemma to_e_list_2:"[$ a, $ b] = $* [a, b]"
by simp
lemma to_e_list_3:"[$ a, $ b, $ c] = $* [a, b, c]"
by simp
lemma v_exists_b_e:"∃ves. ($$*vs) = ($*ves)"
proof (induction vs)
case (Cons a vs)
thus ?case
by (metis list.simps(9))
qed auto
lemma Lfilled_exact_imp_Lfilled:
assumes "Lfilled_exact n lholed es LI"
shows "Lfilled n lholed es LI"
using assms
proof (induction rule: Lfilled_exact.induct)
case (L0 lholed es)
thus ?case
using const_list_def Lfilled.intros(1)
by fastforce
next
case (LN vs lholed n es' l es'' k es lfilledk)
thus ?case
using Lfilled.intros(2)
by fastforce
qed
lemma Lfilled_exact_app_imp_exists_Lfilled:
assumes "const_list ves"
"Lfilled_exact n lholed (ves@es) LI"
shows "∃lholed'. Lfilled n lholed' es LI"
using assms(2,1)
proof (induction "(ves@es)" LI rule: Lfilled_exact.induct)
case (L0 lholed)
show ?case
using Lfilled.intros(1)[OF L0(2), of _ "[]"]
by fastforce
next
case (LN vs lholed n es' l es'' k lfilledk)
thus ?case
using Lfilled.intros(2)
by fastforce
qed
lemma Lfilled_imp_exists_Lfilled_exact:
assumes "Lfilled n lholed es LI"
shows "∃lholed' ves es_c. const_list ves ∧ Lfilled_exact n lholed' (ves@es@es_c) LI"
using assms Lfilled_exact.intros
by (induction rule: Lfilled.induct) fastforce+
lemma n_zeros_typeof:
"n_zeros ts = vs ⟹ (ts = map typeof vs)"
proof (induction ts arbitrary: vs)
case Nil
thus ?case
unfolding n_zeros_def
by simp
next
case (Cons t ts)
obtain vs' where "n_zeros ts = vs'"
using n_zeros_def
by blast
moreover
have "typeof (bitzero t) = t"
unfolding typeof_def bitzero_def
by (cases t, simp_all)
ultimately
show ?case
using Cons
unfolding n_zeros_def
by auto
qed
end
Theory Wasm
theory Wasm imports Wasm_Base_Defs begin
inductive b_e_typing :: "[t_context, b_e list, tf] ⇒ bool" ("_ ⊢ _ : _" 60) where
const:"𝒞 ⊢ [C v] : ([] _> [(typeof v)])"
| unop_i:"is_int_t t ⟹ 𝒞 ⊢ [Unop_i t _] : ([t] _> [t])"
| unop_f:"is_float_t t ⟹ 𝒞 ⊢ [Unop_f t _] : ([t] _> [t])"
| binop_i:"is_int_t t ⟹ 𝒞 ⊢ [Binop_i t iop] : ([t,t] _> [t])"
| binop_f:"is_float_t t ⟹ 𝒞 ⊢ [Binop_f t _] : ([t,t] _> [t])"
| testop:"is_int_t t ⟹ 𝒞 ⊢ [Testop t _] : ([t] _> [T_i32])"
| relop_i:"is_int_t t ⟹ 𝒞 ⊢ [Relop_i t _] : ([t,t] _> [T_i32])"
| relop_f:"is_float_t t ⟹ 𝒞 ⊢ [Relop_f t _] : ([t,t] _> [T_i32])"
| convert:"⟦(t1 ≠ t2); (sx = None) = ((is_float_t t1 ∧ is_float_t t2) ∨ (is_int_t t1 ∧ is_int_t t2 ∧ (t_length t1 < t_length t2)))⟧ ⟹ 𝒞 ⊢ [Cvtop t1 Convert t2 sx] : ([t2] _> [t1])"
| reinterpret:"⟦(t1 ≠ t2); t_length t1 = t_length t2⟧ ⟹ 𝒞 ⊢ [Cvtop t1 Reinterpret t2 None] : ([t2] _> [t1])"
| unreachable:"𝒞 ⊢ [Unreachable] : (ts _> ts')"
| nop:"𝒞 ⊢ [Nop] : ([] _> [])"
| drop:"𝒞 ⊢ [Drop] : ([t] _> [])"
| select:"𝒞 ⊢ [Select] : ([t,t,T_i32] _> [t])"
| block:"⟦tf = (tn _> tm); 𝒞⦇label := ([tm] @ (label 𝒞))⦈ ⊢ es : (tn _> tm)⟧ ⟹ 𝒞 ⊢ [Block tf es] : (tn _> tm)"
| loop:"⟦tf = (tn _> tm); 𝒞⦇label := ([tn] @ (label 𝒞))⦈ ⊢ es : (tn _> tm)⟧ ⟹ 𝒞 ⊢ [Loop tf es] : (tn _> tm)"
| if_wasm:"⟦tf = (tn _> tm); 𝒞⦇label := ([tm] @ (label 𝒞))⦈ ⊢ es1 : (tn _> tm); 𝒞⦇label := ([tm] @ (label 𝒞))⦈ ⊢ es2 : (tn _> tm)⟧ ⟹ 𝒞 ⊢ [If tf es1 es2] : (tn @ [T_i32] _> tm)"
| br:"⟦i < length(label 𝒞); (label 𝒞)!i = ts⟧ ⟹ 𝒞 ⊢ [Br i] : (t1s @ ts _> t2s)"
| br_if:"⟦i < length(label 𝒞); (label 𝒞)!i = ts⟧ ⟹ 𝒞 ⊢ [Br_if i] : (ts @ [T_i32] _> ts)"
| br_table:"⟦list_all (λi. i < length(label 𝒞) ∧ (label 𝒞)!i = ts) (is@[i])⟧ ⟹ 𝒞 ⊢ [Br_table is i] : (t1s @ ts @ [T_i32] _> t2s)"
| return:"⟦(return 𝒞) = Some ts⟧ ⟹ 𝒞 ⊢ [Return] : (t1s @ ts _> t2s)"
| call:"⟦i < length(func_t 𝒞); (func_t 𝒞)!i = tf⟧ ⟹ 𝒞 ⊢ [Call i] : tf"
| call_indirect:"⟦i < length(types_t 𝒞); (types_t 𝒞)!i = (t1s _> t2s); (table 𝒞) ≠ None⟧ ⟹ 𝒞 ⊢ [Call_indirect i] : (t1s @ [T_i32] _> t2s)"
| get_local:"⟦i < length(local 𝒞); (local 𝒞)!i = t⟧ ⟹ 𝒞 ⊢ [Get_local i] : ([] _> [t])"
| set_local:"⟦i < length(local 𝒞); (local 𝒞)!i = t⟧ ⟹ 𝒞 ⊢ [Set_local i] : ([t] _> [])"
| tee_local:"⟦i < length(local 𝒞); (local 𝒞)!i = t⟧ ⟹ 𝒞 ⊢ [Tee_local i] : ([t] _> [t])"
| get_global:"⟦i < length(global 𝒞); tg_t ((global 𝒞)!i) = t⟧ ⟹ 𝒞 ⊢ [Get_global i] : ([] _> [t])"
| set_global:"⟦i < length(global 𝒞); tg_t ((global 𝒞)!i) = t; is_mut ((global 𝒞)!i)⟧ ⟹ 𝒞 ⊢ [Set_global i] : ([t] _> [])"
| load:"⟦(memory 𝒞) = Some n; load_store_t_bounds a (option_projl tp_sx) t⟧ ⟹ 𝒞 ⊢ [Load t tp_sx a off] : ([T_i32] _> [t])"
| store:"⟦(memory 𝒞) = Some n; load_store_t_bounds a tp t⟧ ⟹ 𝒞 ⊢ [Store t tp a off] : ([T_i32,t] _> [])"
| current_memory:"(memory 𝒞) = Some n ⟹ 𝒞 ⊢ [Current_memory] : ([] _> [T_i32])"
| grow_memory:"(memory 𝒞) = Some n ⟹ 𝒞 ⊢ [Grow_memory] : ([T_i32] _> [T_i32])"
| empty:"𝒞 ⊢ [] : ([] _> [])"
| composition:"⟦𝒞 ⊢ es : (t1s _> t2s); 𝒞 ⊢ [e] : (t2s _> t3s)⟧ ⟹ 𝒞 ⊢ es @ [e] : (t1s _> t3s)"
| weakening:"𝒞 ⊢ es : (t1s _> t2s) ⟹ 𝒞 ⊢ es : (ts @ t1s _> ts @ t2s)"
inductive cl_typing :: "[s_context, cl, tf] ⇒ bool" where
"⟦i < length (s_inst 𝒮); ((s_inst 𝒮)!i) = 𝒞; tf = (t1s _> t2s); 𝒞⦇local := (local 𝒞) @ t1s @ ts, label := ([t2s] @ (label 𝒞)), return := Some t2s⦈ ⊢ es : ([] _> t2s)⟧ ⟹ cl_typing 𝒮 (Func_native i tf ts es) (t1s _> t2s)"
| "cl_typing 𝒮 (Func_host tf h) tf"
inductive e_typing :: "[s_context, t_context, e list, tf] ⇒ bool" ("_∙_ ⊢ _ : _" 60)
and s_typing :: "[s_context, (t list) option, nat, v list, e list, t list] ⇒ bool" ("_∙_ ⊩'_ _ _;_ : _" 60) where
"𝒞 ⊢ b_es : tf ⟹ 𝒮∙𝒞 ⊢ $*b_es : tf"
| "⟦𝒮∙𝒞 ⊢ es : (t1s _> t2s); 𝒮∙𝒞 ⊢ [e] : (t2s _> t3s)⟧ ⟹ 𝒮∙𝒞 ⊢ es @ [e] : (t1s _> t3s)"
| "𝒮∙𝒞 ⊢ es : (t1s _> t2s) ⟹𝒮∙𝒞 ⊢ es : (ts @ t1s _> ts @ t2s)"
| "𝒮∙𝒞 ⊢ [Trap] : tf"
| "⟦𝒮∙Some ts ⊩_i vs;es : ts; length ts = n⟧ ⟹ 𝒮∙𝒞 ⊢ [Local n i vs es] : ([] _> ts)"
| "⟦cl_typing 𝒮 cl tf⟧ ⟹ 𝒮∙𝒞 ⊢ [Callcl cl] : tf"
| "⟦𝒮∙𝒞 ⊢ e0s : (ts _> t2s); 𝒮∙𝒞⦇label := ([ts] @ (label 𝒞))⦈ ⊢ es : ([] _> t2s); length ts = n⟧ ⟹ 𝒮∙𝒞 ⊢ [Label n e0s es] : ([] _> t2s)"
| "⟦i < (length (s_inst 𝒮)); tvs = map typeof vs; 𝒞 =((s_inst 𝒮)!i)⦇local := (local ((s_inst 𝒮)!i) @ tvs), return := rs⦈; 𝒮∙𝒞 ⊢ es : ([] _> ts); (rs = Some ts) ∨ rs = None⟧ ⟹ 𝒮∙rs ⊩_i vs;es : ts"
definition "globi_agree gs n g = (n < length gs ∧ gs!n = g)"
definition "memi_agree sm j m = ((∃j' m'. j = Some j' ∧ j' < length sm ∧ m = Some m' ∧ sm!j' = m') ∨ j = None ∧ m = None)"
definition "funci_agree fs n f = (n < length fs ∧ fs!n = f)"
inductive inst_typing :: "[s_context, inst, t_context] ⇒ bool" where
"⟦list_all2 (funci_agree (s_funcs 𝒮)) fs tfs; list_all2 (globi_agree (s_globs 𝒮)) gs tgs; (i = Some i' ∧ i' < length (s_tab 𝒮) ∧ (s_tab 𝒮)!i' = (the n)) ∨ (i = None ∧ n = None); memi_agree (s_mem 𝒮) j m⟧ ⟹ inst_typing 𝒮 ⦇types = ts, funcs = fs, tab = i, mem = j, globs = gs⦈ ⦇types_t = ts, func_t = tfs, global = tgs, table = n, memory = m, local = [], label = [], return = None⦈"
definition "glob_agree g tg = (tg_mut tg = g_mut g ∧ tg_t tg = typeof (g_val g))"
definition "tab_agree 𝒮 tcl = (case tcl of None ⇒ True | Some cl ⇒ ∃tf. cl_typing 𝒮 cl tf)"
definition "mem_agree bs m = (λ bs m. m ≤ mem_size bs) bs m"
inductive store_typing :: "[s, s_context] ⇒ bool" where
"⟦𝒮 = ⦇s_inst = 𝒞s, s_funcs = tfs, s_tab = ns, s_mem = ms, s_globs = tgs⦈; list_all2 (inst_typing 𝒮) insts 𝒞s; list_all2 (cl_typing 𝒮) fs tfs; list_all (tab_agree 𝒮) (concat tclss); list_all2 (λ tcls n. n ≤ length tcls) tclss ns; list_all2 mem_agree bss ms; list_all2 glob_agree gs tgs⟧ ⟹ store_typing ⦇s.inst = insts, s.funcs = fs, s.tab = tclss, s.mem = bss, s.globs = gs⦈ 𝒮"
inductive config_typing :: "[nat, s, v list, e list, t list] ⇒ bool" ("⊢'_ _ _;_;_ : _" 60) where
"⟦store_typing s 𝒮; 𝒮∙None ⊩_i vs;es : ts⟧ ⟹ ⊢_i s;vs;es : ts"
inductive reduce_simple :: "[e list, e list] ⇒ bool" ("⦇_⦈ ↝ ⦇_⦈" 60) where
unop_i32:"⦇[$C (ConstInt32 c), $(Unop_i T_i32 iop)]⦈ ↝ ⦇[$C (ConstInt32 (app_unop_i iop c))]⦈"
| unop_i64:"⦇[$C (ConstInt64 c), $(Unop_i T_i64 iop)]⦈ ↝ ⦇[$C (ConstInt64 (app_unop_i iop c))]⦈"
| unop_f32:"⦇[$C (ConstFloat32 c), $(Unop_f T_f32 fop)]⦈ ↝ ⦇[$C (ConstFloat32 (app_unop_f fop c))]⦈"
| unop_f64:"⦇[$C (ConstFloat64 c), $(Unop_f T_f64 fop)]⦈ ↝ ⦇[$C (ConstFloat64 (app_unop_f fop c))]⦈"
| binop_i32_Some:"⟦app_binop_i iop c1 c2 = (Some c)⟧ ⟹ ⦇[$C (ConstInt32 c1), $C (ConstInt32 c2), $(Binop_i T_i32 iop)]⦈ ↝ ⦇[$C (ConstInt32 c)]⦈"
| binop_i32_None:"⟦app_binop_i iop c1 c2 = None⟧ ⟹ ⦇[$C (ConstInt32 c1), $C (ConstInt32 c2), $(Binop_i T_i32 iop)]⦈ ↝ ⦇[Trap]⦈"
| binop_i64_Some:"⟦app_binop_i iop c1 c2 = (Some c)⟧ ⟹ ⦇[$C (ConstInt64 c1), $C (ConstInt64 c2), $(Binop_i T_i64 iop)]⦈ ↝ ⦇[$C (ConstInt64 c)]⦈"
| binop_i64_None:"⟦app_binop_i iop c1 c2 = None⟧ ⟹ ⦇[$C (ConstInt64 c1), $C (ConstInt64 c2), $(Binop_i T_i64 iop)]⦈ ↝ ⦇[Trap]⦈"
| binop_f32_Some:"⟦app_binop_f fop c1 c2 = (Some c)⟧ ⟹ ⦇[$C (ConstFloat32 c1), $C (ConstFloat32 c2), $(Binop_f T_f32 fop)]⦈ ↝ ⦇[$C (ConstFloat32 c)]⦈"
| binop_f32_None:"⟦app_binop_f fop c1 c2 = None⟧ ⟹ ⦇[$C (ConstFloat32 c1), $C (ConstFloat32 c2), $(Binop_f T_f32 fop)]⦈ ↝ ⦇[Trap]⦈"
| binop_f64_Some:"⟦app_binop_f fop c1 c2 = (Some c)⟧ ⟹ ⦇[$C (ConstFloat64 c1), $C (ConstFloat64 c2), $(Binop_f T_f64 fop)]⦈ ↝ ⦇[$C (ConstFloat64 c)]⦈"
| binop_f64_None:"⟦app_binop_f fop c1 c2 = None⟧ ⟹ ⦇[$C (ConstFloat64 c1), $C (ConstFloat64 c2), $(Binop_f T_f64 fop)]⦈ ↝ ⦇[Trap]⦈"
| testop_i32:"⦇[$C (ConstInt32 c), $(Testop T_i32 testop)]⦈ ↝ ⦇[$C ConstInt32 (wasm_bool (app_testop_i testop c))]⦈"
| testop_i64:"⦇[$C (ConstInt64 c), $(Testop T_i64 testop)]⦈ ↝ ⦇[$C ConstInt32 (wasm_bool (app_testop_i testop c))]⦈"
| relop_i32:"⦇[$C (ConstInt32 c1), $C (ConstInt32 c2), $(Relop_i T_i32 iop)]⦈ ↝ ⦇[$C (ConstInt32 (wasm_bool (app_relop_i iop c1 c2)))]⦈"
| relop_i64:"⦇[$C (ConstInt64 c1), $C (ConstInt64 c2), $(Relop_i T_i64 iop)]⦈ ↝ ⦇[$C (ConstInt32 (wasm_bool (app_relop_i iop c1 c2)))]⦈"
| relop_f32:"⦇[$C (ConstFloat32 c1), $C (ConstFloat32 c2), $(Relop_f T_f32 fop)]⦈ ↝ ⦇[$C (ConstInt32 (wasm_bool (app_relop_f fop c1 c2)))]⦈"
| relop_f64:"⦇[$C (ConstFloat64 c1), $C (ConstFloat64 c2), $(Relop_f T_f64 fop)]⦈ ↝ ⦇[$C (ConstInt32 (wasm_bool (app_relop_f fop c1 c2)))]⦈"
| convert_Some:"⟦types_agree t1 v; cvt t2 sx v = (Some v')⟧ ⟹ ⦇[$(C v), $(Cvtop t2 Convert t1 sx)]⦈ ↝ ⦇[$(C v')]⦈"
| convert_None:"⟦types_agree t1 v; cvt t2 sx v = None⟧ ⟹ ⦇[$(C v), $(Cvtop t2 Convert t1 sx)]⦈ ↝ ⦇[Trap]⦈"
| reinterpret:"types_agree t1 v ⟹ ⦇[$(C v), $(Cvtop t2 Reinterpret t1 None)]⦈ ↝ ⦇[$(C (wasm_deserialise (bits v) t2))]⦈"
| unreachable:"⦇[$ Unreachable]⦈ ↝ ⦇[Trap]⦈"
| nop:"⦇[$ Nop]⦈ ↝ ⦇[]⦈"
| drop:"⦇[$(C v), ($ Drop)]⦈ ↝ ⦇[]⦈"
| select_false:"int_eq n 0 ⟹ ⦇[$(C v1), $(C v2), $C (ConstInt32 n), ($ Select)]⦈ ↝ ⦇[$(C v2)]⦈"
| select_true:"int_ne n 0 ⟹ ⦇[$(C v1), $(C v2), $C (ConstInt32 n), ($ Select)]⦈ ↝ ⦇[$(C v1)]⦈"
| block:"⟦const_list vs; length vs = n; length t1s = n; length t2s = m⟧ ⟹ ⦇vs @ [$(Block (t1s _> t2s) es)]⦈ ↝ ⦇[Label m [] (vs @ ($* es))]⦈"
| loop:"⟦const_list vs; length vs = n; length t1s = n; length t2s = m⟧ ⟹ ⦇vs @ [$(Loop (t1s _> t2s) es)]⦈ ↝ ⦇[Label n [$(Loop (t1s _> t2s) es)] (vs @ ($* es))]⦈"
| if_false:"int_eq n 0 ⟹ ⦇[$C (ConstInt32 n), $(If tf e1s e2s)]⦈ ↝ ⦇[$(Block tf e2s)]⦈"
| if_true:"int_ne n 0 ⟹ ⦇[$C (ConstInt32 n), $(If tf e1s e2s)]⦈ ↝ ⦇[$(Block tf e1s)]⦈"
| label_const:"const_list vs ⟹ ⦇[Label n es vs]⦈ ↝ ⦇vs⦈"
| label_trap:"⦇[Label n es [Trap]]⦈ ↝ ⦇[Trap]⦈"
| br:"⟦const_list vs; length vs = n; Lfilled i lholed (vs @ [$(Br i)]) LI⟧ ⟹ ⦇[Label n es LI]⦈ ↝ ⦇vs @ es⦈"
| br_if_false:"int_eq n 0 ⟹ ⦇[$C (ConstInt32 n), $(Br_if i)]⦈ ↝ ⦇[]⦈"
| br_if_true:"int_ne n 0 ⟹ ⦇[$C (ConstInt32 n), $(Br_if i)]⦈ ↝ ⦇[$(Br i)]⦈"
| br_table:"⟦length is > (nat_of_int c)⟧ ⟹ ⦇[$C (ConstInt32 c), $(Br_table is i)]⦈ ↝ ⦇[$(Br (is!(nat_of_int c)))]⦈"
| br_table_length:"⟦length is ≤ (nat_of_int c)⟧ ⟹ ⦇[$C (ConstInt32 c), $(Br_table is i)]⦈ ↝ ⦇[$(Br i)]⦈"
| local_const:"⟦const_list es; length es = n⟧ ⟹ ⦇[Local n i vs es]⦈ ↝ ⦇es⦈"
| local_trap:"⦇[Local n i vs [Trap]]⦈ ↝ ⦇[Trap]⦈"
| return:"⟦const_list vs; length vs = n; Lfilled j lholed (vs @ [$Return]) es⟧ ⟹ ⦇[Local n i vls es]⦈ ↝ ⦇vs⦈"
| tee_local:"is_const v ⟹ ⦇[v, $(Tee_local i)]⦈ ↝ ⦇[v, v, $(Set_local i)]⦈"
| trap:"⟦es ≠ [Trap]; Lfilled 0 lholed [Trap] es⟧ ⟹ ⦇es⦈ ↝ ⦇[Trap]⦈"
inductive reduce :: "[s, v list, e list, nat, s, v list, e list] ⇒ bool" ("⦇_;_;_⦈ ↝'_ _ ⦇_;_;_⦈" 60) where
basic:"⦇e⦈ ↝ ⦇e'⦈ ⟹ ⦇s;vs;e⦈ ↝_i ⦇s;vs;e'⦈"
| call:"⦇s;vs;[$(Call j)]⦈ ↝_i ⦇s;vs;[Callcl (sfunc s i j)]⦈"
| call_indirect_Some:"⟦stab s i (nat_of_int c) = Some cl; stypes s i j = tf; cl_type cl = tf⟧ ⟹ ⦇s;vs;[$C (ConstInt32 c), $(Call_indirect j)]⦈ ↝_i ⦇s;vs;[Callcl cl]⦈"
| call_indirect_None:"⟦(stab s i (nat_of_int c) = Some cl ∧ stypes s i j ≠ cl_type cl) ∨ stab s i (nat_of_int c) = None⟧ ⟹ ⦇s;vs;[$C (ConstInt32 c), $(Call_indirect j)]⦈ ↝_i ⦇s;vs;[Trap]⦈"
| callcl_native:"⟦cl = Func_native j (t1s _> t2s) ts es; ves = ($$* vcs); length vcs = n; length ts = k; length t1s = n; length t2s = m; (n_zeros ts = zs) ⟧ ⟹ ⦇s;vs;ves @ [Callcl cl]⦈ ↝_i ⦇s;vs;[Local m j (vcs@zs) [$(Block ([] _> t2s) es)]]⦈"
| callcl_host_Some:"⟦cl = Func_host (t1s _> t2s) f; ves = ($$* vcs); length vcs = n; length t1s = n; length t2s = m; host_apply s (t1s _> t2s) f vcs hs = Some (s', vcs')⟧ ⟹ ⦇s;vs;ves @ [Callcl cl]⦈ ↝_i ⦇s';vs;($$* vcs')⦈"
| callcl_host_None:"⟦cl = Func_host (t1s _> t2s) f; ves = ($$* vcs); length vcs = n; length t1s = n; length t2s = m⟧ ⟹ ⦇s;vs;ves @ [Callcl cl]⦈ ↝_i ⦇s;vs;[Trap]⦈"
| get_local:"⟦length vi = j⟧ ⟹ ⦇s;(vi @ [v] @ vs);[$(Get_local j)]⦈ ↝_i ⦇s;(vi @ [v] @ vs);[$(C v)]⦈"
| set_local:"⟦length vi = j⟧ ⟹ ⦇s;(vi @ [v] @ vs);[$(C v'), $(Set_local j)]⦈ ↝_i ⦇s;(vi @ [v'] @ vs);[]⦈"
| get_global:"⦇s;vs;[$(Get_global j)]⦈ ↝_i ⦇s;vs;[$ C(sglob_val s i j)]⦈"
| set_global:"supdate_glob s i j v = s' ⟹ ⦇s;vs;[$(C v), $(Set_global j)]⦈ ↝_i ⦇s';vs;[]⦈"
| load_Some:"⟦smem_ind s i = Some j; ((mem s)!j) = m; load m (nat_of_int k) off (t_length t) = Some bs⟧ ⟹ ⦇s;vs;[$C (ConstInt32 k), $(Load t None a off)]⦈ ↝_i ⦇s;vs;[$C (wasm_deserialise bs t)]⦈"
| load_None:"⟦smem_ind s i = Some j; ((mem s)!j) = m; load m (nat_of_int k) off (t_length t) = None⟧ ⟹ ⦇s;vs;[$C (ConstInt32 k), $(Load t None a off)]⦈ ↝_i ⦇s;vs;[Trap]⦈"
| load_packed_Some:"⟦smem_ind s i = Some j; ((mem s)!j) = m; load_packed sx m (nat_of_int k) off (tp_length tp) (t_length t) = Some bs⟧ ⟹ ⦇s;vs;[$C (ConstInt32 k), $(Load t (Some (tp, sx)) a off)]⦈ ↝_i ⦇s;vs;[$C (wasm_deserialise bs t)]⦈"
| load_packed_None:"⟦smem_ind s i = Some j; ((mem s)!j) = m; load_packed sx m (nat_of_int k) off (tp_length tp) (t_length t) = None⟧ ⟹ ⦇s;vs;[$C (ConstInt32 k), $(Load t (Some (tp, sx)) a off)]⦈ ↝_i ⦇s;vs;[Trap]⦈"
| store_Some:"⟦types_agree t v; smem_ind s i = Some j; ((mem s)!j) = m; store m (nat_of_int k) off (bits v) (t_length t) = Some mem'⟧ ⟹ ⦇s;vs;[$C (ConstInt32 k), $C v, $(Store t None a off)]⦈ ↝_i ⦇s⦇mem:= ((mem s)[j := mem'])⦈;vs;[]⦈"
| store_None:"⟦types_agree t v; smem_ind s i = Some j; ((mem s)!j) = m; store m (nat_of_int k) off (bits v) (t_length t) = None⟧ ⟹ ⦇s;vs;[$C (ConstInt32 k), $C v, $(Store t None a off)]⦈ ↝_i ⦇s;vs;[Trap]⦈"
| store_packed_Some:"⟦types_agree t v; smem_ind s i = Some j; ((mem s)!j) = m; store_packed m (nat_of_int k) off (bits v) (tp_length tp) = Some mem'⟧ ⟹ ⦇s;vs;[$C (ConstInt32 k), $C v, $(Store t (Some tp) a off)]⦈ ↝_i ⦇s⦇mem:= ((mem s)[j := mem'])⦈;vs;[]⦈"
| store_packed_None:"⟦types_agree t v; smem_ind s i = Some j; ((mem s)!j) = m; store_packed m (nat_of_int k) off (bits v) (tp_length tp) = None⟧ ⟹ ⦇s;vs;[$C (ConstInt32 k), $C v, $(Store t (Some tp) a off)]⦈ ↝_i ⦇s;vs;[Trap]⦈"
| current_memory:"⟦smem_ind s i = Some j; ((mem s)!j) = m; mem_size m = n⟧ ⟹ ⦇s;vs;[ $(Current_memory)]⦈ ↝_i ⦇s;vs;[$C (ConstInt32 (int_of_nat n))]⦈"
| grow_memory:"⟦smem_ind s i = Some j; ((mem s)!j) = m; mem_size m = n; mem_grow m (nat_of_int c) = mem'⟧ ⟹ ⦇s;vs;[$C (ConstInt32 c), $(Grow_memory)]⦈ ↝_i ⦇s⦇mem:= ((mem s)[j := mem'])⦈;vs;[$C (ConstInt32 (int_of_nat n))]⦈"
| grow_memory_fail:"⟦smem_ind s i = Some j; ((mem s)!j) = m; mem_size m = n⟧ ⟹ ⦇s;vs;[$C (ConstInt32 c),$(Grow_memory)]⦈ ↝_i ⦇s;vs;[$C (ConstInt32 int32_minus_one)]⦈"
| label:"⟦⦇s;vs;es⦈ ↝_i ⦇s';vs';es'⦈; Lfilled k lholed es les; Lfilled k lholed es' les'⟧ ⟹ ⦇s;vs;les⦈ ↝_i ⦇s';vs';les'⦈"
| local:"⟦⦇s;vs;es⦈ ↝_i ⦇s';vs';es'⦈⟧ ⟹ ⦇s;v0s;[Local n i vs es]⦈ ↝_j ⦇s';v0s;[Local n i vs' es']⦈"
end
Theory Wasm_Axioms
section ‹Host Properties›
theory Wasm_Axioms imports Wasm begin
lemma mem_grow_size:
assumes "mem_grow m n = m'"
shows "(mem_size m + (64000 * n)) = mem_size m'"
using assms Abs_mem_inverse Abs_bytes_inverse
unfolding mem_grow_def mem_size_def mem_append_def bytes_replicate_def
by auto
lemma load_size:
"(load m n off l = None) = (mem_size m < (off + n + l))"
unfolding load_def
by (cases "n + off + l ≤ mem_size m") auto
lemma load_packed_size:
"(load_packed sx m n off lp l = None) = (mem_size m < (off + n + lp))"
using load_size
unfolding load_packed_def
by (cases "n + off + l ≤ mem_size m") auto
lemma store_size1:
"(store m n off v l = None) = (mem_size m < (off + n + l))"
unfolding store_def
by (cases "n + off + l ≤ mem_size m") auto
lemma store_size:
assumes "(store m n off v l = Some m')"
shows "mem_size m = mem_size m'"
using assms Abs_mem_inverse Abs_bytes_inverse
unfolding store_def write_bytes_def bytes_takefill_def
by (cases "n + off + l ≤ mem_size m") (auto simp add: mem_size_def)
lemma store_packed_size1:
"(store_packed m n off v l = None) = (mem_size m < (off + n + l))"
using store_size1
unfolding store_packed_def
by simp
lemma store_packed_size:
assumes "(store_packed m n off v l = Some m')"
shows "mem_size m = mem_size m'"
using assms store_size
unfolding store_packed_def
by simp
axiomatization where
wasm_deserialise_type:"typeof (wasm_deserialise bs t) = t"
axiomatization where
host_apply_preserve_store:" list_all2 types_agree t1s vs ⟹ host_apply s (t1s _> t2s) f vs hs = Some (s', vs') ⟹ store_extension s s'"
and host_apply_respect_type:"list_all2 types_agree t1s vs ⟹ host_apply s (t1s _> t2s) f vs hs = Some (s', vs') ⟹ list_all2 types_agree t2s vs'"
end
Theory Wasm_Properties_Aux
section ‹Auxiliary Type System Properties›
theory Wasm_Properties_Aux imports Wasm_Axioms begin
lemma typeof_i32:
assumes "typeof v = T_i32"
shows "∃c. v = ConstInt32 c"
using assms
unfolding typeof_def
by (cases v) auto
lemma typeof_i64:
assumes "typeof v = T_i64"
shows "∃c. v = ConstInt64 c"
using assms
unfolding typeof_def
by (cases v) auto
lemma typeof_f32:
assumes "typeof v = T_f32"
shows "∃c. v = ConstFloat32 c"
using assms
unfolding typeof_def
by (cases v) auto
lemma typeof_f64:
assumes "typeof v = T_f64"
shows "∃c. v = ConstFloat64 c"
using assms
unfolding typeof_def
by (cases v) auto
lemma exists_v_typeof: "∃v v. typeof v = t"
proof (cases t)
case T_i32
fix v
have "typeof (ConstInt32 v) = t"
using T_i32
unfolding typeof_def
by simp
thus ?thesis
using T_i32
by fastforce
next
case T_i64
fix v
have "typeof (ConstInt64 v) = t"
using T_i64
unfolding typeof_def
by simp
thus ?thesis
using T_i64
by fastforce
next
case T_f32
fix v
have "typeof (ConstFloat32 v) = t"
using T_f32
unfolding typeof_def
by simp
thus ?thesis
using T_f32
by fastforce
next
case T_f64
fix v
have "typeof (ConstFloat64 v) = t"
using T_f64
unfolding typeof_def
by simp
thus ?thesis
using T_f64
by fastforce
qed
lemma lfilled_collapse1:
assumes "Lfilled n lholed (vs@es) LI"
"const_list vs"
"length vs ≥ l"
shows "∃lholed'. Lfilled n lholed' ((drop (length vs - l) vs)@es) LI"
using assms(1)
proof (induction "vs@es" LI rule: Lfilled.induct)
case (L0 vs' lholed es')
obtain vs1 vs2 where "vs = vs1@vs2" "length vs2 = l"
using assms(3)
by (metis append_take_drop_id diff_diff_cancel length_drop)
moreover
hence "const_list (vs'@vs1)"
using L0(1) assms(2)
unfolding const_list_def
by simp
ultimately
show ?case
using Lfilled.intros(1)[of "vs'@vs1" _ es' "vs2@es"]
by fastforce
next
case (LN vs lholed n es' l es'' k lfilledk)
thus ?case
using Lfilled.intros(2)
by fastforce
qed
lemma lfilled_collapse2:
assumes "Lfilled n lholed (es@es') LI"
shows "∃lholed' vs'. Lfilled n lholed' es LI"
using assms
proof (induction "es@es'" LI rule: Lfilled.induct)
case (L0 vs lholed es')
thus ?case
using Lfilled.intros(1)
by fastforce
next
case (LN vs lholed n es' l es'' k lfilledk)
thus ?case
using Lfilled.intros(2)
by fastforce
qed
lemma lfilled_collapse3:
assumes "Lfilled k lholed [Label n les es] LI"
shows "∃lholed'. Lfilled (Suc k) lholed' es LI"
using assms
proof (induction "[Label n les es]" LI rule: Lfilled.induct)
case (L0 vs lholed es')
have "Lfilled 0 (LBase [] []) es es"
using Lfilled.intros(1)
unfolding const_list_def
by (metis append.left_neutral append_Nil2 list_all_simps(2))
thus ?case
using Lfilled.intros(2) L0
by fastforce
next
case (LN vs lholed n es' l es'' k lfilledk)
thus ?case
using Lfilled.intros(2)
by fastforce
qed
lemma unlift_b_e: assumes "𝒮∙𝒞 ⊢ $*b_es : tf" shows "𝒞 ⊢ b_es : tf"
using assms proof (induction "𝒮" "𝒞" "($*b_es)" "tf" arbitrary: b_es)
case (1 𝒞 b_es tf 𝒮)
then show ?case
using inj_basic map_injective
by auto
next
case (2 𝒮 𝒞 es t1s t2s e t3s)
obtain es' e' where "es' @ [e'] = b_es"
using 2(5)
by (simp add: snoc_eq_iff_butlast)
then show ?case using 2
using b_e_typing.composition
by fastforce
next
case (3 𝒮 𝒞 t1s t2s ts)
then show ?case
using b_e_typing.weakening
by blast
qed auto
lemma store_typing_imp_inst_length_eq:
assumes "store_typing s 𝒮"
shows "length (inst s) = length (s_inst 𝒮)"
using assms list_all2_lengthD
unfolding store_typing.simps
by fastforce
lemma store_typing_imp_func_length_eq:
assumes "store_typing s 𝒮"
shows "length (funcs s) = length (s_funcs 𝒮)"
using assms list_all2_lengthD
unfolding store_typing.simps
by fastforce
lemma store_typing_imp_mem_length_eq:
assumes "store_typing s 𝒮"
shows "length (s.mem s) = length (s_mem 𝒮)"
using assms list_all2_lengthD
unfolding store_typing.simps
by fastforce
lemma store_typing_imp_glob_length_eq:
assumes "store_typing s 𝒮"
shows "length (globs s) = length (s_globs 𝒮)"
using assms list_all2_lengthD
unfolding store_typing.simps
by fastforce
lemma store_typing_imp_inst_typing:
assumes "store_typing s 𝒮"
"i < length (inst s)"
shows "inst_typing 𝒮 ((inst s)!i) ((s_inst 𝒮)!i)"
using assms
unfolding list_all2_conv_all_nth store_typing.simps
by fastforce
lemma stab_typed_some_imp_member:
assumes "stab s i c = Some cl"
"store_typing s 𝒮"
"i < length (inst s)"
shows "Some cl ∈ set (concat (s.tab s))"
proof -
obtain k' where k_def:"inst.tab ((inst s)!i) = Some k'"
"length ((s.tab s)!k') > c"
"((s.tab s)!k')!c = Some cl"
using stab_unfold assms(1,3)
by fastforce
hence "Some cl ∈ set ((s.tab s)!k')"
using nth_mem
by fastforce
moreover
have "inst_typing 𝒮 ((inst s)!i) ((s_inst 𝒮)!i)"
using assms(2,3) store_typing_imp_inst_typing
by blast
hence "k' < length (s_tab 𝒮)"
using k_def(1)
unfolding inst_typing.simps stypes_def
by auto
hence "k' < length (s.tab s)"
using assms(2) list_all2_lengthD
unfolding store_typing.simps
by fastforce
ultimately
show ?thesis
using k_def
by auto
qed
lemma stab_typed_some_imp_cl_typed:
assumes "stab s i c = Some cl"
"store_typing s 𝒮"
"i < length (inst s)"
shows "∃tf. cl_typing 𝒮 cl tf"
proof -
have "Some cl ∈ set (concat (s.tab s))"
using assms stab_typed_some_imp_member
by auto
moreover
have "list_all (tab_agree 𝒮) (concat (s.tab s))"
using assms(2)
unfolding store_typing.simps
by auto
ultimately
show ?thesis
unfolding in_set_conv_nth list_all_length tab_agree_def
by fastforce
qed
lemma b_e_type_empty1[dest]: assumes "𝒞 ⊢ [] : (ts _> ts')" shows "ts = ts'"
using assms
by (induction "[]::(b_e list)" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, simp_all)
lemma b_e_type_empty: "(𝒞 ⊢ [] : (ts _> ts')) = (ts = ts')"
proof (safe)
assume "𝒞 ⊢ [] : (ts _> ts')"
thus "ts = ts'"
by blast
next
assume "ts = ts'"
thus "𝒞 ⊢ [] : (ts' _> ts')"
using b_e_typing.empty b_e_typing.weakening
by fastforce
qed
lemma b_e_type_value:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = C v"
shows "ts' = ts @ [typeof v]"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_load:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Load t tp_sx a off"
shows "∃ts'' sec n. ts = ts''@[T_i32] ∧ ts' = ts''@[t] ∧ (memory 𝒞) = Some n"
"load_store_t_bounds a (option_projl tp_sx) t"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_store:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Store t tp a off"
shows "ts = ts'@[T_i32, t]"
"∃sec n. (memory 𝒞) = Some n"
"load_store_t_bounds a tp t"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_current_memory:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Current_memory"
shows "∃sec n. ts' = ts @ [T_i32] ∧ (memory 𝒞) = Some n"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_grow_memory:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Grow_memory"
shows "∃ts''. ts = ts''@[T_i32] ∧ ts = ts' ∧ (∃n. (memory 𝒞) = Some n)"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct) auto
lemma b_e_type_nop:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Nop"
shows "ts = ts'"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
definition arity_2_result :: "b_e ⇒ t" where
"arity_2_result op2 = (case op2 of
Binop_i t _ ⇒ t
| Binop_f t _ ⇒ t
| Relop_i t _ ⇒ T_i32
| Relop_f t _ ⇒ T_i32)"
lemma b_e_type_binop_relop:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Binop_i t iop ∨ e = Binop_f t fop ∨ e = Relop_i t irop ∨ e = Relop_f t frop"
shows "∃ts''. ts = ts''@[t,t] ∧ ts' = ts''@[arity_2_result(e)]"
"e = Binop_f t fop ⟹ is_float_t t"
"e = Relop_f t frop ⟹ is_float_t t"
using assms
unfolding arity_2_result_def
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_testop_drop_cvt0:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Testop t testop ∨ e = Drop ∨ e = Cvtop t1 cvtop t2 sx"
shows "ts ≠ []"
using assms
by (induction "[e]" "ts _> ts'" arbitrary: ts' rule: b_e_typing.induct, auto)
definition arity_1_result :: "b_e ⇒ t" where
"arity_1_result op1 = (case op1 of
Unop_i t _ ⇒ t
| Unop_f t _ ⇒ t
| Testop t _ ⇒ T_i32
| Cvtop t1 Convert _ _ ⇒ t1
| Cvtop t1 Reinterpret _ _ ⇒ t1)"
lemma b_e_type_unop_testop:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Unop_i t iop ∨ e = Unop_f t fop ∨ e = Testop t testop"
shows "∃ts''. ts = ts''@[t] ∧ ts' = ts''@[arity_1_result e]"
"e = Unop_f t fop ⟹ is_float_t t"
using assms int_float_disjoint
unfolding arity_1_result_def
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct) fastforce+
lemma b_e_type_cvtop:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Cvtop t1 cvtop t sx"
shows "∃ts''. ts = ts''@[t] ∧ ts' = ts''@[arity_1_result e]"
"cvtop = Convert ⟹ (t1 ≠ t) ∧ (sx = None) = ((is_float_t t1 ∧ is_float_t t) ∨ (is_int_t t1 ∧ is_int_t t ∧ (t_length t1 < t_length t)))"
"cvtop = Reinterpret ⟹ (t1 ≠ t) ∧ t_length t1 = t_length t"
using assms
unfolding arity_1_result_def
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_drop:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Drop"
shows "∃t. ts = ts'@[t]"
using assms b_e_type_testop_drop_cvt0
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_select:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Select"
shows "∃ts'' t. ts = ts''@[t,t,T_i32] ∧ ts' = ts''@[t]"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_call:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Call i"
shows "i < length (func_t 𝒞)"
"∃ts'' tf1 tf2. ts = ts''@tf1 ∧ ts' = ts''@tf2 ∧ (func_t 𝒞)!i = (tf1 _> tf2)"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_call_indirect:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Call_indirect i"
shows "i < length (types_t 𝒞)"
"∃ts'' tf1 tf2. ts = ts''@tf1@[T_i32] ∧ ts' = ts''@tf2 ∧ (types_t 𝒞)!i = (tf1 _> tf2)"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_get_local:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Get_local i"
shows "∃t. ts' = ts@[t] ∧ (local 𝒞)!i = t" "i < length(local 𝒞)"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_set_local:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Set_local i"
shows "∃t. ts = ts'@[t] ∧ (local 𝒞)!i = t" "i < length(local 𝒞)"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_tee_local:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Tee_local i"
shows "∃ts'' t. ts = ts''@[t] ∧ ts' = ts''@[t] ∧ (local 𝒞)!i = t" "i < length(local 𝒞)"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_get_global:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Get_global i"
shows "∃t. ts' = ts@[t] ∧ tg_t((global 𝒞)!i) = t" "i < length(global 𝒞)"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_set_global:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Set_global i"
shows "∃t. ts = ts'@[t] ∧ (global 𝒞)!i = ⦇tg_mut = T_mut, tg_t = t⦈ ∧ i < length(global 𝒞)"
using assms is_mut_def
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct) auto
lemma b_e_type_block:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Block tf es"
shows "∃ts'' tfn tfm. tf = (tfn _> tfm) ∧ (ts = ts''@tfn) ∧ (ts' = ts''@tfm) ∧
(𝒞⦇label := [tfm] @ label 𝒞⦈ ⊢ es : tf)"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_loop:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Loop tf es"
shows "∃ts'' tfn tfm. tf = (tfn _> tfm) ∧ (ts = ts''@tfn) ∧ (ts' = ts''@tfm) ∧
(𝒞⦇label := [tfn] @ label 𝒞⦈ ⊢ es : tf)"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_if:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = If tf es1 es2"
shows "∃ts'' tfn tfm. tf = (tfn _> tfm) ∧ (ts = ts''@tfn @ [T_i32]) ∧ (ts' = ts''@tfm) ∧
(𝒞⦇label := [tfm] @ label 𝒞⦈ ⊢ es1 : tf) ∧
(𝒞⦇label := [tfm] @ label 𝒞⦈ ⊢ es2 : tf)"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_br:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Br i"
shows "i < length(label 𝒞)"
"∃ts_c ts''. ts = ts_c @ ts'' ∧ (label 𝒞)!i = ts''"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_br_if:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Br_if i"
shows "i < length(label 𝒞)"
"∃ts_c ts''. ts = ts_c @ ts'' @ [T_i32] ∧ ts' = ts_c @ ts'' ∧ (label 𝒞)!i = ts''"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_br_table:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Br_table is i"
shows "∃ts_c ts''. list_all (λi. i < length(label 𝒞) ∧ (label 𝒞)!i = ts'') (is@[i]) ∧ ts = ts_c @ ts''@[T_i32]"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, fastforce+)
lemma b_e_type_return:
assumes "𝒞 ⊢ [e] : (ts _> ts')"
"e = Return"
shows "∃ts_c ts''. ts = ts_c @ ts'' ∧ (return 𝒞) = Some ts''"
using assms
by (induction "[e]" "(ts _> ts')" arbitrary: ts ts' rule: b_e_typing.induct, auto)
lemma b_e_type_comp:
assumes "𝒞 ⊢ es@[e] : (t1s _> t4s)"
shows "∃ts'. (𝒞 ⊢ es : (t1s _> ts')) ∧ (𝒞 ⊢ [e] : (ts' _> t4s))"
proof (cases es rule: List.rev_cases)
case Nil
then show ?thesis
using assms b_e_typing.empty b_e_typing.weakening
by fastforce
next
case (snoc es' e')
show ?thesis using assms snoc b_e_typing.weakening
by (induction "es@[e]" "(t1s _> t4s)" arbitrary: t1s t4s, fastforce+)
qed
lemma b_e_type_comp2_unlift:
assumes "𝒮∙𝒞 ⊢ [$e1, $e2] : (t1s _> t2s)"
shows "∃ts'. (𝒞 ⊢ [e1] : (t1s _> ts')) ∧ (𝒞 ⊢ [e2] : (ts' _> t2s))"
using assms
unlift_b_e[of 𝒮 𝒞 "([e1, e2])" "(t1s _> t2s)"]
b_e_type_comp[of 𝒞 "[e1]" e2 t1s t2s]
by simp
lemma b_e_type_comp2_relift:
assumes "𝒞 ⊢ [e1] : (t1s _> ts')" "𝒞 ⊢ [e2] : (ts' _> t2s)"
shows "𝒮∙𝒞 ⊢ [$e1, $e2] : (ts@t1s _> ts@t2s)"
using assms
b_e_typing.composition[OF assms]
e_typing_s_typing.intros(1)[of 𝒞 "[e1, e2]" "(t1s _> t2s)"]
e_typing_s_typing.intros(3)[of 𝒮 𝒞 "([$e1,$e2])" t1s t2s ts]
by simp
lemma b_e_type_value2:
assumes "𝒞 ⊢ [C v1, C v2] : (t1s _> t2s)"
shows "t2s = t1s @ [typeof v1, typeof v2]"
proof -
obtain ts' where ts'_def:"𝒞 ⊢ [C v1] : (t1s _> ts')"
"𝒞 ⊢ [C v2] : (ts' _> t2s)"
using b_e_type_comp assms
by (metis append_butlast_last_id butlast.simps(2) last_ConsL last_ConsR list.distinct(1))
have "ts' = t1s @ [typeof v1]"
using b_e_type_value ts'_def(1)
by fastforce
thus ?thesis
using b_e_type_value ts'_def(2)
by fastforce
qed
lemma e_type_comp:
assumes "𝒮∙𝒞 ⊢ es@[e] : (t1s _> t3s)"
shows "∃ts'. (𝒮∙𝒞 ⊢ es : (t1s _> ts')) ∧ (𝒮∙𝒞 ⊢ [e] : (ts' _> t3s))"
proof (cases es rule: List.rev_cases)
case Nil
thus ?thesis
using assms e_typing_s_typing.intros(1)
by (metis append_Nil b_e_type_empty list.simps(8))
next
case (snoc es' e')
show ?thesis using assms snoc
proof (induction "es@[e]" "(t1s _> t3s)" arbitrary: t1s t3s)
case (1 𝒞 b_es 𝒮)
obtain es'' e'' where b_e_defs:"($* (es'' @ [e''])) = ($* b_es)"
using 1(1,2)
by (metis Nil_is_map_conv append_is_Nil_conv not_Cons_self2 rev_exhaust)
hence "($*es'') = es" "($e'') = e"
using 1(2) inj_basic map_injective
by auto
moreover
have "𝒞 ⊢ (es'' @ [e'']) : (t1s _> t3s)" using 1(1)
using inj_basic map_injective b_e_defs
by blast
then obtain t2s where "𝒞 ⊢ es'' : (t1s _> t2s)" "𝒞 ⊢ [e''] : (t2s _> t3s)"
using b_e_type_comp
by blast
ultimately
show ?case
using e_typing_s_typing.intros(1)
by fastforce
next
case (3 𝒮 𝒞 t1s t2s ts)
thus ?case
using e_typing_s_typing.intros(3)
by fastforce
qed auto
qed
lemma e_type_comp_conc:
assumes "𝒮∙𝒞 ⊢ es : (t1s _> t2s)"
"𝒮∙𝒞 ⊢ es' : (t2s _> t3s)"
shows "𝒮∙𝒞 ⊢ es@es' : (t1s _> t3s)"
using assms(2)
proof (induction es' arbitrary: t3s rule: List.rev_induct)
case Nil
hence "t2s = t3s"
using unlift_b_e[of _ _ "[]"] b_e_type_empty[of _ t2s t3s]
by fastforce
then show ?case
using Nil assms(1) e_typing_s_typing.intros(2)
by fastforce
next
case (snoc x xs)
then obtain ts' where "𝒮∙𝒞 ⊢ xs : (t2s _> ts')" "𝒮∙𝒞 ⊢ [x] : (ts' _> t3s)"
using e_type_comp[of _ _ xs x]
by fastforce
then show ?case
using snoc(1)[of ts'] e_typing_s_typing.intros(2)[of _ _ "es @ xs" t1s ts' x t3s]
by simp
qed
lemma b_e_type_comp_conc:
assumes "𝒞 ⊢ es : (t1s _> t2s)"
"𝒞 ⊢ es' : (t2s _> t3s)"
shows "𝒞 ⊢ es@es' : (t1s _> t3s)"
proof -
fix 𝒮
have 1:"𝒮∙𝒞 ⊢ $*es : (t1s _> t2s)"
using e_typing_s_typing.intros(1)[OF assms(1)]
by fastforce
have 2:"𝒮∙𝒞 ⊢ $*es' : (t2s _> t3s)"
using e_typing_s_typing.intros(1)[OF assms(2)]
by fastforce
show ?thesis
using e_type_comp_conc[OF 1 2]
by (simp add: unlift_b_e)
qed
lemma e_type_comp_conc1:
assumes "𝒮∙𝒞 ⊢ es@es' : (ts _> ts')"
shows "∃ts''. (𝒮∙𝒞 ⊢ es : (ts _> ts'')) ∧ (𝒮∙𝒞 ⊢ es' : (ts'' _> ts'))"
using assms
proof (induction es' arbitrary: ts ts' rule: List.rev_induct)
case Nil
thus ?case
using b_e_type_empty[of _ ts' ts'] e_typing_s_typing.intros(1)
by fastforce
next
case (snoc x xs)
then show ?case
using e_type_comp[of 𝒮 𝒞 "es @ xs" x ts ts'] e_typing_s_typing.intros(2)[of 𝒮 𝒞 xs _ _ x ts']
by fastforce
qed
lemma e_type_comp_conc2:
assumes "𝒮∙𝒞 ⊢ es@es'@es'' : (t1s _> t2s)"
shows "∃ts' ts''. (𝒮∙𝒞 ⊢ es : (t1s _> ts'))
∧ (𝒮∙𝒞 ⊢ es' : (ts' _> ts''))
∧ (𝒮∙𝒞 ⊢ es'' : (ts'' _> t2s))"
proof -
obtain ts' where "𝒮∙𝒞 ⊢ es : (t1s _> ts')" "𝒮∙𝒞 ⊢ es'@es'' : (ts' _> t2s)"
using assms(1) e_type_comp_conc1
by fastforce
moreover
then obtain ts'' where "𝒮∙𝒞 ⊢ es' : (ts' _> ts'')" "𝒮∙𝒞 ⊢ es'' : (ts'' _> t2s)"
using e_type_comp_conc1
by fastforce
ultimately
show ?thesis
by fastforce
qed
lemma b_e_type_value_list:
assumes "(𝒞 ⊢ es@[C v] : (ts _> ts'@[t]))"
shows "(𝒞 ⊢ es : (ts _> ts'))"
"(typeof v = t)"
proof -
obtain ts'' where "(𝒞 ⊢ es : (ts _> ts''))" "(𝒞 ⊢ [C v] : (ts'' _> ts' @ [t]))"
using b_e_type_comp assms
by blast
thus "(𝒞 ⊢ es : (ts _> ts'))" "(typeof v = t)"
using b_e_type_value[of 𝒞 "C v" "ts''" "ts' @ [t]"]
by auto
qed
lemma e_type_label:
assumes "𝒮∙𝒞 ⊢ [Label n es0 es] : (ts _> ts')"
shows "∃tls t2s. (ts' = (ts@t2s))
∧ length tls = n
∧ (𝒮∙𝒞 ⊢ es0 : (tls _> t2s))
∧ (𝒮∙𝒞⦇label := [tls] @ (label 𝒞)⦈ ⊢ es : ([] _> t2s))"
using assms
proof (induction "𝒮" "𝒞" "[Label n es0 es]" "(ts _> ts')" arbitrary: ts ts')
case (1 𝒞 b_es 𝒮)
then show ?case
by (simp add: map_eq_Cons_conv)
next
case (2 𝒮 𝒞 es t1s t2s e t3s)
then show ?case
by (metis append_self_conv2 b_e_type_empty last_snoc list.simps(8) unlift_b_e)
next
case (3 𝒮 𝒞 t1s t2s ts)
then show ?case
by simp
next
case (7 𝒮 𝒞 t2s)
then show ?case
by fastforce
qed
lemma e_type_callcl_native:
assumes "𝒮∙𝒞 ⊢ [Callcl cl] : (t1s' _> t2s')"
"cl = Func_native i tf ts es"
shows "∃t1s t2s ts_c. (t1s' = ts_c @ t1s)
∧ (t2s' = ts_c @ t2s)
∧ tf = (t1s _> t2s)
∧ i < length (s_inst 𝒮)
∧ (((s_inst 𝒮)!i)⦇local := (local ((s_inst 𝒮)!i)) @ t1s @ ts, label := ([t2s] @ (label ((s_inst 𝒮)!i))), return := Some t2s⦈ ⊢ es : ([] _> t2s))"
using assms
proof (induction "𝒮" "𝒞" "[Callcl cl]" "(t1s' _> t2s')" arbitrary: t1s' t2s')
case (1 𝒞 b_es 𝒮)
thus ?case
by auto
next
case (2 𝒮 𝒞 es t1s t2s e t3s)
have "𝒞 ⊢ [] : (t1s _> t2s)"
using 2(1,5) unlift_b_e
by (metis Nil_is_map_conv append_Nil butlast_snoc)
thus ?case
using 2(4,5,6)
by fastforce
next
case (3 𝒮 𝒞 t1s t2s ts)
thus ?case
by fastforce
next
case (6 𝒮 𝒞)
thus ?case
unfolding cl_typing.simps
by fastforce
qed
lemma e_type_callcl_host:
assumes "𝒮∙𝒞 ⊢ [Callcl cl] : (t1s' _> t2s')"
"cl = Func_host tf f"
shows "∃t1s t2s ts_c. (t1s' = ts_c @ t1s)
∧ (t2s' = ts_c @ t2s)
∧ tf = (t1s _> t2s)"
using assms
proof (induction "𝒮" "𝒞" "[Callcl cl]" "(t1s' _> t2s')" arbitrary: t1s' t2s')
case (1 𝒞 b_es 𝒮)
thus ?case
by auto
next
case (2 𝒮 𝒞 es t1s t2s e t3s)
have "𝒞 ⊢ [] : (t1s _> t2s)"
using 2(1,5) unlift_b_e
by (metis Nil_is_map_conv append_Nil butlast_snoc)
thus ?case
using 2(4,5,6)
by fastforce
next
case (3 𝒮 𝒞 t1s t2s ts)
thus ?case
by fastforce
next
case (6 𝒮 𝒞)
thus ?case
unfolding cl_typing.simps
by fastforce
qed
lemma e_type_callcl:
assumes "𝒮∙𝒞 ⊢ [Callcl cl] : (t1s' _> t2s')"
shows "∃t1s t2s ts_c. (t1s' = ts_c @ t1s)
∧ (t2s' = ts_c @ t2s)
∧ cl_type cl = (t1s _> t2s)"
proof (cases cl)
case (Func_native x11 x12 x13 x14)
thus ?thesis
using e_type_callcl_native[OF assms]
unfolding cl_type_def
by (cases x12) fastforce
next
case (Func_host x21 x22)
thus ?thesis
using e_type_callcl_host[OF assms]
unfolding cl_type_def
by fastforce
qed
lemma s_type_unfold:
assumes "𝒮∙rs ⊩_i vs;es : ts"
shows "i < length (s_inst 𝒮)"
"(rs = Some ts) ∨ rs = None"
"(𝒮∙((s_inst 𝒮)!i)⦇local := (local ((s_inst 𝒮)!i)) @ (map typeof vs), return := rs⦈ ⊢ es : ([] _> ts))"
using assms
by (induction vs es ts, auto)
lemma e_type_local:
assumes "𝒮∙𝒞 ⊢ [Local n i vs es] : (ts _> ts')"
shows "∃tls. i < length (s_inst 𝒮)
∧ length tls = n
∧ (𝒮∙((s_inst 𝒮)!i)⦇local := (local ((s_inst 𝒮)!i)) @ (map typeof vs), return := Some tls⦈ ⊢ es : ([] _> tls))
∧ ts' = ts @ tls"
using assms
proof (induction "𝒮" "𝒞" "[Local n i vs es]" "(ts _> ts')" arbitrary: ts ts')
case (2 𝒮 𝒞 es' t1s t2s e t3s)
have "t1s = t2s"
using 2 unlift_b_e
by force
thus ?case
using 2
by simp
qed (auto simp add: unlift_b_e s_typing.simps)
lemma e_type_local_shallow:
assumes "𝒮∙𝒞 ⊢ [Local n i vs es] : (ts _> ts')"
shows "∃tls. length tls = n ∧ ts' = ts@tls ∧ (𝒮∙(Some tls) ⊩_i vs;es : tls)"
using assms
proof (induction "𝒮" "𝒞" "[Local n i vs es]" "(ts _> ts')" arbitrary: ts ts')
case (1 𝒞 b_es 𝒮)
thus ?case
by (metis e.distinct(7) map_eq_Cons_D)
next
case (2 𝒮 𝒞 es t1s t2s e t3s)
thus ?case
by simp (metis append_Nil append_eq_append_conv e_type_comp_conc e_type_local)
qed simp_all
lemma e_type_const_unwrap:
assumes "is_const e"
shows "∃v. e = $C v"
using assms
proof (cases e)
case (Basic x1)
then show ?thesis
using assms
proof (cases x1)
case (EConst x23)
thus ?thesis
using Basic e_typing_s_typing.intros(1,3)
by fastforce
qed (simp_all add: is_const_def)
qed (simp_all add: is_const_def)
lemma is_const_list1:
assumes "ves = map (Basic ∘ EConst) vs"
shows "const_list ves"
using assms
proof (induction vs arbitrary: ves)
case Nil
then show ?case
unfolding const_list_def
by simp
next
case (Cons a vs)
then obtain ves' where "ves' = map (Basic ∘ EConst) vs"
by blast
moreover
have "is_const ((Basic ∘ EConst) a)"
unfolding is_const_def
by simp
ultimately
show ?case
using Cons
unfolding const_list_def
by auto
qed
lemma is_const_list:
assumes "ves = $$* vs"
shows "const_list ves"
using assms is_const_list1
unfolding comp_def
by auto
lemma const_list_cons_last:
assumes "const_list (es@[e])"
shows "const_list es"
"is_const e"
using assms list_all_append[of is_const es "[e]"]
unfolding const_list_def
by auto
lemma e_type_const1:
assumes "is_const e"
shows "∃t. (𝒮∙𝒞 ⊢ [e] : (ts _> ts@[t]))"
using assms
proof (cases e)
case (Basic x1)
then show ?thesis
using assms
proof (cases x1)
case (EConst x23)
hence "𝒞 ⊢ [x1] : ([] _> [typeof x23])"
by (simp add: b_e_typing.intros(1))
thus ?thesis
using Basic e_typing_s_typing.intros(1,3)
by (metis append_Nil2 to_e_list_1)
qed (simp_all add: is_const_def)
qed (simp_all add: is_const_def)
lemma e_type_const:
assumes "is_const e"
"𝒮∙𝒞 ⊢ [e] : (ts _> ts')"
shows "∃t. (ts' = ts@[t]) ∧ (𝒮∙𝒞' ⊢ [e] : ([] _> [t]))"
using assms
proof (cases e)
case (Basic x1)
then show ?thesis
using assms
proof (cases x1)
case (EConst x23)
then have "ts' = ts @ [typeof x23]"
by (metis (no_types) Basic assms(2) b_e_type_value list.simps(8,9) unlift_b_e)
moreover
have "𝒮∙𝒞' ⊢ [e] : ([] _> [typeof x23])"
using Basic EConst b_e_typing.intros(1) e_typing_s_typing.intros(1)
by fastforce
ultimately
show ?thesis
by simp
qed (simp_all add: is_const_def)
qed (simp_all add: is_const_def)
lemma const_typeof:
assumes "𝒮∙𝒞 ⊢ [$C v] : ([] _> [t])"
shows "typeof v = t"
using assms
proof -
have "𝒞 ⊢ [C v] : ([] _> [t])"
using unlift_b_e assms
by fastforce
thus ?thesis
by (induction "[C v]" "([] _> [t])" rule: b_e_typing.induct, auto)
qed
lemma e_type_const_list:
assumes "const_list vs"
"𝒮∙𝒞 ⊢ vs : (ts _> ts')"
shows "∃tvs. ts' = ts @ tvs ∧ length vs = length tvs ∧ (𝒮∙𝒞' ⊢ vs : ([] _> tvs))"
using assms
proof (induction vs arbitrary: ts ts' rule: List.rev_induct)
case Nil
have "𝒮∙𝒞' ⊢ [] : ([] _> [])"
using b_e_type_empty[of 𝒞' "[]" "[]"] e_typing_s_typing.intros(1)
by fastforce
thus ?case
using Nil
by (metis append_Nil2 b_e_type_empty list.map(1) list.size(3) unlift_b_e)
next
case (snoc x xs)
hence v_lists:"list_all is_const xs" "is_const x"
unfolding const_list_def
by simp_all
obtain ts'' where ts''_def:"𝒮∙𝒞 ⊢ xs : (ts _> ts'')" "𝒮∙𝒞 ⊢ [x] : (ts'' _> ts')"
using snoc(3) e_type_comp
by fastforce
then obtain ts_b where ts_b_def:"ts'' = ts @ ts_b" "length xs = length ts_b" "𝒮∙𝒞' ⊢ xs : ([] _> ts_b)"
using snoc(1) v_lists(1)
unfolding const_list_def
by fastforce
then obtain t where t_def:"ts' = ts @ ts_b @ [t]" "𝒮∙𝒞' ⊢ [x] : ([] _> [t])"
using e_type_const v_lists(2) ts''_def
by fastforce
moreover
then have "length (ts_b@[t]) = length (xs@[x])"
using ts_b_def(2)
by simp
moreover
have "𝒮∙𝒞' ⊢ (xs@[x]) : ([] _> ts_b@[t])"
using ts_b_def(3) t_def e_typing_s_typing.intros(2,3)
by fastforce
ultimately
show ?case
by simp
qed
lemma e_type_const_list_snoc:
assumes "const_list vs"
"𝒮∙𝒞 ⊢ vs : ([] _> ts@[t])"
shows "∃vs1 v2. (𝒮∙𝒞 ⊢ vs1 : ([] _> ts))
∧ (𝒮∙𝒞 ⊢ [v2] : (ts _> ts@[t]))
∧ (vs = vs1@[v2])
∧ const_list vs1
∧ is_const v2"
using assms
proof -
obtain vs' v where vs_def:"vs = vs'@[v]"
using e_type_const_list[OF assms(1,2)]
by (metis append_Nil append_eq_append_conv list.size(3) snoc_eq_iff_butlast)
hence consts_def:"const_list vs'" "is_const v"
using assms(1)
unfolding const_list_def
by auto
obtain ts' where ts'_def:"𝒮∙𝒞 ⊢ vs' : ([] _> ts')" "𝒮∙𝒞 ⊢ [v] : (ts' _> ts@[t])"
using vs_def assms(2) e_type_comp[of 𝒮 𝒞 vs' v "[]" "ts@[t]"]
by fastforce
obtain c where "v = $C c"
using e_type_const_unwrap consts_def(2)
by fastforce
hence "ts' = ts"
using ts'_def(2) unlift_b_e[of 𝒮 𝒞 "[C c]"] b_e_type_value
by fastforce
thus ?thesis using ts'_def vs_def consts_def
by simp
qed
lemma e_type_const_list_cons:
assumes "const_list vs"
"𝒮∙𝒞 ⊢ vs : ([] _> (ts1@ts2))"
shows "∃vs1 vs2. (𝒮∙𝒞 ⊢ vs1 : ([] _> ts1))
∧ (𝒮∙𝒞 ⊢ vs2 : (ts1 _> (ts1@ts2)))
∧ vs = vs1@vs2
∧ const_list vs1
∧ const_list vs2"
using assms
proof (induction "ts1@ts2" arbitrary: vs ts1 ts2 rule: List.rev_induct)
case Nil
thus ?case
using e_type_const_list
by fastforce
next
case (snoc t ts)
note snoc_outer = snoc
show ?case
proof (cases ts2 rule: List.rev_cases)
case Nil
have "𝒮∙𝒞 ⊢ [] : (ts1 _> ts1 @ [])"
using b_e_typing.empty b_e_typing.weakening e_typing_s_typing.intros(1)
by fastforce
then show ?thesis
using snoc(3,4) Nil
unfolding const_list_def
by auto
next
case (snoc ts2' a)
obtain vs1 v2 where vs1_def:"(𝒮∙𝒞 ⊢ vs1 : ([] _> ts1 @ ts2'))"
"(𝒮∙𝒞 ⊢ [v2] : (ts1 @ ts2' _> ts1 @ ts2' @[t]))"
"(vs = vs1@[v2])"
"const_list vs1"
"is_const v2"
"ts = ts1 @ ts2'"
using e_type_const_list_snoc[OF snoc_outer(3), of 𝒮 𝒞 "ts1@ts2'" t]
snoc_outer(2,4) snoc
by fastforce
show ?thesis
using snoc_outer(1)[OF vs1_def(6,4,1)] snoc_outer(2) vs1_def(3,5)
e_typing_s_typing.intros(2)[OF _ vs1_def(2), of _ ts1]
snoc
unfolding const_list_def
by fastforce
qed
qed
lemma e_type_const_conv_vs:
assumes "const_list ves"
shows "∃vs. ves = $$* vs"
using assms
proof (induction ves)
case Nil
thus ?case
by simp
next
case (Cons a ves)
thus ?case
using e_type_const_unwrap
unfolding const_list_def
by (metis (no_types, lifting) list.pred_inject(2) list.simps(9))
qed
lemma types_exist_lfilled:
assumes "Lfilled k lholed es lfilled"
"𝒮∙𝒞 ⊢ lfilled : (ts _> ts')"
shows "∃t1s t2s 𝒞' arb_label. (𝒮∙𝒞⦇label := arb_label@(label 𝒞)⦈ ⊢ es : (t1s _> t2s))"
using assms
proof (induction arbitrary: 𝒞 ts ts' rule: Lfilled.induct)
case (L0 vs lholed es' es)
hence "𝒮∙(𝒞⦇label := label 𝒞⦈) ⊢ vs @ es @ es' : (ts _> ts')"
by simp
thus ?case
using e_type_comp_conc2
by (metis append_Nil)
next
case (LN vs lholed n es' l es'' k es lfilledk)
obtain ts'' ts''' where "𝒮∙𝒞 ⊢ [Label n es' lfilledk] : (ts'' _> ts''')"
using e_type_comp_conc2[OF LN(5)]
by fastforce
then obtain t1s t2s ts where test:"𝒮∙𝒞⦇label := [ts] @ (label 𝒞)⦈ ⊢ lfilledk : (t1s _> t2s)"
using e_type_label
by metis
show ?case
using LN(4)[OF test(1)]
by simp (metis append.assoc append_Cons append_Nil)
qed
lemma types_exist_lfilled_weak:
assumes "Lfilled k lholed es lfilled"
"𝒮∙𝒞 ⊢ lfilled : (ts _> ts')"
shows "∃t1s t2s 𝒞' arb_label arb_return. (𝒮∙𝒞⦇label := arb_label, return := arb_return⦈ ⊢ es : (t1s _> t2s))"
proof -
have "∃t1s t2s 𝒞' arb_label. (𝒮∙𝒞⦇label := arb_label, return := (return 𝒞)⦈ ⊢ es : (t1s _> t2s))"
using types_exist_lfilled[OF assms]
by fastforce
thus ?thesis
by fastforce
qed
lemma store_typing_imp_func_agree:
assumes "store_typing s 𝒮"
"i < length (s_inst 𝒮)"
"j < length (func_t ((s_inst 𝒮)!i))"
shows "(sfunc_ind s i j) < length (s_funcs 𝒮)"
"cl_typing 𝒮 (sfunc s i j) ((s_funcs 𝒮)!(sfunc_ind s i j))"
"((s_funcs 𝒮)!(sfunc_ind s i j)) = (func_t ((s_inst 𝒮)!i))!j"
proof -
have funcs_agree:"list_all2 (cl_typing 𝒮) (funcs s) (s_funcs 𝒮)"
using assms(1)
unfolding store_typing.simps
by auto
have "list_all2 (funci_agree (s_funcs 𝒮)) (inst.funcs ((inst s)!i)) (func_t ((s_inst 𝒮)!i))"
using assms(1,2) store_typing_imp_inst_length_eq store_typing_imp_inst_typing
by (fastforce simp add: inst_typing.simps)
hence "funci_agree (s_funcs 𝒮) ((inst.funcs ((inst s)!i))!j) ((func_t ((s_inst 𝒮)!i))!j)"
using assms(3) list_all2_nthD2
by blast
thus "(sfunc_ind s i j) < length (s_funcs 𝒮)"
"((s_funcs 𝒮)!(sfunc_ind s i j)) = (func_t ((s_inst 𝒮)!i))!j"
unfolding funci_agree_def sfunc_ind_def
by auto
thus "cl_typing 𝒮 (sfunc s i j) ((s_funcs 𝒮)!(sfunc_ind s i j))"
using funcs_agree list_all2_nthD2
unfolding sfunc_def
by fastforce
qed
lemma store_typing_imp_glob_agree:
assumes "store_typing s 𝒮"
"i < length (s_inst 𝒮)"
"j < length (global ((s_inst 𝒮)!i))"
shows "(sglob_ind s i j) < length (s_globs 𝒮)"
"glob_agree (sglob s i j) ((s_globs 𝒮)!(sglob_ind s i j))"
"((s_globs 𝒮)!(sglob_ind s i j)) = (global ((s_inst 𝒮)!i))!j"
proof -
have globs_agree:"list_all2 glob_agree (globs s) (s_globs 𝒮)"
using assms(1)
unfolding store_typing.simps
by auto
have "list_all2 (globi_agree (s_globs 𝒮)) (inst.globs ((inst s)!i)) (global ((s_inst 𝒮)!i))"
using assms(1,2) store_typing_imp_inst_length_eq store_typing_imp_inst_typing
by (fastforce simp add: inst_typing.simps)
hence "globi_agree (s_globs 𝒮) ((inst.globs ((inst s)!i))!j) ((global ((s_inst 𝒮)!i))!j)"
using assms(3) list_all2_nthD2
by blast
thus "(sglob_ind s i j) < length (s_globs 𝒮)"
"((s_globs 𝒮)!(sglob_ind s i j)) = (global ((s_inst 𝒮)!i))!j"
unfolding globi_agree_def sglob_ind_def
by auto
thus "glob_agree (sglob s i j) ((s_globs 𝒮)!(sglob_ind s i j))"
using globs_agree list_all2_nthD2
unfolding sglob_def
by fastforce
qed
lemma store_typing_imp_mem_agree_Some:
assumes "store_typing s 𝒮"
"i < length (s_inst 𝒮)"
"smem_ind s i = Some j"
shows "j < length (s_mem 𝒮)"
"mem_agree ((mem s)!j) ((s_mem 𝒮)!j)"
"∃x. ((s_mem 𝒮)!j) = x ∧ (memory ((s_inst 𝒮)!i)) = Some x"
proof -
have mems_agree:"list_all2 mem_agree (mem s) (s_mem 𝒮)"
using assms(1)
unfolding store_typing.simps
by auto
hence "memi_agree (s_mem 𝒮) ((inst.mem ((inst s)!i))) ((memory ((s_inst 𝒮)!i)))"
using assms(1,2) store_typing_imp_inst_length_eq store_typing_imp_inst_typing
by (fastforce simp add: inst_typing.simps)
thus "j < length (s_mem 𝒮)"
"∃x. ((s_mem 𝒮)!j) = x ∧ (memory ((s_inst 𝒮)!i)) = Some x"
using assms(3)
unfolding memi_agree_def smem_ind_def
by auto
thus "mem_agree ((mem s)!j) ((s_mem 𝒮)!j)"
using mems_agree list_all2_nthD2
unfolding sglob_def
by fastforce
qed
lemma store_typing_imp_mem_agree_None:
assumes "store_typing s 𝒮"
"i < length (s_inst 𝒮)"
"smem_ind s i = None"
shows "(memory ((s_inst 𝒮)!i)) = None"
proof -
have mems_agree:"list_all2 mem_agree (mem s) (s_mem 𝒮)"
using assms(1)
unfolding store_typing.simps
by auto
hence "memi_agree (s_mem 𝒮) ((inst.mem ((inst s)!i))) ((memory ((s_inst 𝒮)!i)))"
using assms(1,2) store_typing_imp_inst_length_eq store_typing_imp_inst_typing
by (fastforce simp add: inst_typing.simps)
thus ?thesis
using assms(3)
unfolding memi_agree_def smem_ind_def
by auto
qed
lemma store_mem_exists:
assumes "i < length (s_inst 𝒮)"
"store_typing s 𝒮"
shows "Option.is_none (memory ((s_inst 𝒮)!i)) = Option.is_none (inst.mem ((inst s)!i))"
proof -
obtain j where j_def:"j = (inst.mem ((inst s)!i))"
by blast
obtain m where m_def:"m = (memory ((s_inst 𝒮)!i))"
by blast
have inst_typ:"inst_typing 𝒮 ((inst s)!i) ((s_inst 𝒮)!i)"
using assms
unfolding store_typing.simps list_all2_conv_all_nth
by auto
thus ?thesis
unfolding inst_typing.simps memi_agree_def
by auto
qed
lemma store_preserved_mem:
assumes "store_typing s 𝒮"
"s' = s⦇s.mem := (s.mem s)[i := mem']⦈"
"mem_size mem' ≥ mem_size orig_mem"
"((s.mem s)!i) = orig_mem"
shows "store_typing s' 𝒮"
proof -
obtain insts fs clss bss gs where "s = ⦇inst = insts, funcs = fs, tab = clss, mem = bss, globs = gs⦈"
using s.cases
by blast
moreover
obtain insts' fs' clss' bss' gs' where "s' = ⦇inst = insts', funcs = fs', tab = clss', mem = bss', globs = gs'⦈"
using s.cases
by blast
moreover
obtain 𝒞s tfs ns ms tgs where "𝒮 = ⦇s_inst = 𝒞s, s_funcs = tfs, s_tab = ns, s_mem = ms, s_globs = tgs⦈"
using s_context.cases
by blast
moreover
note s_S_defs = calculation
hence
"insts = insts'"
"fs = fs'"
"clss = clss'"
"gs = gs'"
using assms(2)
by simp_all
hence
"list_all2 (inst_typing 𝒮) insts' 𝒞s"
"list_all2 (cl_typing 𝒮) fs' tfs"
"list_all (tab_agree 𝒮) (concat clss')"
"list_all2 (λcls n. n ≤ length cls) clss' ns"
"list_all2 glob_agree gs' tgs"
using s_S_defs assms(1)
unfolding store_typing.simps
by auto
moreover
have "list_all2 (λ bs m. m ≤ mem_size bs) bss' ms"
proof -
have "length bss = length bss'"
using assms(2) s_S_defs
by (simp)
moreover
have initial_mem:"list_all2 (λ bs m. m ≤ mem_size bs) bss ms"
using assms(1) s_S_defs
unfolding store_typing.simps mem_agree_def
by blast
have "⋀n. n < length bss ⟹ (λ bs m. m ≤ mem_size bs) (bss'!n) (ms!n)"
proof -
fix n
assume local_assms:"n < length bss"
obtain 𝒞_m where cmdef:"𝒞_m = 𝒞s ! n"
by blast
hence "(λ bs m. m ≤ mem_size bs) (bss!n) (ms!n)"
using initial_mem local_assms
unfolding list_all2_conv_all_nth
by simp
thus "(λ bs m. m ≤ mem_size bs) (bss'!n) (ms!n)"
using assms(2,3,4) s_S_defs local_assms
by (cases "n=i", auto)
qed
ultimately
show ?thesis
by (metis initial_mem list_all2_all_nthI list_all2_lengthD)
qed
ultimately
show ?thesis
unfolding store_typing.simps mem_agree_def
by simp
qed
lemma types_agree_imp_e_typing:
assumes "types_agree t v"
shows "𝒮∙𝒞 ⊢ [$C v] : ([] _> [t])"
using assms e_typing_s_typing.intros(1)[OF b_e_typing.intros(1)]
unfolding types_agree_def
by fastforce
lemma list_types_agree_imp_e_typing:
assumes "list_all2 types_agree ts vs"
shows "𝒮∙𝒞 ⊢ $$* vs : ([] _> ts)"
using assms
proof (induction rule: list_all2_induct)
case Nil
thus ?case
using b_e_typing.empty e_typing_s_typing.intros(1)
by fastforce
next
case (Cons t ts v vs)
hence "𝒮∙𝒞 ⊢ [$C v] : ([] _> [t])"
using types_agree_imp_e_typing
by fastforce
thus ?case
using e_typing_s_typing.intros(3)[OF Cons(3), of "[t]"] e_type_comp_conc
by fastforce
qed
lemma b_e_typing_imp_list_types_agree:
assumes "𝒞 ⊢ (map (λv. C v) vs) : (ts' _> ts'@ts)"
shows "list_all2 types_agree ts vs"
using assms
proof (induction "(map (λv. C v) vs)" "(ts' _> ts'@ts)" arbitrary: ts ts' vs rule: b_e_typing.induct)
case (composition 𝒞 es t1s t2s e)
obtain vs1 vs2 where es_e_def:"es = map EConst vs1" "[e] = map EConst vs2" "vs1@vs2=vs"
using composition(5)
by (metis (no_types) last_map list.simps(8,9) map_butlast snoc_eq_iff_butlast)
have "const_list ($*es)"
using es_e_def(1) is_const_list1
by auto
then obtain tvs1 where "t2s = t1s@tvs1"
using e_type_const_list e_typing_s_typing.intros(1)[OF composition(1)]
by fastforce
moreover
have "const_list ($*[e])"
using es_e_def(2) is_const_list1
by auto
then obtain tvs2 where "t1s @ ts = t2s @ tvs2"
using e_type_const_list e_typing_s_typing.intros(1)[OF composition(3)]
by fastforce
ultimately
show ?case
using composition(2,4,5) es_e_def
by (auto simp add: list_all2_appendI)
qed (auto simp add: types_agree_def)
lemma e_typing_imp_list_types_agree:
assumes "𝒮∙𝒞 ⊢ ($$* vs) : (ts' _> ts'@ts)"
shows "list_all2 types_agree ts vs"
proof -
have "($$* vs) = $* (map (λv. C v) vs)"
by simp
thus ?thesis
using assms unlift_b_e b_e_typing_imp_list_types_agree
by (fastforce simp del: map_map)
qed
lemma store_extension_imp_store_typing:
assumes "store_extension s s'"
"store_typing s 𝒮"
shows "store_typing s' 𝒮"
proof -
obtain insts fs clss bss gs where "s = ⦇inst = insts, funcs = fs, tab = clss, mem = bss, globs = gs⦈"
using s.cases
by blast
moreover
obtain insts' fs' clss' bss' gs' where "s' = ⦇inst = insts', funcs = fs', tab = clss', mem = bss', globs = gs'⦈"
using s.cases
by blast
moreover
obtain 𝒞s tfs ns ms tgs where "𝒮 = ⦇s_inst = 𝒞s, s_funcs = tfs, s_tab = ns, s_mem = ms, s_globs = tgs⦈"
using s_context.cases
by blast
moreover
note s_S_defs = calculation
hence
"insts = insts'"
"fs = fs'"
"clss = clss'"
"gs = gs'"
using assms(1)
unfolding store_extension.simps
by simp_all
hence
"list_all2 (inst_typing 𝒮) insts' 𝒞s"
"list_all2 (cl_typing 𝒮) fs' tfs"
"list_all (tab_agree 𝒮) (concat clss')"
"list_all2 (λcls n. n ≤ length cls) clss' ns"
"list_all2 glob_agree gs' tgs"
using s_S_defs assms(2)
unfolding store_typing.simps
by auto
moreover
have "list_all2 (λ bs m. m ≤ mem_size bs) bss ms"
using s_S_defs(1,3) assms(2)
unfolding store_typing.simps mem_agree_def
by simp
hence "list_all2 mem_agree bss' ms"
using assms(1) s_S_defs(1,2)
unfolding store_extension.simps list_all2_conv_all_nth mem_agree_def
by fastforce
ultimately
show ?thesis
using store_typing.intros
by fastforce
qed
lemma lfilled_deterministic:
assumes "Lfilled k lfilled es les"
"Lfilled k lfilled es les'"
shows "les = les'"
using assms
proof (induction arbitrary: les' rule: Lfilled.induct)
case (L0 vs lholed es' es)
thus ?case
by (fastforce simp add: Lfilled.simps[of 0])
next
case (LN vs lholed n es' l es'' k es lfilledk)
thus ?case
unfolding Lfilled.simps[of "(k + 1)"]
by fastforce
qed
end
Theory Wasm_Properties
section ‹Lemmas for Soundness Proof›
theory Wasm_Properties imports Wasm_Properties_Aux begin
subsection ‹Preservation›
lemma t_cvt: assumes "cvt t sx v = Some v'" shows "t = typeof v'"
using assms
unfolding cvt_def typeof_def
apply (cases t)
apply (simp add: option.case_eq_if, metis option.discI option.inject v.simps(17))
apply (simp add: option.case_eq_if, metis option.discI option.inject v.simps(18))
apply (simp add: option.case_eq_if, metis option.discI option.inject v.simps(19))
apply (simp add: option.case_eq_if, metis option.discI option.inject v.simps(20))
done
lemma store_preserved1:
assumes "⦇s;vs;es⦈ ↝_i ⦇s';vs';es'⦈"
"store_typing s 𝒮"
"𝒮∙𝒞 ⊢ es : (ts _> ts')"
"𝒞 = ((s_inst 𝒮)!i)⦇local := local ((s_inst 𝒮)!i) @ (map typeof vs), label := arb_label, return := arb_return⦈"
"i < length (s_inst 𝒮)"
shows "store_typing s' 𝒮"
using assms
proof (induction arbitrary: 𝒞 arb_label arb_return ts ts' rule: reduce.induct)
case (callcl_host_Some cl t1s t2s f ves vcs n m s hs s' vcs' vs i)
obtain ts'' where ts''_def:"𝒮∙𝒞 ⊢ ves : (ts _> ts'')" "𝒮∙𝒞 ⊢ [Callcl cl] : (ts'' _> ts')"
using callcl_host_Some(8) e_type_comp
by fastforce
have ves_c:"const_list ves"
using is_const_list[OF callcl_host_Some(2)]
by simp
then obtain tvs where tvs_def:"ts'' = ts @ tvs"
"length t1s = length tvs"
"𝒮∙𝒞 ⊢ ves : ([] _> tvs)"
using ts''_def(1) e_type_const_list[of ves 𝒮 𝒞 ts ts''] callcl_host_Some
by fastforce
hence "ts'' = ts @ t1s"
"ts' = ts @ t2s"
using e_type_callcl_host[OF ts''_def(2) callcl_host_Some(1)]
by auto
moreover
hence "list_all2 types_agree t1s vcs"
using e_typing_imp_list_types_agree[where ?ts' = "[]"] callcl_host_Some(2) tvs_def(1,3)
by fastforce
thus ?case
using store_extension_imp_store_typing
host_apply_preserve_store[OF _ callcl_host_Some(6)] callcl_host_Some(7)
by fastforce
next
case (set_global s i j v s' vs)
obtain insts fs clss bss gs where "s = ⦇inst = insts, funcs = fs, tab = clss, mem = bss, globs = gs⦈"
using s.cases
by blast
moreover
obtain insts' fs' clss' bss' gs' where "s' = ⦇inst = insts', funcs = fs', tab = clss', mem = bss', globs = gs'⦈"
using s.cases
by blast
moreover
obtain 𝒞s tfs ns ms tgs where "𝒮 = ⦇s_inst = 𝒞s, s_funcs = tfs, s_tab = ns, s_mem = ms, s_globs = tgs⦈"
using s_context.cases
by blast
moreover
note s_S_defs = calculation
have
"insts = insts'"
"fs = fs'"
"clss = clss'"
"bss = bss'"
using set_global(1) s_S_defs(1,2)
unfolding supdate_glob_def supdate_glob_s_def
by (metis s.ext_inject s.update_convs(5))+
hence
"list_all2 (inst_typing 𝒮) insts' 𝒞s"
"list_all2 (cl_typing 𝒮) fs' tfs"
"list_all (tab_agree 𝒮) (concat clss')"
"list_all2 (λcls n. n ≤ length cls) clss' ns"
"list_all2 mem_agree bss' ms"
using set_global(2) s_S_defs
unfolding store_typing.simps
by auto
moreover
have "list_all2 glob_agree gs' tgs"
proof -
have gs_agree:"list_all2 glob_agree gs tgs"
using set_global(2) s_S_defs
unfolding store_typing.simps
by auto
have "length gs = length gs'"
using s_S_defs(1,2) set_global(1)
unfolding supdate_glob_def supdate_glob_s_def
by (metis length_list_update s.select_convs(5) s.update_convs(5))
moreover
obtain k where k_def:"(sglob_ind s i j) = k"
by blast
hence "⋀j'. ⟦j' ≠ k; j' < length gs⟧ ⟹ gs!j' = gs'!j'"
using s_S_defs(1,2) set_global(1)
unfolding supdate_glob_def supdate_glob_s_def
by auto
hence "⋀j'. ⟦j' ≠ k; j' < length gs⟧ ⟹ glob_agree (gs'!j') (tgs!j')"
using gs_agree
by (metis list_all2_conv_all_nth)
moreover
have "glob_agree (gs'!k) (tgs!k)"
proof -
obtain ts'' where ts''_def:"𝒞 ⊢ [C v] : (ts _> ts'')" "𝒞 ⊢ [Set_global j] : (ts'' _> ts')"
by (metis b_e_type_comp2_unlift set_global.prems(2))
have b_es:"ts'' = ts@[typeof v]"
"ts = ts'"
"global 𝒞 ! j = ⦇tg_mut = T_mut, tg_t = typeof v⦈"
"j < length (global 𝒞)"
using b_e_type_value[OF ts''_def(1)] b_e_type_set_global[OF ts''_def(2)]
by auto
hence "j < length (global ((s_inst 𝒮)!i))"
using set_global(4)
by fastforce
hence globs_agree:"k < length (s_globs 𝒮)"
"glob_agree (gs!k) (tgs!k)"
"(tgs!k) = (global 𝒞)!j"
using store_typing_imp_glob_agree[OF set_global(2,5)] b_es(4) s_S_defs(1,3) k_def set_global(4)
unfolding sglob_def
by auto
hence "g_mut (gs!k) = T_mut"
"typeof (g_val (gs!k)) = typeof v"
using b_es(3)
unfolding glob_agree_def
by auto
hence "g_mut (gs'!k) = T_mut"
"typeof (g_val (gs'!k)) = typeof v"
using set_global(1) k_def globs_agree(1) store_typing_imp_glob_length_eq[OF set_global(2)] s_S_defs(1,2)
unfolding supdate_glob_def supdate_glob_s_def
by auto
thus ?thesis
using globs_agree(3) b_es(3)
unfolding glob_agree_def
by fastforce
qed
ultimately
show ?thesis
using gs_agree
unfolding list_all2_conv_all_nth
by fastforce
qed
ultimately
show ?case
using store_typing.intros
by simp
next
case (store_Some t v s i j m k off mem' vs a)
show ?case
using store_preserved_mem[OF store_Some(5) _ _ store_Some(3)] store_size[OF store_Some(4)]
by fastforce
next
case (store_packed_Some t v s i j m k off tp mem' vs a)
thus ?case
using store_preserved_mem[OF store_packed_Some(5) _ _ store_packed_Some(3)] store_packed_size[OF store_packed_Some(4)]
by simp
next
case (grow_memory s i j n mem c mem' vs)
show ?case
using store_preserved_mem[OF grow_memory(5)_ _ grow_memory(2)] mem_grow_size[OF grow_memory(4)]
by simp
next
case (label s vs es i s' vs' es' k lholed les les')
obtain 𝒞' t1s t2s arb_label' arb_return' where es_def:"𝒞' = 𝒞⦇label := arb_label', return := arb_return'⦈" "𝒮∙𝒞' ⊢ es : (t1s _> t2s)"
using types_exist_lfilled_weak[OF label(2,6)]
by fastforce
thus ?case
using label(4)[OF label(5) es_def(2) _ label(8)] label(7)
by fastforce
next
case (local s vs es i s' vs' es' v0s n j)
obtain tls where t_local:"(𝒮∙((s_inst 𝒮)!i)⦇local := (local ((s_inst 𝒮)!i)) @ (map typeof vs), return := Some tls⦈ ⊢ es : ([] _> tls))"
"ts' = ts @ tls" "i < length (s_inst 𝒮)"
using e_type_local[OF local(4)]
by blast+
show ?case
using local(2)[OF local(3) t_local(1) _ t_local(3), of "(Some tls)" "label ((s_inst 𝒮)!i)" ]
by fastforce
qed (simp_all)
lemma store_preserved:
assumes "⦇s;vs;es⦈ ↝_i ⦇s';vs';es'⦈"
"store_typing s 𝒮"
"𝒮∙None ⊩_i vs;es : ts"
shows "store_typing s' 𝒮"
proof -
show ?thesis
using store_preserved1[OF assms(1,2), of _ "[]" "ts" None "label (s_inst 𝒮!i)"]
s_type_unfold[OF assms(3)]
by fastforce
qed
lemma typeof_unop_testop:
assumes "𝒮∙𝒞 ⊢ [$C v, $e] : (ts _> ts')"
"(e = (Unop_i t iop)) ∨ (e = (Unop_f t fop)) ∨ (e = (Testop t testop))"
shows "(typeof v) = t"
"e = (Unop_f t fop) ⟹ is_float_t t"
proof -
have "𝒞 ⊢ [C v, e] : (ts _> ts')"
using unlift_b_e assms(1)
by simp
then obtain ts'' where ts''_def:"𝒞 ⊢ [C v] : (ts _> ts'')" "𝒞 ⊢ [e] : (ts'' _> ts')"
using b_e_type_comp[where ?e = e and ?es = "[C v]"]
by fastforce
show "(typeof v) = t" "e = (Unop_f t fop) ⟹ is_float_t t"
using b_e_type_value[OF ts''_def(1)] assms(2) b_e_type_unop_testop[OF ts''_def(2)]
by simp_all
qed
lemma typeof_cvtop:
assumes "𝒮∙𝒞 ⊢ [$C v, $e] : (ts _> ts')"
"e = Cvtop t1 cvtop t sx"
shows "(typeof v) = t"
"cvtop = Convert ⟹ (t1 ≠ t) ∧ ((sx = None) = ((is_float_t t1 ∧ is_float_t t) ∨ (is_int_t t1 ∧ is_int_t t ∧ (t_length t1 < t_length t))))"
"cvtop = Reinterpret ⟹ (t1 ≠ t) ∧ t_length t1 = t_length t"
proof -
have "𝒞 ⊢ [C v, e] : (ts _> ts')"
using unlift_b_e assms(1)
by simp
then obtain ts'' where ts''_def:"𝒞 ⊢ [C v] : (ts _> ts'')" "𝒞 ⊢ [e] : (ts'' _> ts')"
using b_e_type_comp[where ?e = e and ?es = "[C v]"]
by fastforce
show "(typeof v) = t"
"cvtop = Convert ⟹ (t1 ≠ t) ∧ (sx = None) = ((is_float_t t1 ∧ is_float_t t) ∨ (is_int_t t1 ∧ is_int_t t ∧ (t_length t1 < t_length t)))"
"cvtop = Reinterpret ⟹ (t1 ≠ t) ∧ t_length t1 = t_length t"
using b_e_type_value[OF ts''_def(1)] b_e_type_cvtop[OF ts''_def(2) assms(2)]
by simp_all
qed
lemma types_preserved_unop_testop_cvtop:
assumes "⦇[$C v, $e]⦈ ↝ ⦇[$C v']⦈"
"𝒮∙𝒞 ⊢ [$C v, $e] : (ts _> ts')"
"(e = (Unop_i t iop)) ∨ (e = (Unop_f t fop)) ∨ (e = (Testop t testop)) ∨ (e = (Cvtop t2 cvtop t sx))"
shows "𝒮∙𝒞 ⊢ [$C v'] : (ts _> ts')"
proof -
have "𝒞 ⊢ [C v, e] : (ts _> ts')"
using unlift_b_e assms(2)
by simp
then obtain ts'' where ts''_def:"𝒞 ⊢ [C v] : (ts _> ts'')" "𝒞 ⊢ [e] : (ts'' _> ts')"
using b_e_type_comp[where ?e = e and ?es = "[C v]"]
by fastforce
have "ts@[arity_1_result e] = ts'" "(typeof v) = t"
using b_e_type_value[OF ts''_def(1)] assms(3) b_e_type_unop_testop(1)[OF ts''_def(2)]
b_e_type_cvtop(1)[OF ts''_def(2)]
by (metis butlast_snoc, metis last_snoc)
moreover
have "arity_1_result e = typeof (v')"
using assms(1,3)
apply (cases rule: reduce_simple.cases)
apply (simp_all add: arity_1_result_def wasm_deserialise_type t_cvt)
apply (auto simp add: typeof_def)
done
hence "𝒞 ⊢ [C v'] : ([] _> [arity_1_result e])"
using b_e_typing.const
by metis
ultimately
show "𝒮∙𝒞 ⊢ [$C v'] : (ts _> ts')"
using e_typing_s_typing.intros(1)
b_e_typing.weakening[of 𝒞 "[C v']" "[]" "[arity_1_result e]" ts]
by fastforce
qed
lemma typeof_binop_relop:
assumes "𝒮∙𝒞 ⊢ [$C v1, $C v2, $e] : (ts _> ts')"
"e = Binop_i t iop ∨ e = Binop_f t fop ∨ e = Relop_i t irop ∨ e = Relop_f t frop"
shows "typeof v1 = t"
"typeof v2 = t"
"e = Binop_f t fop ⟹ is_float_t t"
"e = Relop_f t frop ⟹ is_float_t t"
proof -
have "𝒞 ⊢ [C v1, C v2, e] : (ts _> ts')"
using unlift_b_e assms(1)
by simp
then obtain ts'' where ts''_def:"𝒞 ⊢ [C v1, C v2] : (ts _> ts'')" "𝒞 ⊢ [e] : (ts'' _> ts')"
using b_e_type_comp[where ?e = e and ?es = "[C v1, C v2]"]
by fastforce
then obtain ts_id where ts_id_def:"ts_id@[t,t] = ts''" "ts' = ts_id @ [arity_2_result e]"
"e = Binop_f t fop ⟹ is_float_t t"
"e = Relop_f t frop ⟹ is_float_t t"
using assms(2) b_e_type_binop_relop[of 𝒞 e ts'' ts' t]
by blast
thus "typeof v1 = t"
"typeof v2 = t"
"e = Binop_f t fop ⟹ is_float_t t"
"e = Relop_f t frop ⟹ is_float_t t"
using ts''_def b_e_type_comp[of 𝒞 "[C v1]" "C v2" ts ts''] b_e_type_value2
by fastforce+
qed
lemma types_preserved_binop_relop:
assumes "⦇[$C v1, $C v2, $e]⦈ ↝ ⦇[$C v']⦈"
"𝒮∙𝒞 ⊢ [$C v1, $C v2, $e] : (ts _> ts')"
"e = Binop_i t iop ∨ e = Binop_f t fop ∨ e = Relop_i t irop ∨ e = Relop_f t frop"
shows "𝒮∙𝒞 ⊢ [$C v'] : (ts _> ts')"
proof -
have "𝒞 ⊢ [C v1, C v2, e] : (ts _> ts')"
using unlift_b_e assms(2)
by simp
then obtain ts'' where ts''_def:"𝒞 ⊢ [C v1, C v2] : (ts _> ts'')" "𝒞 ⊢ [e] : (ts'' _> ts')"
using b_e_type_comp[where ?e = e and ?es = "[C v1, C v2]"]
by fastforce
then obtain ts_id where ts_id_def:"ts_id@[t,t] = ts''" "ts' = ts_id @ [arity_2_result e]"
using assms(3) b_e_type_binop_relop[of 𝒞 e ts'' ts' t]
by blast
hence "𝒞 ⊢ [C v1] : (ts _> ts_id@[t])"
using ts''_def b_e_type_comp[of 𝒞 "[C v1]" "C v2" ts ts''] b_e_type_value
by fastforce
hence "ts@[arity_2_result e] = ts'"
using b_e_type_value ts_id_def(2)
by fastforce
moreover
have "arity_2_result e = typeof (v')"
using assms(1,3)
by (cases rule: reduce_simple.cases) (auto simp add: arity_2_result_def typeof_def)
hence "𝒞 ⊢ [C v'] : ([] _> [arity_2_result e])"
using b_e_typing.const
by metis
ultimately show ?thesis
using e_typing_s_typing.intros(1)
b_e_typing.weakening[of 𝒞 "[C v']" "[]" "[arity_2_result e]" ts]
by fastforce
qed
lemma types_preserved_drop:
assumes "⦇[$C v, $e]⦈ ↝ ⦇[]⦈"
"𝒮∙𝒞 ⊢ [$C v, $e] : (ts _> ts')"
"(e = (Drop))"
shows "𝒮∙𝒞 ⊢ [] : (ts _> ts')"
proof -
have "𝒞 ⊢ [C v, e] : (ts _> ts')"
using unlift_b_e assms(2)
by simp
then obtain ts'' where ts''_def:"𝒞 ⊢ [C v] : (ts _> ts'')" "𝒞 ⊢ [e] : (ts'' _> ts')"
using b_e_type_comp[where ?e = e and ?es = "[C v]"]
by fastforce
hence "ts'' = ts@[typeof v]"
using b_e_type_value
by blast
hence "ts = ts'"
using ts''_def assms(3) b_e_type_drop
by blast
hence "𝒞 ⊢ [] : (ts _> ts')"
using b_e_type_empty
by simp
thus ?thesis
using e_typing_s_typing.intros(1)
by fastforce
qed
lemma types_preserved_select:
assumes "⦇[$C v1, $C v2, $C vn, $e]⦈ ↝ ⦇[$C v3]⦈"
"𝒮∙𝒞 ⊢ [$C v1, $C v2, $C vn, $e] : (ts _> ts')"
"(e = Select)"
shows "𝒮∙𝒞 ⊢ [$C v3] : (ts _> ts')"
proof -
have "𝒞 ⊢ [C v1, C v2, C vn, e] : (ts _> ts')"
using unlift_b_e assms(2)
by simp
then obtain t1s where t1s_def:"𝒞 ⊢ [C v1, C v2, C vn] : (ts _> t1s)" "𝒞 ⊢ [e] : (t1s _> ts')"
using b_e_type_comp[where ?e = e and ?es = "[C v1, C v2, C vn]"]
by fastforce
then obtain t2s t where t2s_def:"t1s = t2s @ [t, t, (T_i32)]" "ts' = t2s@[t]"
using b_e_type_select[of 𝒞 e t1s] assms
by fastforce
hence "𝒞 ⊢ [C v1, C v2] : (ts _> t2s@[t,t])"
using t1s_def t2s_def b_e_type_value_list[of 𝒞 "[C v1, C v2]" "vn" ts "t2s@[t,t]"]
by fastforce
hence v2_t_def:"𝒞 ⊢ [C v1] : (ts _> t2s@[t])" "typeof v2 = t"
using t1s_def t2s_def b_e_type_value_list[of 𝒞 "[C v1]" "v2" ts "t2s@[t]"]
by fastforce+
hence v1_t_def:"ts = t2s" "typeof v1 = t"
using b_e_type_value
by fastforce+
have "typeof v3 = t"
using assms(1) v2_t_def(2) v1_t_def(2)
by (cases rule: reduce_simple.cases, simp_all)
hence "𝒞 ⊢ [C v3] : (ts _> ts')"
using b_e_typing.const b_e_typing.weakening t2s_def(2) v1_t_def(1)
by fastforce
thus ?thesis
using e_typing_s_typing.intros(1)
by fastforce
qed
lemma types_preserved_block:
assumes "⦇vs @ [$Block (tn _> tm) es]⦈ ↝ ⦇[Label m [] (vs @ ($* es))]⦈"
"𝒮∙𝒞 ⊢ vs @ [$Block (tn _> tm) es] : (ts _> ts')"
"const_list vs"
"length vs = n"
"length tn = n"
"length tm = m"
shows "𝒮∙𝒞 ⊢ [Label m [] (vs @ ($* es))] : (ts _> ts')"
proof -
obtain 𝒞' where c_def:"𝒞' = 𝒞⦇label := [tm] @ label 𝒞⦈" by blast
obtain ts'' where ts''_def:"𝒮∙𝒞 ⊢ vs : (ts _> ts'')" "𝒮∙𝒞 ⊢ [$Block (tn _> tm) es] : (ts'' _> ts')"
using assms(2) e_type_comp[of 𝒮 𝒞 vs "$Block (tn _> tm) es" ts ts']
by fastforce
hence "𝒞 ⊢ [Block (tn _> tm) es] : (ts'' _> ts')"
using unlift_b_e
by auto
then obtain ts_c tfn tfm where ts_c_def:"(tn _> tm) = (tfn _> tfm)" "ts'' = ts_c@tfn" "ts' = ts_c@tfm" " (𝒞⦇label := [tfm] @ label 𝒞⦈ ⊢ es : (tn _> tm))"
using b_e_type_block[of 𝒞 "Block (tn _> tm) es" ts'' ts' "(tn _> tm)" es]
by fastforce
hence tfn_l:"length tfn = n"
using assms(5)
by simp
obtain tvs' where tvs'_def:"ts'' = ts@tvs'" "length tvs' = n" "𝒮∙𝒞' ⊢ vs : ([] _> tvs')"
using e_type_const_list assms(3,4) ts''_def(1)
by fastforce
hence "𝒮∙𝒞' ⊢ vs : ([] _> tn)" "𝒮∙𝒞' ⊢ $*es : (tn _> tm)"
using ts_c_def tvs'_def tfn_l ts''_def c_def e_typing_s_typing.intros(1)
by simp_all
hence "𝒮∙𝒞' ⊢ (vs @ ($* es)) : ([] _> tm)" using e_type_comp_conc
by simp
moreover
have "𝒮∙𝒞 ⊢ [] : (tm _> tm)"
using b_e_type_empty[of 𝒞 "[]" "[]"]
e_typing_s_typing.intros(1)[where ?b_es = "[]"]
e_typing_s_typing.intros(3)[of 𝒮 𝒞 "[]" "[]" "[]" "tm"]
by fastforce
ultimately
show ?thesis
using e_typing_s_typing.intros(7)[of 𝒮 𝒞 "[]" tm _ "vs @ ($* es)" m]
ts_c_def tvs'_def assms(5,6) e_typing_s_typing.intros(3) c_def
by fastforce
qed
lemma types_preserved_if:
assumes "⦇[$C ConstInt32 n, $If tf e1s e2s]⦈ ↝ ⦇[$Block tf es']⦈"
"𝒮∙𝒞 ⊢ [$C ConstInt32 n, $If tf e1s e2s] : (ts _> ts')"
shows "𝒮∙𝒞 ⊢ [$Block tf es'] : (ts _> ts')"
proof -
have "𝒞 ⊢ [C ConstInt32 n, If tf e1s e2s] : (ts _> ts')"
using unlift_b_e assms(2)
by fastforce
then obtain ts_i where ts_i_def:"𝒞 ⊢ [C ConstInt32 n] : (ts _> ts_i)" "𝒞 ⊢ [If tf e1s e2s] : (ts_i _> ts')"
using b_e_type_comp
by (metis append_Cons append_Nil)
then obtain ts'' tfn tfm where ts_def:"tf = (tfn _> tfm)"
"ts_i = ts''@tfn @ [T_i32]"
"ts' = ts''@tfm"
"(𝒞⦇label := [tfm] @ label 𝒞⦈ ⊢ e1s : tf)"
"(𝒞⦇label := [tfm] @ label 𝒞⦈ ⊢ e2s : tf)"
using b_e_type_if[of 𝒞 "If tf e1s e2s"]
by fastforce
have "ts_i = ts @ [(T_i32)]"
using ts_i_def(1) b_e_type_value
unfolding typeof_def
by fastforce
moreover
have "(𝒞⦇label := [tfm] @ label 𝒞⦈ ⊢ es' : (tfn _> tfm))"
using assms(1) ts_def(4,5) ts_def(1)
by (cases rule: reduce_simple.cases, simp_all)
hence "𝒞 ⊢ [Block tf es'] : (tfn _> tfm)"
using ts_def(1) b_e_typing.block[of tf tfn tfm 𝒞 es']
by simp
ultimately
show ?thesis
using ts_def(2,3) e_typing_s_typing.intros(1,3)
by fastforce
qed
lemma types_preserved_tee_local:
assumes "⦇[v, $Tee_local i]⦈ ↝ ⦇[v, v, $Set_local i]⦈"
"𝒮∙𝒞 ⊢ [v, $Tee_local i] : (ts _> ts')"
"is_const v"
shows "𝒮∙𝒞 ⊢ [v, v, $Set_local i] : (ts _> ts')"
proof -
obtain bv where bv_def:"v = $C bv"
using e_type_const_unwrap assms(3)
by fastforce
hence "𝒞 ⊢ [C bv, Tee_local i] : (ts _> ts')"
using unlift_b_e assms(2)
by fastforce
then obtain ts'' where ts''_def:"𝒞 ⊢ [C bv] : (ts _> ts'')" "𝒞 ⊢ [Tee_local i] : (ts'' _> ts')"
using b_e_type_comp[of _ "[C bv]" "Tee_local i"]
by fastforce
then obtain ts_c t where ts_c_def:"ts'' = ts_c@[t]" "ts' = ts_c@[t]" "(local 𝒞)!i = t" "i < length(local 𝒞)"
using b_e_type_tee_local[of 𝒞 "Tee_local i" ts'' ts' i]
by fastforce
hence t_bv:"t = typeof bv" "ts = ts_c"
using b_e_type_value ts''_def
by fastforce+
have "𝒞 ⊢ [Set_local i] : ([t,t] _> [t])"
using ts_c_def(3,4) b_e_typing.set_local[of i 𝒞 t]
b_e_typing.weakening[of 𝒞 "[Set_local i]" "[t]" "[]" "[t]"]
by fastforce
moreover
have "𝒞 ⊢ [C bv] : ([t] _> [t,t])"
using t_bv b_e_typing.const[of 𝒞 bv] b_e_typing.weakening[of 𝒞 "[C bv]" "[]" "[t]" "[t]"]
by fastforce
hence "𝒞 ⊢ [C bv, C bv] : ([] _> [t,t])"
using t_bv b_e_typing.const[of 𝒞 bv] b_e_typing.composition[of 𝒞 "[C bv]" "[]" "[t]"]
by fastforce
ultimately
have "𝒞 ⊢ [C bv, C bv, Set_local i] : (ts _> ts@[t])"
using b_e_typing.composition b_e_typing.weakening[of 𝒞 "[C bv, C bv, Set_local i]"]
by fastforce
thus ?thesis
using t_bv(2) ts_c_def(2) bv_def e_typing_s_typing.intros(1)
by fastforce
qed
lemma types_preserved_loop:
assumes "⦇vs @ [$Loop (t1s _> t2s) es]⦈ ↝ ⦇[Label n [$Loop (t1s _> t2s) es] (vs @ ($* es))]⦈"
"𝒮∙𝒞 ⊢ vs @ [$Loop (t1s _> t2s) es] : (ts _> ts')"
"const_list vs"
"length vs = n"
"length t1s = n"
"length t2s = m"
shows "𝒮∙𝒞 ⊢ [Label n [$Loop (t1s _> t2s) es] (vs @ ($* es))] : (ts _> ts')"
proof -
obtain ts'' where ts''_def:"𝒮∙𝒞 ⊢ vs : (ts _> ts'')" "𝒮∙𝒞 ⊢ [$Loop (t1s _> t2s) es] : (ts'' _> ts')"
using assms(2) e_type_comp
by fastforce
then have "𝒞 ⊢ [Loop (t1s _> t2s) es] : (ts'' _> ts')"
using unlift_b_e assms(2)
by fastforce
then obtain ts_c tfn tfm 𝒞' where t_loop:"(t1s _> t2s) = (tfn _> tfm)"
"(ts'' = ts_c@tfn)"
"(ts' = ts_c@tfm)"
"𝒞' = 𝒞⦇label := [t1s] @ label 𝒞⦈"
"(𝒞' ⊢ es : (tfn _> tfm))"
using b_e_type_loop[of 𝒞 "Loop (t1s _> t2s) es" ts'' ts']
by fastforce
obtain tvs where tvs_def:"ts'' = ts @ tvs" "length vs = length tvs" "𝒮∙𝒞' ⊢ vs : ([] _> tvs)"
using e_type_const_list assms(3) ts''_def(1)
by fastforce
then have tvs_eq:"tvs = t1s" "tfn = t1s"
using assms(4,5) t_loop(1,2)
by simp_all
have "𝒮∙𝒞 ⊢ [$Loop (t1s _> t2s) es] : (t1s _> t2s)"
using t_loop b_e_typing.loop e_typing_s_typing.intros(1)
by fastforce
moreover
have "𝒮∙𝒞' ⊢ $*es : (t1s _> t2s)"
using t_loop e_typing_s_typing.intros(1)
by fastforce
then have "𝒮∙𝒞' ⊢ vs@($*es) : ([] _> t2s)"
using tvs_eq tvs_def(3) e_type_comp_conc
by blast
ultimately
have "𝒮∙𝒞 ⊢ [Label n [$Loop (t1s _> t2s) es] (vs @ ($* es))] : ([] _> t2s)"
using e_typing_s_typing.intros(7)[of 𝒮 𝒞 "[$Loop (t1s _> t2s) es]" t1s t2s "vs @ ($* es)"]
t_loop(4) assms(5)
by fastforce
then show ?thesis
using t_loop e_typing_s_typing.intros(3) tvs_def(1) tvs_eq(1)
by fastforce
qed
lemma types_preserved_label_value:
assumes "⦇[Label n es0 vs]⦈ ↝ ⦇vs⦈"
"𝒮∙𝒞 ⊢ [Label n es0 vs] : (ts _> ts')"
"const_list vs"
shows "𝒮∙𝒞 ⊢ vs : (ts _> ts')"
proof -
obtain tls t2s where t2s_def:"(ts' = (ts@t2s))"
"(𝒮∙𝒞 ⊢ es0 : (tls _> t2s))"
"(𝒮∙𝒞⦇label := [tls] @ (label 𝒞)⦈ ⊢ vs : ([] _> t2s))"
using assms e_type_label
by fastforce
thus ?thesis
using e_type_const_list[of vs 𝒮 "𝒞⦇label := [tls] @ (label 𝒞)⦈" "[]" t2s]
assms(3) e_typing_s_typing.intros(3)
by fastforce
qed
lemma types_preserved_br_if:
assumes "⦇[$C ConstInt32 n, $Br_if i]⦈ ↝ ⦇e⦈"
"𝒮∙𝒞 ⊢ [$C ConstInt32 n, $Br_if i] : (ts _> ts')"
"e = [$Br i] ∨ e = []"
shows "𝒮∙𝒞 ⊢ e : (ts _> ts')"
proof -
have "𝒞 ⊢ [C ConstInt32 n, Br_if i] : (ts _> ts')"
using unlift_b_e assms(2)
by fastforce
then obtain ts'' where ts''_def:"𝒞 ⊢ [C ConstInt32 n] : (ts _> ts'')" "𝒞 ⊢ [Br_if i] : (ts'' _> ts')"
using b_e_type_comp[of _ "[C ConstInt32 n]" "Br_if i"]
by fastforce
then obtain ts_c ts_b where ts_bc_def:"i < length(label 𝒞)"
"ts'' = ts_c @ ts_b @ [T_i32]"
"ts' = ts_c @ ts_b"
"(label 𝒞)!i = ts_b"
using b_e_type_br_if[of 𝒞 "Br_if i" ts'' ts' i]
by fastforce
hence ts_def:"ts = ts_c @ ts_b"
using ts''_def(1) b_e_type_value
by fastforce
show ?thesis
using assms(3)
proof (rule disjE)
assume "e = [$Br i]"
thus ?thesis
using ts_def e_typing_s_typing.intros(1) b_e_typing.br ts_bc_def
by fastforce
next
assume "e = []"
thus ?thesis
using ts_def b_e_type_empty ts_bc_def(3)
e_typing_s_typing.intros(1)[of _ "[]" "(ts _> ts')"]
by fastforce
qed
qed
lemma types_preserved_br_table:
assumes "⦇[$C ConstInt32 c, $Br_table is i]⦈ ↝ ⦇[$Br i']⦈"
"𝒮∙𝒞 ⊢ [$C ConstInt32 c, $Br_table is i] : (ts _> ts')"
"(i' = (is ! nat_of_int c) ∧ length is > nat_of_int c) ∨ i' = i"
shows "𝒮∙𝒞 ⊢ [$Br i'] : (ts _> ts')"
proof -
have "𝒞 ⊢ [C ConstInt32 c, Br_table is i] : (ts _> ts')"
using unlift_b_e assms(2)
by fastforce
then obtain ts'' where ts''_def:"𝒞 ⊢ [C ConstInt32 c] : (ts _> ts'')" "𝒞 ⊢ [Br_table is i] : (ts'' _> ts')"
using b_e_type_comp[of _ "[C ConstInt32 c]" "Br_table is i"]
by fastforce
then obtain ts_l ts_c where ts_c_def:"list_all (λi. i < length(label 𝒞) ∧ (label 𝒞)!i = ts_l) (is@[i])"
"ts'' = ts_c @ ts_l@[T_i32]"
using b_e_type_br_table[of 𝒞 "Br_table is i" ts'' ts']
by fastforce
hence ts_def:"ts = ts_c @ ts_l"
using ts''_def(1) b_e_type_value
by fastforce
have "𝒞 ⊢ [Br i'] : (ts _> ts')"
using assms(3) ts_c_def(1,2) b_e_typing.br[of i' 𝒞 ts_l ts_c ts'] ts_def
unfolding list_all_length
by (fastforce simp add: less_Suc_eq nth_append)
thus ?thesis
using e_typing_s_typing.intros(1)
by fastforce
qed
lemma types_preserved_local_const:
assumes "⦇[Local n i vs es]⦈ ↝ ⦇es⦈"
"𝒮∙𝒞 ⊢ [Local n i vs es] : (ts _> ts')"
"const_list es"
shows "𝒮∙𝒞 ⊢ es: (ts _> ts')"
proof -
obtain tls where "(𝒮∙((s_inst 𝒮)!i)⦇local := (local ((s_inst 𝒮)!i)) @ (map typeof vs), return := Some tls⦈ ⊢ es : ([] _> tls))"
"ts' = ts @ tls"
using e_type_local[OF assms(2)]
by blast+
moreover
then have "𝒮∙𝒞 ⊢ es : ([] _> tls)"
using assms(3) e_type_const_list
by fastforce
ultimately
show ?thesis
using e_typing_s_typing.intros(3)
by fastforce
qed
lemma typing_map_typeof:
assumes "ves = $$* vs"
"𝒮∙𝒞 ⊢ ves : ([] _> tvs)"
shows "tvs = map typeof vs"
using assms
proof (induction ves arbitrary: vs tvs rule: List.rev_induct)
case Nil
hence "𝒞 ⊢ [] : ([] _> tvs)"
using unlift_b_e
by auto
thus ?case
using Nil
by auto
next
case (snoc a ves)
obtain vs' v' where vs'_def:"ves @ [a] = $$* (vs'@[v'])" "vs = vs'@[v']"
using snoc(2)
by (metis Nil_is_map_conv append_is_Nil_conv list.distinct(1) rev_exhaust)
obtain tvs' where tvs'_def:"𝒮∙𝒞 ⊢ ves: ([] _> tvs')" "𝒮∙𝒞 ⊢ [a] : (tvs' _> tvs)"
using snoc(3) e_type_comp
by fastforce
hence "tvs' = map typeof vs'"
using snoc(1) vs'_def
by fastforce
moreover
have "is_const a"
using vs'_def
unfolding is_const_def
by auto
then obtain t where t_def:"tvs = tvs' @ [t]" "𝒮∙𝒞 ⊢ [a] : ([] _> [t])"
using tvs'_def(2) e_type_const[of a 𝒮 𝒞 tvs' tvs]
by fastforce
have "a = $ C v'"
using vs'_def(1)
by auto
hence "t = typeof v'"
using t_def unlift_b_e[of 𝒮 𝒞 "[C v']" "([] _> [t])"] b_e_type_value[of 𝒞 "C v'" "[]" "[t]" v']
by fastforce
ultimately
show ?case
using vs'_def t_def
by simp
qed
lemma types_preserved_call_indirect_Some:
assumes "𝒮∙𝒞 ⊢ [$C ConstInt32 c, $Call_indirect j] : (ts _> ts')"
"stab s i' (nat_of_int c) = Some cl"
"stypes s i' j = tf"
"cl_type cl = tf"
"store_typing s 𝒮"
"i' < length (inst s)"
"𝒞 = (s_inst 𝒮 ! i') ⦇local := local (s_inst 𝒮 ! i') @ tvs, label := arb_labs, return := arb_return⦈"
shows "𝒮∙𝒞 ⊢ [Callcl cl] : (ts _> ts')"
proof -
obtain t1s t2s where tf_def:"tf = (t1s _> t2s)"
using tf.exhaust by blast
obtain ts'' where ts''_def:"𝒞 ⊢ [C ConstInt32 c] : (ts _> ts'')"
"𝒞 ⊢ [Call_indirect j] : (ts'' _> ts')"
using e_type_comp[of 𝒮 𝒞 "[$C ConstInt32 c]" "$Call_indirect j" ts ts']
assms(1)
unlift_b_e[of 𝒮 𝒞 "[C ConstInt32 c]"]
unlift_b_e[of 𝒮 𝒞 "[Call_indirect j]"]
by fastforce
hence "ts'' = ts@[(T_i32)]"
using b_e_type_value
unfolding typeof_def
by fastforce
moreover
have "i' < length (s_inst 𝒮)"
using assms(5,6) store_typing_imp_inst_length_eq
by fastforce
hence stypes_eq:"types_t (s_inst 𝒮 ! i') = types (inst s ! i')"
using store_typing_imp_inst_typing[OF assms(5)] store_typing_imp_inst_length_eq[OF assms(5)]
unfolding inst_typing.simps
by fastforce
obtain ts''a where ts''a_def:"j < length (types_t 𝒞)"
"ts'' = ts''a @ t1s @ [T_i32]"
"ts' = ts''a @ t2s"
"types_t 𝒞 ! j = (t1s _> t2s)"
using b_e_type_call_indirect[OF ts''_def(2), of j] tf_def assms(3,7) stypes_eq
unfolding stypes_def
by fastforce
moreover
obtain tf' where tf'_def:"cl_typing 𝒮 cl tf'"
using assms(2,5,6) stab_typed_some_imp_cl_typed
by blast
hence "cl_typing 𝒮 cl tf"
using assms(4)
unfolding cl_typing.simps cl_type_def
by auto
hence "𝒮∙𝒞 ⊢ [Callcl cl] : tf"
using e_typing_s_typing.intros(6) assms(6,7) ts''a_def(1)
by fastforce
ultimately
show "𝒮∙𝒞 ⊢ [Callcl cl] : (ts _> ts')"
using tf_def e_typing_s_typing.intros(3)
by auto
qed
lemma types_preserved_call_indirect_None:
assumes "𝒮∙𝒞 ⊢ [$C ConstInt32 c, $Call_indirect j] : (ts _> ts')"
shows "𝒮∙𝒞 ⊢ [Trap] : (ts _> ts')"
using e_typing_s_typing.intros(4)
by blast
lemma types_preserved_callcl_native:
assumes "𝒮∙𝒞 ⊢ ves @ [Callcl cl] : (ts _> ts')"
"cl = Func_native i (t1s _> t2s) tfs es"
"ves = $$* vs"
"length vs = n"
"length tfs = k"
"length t1s = n"
"length t2s = m"
"n_zeros tfs = zs"
"store_typing s 𝒮"
shows "𝒮∙𝒞 ⊢ [Local m i (vs @ zs) [$Block ([] _> t2s) es]] : (ts _> ts')"
proof -
obtain ts'' where ts''_def:"𝒮∙𝒞 ⊢ ves : (ts _> ts'')" "𝒮∙𝒞 ⊢ [Callcl cl] : (ts'' _> ts')"
using assms(1) e_type_comp
by fastforce
have ves_c:"const_list ves"
using is_const_list[OF assms(3)]
by simp
then obtain tvs where tvs_def:"ts'' = ts @ tvs"
"length t1s = length tvs"
"𝒮∙𝒞 ⊢ ves : ([] _> tvs)"
using ts''_def(1) e_type_const_list[of ves 𝒮 𝒞 ts ts''] assms
by fastforce
obtain ts_c 𝒞' where ts_c_def:"(ts'' = ts_c @ t1s)"
"(ts' = ts_c @ t2s)"
"i < length (s_inst 𝒮)"
"𝒞' = ((s_inst 𝒮)!i)"
"(𝒞'⦇local := (local 𝒞') @ t1s @ tfs, label := ([t2s] @ (label 𝒞')), return := Some t2s⦈ ⊢ es : ([] _> t2s))"
using e_type_callcl_native[OF ts''_def(2) assms(2)]
by fastforce
have "inst_typing 𝒮 (inst s ! i) (s_inst 𝒮 ! i)"
using store_typing_imp_inst_length_eq[OF assms(9)] store_typing_imp_inst_typing[OF assms(9)]
ts_c_def(3)
by simp
obtain 𝒞'' where c''_def:"𝒞'' = 𝒞'⦇local := (local 𝒞') @ t1s @ tfs, return := Some t2s⦈"
by blast
hence "𝒞''⦇label := ([t2s] @ (label 𝒞''))⦈ = 𝒞'⦇local := (local 𝒞') @ t1s @ tfs, label := ([t2s] @ (label 𝒞')), return := Some t2s⦈"
by fastforce
hence "𝒮∙𝒞'' ⊢ [$Block ([] _> t2s) es] : ([] _> t2s)"
using ts_c_def b_e_typing.block[of "([] _> t2s)" "[]" "t2s" _ es] e_typing_s_typing.intros(1)[of _ "[Block ([] _> t2s) es]"]
by fastforce
moreover
have t_eqs:"ts = ts_c" "t1s = tvs"
using tvs_def(1,2) ts_c_def(1)
by simp_all
have 1:"tfs = map typeof zs"
using n_zeros_typeof assms(8)
by auto
have "t1s = map typeof vs"
using typing_map_typeof assms(3) tvs_def t_eqs
by fastforce
hence "(t1s @ tfs) = map typeof (vs @ zs)"
using 1
by simp
ultimately
have "𝒮∙Some t2s ⊩_i (vs @ zs);([$Block ([] _> t2s) es]) : t2s"
using e_typing_s_typing.intros(8) ts_c_def c''_def
by fastforce
thus ?thesis
using e_typing_s_typing.intros(3,5) ts_c_def t_eqs(1) assms(2,7)
by fastforce
qed
lemma types_preserved_callcl_host_some:
assumes "𝒮∙𝒞 ⊢ ves @ [Callcl cl] : (ts _> ts')"
"cl = Func_host (t1s _> t2s) f"
"ves = $$* vcs"
"length vcs = n"
"length t1s = n"
"length t2s = m"
"host_apply s (t1s _> t2s) f vcs hs = Some (s', vcs')"
"store_typing s 𝒮"
shows "𝒮∙𝒞 ⊢ $$* vcs' : (ts _> ts')"
proof -
obtain ts'' where ts''_def:"𝒮∙𝒞 ⊢ ves : (ts _> ts'')" "𝒮∙𝒞 ⊢ [Callcl cl] : (ts'' _> ts')"
using assms(1) e_type_comp
by fastforce
have ves_c:"const_list ves"
using is_const_list[OF assms(3)]
by simp
then obtain tvs where tvs_def:"ts'' = ts @ tvs"
"length t1s = length tvs"
"𝒮∙𝒞 ⊢ ves : ([] _> tvs)"
using ts''_def(1) e_type_const_list[of ves 𝒮 𝒞 ts ts''] assms
by fastforce
hence "ts'' = ts @ t1s"
"ts' = ts @ t2s"
using e_type_callcl_host[OF ts''_def(2) assms(2)]
by auto
moreover
hence "list_all2 types_agree t1s vcs"
using e_typing_imp_list_types_agree[where ?ts' = "[]"] assms(3) tvs_def(1,3)
by fastforce
hence "𝒮∙𝒞 ⊢ $$* vcs' : ([] _> t2s)"
using list_types_agree_imp_e_typing host_apply_respect_type[OF _ assms(7)]
by fastforce
ultimately
show ?thesis
using e_typing_s_typing.intros(3)
by fastforce
qed
lemma types_imp_concat:
assumes "𝒮∙𝒞 ⊢ es @ [e] @ es' : (ts _> ts')"
"⋀tes tes'. ((𝒮∙𝒞 ⊢ [e] : (tes _> tes')) ⟹ (𝒮∙𝒞 ⊢ [e'] : (tes _> tes')))"
shows "𝒮∙𝒞 ⊢ es @ [e'] @ es' : (ts _> ts')"
proof -
obtain ts'' where "𝒮∙𝒞 ⊢ es : (ts _> ts'')"
"𝒮∙𝒞 ⊢ [e] @ es' : (ts'' _> ts')"
using e_type_comp_conc1[of _ _ es "[e] @ es'"] assms(1)
by fastforce
moreover
then obtain ts''' where "𝒮∙𝒞 ⊢ [e] : (ts'' _> ts''')" "𝒮∙𝒞 ⊢ es' : (ts''' _> ts')"
using e_type_comp_conc1[of _ _ "[e]" es' ts'' ts'] assms
by fastforce
ultimately
show ?thesis
using assms(2) e_type_comp_conc[of _ _ es ts ts'' "[e']" ts''']
e_type_comp_conc[of _ _ "es @ [e']" ts ts''']
by fastforce
qed
lemma type_const_return:
assumes "Lfilled i lholed (vs @ [$Return]) LI"
"(return 𝒞) = Some tcs"
"length tcs = length vs"
"𝒮∙𝒞 ⊢ LI : (ts _> ts')"
"const_list vs"
shows "𝒮∙𝒞' ⊢ vs : ([] _> tcs)"
using assms
proof (induction i arbitrary: ts ts' lholed 𝒞 LI 𝒞')
case 0
obtain vs' es' where "LI = (vs' @ (vs @ [$Return]) @ es')"
using Lfilled.simps[of 0 lholed "(vs @ [$Return])" LI] 0(1)
by fastforce
then obtain ts'' ts''' where "𝒮∙𝒞 ⊢ vs' : (ts _> ts'')"
"𝒮∙𝒞 ⊢ (vs @ [$Return]) : (ts'' _> ts''')"
"𝒮∙𝒞 ⊢ es' : (ts''' _> ts')"
using e_type_comp_conc2[of 𝒮 𝒞 vs' "(vs @ [$Return])" es'] 0(4)
by fastforce
then obtain ts_b where ts_b_def:"𝒮∙𝒞 ⊢ vs : (ts'' _> ts_b)" "𝒮∙𝒞 ⊢ [$Return] : (ts_b _> ts''')"
using e_type_comp_conc1
by fastforce
then obtain ts_c where ts_c_def:"ts_b = ts_c @ tcs" "(return 𝒞) = Some tcs"
using 0(2) b_e_type_return[of 𝒞] unlift_b_e[of 𝒮 𝒞 "[Return]" "ts_b _> ts'''"]
by fastforce
obtain tcs' where "ts_b = ts'' @ tcs'" "length vs = length tcs'" "𝒮∙𝒞' ⊢ vs : ([] _> tcs')"
using ts_b_def(1) e_type_const_list 0(5)
by fastforce
thus ?case
using 0(3) ts_c_def
by simp
next
case (Suc i)
obtain vs' n l les les' LK where es_def:"lholed = (LRec vs' n les l les')"
"Lfilled i l (vs @ [$Return]) LK"
"LI = (vs' @ [Label n les LK] @ les')"
using Lfilled.simps[of "(Suc i)" lholed "(vs @ [$Return])" LI] Suc(2)
by fastforce
then obtain ts'' ts''' where "𝒮∙𝒞 ⊢ [Label n les LK] : (ts'' _> ts''')"
using e_type_comp_conc2[of 𝒮 𝒞 vs' "[Label n les LK]" les'] Suc(5)
by fastforce
then obtain tls t2s where
"ts''' = ts'' @ t2s"
"length tls = n"
"𝒮∙𝒞 ⊢ les : (tls _> t2s)"
"𝒮∙𝒞⦇label := [tls] @ label 𝒞⦈ ⊢ LK : ([] _> t2s)"
"return (𝒞⦇label := [tls] @ label 𝒞⦈) = Some tcs"
using e_type_label[of 𝒮 𝒞 n les LK ts'' ts'''] Suc(3)
by fastforce
then show ?case
using Suc(1)[OF es_def(2) _ assms(3) _ assms(5)]
by fastforce
qed
lemma types_preserved_return:
assumes "⦇[Local n i vls LI]⦈ ↝ ⦇ves⦈"
"𝒮∙𝒞 ⊢ [Local n i vls LI] : (ts _> ts')"
"const_list ves"
"length ves = n"
"Lfilled j lholed (ves @ [$Return]) LI"
shows "𝒮∙𝒞 ⊢ ves : (ts _> ts')"
proof -
obtain tls 𝒞' where l_def:"i < length (s_inst 𝒮)"
"𝒞' = ((s_inst 𝒮)!i)⦇local := (local ((s_inst 𝒮)!i)) @ (map typeof vls), return := Some tls⦈"
"𝒮∙𝒞' ⊢ LI : ([] _> tls)"
"ts' = ts @ tls"
"length tls = n"
using e_type_local[OF assms(2)]
by blast
hence "𝒮∙𝒞 ⊢ ves : ([] _> tls)"
using type_const_return[OF assms(5) _ _ l_def(3)] assms(3-5)
by fastforce
thus ?thesis
using e_typing_s_typing.intros(3) l_def(4)
by fastforce
qed
lemma type_const_br:
assumes "Lfilled i lholed (vs @ [$Br (i+k)]) LI"
"length (label 𝒞) > k"
"(label 𝒞)!k = tcs"
"length tcs = length vs"
"𝒮∙𝒞 ⊢ LI : (ts _> ts')"
"const_list vs"
shows "𝒮∙𝒞' ⊢ vs : ([] _> tcs)"
using assms
proof (induction i arbitrary: k ts ts' lholed 𝒞 LI 𝒞')
case 0
obtain vs' es' where "LI = (vs' @ (vs @ [$Br (0+k)]) @ es')"
using Lfilled.simps[of 0 lholed "(vs @ [$Br (0 + k)])" LI] 0(1)
by fastforce
then obtain ts'' ts''' where "𝒮∙𝒞 ⊢ vs' : (ts _> ts'')"
"𝒮∙𝒞 ⊢ (vs @ [$Br (0+k)]) : (ts'' _> ts''')"
"𝒮∙𝒞 ⊢ es' : (ts''' _> ts')"
using e_type_comp_conc2[of 𝒮 𝒞 vs' "(vs @ [$Br (0+k)])" es'] 0(5)
by fastforce
then obtain ts_b where ts_b_def:"𝒮∙𝒞 ⊢ vs : (ts'' _> ts_b)" "𝒮∙𝒞 ⊢ [$Br (0+k)] : (ts_b _> ts''')"
using e_type_comp_conc1
by fastforce
then obtain ts_c where ts_c_def:"ts_b = ts_c @ tcs" "(label 𝒞)!k = tcs"
using 0(3) b_e_type_br[of 𝒞 "Br (0 + k)"] unlift_b_e[of 𝒮 𝒞 "[Br (0 + k)]" "ts_b _> ts'''"]
by fastforce
obtain tcs' where "ts_b = ts'' @ tcs'" "length vs = length tcs'" "𝒮∙𝒞' ⊢ vs : ([] _> tcs')"
using ts_b_def(1) e_type_const_list 0(6)
by fastforce
thus ?case
using 0(4) ts_c_def
by simp
next
case (Suc i k ts ts' lholed 𝒞 LI)
obtain vs' n l les les' LK where es_def:"lholed = (LRec vs' n les l les')"
"Lfilled i l (vs @ [$Br (i + (Suc k))]) LK"
"LI = (vs' @ [Label n les LK] @ les')"