| (* |
| * Copyright 2016, NICTA |
| * |
| * This software may be distributed and modified according to the terms of |
| * the GNU General Public License version 2. Note that NO WARRANTY is provided. |
| * See "LICENSE_GPLv2.txt" for details. |
| * |
| * @TAG(NICTA_GPL) |
| *) |
| |
| theory ArrayT |
| imports "../lib/TypBucket" |
| "../adt/BilbyT" |
| "../adt/WordArrayT" |
| "../lib/Loops" |
| begin |
| |
| consts \<alpha>a :: "'a Array \<Rightarrow> 'a Option\<^sub>T list" |
| consts make :: "'a Option\<^sub>T list \<Rightarrow> 'a Array" |
| (* I believe we could simplify this by converting the 'a Option\<^sub>T list to a |
| 'a list first using trimNone *) |
| fun trimNone :: "'a Option\<^sub>T list \<Rightarrow> 'a list" |
| where |
| "trimNone [] = []" | |
| "trimNone (Option.None ()#xs) = trimNone xs" | |
| "trimNone (Option.Some v#xs) = v#(trimNone xs)" |
| |
| definition |
| map_acc_obs_existing :: "('a \<times> 'acc \<times> 'obsv \<Rightarrow> ('a \<times> 'b, 'a \<times> 'acc) LoopResult) |
| \<Rightarrow> 'a Option\<^sub>T list |
| \<Rightarrow> 'acc \<Rightarrow> 'obsv \<Rightarrow> 'a Option\<^sub>T list \<times> |
| ('b, 'acc) LoopResult" |
| where |
| "map_acc_obs_existing fx xs xacc obs = |
| fold (\<lambda>val (ys,lr). |
| (case val of Option.None _ \<Rightarrow> |
| (ys@[Option.None ()], lr) |
| | Option.Some tval \<Rightarrow> |
| (case lr of Break xrbrk \<Rightarrow> (ys@[Option.Some tval],Break xrbrk) |
| | Iterate accx \<Rightarrow> |
| (case fx (tval,accx,obs) of (* This is wrong break returns a truncated array *) |
| Break (tval,xrbrk) \<Rightarrow> (ys@[Option.Some tval], Break xrbrk) |
| | Iterate (tval,accx) \<Rightarrow> (ys@[Option.Some tval], Iterate accx))))) |
| xs ([],Iterate xacc)" |
| |
| definition |
| arr_iterate_ex_no_break_body :: "(('a, 'acc, 'obsv) ElemAO \<Rightarrow> ('acc \<times> ('a, unit) R)) |
| \<Rightarrow> 'a Option\<^sub>T \<Rightarrow> 'a Option\<^sub>T list \<times> 'acc \<Rightarrow> 'obsv \<Rightarrow> 'a Option\<^sub>T list \<times> 'acc" |
| where |
| "arr_iterate_ex_no_break_body body \<equiv> |
| (\<lambda>el (ys,acc) obs. |
| (case el of |
| Option.None _ \<Rightarrow> (ys@[Option.None ()], acc) |
| | Option.Some tval \<Rightarrow> |
| (let (acc, r) = body(ElemAO.make tval acc obs) |
| in |
| (case r of |
| Success _ \<Rightarrow> (ys@[Option.None ()],acc) |
| | Error a \<Rightarrow> |
| (ys @[Option.Some a],acc)))))" |
| |
| definition |
| "array_iterate_ex_no_break body xs accx obs \<equiv> |
| arr_iteratei (length xs) xs (\<lambda>_. True) (arr_iterate_ex_no_break_body body) ([],accx) obs" |
| |
| |
| definition |
| mapAccumObsOpt :: "nat \<Rightarrow> nat \<Rightarrow> |
| (('a Option\<^sub>T, 'acc, 'obsv) OptElemAO |
| \<Rightarrow> ('a Option\<^sub>T \<times> 'd, 'a Option\<^sub>T \<times> 'acc) LoopResult) |
| \<Rightarrow> 'a Option\<^sub>T list \<Rightarrow> 'acc \<Rightarrow> 'obsv \<Rightarrow> ('a Option\<^sub>T list \<times> 'd, 'a Option\<^sub>T list \<times> 'acc) LoopResult" |
| where |
| "mapAccumObsOpt frm to fn xs vacc obs = |
| (case (fold (\<lambda>elem iter. |
| (case iter |
| of Iterate (ys, acc) \<Rightarrow> |
| (case fn (OptElemAO.make elem acc obs) |
| of Iterate (oelem, acc) \<Rightarrow> Iterate (ys @ [oelem], acc) |
| | Break (oelem, d) \<Rightarrow> Break (ys @ [oelem], d)) |
| | Break (ys, d) \<Rightarrow> Break (ys @ [elem], d))) |
| (slice frm to xs) (Iterate ([],vacc))) |
| of Iterate (ys, acc) \<Rightarrow> Iterate (take frm xs @ ys @ drop (max frm to) xs, acc) |
| | Break (ys, d) \<Rightarrow> Break (take frm xs @ ys @ drop (max frm to) xs, d))" |
| |
| axiomatization where |
| array_make: "\<alpha>a (ArrayT.make xs) = xs" |
| and |
| array_make': "ArrayT.make (\<alpha>a a) = a" |
| and |
| array_create_ret: |
| "\<lbrakk> \<And>ex'. (ex',Option.None ()) = malloc ex \<Longrightarrow> P (Error ex'); |
| \<And>ex' arr a. \<lbrakk> sz > 0 ; (ex', Option.Some arr) = malloc ex; |
| \<alpha>a a = replicate (unat sz) (Option.None ()) \<rbrakk> \<Longrightarrow> |
| P (Success (ex', a)) |
| \<rbrakk> \<Longrightarrow> |
| P (array_create (ex, sz))" |
| and |
| array_length_ret: |
| "unat (array_length arr) = length (\<alpha>a arr)" |
| and |
| array_nb_elem_ret: |
| "unat (array_nb_elem arrx) = \<alpha>_array_nb_elem (\<alpha>a arrx)" |
| and |
| array_modify_ret: |
| "\<And>P r arr'. \<lbrakk> unat index < length (\<alpha>a arr); |
| r = modifier (OptElemA.make ((\<alpha>a arr)!unat index) acc); |
| arr' = ArrayT.make ((\<alpha>a arr)[unat index:= OptElemA.oelem\<^sub>f r]); |
| (* \<alpha>a arr' = ((\<alpha>a arr)[unat index:= OptElemA.oelem\<^sub>f r]); *) |
| P (ArrA.make arr' (OptElemA.acc\<^sub>f r)) \<rbrakk> \<Longrightarrow> |
| P (array_modify (ArrayModifyP.make arr index modifier acc))" |
| |
| (* arr' = snd (select (arr,{v. \<alpha>a v = (\<alpha>a arr)[unat index:=Some (OptElemA.oelem\<^sub>f r)]})); *) |
| (* |
| axiomatization where array_iterate_existing_ret: |
| "\<And>P. P (map_acc_obs_existing body (\<alpha>a arrx) accx obs) |
| \<Longrightarrow> case array_iterate_existing (arrx, body, accx, obs) of |
| Break (arrx,rbrkx) \<Rightarrow> P ((\<alpha>a arrx), Break rbrkx) |
| | Iterate (arrx, accx) \<Rightarrow> P ((\<alpha>a arrx), Iterate accx)" |
| *) |
| and |
| array_iterate_enb_ret: |
| "\<And>P. let (arr, acc) = array_iterate_ex_no_break body (\<alpha>a arr) acc obs |
| in P (ArrA.make (ArrayT.make arr) acc) |
| \<Longrightarrow> P (array_filter (ArrayFoldP.make arr body acc obs))" |
| and array_map_ret: |
| "array_map am = |
| (case (mapAccumObsOpt |
| (unat (ArrayMapP.frm\<^sub>f am)) (unat (ArrayMapP.to\<^sub>f am)) (ArrayMapP.f\<^sub>f am) |
| (\<alpha>a (ArrayMapP.arr\<^sub>f am)) (ArrayMapP.acc\<^sub>f am) (ArrayMapP.obsv\<^sub>f am)) |
| of Iterate (ys, acc) \<Rightarrow> Iterate (ArrayT.make ys, acc) |
| | Break (ys, d) \<Rightarrow> Break(ArrayT.make ys, d))" |
| |
| lemma array_\<alpha>a_eq: |
| "(xs = ys) \<longleftrightarrow> \<alpha>a xs = \<alpha>a ys" |
| apply (rule iffI) |
| apply (erule arg_cong[where f=\<alpha>a]) |
| apply (drule_tac x="\<alpha>a xs" and y="\<alpha>a ys" in arg_cong[where f=ArrayT.make]) |
| apply (simp add: array_make') |
| done |
| |
| lemma array_make_eq: |
| "(xs = ys) \<longleftrightarrow> ArrayT.make xs = ArrayT.make ys" |
| apply (rule iffI) |
| apply (erule arg_cong[where f=ArrayT.make]) |
| apply (drule_tac x="ArrayT.make xs" and y="ArrayT.make ys" in arg_cong[where f=\<alpha>a]) |
| apply (simp add: array_make) |
| done |
| |
| end |
| |