From f36cbcc496fad407560d734cf960ea3afbcf8682 Mon Sep 17 00:00:00 2001 From: "Achim D. Brucker" Date: Sat, 19 Dec 2020 15:09:58 +0000 Subject: [PATCH] Initial import from AFP. --- Shadow_DOM/ROOT | 14 + Shadow_DOM/Shadow_DOM.thy | 10508 ++++++++++++++++ Shadow_DOM/Shadow_DOM_Tests.thy | 42 + Shadow_DOM/classes/ShadowRootClass.thy | 460 + Shadow_DOM/document/root.bib | 518 + Shadow_DOM/document/root.tex | 216 + Shadow_DOM/monads/ShadowRootMonad.thy | 711 ++ Shadow_DOM/tests/Document-adoptNode.html | 36 + Shadow_DOM/tests/Document-getElementById.html | 251 + Shadow_DOM/tests/Node-insertBefore.html | 288 + Shadow_DOM/tests/Node-removeChild.html | 66 + Shadow_DOM/tests/Shadow_DOM_BaseTest.thy | 373 + .../tests/Shadow_DOM_Document_adoptNode.thy | 114 + .../Shadow_DOM_Document_getElementById.thy | 278 + .../tests/Shadow_DOM_Node_insertBefore.thy | 129 + .../tests/Shadow_DOM_Node_removeChild.thy | 160 + Shadow_DOM/tests/my_get_owner_document.html | 28 + Shadow_DOM/tests/my_get_owner_document.thy | 81 + Shadow_DOM/tests/slots-fallback.html | 253 + Shadow_DOM/tests/slots.html | 526 + Shadow_DOM/tests/slots.thy | 947 ++ Shadow_DOM/tests/slots_fallback.thy | 507 + 22 files changed, 16506 insertions(+) create mode 100644 Shadow_DOM/ROOT create mode 100644 Shadow_DOM/Shadow_DOM.thy create mode 100644 Shadow_DOM/Shadow_DOM_Tests.thy create mode 100644 Shadow_DOM/classes/ShadowRootClass.thy create mode 100644 Shadow_DOM/document/root.bib create mode 100644 Shadow_DOM/document/root.tex create mode 100644 Shadow_DOM/monads/ShadowRootMonad.thy create mode 100644 Shadow_DOM/tests/Document-adoptNode.html create mode 100644 Shadow_DOM/tests/Document-getElementById.html create mode 100644 Shadow_DOM/tests/Node-insertBefore.html create mode 100644 Shadow_DOM/tests/Node-removeChild.html create mode 100644 Shadow_DOM/tests/Shadow_DOM_BaseTest.thy create mode 100644 Shadow_DOM/tests/Shadow_DOM_Document_adoptNode.thy create mode 100644 Shadow_DOM/tests/Shadow_DOM_Document_getElementById.thy create mode 100644 Shadow_DOM/tests/Shadow_DOM_Node_insertBefore.thy create mode 100644 Shadow_DOM/tests/Shadow_DOM_Node_removeChild.thy create mode 100644 Shadow_DOM/tests/my_get_owner_document.html create mode 100644 Shadow_DOM/tests/my_get_owner_document.thy create mode 100644 Shadow_DOM/tests/slots-fallback.html create mode 100644 Shadow_DOM/tests/slots.html create mode 100644 Shadow_DOM/tests/slots.thy create mode 100644 Shadow_DOM/tests/slots_fallback.thy diff --git a/Shadow_DOM/ROOT b/Shadow_DOM/ROOT new file mode 100644 index 0000000..09984a5 --- /dev/null +++ b/Shadow_DOM/ROOT @@ -0,0 +1,14 @@ +chapter AFP + +session "Shadow_DOM" (AFP) = "Core_DOM" + + options [timeout = 3600] + directories + classes + monads + tests + theories + Shadow_DOM + Shadow_DOM_Tests + document_files + "root.tex" + "root.bib" diff --git a/Shadow_DOM/Shadow_DOM.thy b/Shadow_DOM/Shadow_DOM.thy new file mode 100644 index 0000000..d9a2e26 --- /dev/null +++ b/Shadow_DOM/Shadow_DOM.thy @@ -0,0 +1,10508 @@ +(*********************************************************************************** + * Copyright (c) 2016-2020 The University of Sheffield, UK + * 2019-2020 University of Exeter, UK + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-2-Clause + ***********************************************************************************) + +section\The Shadow DOM\ +theory Shadow_DOM + imports + "monads/ShadowRootMonad" + Core_DOM.Core_DOM +begin + +abbreviation "safe_shadow_root_element_types \ {''article'', ''aside'', ''blockquote'', ''body'', + ''div'', ''footer'', ''h1'', ''h2'', ''h3'', ''h4'', ''h5'', ''h6'', ''header'', ''main'', + ''nav'', ''p'', ''section'', ''span''}" + + +subsection \Function Definitions\ + + +subsubsection \get\_child\_nodes\ + +locale l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs = + CD: l_get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs +begin +definition get_child_nodes\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r :: "(_) shadow_root_ptr \ unit + \ (_, (_) node_ptr list) dom_prog" where + "get_child_nodes\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r shadow_root_ptr _ = get_M shadow_root_ptr RShadowRoot.child_nodes" + +definition a_get_child_nodes_tups :: "(((_) object_ptr \ bool) \ ((_) object_ptr \ unit + \ (_, (_) node_ptr list) dom_prog)) list" where + "a_get_child_nodes_tups \ [(is_shadow_root_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r, get_child_nodes\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r \ the \ cast)]" + +definition a_get_child_nodes :: "(_) object_ptr \ (_, (_) node_ptr list) dom_prog" where + "a_get_child_nodes ptr = invoke (CD.a_get_child_nodes_tups @ a_get_child_nodes_tups) ptr ()" + +definition a_get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" where + "a_get_child_nodes_locs ptr \ + (if is_shadow_root_ptr_kind ptr + then {preserved (get_M (the (cast ptr)) RShadowRoot.child_nodes)} else {}) \ + CD.a_get_child_nodes_locs ptr" + +definition first_child :: "(_) object_ptr \ (_, (_) node_ptr option) dom_prog" + where + "first_child ptr = do { + children \ a_get_child_nodes ptr; + return (case children of [] \ None | child#_ \ Some child)}" +end + +global_interpretation l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs defines + get_child_nodes = l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_get_child_nodes and + get_child_nodes_locs = l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_get_child_nodes_locs + . + +locale l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_type_wf type_wf + + l_known_ptr known_ptr + + l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + + l_get_child_nodes_defs get_child_nodes get_child_nodes_locs + + CD: l_get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + get_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + for type_wf :: "(_) heap \ bool" + and known_ptr :: "(_) object_ptr \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ bool" + and get_child_nodes :: "(_) object_ptr \ (_, (_) node_ptr list) dom_prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ (_, (_) node_ptr list) dom_prog" + and get_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + + assumes known_ptr_impl: "known_ptr = ShadowRootClass.known_ptr" + assumes type_wf_impl: "type_wf = ShadowRootClass.type_wf" + assumes get_child_nodes_impl: "get_child_nodes = a_get_child_nodes" + assumes get_child_nodes_locs_impl: "get_child_nodes_locs = a_get_child_nodes_locs" +begin +lemmas get_child_nodes_def = get_child_nodes_impl[unfolded a_get_child_nodes_def get_child_nodes_def] +lemmas get_child_nodes_locs_def = get_child_nodes_locs_impl[unfolded a_get_child_nodes_locs_def + get_child_nodes_locs_def, folded CD.get_child_nodes_locs_impl] + +lemma get_child_nodes_ok: + assumes "known_ptr ptr" + assumes "type_wf h" + assumes "ptr |\| object_ptr_kinds h" + shows "h \ ok (get_child_nodes ptr)" + using assms[unfolded known_ptr_impl type_wf_impl] + apply(auto simp add: get_child_nodes_def)[1] + apply(split CD.get_child_nodes_splits, rule conjI)+ + using ShadowRootClass.type_wf\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t CD.get_child_nodes_ok CD.known_ptr_impl CD.type_wf_impl + apply blast + apply(auto simp add: CD.known_ptr_impl a_get_child_nodes_tups_def get_child_nodes\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def + get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ok + dest!: known_ptr_new_shadow_root_ptr intro!: bind_is_OK_I2)[1] + by (metis is_shadow_root_ptr_kind_none l_get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_lemmas.get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ok + l_get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_lemmas_axioms option.case_eq_if shadow_root_ptr_casts_commute3 + shadow_root_ptr_kinds_commutes) + +lemma get_child_nodes_ptr_in_heap: + assumes "h \ get_child_nodes ptr \\<^sub>r children" + shows "ptr |\| object_ptr_kinds h" + using assms + by(auto simp add: get_child_nodes_def invoke_ptr_in_heap dest: is_OK_returns_result_I) + +lemma get_child_nodes_pure [simp]: + "pure (get_child_nodes ptr) h" + unfolding get_child_nodes_def a_get_child_nodes_tups_def +proof(split CD.get_child_nodes_splits, rule conjI; clarify) + assume "known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M ptr" + then show "pure (get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M ptr) h" + by simp +next + assume "\ known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M ptr" + then show "pure (invoke [(is_shadow_root_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r, + get_child_nodes\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r \ the \ cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r)] + ptr ()) h" + by(auto simp add: get_child_nodes\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def intro: bind_pure_I split: invoke_splits) +qed + +lemma get_child_nodes_reads: "reads (get_child_nodes_locs ptr) (get_child_nodes ptr) h h'" + apply (simp add: get_child_nodes_def a_get_child_nodes_tups_def get_child_nodes_locs_def + CD.get_child_nodes_locs_def) + apply(split CD.get_child_nodes_splits, rule conjI)+ + apply(auto intro!: reads_subset[OF CD.get_child_nodes_reads[unfolded CD.get_child_nodes_locs_def]] + split: if_splits)[1] + apply(split invoke_splits, rule conjI)+ + apply(auto)[1] + apply(auto simp add: get_child_nodes\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def + intro: reads_subset[OF reads_singleton] reads_subset[OF check_in_heap_reads] + intro!: reads_bind_pure reads_subset[OF return_reads] split: option.splits)[1] + done +end + +interpretation i_get_child_nodes?: l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr DocumentClass.type_wf + DocumentClass.known_ptr get_child_nodes get_child_nodes_locs Core_DOM_Functions.get_child_nodes + Core_DOM_Functions.get_child_nodes_locs + by(simp add: l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def instances) +declare l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma get_child_nodes_is_l_get_child_nodes [instances]: "l_get_child_nodes type_wf known_ptr + get_child_nodes get_child_nodes_locs" + apply(auto simp add: l_get_child_nodes_def instances)[1] + using get_child_nodes_reads get_child_nodes_ok get_child_nodes_ptr_in_heap get_child_nodes_pure + by blast+ + +paragraph \new\_document\ + +locale l_new_document_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + CD: l_new_document_get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + get_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes + get_child_nodes_locs get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + for type_wf :: "(_) heap \ bool" + and known_ptr :: "(_) object_ptr \ bool" + and get_child_nodes :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ bool" + and get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +lemma get_child_nodes_new_document: + "ptr' \ cast new_document_ptr \ h \ new_document \\<^sub>r new_document_ptr + \ h \ new_document \\<^sub>h h' \ r \ get_child_nodes_locs ptr' \ r h h'" + apply(auto simp add: get_child_nodes_locs_def)[1] + using CD.get_child_nodes_new_document + apply (metis document_ptr_casts_commute3 empty_iff is_document_ptr_kind_none + new_document_get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t option.case_eq_if shadow_root_ptr_casts_commute3 + singletonD) + by (simp add: CD.get_child_nodes_new_document) + +lemma new_document_no_child_nodes: + "h \ new_document \\<^sub>r new_document_ptr \ h \ new_document \\<^sub>h h' + \ h' \ get_child_nodes (cast new_document_ptr) \\<^sub>r []" + apply(auto simp add: get_child_nodes_def)[1] + apply(split CD.get_child_nodes_splits, rule conjI)+ + using CD.new_document_no_child_nodes apply auto[1] + by(auto simp add: DocumentClass.a_known_ptr_def CD.known_ptr_impl known_ptr_def + dest!: new_document_is_document_ptr) +end +interpretation i_new_document_get_child_nodes?: + l_new_document_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr get_child_nodes get_child_nodes_locs + DocumentClass.type_wf DocumentClass.known_ptr Core_DOM_Functions.get_child_nodes + Core_DOM_Functions.get_child_nodes_locs + by(unfold_locales) +declare l_new_document_get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma new_document_get_child_nodes_is_l_new_document_get_child_nodes [instances]: + "l_new_document_get_child_nodes type_wf known_ptr get_child_nodes get_child_nodes_locs" + using new_document_is_l_new_document get_child_nodes_is_l_get_child_nodes + apply(simp add: l_new_document_get_child_nodes_def l_new_document_get_child_nodes_axioms_def) + using get_child_nodes_new_document new_document_no_child_nodes + by fast + +paragraph \new\_shadow\_root\ + +locale l_new_shadow_root_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes + get_child_nodes_locs get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + for type_wf :: "(_) heap \ bool" + and known_ptr :: "(_) object_ptr \ bool" + and get_child_nodes :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ bool" + and get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +lemma get_child_nodes_new_shadow_root: + "ptr' \ cast new_shadow_root_ptr \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr + \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' \ r \ get_child_nodes_locs ptr' \ r h h'" + apply(auto simp add: get_child_nodes_locs_def)[1] + apply (metis document_ptr_casts_commute3 insert_absorb insert_not_empty is_document_ptr_kind_none + new_shadow_root_get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t option.case_eq_if shadow_root_ptr_casts_commute3 singletonD) + apply(auto simp add: CD.get_child_nodes_locs_def)[1] + using new_shadow_root_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t apply blast + apply (smt insertCI new_shadow_root_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t singleton_iff) + apply (metis document_ptr_casts_commute3 empty_iff new_shadow_root_get_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t singletonD) + done + +lemma new_shadow_root_no_child_nodes: + "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' + \ h' \ get_child_nodes (cast new_shadow_root_ptr) \\<^sub>r []" + apply(auto simp add: get_child_nodes_def )[1] + apply(split CD.get_child_nodes_splits, rule conjI)+ + apply(auto simp add: CD.get_child_nodes_def CD.a_get_child_nodes_tups_def)[1] + apply(split invoke_splits, rule conjI)+ + using NodeClass.a_known_ptr_def known_ptr_not_character_data_ptr known_ptr_not_document_ptr + known_ptr_not_element_ptr local.CD.known_ptr_impl apply blast + apply(auto simp add: is_document_ptr_def split: option.splits document_ptr.splits)[1] + apply(auto simp add: is_character_data_ptr_def split: option.splits document_ptr.splits)[1] + apply(auto simp add: is_element_ptr_def split: option.splits document_ptr.splits)[1] + apply(auto simp add: a_get_child_nodes_tups_def)[1] + apply(split invoke_splits, rule conjI)+ + apply(auto simp add: is_shadow_root_ptr_def split: shadow_root_ptr.splits + dest!: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_is_shadow_root_ptr)[1] + apply(auto intro!: bind_pure_returns_result_I)[1] + apply(drule(1) new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_ptr_in_heap) + apply(auto simp add: shadow_root_ptr_kinds_def document_ptr_kinds_def)[1] + apply (metis check_in_heap_ptr_in_heap is_OK_returns_result_E old.unit.exhaust) + using new_shadow_root_children + by (simp add: new_shadow_root_children get_child_nodes\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def) +end +interpretation i_new_shadow_root_get_child_nodes?: + l_new_shadow_root_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr get_child_nodes get_child_nodes_locs + DocumentClass.type_wf DocumentClass.known_ptr Core_DOM_Functions.get_child_nodes + Core_DOM_Functions.get_child_nodes_locs + by(unfold_locales) +declare l_new_shadow_root_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def[instances] + +locale l_new_shadow_root_get_child_nodes = l_get_child_nodes + + assumes get_child_nodes_new_shadow_root: + "ptr' \ cast new_shadow_root_ptr \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr + \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' \ r \ get_child_nodes_locs ptr' \ r h h'" + assumes new_shadow_root_no_child_nodes: + "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' + \ h' \ get_child_nodes (cast new_shadow_root_ptr) \\<^sub>r []" + +lemma new_shadow_root_get_child_nodes_is_l_new_shadow_root_get_child_nodes [instances]: + "l_new_shadow_root_get_child_nodes type_wf known_ptr get_child_nodes get_child_nodes_locs" + apply(simp add: l_new_shadow_root_get_child_nodes_def l_new_shadow_root_get_child_nodes_axioms_def + instances) + using get_child_nodes_new_shadow_root new_shadow_root_no_child_nodes + by fast + +paragraph \new\_element\ + +locale l_new_element_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_new_element_get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + get_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma get_child_nodes_new_element: + "ptr' \ cast new_element_ptr \ h \ new_element \\<^sub>r new_element_ptr \ h \ new_element \\<^sub>h h' + \ r \ get_child_nodes_locs ptr' \ r h h'" + by (auto simp add: get_child_nodes_locs_def CD.get_child_nodes_locs_def new_element_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t + new_element_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t new_element_get_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t new_element_get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t + split: prod.splits if_splits option.splits + elim!: bind_returns_result_E bind_returns_heap_E + intro: is_element_ptr_kind_obtains) + +lemma new_element_no_child_nodes: + "h \ new_element \\<^sub>r new_element_ptr \ h \ new_element \\<^sub>h h' + \ h' \ get_child_nodes (cast new_element_ptr) \\<^sub>r []" + apply(auto simp add: get_child_nodes_def a_get_child_nodes_tups_def + split: prod.splits elim!: bind_returns_result_E bind_returns_heap_E)[1] + apply(split CD.get_child_nodes_splits, rule conjI)+ + using local.new_element_no_child_nodes apply auto[1] + apply(auto simp add: invoke_def)[1] + apply(auto simp add: new_element_ptr_in_heap get_child_nodes\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def check_in_heap_def + new_element_child_nodes intro!: bind_pure_returns_result_I + intro: new_element_is_element_ptr elim!: new_element_ptr_in_heap)[1] +proof - + assume " h \ new_element \\<^sub>r new_element_ptr" + assume "h \ new_element \\<^sub>h h'" + assume "\ known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr)" + moreover + have "known_ptr (cast new_element_ptr)" + using new_element_is_element_ptr \h \ new_element \\<^sub>r new_element_ptr\ + by(auto simp add: known_ptr_impl ShadowRootClass.a_known_ptr_def DocumentClass.a_known_ptr_def + CharacterDataClass.a_known_ptr_def ElementClass.a_known_ptr_def) + ultimately show "False" + by(simp add: known_ptr_impl CD.known_ptr_impl ShadowRootClass.a_known_ptr_def + is_document_ptr_kind_none) +qed +end + +interpretation i_new_element_get_child_nodes?: + l_new_element_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr DocumentClass.type_wf + DocumentClass.known_ptr get_child_nodes get_child_nodes_locs Core_DOM_Functions.get_child_nodes + Core_DOM_Functions.get_child_nodes_locs + by(unfold_locales) +declare l_new_element_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma new_element_get_child_nodes_is_l_new_element_get_child_nodes [instances]: + "l_new_element_get_child_nodes type_wf known_ptr get_child_nodes get_child_nodes_locs" + using new_element_is_l_new_element get_child_nodes_is_l_get_child_nodes + apply(auto simp add: l_new_element_get_child_nodes_def l_new_element_get_child_nodes_axioms_def)[1] + using get_child_nodes_new_element new_element_no_child_nodes + by fast+ + + + + +subsubsection \delete\_shadow\_root\ + +locale l_delete_shadow_root_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma get_child_nodes_delete_shadow_root: + "ptr' \ cast shadow_root_ptr \ h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h' \ + r \ get_child_nodes_locs ptr' \ r h h'" + by(auto simp add: get_child_nodes_locs_def CD.get_child_nodes_locs_def + delete_shadow_root_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t delete_shadow_root_get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t + delete_shadow_root_get_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t delete_shadow_root_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t + split: if_splits option.splits + intro: is_shadow_root_ptr_kind_obtains) +end + +locale l_delete_shadow_root_get_child_nodes = l_get_child_nodes_defs + + assumes get_child_nodes_delete_shadow_root: + "ptr' \ cast shadow_root_ptr \ h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h' \ + r \ get_child_nodes_locs ptr' \ r h h'" + +interpretation l_delete_shadow_root_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr DocumentClass.type_wf + DocumentClass.known_ptr get_child_nodes get_child_nodes_locs Core_DOM_Functions.get_child_nodes + Core_DOM_Functions.get_child_nodes_locs + by(auto simp add: l_delete_shadow_root_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) + +lemma l_delete_shadow_root_get_child_nodes_get_child_nodes_locs [instances]: "l_delete_shadow_root_get_child_nodes get_child_nodes_locs" + apply(auto simp add: l_delete_shadow_root_get_child_nodes_def)[1] + using get_child_nodes_delete_shadow_root apply fast + done + + + +subsubsection \set\_child\_nodes\ + +locale l_set_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs = + CD: l_set_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs +begin +definition set_child_nodes\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r :: "(_) shadow_root_ptr \ (_) node_ptr list + \ (_, unit) dom_prog" where + "set_child_nodes\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r shadow_root_ptr = put_M shadow_root_ptr RShadowRoot.child_nodes_update" + +definition a_set_child_nodes_tups :: "(((_) object_ptr \ bool) \ ((_) object_ptr \ (_) node_ptr list + \ (_, unit) dom_prog)) list" where + "a_set_child_nodes_tups \ [(is_shadow_root_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r, set_child_nodes\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r \ the \ cast)]" + +definition a_set_child_nodes :: "(_) object_ptr \ (_) node_ptr list \ (_, unit) dom_prog" where + "a_set_child_nodes ptr children = invoke (CD.a_set_child_nodes_tups @ a_set_child_nodes_tups) + ptr children" + +definition a_set_child_nodes_locs :: "(_) object_ptr \ (_, unit) dom_prog set" + where + "a_set_child_nodes_locs ptr \ + (if is_shadow_root_ptr_kind ptr + then all_args (put_M (the (cast ptr)) RShadowRoot.child_nodes_update) + else {}) \ CD.a_set_child_nodes_locs ptr" +end + +global_interpretation l_set_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs defines + set_child_nodes = l_set_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_set_child_nodes and + set_child_nodes_locs = l_set_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_set_child_nodes_locs + . + +locale l_set_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_type_wf type_wf + + l_known_ptr known_ptr + + l_set_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + + l_set_child_nodes_defs set_child_nodes set_child_nodes_locs + + CD: l_set_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M set_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + set_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + for type_wf :: "(_) heap \ bool" + and known_ptr :: "(_) object_ptr \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ bool" + and set_child_nodes :: "(_) object_ptr \ (_) node_ptr list \ (_, unit) dom_prog" + and set_child_nodes_locs :: "(_) object_ptr \ (_, unit) dom_prog set" + and set_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ (_) node_ptr list \ (_, unit) dom_prog" + and set_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ (_, unit) dom_prog set" + + assumes known_ptr_impl: "known_ptr = ShadowRootClass.known_ptr" + assumes type_wf_impl: "type_wf = ShadowRootClass.type_wf" + assumes set_child_nodes_impl: "set_child_nodes = a_set_child_nodes" + assumes set_child_nodes_locs_impl: "set_child_nodes_locs = a_set_child_nodes_locs" +begin +lemmas set_child_nodes_def = set_child_nodes_impl[unfolded a_set_child_nodes_def set_child_nodes_def] +lemmas set_child_nodes_locs_def = set_child_nodes_locs_impl[unfolded a_set_child_nodes_locs_def + set_child_nodes_locs_def, folded CD.set_child_nodes_locs_impl] + +lemma set_child_nodes_writes: "writes (set_child_nodes_locs ptr) (set_child_nodes ptr children) h h'" + apply (simp add: set_child_nodes_def a_set_child_nodes_tups_def set_child_nodes_locs_def) + apply(split CD.set_child_nodes_splits, rule conjI)+ + apply (simp add: CD.set_child_nodes_writes writes_union_right_I) + apply(split invoke_splits, rule conjI)+ + apply(auto simp add: a_set_child_nodes_def)[1] + apply(auto simp add: set_child_nodes\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def + intro!: writes_bind_pure + intro: writes_union_right_I writes_union_left_I + split: list.splits)[1] + by (simp add: is_shadow_root_ptr_kind_none) + +lemma set_child_nodes_pointers_preserved: + assumes "w \ set_child_nodes_locs object_ptr" + assumes "h \ w \\<^sub>h h'" + shows "object_ptr_kinds h = object_ptr_kinds h'" + using assms(1) object_ptr_kinds_preserved[OF writes_singleton2 assms(2)] + by(auto simp add: all_args_def set_child_nodes_locs_def CD.set_child_nodes_locs_def + split: if_splits) + +lemma set_child_nodes_types_preserved: + assumes "w \ set_child_nodes_locs object_ptr" + assumes "h \ w \\<^sub>h h'" + shows "type_wf h = type_wf h'" + using assms(1) type_wf_preserved[OF writes_singleton2 assms(2)] + by(auto simp add: all_args_def type_wf_impl a_set_child_nodes_tups_def set_child_nodes_locs_def + CD.set_child_nodes_locs_def + split: if_splits option.splits) +end + +interpretation + i_set_child_nodes?: l_set_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr DocumentClass.type_wf + DocumentClass.known_ptr set_child_nodes set_child_nodes_locs Core_DOM_Functions.set_child_nodes + Core_DOM_Functions.set_child_nodes_locs + apply(unfold_locales) + by (auto simp add: set_child_nodes_def set_child_nodes_locs_def) +declare l_set_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma set_child_nodes_is_l_set_child_nodes [instances]: "l_set_child_nodes type_wf set_child_nodes + set_child_nodes_locs" + using instances + apply(auto simp add: l_set_child_nodes_def)[1] + using set_child_nodes_writes apply fast + using set_child_nodes_pointers_preserved apply(fast, fast) + using set_child_nodes_types_preserved apply(fast, fast) + done + + + +paragraph \get\_child\_nodes\ + +locale l_set_child_nodes_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + type_wf known_ptr type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes get_child_nodes_locs + get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_set_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + type_wf known_ptr type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M set_child_nodes set_child_nodes_locs + set_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M set_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + CD: l_set_child_nodes_get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + set_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M set_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + for type_wf :: "(_) heap \ bool" + and known_ptr :: "(_) object_ptr \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ bool" + and get_child_nodes :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and set_child_nodes :: "(_) object_ptr \ (_) node_ptr list \ ((_) heap, exception, unit) prog" + and set_child_nodes_locs :: "(_) object_ptr \ ((_) heap, exception, unit) prog set" + and set_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ (_) node_ptr list \ ((_) heap, exception, unit) prog" + and set_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ ((_) heap, exception, unit) prog set" +begin + +lemma set_child_nodes_get_child_nodes: + assumes "known_ptr ptr" + assumes "type_wf h" + assumes "h \ set_child_nodes ptr children \\<^sub>h h'" + shows "h' \ get_child_nodes ptr \\<^sub>r children" +proof - + have "h \ check_in_heap ptr \\<^sub>r ()" + using assms set_child_nodes_def invoke_ptr_in_heap + by (metis (full_types) check_in_heap_ptr_in_heap is_OK_returns_heap_I is_OK_returns_result_E + old.unit.exhaust) + then have ptr_in_h: "ptr |\| object_ptr_kinds h" + by (simp add: check_in_heap_ptr_in_heap is_OK_returns_result_I) + + have "type_wf h'" + apply(unfold type_wf_impl) + apply(rule subst[where P=id, OF type_wf_preserved[OF set_child_nodes_writes assms(3), + unfolded all_args_def], simplified]) + by(auto simp add: all_args_def assms(2)[unfolded type_wf_impl] set_child_nodes_locs_def + CD.set_child_nodes_locs_def + split: if_splits) + have "h' \ check_in_heap ptr \\<^sub>r ()" + using check_in_heap_reads set_child_nodes_writes assms(3) \h \ check_in_heap ptr \\<^sub>r ()\ + apply(rule reads_writes_separate_forwards) + apply(auto simp add: all_args_def set_child_nodes_locs_def CD.set_child_nodes_locs_def)[1] + done + then have "ptr |\| object_ptr_kinds h'" + using check_in_heap_ptr_in_heap by blast + with assms ptr_in_h \type_wf h'\ show ?thesis + apply(auto simp add: type_wf_impl known_ptr_impl get_child_nodes_def a_get_child_nodes_tups_def + set_child_nodes_def a_set_child_nodes_tups_def + del: bind_pure_returns_result_I2 + intro!: bind_pure_returns_result_I2)[1] + apply(split CD.get_child_nodes_splits, (rule conjI impI)+)+ + apply(split CD.set_child_nodes_splits)+ + apply(auto simp add: CD.set_child_nodes_get_child_nodes type_wf_impl CD.type_wf_impl + dest: ShadowRootClass.type_wf\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t)[1] + apply(auto simp add: CD.set_child_nodes_get_child_nodes type_wf_impl CD.type_wf_impl + dest: ShadowRootClass.type_wf\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t)[1] + apply(split CD.set_child_nodes_splits)+ + by(auto simp add: known_ptr_impl CD.known_ptr_impl set_child_nodes\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def + get_child_nodes\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def CD.type_wf_impl ShadowRootClass.type_wf\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t + dest: known_ptr_new_shadow_root_ptr)[2] +qed + +lemma set_child_nodes_get_child_nodes_different_pointers: + assumes "ptr \ ptr'" + assumes "w \ set_child_nodes_locs ptr" + assumes "h \ w \\<^sub>h h'" + assumes "r \ get_child_nodes_locs ptr'" + shows "r h h'" + using assms + apply(auto simp add: set_child_nodes_locs_def CD.set_child_nodes_locs_def + get_child_nodes_locs_def CD.get_child_nodes_locs_def)[1] + by(auto simp add: all_args_def + elim!: is_document_ptr_kind_obtains is_shadow_root_ptr_kind_obtains + is_element_ptr_kind_obtains + split: if_splits option.splits) + +end + +interpretation + i_set_child_nodes_get_child_nodes?: l_set_child_nodes_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr + DocumentClass.type_wf DocumentClass.known_ptr get_child_nodes get_child_nodes_locs + Core_DOM_Functions.get_child_nodes Core_DOM_Functions.get_child_nodes_locs set_child_nodes + set_child_nodes_locs Core_DOM_Functions.set_child_nodes Core_DOM_Functions.set_child_nodes_locs + using instances + by(auto simp add: l_set_child_nodes_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def ) +declare l_set_child_nodes_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma set_child_nodes_get_child_nodes_is_l_set_child_nodes_get_child_nodes [instances]: + "l_set_child_nodes_get_child_nodes type_wf known_ptr get_child_nodes get_child_nodes_locs + set_child_nodes set_child_nodes_locs" + apply(auto simp add: instances l_set_child_nodes_get_child_nodes_def + l_set_child_nodes_get_child_nodes_axioms_def)[1] + using set_child_nodes_get_child_nodes apply fast + using set_child_nodes_get_child_nodes_different_pointers apply fast + done + +subsubsection \set\_tag\_type\ + +locale l_set_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + CD: l_set_tag_name\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M set_tag_name set_tag_name_locs + + l_type_wf type_wf + for type_wf :: "(_) heap \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and set_tag_name :: "(_) element_ptr \ tag_name \ (_, unit) dom_prog" + and set_tag_name_locs :: "(_) element_ptr \ (_, unit) dom_prog set" + + assumes type_wf_impl: "type_wf = ShadowRootClass.type_wf" +begin +lemmas set_tag_name_def = CD.set_tag_name_impl[unfolded CD.a_set_tag_name_def set_tag_name_def] +lemmas set_tag_name_locs_def = CD.set_tag_name_locs_impl[unfolded CD.a_set_tag_name_locs_def + set_tag_name_locs_def] + +lemma set_tag_name_ok: + "type_wf h \ element_ptr |\| element_ptr_kinds h \ h \ ok (set_tag_name element_ptr tag)" + apply(unfold type_wf_impl) + unfolding set_tag_name_impl[unfolded a_set_tag_name_def] using get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_ok put_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_ok + using CD.set_tag_name_ok CD.type_wf_impl ShadowRootClass.type_wf\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t by blast + +lemma set_tag_name_writes: + "writes (set_tag_name_locs element_ptr) (set_tag_name element_ptr tag) h h'" + using CD.set_tag_name_writes . + +lemma set_tag_name_pointers_preserved: + assumes "w \ set_tag_name_locs element_ptr" + assumes "h \ w \\<^sub>h h'" + shows "object_ptr_kinds h = object_ptr_kinds h'" + using assms + by(simp add: CD.set_tag_name_pointers_preserved) + +lemma set_tag_name_typess_preserved: + assumes "w \ set_tag_name_locs element_ptr" + assumes "h \ w \\<^sub>h h'" + shows "type_wf h = type_wf h'" + apply(unfold type_wf_impl) + apply(rule type_wf_preserved[OF writes_singleton2 assms(2)]) + using assms(1) set_tag_name_locs_def + by(auto simp add: all_args_def set_tag_name_locs_def + split: if_splits) +end + +interpretation i_set_tag_name?: l_set_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf DocumentClass.type_wf set_tag_name + set_tag_name_locs + by(auto simp add: l_set_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_set_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def instances) +declare l_set_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma set_tag_name_is_l_set_tag_name [instances]: + "l_set_tag_name type_wf set_tag_name set_tag_name_locs" + apply(auto simp add: l_set_tag_name_def)[1] + using set_tag_name_writes apply fast + using set_tag_name_ok apply fast + using set_tag_name_pointers_preserved apply (fast, fast) + using set_tag_name_typess_preserved apply (fast, fast) + done + +paragraph \get\_child\_nodes\ + +locale l_set_tag_name_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + CD: l_set_tag_name_get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M set_tag_name set_tag_name_locs + known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_tag_name_get_child_nodes: + "\w \ set_tag_name_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_child_nodes_locs ptr'. r h h'))" + apply(auto simp add: get_child_nodes_locs_def)[1] + apply(auto simp add: set_tag_name_locs_def all_args_def)[1] + using CD.set_tag_name_get_child_nodes apply(blast) + using CD.set_tag_name_get_child_nodes apply(blast) + done +end + +interpretation + i_set_tag_name_get_child_nodes?: l_set_tag_name_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf + DocumentClass.type_wf set_tag_name set_tag_name_locs known_ptr DocumentClass.known_ptr + get_child_nodes get_child_nodes_locs Core_DOM_Functions.get_child_nodes + Core_DOM_Functions.get_child_nodes_locs + by unfold_locales +declare l_set_tag_name_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma set_tag_name_get_child_nodes_is_l_set_tag_name_get_child_nodes [instances]: + "l_set_tag_name_get_child_nodes type_wf set_tag_name set_tag_name_locs known_ptr get_child_nodes + get_child_nodes_locs" + using set_tag_name_is_l_set_tag_name get_child_nodes_is_l_get_child_nodes + apply(simp add: l_set_tag_name_get_child_nodes_def + l_set_tag_name_get_child_nodes_axioms_def) + using set_tag_name_get_child_nodes + by fast + + + +subsubsection \get\_shadow\_root\ + +locale l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs +begin +definition a_get_shadow_root :: "(_) element_ptr \ (_, (_) shadow_root_ptr option) dom_prog" + where + "a_get_shadow_root element_ptr = get_M element_ptr shadow_root_opt" + +definition a_get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + where + "a_get_shadow_root_locs element_ptr \ {preserved (get_M element_ptr shadow_root_opt)}" +end + +global_interpretation l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + defines get_shadow_root = a_get_shadow_root + and get_shadow_root_locs = a_get_shadow_root_locs + . + +locale l_get_shadow_root_defs = + fixes get_shadow_root :: "(_) element_ptr \ (_, (_) shadow_root_ptr option) dom_prog" + fixes get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + +locale l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + + l_get_shadow_root_defs get_shadow_root get_shadow_root_locs + + l_type_wf type_wf + for type_wf :: "(_) heap \ bool" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + + assumes type_wf_impl: "type_wf = ShadowRootClass.type_wf" + assumes get_shadow_root_impl: "get_shadow_root = a_get_shadow_root" + assumes get_shadow_root_locs_impl: "get_shadow_root_locs = a_get_shadow_root_locs" +begin +lemmas get_shadow_root_def = get_shadow_root_impl[unfolded get_shadow_root_def a_get_shadow_root_def] +lemmas get_shadow_root_locs_def = get_shadow_root_locs_impl[unfolded get_shadow_root_locs_def + a_get_shadow_root_locs_def] + +lemma get_shadow_root_ok: + "type_wf h \ element_ptr |\| element_ptr_kinds h \ h \ ok (get_shadow_root element_ptr)" + unfolding get_shadow_root_def type_wf_impl + using ShadowRootMonad.get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_ok by blast + +lemma get_shadow_root_pure [simp]: "pure (get_shadow_root element_ptr) h" + unfolding get_shadow_root_def by simp + +lemma get_shadow_root_ptr_in_heap: + assumes "h \ get_shadow_root element_ptr \\<^sub>r children" + shows "element_ptr |\| element_ptr_kinds h" + using assms + by(auto simp add: get_shadow_root_def get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_ptr_in_heap dest: is_OK_returns_result_I) + +lemma get_shadow_root_reads: + "reads (get_shadow_root_locs element_ptr) (get_shadow_root element_ptr) h h'" + by(simp add: get_shadow_root_def get_shadow_root_locs_def reads_bind_pure + reads_insert_writes_set_right) +end + +interpretation i_get_shadow_root?: l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_shadow_root + get_shadow_root_locs + using instances + by (auto simp add: l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def) +declare l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +locale l_get_shadow_root = l_type_wf + l_get_shadow_root_defs + + assumes get_shadow_root_reads: + "reads (get_shadow_root_locs element_ptr) (get_shadow_root element_ptr) h h'" + assumes get_shadow_root_ok: + "type_wf h \ element_ptr |\| element_ptr_kinds h \ h \ ok (get_shadow_root element_ptr)" + assumes get_shadow_root_ptr_in_heap: + "h \ ok (get_shadow_root element_ptr) \ element_ptr |\| element_ptr_kinds h" + assumes get_shadow_root_pure [simp]: + "pure (get_shadow_root element_ptr) h" + +lemma get_shadow_root_is_l_get_shadow_root [instances]: + "l_get_shadow_root type_wf get_shadow_root get_shadow_root_locs" + using instances + apply(auto simp add: l_get_shadow_root_def)[1] + using get_shadow_root_reads apply blast + using get_shadow_root_ok apply blast + using get_shadow_root_ptr_in_heap apply blast + done + + +paragraph \set\_disconnected\_nodes\ + +locale l_set_disconnected_nodes_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_disconnected_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M set_disconnected_nodes set_disconnected_nodes_locs + + l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_shadow_root get_shadow_root_locs + for type_wf :: "(_) heap \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and set_disconnected_nodes + :: "(_) document_ptr \ (_) node_ptr list \ ((_) heap, exception, unit) prog" + and set_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap, exception, unit) prog set" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +lemma set_disconnected_nodes_get_shadow_root: + "\w \ set_disconnected_nodes_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_shadow_root_locs ptr'. r h h'))" + by(auto simp add: set_disconnected_nodes_locs_def get_shadow_root_locs_def all_args_def) +end + +locale l_set_disconnected_nodes_get_shadow_root = + l_set_disconnected_nodes_defs + + l_get_shadow_root_defs + + assumes set_disconnected_nodes_get_shadow_root: + "\w \ set_disconnected_nodes_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_shadow_root_locs ptr'. r h h'))" + +interpretation + i_set_disconnected_nodes_get_shadow_root?: l_set_disconnected_nodes_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + type_wf DocumentClass.type_wf set_disconnected_nodes set_disconnected_nodes_locs get_shadow_root + get_shadow_root_locs + by(auto simp add: l_set_disconnected_nodes_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_set_disconnected_nodes_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma set_disconnected_nodes_get_shadow_root_is_l_set_disconnected_nodes_get_shadow_root [instances]: + "l_set_disconnected_nodes_get_shadow_root set_disconnected_nodes_locs get_shadow_root_locs" + apply(auto simp add: l_set_disconnected_nodes_get_shadow_root_def)[1] + using set_disconnected_nodes_get_shadow_root apply fast + done + +paragraph \set\_tag\_type\ + +locale l_set_tag_name_get_shadow_root\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_tag_name_get_shadow_root: + "\w \ set_tag_name_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_shadow_root_locs ptr'. r h h'))" + by(auto simp add: set_tag_name_locs_def + get_shadow_root_locs_def all_args_def + intro: element_put_get_preserved[where setter=tag_name_update and getter=shadow_root_opt]) +end + +locale l_set_tag_name_get_shadow_root = l_set_tag_name + l_get_shadow_root + + assumes set_tag_name_get_shadow_root: + "\w \ set_tag_name_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_shadow_root_locs ptr'. r h h'))" + +interpretation + i_set_tag_name_get_shadow_root?: l_set_tag_name_get_shadow_root\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf DocumentClass.type_wf + set_tag_name set_tag_name_locs + get_shadow_root get_shadow_root_locs + apply(auto simp add: l_set_tag_name_get_shadow_root\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances)[1] + using l_set_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms + by unfold_locales +declare l_set_tag_name_get_shadow_root\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma set_tag_name_get_shadow_root_is_l_set_tag_name_get_shadow_root [instances]: + "l_set_tag_name_get_shadow_root type_wf set_tag_name set_tag_name_locs get_shadow_root + get_shadow_root_locs" + using set_tag_name_is_l_set_tag_name get_shadow_root_is_l_get_shadow_root + apply(simp add: l_set_tag_name_get_shadow_root_def l_set_tag_name_get_shadow_root_axioms_def) + using set_tag_name_get_shadow_root + by fast + + +paragraph \set\_child\_nodes\ + +locale l_set_child_nodes_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M set_child_nodes + set_child_nodes_locs set_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M set_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_shadow_root get_shadow_root_locs + for type_wf :: "(_) heap \ bool" + and known_ptr :: "(_) object_ptr \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ bool" + and set_child_nodes :: "(_) object_ptr \ (_) node_ptr list \ ((_) heap, exception, unit) prog" + and set_child_nodes_locs :: "(_) object_ptr \ ((_) heap, exception, unit) prog set" + and set_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ (_) node_ptr list \ ((_) heap, exception, unit) prog" + and set_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ ((_) heap, exception, unit) prog set" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +lemma set_child_nodes_get_shadow_root: "\w \ set_child_nodes_locs ptr. (h \ w \\<^sub>h h' \ + (\r \ get_shadow_root_locs ptr'. r h h'))" + apply(auto simp add: set_child_nodes_locs_def get_shadow_root_locs_def CD.set_child_nodes_locs_def + all_args_def)[1] + by(auto intro!: element_put_get_preserved[where getter=shadow_root_opt and + setter=RElement.child_nodes_update]) +end + +locale l_set_child_nodes_get_shadow_root = l_set_child_nodes_defs + l_get_shadow_root_defs + + assumes set_child_nodes_get_shadow_root: + "\w \ set_child_nodes_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_shadow_root_locs ptr'. r h h'))" + +interpretation + i_set_child_nodes_get_shadow_root?: l_set_child_nodes_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr + DocumentClass.type_wf DocumentClass.known_ptr set_child_nodes set_child_nodes_locs + Core_DOM_Functions.set_child_nodes Core_DOM_Functions.set_child_nodes_locs get_shadow_root + get_shadow_root_locs + by(auto simp add: l_set_child_nodes_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_set_child_nodes_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma set_child_nodes_get_shadow_root_is_l_set_child_nodes_get_shadow_root [instances]: + "l_set_child_nodes_get_shadow_root set_child_nodes_locs get_shadow_root_locs" + apply(auto simp add: l_set_child_nodes_get_shadow_root_def)[1] + using set_child_nodes_get_shadow_root apply fast + done + + +paragraph \delete\_shadow\_root\ + +locale l_delete_shadow_root_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma get_shadow_root_delete_shadow_root: "h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h' + \ r \ get_shadow_root_locs ptr' \ r h h'" + by(auto simp add: get_shadow_root_locs_def delete_shadow_root_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t) +end + +locale l_delete_shadow_root_get_shadow_root = l_get_shadow_root_defs + + assumes get_shadow_root_delete_shadow_root: "h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h' + \ r \ get_shadow_root_locs ptr' \ r h h'" +interpretation l_delete_shadow_root_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_shadow_root + get_shadow_root_locs + by(auto simp add: l_delete_shadow_root_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) + +lemma l_delete_shadow_root_get_shadow_root_get_shadow_root_locs [instances]: "l_delete_shadow_root_get_shadow_root get_shadow_root_locs" + apply(auto simp add: l_delete_shadow_root_get_shadow_root_def)[1] + using get_shadow_root_delete_shadow_root apply fast + done + +paragraph \new\_character\_data\ + +locale l_new_character_data_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_shadow_root get_shadow_root_locs + for type_wf :: "(_) heap \ bool" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +lemma get_shadow_root_new_character_data: + "h \ new_character_data \\<^sub>r new_character_data_ptr \ h \ new_character_data \\<^sub>h h' + \ r \ get_shadow_root_locs ptr' \ r h h'" + by (auto simp add: get_shadow_root_locs_def new_character_data_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t + new_character_data_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t + split: prod.splits if_splits option.splits + elim!: bind_returns_result_E bind_returns_heap_E + intro: is_element_ptr_kind_obtains) +end + +locale l_new_character_data_get_shadow_root = l_new_character_data + l_get_shadow_root + + assumes get_shadow_root_new_character_data: + "h \ new_character_data \\<^sub>r new_character_data_ptr + \ h \ new_character_data \\<^sub>h h' \ r \ get_shadow_root_locs ptr' \ r h h'" + + +interpretation i_new_character_data_get_shadow_root?: + l_new_character_data_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_shadow_root get_shadow_root_locs + by(unfold_locales) +declare l_new_character_data_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma new_character_data_get_shadow_root_is_l_new_character_data_get_shadow_root [instances]: + "l_new_character_data_get_shadow_root type_wf get_shadow_root get_shadow_root_locs" + using new_character_data_is_l_new_character_data get_shadow_root_is_l_get_shadow_root + apply(auto simp add: l_new_character_data_get_shadow_root_def + l_new_character_data_get_shadow_root_axioms_def instances)[1] + using get_shadow_root_new_character_data + by fast + +paragraph \new\_document\ + +locale l_new_document_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_shadow_root get_shadow_root_locs + for type_wf :: "(_) heap \ bool" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +lemma get_shadow_root_new_document: + "h \ new_document \\<^sub>r new_document_ptr \ h \ new_document \\<^sub>h h' + \ r \ get_shadow_root_locs ptr' \ r h h'" + by (auto simp add: get_shadow_root_locs_def new_document_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t new_document_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t + split: prod.splits if_splits option.splits + elim!: bind_returns_result_E bind_returns_heap_E intro: is_element_ptr_kind_obtains) +end + +locale l_new_document_get_shadow_root = l_new_document + l_get_shadow_root + + assumes get_shadow_root_new_document: + "h \ new_document \\<^sub>r new_document_ptr + \ h \ new_document \\<^sub>h h' \ r \ get_shadow_root_locs ptr' \ r h h'" + + +interpretation i_new_document_get_shadow_root?: + l_new_document_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_shadow_root get_shadow_root_locs + by(unfold_locales) +declare l_new_document_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma new_document_get_shadow_root_is_l_new_document_get_shadow_root [instances]: + "l_new_document_get_shadow_root type_wf get_shadow_root get_shadow_root_locs" + using new_document_is_l_new_document get_shadow_root_is_l_get_shadow_root + apply(auto simp add: l_new_document_get_shadow_root_def l_new_document_get_shadow_root_axioms_def + instances)[1] + using get_shadow_root_new_document + by fast + +paragraph \new\_element\ + +locale l_new_element_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_shadow_root get_shadow_root_locs + for type_wf :: "(_) heap \ bool" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +lemma get_shadow_root_new_element: + "ptr' \ new_element_ptr \ h \ new_element \\<^sub>r new_element_ptr \ h \ new_element \\<^sub>h h' + \ r \ get_shadow_root_locs ptr' \ r h h'" + by (auto simp add: get_shadow_root_locs_def new_element_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t new_element_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t + new_element_get_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t split: prod.splits if_splits option.splits + elim!: bind_returns_result_E bind_returns_heap_E intro: is_element_ptr_kind_obtains) + +lemma new_element_no_shadow_root: + "h \ new_element \\<^sub>r new_element_ptr \ h \ new_element \\<^sub>h h' + \ h' \ get_shadow_root new_element_ptr \\<^sub>r None" + by(simp add: get_shadow_root_def new_element_shadow_root_opt) +end + +locale l_new_element_get_shadow_root = l_new_element + l_get_shadow_root + + assumes get_shadow_root_new_element: + "ptr' \ new_element_ptr \ h \ new_element \\<^sub>r new_element_ptr + \ h \ new_element \\<^sub>h h' \ r \ get_shadow_root_locs ptr' \ r h h'" + assumes new_element_no_shadow_root: + "h \ new_element \\<^sub>r new_element_ptr \ h \ new_element \\<^sub>h h' + \ h' \ get_shadow_root new_element_ptr \\<^sub>r None" + + +interpretation i_new_element_get_shadow_root?: + l_new_element_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_shadow_root get_shadow_root_locs + by(unfold_locales) +declare l_new_element_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma new_element_get_shadow_root_is_l_new_element_get_shadow_root [instances]: + "l_new_element_get_shadow_root type_wf get_shadow_root get_shadow_root_locs" + using new_element_is_l_new_element get_shadow_root_is_l_get_shadow_root + apply(auto simp add: l_new_element_get_shadow_root_def l_new_element_get_shadow_root_axioms_def + instances)[1] + using get_shadow_root_new_element new_element_no_shadow_root + by fast+ + +paragraph \new\_shadow\_root\ + +locale l_new_shadow_root_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_shadow_root get_shadow_root_locs + for type_wf :: "(_) heap \ bool" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +lemma get_shadow_root_new_shadow_root: + "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' + \ r \ get_shadow_root_locs ptr' \ r h h'" + by (auto simp add: get_shadow_root_locs_def new_shadow_root_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t new_shadow_root_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t + split: prod.splits if_splits option.splits + elim!: bind_returns_result_E bind_returns_heap_E intro: is_element_ptr_kind_obtains) +end + +locale l_new_shadow_root_get_shadow_root = l_get_shadow_root + + assumes get_shadow_root_new_shadow_root: + "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr + \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' \ r \ get_shadow_root_locs ptr' \ r h h'" + +interpretation i_new_shadow_root_get_shadow_root?: + l_new_shadow_root_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_shadow_root get_shadow_root_locs + by(unfold_locales) +declare l_new_shadow_root_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma new_shadow_root_get_shadow_root_is_l_new_shadow_root_get_shadow_root [instances]: + "l_new_shadow_root_get_shadow_root type_wf get_shadow_root get_shadow_root_locs" + using get_shadow_root_is_l_get_shadow_root + apply(auto simp add: l_new_shadow_root_get_shadow_root_def + l_new_shadow_root_get_shadow_root_axioms_def instances)[1] + using get_shadow_root_new_shadow_root + by fast + + +subsubsection \set\_shadow\_root\ + +locale l_set_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs +begin +definition a_set_shadow_root :: "(_) element_ptr \ (_) shadow_root_ptr option \ (_, unit) dom_prog" + where + "a_set_shadow_root element_ptr = put_M element_ptr shadow_root_opt_update" + +definition a_set_shadow_root_locs :: "(_) element_ptr \ ((_, unit) dom_prog) set" + where + "a_set_shadow_root_locs element_ptr \ all_args (put_M element_ptr shadow_root_opt_update)" +end + +global_interpretation l_set_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + defines set_shadow_root = a_set_shadow_root + and set_shadow_root_locs = a_set_shadow_root_locs + . + +locale l_set_shadow_root_defs = + fixes set_shadow_root :: "(_) element_ptr \ (_) shadow_root_ptr option \ (_, unit) dom_prog" + fixes set_shadow_root_locs :: "(_) element_ptr \ (_, unit) dom_prog set" + + +locale l_set_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_type_wf type_wf + + l_set_shadow_root_defs set_shadow_root set_shadow_root_locs + + l_set_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + for type_wf :: "(_) heap \ bool" + and set_shadow_root :: "(_) element_ptr \ (_) shadow_root_ptr option \ (_, unit) dom_prog" + and set_shadow_root_locs :: "(_) element_ptr \ (_, unit) dom_prog set" + + assumes type_wf_impl: "type_wf = ShadowRootClass.type_wf" + assumes set_shadow_root_impl: "set_shadow_root = a_set_shadow_root" + assumes set_shadow_root_locs_impl: "set_shadow_root_locs = a_set_shadow_root_locs" +begin +lemmas set_shadow_root_def = set_shadow_root_impl[unfolded set_shadow_root_def + a_set_shadow_root_def] +lemmas set_shadow_root_locs_def = set_shadow_root_locs_impl[unfolded set_shadow_root_locs_def + a_set_shadow_root_locs_def] + +lemma set_shadow_root_ok: "type_wf h \ element_ptr |\| element_ptr_kinds h \ + h \ ok (set_shadow_root element_ptr tag)" + apply(unfold type_wf_impl) + unfolding set_shadow_root_def using get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_ok put_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_ok + by (simp add: ShadowRootMonad.put_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_ok) + +lemma set_shadow_root_ptr_in_heap: + "h \ ok (set_shadow_root element_ptr shadow_root) \ element_ptr |\| element_ptr_kinds h" + by(simp add: set_shadow_root_def ElementMonad.put_M_ptr_in_heap) + +lemma set_shadow_root_writes: + "writes (set_shadow_root_locs element_ptr) (set_shadow_root element_ptr tag) h h'" + by(auto simp add: set_shadow_root_def set_shadow_root_locs_def intro: writes_bind_pure) + +lemma set_shadow_root_pointers_preserved: + assumes "w \ set_shadow_root_locs element_ptr" + assumes "h \ w \\<^sub>h h'" + shows "object_ptr_kinds h = object_ptr_kinds h'" + using assms(1) object_ptr_kinds_preserved[OF writes_singleton2 assms(2)] + by(auto simp add: all_args_def set_shadow_root_locs_def split: if_splits) + +lemma set_shadow_root_types_preserved: + assumes "w \ set_shadow_root_locs element_ptr" + assumes "h \ w \\<^sub>h h'" + shows "type_wf h = type_wf h'" + apply(unfold type_wf_impl) + using assms(1) type_wf_preserved[OF writes_singleton2 assms(2)] + by(auto simp add: all_args_def set_shadow_root_locs_def split: if_splits) +end + +interpretation i_set_shadow_root?: l_set_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf set_shadow_root + set_shadow_root_locs + by (auto simp add: l_set_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_set_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +locale l_set_shadow_root = l_type_wf +l_set_shadow_root_defs + + assumes set_shadow_root_writes: + "writes (set_shadow_root_locs element_ptr) (set_shadow_root element_ptr disc_nodes) h h'" + assumes set_shadow_root_ok: + "type_wf h \ element_ptr |\| element_ptr_kinds h \ + h \ ok (set_shadow_root element_ptr shadow_root)" + assumes set_shadow_root_ptr_in_heap: + "h \ ok (set_shadow_root element_ptr shadow_root) \ element_ptr |\| element_ptr_kinds h" + assumes set_shadow_root_pointers_preserved: + "w \ set_shadow_root_locs element_ptr \ h \ w \\<^sub>h h' \ + object_ptr_kinds h = object_ptr_kinds h'" + assumes set_shadow_root_types_preserved: + "w \ set_shadow_root_locs element_ptr \ h \ w \\<^sub>h h' \ type_wf h = type_wf h'" + +lemma set_shadow_root_is_l_set_shadow_root [instances]: + "l_set_shadow_root type_wf set_shadow_root set_shadow_root_locs" + apply(auto simp add: l_set_shadow_root_def instances)[1] + using set_shadow_root_writes apply blast + using set_shadow_root_ok apply (blast) + using set_shadow_root_ptr_in_heap apply blast + using set_shadow_root_pointers_preserved apply(blast, blast) + using set_shadow_root_types_preserved apply(blast, blast) + done + +paragraph \get\_shadow\_root\ + +locale l_set_shadow_root_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_shadow_root_get_shadow_root: + "type_wf h \ h \ set_shadow_root ptr shadow_root_ptr_opt \\<^sub>h h' \ + h' \ get_shadow_root ptr \\<^sub>r shadow_root_ptr_opt" + by(auto simp add: set_shadow_root_def get_shadow_root_def) + +lemma set_shadow_root_get_shadow_root_different_pointers: "ptr \ ptr' \ + \w \ set_shadow_root_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_shadow_root_locs ptr'. r h h'))" + by(auto simp add: set_shadow_root_locs_def get_shadow_root_locs_def all_args_def) +end + +interpretation i_set_shadow_root_get_shadow_root?: l_set_shadow_root_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf + set_shadow_root set_shadow_root_locs get_shadow_root get_shadow_root_locs + apply(auto simp add: l_set_shadow_root_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances)[1] + by(unfold_locales) +declare l_set_shadow_root_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +locale l_set_shadow_root_get_shadow_root = + l_type_wf + + l_set_shadow_root_defs + + l_get_shadow_root_defs + + assumes set_shadow_root_get_shadow_root: + "type_wf h \ h \ set_shadow_root ptr shadow_root_ptr_opt \\<^sub>h h' \ + h' \ get_shadow_root ptr \\<^sub>r shadow_root_ptr_opt" + assumes set_shadow_root_get_shadow_root_different_pointers: + "ptr \ ptr' \ w \ set_shadow_root_locs ptr \ h \ w \\<^sub>h h' \ + r \ get_shadow_root_locs ptr' \ r h h'" + +lemma set_shadow_root_get_shadow_root_is_l_set_shadow_root_get_shadow_root [instances]: + "l_set_shadow_root_get_shadow_root type_wf set_shadow_root set_shadow_root_locs get_shadow_root + get_shadow_root_locs" + apply(auto simp add: l_set_shadow_root_get_shadow_root_def instances)[1] + using set_shadow_root_get_shadow_root apply fast + using set_shadow_root_get_shadow_root_different_pointers apply fast + done + + + +subsubsection \set\_mode\ + +locale l_set_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs +begin +definition a_set_mode :: "(_) shadow_root_ptr \ shadow_root_mode \ (_, unit) dom_prog" + where + "a_set_mode shadow_root_ptr = put_M shadow_root_ptr mode_update" + +definition a_set_mode_locs :: "(_) shadow_root_ptr \ ((_, unit) dom_prog) set" + where + "a_set_mode_locs shadow_root_ptr \ all_args (put_M shadow_root_ptr mode_update)" +end + +global_interpretation l_set_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + defines set_mode = a_set_mode + and set_mode_locs = a_set_mode_locs + . + +locale l_set_mode_defs = + fixes set_mode :: "(_) shadow_root_ptr \ shadow_root_mode \ (_, unit) dom_prog" + fixes set_mode_locs :: "(_) shadow_root_ptr \ (_, unit) dom_prog set" + + +locale l_set_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_type_wf type_wf + + l_set_mode_defs set_mode set_mode_locs + + l_set_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + for type_wf :: "(_) heap \ bool" + and set_mode :: "(_) shadow_root_ptr \ shadow_root_mode \ (_, unit) dom_prog" + and set_mode_locs :: "(_) shadow_root_ptr \ (_, unit) dom_prog set" + + assumes type_wf_impl: "type_wf = ShadowRootClass.type_wf" + assumes set_mode_impl: "set_mode = a_set_mode" + assumes set_mode_locs_impl: "set_mode_locs = a_set_mode_locs" +begin +lemmas set_mode_def = set_mode_impl[unfolded set_mode_def a_set_mode_def] +lemmas set_mode_locs_def = set_mode_locs_impl[unfolded set_mode_locs_def a_set_mode_locs_def] + +lemma set_mode_ok: + "type_wf h \ shadow_root_ptr |\| shadow_root_ptr_kinds h \ + h \ ok (set_mode shadow_root_ptr shadow_root_mode)" + apply(unfold type_wf_impl) + unfolding set_mode_def using get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ok put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ok + by (simp add: ShadowRootMonad.put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ok) + +lemma set_mode_ptr_in_heap: + "h \ ok (set_mode shadow_root_ptr shadow_root_mode) \ + shadow_root_ptr |\| shadow_root_ptr_kinds h" + by(simp add: set_mode_def put_M_ptr_in_heap) + +lemma set_mode_writes: + "writes (set_mode_locs shadow_root_ptr) (set_mode shadow_root_ptr shadow_root_mode) h h'" + by(auto simp add: set_mode_def set_mode_locs_def intro: writes_bind_pure) + +lemma set_mode_pointers_preserved: + assumes "w \ set_mode_locs element_ptr" + assumes "h \ w \\<^sub>h h'" + shows "object_ptr_kinds h = object_ptr_kinds h'" + using assms(1) object_ptr_kinds_preserved[OF writes_singleton2 assms(2)] + by(auto simp add: all_args_def set_mode_locs_def split: if_splits) + +lemma set_mode_types_preserved: + assumes "w \ set_mode_locs element_ptr" + assumes "h \ w \\<^sub>h h'" + shows "type_wf h = type_wf h'" + apply(unfold type_wf_impl) + using assms(1) type_wf_preserved[OF writes_singleton2 assms(2)] + by(auto simp add: all_args_def set_mode_locs_def split: if_splits) +end + +interpretation i_set_mode?: l_set_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf set_mode set_mode_locs + by (auto simp add: l_set_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_set_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +locale l_set_mode = l_type_wf +l_set_mode_defs + + assumes set_mode_writes: + "writes (set_mode_locs shadow_root_ptr) (set_mode shadow_root_ptr shadow_root_mode) h h'" + assumes set_mode_ok: + "type_wf h \ shadow_root_ptr |\| shadow_root_ptr_kinds h \ + h \ ok (set_mode shadow_root_ptr shadow_root_mode)" + assumes set_mode_ptr_in_heap: + "h \ ok (set_mode shadow_root_ptr shadow_root_mode) \ + shadow_root_ptr |\| shadow_root_ptr_kinds h" + assumes set_mode_pointers_preserved: + "w \ set_mode_locs shadow_root_ptr \ + h \ w \\<^sub>h h' \ object_ptr_kinds h = object_ptr_kinds h'" + assumes set_mode_types_preserved: + "w \ set_mode_locs shadow_root_ptr \ h \ w \\<^sub>h h' \ type_wf h = type_wf h'" + +lemma set_mode_is_l_set_mode [instances]: "l_set_mode type_wf set_mode set_mode_locs" + apply(auto simp add: l_set_mode_def instances)[1] + using set_mode_writes apply blast + using set_mode_ok apply (blast) + using set_mode_ptr_in_heap apply blast + using set_mode_pointers_preserved apply(blast, blast) + using set_mode_types_preserved apply(blast, blast) + done + + +paragraph \get\_child\_nodes\ + +locale l_set_shadow_root_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_set_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_shadow_root_get_child_nodes: + "\w \ set_shadow_root_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_child_nodes_locs ptr'. r h h'))" + by(auto simp add: get_child_nodes_locs_def set_shadow_root_locs_def CD.get_child_nodes_locs_def + all_args_def + intro: element_put_get_preserved[where setter=shadow_root_opt_update]) +end + +interpretation i_set_shadow_root_get_child_nodes?: l_set_shadow_root_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf + known_ptr DocumentClass.type_wf DocumentClass.known_ptr get_child_nodes get_child_nodes_locs + Core_DOM_Functions.get_child_nodes Core_DOM_Functions.get_child_nodes_locs set_shadow_root + set_shadow_root_locs + by(unfold_locales) +declare l_set_shadow_root_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +locale l_set_shadow_root_get_child_nodes = l_set_shadow_root + l_get_child_nodes + + assumes set_shadow_root_get_child_nodes: + "\w \ set_shadow_root_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_child_nodes_locs ptr'. r h h'))" + +lemma set_shadow_root_get_child_nodes_is_l_set_shadow_root_get_child_nodes [instances]: + "l_set_shadow_root_get_child_nodes type_wf set_shadow_root set_shadow_root_locs known_ptr + get_child_nodes get_child_nodes_locs" + apply(auto simp add: l_set_shadow_root_get_child_nodes_def + l_set_shadow_root_get_child_nodes_axioms_def instances)[1] + using set_shadow_root_get_child_nodes apply blast + done + +paragraph \get\_shadow\_root\ + + +locale l_set_mode_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_mode_get_shadow_root: + "\w \ set_mode_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_shadow_root_locs ptr'. r h h'))" + by(auto simp add: set_mode_locs_def get_shadow_root_locs_def all_args_def) +end + +interpretation + i_set_mode_get_shadow_root?: l_set_mode_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf + set_mode set_mode_locs get_shadow_root + get_shadow_root_locs + by unfold_locales +declare l_set_mode_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +locale l_set_mode_get_shadow_root = l_set_mode + l_get_shadow_root + + assumes set_mode_get_shadow_root: + "\w \ set_mode_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_shadow_root_locs ptr'. r h h'))" + +lemma set_mode_get_shadow_root_is_l_set_mode_get_shadow_root [instances]: + "l_set_mode_get_shadow_root type_wf set_mode set_mode_locs get_shadow_root + get_shadow_root_locs" + using set_mode_is_l_set_mode get_shadow_root_is_l_get_shadow_root + apply(simp add: l_set_mode_get_shadow_root_def + l_set_mode_get_shadow_root_axioms_def) + using set_mode_get_shadow_root + by fast + +paragraph \get\_child\_nodes\ + +locale l_set_mode_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_mode_get_child_nodes: + "\w \ set_mode_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_child_nodes_locs ptr'. r h h'))" + by(auto simp add: get_child_nodes_locs_def CD.get_child_nodes_locs_def set_mode_locs_def + all_args_def)[1] +end + +interpretation i_set_mode_get_child_nodes?: l_set_mode_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf set_mode + set_mode_locs known_ptr DocumentClass.type_wf DocumentClass.known_ptr get_child_nodes + get_child_nodes_locs Core_DOM_Functions.get_child_nodes Core_DOM_Functions.get_child_nodes_locs + by unfold_locales +declare l_set_mode_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +locale l_set_mode_get_child_nodes = l_set_mode + l_get_child_nodes + + assumes set_mode_get_child_nodes: + "\w \ set_mode_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_child_nodes_locs ptr'. r h h'))" + +lemma set_mode_get_child_nodes_is_l_set_mode_get_child_nodes [instances]: + "l_set_mode_get_child_nodes type_wf set_mode set_mode_locs known_ptr get_child_nodes + get_child_nodes_locs" + using set_mode_is_l_set_mode get_child_nodes_is_l_get_child_nodes + apply(simp add: l_set_mode_get_child_nodes_def + l_set_mode_get_child_nodes_axioms_def) + using set_mode_get_child_nodes + by fast + + +subsubsection \get\_host\ + +locale l_get_host\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs = + l_get_shadow_root_defs get_shadow_root get_shadow_root_locs + for get_shadow_root + :: "(_::linorder) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +definition a_get_host :: "(_) shadow_root_ptr \ (_, (_) element_ptr) dom_prog" where + "a_get_host shadow_root_ptr = do { + host_ptrs \ element_ptr_kinds_M \ filter_M (\element_ptr. do { + shadow_root_opt \ get_shadow_root element_ptr; + return (shadow_root_opt = Some shadow_root_ptr) + }); + (case host_ptrs of host_ptr#[] \ return host_ptr | _ \ error HierarchyRequestError) + }" +definition "a_get_host_locs \ (\element_ptr. (get_shadow_root_locs element_ptr)) \ + (\ptr. {preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr RObject.nothing)})" + +end + +global_interpretation l_get_host\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_shadow_root get_shadow_root_locs + defines get_host = "a_get_host" + and get_host_locs = "a_get_host_locs" + . + +locale l_get_host_defs = + fixes get_host :: "(_) shadow_root_ptr \ (_, (_) element_ptr) dom_prog" + fixes get_host_locs :: "((_) heap \ (_) heap \ bool) set" + +locale l_get_host\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_host\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + + l_get_host_defs + + l_get_shadow_root + + assumes get_host_impl: "get_host = a_get_host" + assumes get_host_locs_impl: "get_host_locs = a_get_host_locs" +begin +lemmas get_host_def = get_host_impl[unfolded a_get_host_def] +lemmas get_host_locs_def = get_host_locs_impl[unfolded a_get_host_locs_def] + +lemma get_host_pure [simp]: "pure (get_host element_ptr) h" + by(auto simp add: get_host_def intro!: bind_pure_I filter_M_pure_I split: list.splits) + +lemma get_host_reads: "reads get_host_locs (get_host element_ptr) h h'" + using get_shadow_root_reads[unfolded reads_def] + by(auto simp add: get_host_def get_host_locs_def + intro!: reads_bind_pure reads_subset[OF check_in_heap_reads] reads_subset[OF error_reads] + reads_subset[OF get_shadow_root_reads] reads_subset[OF return_reads] + reads_subset[OF element_ptr_kinds_M_reads] filter_M_reads filter_M_pure_I + bind_pure_I + split: list.splits) +end + +locale l_get_host = l_get_host_defs + + assumes get_host_pure [simp]: "pure (get_host element_ptr) h" + assumes get_host_reads: "reads get_host_locs (get_host node_ptr) h h'" + + +interpretation i_get_host?: l_get_host\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_shadow_root get_shadow_root_locs get_host + get_host_locs type_wf + using instances + by (simp add: l_get_host\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_get_host\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def get_host_def get_host_locs_def) +declare l_get_host\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma get_host_is_l_get_host [instances]: "l_get_host get_host get_host_locs" + apply(auto simp add: l_get_host_def)[1] + using get_host_reads apply fast + done + + + +subsubsection \get\_mode\ + +locale l_get_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs +begin +definition a_get_mode :: "(_) shadow_root_ptr \ (_, shadow_root_mode) dom_prog" + where + "a_get_mode shadow_root_ptr = get_M shadow_root_ptr mode" + +definition a_get_mode_locs :: "(_) shadow_root_ptr \ ((_) heap \ (_) heap \ bool) set" + where + "a_get_mode_locs shadow_root_ptr \ {preserved (get_M shadow_root_ptr mode)}" +end + +global_interpretation l_get_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + defines get_mode = a_get_mode + and get_mode_locs = a_get_mode_locs + . + +locale l_get_mode_defs = + fixes get_mode :: "(_) shadow_root_ptr \ (_, shadow_root_mode) dom_prog" + fixes get_mode_locs :: "(_) shadow_root_ptr \ ((_) heap \ (_) heap \ bool) set" + +locale l_get_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + + l_get_mode_defs get_mode get_mode_locs + + l_type_wf type_wf + for get_mode :: "(_) shadow_root_ptr \ ((_) heap, exception, shadow_root_mode) prog" + and get_mode_locs :: "(_) shadow_root_ptr \ ((_) heap \ (_) heap \ bool) set" + and type_wf :: "(_) heap \ bool" + + assumes type_wf_impl: "type_wf = ShadowRootClass.type_wf" + assumes get_mode_impl: "get_mode = a_get_mode" + assumes get_mode_locs_impl: "get_mode_locs = a_get_mode_locs" +begin +lemmas get_mode_def = get_mode_impl[unfolded get_mode_def a_get_mode_def] +lemmas get_mode_locs_def = get_mode_locs_impl[unfolded get_mode_locs_def a_get_mode_locs_def] + +lemma get_mode_ok: "type_wf h \ shadow_root_ptr |\| shadow_root_ptr_kinds h \ + h \ ok (get_mode shadow_root_ptr)" + unfolding get_mode_def type_wf_impl + using ShadowRootMonad.get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ok by blast + +lemma get_mode_pure [simp]: "pure (get_mode element_ptr) h" + unfolding get_mode_def by simp + +lemma get_mode_ptr_in_heap: + assumes "h \ get_mode shadow_root_ptr \\<^sub>r children" + shows "shadow_root_ptr |\| shadow_root_ptr_kinds h" + using assms + by(auto simp add: get_mode_def get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ptr_in_heap dest: is_OK_returns_result_I) + +lemma get_mode_reads: "reads (get_mode_locs element_ptr) (get_mode element_ptr) h h'" + by(simp add: get_mode_def get_mode_locs_def reads_bind_pure reads_insert_writes_set_right) +end + +interpretation i_get_mode?: l_get_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_mode get_mode_locs type_wf + using instances + by (auto simp add: l_get_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def) +declare l_get_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +locale l_get_mode = l_type_wf + l_get_mode_defs + + assumes get_mode_reads: "reads (get_mode_locs shadow_root_ptr) (get_mode shadow_root_ptr) h h'" + assumes get_mode_ok: + "type_wf h \ shadow_root_ptr |\| shadow_root_ptr_kinds h \ h \ ok (get_mode shadow_root_ptr)" + assumes get_mode_ptr_in_heap: + "h \ ok (get_mode shadow_root_ptr) \ shadow_root_ptr |\| shadow_root_ptr_kinds h" + assumes get_mode_pure [simp]: "pure (get_mode shadow_root_ptr) h" + +lemma get_mode_is_l_get_mode [instances]: "l_get_mode type_wf get_mode get_mode_locs" + apply(auto simp add: l_get_mode_def instances)[1] + using get_mode_reads apply blast + using get_mode_ok apply blast + using get_mode_ptr_in_heap apply blast + done + +subsubsection \get\_shadow\_root\_safe\ + +locale l_get_shadow_root_safe\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs = + l_get_shadow_root_defs get_shadow_root get_shadow_root_locs + + l_get_mode_defs get_mode get_mode_locs + for get_shadow_root :: "(_) element_ptr \ (_, (_) shadow_root_ptr option) dom_prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_mode :: "(_) shadow_root_ptr \ (_, shadow_root_mode) dom_prog" + and get_mode_locs :: "(_) shadow_root_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +definition a_get_shadow_root_safe :: "(_) element_ptr \ (_, (_) shadow_root_ptr option) dom_prog" + where + "a_get_shadow_root_safe element_ptr = do { + shadow_root_ptr_opt \ get_shadow_root element_ptr; + (case shadow_root_ptr_opt of + Some shadow_root_ptr \ do { + mode \ get_mode shadow_root_ptr; + (if mode = Open then + return (Some shadow_root_ptr) + else + return None + ) + } | None \ return None) + }" + +definition a_get_shadow_root_safe_locs + :: "(_) element_ptr \ (_) shadow_root_ptr \ ((_) heap \ (_) heap \ bool) set" where + "a_get_shadow_root_safe_locs element_ptr shadow_root_ptr \ + (get_shadow_root_locs element_ptr) \ (get_mode_locs shadow_root_ptr)" +end + +global_interpretation l_get_shadow_root_safe\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_shadow_root get_shadow_root_locs + get_mode get_mode_locs + defines get_shadow_root_safe = a_get_shadow_root_safe + and get_shadow_root_safe_locs = a_get_shadow_root_safe_locs + . + +locale l_get_shadow_root_safe_defs = + fixes get_shadow_root_safe :: "(_) element_ptr \ (_, (_) shadow_root_ptr option) dom_prog" + fixes get_shadow_root_safe_locs :: + "(_) element_ptr \ (_) shadow_root_ptr \ ((_) heap \ (_) heap \ bool) set" + +locale l_get_shadow_root_safe\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_shadow_root_safe\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_shadow_root get_shadow_root_locs get_mode get_mode_locs + + l_get_shadow_root_safe_defs get_shadow_root_safe get_shadow_root_safe_locs + + l_get_shadow_root type_wf get_shadow_root get_shadow_root_locs + + l_get_mode type_wf get_mode get_mode_locs + + l_type_wf type_wf + for type_wf :: "(_) heap \ bool" + and get_shadow_root_safe :: + "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_safe_locs :: + "(_) element_ptr \ (_) shadow_root_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_shadow_root :: "(_) element_ptr \ (_, (_) shadow_root_ptr option) dom_prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_mode :: "(_) shadow_root_ptr \ (_, shadow_root_mode) dom_prog" + and get_mode_locs :: "(_) shadow_root_ptr \ ((_) heap \ (_) heap \ bool) set" + + assumes type_wf_impl: "type_wf = ShadowRootClass.type_wf" + assumes get_shadow_root_safe_impl: "get_shadow_root_safe = a_get_shadow_root_safe" + assumes get_shadow_root_safe_locs_impl: "get_shadow_root_safe_locs = a_get_shadow_root_safe_locs" +begin +lemmas get_shadow_root_safe_def = + get_shadow_root_safe_impl[unfolded get_shadow_root_safe_def a_get_shadow_root_safe_def] +lemmas get_shadow_root_safe_locs_def = + get_shadow_root_safe_locs_impl[unfolded get_shadow_root_safe_locs_def a_get_shadow_root_safe_locs_def] + +lemma get_shadow_root_safe_pure [simp]: "pure (get_shadow_root_safe element_ptr) h" + apply(auto simp add: get_shadow_root_safe_def)[1] + by (smt bind_returns_heap_E is_OK_returns_heap_E local.get_mode_pure local.get_shadow_root_pure + option.case_eq_if pure_def pure_returns_heap_eq return_pure) +end + +interpretation i_get_shadow_root_safe?: l_get_shadow_root_safe\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_shadow_root_safe + get_shadow_root_safe_locs get_shadow_root get_shadow_root_locs get_mode get_mode_locs + using instances + by (auto simp add: l_get_shadow_root_safe\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_get_shadow_root_safe\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def + get_shadow_root_safe_def get_shadow_root_safe_locs_def) +declare l_get_shadow_root_safe\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +locale l_get_shadow_root_safe = l_get_shadow_root_safe_defs + + assumes get_shadow_root_safe_pure [simp]: "pure (get_shadow_root_safe element_ptr) h" + +lemma get_shadow_root_safe_is_l_get_shadow_root_safe [instances]: + "l_get_shadow_root_safe get_shadow_root_safe" + using instances + apply(auto simp add: l_get_shadow_root_safe_def)[1] + done + +subsubsection \set\_disconnected\_nodes\ + +locale l_set_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + CD: l_set_disconnected_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M set_disconnected_nodes set_disconnected_nodes_locs + + l_type_wf type_wf + for type_wf :: "(_) heap \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and set_disconnected_nodes :: + "(_) document_ptr \ (_) node_ptr list \ ((_) heap, exception, unit) prog" + and set_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap, exception, unit) prog set" + + assumes type_wf_impl: "type_wf = ShadowRootClass.type_wf" +begin +lemma set_disconnected_nodes_ok: + "type_wf h \ document_ptr |\| document_ptr_kinds h \ + h \ ok (set_disconnected_nodes document_ptr node_ptrs)" + using CD.set_disconnected_nodes_ok CD.type_wf_impl ShadowRootClass.type_wf_defs local.type_wf_impl + by blast + +lemma set_disconnected_nodes_typess_preserved: + assumes "w \ set_disconnected_nodes_locs object_ptr" + assumes "h \ w \\<^sub>h h'" + shows "type_wf h = type_wf h'" + using assms(1) type_wf_preserved[OF writes_singleton2 assms(2)] + apply(unfold type_wf_impl) + by(auto simp add: all_args_def CD.set_disconnected_nodes_locs_def split: if_splits) +end + +interpretation i_set_disconnected_nodes?: l_set_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf + DocumentClass.type_wf set_disconnected_nodes set_disconnected_nodes_locs + by(auto simp add: l_set_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def + l_set_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def instances) +declare l_set_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma set_disconnected_nodes_is_l_set_disconnected_nodes [instances]: + "l_set_disconnected_nodes type_wf set_disconnected_nodes set_disconnected_nodes_locs" + apply(auto simp add: l_set_disconnected_nodes_def)[1] + apply (simp add: i_set_disconnected_nodes.set_disconnected_nodes_writes) + using set_disconnected_nodes_ok apply blast + apply (simp add: i_set_disconnected_nodes.set_disconnected_nodes_ptr_in_heap) + using i_set_disconnected_nodes.set_disconnected_nodes_pointers_preserved apply (blast, blast) + using set_disconnected_nodes_typess_preserved apply(blast, blast) + done + + +paragraph \get\_child\_nodes\ + +locale l_set_disconnected_nodes_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_disconnected_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M set_disconnected_nodes set_disconnected_nodes_locs + + l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes + get_child_nodes_locs get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + for type_wf :: "(_) heap \ bool" + and set_disconnected_nodes :: "(_) document_ptr \ (_) node_ptr list \ ((_) heap, exception, unit) + prog" + and set_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap, exception, unit) prog set" + and known_ptr :: "(_) object_ptr \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ bool" + and get_child_nodes :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" +begin + +lemma set_disconnected_nodes_get_child_nodes: + "\w \ set_disconnected_nodes_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_child_nodes_locs ptr'. r h h'))" + by(auto simp add: set_disconnected_nodes_locs_def get_child_nodes_locs_def + CD.get_child_nodes_locs_def all_args_def) +end + +interpretation i_set_disconnected_nodes_get_child_nodes?: + l_set_disconnected_nodes_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf set_disconnected_nodes + set_disconnected_nodes_locs known_ptr DocumentClass.type_wf DocumentClass.known_ptr get_child_nodes + get_child_nodes_locs Core_DOM_Functions.get_child_nodes Core_DOM_Functions.get_child_nodes_locs + by(auto simp add: l_set_disconnected_nodes_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_set_disconnected_nodes_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma set_disconnected_nodes_get_child_nodes_is_l_set_disconnected_nodes_get_child_nodes [instances]: + "l_set_disconnected_nodes_get_child_nodes set_disconnected_nodes_locs get_child_nodes_locs" + apply(auto simp add: l_set_disconnected_nodes_get_child_nodes_def)[1] + using set_disconnected_nodes_get_child_nodes apply fast + done + + +paragraph \get\_host\ + +locale l_set_disconnected_nodes_get_host\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_host\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_disconnected_nodes_get_host: + "\w \ set_disconnected_nodes_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_host_locs. r h h'))" + by(auto simp add: CD.set_disconnected_nodes_locs_def get_shadow_root_locs_def get_host_locs_def all_args_def) +end + +interpretation i_set_disconnected_nodes_get_host?: l_set_disconnected_nodes_get_host\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf + DocumentClass.type_wf set_disconnected_nodes set_disconnected_nodes_locs get_shadow_root + get_shadow_root_locs get_host get_host_locs + by(auto simp add: l_set_disconnected_nodes_get_host\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_set_disconnected_nodes_get_host\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +locale l_set_disconnected_nodes_get_host = l_set_disconnected_nodes_defs + l_get_host_defs + + assumes set_disconnected_nodes_get_host: + "\w \ set_disconnected_nodes_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_host_locs. r h h'))" + +lemma set_disconnected_nodes_get_host_is_l_set_disconnected_nodes_get_host [instances]: + "l_set_disconnected_nodes_get_host set_disconnected_nodes_locs get_host_locs" + apply(auto simp add: l_set_disconnected_nodes_get_host_def instances)[1] + using set_disconnected_nodes_get_host + by fast + + + +subsubsection \get\_tag\_name\ + +locale l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + CD: l_get_tag_name\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_tag_name get_tag_name_locs + + l_type_wf type_wf + for type_wf :: "(_) heap \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and get_tag_name :: "(_) element_ptr \ (_, tag_name) dom_prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + + assumes type_wf_impl: "type_wf = ShadowRootClass.type_wf" +begin + +lemma get_tag_name_ok: + "type_wf h \ element_ptr |\| element_ptr_kinds h \ h \ ok (get_tag_name element_ptr)" + apply(unfold type_wf_impl get_tag_name_impl[unfolded a_get_tag_name_def]) + using CD.get_tag_name_ok CD.type_wf_impl ShadowRootClass.type_wf\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t + by blast +end + +interpretation i_get_tag_name?: l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf DocumentClass.type_wf get_tag_name + get_tag_name_locs + by(auto simp add: l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def instances) +declare l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma get_tag_name_is_l_get_tag_name [instances]: "l_get_tag_name type_wf get_tag_name + get_tag_name_locs" + apply(auto simp add: l_get_tag_name_def)[1] + using get_tag_name_reads apply fast + using get_tag_name_ok apply fast + done + + +paragraph \set\_disconnected\_nodes\ + +locale l_set_disconnected_nodes_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_disconnected_nodes_get_tag_name: + "\w \ set_disconnected_nodes_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_tag_name_locs ptr'. r h h'))" + by(auto simp add: CD.set_disconnected_nodes_locs_def CD.get_tag_name_locs_def all_args_def) +end + +interpretation i_set_disconnected_nodes_get_tag_name?: l_set_disconnected_nodes_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + type_wf DocumentClass.type_wf set_disconnected_nodes set_disconnected_nodes_locs get_tag_name + get_tag_name_locs + by(auto simp add: l_set_disconnected_nodes_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_set_disconnected_nodes_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma set_disconnected_nodes_get_tag_name_is_l_set_disconnected_nodes_get_tag_name [instances]: + "l_set_disconnected_nodes_get_tag_name type_wf set_disconnected_nodes set_disconnected_nodes_locs + get_tag_name get_tag_name_locs" + apply(auto simp add: l_set_disconnected_nodes_get_tag_name_def + l_set_disconnected_nodes_get_tag_name_axioms_def instances)[1] + using set_disconnected_nodes_get_tag_name + by fast + + +paragraph \set\_child\_nodes\ + +locale l_set_child_nodes_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_child_nodes_get_tag_name: + "\w \ set_child_nodes_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_tag_name_locs ptr'. r h h'))" + by(auto simp add: CD.set_child_nodes_locs_def set_child_nodes_locs_def CD.get_tag_name_locs_def + all_args_def + intro: element_put_get_preserved[where getter=tag_name and + setter=RElement.child_nodes_update]) +end + +interpretation i_set_child_nodes_get_tag_name?: l_set_child_nodes_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf + known_ptr DocumentClass.type_wf DocumentClass.known_ptr set_child_nodes set_child_nodes_locs + Core_DOM_Functions.set_child_nodes Core_DOM_Functions.set_child_nodes_locs get_tag_name + get_tag_name_locs + by(auto simp add: l_set_child_nodes_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_set_child_nodes_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma set_child_nodes_get_tag_name_is_l_set_child_nodes_get_tag_name [instances]: + "l_set_child_nodes_get_tag_name type_wf set_child_nodes set_child_nodes_locs get_tag_name + get_tag_name_locs" + apply(auto simp add: l_set_child_nodes_get_tag_name_def l_set_child_nodes_get_tag_name_axioms_def + instances)[1] + using set_child_nodes_get_tag_name + by fast + + +paragraph \delete\_shadow\_root\ + +locale l_delete_shadow_root_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma get_tag_name_delete_shadow_root: "h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h' + \ r \ get_tag_name_locs ptr' \ r h h'" + by(auto simp add: CD.get_tag_name_locs_def delete_shadow_root_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t) +end + +locale l_delete_shadow_root_get_tag_name = l_get_tag_name_defs + + assumes get_tag_name_delete_shadow_root: "h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h' + \ r \ get_tag_name_locs ptr' \ r h h'" +interpretation l_delete_shadow_root_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf DocumentClass.type_wf get_tag_name + get_tag_name_locs + by(auto simp add: l_delete_shadow_root_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) + +lemma l_delete_shadow_root_get_tag_name_get_tag_name_locs [instances]: "l_delete_shadow_root_get_tag_name get_tag_name_locs" + apply(auto simp add: l_delete_shadow_root_get_tag_name_def)[1] + using get_tag_name_delete_shadow_root apply fast + done + + +paragraph \set\_shadow\_root\ + +locale l_set_shadow_root_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_shadow_root_get_tag_name: + "\w \ set_shadow_root_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_tag_name_locs ptr'. r h h'))" + by(auto simp add: set_shadow_root_locs_def CD.get_tag_name_locs_def all_args_def + element_put_get_preserved[where setter=shadow_root_opt_update]) +end + +interpretation i_set_shadow_root_get_tag_name?: l_set_shadow_root_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf + set_shadow_root set_shadow_root_locs DocumentClass.type_wf get_tag_name get_tag_name_locs + apply(auto simp add: l_set_shadow_root_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances)[1] + by(unfold_locales) +declare l_set_shadow_root_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +locale l_set_shadow_root_get_tag_name = l_set_shadow_root_defs + l_get_tag_name_defs + + assumes set_shadow_root_get_tag_name: + "\w \ set_shadow_root_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_tag_name_locs ptr'. r h h'))" + +lemma set_shadow_root_get_tag_name_is_l_set_shadow_root_get_tag_name [instances]: + "l_set_shadow_root_get_tag_name set_shadow_root_locs get_tag_name_locs" + using set_shadow_root_is_l_set_shadow_root get_tag_name_is_l_get_tag_name + apply(simp add: l_set_shadow_root_get_tag_name_def ) + using set_shadow_root_get_tag_name + by fast + +paragraph \new\_element\ + +locale l_new_element_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_tag_name get_tag_name_locs + for type_wf :: "(_) heap \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and get_tag_name :: "(_) element_ptr \ (_, tag_name) dom_prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +lemma get_tag_name_new_element: + "ptr' \ new_element_ptr \ h \ new_element \\<^sub>r new_element_ptr \ h \ new_element \\<^sub>h h' + \ r \ get_tag_name_locs ptr' \ r h h'" + by (auto simp add: CD.get_tag_name_locs_def new_element_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t new_element_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t + new_element_get_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t split: prod.splits if_splits option.splits + elim!: bind_returns_result_E bind_returns_heap_E intro: is_element_ptr_kind_obtains) + +lemma new_element_empty_tag_name: + "h \ new_element \\<^sub>r new_element_ptr \ h \ new_element \\<^sub>h h' + \ h' \ get_tag_name new_element_ptr \\<^sub>r ''''" + by(simp add: CD.get_tag_name_def new_element_tag_name) +end + +locale l_new_element_get_tag_name = l_new_element + l_get_tag_name + + assumes get_tag_name_new_element: + "ptr' \ new_element_ptr \ h \ new_element \\<^sub>r new_element_ptr + \ h \ new_element \\<^sub>h h' \ r \ get_tag_name_locs ptr' \ r h h'" + assumes new_element_empty_tag_name: + "h \ new_element \\<^sub>r new_element_ptr \ h \ new_element \\<^sub>h h' + \ h' \ get_tag_name new_element_ptr \\<^sub>r ''''" + + +interpretation i_new_element_get_tag_name?: + l_new_element_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf DocumentClass.type_wf get_tag_name get_tag_name_locs + by(auto simp add: l_new_element_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_new_element_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma new_element_get_tag_name_is_l_new_element_get_tag_name [instances]: + "l_new_element_get_tag_name type_wf get_tag_name get_tag_name_locs" + using new_element_is_l_new_element get_tag_name_is_l_get_tag_name + apply(auto simp add: l_new_element_get_tag_name_def l_new_element_get_tag_name_axioms_def + instances)[1] + using get_tag_name_new_element new_element_empty_tag_name + by fast+ + +paragraph \get\_shadow\_root\ + +locale l_set_mode_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_mode_get_tag_name: + "\w \ set_mode_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_tag_name_locs ptr'. r h h'))" + by(auto simp add: set_mode_locs_def CD.get_tag_name_locs_def all_args_def) +end + +interpretation + i_set_mode_get_tag_name?: l_set_mode_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf + set_mode set_mode_locs DocumentClass.type_wf get_tag_name + get_tag_name_locs + by unfold_locales +declare l_set_mode_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +locale l_set_mode_get_tag_name = l_set_mode + l_get_tag_name + + assumes set_mode_get_tag_name: + "\w \ set_mode_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_tag_name_locs ptr'. r h h'))" + +lemma set_mode_get_tag_name_is_l_set_mode_get_tag_name [instances]: + "l_set_mode_get_tag_name type_wf set_mode set_mode_locs get_tag_name + get_tag_name_locs" + using set_mode_is_l_set_mode get_tag_name_is_l_get_tag_name + apply(simp add: l_set_mode_get_tag_name_def + l_set_mode_get_tag_name_axioms_def) + using set_mode_get_tag_name + by fast + +paragraph \new\_document\ + +locale l_new_document_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_tag_name get_tag_name_locs + for type_wf :: "(_) heap \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and get_tag_name :: "(_) element_ptr \ ((_) heap, exception, tag_name) prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +lemma get_tag_name_new_document: + "h \ new_document \\<^sub>r new_document_ptr \ h \ new_document \\<^sub>h h' + \ r \ get_tag_name_locs ptr' \ r h h'" + by(auto simp add: CD.get_tag_name_locs_def new_document_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t) +end + +locale l_new_document_get_tag_name = l_get_tag_name_defs + + assumes get_tag_name_new_document: + "h \ new_document \\<^sub>r new_document_ptr \ h \ new_document \\<^sub>h h' + \ r \ get_tag_name_locs ptr' \ r h h'" + +interpretation i_new_document_get_tag_name?: + l_new_document_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf DocumentClass.type_wf get_tag_name + get_tag_name_locs + by unfold_locales +declare l_new_document_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def[instances] + +lemma new_document_get_tag_name_is_l_new_document_get_tag_name [instances]: + "l_new_document_get_tag_name get_tag_name_locs" + unfolding l_new_document_get_tag_name_def + unfolding get_tag_name_locs_def + using new_document_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t by blast + +paragraph \new\_shadow\_root\ + +locale l_new_shadow_root_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma get_tag_name_new_shadow_root: + "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' + \ r \ get_tag_name_locs ptr' \ r h h'" + by (auto simp add: CD.get_tag_name_locs_def new_shadow_root_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t new_shadow_root_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t + split: prod.splits if_splits option.splits + elim!: bind_returns_result_E bind_returns_heap_E intro: is_element_ptr_kind_obtains) +end + +locale l_new_shadow_root_get_tag_name = l_get_tag_name + + assumes get_tag_name_new_shadow_root: + "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr + \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' \ r \ get_tag_name_locs ptr' \ r h h'" + +interpretation i_new_shadow_root_get_tag_name?: + l_new_shadow_root_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf DocumentClass.type_wf get_tag_name get_tag_name_locs + by(unfold_locales) +declare l_new_shadow_root_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma new_shadow_root_get_tag_name_is_l_new_shadow_root_get_tag_name [instances]: + "l_new_shadow_root_get_tag_name type_wf get_tag_name get_tag_name_locs" + using get_tag_name_is_l_get_tag_name + apply(auto simp add: l_new_shadow_root_get_tag_name_def l_new_shadow_root_get_tag_name_axioms_def + instances)[1] + using get_tag_name_new_shadow_root + by fast + +paragraph \new\_character\_data\ + +locale l_new_character_data_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_tag_name get_tag_name_locs + for type_wf :: "(_) heap \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and get_tag_name :: "(_) element_ptr \ ((_) heap, exception, tag_name) prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +lemma get_tag_name_new_character_data: + "h \ new_character_data \\<^sub>r new_character_data_ptr \ h \ new_character_data \\<^sub>h h' + \ r \ get_tag_name_locs ptr' \ r h h'" + by(auto simp add: CD.get_tag_name_locs_def new_character_data_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t) +end + +locale l_new_character_data_get_tag_name = l_get_tag_name_defs + + assumes get_tag_name_new_character_data: + "h \ new_character_data \\<^sub>r new_character_data_ptr \ h \ new_character_data \\<^sub>h h' + \ r \ get_tag_name_locs ptr' \ r h h'" + +interpretation i_new_character_data_get_tag_name?: + l_new_character_data_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf DocumentClass.type_wf get_tag_name + get_tag_name_locs + by unfold_locales +declare l_new_character_data_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def[instances] + +lemma new_character_data_get_tag_name_is_l_new_character_data_get_tag_name [instances]: + "l_new_character_data_get_tag_name get_tag_name_locs" + unfolding l_new_character_data_get_tag_name_def + unfolding get_tag_name_locs_def + using new_character_data_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t by blast + +paragraph \get\_tag\_type\ + +locale l_set_tag_name_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_set_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_tag_name_get_tag_name: + assumes "h \ CD.a_set_tag_name element_ptr tag \\<^sub>h h'" + shows "h' \ CD.a_get_tag_name element_ptr \\<^sub>r tag" + using assms + by(auto simp add: CD.a_get_tag_name_def CD.a_set_tag_name_def) + +lemma set_tag_name_get_tag_name_different_pointers: + assumes "ptr \ ptr'" + assumes "w \ CD.a_set_tag_name_locs ptr" + assumes "h \ w \\<^sub>h h'" + assumes "r \ CD.a_get_tag_name_locs ptr'" + shows "r h h'" + using assms + by(auto simp add: all_args_def CD.a_set_tag_name_locs_def CD.a_get_tag_name_locs_def + split: if_splits option.splits ) +end + +interpretation i_set_tag_name_get_tag_name?: + l_set_tag_name_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf DocumentClass.type_wf get_tag_name + get_tag_name_locs set_tag_name set_tag_name_locs + by unfold_locales +declare l_set_tag_name_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma set_tag_name_get_tag_name_is_l_set_tag_name_get_tag_name [instances]: + "l_set_tag_name_get_tag_name type_wf get_tag_name get_tag_name_locs + set_tag_name set_tag_name_locs" + using set_tag_name_is_l_set_tag_name get_tag_name_is_l_get_tag_name + apply(simp add: l_set_tag_name_get_tag_name_def + l_set_tag_name_get_tag_name_axioms_def) + using set_tag_name_get_tag_name + set_tag_name_get_tag_name_different_pointers + by fast+ + + +subsubsection \attach\_shadow\_root\ + +locale l_attach_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs = + l_set_shadow_root_defs set_shadow_root set_shadow_root_locs + + l_set_mode_defs set_mode set_mode_locs + + l_get_tag_name_defs get_tag_name get_tag_name_locs + + l_get_shadow_root_defs get_shadow_root get_shadow_root_locs + for set_shadow_root :: + "(_) element_ptr \ (_) shadow_root_ptr option \ ((_) heap, exception, unit) prog" + and set_shadow_root_locs :: "(_) element_ptr \ ((_) heap, exception, unit) prog set" + and set_mode :: "(_) shadow_root_ptr \ shadow_root_mode \ ((_) heap, exception, unit) prog" + and set_mode_locs :: "(_) shadow_root_ptr \ ((_) heap, exception, unit) prog set" + and get_tag_name :: "(_) element_ptr \ (_, char list) dom_prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +definition a_attach_shadow_root :: + "(_) element_ptr \ shadow_root_mode \ (_, (_) shadow_root_ptr) dom_prog" + where + "a_attach_shadow_root element_ptr shadow_root_mode = do { + tag \ get_tag_name element_ptr; + (if tag \ safe_shadow_root_element_types then error NotSupportedError else return ()); + prev_shadow_root \ get_shadow_root element_ptr; + (if prev_shadow_root \ None then error NotSupportedError else return ()); + new_shadow_root_ptr \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M; + set_mode new_shadow_root_ptr shadow_root_mode; + set_shadow_root element_ptr (Some new_shadow_root_ptr); + return new_shadow_root_ptr + }" +end + +locale l_attach_shadow_root_defs = + fixes attach_shadow_root :: + "(_) element_ptr \ shadow_root_mode \ (_, (_) shadow_root_ptr) dom_prog" + +global_interpretation l_attach_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs set_shadow_root set_shadow_root_locs + set_mode set_mode_locs get_tag_name get_tag_name_locs get_shadow_root get_shadow_root_locs + defines attach_shadow_root = a_attach_shadow_root + . + +locale l_attach_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_attach_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs set_shadow_root set_shadow_root_locs set_mode set_mode_locs + get_tag_name get_tag_name_locs get_shadow_root get_shadow_root_locs + + l_attach_shadow_root_defs attach_shadow_root + + l_set_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf set_shadow_root set_shadow_root_locs + + l_set_mode type_wf set_mode set_mode_locs + + l_get_tag_name type_wf get_tag_name get_tag_name_locs + + l_get_shadow_root type_wf get_shadow_root get_shadow_root_locs + + l_known_ptr known_ptr + for known_ptr :: "(_) object_ptr \ bool" + and set_shadow_root :: + "(_) element_ptr \ (_) shadow_root_ptr option \ ((_) heap, exception, unit) prog" + and set_shadow_root_locs :: "(_) element_ptr \ ((_) heap, exception, unit) prog set" + and set_mode :: "(_) shadow_root_ptr \ shadow_root_mode \ ((_) heap, exception, unit) prog" + and set_mode_locs :: "(_) shadow_root_ptr \ ((_) heap, exception, unit) prog set" + and attach_shadow_root :: + "(_) element_ptr \ shadow_root_mode \ ((_) heap, exception, (_) shadow_root_ptr) prog" + and type_wf :: "(_) heap \ bool" + and get_tag_name :: "(_) element_ptr \ (_, char list) dom_prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + + assumes known_ptr_impl: "known_ptr = a_known_ptr" + assumes attach_shadow_root_impl: "attach_shadow_root = a_attach_shadow_root" +begin +lemmas attach_shadow_root_def = a_attach_shadow_root_def[folded attach_shadow_root_impl] + +lemma attach_shadow_root_element_ptr_in_heap: + assumes "h \ ok (attach_shadow_root element_ptr shadow_root_mode)" + shows "element_ptr |\| element_ptr_kinds h" +proof - + obtain h' where "h \ attach_shadow_root element_ptr shadow_root_mode \\<^sub>h h'" + using assms by auto + then + obtain h2 h3 new_shadow_root_ptr where + h2: "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h2" and + new_shadow_root_ptr: "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr" and + h3: "h2 \ set_mode new_shadow_root_ptr shadow_root_mode \\<^sub>h h3" and + "h3 \ set_shadow_root element_ptr (Some new_shadow_root_ptr) \\<^sub>h h'" + by(auto simp add: attach_shadow_root_def + elim!: bind_returns_heap_E bind_returns_heap_E2[rotated, OF get_tag_name_pure, rotated] + bind_returns_heap_E2[rotated, OF get_shadow_root_pure, rotated] split: if_splits) + + then have "element_ptr |\| element_ptr_kinds h3" + using set_shadow_root_ptr_in_heap by blast + + moreover + have "object_ptr_kinds h2 = object_ptr_kinds h |\| {|cast new_shadow_root_ptr|}" + using h2 new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_new_ptr new_shadow_root_ptr by auto + + moreover + have "object_ptr_kinds h2 = object_ptr_kinds h3" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h = object_ptr_kinds h'", + OF set_mode_writes h3]) + using set_mode_pointers_preserved + apply blast + by (auto simp add: reflp_def transp_def) + ultimately + show ?thesis + by(auto simp add: element_ptr_kinds_def node_ptr_kinds_def) +qed + +lemma create_shadow_root_known_ptr: + assumes "h \ attach_shadow_root element_ptr shadow_root_mode \\<^sub>r new_shadow_root_ptr" + shows "known_ptr (cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_shadow_root_ptr)" + using assms + by(auto simp add: attach_shadow_root_def known_ptr_impl ShadowRootClass.a_known_ptr_def + new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def Let_def + elim!: bind_returns_result_E) +end + +locale l_attach_shadow_root = l_attach_shadow_root_defs + +interpretation + i_attach_shadow_root?: l_attach_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr set_shadow_root set_shadow_root_locs + set_mode set_mode_locs attach_shadow_root type_wf get_tag_name get_tag_name_locs get_shadow_root + get_shadow_root_locs + by(auto simp add: l_attach_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_attach_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def + attach_shadow_root_def instances) +declare l_attach_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + + +subsubsection \get\_parent\ + +global_interpretation l_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_child_nodes get_child_nodes_locs + defines get_parent = "l_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_get_parent get_child_nodes" + and get_parent_locs = "l_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_get_parent_locs get_child_nodes_locs" + . + +interpretation i_get_parent?: l_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr type_wf get_child_nodes + get_child_nodes_locs known_ptrs get_parent get_parent_locs + by(simp add: l_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def get_parent_def + get_parent_locs_def instances) +declare l_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma get_parent_is_l_get_parent [instances]: "l_get_parent type_wf known_ptr known_ptrs get_parent + get_parent_locs get_child_nodes get_child_nodes_locs" + apply(simp add: l_get_parent_def l_get_parent_axioms_def instances) + using get_parent_reads get_parent_ok get_parent_ptr_in_heap get_parent_pure + get_parent_parent_in_heap get_parent_child_dual get_parent_reads_pointers + by blast + + + +paragraph \set\_disconnected\_nodes\ + +locale l_set_disconnected_nodes_get_parent\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_disconnected_nodes_get_child_nodes + + l_set_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_disconnected_nodes_get_parent [simp]: + "\w \ set_disconnected_nodes_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_parent_locs. r h h'))" + by(auto simp add: get_parent_locs_def CD.set_disconnected_nodes_locs_def all_args_def) +end +interpretation i_set_disconnected_nodes_get_parent?: l_set_disconnected_nodes_get_parent\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + set_disconnected_nodes set_disconnected_nodes_locs get_child_nodes get_child_nodes_locs type_wf + DocumentClass.type_wf known_ptr known_ptrs get_parent get_parent_locs + by (simp add: l_set_disconnected_nodes_get_parent\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_set_disconnected_nodes_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma set_disconnected_nodes_get_parent_is_l_set_disconnected_nodes_get_parent [instances]: + "l_set_disconnected_nodes_get_parent set_disconnected_nodes_locs get_parent_locs" + by(simp add: l_set_disconnected_nodes_get_parent_def) + + + +subsubsection \get\_root\_node\ + +global_interpretation l_get_root_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_parent get_parent_locs + defines get_root_node = "l_get_root_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_get_root_node get_parent" + and get_root_node_locs = "l_get_root_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_get_root_node_locs get_parent_locs" + and get_ancestors = "l_get_root_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_get_ancestors get_parent" + and get_ancestors_locs = "l_get_root_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_get_ancestors_locs get_parent_locs" + . +declare a_get_ancestors.simps [code] + +interpretation i_get_root_node?: l_get_root_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr known_ptrs get_parent + get_parent_locs get_child_nodes get_child_nodes_locs get_ancestors get_ancestors_locs + get_root_node get_root_node_locs + by(simp add: l_get_root_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_get_root_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def get_root_node_def + get_root_node_locs_def get_ancestors_def get_ancestors_locs_def instances) +declare l_get_root_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma get_ancestors_is_l_get_ancestors [instances]: "l_get_ancestors get_ancestors" + apply(auto simp add: l_get_ancestors_def)[1] + using get_ancestors_ptr_in_heap apply fast + using get_ancestors_ptr apply fast + done + +lemma get_root_node_is_l_get_root_node [instances]: "l_get_root_node get_root_node get_parent" + by (simp add: l_get_root_node_def Shadow_DOM.i_get_root_node.get_root_node_no_parent) + + + +subsubsection \get\_root\_node\_si\ + +locale l_get_root_node_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs = + l_get_parent_defs get_parent get_parent_locs + + l_get_host_defs get_host get_host_locs + for get_parent :: "(_) node_ptr \ ((_) heap, exception, (_::linorder) object_ptr option) prog" + and get_parent_locs :: "((_) heap \ (_) heap \ bool) set" + and get_host :: "(_) shadow_root_ptr \ ((_) heap, exception, (_) element_ptr) prog" + and get_host_locs :: "((_) heap \ (_) heap \ bool) set" +begin +partial_function (dom_prog) a_get_ancestors_si :: + "(_::linorder) object_ptr \ (_, (_) object_ptr list) dom_prog" + where + "a_get_ancestors_si ptr = do { + check_in_heap ptr; + ancestors \ (case cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr of + Some node_ptr \ do { + parent_ptr_opt \ get_parent node_ptr; + (case parent_ptr_opt of + Some parent_ptr \ a_get_ancestors_si parent_ptr + | None \ return []) + } + | None \ (case cast ptr of + Some shadow_root_ptr \ do { + host \ get_host shadow_root_ptr; + a_get_ancestors_si (cast host) + } | + None \ return [])); + return (ptr # ancestors) + }" + +definition "a_get_ancestors_si_locs = get_parent_locs \ get_host_locs" + +definition a_get_root_node_si :: "(_) object_ptr \ (_, (_) object_ptr) dom_prog" + where + "a_get_root_node_si ptr = do { + ancestors \ a_get_ancestors_si ptr; + return (last ancestors) + }" +definition "a_get_root_node_si_locs = a_get_ancestors_si_locs" +end + +locale l_get_ancestors_si_defs = + fixes get_ancestors_si :: "(_::linorder) object_ptr \ (_, (_) object_ptr list) dom_prog" + fixes get_ancestors_si_locs :: "((_) heap \ (_) heap \ bool) set" + +locale l_get_root_node_si_defs = + fixes get_root_node_si :: "(_) object_ptr \ (_, (_) object_ptr) dom_prog" + fixes get_root_node_si_locs :: "((_) heap \ (_) heap \ bool) set" + +locale l_get_root_node_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_parent + + l_get_host + + l_get_root_node_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + + l_get_ancestors_si_defs + + l_get_root_node_si_defs + + assumes get_ancestors_si_impl: "get_ancestors_si = a_get_ancestors_si" + assumes get_ancestors_si_locs_impl: "get_ancestors_si_locs = a_get_ancestors_si_locs" + assumes get_root_node_si_impl: "get_root_node_si = a_get_root_node_si" + assumes get_root_node_si_locs_impl: "get_root_node_si_locs = a_get_root_node_si_locs" +begin +lemmas get_ancestors_si_def = a_get_ancestors_si.simps[folded get_ancestors_si_impl] +lemmas get_ancestors_si_locs_def = a_get_ancestors_si_locs_def[folded get_ancestors_si_locs_impl] +lemmas get_root_node_si_def = + a_get_root_node_si_def[folded get_root_node_si_impl get_ancestors_si_impl] +lemmas get_root_node_si_locs_def = + a_get_root_node_si_locs_def[folded get_root_node_si_locs_impl get_ancestors_si_locs_impl] + +lemma get_ancestors_si_pure [simp]: + "pure (get_ancestors_si ptr) h" +proof - + have "\ptr h h' x. h \ get_ancestors_si ptr \\<^sub>r x \ h \ get_ancestors_si ptr \\<^sub>h h' \ h = h'" + proof (induct rule: a_get_ancestors_si.fixp_induct[folded get_ancestors_si_impl]) + case 1 + then show ?case + by(rule admissible_dom_prog) + next + case 2 + then show ?case + by simp + next + case (3 f) + then show ?case + using get_parent_pure get_host_pure + apply(auto simp add: pure_returns_heap_eq pure_def + split: option.splits + elim!: bind_returns_heap_E bind_returns_result_E + dest!: pure_returns_heap_eq[rotated, OF check_in_heap_pure])[1] + apply (meson option.simps(3) returns_result_eq) + apply(metis get_parent_pure pure_returns_heap_eq) + apply(metis get_host_pure pure_returns_heap_eq) + done + qed + then show ?thesis + by (meson pure_eq_iff) +qed + + +lemma get_root_node_si_pure [simp]: "pure (get_root_node_si ptr) h" + by(auto simp add: get_root_node_si_def bind_pure_I) + + +lemma get_ancestors_si_ptr_in_heap: + assumes "h \ ok (get_ancestors_si ptr)" + shows "ptr |\| object_ptr_kinds h" + using assms + by(auto simp add: get_ancestors_si_def check_in_heap_ptr_in_heap elim!: bind_is_OK_E + dest: is_OK_returns_result_I) + +lemma get_ancestors_si_ptr: + assumes "h \ get_ancestors_si ptr \\<^sub>r ancestors" + shows "ptr \ set ancestors" + using assms + by(simp add: get_ancestors_si_def) + (auto elim!: bind_returns_result_E2 + split: option.splits + intro!: bind_pure_I) + + +lemma get_ancestors_si_never_empty: + assumes "h \ get_ancestors_si child \\<^sub>r ancestors" + shows "ancestors \ []" + using assms + apply(simp add: get_ancestors_si_def) + by(auto elim!: bind_returns_result_E2 split: option.splits) + +lemma get_root_node_si_no_parent: + "h \ get_parent node_ptr \\<^sub>r None \ h \ get_root_node_si (cast node_ptr) \\<^sub>r cast node_ptr" + apply(auto simp add: check_in_heap_def get_root_node_si_def get_ancestors_si_def + intro!: bind_pure_returns_result_I )[1] + using get_parent_ptr_in_heap by blast + + +lemma get_root_node_si_root_not_shadow_root: + assumes "h \ get_root_node_si ptr \\<^sub>r root" + shows "\ is_shadow_root_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r root" + using assms +proof(auto simp add: get_root_node_si_def elim!: bind_returns_result_E2) + fix y + assume "h \ get_ancestors_si ptr \\<^sub>r y" + and "is_shadow_root_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r (last y)" + and "root = last y" + then + show False + proof(induct y arbitrary: ptr) + case Nil + then show ?case + using assms(1) get_ancestors_si_never_empty by blast + next + case (Cons a x) + then show ?case + apply(auto simp add: get_ancestors_si_def[of ptr] + elim!: bind_returns_result_E2 + split: option.splits if_splits)[1] + using get_ancestors_si_never_empty apply blast + using Cons.prems(2) apply auto[1] + using \is_shadow_root_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r (last y)\ \root = last y\ by auto + qed +qed +end + +global_interpretation l_get_root_node_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_parent get_parent_locs get_host get_host_locs + defines get_root_node_si = a_get_root_node_si + and get_root_node_si_locs = a_get_root_node_si_locs + and get_ancestors_si = a_get_ancestors_si + and get_ancestors_si_locs = a_get_ancestors_si_locs + . +declare a_get_ancestors_si.simps [code] + +interpretation i_get_root_node_si?: l_get_root_node_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr known_ptrs + get_parent get_parent_locs get_child_nodes get_child_nodes_locs get_host get_host_locs + get_ancestors_si get_ancestors_si_locs get_root_node_si get_root_node_si_locs + apply(auto simp add: l_get_root_node_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_get_root_node_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def + instances)[1] + by(auto simp add: get_root_node_si_def get_root_node_si_locs_def get_ancestors_si_def + get_ancestors_si_locs_def) +declare l_get_root_node_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma get_ancestors_si_is_l_get_ancestors [instances]: "l_get_ancestors get_ancestors_si" + unfolding l_get_ancestors_def + using get_ancestors_si_pure get_ancestors_si_ptr get_ancestors_si_ptr_in_heap + by blast + +lemma get_root_node_si_is_l_get_root_node [instances]: "l_get_root_node get_root_node_si get_parent" + apply(simp add: l_get_root_node_def) + using get_root_node_si_no_parent + by fast + + +paragraph \set\_disconnected\_nodes\ + + +locale l_set_disconnected_nodes_get_ancestors_si\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_disconnected_nodes_get_parent + + l_get_root_node_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_set_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_set_disconnected_nodes_get_host +begin +lemma set_disconnected_nodes_get_ancestors_si: + "\w \ set_disconnected_nodes_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_ancestors_si_locs. r h h'))" + by(auto simp add: get_parent_locs_def set_disconnected_nodes_locs_def + set_disconnected_nodes_get_host get_ancestors_si_locs_def all_args_def) +end + +locale l_set_disconnected_nodes_get_ancestors_si = + l_set_disconnected_nodes_defs + + l_get_ancestors_si_defs + + assumes set_disconnected_nodes_get_ancestors_si: + "\w \ set_disconnected_nodes_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_ancestors_si_locs. r h h'))" + +interpretation i_set_disconnected_nodes_get_ancestors_si?: + l_set_disconnected_nodes_get_ancestors_si\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M set_disconnected_nodes set_disconnected_nodes_locs + get_parent get_parent_locs type_wf known_ptr known_ptrs get_child_nodes get_child_nodes_locs + get_host get_host_locs get_ancestors_si get_ancestors_si_locs get_root_node_si + get_root_node_si_locs DocumentClass.type_wf + + by (auto simp add: l_set_disconnected_nodes_get_ancestors_si\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_set_disconnected_nodes_get_ancestors_si\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + + +lemma set_disconnected_nodes_get_ancestors_si_is_l_set_disconnected_nodes_get_ancestors_si [instances]: + "l_set_disconnected_nodes_get_ancestors_si set_disconnected_nodes_locs get_ancestors_si_locs" + using instances + apply(simp add: l_set_disconnected_nodes_get_ancestors_si_def) + using set_disconnected_nodes_get_ancestors_si + by fast + + + +subsubsection \get\_attribute\ + +lemma get_attribute_is_l_get_attribute [instances]: + "l_get_attribute type_wf get_attribute get_attribute_locs" + apply(auto simp add: l_get_attribute_def)[1] + using i_get_attribute.get_attribute_reads apply fast + using type_wf\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t i_get_attribute.get_attribute_ok apply blast + using i_get_attribute.get_attribute_ptr_in_heap apply fast + done + + + +subsubsection \to\_tree\_order\ + +global_interpretation l_to_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_child_nodes get_child_nodes_locs defines + to_tree_order = "l_to_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_to_tree_order get_child_nodes" . +declare a_to_tree_order.simps [code] + +interpretation i_to_tree_order?: l_to_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M ShadowRootClass.known_ptr + ShadowRootClass.type_wf Shadow_DOM.get_child_nodes Shadow_DOM.get_child_nodes_locs to_tree_order + by(auto simp add: l_to_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_to_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def to_tree_order_def + instances) +declare l_to_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + + +subsubsection \to\_tree\_order\_si\ + + +locale l_to_tree_order_si\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs = + l_get_child_nodes_defs get_child_nodes get_child_nodes_locs + + l_get_shadow_root_defs get_shadow_root get_shadow_root_locs + for get_child_nodes :: "(_::linorder) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +partial_function (dom_prog) a_to_tree_order_si :: "(_) object_ptr \ (_, (_) object_ptr list) dom_prog" + where + "a_to_tree_order_si ptr = (do { + children \ get_child_nodes ptr; + shadow_root_part \ (case cast ptr of + Some element_ptr \ do { + shadow_root_opt \ get_shadow_root element_ptr; + (case shadow_root_opt of + Some shadow_root_ptr \ return [cast shadow_root_ptr] + | None \ return []) + } | + None \ return []); + treeorders \ map_M a_to_tree_order_si ((map (cast) children) @ shadow_root_part); + return (ptr # concat treeorders) + })" +end + +locale l_to_tree_order_si_defs = + fixes to_tree_order_si :: "(_) object_ptr \ (_, (_) object_ptr list) dom_prog" + +global_interpretation l_to_tree_order_si\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_child_nodes get_child_nodes_locs + get_shadow_root get_shadow_root_locs + defines to_tree_order_si = "a_to_tree_order_si" . +declare a_to_tree_order_si.simps [code] + + +locale l_to_tree_order_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_to_tree_order_si_defs + + l_to_tree_order_si\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + + l_get_child_nodes + + l_get_shadow_root + + assumes to_tree_order_si_impl: "to_tree_order_si = a_to_tree_order_si" +begin +lemmas to_tree_order_si_def = a_to_tree_order_si.simps[folded to_tree_order_si_impl] + +lemma to_tree_order_si_pure [simp]: "pure (to_tree_order_si ptr) h" +proof - + have "\ptr h h' x. h \ to_tree_order_si ptr \\<^sub>r x \ h \ to_tree_order_si ptr \\<^sub>h h' \ h = h'" + proof (induct rule: a_to_tree_order_si.fixp_induct[folded to_tree_order_si_impl]) + case 1 + then show ?case + by (rule admissible_dom_prog) + next + case 2 + then show ?case + by simp + next + case (3 f) + then have "\x h. pure (f x) h" + by (metis is_OK_returns_heap_E is_OK_returns_result_E pure_def) + then have "\xs h. pure (map_M f xs) h" + by(rule map_M_pure_I) + then show ?case + by(auto elim!: bind_returns_heap_E2 split: option.splits) + qed + then show ?thesis + unfolding pure_def + by (metis is_OK_returns_heap_E is_OK_returns_result_E) +qed +end + +interpretation i_to_tree_order_si?: l_to_tree_order_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M to_tree_order_si get_child_nodes + get_child_nodes_locs get_shadow_root get_shadow_root_locs type_wf known_ptr + by(auto simp add: l_to_tree_order_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_to_tree_order_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def + to_tree_order_si_def instances) +declare l_to_tree_order_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsubsection \first\_in\_tree\_order\ + +global_interpretation l_first_in_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs to_tree_order defines + first_in_tree_order = "l_first_in_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_first_in_tree_order to_tree_order" . + +interpretation i_first_in_tree_order?: l_first_in_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M to_tree_order first_in_tree_order + by(auto simp add: l_first_in_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def first_in_tree_order_def) +declare l_first_in_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma to_tree_order_is_l_to_tree_order [instances]: "l_to_tree_order to_tree_order" + by(auto simp add: l_to_tree_order_def) + + + +subsubsection \first\_in\_tree\_order\ + +global_interpretation l_dummy defines + first_in_tree_order_si = "l_first_in_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_first_in_tree_order to_tree_order_si" + . + + +subsubsection \get\_element\_by\ + +global_interpretation l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs to_tree_order first_in_tree_order get_attribute + get_attribute_locs + defines + get_element_by_id = + "l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_get_element_by_id first_in_tree_order get_attribute" and + get_elements_by_class_name = + "l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_get_elements_by_class_name to_tree_order get_attribute" and + get_elements_by_tag_name = + "l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_get_elements_by_tag_name to_tree_order" . + +interpretation i_get_element_by?: l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M to_tree_order first_in_tree_order + get_attribute get_attribute_locs get_element_by_id get_elements_by_class_name + get_elements_by_tag_name type_wf + by(auto simp add: l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def + get_element_by_id_def get_elements_by_class_name_def get_elements_by_tag_name_def + instances) +declare l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + + +lemma get_element_by_is_l_get_element_by [instances]: + "l_get_element_by get_element_by_id get_elements_by_tag_name to_tree_order" + apply(auto simp add: l_get_element_by_def)[1] + using get_element_by_id_result_in_tree_order apply fast + done + + +subsubsection \get\_element\_by\_si\ + +global_interpretation l_dummy defines + get_element_by_id_si = + "l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_get_element_by_id first_in_tree_order_si get_attribute" and + get_elements_by_class_name_si = + "l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_get_elements_by_class_name to_tree_order_si get_attribute" and + get_elements_by_tag_name_si = + "l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_get_elements_by_tag_name to_tree_order_si" + . + + + +subsubsection \find\_slot\ + +locale l_find_slot\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs = + l_get_parent_defs get_parent get_parent_locs + + l_get_shadow_root_defs get_shadow_root get_shadow_root_locs + + l_get_mode_defs get_mode get_mode_locs + + l_get_attribute_defs get_attribute get_attribute_locs + + l_get_tag_name_defs get_tag_name get_tag_name_locs + + l_first_in_tree_order_defs first_in_tree_order + for get_parent :: "(_) node_ptr \ ((_) heap, exception, (_::linorder) object_ptr option) prog" + and get_parent_locs :: "((_) heap \ (_) heap \ bool) set" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_mode :: "(_) shadow_root_ptr \ ((_) heap, exception, shadow_root_mode) prog" + and get_mode_locs :: "(_) shadow_root_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_attribute :: "(_) element_ptr \ char list \ ((_) heap, exception, char list option) prog" + and get_attribute_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_tag_name :: "(_) element_ptr \ ((_) heap, exception, char list) prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and first_in_tree_order :: + "(_) object_ptr \ ((_) object_ptr \ ((_) heap, exception, (_) element_ptr option) prog) \ + ((_) heap, exception, (_) element_ptr option) prog" +begin +definition a_find_slot :: "bool \ (_) node_ptr \ (_, (_) element_ptr option) dom_prog" + where + "a_find_slot open_flag slotable = do { + parent_opt \ get_parent slotable; + (case parent_opt of + Some parent \ + if is_element_ptr_kind parent + then do { + shadow_root_ptr_opt \ get_shadow_root (the (cast parent)); + (case shadow_root_ptr_opt of + Some shadow_root_ptr \ do { + shadow_root_mode \ get_mode shadow_root_ptr; + if open_flag \ shadow_root_mode \ Open + then return None + else first_in_tree_order (cast shadow_root_ptr) (\ptr. if is_element_ptr_kind ptr + then do { + tag \ get_tag_name (the (cast ptr)); + name_attr \ get_attribute (the (cast ptr)) ''name''; + slotable_name_attr \ (if is_element_ptr_kind slotable + then get_attribute (the (cast slotable)) ''slot'' + else return None); + (if (tag = ''slot'' \ (name_attr = slotable_name_attr \ + (name_attr = None \ slotable_name_attr = Some '''') \ + (name_attr = Some '''' \ slotable_name_attr = None))) + then return (Some (the (cast ptr))) + else return None)} + else return None)} + | None \ return None)} + else return None + | _ \ return None)}" + +definition a_assigned_slot :: "(_) node_ptr \ (_, (_) element_ptr option) dom_prog" + where + "a_assigned_slot = a_find_slot True" +end + +global_interpretation l_find_slot\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_parent get_parent_locs get_shadow_root + get_shadow_root_locs get_mode get_mode_locs get_attribute get_attribute_locs get_tag_name + get_tag_name_locs first_in_tree_order + defines find_slot = a_find_slot + and assigned_slot = a_assigned_slot + . + +locale l_find_slot_defs = + fixes find_slot :: "bool \ (_) node_ptr \ (_, (_) element_ptr option) dom_prog" + and assigned_slot :: "(_) node_ptr \ (_, (_) element_ptr option) dom_prog" + +locale l_find_slot\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_find_slot\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + + l_find_slot_defs + + l_get_parent + + l_get_shadow_root + + l_get_mode + + l_get_attribute + + l_get_tag_name + + l_to_tree_order + + l_first_in_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + assumes find_slot_impl: "find_slot = a_find_slot" + assumes assigned_slot_impl: "assigned_slot = a_assigned_slot" +begin +lemmas find_slot_def = find_slot_impl[unfolded a_find_slot_def] +lemmas assigned_slot_def = assigned_slot_impl[unfolded a_assigned_slot_def] + +lemma find_slot_ptr_in_heap: + assumes "h \ find_slot open_flag slotable \\<^sub>r slot_opt" + shows "slotable |\| node_ptr_kinds h" + using assms + apply(auto simp add: find_slot_def elim!: bind_returns_result_E2)[1] + using get_parent_ptr_in_heap by blast + +lemma find_slot_slot_in_heap: + assumes "h \ find_slot open_flag slotable \\<^sub>r Some slot" + shows "slot |\| element_ptr_kinds h" + using assms + apply(auto simp add: find_slot_def first_in_tree_order_def + elim!: bind_returns_result_E2 map_filter_M_pure_E[where y=slot] + split: option.splits if_splits list.splits + intro!: map_filter_M_pure bind_pure_I)[1] + using get_tag_name_ptr_in_heap by blast+ + +lemma find_slot_pure [simp]: "pure (find_slot open_flag slotable) h" + by(auto simp add: find_slot_def first_in_tree_order_def + intro!: bind_pure_I map_filter_M_pure + split: option.splits list.splits) +end + +interpretation i_find_slot?: l_find_slot\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_parent get_parent_locs get_shadow_root + get_shadow_root_locs get_mode get_mode_locs get_attribute get_attribute_locs get_tag_name + get_tag_name_locs first_in_tree_order find_slot assigned_slot type_wf known_ptr known_ptrs + get_child_nodes get_child_nodes_locs to_tree_order + by (auto simp add: find_slot_def assigned_slot_def l_find_slot\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def + l_find_slot\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def instances) +declare l_find_slot\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +locale l_find_slot = l_find_slot_defs + + assumes find_slot_ptr_in_heap: + "h \ find_slot open_flag slotable \\<^sub>r slot_opt \ slotable |\| node_ptr_kinds h" + assumes find_slot_slot_in_heap: + "h \ find_slot open_flag slotable \\<^sub>r Some slot \ slot |\| element_ptr_kinds h" + assumes find_slot_pure [simp]: + "pure (find_slot open_flag slotable) h" + +lemma find_slot_is_l_find_slot [instances]: "l_find_slot find_slot" + apply(auto simp add: l_find_slot_def)[1] + using find_slot_ptr_in_heap apply fast + using find_slot_slot_in_heap apply fast + done + + + +subsubsection \get\_disconnected\_nodes\ + +locale l_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + CD: l_get_disconnected_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_nodes + get_disconnected_nodes_locs + + l_type_wf type_wf + for type_wf :: "(_) heap \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and get_disconnected_nodes :: "(_) document_ptr \ (_, (_) node_ptr list) dom_prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" + + assumes type_wf_impl: "type_wf = ShadowRootClass.type_wf" +begin + +lemma get_disconnected_nodes_ok: + "type_wf h \ document_ptr |\| document_ptr_kinds h \ + h \ ok (get_disconnected_nodes document_ptr)" + apply(unfold type_wf_impl get_disconnected_nodes_impl[unfolded a_get_disconnected_nodes_def]) + using CD.get_disconnected_nodes_ok CD.type_wf_impl ShadowRootClass.type_wf\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t + by blast +end + +interpretation i_get_disconnected_nodes?: l_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf + DocumentClass.type_wf get_disconnected_nodes get_disconnected_nodes_locs + by(auto simp add: l_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def + instances) +declare l_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma get_disconnected_nodes_is_l_get_disconnected_nodes [instances]: + "l_get_disconnected_nodes type_wf get_disconnected_nodes get_disconnected_nodes_locs" + apply(auto simp add: l_get_disconnected_nodes_def)[1] + using i_get_disconnected_nodes.get_disconnected_nodes_reads apply fast + using get_disconnected_nodes_ok apply fast + using i_get_disconnected_nodes.get_disconnected_nodes_ptr_in_heap apply fast + done + + +paragraph \set\_child\_nodes\ + +locale l_set_child_nodes_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_child_nodes_get_disconnected_nodes: + "\w \ set_child_nodes_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_disconnected_nodes_locs ptr'. r h h'))" + by(auto simp add: set_child_nodes_locs_def CD.set_child_nodes_locs_def + CD.get_disconnected_nodes_locs_def all_args_def) +end + +interpretation + i_set_child_nodes_get_disconnected_nodes?: l_set_child_nodes_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf + known_ptr DocumentClass.type_wf DocumentClass.known_ptr set_child_nodes set_child_nodes_locs + Core_DOM_Functions.set_child_nodes Core_DOM_Functions.set_child_nodes_locs + get_disconnected_nodes get_disconnected_nodes_locs + apply(auto simp add: l_set_child_nodes_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances)[1] + by(unfold_locales) +declare l_set_child_nodes_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma set_child_nodes_get_disconnected_nodes_is_l_set_child_nodes_get_disconnected_nodes [instances]: + "l_set_child_nodes_get_disconnected_nodes type_wf set_child_nodes set_child_nodes_locs + get_disconnected_nodes get_disconnected_nodes_locs" + using set_child_nodes_is_l_set_child_nodes get_disconnected_nodes_is_l_get_disconnected_nodes + apply(simp add: l_set_child_nodes_get_disconnected_nodes_def + l_set_child_nodes_get_disconnected_nodes_axioms_def) + using set_child_nodes_get_disconnected_nodes + by fast + + +paragraph \set\_disconnected\_nodes\ + +lemma set_disconnected_nodes_get_disconnected_nodes_l_set_disconnected_nodes_get_disconnected_nodes + [instances]: + "l_set_disconnected_nodes_get_disconnected_nodes ShadowRootClass.type_wf get_disconnected_nodes + get_disconnected_nodes_locs set_disconnected_nodes set_disconnected_nodes_locs" + apply(auto simp add: l_set_disconnected_nodes_get_disconnected_nodes_def + l_set_disconnected_nodes_get_disconnected_nodes_axioms_def instances)[1] + using i_set_disconnected_nodes_get_disconnected_nodes.set_disconnected_nodes_get_disconnected_nodes + apply fast + using i_set_disconnected_nodes_get_disconnected_nodes.set_disconnected_nodes_get_disconnected_nodes_different_pointers + apply fast + done + + +paragraph \delete\_shadow\_root\ + +locale l_delete_shadow_root_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma get_disconnected_nodes_delete_shadow_root: "h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h' + \ r \ get_disconnected_nodes_locs ptr' \ r h h'" + by(auto simp add: CD.get_disconnected_nodes_locs_def delete_shadow_root_get_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t) +end + +locale l_delete_shadow_root_get_disconnected_nodes = l_get_disconnected_nodes_defs + + assumes get_disconnected_nodes_delete_shadow_root: "h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h' + \ r \ get_disconnected_nodes_locs ptr' \ r h h'" +interpretation l_delete_shadow_root_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf DocumentClass.type_wf + get_disconnected_nodes get_disconnected_nodes_locs + by(auto simp add: l_delete_shadow_root_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) + +lemma l_delete_shadow_root_get_disconnected_nodes_get_disconnected_nodes_locs [instances]: "l_delete_shadow_root_get_disconnected_nodes get_disconnected_nodes_locs" + apply(auto simp add: l_delete_shadow_root_get_disconnected_nodes_def)[1] + using get_disconnected_nodes_delete_shadow_root apply fast + done + + +paragraph \set\_shadow\_root\ + +locale l_set_shadow_root_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_shadow_root_get_disconnected_nodes: + "\w \ set_shadow_root_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_disconnected_nodes_locs ptr'. r h h'))" + by(auto simp add: set_shadow_root_locs_def CD.get_disconnected_nodes_locs_def all_args_def) +end + +interpretation i_set_shadow_root_get_disconnected_nodes?: + l_set_shadow_root_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf set_shadow_root set_shadow_root_locs + DocumentClass.type_wf get_disconnected_nodes get_disconnected_nodes_locs + apply(auto simp add: l_set_shadow_root_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances)[1] + by(unfold_locales) +declare l_set_shadow_root_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +locale l_set_shadow_root_get_disconnected_nodes = + l_set_shadow_root_defs + + l_get_disconnected_nodes_defs + + assumes set_shadow_root_get_disconnected_nodes: + "\w \ set_shadow_root_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_disconnected_nodes_locs ptr'. r h h'))" + +lemma set_shadow_root_get_disconnected_nodes_is_l_set_shadow_root_get_disconnected_nodes [instances]: + "l_set_shadow_root_get_disconnected_nodes set_shadow_root_locs get_disconnected_nodes_locs" + using set_shadow_root_is_l_set_shadow_root get_disconnected_nodes_is_l_get_disconnected_nodes + apply(simp add: l_set_shadow_root_get_disconnected_nodes_def ) + using set_shadow_root_get_disconnected_nodes + by fast + + +paragraph \set\_mode\ + +locale l_set_mode_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_mode_get_disconnected_nodes: + "\w \ set_mode_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_disconnected_nodes_locs ptr'. r h h'))" + by(auto simp add: set_mode_locs_def + CD.get_disconnected_nodes_locs_impl[unfolded CD.a_get_disconnected_nodes_locs_def] + all_args_def) +end + +interpretation i_set_mode_get_disconnected_nodes?: l_set_mode_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf + set_mode set_mode_locs DocumentClass.type_wf get_disconnected_nodes get_disconnected_nodes_locs + by unfold_locales +declare l_set_mode_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +locale l_set_mode_get_disconnected_nodes = l_set_mode + l_get_disconnected_nodes + + assumes set_mode_get_disconnected_nodes: + "\w \ set_mode_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_disconnected_nodes_locs ptr'. r h h'))" + +lemma set_mode_get_disconnected_nodes_is_l_set_mode_get_disconnected_nodes [instances]: + "l_set_mode_get_disconnected_nodes type_wf set_mode set_mode_locs get_disconnected_nodes + get_disconnected_nodes_locs" + using set_mode_is_l_set_mode get_disconnected_nodes_is_l_get_disconnected_nodes + apply(simp add: l_set_mode_get_disconnected_nodes_def + l_set_mode_get_disconnected_nodes_axioms_def) + using set_mode_get_disconnected_nodes + by fast + +paragraph \new\_shadow\_root\ + +locale l_new_shadow_root_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_nodes + get_disconnected_nodes_locs + for type_wf :: "(_) heap \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and get_disconnected_nodes :: "(_) document_ptr \ (_, (_) node_ptr list) dom_prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +lemma get_disconnected_nodes_new_shadow_root: + "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' + \ r \ get_disconnected_nodes_locs ptr' \ r h h'" + by(auto simp add: CD.get_disconnected_nodes_locs_def new_shadow_root_get_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t) +end + +interpretation i_new_shadow_root_get_disconnected_nodes?: + l_new_shadow_root_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf DocumentClass.type_wf + get_disconnected_nodes get_disconnected_nodes_locs + by unfold_locales +declare l_new_shadow_root_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +locale l_new_shadow_root_get_disconnected_nodes = l_get_disconnected_nodes_defs + + assumes get_disconnected_nodes_new_shadow_root: + "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' + \ r \ get_disconnected_nodes_locs ptr' \ r h h'" + +lemma new_shadow_root_get_disconnected_nodes_is_l_new_shadow_root_get_disconnected_nodes [instances]: + "l_new_shadow_root_get_disconnected_nodes get_disconnected_nodes_locs" + apply (auto simp add: l_new_shadow_root_get_disconnected_nodes_def)[1] + using get_disconnected_nodes_new_shadow_root apply fast + done + + +subsubsection \remove\_shadow\_root\ + +locale l_remove_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs = + l_get_child_nodes_defs get_child_nodes get_child_nodes_locs + + l_get_shadow_root_defs get_shadow_root get_shadow_root_locs + + l_set_shadow_root_defs set_shadow_root set_shadow_root_locs + + l_get_disconnected_nodes_defs get_disconnected_nodes get_disconnected_nodes_locs + for get_child_nodes :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and set_shadow_root :: + "(_) element_ptr \ (_) shadow_root_ptr option \ ((_) heap, exception, unit) prog" + and set_shadow_root_locs :: "(_) element_ptr \ ((_) heap, exception, unit) prog set" + and get_disconnected_nodes :: "(_) document_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" +begin + +definition a_remove_shadow_root :: "(_) element_ptr \ (_, unit) dom_prog" where + "a_remove_shadow_root element_ptr = do { + shadow_root_ptr_opt \ get_shadow_root element_ptr; + (case shadow_root_ptr_opt of + Some shadow_root_ptr \ do { + children \ get_child_nodes (cast shadow_root_ptr); + (if children = [] + then do { + set_shadow_root element_ptr None; + delete_M shadow_root_ptr + } else do { + error HierarchyRequestError + }) + } | + None \ error HierarchyRequestError) + }" + +definition a_remove_shadow_root_locs :: + "(_) element_ptr \ (_) shadow_root_ptr \ ((_, unit) dom_prog) set" + where + "a_remove_shadow_root_locs element_ptr shadow_root_ptr \ + set_shadow_root_locs element_ptr \ {delete_M shadow_root_ptr}" +end + +global_interpretation l_remove_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_child_nodes get_child_nodes_locs + get_shadow_root get_shadow_root_locs set_shadow_root set_shadow_root_locs get_disconnected_nodes + get_disconnected_nodes_locs + defines remove_shadow_root = "a_remove_shadow_root" + and remove_shadow_root_locs = a_remove_shadow_root_locs + . + +locale l_remove_shadow_root_defs = + fixes remove_shadow_root :: "(_) element_ptr \ (_, unit) dom_prog" + fixes remove_shadow_root_locs :: + "(_) element_ptr \ (_) shadow_root_ptr \ ((_, unit) dom_prog) set" + + +locale l_remove_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_remove_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + + l_remove_shadow_root_defs + + l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_set_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_child_nodes + + l_get_disconnected_nodes type_wf get_disconnected_nodes get_disconnected_nodes_locs + + assumes remove_shadow_root_impl: "remove_shadow_root = a_remove_shadow_root" + assumes remove_shadow_root_locs_impl: "remove_shadow_root_locs = a_remove_shadow_root_locs" +begin +lemmas remove_shadow_root_def = + remove_shadow_root_impl[unfolded remove_shadow_root_def a_remove_shadow_root_def] +lemmas remove_shadow_root_locs_def = + remove_shadow_root_locs_impl[unfolded remove_shadow_root_locs_def a_remove_shadow_root_locs_def] + +lemma remove_shadow_root_writes: + "writes (remove_shadow_root_locs element_ptr (the |h \ get_shadow_root element_ptr|\<^sub>r)) + (remove_shadow_root element_ptr) h h'" + apply(auto simp add: remove_shadow_root_locs_def remove_shadow_root_def all_args_def + writes_union_right_I writes_union_left_I set_shadow_root_writes + intro!: writes_bind writes_bind_pure[OF get_shadow_root_pure] + writes_bind_pure[OF get_child_nodes_pure] + intro: writes_subset[OF set_shadow_root_writes] writes_subset[OF writes_singleton2] + split: option.splits)[1] + using writes_union_left_I[OF set_shadow_root_writes] + apply (metis inf_sup_aci(5) insert_is_Un) + using writes_union_right_I[OF writes_singleton[of delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M]] + by (smt insert_is_Un writes_singleton2 writes_union_left_I) +end + +interpretation i_remove_shadow_root?: l_remove_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes + get_child_nodes_locs get_shadow_root get_shadow_root_locs set_shadow_root set_shadow_root_locs + get_disconnected_nodes get_disconnected_nodes_locs remove_shadow_root remove_shadow_root_locs + type_wf known_ptr + by(auto simp add: l_remove_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_remove_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def + remove_shadow_root_def remove_shadow_root_locs_def instances) +declare l_remove_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +paragraph \get\_child\_nodes\ + +locale l_remove_shadow_root_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_remove_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin + +lemma remove_shadow_root_get_child_nodes_different_pointers: + assumes "ptr \ cast shadow_root_ptr" + assumes "w \ remove_shadow_root_locs element_ptr shadow_root_ptr" + assumes "h \ w \\<^sub>h h'" + assumes "r \ get_child_nodes_locs ptr" + shows "r h h'" + using assms + apply(auto simp add: all_args_def get_child_nodes_locs_def CD.get_child_nodes_locs_def + remove_shadow_root_locs_def set_shadow_root_locs_def + delete_shadow_root_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t delete_shadow_root_get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t + delete_shadow_root_get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t delete_shadow_root_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t + delete_shadow_root_get_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t[rotated] + element_put_get_preserved[where setter=shadow_root_opt_update] + intro: is_shadow_root_ptr_kind_obtains + elim: is_document_ptr_kind_obtains is_shadow_root_ptr_kind_obtains + split: if_splits option.splits)[1] + done +end + +locale l_remove_shadow_root_get_child_nodes = l_get_child_nodes_defs + l_remove_shadow_root_defs + + assumes remove_shadow_root_get_child_nodes_different_pointers: + "ptr \ cast shadow_root_ptr \ w \ remove_shadow_root_locs element_ptr shadow_root_ptr \ + h \ w \\<^sub>h h' \ r \ get_child_nodes_locs ptr \ r h h'" + +interpretation i_remove_shadow_root_get_child_nodes?: l_remove_shadow_root_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + type_wf known_ptr DocumentClass.type_wf DocumentClass.known_ptr get_child_nodes + get_child_nodes_locs Core_DOM_Functions.get_child_nodes Core_DOM_Functions.get_child_nodes_locs + get_shadow_root get_shadow_root_locs set_shadow_root set_shadow_root_locs get_disconnected_nodes + get_disconnected_nodes_locs remove_shadow_root remove_shadow_root_locs + by(auto simp add: l_remove_shadow_root_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_remove_shadow_root_get_child_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma remove_shadow_root_get_child_nodes_is_l_remove_shadow_root_get_child_nodes [instances]: + "l_remove_shadow_root_get_child_nodes get_child_nodes_locs remove_shadow_root_locs" + apply(auto simp add: l_remove_shadow_root_get_child_nodes_def instances )[1] + using remove_shadow_root_get_child_nodes_different_pointers apply fast + done + +paragraph \get\_tag\_name\ + +locale l_remove_shadow_root_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_remove_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin + +lemma remove_shadow_root_get_tag_name: + assumes "w \ remove_shadow_root_locs element_ptr shadow_root_ptr" + assumes "h \ w \\<^sub>h h'" + assumes "r \ get_tag_name_locs ptr" + shows "r h h'" + using assms + by(auto simp add: all_args_def remove_shadow_root_locs_def set_shadow_root_locs_def + CD.get_tag_name_locs_def delete_shadow_root_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t + element_put_get_preserved[where setter=shadow_root_opt_update] + split: if_splits option.splits) +end + +locale l_remove_shadow_root_get_tag_name = l_get_tag_name_defs + l_remove_shadow_root_defs + + assumes remove_shadow_root_get_tag_name: + "w \ remove_shadow_root_locs element_ptr shadow_root_ptr \ h \ w \\<^sub>h h' \ + r \ get_tag_name_locs ptr \ r h h'" + +interpretation i_remove_shadow_root_get_tag_name?: l_remove_shadow_root_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf + DocumentClass.type_wf get_tag_name get_tag_name_locs get_child_nodes get_child_nodes_locs + get_shadow_root get_shadow_root_locs set_shadow_root set_shadow_root_locs get_disconnected_nodes + get_disconnected_nodes_locs remove_shadow_root remove_shadow_root_locs known_ptr + by(auto simp add: l_remove_shadow_root_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_remove_shadow_root_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma remove_shadow_root_get_tag_name_is_l_remove_shadow_root_get_tag_name [instances]: + "l_remove_shadow_root_get_tag_name get_tag_name_locs remove_shadow_root_locs" + apply(auto simp add: l_remove_shadow_root_get_tag_name_def instances )[1] + using remove_shadow_root_get_tag_name apply fast + done + + +subsubsection \get\_owner\_document\ + +locale l_get_owner_document\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs = + l_get_host_defs get_host get_host_locs + + CD: l_get_owner_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_root_node get_root_node_locs get_disconnected_nodes + get_disconnected_nodes_locs + for get_root_node :: "(_::linorder) object_ptr \ ((_) heap, exception, (_) object_ptr) prog" + and get_root_node_locs :: "((_) heap \ (_) heap \ bool) set" + and get_disconnected_nodes :: "(_) document_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_host :: "(_) shadow_root_ptr \ ((_) heap, exception, (_) element_ptr) prog" + and get_host_locs :: "((_) heap \ (_) heap \ bool) set" +begin +definition a_get_owner_document\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r :: + "(_) shadow_root_ptr \ unit \ (_, (_) document_ptr) dom_prog" + where + "a_get_owner_document\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r shadow_root_ptr _ = do { + host \ get_host shadow_root_ptr; + CD.a_get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r (cast host) () + }" + +definition a_get_owner_document_tups :: "(((_) object_ptr \ bool) \ ((_) object_ptr \ unit + \ (_, (_) document_ptr) dom_prog)) list" + where + "a_get_owner_document_tups = [(is_shadow_root_ptr, a_get_owner_document\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r \ the \ cast)]" + +definition a_get_owner_document :: "(_::linorder) object_ptr \ (_, (_) document_ptr) dom_prog" + where + "a_get_owner_document ptr = invoke (CD.a_get_owner_document_tups @ a_get_owner_document_tups) ptr ()" +end + +global_interpretation l_get_owner_document\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_root_node_si get_root_node_si_locs + get_disconnected_nodes get_disconnected_nodes_locs get_host get_host_locs + defines get_owner_document_tups = a_get_owner_document_tups + and get_owner_document = a_get_owner_document + and get_owner_document\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r = a_get_owner_document\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r + and get_owner_document_tups\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + "l_get_owner_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_get_owner_document_tups + get_root_node_si get_disconnected_nodes" + and get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r = + "l_get_owner_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r + get_root_node_si get_disconnected_nodes" + . + +locale l_get_owner_document\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_known_ptr known_ptr + + l_get_owner_document\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_root_node_si get_root_node_si_locs get_disconnected_nodes + get_disconnected_nodes_locs get_host get_host_locs + + l_get_owner_document_defs get_owner_document + + l_get_host get_host get_host_locs + + CD: l_get_owner_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + get_parent get_parent_locs known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_disconnected_nodes + get_disconnected_nodes_locs get_root_node_si get_root_node_si_locs get_owner_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + for known_ptr :: "(_::linorder) object_ptr \ bool" + and known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_::linorder) object_ptr \ bool" + and get_parent :: "(_) node_ptr \ ((_) heap, exception, (_) object_ptr option) prog" + and get_parent_locs :: "((_) heap \ (_) heap \ bool) set" + and type_wf :: "(_) heap \ bool" + and get_disconnected_nodes :: "(_) document_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_root_node_si :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr) prog" + and get_root_node_si_locs :: "((_) heap \ (_) heap \ bool) set" + and get_owner_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ ((_) heap, exception, (_) document_ptr) prog" + and get_host :: "(_) shadow_root_ptr \ ((_) heap, exception, (_) element_ptr) prog" + and get_host_locs :: "((_) heap \ (_) heap \ bool) set" + and get_owner_document :: "(_) object_ptr \ ((_) heap, exception, (_) document_ptr) prog" + + assumes known_ptr_impl: "known_ptr = a_known_ptr" + assumes get_owner_document_impl: "get_owner_document = a_get_owner_document" +begin +lemmas known_ptr_def = known_ptr_impl[unfolded a_known_ptr_def] +lemmas get_owner_document_def = a_get_owner_document_def[folded get_owner_document_impl] + +lemma get_owner_document_pure [simp]: + "pure (get_owner_document ptr) h" +proof - + have "\shadow_root_ptr. pure (a_get_owner_document\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r shadow_root_ptr ()) h" + apply(auto simp add: a_get_owner_document\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def + intro!: bind_pure_I filter_M_pure_I + split: option.splits)[1] + by(auto simp add: CD.a_get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def + intro!: bind_pure_I filter_M_pure_I + split: option.splits) + then show ?thesis + apply(auto simp add: get_owner_document_def)[1] + apply(split CD.get_owner_document_splits, rule conjI)+ + apply(simp) + apply(auto simp add: a_get_owner_document_tups_def)[1] + apply(split invoke_splits, rule conjI)+ + apply simp + by(auto intro!: bind_pure_I) +qed + +lemma get_owner_document_ptr_in_heap: + assumes "h \ ok (get_owner_document ptr)" + shows "ptr |\| object_ptr_kinds h" + using assms + by(auto simp add: get_owner_document_def invoke_ptr_in_heap dest: is_OK_returns_heap_I) + +end + +interpretation i_get_owner_document?: l_get_owner_document\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr DocumentClass.known_ptr + get_parent get_parent_locs type_wf get_disconnected_nodes get_disconnected_nodes_locs + get_root_node_si get_root_node_si_locs CD.a_get_owner_document get_host get_host_locs + get_owner_document + by(auto simp add: instances l_get_owner_document\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_get_owner_document\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def + l_get_owner_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_get_owner_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def + get_owner_document_def Core_DOM_Functions.get_owner_document_def) +declare l_get_owner_document\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma get_owner_document_is_l_get_owner_document [instances]: + "l_get_owner_document get_owner_document" + apply(auto simp add: l_get_owner_document_def)[1] + using get_owner_document_ptr_in_heap apply fast + done + + + + +subsubsection \remove\_child\ + +global_interpretation l_remove_child\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_child_nodes get_child_nodes_locs set_child_nodes + set_child_nodes_locs get_parent get_parent_locs get_owner_document get_disconnected_nodes + get_disconnected_nodes_locs set_disconnected_nodes set_disconnected_nodes_locs + defines remove = "l_remove_child\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_remove get_child_nodes set_child_nodes get_parent + get_owner_document get_disconnected_nodes set_disconnected_nodes" + and remove_child = "l_remove_child\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_remove_child get_child_nodes set_child_nodes + get_owner_document get_disconnected_nodes set_disconnected_nodes" + and remove_child_locs = "l_remove_child\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_remove_child_locs set_child_nodes_locs + set_disconnected_nodes_locs" + . + +interpretation i_remove_child?: l_remove_child\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M Shadow_DOM.get_child_nodes + Shadow_DOM.get_child_nodes_locs Shadow_DOM.set_child_nodes Shadow_DOM.set_child_nodes_locs + Shadow_DOM.get_parent Shadow_DOM.get_parent_locs Shadow_DOM.get_owner_document + get_disconnected_nodes get_disconnected_nodes_locs set_disconnected_nodes + set_disconnected_nodes_locs remove_child remove_child_locs remove ShadowRootClass.type_wf + ShadowRootClass.known_ptr ShadowRootClass.known_ptrs + by(auto simp add: l_remove_child\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_remove_child\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def remove_child_def + remove_child_locs_def remove_def instances) +declare l_remove_child\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + + +subsubsection \get\_disconnected\_document\ + +locale l_get_disconnected_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs = + l_get_disconnected_nodes_defs get_disconnected_nodes get_disconnected_nodes_locs + for get_disconnected_nodes :: + "(_::linorder) document_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +definition a_get_disconnected_document :: "(_) node_ptr \ (_, (_) document_ptr) dom_prog" + where + "a_get_disconnected_document node_ptr = do { + check_in_heap (cast node_ptr); + ptrs \ document_ptr_kinds_M; + candidates \ filter_M (\document_ptr. do { + disconnected_nodes \ get_disconnected_nodes document_ptr; + return (node_ptr \ set disconnected_nodes) + }) ptrs; + (case candidates of + Cons document_ptr [] \ return document_ptr | + _ \ error HierarchyRequestError + ) + }" +definition "a_get_disconnected_document_locs = + (\document_ptr. get_disconnected_nodes_locs document_ptr) \ + (\ptr. {preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr RObject.nothing)})" +end + +locale l_get_disconnected_document_defs = + fixes get_disconnected_document :: "(_) node_ptr \ (_, (_::linorder) document_ptr) dom_prog" + fixes get_disconnected_document_locs :: "((_) heap \ (_) heap \ bool) set" + +locale l_get_disconnected_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_disconnected_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + + l_get_disconnected_document_defs + + l_get_disconnected_nodes + + assumes get_disconnected_document_impl: + "get_disconnected_document = a_get_disconnected_document" + assumes get_disconnected_document_locs_impl: + "get_disconnected_document_locs = a_get_disconnected_document_locs" +begin +lemmas get_disconnected_document_def = + get_disconnected_document_impl[unfolded a_get_disconnected_document_def] +lemmas get_disconnected_document_locs_def = + get_disconnected_document_locs_impl[unfolded a_get_disconnected_document_locs_def] + + +lemma get_disconnected_document_pure [simp]: "pure (get_disconnected_document ptr) h" + using get_disconnected_nodes_pure + by(auto simp add: get_disconnected_document_def + intro!: bind_pure_I filter_M_pure_I + split: list.splits) + +lemma get_disconnected_document_ptr_in_heap [simp]: + "h \ ok (get_disconnected_document node_ptr) \ node_ptr |\| node_ptr_kinds h" + using get_disconnected_document_def is_OK_returns_result_I check_in_heap_ptr_in_heap + by (metis (no_types, lifting) bind_returns_heap_E get_disconnected_document_pure + node_ptr_kinds_commutes pure_pure) + +lemma get_disconnected_document_disconnected_document_in_heap: + assumes "h \ get_disconnected_document child_node \\<^sub>r disconnected_document" + shows "disconnected_document |\| document_ptr_kinds h" + using assms get_disconnected_nodes_pure + by(auto simp add: get_disconnected_document_def elim!: bind_returns_result_E2 + dest!: filter_M_not_more_elements[where x=disconnected_document] + intro!: filter_M_pure_I bind_pure_I + split: if_splits list.splits) + +lemma get_disconnected_document_reads: + "reads get_disconnected_document_locs (get_disconnected_document node_ptr) h h'" + using get_disconnected_nodes_reads[unfolded reads_def] + by(auto simp add: get_disconnected_document_def get_disconnected_document_locs_def + intro!: reads_bind_pure reads_subset[OF check_in_heap_reads] + reads_subset[OF error_reads] + reads_subset[OF get_disconnected_nodes_reads] reads_subset[OF return_reads] + reads_subset[OF document_ptr_kinds_M_reads] filter_M_reads filter_M_pure_I + bind_pure_I + split: list.splits) + +end + +locale l_get_disconnected_document = l_get_disconnected_document_defs + + assumes get_disconnected_document_reads: + "reads get_disconnected_document_locs (get_disconnected_document node_ptr) h h'" + assumes get_disconnected_document_ptr_in_heap: + "h \ ok (get_disconnected_document node_ptr) \ node_ptr |\| node_ptr_kinds h" + assumes get_disconnected_document_pure [simp]: + "pure (get_disconnected_document node_ptr) h" + assumes get_disconnected_document_disconnected_document_in_heap: + "h \ get_disconnected_document child_node \\<^sub>r disconnected_document \ + disconnected_document |\| document_ptr_kinds h" + +global_interpretation l_get_disconnected_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_disconnected_nodes + get_disconnected_nodes_locs defines + get_disconnected_document = a_get_disconnected_document and + get_disconnected_document_locs = a_get_disconnected_document_locs . + +interpretation i_get_disconnected_document?: l_get_disconnected_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + get_disconnected_nodes get_disconnected_nodes_locs get_disconnected_document + get_disconnected_document_locs type_wf + by(auto simp add: l_get_disconnected_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_get_disconnected_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def + get_disconnected_document_def get_disconnected_document_locs_def instances) +declare l_get_disconnected_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma get_disconnected_document_is_l_get_disconnected_document [instances]: + "l_get_disconnected_document get_disconnected_document get_disconnected_document_locs" + apply(auto simp add: l_get_disconnected_document_def instances)[1] + using get_disconnected_document_ptr_in_heap get_disconnected_document_pure + get_disconnected_document_disconnected_document_in_heap get_disconnected_document_reads + by blast+ + +paragraph \get\_disconnected\_nodes\ + +locale l_set_tag_name_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_tag_name_get_disconnected_nodes: + "\w \ set_tag_name_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_disconnected_nodes_locs ptr'. r h h'))" + by(auto simp add: CD.set_tag_name_locs_impl[unfolded CD.a_set_tag_name_locs_def] + CD.get_disconnected_nodes_locs_impl[unfolded CD.a_get_disconnected_nodes_locs_def] + all_args_def) +end + +interpretation + i_set_tag_name_get_disconnected_nodes?: l_set_tag_name_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf + DocumentClass.type_wf set_tag_name set_tag_name_locs get_disconnected_nodes + get_disconnected_nodes_locs + by unfold_locales +declare l_set_tag_name_get_disconnected_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma set_tag_name_get_disconnected_nodes_is_l_set_tag_name_get_disconnected_nodes [instances]: + "l_set_tag_name_get_disconnected_nodes type_wf set_tag_name set_tag_name_locs + get_disconnected_nodes get_disconnected_nodes_locs" + using set_tag_name_is_l_set_tag_name get_disconnected_nodes_is_l_get_disconnected_nodes + apply(simp add: l_set_tag_name_get_disconnected_nodes_def + l_set_tag_name_get_disconnected_nodes_axioms_def) + using set_tag_name_get_disconnected_nodes + by fast + + +subsubsection \adopt\_node\ + +global_interpretation l_adopt_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_owner_document get_parent get_parent_locs + remove_child remove_child_locs get_disconnected_nodes get_disconnected_nodes_locs + set_disconnected_nodes set_disconnected_nodes_locs + defines adopt_node = a_adopt_node + and adopt_node_locs = a_adopt_node_locs + . +interpretation i_adopt_node?: l_adopt_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_owner_document get_parent get_parent_locs + remove_child remove_child_locs get_disconnected_nodes get_disconnected_nodes_locs + set_disconnected_nodes set_disconnected_nodes_locs adopt_node adopt_node_locs known_ptr type_wf + get_child_nodes get_child_nodes_locs known_ptrs set_child_nodes set_child_nodes_locs remove + by(auto simp add: l_adopt_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_adopt_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def adopt_node_def + adopt_node_locs_def instances) +declare l_adopt_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma adopt_node_is_l_adopt_node [instances]: "l_adopt_node type_wf known_ptr known_ptrs get_parent + adopt_node adopt_node_locs get_child_nodes get_owner_document" + apply(auto simp add: l_adopt_node_def l_adopt_node_axioms_def instances)[1] + using adopt_node_writes apply fast + using adopt_node_pointers_preserved apply (fast, fast) + using adopt_node_types_preserved apply (fast, fast) + using adopt_node_child_in_heap apply fast + using adopt_node_children_subset apply fast + done + + + +paragraph \get\_shadow\_root\ + +locale l_adopt_node_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_child_nodes_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_set_disconnected_nodes_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_adopt_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma adopt_node_get_shadow_root: + "\w \ adopt_node_locs parent owner_document document_ptr. + (h \ w \\<^sub>h h' \ (\r \ get_shadow_root_locs ptr'. r h h'))" + by(auto simp add: adopt_node_locs_def remove_child_locs_def all_args_def + set_disconnected_nodes_get_shadow_root set_child_nodes_get_shadow_root) +end + +locale l_adopt_node_get_shadow_root = l_adopt_node_defs + l_get_shadow_root_defs + + assumes adopt_node_get_shadow_root: + "\w \ adopt_node_locs parent owner_document document_ptr. + (h \ w \\<^sub>h h' \ (\r \ get_shadow_root_locs ptr'. r h h'))" + +interpretation i_adopt_node_get_shadow_root?: l_adopt_node_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr + DocumentClass.type_wf DocumentClass.known_ptr set_child_nodes set_child_nodes_locs + Core_DOM_Functions.set_child_nodes Core_DOM_Functions.set_child_nodes_locs get_shadow_root + get_shadow_root_locs set_disconnected_nodes set_disconnected_nodes_locs get_owner_document + get_parent get_parent_locs remove_child remove_child_locs get_disconnected_nodes + get_disconnected_nodes_locs adopt_node adopt_node_locs get_child_nodes get_child_nodes_locs + known_ptrs remove + by(auto simp add: l_adopt_node_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_adopt_node_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma adopt_node_get_shadow_root_is_l_adopt_node_get_shadow_root [instances]: + "l_adopt_node_get_shadow_root adopt_node_locs get_shadow_root_locs" + apply(auto simp add: l_adopt_node_get_shadow_root_def)[1] + using adopt_node_get_shadow_root apply fast + done + + + +subsubsection \insert\_before\ + +global_interpretation l_insert_before\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_parent get_parent_locs get_child_nodes + get_child_nodes_locs set_child_nodes set_child_nodes_locs get_ancestors_si get_ancestors_si_locs + adopt_node adopt_node_locs set_disconnected_nodes set_disconnected_nodes_locs + get_disconnected_nodes get_disconnected_nodes_locs get_owner_document + defines + next_sibling = a_next_sibling and + insert_node = a_insert_node and + ensure_pre_insertion_validity = a_ensure_pre_insertion_validity and + insert_before = a_insert_before and + insert_before_locs = a_insert_before_locs + . +global_interpretation l_append_child\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs insert_before + defines append_child = "l_append_child\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs.a_append_child insert_before" + . + +interpretation i_insert_before?: l_insert_before\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_parent get_parent_locs get_child_nodes + get_child_nodes_locs set_child_nodes set_child_nodes_locs get_ancestors_si get_ancestors_si_locs + adopt_node adopt_node_locs set_disconnected_nodes set_disconnected_nodes_locs get_disconnected_nodes + get_disconnected_nodes_locs get_owner_document insert_before insert_before_locs append_child type_wf + known_ptr known_ptrs + by(auto simp add: l_insert_before\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_insert_before\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def insert_before_def + insert_before_locs_def instances) +declare l_insert_before\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +interpretation i_append_child?: l_append_child\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M append_child insert_before insert_before_locs + by(simp add: l_append_child\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances append_child_def) +declare l_append_child\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + + +subsubsection \get\_assigned\_nodes\ + +fun map_filter_M2 :: "('x \ ('heap, 'e, 'y option) prog) \ 'x list + \ ('heap, 'e, 'y list) prog" + where + "map_filter_M2 f [] = return []" | + "map_filter_M2 f (x # xs) = do { + res \ f x; + remainder \ map_filter_M2 f xs; + return ((case res of Some r \ [r] | None \ []) @ remainder) + }" +lemma map_filter_M2_pure [simp]: + assumes "\x. x \ set xs \ pure (f x) h" + shows "pure (map_filter_M2 f xs) h" + using assms + apply(induct xs arbitrary: h) + by(auto elim!: bind_returns_result_E2 intro!: bind_pure_I) + +lemma map_filter_pure_no_monad: + assumes "\x. x \ set xs \ pure (f x) h" + assumes "h \ map_filter_M2 f xs \\<^sub>r ys" + shows + "ys = map the (filter (\x. x \ None) (map (\x. |h \ f x|\<^sub>r) xs))" and + "\x. x \ set xs \ h \ ok (f x)" + using assms + apply(induct xs arbitrary: h ys) + by(auto elim!: bind_returns_result_E2) + +lemma map_filter_pure_foo: + assumes "\x. x \ set xs \ pure (f x) h" + assumes "h \ map_filter_M2 f xs \\<^sub>r ys" + assumes "y \ set ys" + obtains x where "h \ f x \\<^sub>r Some y" and "x \ set xs" + using assms + apply(induct xs arbitrary: ys) + by(auto elim!: bind_returns_result_E2) + + +lemma map_filter_M2_in_result: + assumes "h \ map_filter_M2 P xs \\<^sub>r ys" + assumes "a \ set xs" + assumes "\x. x \ set xs \ pure (P x) h" + assumes "h \ P a \\<^sub>r Some b" + shows "b \ set ys" + using assms + apply(induct xs arbitrary: h ys) + by(auto elim!: bind_returns_result_E2 ) + + +locale l_assigned_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs = + l_get_tag_name_defs get_tag_name get_tag_name_locs + + l_get_root_node_defs get_root_node get_root_node_locs + + l_get_host_defs get_host get_host_locs + + l_get_child_nodes_defs get_child_nodes get_child_nodes_locs + + l_find_slot_defs find_slot assigned_slot + + l_remove_defs remove + + l_insert_before_defs insert_before insert_before_locs + + l_append_child_defs append_child + + l_remove_shadow_root_defs remove_shadow_root remove_shadow_root_locs + for get_child_nodes :: "(_::linorder) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_tag_name :: "(_) element_ptr \ ((_) heap, exception, char list) prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_root_node :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr) prog" + and get_root_node_locs :: "((_) heap \ (_) heap \ bool) set" + and get_host :: "(_) shadow_root_ptr \ ((_) heap, exception, (_) element_ptr) prog" + and get_host_locs :: "((_) heap \ (_) heap \ bool) set" + and find_slot :: "bool \ (_) node_ptr \ ((_) heap, exception, (_) element_ptr option) prog" + and assigned_slot :: "(_) node_ptr \ ((_) heap, exception, (_) element_ptr option) prog" + and remove :: "(_) node_ptr \ ((_) heap, exception, unit) prog" + and insert_before :: + "(_) object_ptr \ (_) node_ptr \ (_) node_ptr option \ ((_) heap, exception, unit) prog" + and insert_before_locs :: "(_) object_ptr \ (_) object_ptr option \ (_) document_ptr \ + (_) document_ptr \ (_, unit) dom_prog set" + and append_child :: "(_) object_ptr \ (_) node_ptr \ ((_) heap, exception, unit) prog" + and remove_shadow_root :: "(_) element_ptr \ ((_) heap, exception, unit) prog" + and remove_shadow_root_locs :: "(_) element_ptr \ (_) shadow_root_ptr \ + ((_) heap, exception, unit) prog set" +begin +definition a_assigned_nodes :: "(_) element_ptr \ (_, (_) node_ptr list) dom_prog" + where + "a_assigned_nodes slot = do { + tag \ get_tag_name slot; + (if tag \ ''slot'' + then error HierarchyRequestError + else return ()); + root \ get_root_node (cast slot); + if is_shadow_root_ptr_kind root + then do { + host \ get_host (the (cast root)); + children \ get_child_nodes (cast host); + filter_M (\slotable. do { + found_slot \ find_slot False slotable; + return (found_slot = Some slot)}) children} + else return []}" + +partial_function (dom_prog) a_assigned_nodes_flatten :: + "(_) element_ptr \ (_, (_) node_ptr list) dom_prog" + where + "a_assigned_nodes_flatten slot = do { + tag \ get_tag_name slot; + (if tag \ ''slot'' + then error HierarchyRequestError + else return ()); + root \ get_root_node (cast slot); + (if is_shadow_root_ptr_kind root + then do { + slotables \ a_assigned_nodes slot; + slotables_or_child_nodes \ (if slotables = [] + then do { + get_child_nodes (cast slot) + } else do { + return slotables + }); + list_of_lists \ map_M (\node_ptr. do { + (case cast node_ptr of + Some element_ptr \ do { + tag \ get_tag_name element_ptr; + (if tag = ''slot'' + then do { + root \ get_root_node (cast element_ptr); + (if is_shadow_root_ptr_kind root + then do { + a_assigned_nodes_flatten element_ptr + } else do { + return [node_ptr] + }) + } else do { + return [node_ptr] + }) + } + | None \ return [node_ptr]) + }) slotables_or_child_nodes; + return (concat list_of_lists) + } else return []) + }" + +definition a_flatten_dom :: "(_, unit) dom_prog" where + "a_flatten_dom = do { + tups \ element_ptr_kinds_M \ map_filter_M2 (\element_ptr. do { + tag \ get_tag_name element_ptr; + assigned_nodes \ a_assigned_nodes element_ptr; + (if tag = ''slot'' \ assigned_nodes \ [] + then return (Some (element_ptr, assigned_nodes)) + else return None)}); + forall_M (\(slot, assigned_nodes). do { + get_child_nodes (cast slot) \ forall_M remove; + forall_M (append_child (cast slot)) assigned_nodes + }) tups; + shadow_root_ptr_kinds_M \ forall_M (\shadow_root_ptr. do { + host \ get_host shadow_root_ptr; + get_child_nodes (cast host) \ forall_M remove; + get_child_nodes (cast shadow_root_ptr) \ forall_M (append_child (cast host)); + remove_shadow_root host + }); + return () + }" +end + +global_interpretation l_assigned_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_child_nodes get_child_nodes_locs + get_tag_name get_tag_name_locs get_root_node get_root_node_locs get_host get_host_locs find_slot + assigned_slot remove insert_before insert_before_locs append_child remove_shadow_root + remove_shadow_root_locs + defines assigned_nodes = a_assigned_nodes + and assigned_nodes_flatten = a_assigned_nodes_flatten + and flatten_dom = a_flatten_dom + . + +declare a_assigned_nodes_flatten.simps [code] + +locale l_assigned_nodes_defs = + fixes assigned_nodes :: "(_) element_ptr \ (_, (_) node_ptr list) dom_prog" + fixes assigned_nodes_flatten :: "(_) element_ptr \ (_, (_) node_ptr list) dom_prog" + fixes flatten_dom :: "(_, unit) dom_prog" + +locale l_assigned_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_assigned_nodes_defs + assigned_nodes assigned_nodes_flatten flatten_dom + + l_assigned_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + get_child_nodes get_child_nodes_locs get_tag_name get_tag_name_locs get_root_node + get_root_node_locs get_host get_host_locs find_slot assigned_slot remove insert_before + insert_before_locs append_child remove_shadow_root remove_shadow_root_locs + + l_get_shadow_root + type_wf get_shadow_root get_shadow_root_locs + + l_set_shadow_root + type_wf set_shadow_root set_shadow_root_locs + + l_remove + + l_insert_before + insert_before insert_before_locs + + l_find_slot + find_slot assigned_slot + + l_get_tag_name + type_wf get_tag_name get_tag_name_locs + + l_get_root_node + get_root_node get_root_node_locs get_parent get_parent_locs + + l_get_host + get_host get_host_locs + + l_get_child_nodes + type_wf known_ptr get_child_nodes get_child_nodes_locs + + l_to_tree_order + to_tree_order + for known_ptr :: "(_::linorder) object_ptr \ bool" + and assigned_nodes :: "(_) element_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and assigned_nodes_flatten :: "(_) element_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and flatten_dom :: "((_) heap, exception, unit) prog" + and get_child_nodes :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_tag_name :: "(_) element_ptr \ ((_) heap, exception, char list) prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_root_node :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr) prog" + and get_root_node_locs :: "((_) heap \ (_) heap \ bool) set" + and get_host :: "(_) shadow_root_ptr \ ((_) heap, exception, (_) element_ptr) prog" + and get_host_locs :: "((_) heap \ (_) heap \ bool) set" + and find_slot :: "bool \ (_) node_ptr \ ((_) heap, exception, (_) element_ptr option) prog" + and assigned_slot :: "(_) node_ptr \ ((_) heap, exception, (_) element_ptr option) prog" + and remove :: "(_) node_ptr \ ((_) heap, exception, unit) prog" + and insert_before :: + "(_) object_ptr \ (_) node_ptr \ (_) node_ptr option \ ((_) heap, exception, unit) prog" + and insert_before_locs :: "(_) object_ptr \ (_) object_ptr option \ (_) document_ptr \ + (_) document_ptr \ (_, unit) dom_prog set" + and append_child :: "(_) object_ptr \ (_) node_ptr \ ((_) heap, exception, unit) prog" + and remove_shadow_root :: "(_) element_ptr \ ((_) heap, exception, unit) prog" + and remove_shadow_root_locs :: "(_) element_ptr \ (_) shadow_root_ptr \ + ((_) heap, exception, unit) prog set" + and type_wf :: "(_) heap \ bool" + and get_shadow_root :: + "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and set_shadow_root :: + "(_) element_ptr \ (_) shadow_root_ptr option \ ((_) heap, exception, unit) prog" + and set_shadow_root_locs :: "(_) element_ptr \ ((_) heap, exception, unit) prog set" + and get_parent :: "(_) node_ptr \ ((_) heap, exception, (_) object_ptr option) prog" + and get_parent_locs :: "((_) heap \ (_) heap \ bool) set" + and to_tree_order :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr list) prog" + + assumes assigned_nodes_impl: "assigned_nodes = a_assigned_nodes" + assumes flatten_dom_impl: "flatten_dom = a_flatten_dom" +begin +lemmas assigned_nodes_def = assigned_nodes_impl[unfolded a_assigned_nodes_def] +lemmas flatten_dom_def = flatten_dom_impl[unfolded a_flatten_dom_def, folded assigned_nodes_impl] + +lemma assigned_nodes_pure [simp]: "pure (assigned_nodes slot) h" + by(auto simp add: assigned_nodes_def intro!: bind_pure_I filter_M_pure_I) + +lemma assigned_nodes_ptr_in_heap: + assumes "h \ ok (assigned_nodes slot)" + shows "slot |\| element_ptr_kinds h" + using assms + apply(auto simp add: assigned_nodes_def)[1] + by (meson bind_is_OK_E is_OK_returns_result_I local.get_tag_name_ptr_in_heap) + +lemma assigned_nodes_slot_is_slot: + assumes "h \ ok (assigned_nodes slot)" + shows "h \ get_tag_name slot \\<^sub>r ''slot''" + using assms + by(auto simp add: assigned_nodes_def elim!: bind_is_OK_E split: if_splits) + +lemma assigned_nodes_different_ptr: + assumes "h \ assigned_nodes slot \\<^sub>r nodes" + assumes "h \ assigned_nodes slot' \\<^sub>r nodes'" + assumes "slot \ slot'" + shows "set nodes \ set nodes' = {}" +proof (rule ccontr) + assume "set nodes \ set nodes' \ {} " + then obtain common_ptr where "common_ptr \ set nodes" and "common_ptr \ set nodes'" + by auto + + have "h \ find_slot False common_ptr \\<^sub>r Some slot" + using \common_ptr \ set nodes\ + using assms(1) + by(auto simp add: assigned_nodes_def + elim!: bind_returns_result_E2 + split: if_splits + dest!: filter_M_holds_for_result[where x=common_ptr] + intro!: bind_pure_I) + moreover + have "h \ find_slot False common_ptr \\<^sub>r Some slot'" + using \common_ptr \ set nodes'\ + using assms(2) + by(auto simp add: assigned_nodes_def + elim!: bind_returns_result_E2 + split: if_splits + dest!: filter_M_holds_for_result[where x=common_ptr] + intro!: bind_pure_I) + ultimately + show False + using assms(3) + by (meson option.inject returns_result_eq) +qed +end + +interpretation i_assigned_nodes?: l_assigned_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr assigned_nodes + assigned_nodes_flatten flatten_dom get_child_nodes get_child_nodes_locs get_tag_name + get_tag_name_locs get_root_node get_root_node_locs get_host get_host_locs find_slot + assigned_slot remove insert_before insert_before_locs append_child remove_shadow_root + remove_shadow_root_locs type_wf get_shadow_root get_shadow_root_locs set_shadow_root + set_shadow_root_locs get_parent get_parent_locs to_tree_order + by(auto simp add: instances l_assigned_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_assigned_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def + assigned_nodes_def flatten_dom_def) +declare l_assigned_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +locale l_assigned_nodes = l_assigned_nodes_defs + + assumes assigned_nodes_pure [simp]: "pure (assigned_nodes slot) h" + assumes assigned_nodes_ptr_in_heap: + "h \ ok (assigned_nodes slot) \ slot |\| element_ptr_kinds h" + assumes assigned_nodes_slot_is_slot: + "h \ ok (assigned_nodes slot) \ h \ get_tag_name slot \\<^sub>r ''slot''" + assumes assigned_nodes_different_ptr: + "h \ assigned_nodes slot \\<^sub>r nodes \ h \ assigned_nodes slot' \\<^sub>r nodes' \ + slot \ slot' \ set nodes \ set nodes' = {}" + +lemma assigned_nodes_is_l_assigned_nodes [instances]: "l_assigned_nodes assigned_nodes" + apply(auto simp add: l_assigned_nodes_def)[1] + using assigned_nodes_ptr_in_heap apply fast + using assigned_nodes_slot_is_slot apply fast + using assigned_nodes_different_ptr apply fast + done + +subsubsection \set\_val\ + +locale l_set_val\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + CD: l_set_val\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M set_val set_val_locs + + l_type_wf type_wf + for type_wf :: "(_) heap \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and set_val :: "(_) character_data_ptr \ char list \ (_, unit) dom_prog" + and set_val_locs :: "(_) character_data_ptr \ (_, unit) dom_prog set" + + assumes type_wf_impl: "type_wf = ShadowRootClass.type_wf" +begin + +lemma set_val_ok: + "type_wf h \ character_data_ptr |\| character_data_ptr_kinds h \ + h \ ok (set_val character_data_ptr tag)" + using CD.set_val_ok CD.type_wf_impl ShadowRootClass.type_wf\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t local.type_wf_impl by blast + +lemma set_val_writes: + "writes (set_val_locs character_data_ptr) (set_val character_data_ptr tag) h h'" + using CD.set_val_writes . + +lemma set_val_pointers_preserved: + assumes "w \ set_val_locs character_data_ptr" + assumes "h \ w \\<^sub>h h'" + shows "object_ptr_kinds h = object_ptr_kinds h'" + using assms CD.set_val_pointers_preserved by simp + +lemma set_val_typess_preserved: + assumes "w \ set_val_locs character_data_ptr" + assumes "h \ w \\<^sub>h h'" + shows "type_wf h = type_wf h'" + apply(unfold type_wf_impl) + using assms(1) type_wf_preserved[OF writes_singleton2 assms(2)] + by(auto simp add: all_args_def CD.set_val_locs_impl[unfolded CD.a_set_val_locs_def] + split: if_splits) +end + +interpretation + i_set_val?: l_set_val\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf DocumentClass.type_wf set_val set_val_locs + apply(unfold_locales) + by (auto simp add: set_val_def set_val_locs_def) +declare l_set_val\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma set_val_is_l_set_val [instances]: "l_set_val type_wf set_val set_val_locs" + apply(simp add: l_set_val_def) + using set_val_ok set_val_writes set_val_pointers_preserved set_val_typess_preserved + by blast + +paragraph \get\_shadow\_root\ + +locale l_set_val_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_val\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_val_get_shadow_root: + "\w \ set_val_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_shadow_root_locs ptr'. r h h'))" + by(auto simp add: CD.set_val_locs_impl[unfolded CD.a_set_val_locs_def] + get_shadow_root_locs_def all_args_def) +end + +locale l_set_val_get_shadow_root = l_set_val + l_get_shadow_root + + assumes set_val_get_shadow_root: + "\w \ set_val_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_shadow_root_locs ptr'. r h h'))" + +interpretation + i_set_val_get_shadow_root?: l_set_val_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf DocumentClass.type_wf + set_val set_val_locs + get_shadow_root get_shadow_root_locs + apply(auto simp add: l_set_val_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances)[1] + using l_set_val\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms + by unfold_locales +declare l_set_val_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma set_val_get_shadow_root_is_l_set_val_get_shadow_root [instances]: + "l_set_val_get_shadow_root type_wf set_val set_val_locs get_shadow_root + get_shadow_root_locs" + using set_val_is_l_set_val get_shadow_root_is_l_get_shadow_root + apply(simp add: l_set_val_get_shadow_root_def l_set_val_get_shadow_root_axioms_def) + using set_val_get_shadow_root + by fast + +paragraph \get\_tag\_type\ + +locale l_set_val_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_val\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma set_val_get_tag_name: + "\w \ set_val_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_tag_name_locs ptr'. r h h'))" + by(auto simp add: CD.set_val_locs_impl[unfolded CD.a_set_val_locs_def] + CD.get_tag_name_locs_impl[unfolded CD.a_get_tag_name_locs_def] + all_args_def) +end + +locale l_set_val_get_tag_name = l_set_val + l_get_tag_name + + assumes set_val_get_tag_name: + "\w \ set_val_locs ptr. (h \ w \\<^sub>h h' \ (\r \ get_tag_name_locs ptr'. r h h'))" + +interpretation + i_set_val_get_tag_name?: l_set_val_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf DocumentClass.type_wf set_val + set_val_locs get_tag_name get_tag_name_locs + by unfold_locales +declare l_set_val_get_tag_name\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma set_val_get_tag_name_is_l_set_val_get_tag_name [instances]: + "l_set_val_get_tag_name type_wf set_val set_val_locs get_tag_name get_tag_name_locs" + using set_val_is_l_set_val get_tag_name_is_l_get_tag_name + apply(simp add: l_set_val_get_tag_name_def l_set_val_get_tag_name_axioms_def) + using set_val_get_tag_name + by fast + +subsubsection \create\_character\_data\ + + +locale l_create_character_data\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + CD: l_create_character_data\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M _ _ _ _ _ _ type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M _ known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_known_ptr known_ptr + for known_ptr :: "(_) object_ptr \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ bool" + + assumes known_ptr_impl: "known_ptr = a_known_ptr" +begin + +lemma create_character_data_document_in_heap: + assumes "h \ ok (create_character_data document_ptr text)" + shows "document_ptr |\| document_ptr_kinds h" + using assms CD.create_character_data_document_in_heap by simp + +lemma create_character_data_known_ptr: + assumes "h \ create_character_data document_ptr text \\<^sub>r new_character_data_ptr" + shows "known_ptr (cast new_character_data_ptr)" + using assms CD.create_character_data_known_ptr + by(simp add: known_ptr_impl CD.known_ptr_impl ShadowRootClass.a_known_ptr_def) +end + +locale l_create_character_data = l_create_character_data_defs + +interpretation i_create_character_data?: l_create_character_data\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_nodes + get_disconnected_nodes_locs set_disconnected_nodes set_disconnected_nodes_locs set_val set_val_locs + create_character_data known_ptr DocumentClass.type_wf DocumentClass.known_ptr + by(auto simp add: l_create_character_data\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_create_character_data\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def + instances) +declare l_create_character_data\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +subsubsection \create\_element\ + +locale l_create_element\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + CD: l_create_element\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_nodes get_disconnected_nodes_locs set_disconnected_nodes + set_disconnected_nodes_locs set_tag_name set_tag_name_locs type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M create_element + known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_known_ptr known_ptr + for get_disconnected_nodes :: "(_) document_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" + and set_disconnected_nodes :: + "(_) document_ptr \ (_) node_ptr list \ ((_) heap, exception, unit) prog" + and set_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap, exception, unit) prog set" + and set_tag_name :: "(_) element_ptr \ char list \ ((_) heap, exception, unit) prog" + and set_tag_name_locs :: "(_) element_ptr \ ((_) heap, exception, unit) prog set" + and type_wf :: "(_) heap \ bool" + and create_element :: + "(_) document_ptr \ char list \ ((_) heap, exception, (_) element_ptr) prog" + and known_ptr :: "(_) object_ptr \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) object_ptr \ bool" + + assumes known_ptr_impl: "known_ptr = a_known_ptr" +begin +lemmas create_element_def = CD.create_element_def + +lemma create_element_document_in_heap: + assumes "h \ ok (create_element document_ptr tag)" + shows "document_ptr |\| document_ptr_kinds h" + using CD.create_element_document_in_heap assms . + +lemma create_element_known_ptr: + assumes "h \ create_element document_ptr tag \\<^sub>r new_element_ptr" + shows "known_ptr (cast new_element_ptr)" +proof - + have "is_element_ptr new_element_ptr" + using assms + apply(auto simp add: create_element_def elim!: bind_returns_result_E)[1] + using new_element_is_element_ptr + by blast + then show ?thesis + by(auto simp add: known_ptr_impl known_ptr_defs DocumentClass.known_ptr_defs + CharacterDataClass.known_ptr_defs ElementClass.known_ptr_defs) +qed +end + +interpretation i_create_element?: l_create_element\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_nodes + get_disconnected_nodes_locs set_disconnected_nodes set_disconnected_nodes_locs set_tag_name + set_tag_name_locs type_wf create_element known_ptr DocumentClass.type_wf DocumentClass.known_ptr + by(auto simp add: l_create_element\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_create_element\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def instances) +declare l_create_element\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + + + +subsection \A wellformed heap (Core DOM)\ + +subsubsection \wellformed\_heap\ + + +locale l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs = + CD: l_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_child_nodes get_child_nodes_locs get_disconnected_nodes + get_disconnected_nodes_locs + + l_get_shadow_root_defs get_shadow_root get_shadow_root_locs + + l_get_tag_name_defs get_tag_name get_tag_name_locs + for get_child_nodes :: "(_::linorder) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_disconnected_nodes :: "(_) document_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_tag_name :: "(_) element_ptr \ ((_) heap, exception, char list) prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" +begin +definition a_host_shadow_root_rel :: "(_) heap \ ((_) object_ptr \ (_) object_ptr) set" + where + "a_host_shadow_root_rel h = (\(x, y). (cast x, cast y)) ` {(host, shadow_root). + host |\| element_ptr_kinds h \ |h \ get_shadow_root host|\<^sub>r = Some shadow_root}" + +lemma a_host_shadow_root_rel_code [code]: "a_host_shadow_root_rel h = set (concat (map + (\host. (case |h \ get_shadow_root host|\<^sub>r of + Some shadow_root \ [(cast host, cast shadow_root)] | + None \ [])) + (sorted_list_of_fset (element_ptr_kinds h))) +)" + by(auto simp add: a_host_shadow_root_rel_def) + +definition a_all_ptrs_in_heap :: "(_) heap \ bool" where + "a_all_ptrs_in_heap h = ((\host shadow_root_ptr. + (h \ get_shadow_root host \\<^sub>r Some shadow_root_ptr) \ + shadow_root_ptr |\| shadow_root_ptr_kinds h))" + +definition a_distinct_lists :: "(_) heap \ bool" + where + "a_distinct_lists h = distinct (concat ( + map (\element_ptr. (case |h \ get_shadow_root element_ptr|\<^sub>r of + Some shadow_root_ptr \ [shadow_root_ptr] | None \ [])) + |h \ element_ptr_kinds_M|\<^sub>r + ))" + + +definition a_shadow_root_valid :: "(_) heap \ bool" where + "a_shadow_root_valid h = (\shadow_root_ptr \ fset (shadow_root_ptr_kinds h). + (\host \ fset(element_ptr_kinds h). + |h \ get_tag_name host|\<^sub>r \ safe_shadow_root_element_types \ + |h \ get_shadow_root host|\<^sub>r = Some shadow_root_ptr))" + +definition a_heap_is_wellformed :: "(_) heap \ bool" + where + "a_heap_is_wellformed h \ CD.a_heap_is_wellformed h \ + acyclic (CD.a_parent_child_rel h \ a_host_shadow_root_rel h) \ + a_all_ptrs_in_heap h \ + a_distinct_lists h \ + a_shadow_root_valid h" +end + +global_interpretation l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_child_nodes get_child_nodes_locs + get_disconnected_nodes get_disconnected_nodes_locs get_shadow_root get_shadow_root_locs + get_tag_name get_tag_name_locs + defines heap_is_wellformed = a_heap_is_wellformed + and parent_child_rel = CD.a_parent_child_rel + and host_shadow_root_rel = a_host_shadow_root_rel + and all_ptrs_in_heap = a_all_ptrs_in_heap + and distinct_lists = a_distinct_lists + and shadow_root_valid = a_shadow_root_valid + and heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = CD.a_heap_is_wellformed + and parent_child_rel\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = CD.a_parent_child_rel + and acyclic_heap\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = CD.a_acyclic_heap + and all_ptrs_in_heap\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = CD.a_all_ptrs_in_heap + and distinct_lists\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = CD.a_distinct_lists + and owner_document_valid\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = CD.a_owner_document_valid + . + +interpretation i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M: l_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr type_wf + get_child_nodes get_child_nodes_locs get_disconnected_nodes get_disconnected_nodes_locs + heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M parent_child_rel + by (auto simp add: l_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def + heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def parent_child_rel_def instances) +declare i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.l_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_is_l_heap_is_wellformed [instances]: + "l_heap_is_wellformed type_wf known_ptr heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M parent_child_rel get_child_nodes + get_disconnected_nodes" + apply(auto simp add: l_heap_is_wellformed_def)[1] + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.heap_is_wellformed_children_in_heap apply blast + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.heap_is_wellformed_disc_nodes_in_heap apply blast + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.heap_is_wellformed_one_parent apply blast + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.heap_is_wellformed_one_disc_parent apply blast + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.heap_is_wellformed_children_disc_nodes_different apply blast + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.heap_is_wellformed_disconnected_nodes_distinct apply blast + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.heap_is_wellformed_children_distinct apply blast + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.heap_is_wellformed_children_disc_nodes apply blast + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.parent_child_rel_child apply (blast, blast) + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.parent_child_rel_finite apply blast + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.parent_child_rel_acyclic apply blast + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.parent_child_rel_node_ptr apply blast + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.parent_child_rel_parent_in_heap apply blast + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.parent_child_rel_child_in_heap apply blast + done + + +locale l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + get_child_nodes get_child_nodes_locs get_disconnected_nodes get_disconnected_nodes_locs + get_shadow_root get_shadow_root_locs get_tag_name get_tag_name_locs + + CD: l_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + known_ptr type_wf get_child_nodes get_child_nodes_locs get_disconnected_nodes + get_disconnected_nodes_locs heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M parent_child_rel + + l_heap_is_wellformed_defs + heap_is_wellformed parent_child_rel + + l_get_host\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + get_shadow_root get_shadow_root_locs get_host get_host_locs type_wf + + l_get_disconnected_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_nodes get_disconnected_nodes_locs + get_disconnected_document get_disconnected_document_locs type_wf + + l_get_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_shadow_root get_shadow_root_locs + for get_child_nodes :: "(_::linorder) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_disconnected_nodes :: "(_) document_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_tag_name :: "(_) element_ptr \ ((_) heap, exception, char list) prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and known_ptr :: "(_) object_ptr \ bool" + and type_wf :: "(_) heap \ bool" + and heap_is_wellformed :: "(_) heap \ bool" + and parent_child_rel :: "(_) heap \ ((_) object_ptr \ (_) object_ptr) set" + and heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and get_host :: "(_) shadow_root_ptr \ ((_) heap, exception, (_) element_ptr) prog" + and get_host_locs :: "((_) heap \ (_) heap \ bool) set" + and get_disconnected_document :: "(_) node_ptr \ ((_) heap, exception, (_) document_ptr) prog" + and get_disconnected_document_locs :: "((_) heap \ (_) heap \ bool) set" + + assumes heap_is_wellformed_impl: "heap_is_wellformed = a_heap_is_wellformed" +begin +lemmas heap_is_wellformed_def = + heap_is_wellformed_impl[unfolded a_heap_is_wellformed_def, + folded CD.heap_is_wellformed_impl CD.parent_child_rel_impl] + +lemma a_distinct_lists_code [code]: + "a_all_ptrs_in_heap h = ((\host \ fset (element_ptr_kinds h). + h \ ok (get_shadow_root host) \ (case |h \ get_shadow_root host|\<^sub>r of + Some shadow_root_ptr \ shadow_root_ptr |\| shadow_root_ptr_kinds h | + None \ True)))" + apply(auto simp add: a_all_ptrs_in_heap_def split: option.splits)[1] + by (meson is_OK_returns_result_I local.get_shadow_root_ptr_in_heap notin_fset select_result_I2) + +lemma get_shadow_root_shadow_root_ptr_in_heap: + assumes "heap_is_wellformed h" + assumes "h \ get_shadow_root host \\<^sub>r Some shadow_root_ptr" + shows "shadow_root_ptr |\| shadow_root_ptr_kinds h" + using assms + by(auto simp add: heap_is_wellformed_def a_all_ptrs_in_heap_def) + +lemma get_host_ptr_in_heap: + assumes "heap_is_wellformed h" + assumes "h \ get_host shadow_root_ptr \\<^sub>r host" + shows "shadow_root_ptr |\| shadow_root_ptr_kinds h" + using assms get_shadow_root_shadow_root_ptr_in_heap + by(auto simp add: get_host_def + elim!: bind_returns_result_E2 + dest!: filter_M_holds_for_result + intro!: bind_pure_I + split: list.splits) + +lemma shadow_root_same_host: + assumes "heap_is_wellformed h" and "type_wf h" + assumes "h \ get_shadow_root host \\<^sub>r Some shadow_root_ptr" + assumes "h \ get_shadow_root host' \\<^sub>r Some shadow_root_ptr" + shows "host = host'" +proof (rule ccontr) + assume " host \ host'" + have "host |\| element_ptr_kinds h" + using assms(3) + by (meson is_OK_returns_result_I local.get_shadow_root_ptr_in_heap) + moreover + have "host' |\| element_ptr_kinds h" + using assms(4) + by (meson is_OK_returns_result_I local.get_shadow_root_ptr_in_heap) + ultimately show False + using assms + apply(auto simp add: heap_is_wellformed_def a_distinct_lists_def)[1] + apply(drule distinct_concat_map_E(1)[where x=host and y=host']) + apply(simp) + apply(simp) + using \host \ host'\ apply(simp) + apply(auto)[1] + done +qed + +lemma shadow_root_host_dual: + assumes "h \ get_host shadow_root_ptr \\<^sub>r host" + shows "h \ get_shadow_root host \\<^sub>r Some shadow_root_ptr" + using assms + by(auto simp add: get_host_def + dest: filter_M_holds_for_result + elim!: bind_returns_result_E2 + intro!: bind_pure_I split: list.splits) + +lemma disc_doc_disc_node_dual: + assumes "h \ get_disconnected_document disc_node \\<^sub>r disc_doc" + obtains disc_nodes where + "h \ get_disconnected_nodes disc_doc \\<^sub>r disc_nodes" and + "disc_node \ set disc_nodes" + using assms get_disconnected_nodes_pure + by(auto simp add: get_disconnected_document_def bind_pure_I + dest!: filter_M_holds_for_result + elim!: bind_returns_result_E2 + intro!: filter_M_pure_I + split: if_splits list.splits) + +lemma get_host_valid_tag_name: + assumes "heap_is_wellformed h" and "type_wf h" + assumes "h \ get_host shadow_root_ptr \\<^sub>r host" + assumes "h \ get_tag_name host \\<^sub>r tag" + shows "tag \ safe_shadow_root_element_types" +proof - + obtain host' where + "host' |\| element_ptr_kinds h" and + "|h \ get_tag_name host'|\<^sub>r \ safe_shadow_root_element_types" + and "h \ get_shadow_root host' \\<^sub>r Some shadow_root_ptr" + using assms + apply(auto simp add: heap_is_wellformed_def a_shadow_root_valid_def)[1] + by (smt assms(1) finite_set_in get_host_ptr_in_heap local.get_shadow_root_ok + returns_result_select_result) + then have "host = host'" + by (meson assms(1) assms(2) assms(3) shadow_root_host_dual shadow_root_same_host) + then show ?thesis + by (smt\\thesis. (\host'. \host' |\| element_ptr_kinds h; + |h \ get_tag_name host'|\<^sub>r \ safe_shadow_root_element_types; + h \ get_shadow_root host' \\<^sub>r Some shadow_root_ptr\ \ thesis) \ thesis\ + \h \ get_shadow_root host' \\<^sub>r Some shadow_root_ptr\ assms(1) assms(2) assms(4) select_result_I2 + shadow_root_same_host) +qed + + +lemma a_host_shadow_root_rel_finite: "finite (a_host_shadow_root_rel h)" +proof - + have "a_host_shadow_root_rel h = (\host \ fset (element_ptr_kinds h). + (case |h \ get_shadow_root host|\<^sub>r of + Some shadow_root \ {(cast host, cast shadow_root)} | None \ {}))" + by(auto simp add: a_host_shadow_root_rel_def split: option.splits) + moreover have "finite (\host \ fset (element_ptr_kinds h). + (case |h \ get_shadow_root host|\<^sub>r of + Some shadow_root \ {(cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host, cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r shadow_root)} | + None \ {}))" + by(auto split: option.splits) + ultimately show ?thesis + by auto +qed + +lemma heap_is_wellformed_children_in_heap: + "heap_is_wellformed h \ h \ get_child_nodes ptr \\<^sub>r children \ child \ set children \ + child |\| node_ptr_kinds h" + using CD.heap_is_wellformed_children_in_heap local.heap_is_wellformed_def by blast +lemma heap_is_wellformed_disc_nodes_in_heap: + "heap_is_wellformed h \ h \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes \ + node \ set disc_nodes \ node |\| node_ptr_kinds h" + using CD.heap_is_wellformed_disc_nodes_in_heap local.heap_is_wellformed_def by blast +lemma heap_is_wellformed_one_parent: + "heap_is_wellformed h \ h \ get_child_nodes ptr \\<^sub>r children \ + h \ get_child_nodes ptr' \\<^sub>r children' \ set children \ set children' \ {} \ ptr = ptr'" + using CD.heap_is_wellformed_one_parent local.heap_is_wellformed_def by blast +lemma heap_is_wellformed_one_disc_parent: + "heap_is_wellformed h \ h \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes \ + h \ get_disconnected_nodes document_ptr' \\<^sub>r disc_nodes' \ set disc_nodes \ set disc_nodes' \ {} + \ document_ptr = document_ptr'" + using CD.heap_is_wellformed_one_disc_parent local.heap_is_wellformed_def by blast +lemma heap_is_wellformed_children_disc_nodes_different: + "heap_is_wellformed h \ h \ get_child_nodes ptr \\<^sub>r children \ + h \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes \ set children \ set disc_nodes = {}" + using CD.heap_is_wellformed_children_disc_nodes_different local.heap_is_wellformed_def by blast +lemma heap_is_wellformed_disconnected_nodes_distinct: + "heap_is_wellformed h \ h \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes \ + distinct disc_nodes" + using CD.heap_is_wellformed_disconnected_nodes_distinct local.heap_is_wellformed_def by blast +lemma heap_is_wellformed_children_distinct: + "heap_is_wellformed h \ h \ get_child_nodes ptr \\<^sub>r children \ distinct children" + using CD.heap_is_wellformed_children_distinct local.heap_is_wellformed_def by blast +lemma heap_is_wellformed_children_disc_nodes: + "heap_is_wellformed h \ node_ptr |\| node_ptr_kinds h \ + \(\parent \ fset (object_ptr_kinds h). node_ptr \ set |h \ get_child_nodes parent|\<^sub>r) \ + (\document_ptr \ fset (document_ptr_kinds h). + node_ptr \ set |h \ get_disconnected_nodes document_ptr|\<^sub>r)" + using CD.heap_is_wellformed_children_disc_nodes local.heap_is_wellformed_def by blast +lemma parent_child_rel_finite: "heap_is_wellformed h \ finite (parent_child_rel h)" + using CD.parent_child_rel_finite by blast +lemma parent_child_rel_acyclic: "heap_is_wellformed h \ acyclic (parent_child_rel h)" + using CD.parent_child_rel_acyclic heap_is_wellformed_def by blast +lemma parent_child_rel_child_in_heap: + "heap_is_wellformed h \ type_wf h \ known_ptr parent \ + (parent, child_ptr) \ parent_child_rel h \ child_ptr |\| object_ptr_kinds h" + using CD.parent_child_rel_child_in_heap local.heap_is_wellformed_def by blast +end + +interpretation i_heap_is_wellformed?: l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes + get_child_nodes_locs get_disconnected_nodes get_disconnected_nodes_locs get_shadow_root + get_shadow_root_locs get_tag_name get_tag_name_locs known_ptr type_wf heap_is_wellformed + parent_child_rel heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host get_host_locs get_disconnected_document + get_disconnected_document_locs + by(auto simp add: l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def + l_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def + heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def parent_child_rel_def heap_is_wellformed_def + instances) +declare l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma heap_is_wellformed_is_l_heap_is_wellformed [instances]: + "l_heap_is_wellformed ShadowRootClass.type_wf ShadowRootClass.known_ptr + Shadow_DOM.heap_is_wellformed Shadow_DOM.parent_child_rel Shadow_DOM.get_child_nodes + get_disconnected_nodes" + apply(auto simp add: l_heap_is_wellformed_def instances)[1] + using heap_is_wellformed_children_in_heap apply metis + using heap_is_wellformed_disc_nodes_in_heap apply metis + using heap_is_wellformed_one_parent apply blast + using heap_is_wellformed_one_disc_parent apply blast + using heap_is_wellformed_children_disc_nodes_different apply blast + using heap_is_wellformed_disconnected_nodes_distinct apply metis + using heap_is_wellformed_children_distinct apply metis + using heap_is_wellformed_children_disc_nodes apply metis + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.parent_child_rel_child apply(blast, blast) + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.parent_child_rel_finite apply blast + using parent_child_rel_acyclic apply blast + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.parent_child_rel_node_ptr apply blast + using i_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.parent_child_rel_parent_in_heap apply blast + using parent_child_rel_child_in_heap apply metis + done + + +subsubsection \get\_parent\ + +interpretation i_get_parent_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M: l_get_parent_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr type_wf get_child_nodes + get_child_nodes_locs known_ptrs get_parent get_parent_locs heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + parent_child_rel get_disconnected_nodes + by(simp add: l_get_parent_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare i_get_parent_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.l_get_parent_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +interpretation i_get_parent_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M: l_get_parent_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr type_wf get_child_nodes + get_child_nodes_locs known_ptrs get_parent get_parent_locs heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + parent_child_rel get_disconnected_nodes get_disconnected_nodes_locs + by(auto simp add: l_get_parent_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare i_get_parent_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.l_get_parent_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma get_parent_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_is_l_get_parent_wf [instances]: "l_get_parent_wf type_wf known_ptr + known_ptrs heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M parent_child_rel get_child_nodes get_parent" + apply(auto simp add: l_get_parent_wf_def l_get_parent_wf_axioms_def instances)[1] + using i_get_parent_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.child_parent_dual apply fast + using i_get_parent_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.heap_wellformed_induct apply metis + using i_get_parent_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.heap_wellformed_induct_rev apply metis + using i_get_parent_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.parent_child_rel_parent apply fast + done + + +subsubsection \get\_disconnected\_nodes\ + + +subsubsection \set\_disconnected\_nodes\ + + +paragraph \get\_disconnected\_nodes\ + +interpretation i_set_disconnected_nodes_get_disconnected_nodes_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M: + l_set_disconnected_nodes_get_disconnected_nodes_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr type_wf + get_disconnected_nodes get_disconnected_nodes_locs set_disconnected_nodes + set_disconnected_nodes_locs heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M parent_child_rel get_child_nodes + by (simp add: l_set_disconnected_nodes_get_disconnected_nodes_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare i_set_disconnected_nodes_get_disconnected_nodes_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.l_set_disconnected_nodes_get_disconnected_nodes_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma set_disconnected_nodes_get_disconnected_nodes_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_is_l_set_disconnected_nodes_get_disconnected_nodes_wf [instances]: + "l_set_disconnected_nodes_get_disconnected_nodes_wf type_wf known_ptr heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + parent_child_rel get_child_nodes get_disconnected_nodes get_disconnected_nodes_locs + set_disconnected_nodes set_disconnected_nodes_locs" + apply(auto simp add: l_set_disconnected_nodes_get_disconnected_nodes_wf_def + l_set_disconnected_nodes_get_disconnected_nodes_wf_axioms_def instances)[1] + using i_set_disconnected_nodes_get_disconnected_nodes_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.remove_from_disconnected_nodes_removes + apply fast + done + + +paragraph \get\_root\_node\ + +interpretation i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M:l_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr type_wf known_ptrs + heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M parent_child_rel get_child_nodes get_child_nodes_locs get_disconnected_nodes + get_disconnected_nodes_locs get_parent get_parent_locs get_ancestors get_ancestors_locs + get_root_node get_root_node_locs + by(simp add: l_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.l_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma get_ancestors_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_is_l_get_ancestors_wf [instances]: + "l_get_ancestors_wf heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M parent_child_rel known_ptr known_ptrs type_wf + get_ancestors get_ancestors_locs get_child_nodes get_parent" + apply(auto simp add: l_get_ancestors_wf_def l_get_ancestors_wf_axioms_def instances)[1] + using i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_ancestors_never_empty apply blast + using i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_ancestors_ok apply blast + using i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_ancestors_reads apply blast + using i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_ancestors_ptrs_in_heap apply blast + using i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_ancestors_remains_not_in_ancestors apply blast + using i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_ancestors_also_parent apply blast + using i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_ancestors_obtains_children apply blast + using i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_ancestors_parent_child_rel apply blast + using i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_ancestors_parent_child_rel apply blast + done + +lemma get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_is_l_get_root_node_wf [instances]: + "l_get_root_node_wf heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_root_node type_wf known_ptr known_ptrs + get_ancestors get_parent" + apply(auto simp add: l_get_root_node_wf_def l_get_root_node_wf_axioms_def instances)[1] + using i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_root_node_ok apply blast + using i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_root_node_ptr_in_heap apply blast + using i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_root_node_root_in_heap apply blast + using i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_ancestors_same_root_node apply(blast, blast) + using i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_root_node_same_no_parent apply blast + (* using i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_root_node_not_node_same apply blast *) + using i_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_root_node_parent_same apply (blast, blast) + done + + +subsubsection \to\_tree\_order\ + +interpretation i_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M: l_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr type_wf get_child_nodes + get_child_nodes_locs to_tree_order known_ptrs get_parent get_parent_locs heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + parent_child_rel get_disconnected_nodes get_disconnected_nodes_locs + apply(simp add: l_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) + done +declare i_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.l_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_is_l_to_tree_order_wf [instances]: + "l_to_tree_order_wf heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M parent_child_rel type_wf known_ptr known_ptrs + to_tree_order get_parent get_child_nodes" + apply(auto simp add: l_to_tree_order_wf_def l_to_tree_order_wf_axioms_def instances)[1] + using i_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.to_tree_order_ok apply blast + using i_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.to_tree_order_ptrs_in_heap apply blast + using i_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.to_tree_order_parent_child_rel apply(blast, blast) + using i_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.to_tree_order_child2 apply blast + using i_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.to_tree_order_node_ptrs apply blast + using i_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.to_tree_order_child apply blast + using i_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.to_tree_order_ptr_in_result apply blast + using i_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.to_tree_order_parent apply blast + using i_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.to_tree_order_subset apply blast + done + +paragraph \get\_root\_node\ + +interpretation i_to_tree_order_wf_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M: l_to_tree_order_wf_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + known_ptr type_wf known_ptrs heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M parent_child_rel get_child_nodes + get_child_nodes_locs get_disconnected_nodes get_disconnected_nodes_locs get_parent get_parent_locs + get_ancestors get_ancestors_locs get_root_node get_root_node_locs to_tree_order + by(auto simp add: l_to_tree_order_wf_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare i_to_tree_order_wf_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.l_to_tree_order_wf_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma to_tree_order_wf_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_is_l_to_tree_order_wf_get_root_node_wf [instances]: + "l_to_tree_order_wf_get_root_node_wf type_wf known_ptr known_ptrs to_tree_order get_root_node + heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M" + apply(auto simp add: l_to_tree_order_wf_get_root_node_wf_def + l_to_tree_order_wf_get_root_node_wf_axioms_def instances)[1] + using i_to_tree_order_wf_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.to_tree_order_get_root_node apply blast + using i_to_tree_order_wf_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.to_tree_order_same_root apply blast + done + +subsubsection \remove\_child\ + +interpretation i_remove_child_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M: l_remove_child_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes get_child_nodes_locs + set_child_nodes set_child_nodes_locs get_parent + get_parent_locs get_owner_document get_disconnected_nodes get_disconnected_nodes_locs + set_disconnected_nodes set_disconnected_nodes_locs remove_child remove_child_locs remove type_wf + known_ptr known_ptrs heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M parent_child_rel + by unfold_locales +declare i_remove_child_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.l_remove_child_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma remove_child_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_is_l_remove_child_wf2 [instances]: "l_remove_child_wf2 type_wf known_ptr + known_ptrs remove_child heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes remove" + apply(auto simp add: l_remove_child_wf2_def l_remove_child_wf2_axioms_def instances)[1] + using i_remove_child_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.remove_child_heap_is_wellformed_preserved apply(fast, fast, fast) + using i_remove_child_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.remove_heap_is_wellformed_preserved apply(fast, fast, fast) + using i_remove_child_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.remove_child_removes_child apply fast + using i_remove_child_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.remove_child_removes_first_child apply fast + using i_remove_child_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.remove_removes_child apply fast + using i_remove_child_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.remove_for_all_empty_children apply fast + done + + +subsection \A wellformed heap\ + +subsubsection \get\_parent\ + +interpretation i_get_parent_wf?: l_get_parent_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr type_wf get_child_nodes + get_child_nodes_locs known_ptrs get_parent get_parent_locs heap_is_wellformed parent_child_rel + get_disconnected_nodes + using instances + by(simp add: l_get_parent_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def) +declare l_get_parent_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma get_parent_wf_is_l_get_parent_wf [instances]: + "l_get_parent_wf ShadowRootClass.type_wf ShadowRootClass.known_ptr ShadowRootClass.known_ptrs + heap_is_wellformed parent_child_rel Shadow_DOM.get_child_nodes Shadow_DOM.get_parent" + apply(auto simp add: l_get_parent_wf_def l_get_parent_wf_axioms_def instances)[1] + using child_parent_dual apply blast + using heap_wellformed_induct apply metis + using heap_wellformed_induct_rev apply metis + using parent_child_rel_parent apply metis + done + + + +subsubsection \remove\_shadow\_root\ + +locale l_remove_shadow_root_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_tag_name + + l_get_disconnected_nodes + + l_set_shadow_root_get_tag_name + + l_get_child_nodes + + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_remove_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_delete_shadow_root_get_disconnected_nodes + + l_delete_shadow_root_get_child_nodes + + l_set_shadow_root_get_disconnected_nodes + + l_set_shadow_root_get_child_nodes + + l_delete_shadow_root_get_tag_name + + l_set_shadow_root_get_shadow_root + + l_delete_shadow_root_get_shadow_root + + l_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin + +lemma remove_shadow_root_preserves: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ remove_shadow_root ptr \\<^sub>h h'" + shows "known_ptrs h'" and "type_wf h'" "heap_is_wellformed h'" +proof - + obtain shadow_root_ptr h2 where + "h \ get_shadow_root ptr \\<^sub>r Some shadow_root_ptr" and + "h \ get_child_nodes (cast shadow_root_ptr) \\<^sub>r []" and + h2: "h \ set_shadow_root ptr None \\<^sub>h h2" and + h': "h2 \ delete_M shadow_root_ptr \\<^sub>h h'" + using assms(4) + by(auto simp add: remove_shadow_root_def + elim!: bind_returns_heap_E bind_returns_heap_E2[rotated, OF get_shadow_root_pure, rotated] + bind_returns_heap_E2[rotated, OF get_child_nodes_pure, rotated] + split: option.splits if_splits) + + have "type_wf h2" + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", OF set_shadow_root_writes h2] + using \type_wf h\ set_shadow_root_types_preserved + by(auto simp add: reflp_def transp_def) + then show "type_wf h'" + using h' delete_shadow_root_type_wf_preserved local.type_wf_impl + by blast + + have object_ptr_kinds_eq_h: "object_ptr_kinds h = object_ptr_kinds h2" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h = object_ptr_kinds h'", + OF set_shadow_root_writes h2]) + using set_shadow_root_pointers_preserved + apply blast + by (auto simp add: reflp_def transp_def) + have node_ptr_kinds_eq_h: "node_ptr_kinds h = node_ptr_kinds h2" + using object_ptr_kinds_eq_h + by (simp add: node_ptr_kinds_def) + have element_ptr_kinds_eq_h: "element_ptr_kinds h = element_ptr_kinds h2" + using node_ptr_kinds_eq_h + by (simp add: element_ptr_kinds_def) + have document_ptr_kinds_eq_h: "document_ptr_kinds h = document_ptr_kinds h2" + using object_ptr_kinds_eq_h + by (simp add: document_ptr_kinds_def) + have shadow_root_ptr_kinds_eq_h: "shadow_root_ptr_kinds h = shadow_root_ptr_kinds h2" + using object_ptr_kinds_eq_h + by (simp add: shadow_root_ptr_kinds_def) + + have "known_ptrs h2" + using \known_ptrs h\ object_ptr_kinds_eq_h known_ptrs_subset + by blast + + have object_ptr_kinds_eq_h2: "object_ptr_kinds h' |\| object_ptr_kinds h2" + using h' delete_shadow_root_pointers + by auto + have object_ptr_kinds_eq2_h2: + "object_ptr_kinds h2 = object_ptr_kinds h' |\| {|cast shadow_root_ptr|}" + using h' delete_shadow_root_pointers + by auto + have node_ptr_kinds_eq_h2: "node_ptr_kinds h2 = node_ptr_kinds h'" + using object_ptr_kinds_eq_h2 + by(auto simp add: node_ptr_kinds_def delete_shadow_root_pointers[OF h']) + have element_ptr_kinds_eq_h2: "element_ptr_kinds h2 = element_ptr_kinds h'" + using node_ptr_kinds_eq_h2 + by (simp add: element_ptr_kinds_def) + have document_ptr_kinds_eq_h2: "document_ptr_kinds h2 = document_ptr_kinds h'" + using object_ptr_kinds_eq_h2 + by(auto simp add: document_ptr_kinds_def delete_shadow_root_pointers[OF h']) + have shadow_root_ptr_kinds_eq_h2: "shadow_root_ptr_kinds h' |\| shadow_root_ptr_kinds h2" + using object_ptr_kinds_eq_h2 + by (auto simp add: shadow_root_ptr_kinds_def) + have shadow_root_ptr_kinds_eq2_h2: + "shadow_root_ptr_kinds h2 = shadow_root_ptr_kinds h' |\| {|shadow_root_ptr|}" + using object_ptr_kinds_eq2_h2 + apply (auto simp add: shadow_root_ptr_kinds_def)[1] + by (metis \h \ get_shadow_root ptr \\<^sub>r Some shadow_root_ptr\ assms(1) + fset.map_comp local.get_shadow_root_shadow_root_ptr_in_heap object_ptr_kinds_eq_h + shadow_root_ptr_kinds_def) + + show "known_ptrs h'" + using object_ptr_kinds_eq_h2 \known_ptrs h2\ known_ptrs_subset + by blast + + + have disconnected_nodes_eq_h: + "\doc_ptr disc_nodes. h \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes = + h2 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using get_disconnected_nodes_reads set_shadow_root_writes h2 set_shadow_root_get_disconnected_nodes + by(rule reads_writes_preserved) + then have disconnected_nodes_eq2_h: + "\doc_ptr. |h \ get_disconnected_nodes doc_ptr|\<^sub>r = |h2 \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + + have disconnected_nodes_eq_h2: + "\doc_ptr disc_nodes. h2 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes = + h' \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using get_disconnected_nodes_reads get_disconnected_nodes_delete_shadow_root[OF h'] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have disconnected_nodes_eq2_h2: + "\doc_ptr. |h2 \ get_disconnected_nodes doc_ptr|\<^sub>r = |h' \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + + have tag_name_eq_h: + "\doc_ptr disc_nodes. h \ get_tag_name doc_ptr \\<^sub>r disc_nodes = + h2 \ get_tag_name doc_ptr \\<^sub>r disc_nodes" + using get_tag_name_reads set_shadow_root_writes h2 set_shadow_root_get_tag_name + by(rule reads_writes_preserved) + then have tag_name_eq2_h: "\doc_ptr. |h \ get_tag_name doc_ptr|\<^sub>r = |h2 \ get_tag_name doc_ptr|\<^sub>r" + using select_result_eq by force + + have tag_name_eq_h2: + "\doc_ptr disc_nodes. h2 \ get_tag_name doc_ptr \\<^sub>r disc_nodes = + h' \ get_tag_name doc_ptr \\<^sub>r disc_nodes" + using get_tag_name_reads get_tag_name_delete_shadow_root[OF h'] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have tag_name_eq2_h2: "\doc_ptr. |h2 \ get_tag_name doc_ptr|\<^sub>r = |h' \ get_tag_name doc_ptr|\<^sub>r" + using select_result_eq by force + + + have children_eq_h: + "\ptr' children. h \ get_child_nodes ptr' \\<^sub>r children = h2 \ get_child_nodes ptr' \\<^sub>r children" + using get_child_nodes_reads set_shadow_root_writes h2 set_shadow_root_get_child_nodes + by(rule reads_writes_preserved) + + then have children_eq2_h: "\ptr'. |h \ get_child_nodes ptr'|\<^sub>r = |h2 \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + + + have children_eq_h2: + "\ptr' children. ptr' \ cast shadow_root_ptr \ h2 \ get_child_nodes ptr' \\<^sub>r children = + h' \ get_child_nodes ptr' \\<^sub>r children" + using get_child_nodes_reads h' get_child_nodes_delete_shadow_root + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have children_eq2_h2: + "\ptr'. ptr' \ cast shadow_root_ptr \ |h2 \ get_child_nodes ptr'|\<^sub>r = + |h' \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + + have "cast shadow_root_ptr |\| object_ptr_kinds h'" + using h' delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_ptr_not_in_heap + by auto + + have get_shadow_root_eq_h: + "\shadow_root_opt ptr'. ptr \ ptr' \ h \ get_shadow_root ptr' \\<^sub>r shadow_root_opt = + h2 \ get_shadow_root ptr' \\<^sub>r shadow_root_opt" + using get_shadow_root_reads set_shadow_root_writes h2 + apply(rule reads_writes_preserved) + using set_shadow_root_get_shadow_root_different_pointers + by fast + + have get_shadow_root_eq_h2: + "\shadow_root_opt ptr'. h2 \ get_shadow_root ptr' \\<^sub>r shadow_root_opt = + h' \ get_shadow_root ptr' \\<^sub>r shadow_root_opt" + using get_shadow_root_reads get_shadow_root_delete_shadow_root[OF h'] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then + have get_shadow_root_eq2_h2: "\ptr'. |h2 \ get_shadow_root ptr'|\<^sub>r = + |h' \ get_shadow_root ptr'|\<^sub>r" + using select_result_eq by force + + + + have "acyclic (parent_child_rel h)" + using \heap_is_wellformed h\ + by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def CD.acyclic_heap_def) + moreover + have "parent_child_rel h = parent_child_rel h2" + by(auto simp add: CD.parent_child_rel_def object_ptr_kinds_eq_h children_eq2_h) + moreover + have "parent_child_rel h' \ parent_child_rel h2" + using object_ptr_kinds_eq_h2 + apply(auto simp add: CD.parent_child_rel_def)[1] + by (metis \cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r shadow_root_ptr |\| object_ptr_kinds h'\ children_eq2_h2) + ultimately + have "CD.a_acyclic_heap h'" + using acyclic_subset + by (auto simp add: heap_is_wellformed_def CD.heap_is_wellformed_def CD.acyclic_heap_def) + + moreover + have "CD.a_all_ptrs_in_heap h" + using \heap_is_wellformed h\ + by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_all_ptrs_in_heap h2" + by(auto simp add: children_eq2_h disconnected_nodes_eq2_h document_ptr_kinds_eq_h + CD.a_all_ptrs_in_heap_def object_ptr_kinds_eq_h node_ptr_kinds_def + children_eq_h disconnected_nodes_eq_h) + then have "CD.a_all_ptrs_in_heap h'" + apply(auto simp add: CD.a_all_ptrs_in_heap_def node_ptr_kinds_eq_h2 children_eq_h2 + disconnected_nodes_eq_h2)[1] + apply(case_tac "ptr = cast shadow_root_ptr") + using object_ptr_kinds_eq_h2 children_eq_h2 + apply (meson \cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r shadow_root_ptr |\| object_ptr_kinds h'\ + is_OK_returns_result_I local.get_child_nodes_ptr_in_heap) + apply (metis (no_types, lifting) children_eq2_h2 fin_mono finite_set_in object_ptr_kinds_eq_h2 + subsetD) + by (metis (full_types) assms(1) assms(2) disconnected_nodes_eq2_h disconnected_nodes_eq2_h2 + document_ptr_kinds_eq_h document_ptr_kinds_eq_h2 local.get_disconnected_nodes_ok + local.heap_is_wellformed_disc_nodes_in_heap node_ptr_kinds_eq_h node_ptr_kinds_eq_h2 + returns_result_select_result) + + moreover + have "CD.a_distinct_lists h" + using \heap_is_wellformed h\ + by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_distinct_lists h2" + by(auto simp add: CD.a_distinct_lists_def object_ptr_kinds_eq_h document_ptr_kinds_eq_h + children_eq2_h disconnected_nodes_eq2_h) + then have "CD.a_distinct_lists h'" + apply(auto simp add: CD.a_distinct_lists_def document_ptr_kinds_eq_h2 + disconnected_nodes_eq2_h2)[1] + apply(auto simp add: intro!: distinct_concat_map_I)[1] + apply(case_tac "x = cast shadow_root_ptr") + using \cast shadow_root_ptr |\| object_ptr_kinds h'\ apply simp + using children_eq_h2 concat_map_all_distinct[of "(\ptr. |h2 \ get_child_nodes ptr|\<^sub>r)"] + apply (metis (no_types, lifting) children_eq2_h2 finite_fset fmember.rep_eq fset_mp + object_ptr_kinds_eq_h2 set_sorted_list_of_set) + apply(case_tac "x = cast shadow_root_ptr") + using \cast shadow_root_ptr |\| object_ptr_kinds h'\ apply simp + apply(case_tac "y = cast shadow_root_ptr") + using \cast shadow_root_ptr |\| object_ptr_kinds h'\ apply simp + using children_eq_h2 distinct_concat_map_E(1)[of "(\ptr. |h2 \ get_child_nodes ptr|\<^sub>r)"] + apply (smt IntI children_eq2_h2 empty_iff finite_fset fmember.rep_eq fset_mp + object_ptr_kinds_eq_h2 set_sorted_list_of_set) + apply(case_tac "xa = cast shadow_root_ptr") + using \cast shadow_root_ptr |\| object_ptr_kinds h'\ apply simp + by (smt \local.CD.a_distinct_lists h2\ \type_wf h'\ children_eq2_h2 disconnected_nodes_eq_h2 + fset_mp is_OK_returns_result_E local.CD.distinct_lists_no_parent + local.get_disconnected_nodes_ok object_ptr_kinds_eq_h2 select_result_I2) + + moreover + have "CD.a_owner_document_valid h" + using \heap_is_wellformed h\ + by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_owner_document_valid h2" + by(auto simp add: CD.a_owner_document_valid_def object_ptr_kinds_eq_h document_ptr_kinds_eq_h + node_ptr_kinds_eq_h children_eq2_h disconnected_nodes_eq2_h) + then have "CD.a_owner_document_valid h'" + apply(auto simp add: CD.a_owner_document_valid_def document_ptr_kinds_eq_h2 node_ptr_kinds_eq_h2 + disconnected_nodes_eq2_h2)[1] + proof - + fix node_ptr + assume 0: "\node_ptr\fset (node_ptr_kinds h'). + (\document_ptr. document_ptr |\| document_ptr_kinds h' \ + node_ptr \ set |h' \ get_disconnected_nodes document_ptr|\<^sub>r) \ + (\parent_ptr. parent_ptr |\| object_ptr_kinds h2 \ + node_ptr \ set |h2 \ get_child_nodes parent_ptr|\<^sub>r)" + and 1: "node_ptr |\| node_ptr_kinds h'" + and 2: "\parent_ptr. parent_ptr |\| object_ptr_kinds h' \ + node_ptr \ set |h' \ get_child_nodes parent_ptr|\<^sub>r" + then have "\parent_ptr. parent_ptr |\| object_ptr_kinds h2 \ + node_ptr \ set |h2 \ get_child_nodes parent_ptr|\<^sub>r" + apply(auto)[1] + apply(case_tac "parent_ptr = cast shadow_root_ptr") + using \h \ get_child_nodes (cast shadow_root_ptr) \\<^sub>r []\ children_eq_h + apply auto[1] + using children_eq2_h2 object_ptr_kinds_eq_h2 h' delete_shadow_root_pointers + by (metis fempty_iff finsert_iff funionE) + then show "\document_ptr. document_ptr |\| document_ptr_kinds h' \ + node_ptr \ set |h' \ get_disconnected_nodes document_ptr|\<^sub>r" + using 0 1 + by auto + qed + + ultimately have "heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M h'" + by(simp add: CD.heap_is_wellformed_def) + + moreover + have "acyclic (parent_child_rel h \ a_host_shadow_root_rel h)" + using \heap_is_wellformed h\ + by(simp add: heap_is_wellformed_def) + then + have "acyclic (parent_child_rel h2 \ a_host_shadow_root_rel h2)" + proof - + have "a_host_shadow_root_rel h2 \ a_host_shadow_root_rel h" + apply(auto simp add: a_host_shadow_root_rel_def element_ptr_kinds_eq_h)[1] + apply(case_tac "aa = ptr") + apply(simp) + apply (metis (no_types, lifting) \type_wf h2\ assms(2) h2 local.get_shadow_root_ok + local.type_wf_impl option.distinct(1) returns_result_eq + returns_result_select_result set_shadow_root_get_shadow_root) + using get_shadow_root_eq_h + by (metis (mono_tags, lifting) \type_wf h2\ image_eqI is_OK_returns_result_E + local.get_shadow_root_ok mem_Collect_eq prod.simps(2) select_result_I2) + then show ?thesis + using \parent_child_rel h = parent_child_rel h2\ + by (metis (no_types, hide_lams) \acyclic (parent_child_rel h \ a_host_shadow_root_rel h)\ + acyclic_subset order_refl sup_mono) + qed + then + have "acyclic (parent_child_rel h' \ a_host_shadow_root_rel h')" + proof - + have "a_host_shadow_root_rel h' \ a_host_shadow_root_rel h2" + by(auto simp add: a_host_shadow_root_rel_def element_ptr_kinds_eq_h2 get_shadow_root_eq2_h2) + then show ?thesis + using \parent_child_rel h' \ parent_child_rel h2\ + \acyclic (parent_child_rel h2 \ a_host_shadow_root_rel h2)\ + using acyclic_subset sup_mono + by (metis (no_types, hide_lams)) + qed + + moreover + have "a_all_ptrs_in_heap h" + using \heap_is_wellformed h\ + by(simp add: heap_is_wellformed_def) + then + have "a_all_ptrs_in_heap h2" + apply(auto simp add: a_all_ptrs_in_heap_def shadow_root_ptr_kinds_eq_h)[1] + apply(case_tac "host = ptr") + apply(simp) + apply (metis assms(2) h2 local.type_wf_impl option.distinct(1) returns_result_eq + set_shadow_root_get_shadow_root) + using get_shadow_root_eq_h + by fastforce + then + have "a_all_ptrs_in_heap h'" + apply(auto simp add: a_all_ptrs_in_heap_def get_shadow_root_eq_h2)[1] + apply(auto simp add: shadow_root_ptr_kinds_eq2_h2)[1] + by (metis (no_types, lifting) \h \ get_shadow_root ptr \\<^sub>r Some shadow_root_ptr\ assms(1) + assms(2) get_shadow_root_eq_h get_shadow_root_eq_h2 h2 local.shadow_root_same_host + local.type_wf_impl option.distinct(1) select_result_I2 set_shadow_root_get_shadow_root) + + moreover + have "a_distinct_lists h" + using \heap_is_wellformed h\ + by(simp add: heap_is_wellformed_def) + then + have "a_distinct_lists h2" + apply(auto simp add: a_distinct_lists_def element_ptr_kinds_eq_h)[1] + apply(auto intro!: distinct_concat_map_I split: option.splits)[1] + apply(case_tac "x = ptr") + apply(simp) + apply (metis (no_types, hide_lams) assms(2) h2 is_OK_returns_result_I + l_set_shadow_root_get_shadow_root.set_shadow_root_get_shadow_root + l_set_shadow_root_get_shadow_root_axioms local.type_wf_impl option.discI + returns_result_eq returns_result_select_result) + + apply(case_tac "y = ptr") + apply(simp) + apply (metis (no_types, hide_lams) assms(2) h2 is_OK_returns_result_I + l_set_shadow_root_get_shadow_root.set_shadow_root_get_shadow_root + l_set_shadow_root_get_shadow_root_axioms local.type_wf_impl option.discI + returns_result_eq returns_result_select_result) + by (metis \type_wf h2\ assms(1) assms(2) get_shadow_root_eq_h local.get_shadow_root_ok + local.shadow_root_same_host returns_result_select_result) + + then + have "a_distinct_lists h'" + by(auto simp add: a_distinct_lists_def element_ptr_kinds_eq_h2 get_shadow_root_eq2_h2) + + moreover + have "a_shadow_root_valid h" + using \heap_is_wellformed h\ + by(simp add: heap_is_wellformed_def) + then + have "a_shadow_root_valid h'" + apply(auto simp add: a_shadow_root_valid_def shadow_root_ptr_kinds_eq_h element_ptr_kinds_eq_h + tag_name_eq2_h)[1] + apply(simp add: shadow_root_ptr_kinds_eq2_h2 element_ptr_kinds_eq_h2 tag_name_eq2_h2) + using get_shadow_root_eq_h get_shadow_root_eq_h2 + by (smt \cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r shadow_root_ptr |\| object_ptr_kinds h'\ + \h \ get_shadow_root ptr \\<^sub>r Some shadow_root_ptr\ assms(2) element_ptr_kinds_eq_h + element_ptr_kinds_eq_h2 finite_set_in local.get_shadow_root_ok option.inject + returns_result_select_result select_result_I2 shadow_root_ptr_kinds_commutes) + + ultimately show "heap_is_wellformed h'" + by(simp add: heap_is_wellformed_def) +qed +end + +interpretation i_remove_shadow_root_wf?: l_remove_shadow_root_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + type_wf get_tag_name get_tag_name_locs get_disconnected_nodes get_disconnected_nodes_locs + set_shadow_root set_shadow_root_locs known_ptr get_child_nodes get_child_nodes_locs get_shadow_root + get_shadow_root_locs heap_is_wellformed parent_child_rel heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host + get_host_locs get_disconnected_document get_disconnected_document_locs remove_shadow_root + remove_shadow_root_locs known_ptrs get_parent get_parent_locs + by(auto simp add: l_remove_shadow_root_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_remove_shadow_root_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsubsection \get\_root\_node\ + +interpretation i_get_root_node_wf?: l_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr type_wf known_ptrs + heap_is_wellformed parent_child_rel get_child_nodes get_child_nodes_locs get_disconnected_nodes + get_disconnected_nodes_locs get_parent get_parent_locs get_ancestors get_ancestors_locs + get_root_node get_root_node_locs + by(simp add: l_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms[instances] + +lemma get_ancestors_wf_is_l_get_ancestors_wf [instances]: + "l_get_ancestors_wf heap_is_wellformed parent_child_rel known_ptr known_ptrs type_wf get_ancestors + get_ancestors_locs get_child_nodes get_parent" + apply(auto simp add: l_get_ancestors_wf_def l_get_ancestors_wf_axioms_def instances)[1] + using get_ancestors_never_empty apply blast + using get_ancestors_ok apply blast + using get_ancestors_reads apply blast + using get_ancestors_ptrs_in_heap apply blast + using get_ancestors_remains_not_in_ancestors apply blast + using get_ancestors_also_parent apply blast + using get_ancestors_obtains_children apply blast + using get_ancestors_parent_child_rel apply blast + using get_ancestors_parent_child_rel apply blast + done + +lemma get_root_node_wf_is_l_get_root_node_wf [instances]: + "l_get_root_node_wf heap_is_wellformed get_root_node type_wf known_ptr known_ptrs get_ancestors + get_parent" + using known_ptrs_is_l_known_ptrs + apply(auto simp add: l_get_root_node_wf_def l_get_root_node_wf_axioms_def)[1] + using get_root_node_ok apply blast + using get_root_node_ptr_in_heap apply blast + using get_root_node_root_in_heap apply blast + using get_ancestors_same_root_node apply(blast, blast) + using get_root_node_same_no_parent apply blast + (* using get_root_node_not_node_same apply blast *) + using get_root_node_parent_same apply (blast, blast) + done + +subsubsection \get\_parent\_get\_host\ + +locale l_get_parent_get_host_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_parent_wf + + l_get_shadow_root + + l_get_host + + l_get_child_nodes +begin +lemma host_shadow_root_rel_finite: "finite (a_host_shadow_root_rel h)" +proof - + have "a_host_shadow_root_rel h = (\host \ fset (element_ptr_kinds h). + (case |h \ get_shadow_root host|\<^sub>r of + Some shadow_root \ {(cast host, cast shadow_root)} | None \ {}))" + by(auto simp add: a_host_shadow_root_rel_def split: option.splits) + moreover have "finite (\host \ fset (element_ptr_kinds h). + (case |h \ get_shadow_root host|\<^sub>r of + Some shadow_root \ {(cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host, cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r shadow_root)} | + None \ {}))" + by(auto split: option.splits) + ultimately show ?thesis + by auto +qed + +lemma host_shadow_root_rel_shadow_root: + "h \ get_shadow_root host \\<^sub>r shadow_root_option \ + shadow_root_option = Some shadow_root \ ((cast host, cast shadow_root) \ a_host_shadow_root_rel h)" + apply(auto simp add: a_host_shadow_root_rel_def)[1] + by(metis (mono_tags, lifting) case_prodI is_OK_returns_result_I + l_get_shadow_root.get_shadow_root_ptr_in_heap local.l_get_shadow_root_axioms + mem_Collect_eq pair_imageI select_result_I2) + +lemma host_shadow_root_rel_host: + "heap_is_wellformed h \ h \ get_host shadow_root \\<^sub>r host \ + (cast host, cast shadow_root) \ a_host_shadow_root_rel h" + apply(auto simp add: a_host_shadow_root_rel_def)[1] + using shadow_root_host_dual + by (metis (no_types, lifting) Collect_cong host_shadow_root_rel_shadow_root + local.a_host_shadow_root_rel_def split_cong) + +lemma heap_wellformed_induct_si [consumes 1, case_names step]: + assumes "heap_is_wellformed h" + assumes "\parent. (\children child. h \ get_child_nodes parent \\<^sub>r children \ + child \ set children \ P (cast child)) \ (\shadow_root host. parent = cast host \ + h \ get_shadow_root host \\<^sub>r Some shadow_root \ P (cast shadow_root)) \ P parent" + shows "P ptr" +proof - + fix ptr + have "finite (parent_child_rel h \ a_host_shadow_root_rel h)" + using host_shadow_root_rel_finite + using local.CD.parent_child_rel_finite local.CD.parent_child_rel_impl + by auto + then + have "wf ((parent_child_rel h \ a_host_shadow_root_rel h)\)" + using assms(1) + apply(simp add: heap_is_wellformed_def) + by (simp add: finite_acyclic_wf_converse local.CD.parent_child_rel_impl) + then show "?thesis" + proof (induct rule: wf_induct_rule) + case (less parent) + then show ?case + apply(auto)[1] + using assms host_shadow_root_rel_shadow_root local.CD.parent_child_rel_child + by blast + qed +qed + +lemma heap_wellformed_induct_rev_si [consumes 1, case_names step]: + assumes "heap_is_wellformed h" + assumes "\child. (\parent child_node. child = cast child_node \ + h \ get_parent child_node \\<^sub>r Some parent \ P parent) \ + (\host shadow_root. child = cast shadow_root \ h \ get_host shadow_root \\<^sub>r host \ + P (cast host)) \ P child" + shows "P ptr" +proof - + fix ptr + have "finite (parent_child_rel h \ a_host_shadow_root_rel h)" + using host_shadow_root_rel_finite + using local.CD.parent_child_rel_finite local.CD.parent_child_rel_impl + by auto + then + have "wf (parent_child_rel h \ a_host_shadow_root_rel h)" + using assms(1) + apply(simp add: heap_is_wellformed_def) + by (simp add: finite_acyclic_wf) + then show "?thesis" + proof (induct rule: wf_induct_rule) + case (less parent) + then show ?case + apply(auto)[1] + using parent_child_rel_parent host_shadow_root_rel_host + using assms(1) assms(2) by auto + qed +qed +end + +interpretation i_get_parent_get_host_wf?: l_get_parent_get_host_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + get_child_nodes get_child_nodes_locs get_disconnected_nodes get_disconnected_nodes_locs + get_shadow_root get_shadow_root_locs get_tag_name get_tag_name_locs known_ptr type_wf + heap_is_wellformed parent_child_rel heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host get_host_locs + get_disconnected_document get_disconnected_document_locs known_ptrs get_parent get_parent_locs + by(auto simp add: l_get_parent_get_host_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_parent_get_host_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +locale l_get_parent_get_host_wf = + l_heap_is_wellformed_defs + + l_get_parent_defs + + l_get_shadow_root_defs + + l_get_host_defs + + l_get_child_nodes_defs + + assumes heap_wellformed_induct_si [consumes 1, case_names step]: + "heap_is_wellformed h + \ (\parent. (\children child. h \ get_child_nodes parent \\<^sub>r children \ child \ set children + \ P (cast child)) + \ (\shadow_root host. parent = cast host \ h \ get_shadow_root host \\<^sub>r Some shadow_root + \ P (cast shadow_root)) + \ P parent) + \ P ptr" + assumes heap_wellformed_induct_rev_si [consumes 1, case_names step]: + "heap_is_wellformed h + \ (\child. (\parent child_node. child = cast child_node \ + h \ get_parent child_node \\<^sub>r Some parent \ P parent) + \ (\host shadow_root. child = cast shadow_root \ h \ get_host shadow_root \\<^sub>r host + \ P (cast host)) + \ P child) + \ P ptr" + +lemma l_get_parent_get_host_wf_is_get_parent_get_host_wf [instances]: + "l_get_parent_get_host_wf heap_is_wellformed get_parent get_shadow_root get_host get_child_nodes" + apply(auto simp add: l_get_parent_get_host_wf_def instances)[1] + using heap_wellformed_induct_si apply metis + using heap_wellformed_induct_rev_si apply blast + done + + +subsubsection \get\_host\ + +locale l_get_host_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes get_child_nodes_locs get_disconnected_nodes + get_disconnected_nodes_locs get_shadow_root get_shadow_root_locs get_tag_name get_tag_name_locs + known_ptr type_wf heap_is_wellformed parent_child_rel heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host + get_host_locs + + l_type_wf type_wf + + l_get_host\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_shadow_root get_shadow_root_locs get_host get_host_locs type_wf + + l_get_shadow_root type_wf get_shadow_root get_shadow_root_locs + for known_ptr :: "(_::linorder) object_ptr \ bool" + and known_ptrs :: "(_) heap \ bool" + and type_wf :: "(_) heap \ bool" + and get_host :: "(_) shadow_root_ptr \ ((_) heap, exception, (_) element_ptr) prog" + and get_host_locs :: "((_) heap \ (_) heap \ bool) set" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_child_nodes :: "(_::linorder) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_disconnected_nodes :: "(_) document_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_tag_name :: "(_) element_ptr \ ((_) heap, exception, char list) prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and heap_is_wellformed :: "(_) heap \ bool" + and parent_child_rel :: "(_) heap \ ((_) object_ptr \ (_) object_ptr) set" + and heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" +begin + +lemma get_host_ok [simp]: + assumes "heap_is_wellformed h" + assumes "type_wf h" + assumes "known_ptrs h" + assumes "shadow_root_ptr |\| shadow_root_ptr_kinds h" + shows "h \ ok (get_host shadow_root_ptr)" +proof - + obtain host where host: "host |\| element_ptr_kinds h" + and "|h \ get_tag_name host|\<^sub>r \ safe_shadow_root_element_types" + and shadow_root: "h \ get_shadow_root host \\<^sub>r Some shadow_root_ptr" + using assms(1) assms(4) get_shadow_root_ok assms(2) + apply(auto simp add: heap_is_wellformed_def a_shadow_root_valid_def)[1] + by (smt finite_set_in returns_result_select_result) + + + obtain host_candidates where + host_candidates: "h \ filter_M (\element_ptr. Heap_Error_Monad.bind (get_shadow_root element_ptr) + (\shadow_root_opt. return (shadow_root_opt = Some shadow_root_ptr))) + (sorted_list_of_set (fset (element_ptr_kinds h))) + \\<^sub>r host_candidates" + apply(drule is_OK_returns_result_E[rotated]) + using get_shadow_root_ok assms(2) + by(auto intro!: filter_M_is_OK_I bind_pure_I bind_is_OK_I2) + then have "host_candidates = [host]" + apply(rule filter_M_ex1) + apply (simp add: host) + apply (smt assms(1) assms(2) bind_pure_returns_result_I2 bind_returns_result_E finite_set_in host + local.get_shadow_root_ok local.get_shadow_root_pure local.shadow_root_same_host + return_returns_result returns_result_eq shadow_root sorted_list_of_fset.rep_eq + sorted_list_of_fset_simps(1)) + by (simp_all add: assms(2) bind_pure_I bind_pure_returns_result_I2 host local.get_shadow_root_ok + returns_result_eq shadow_root) + then + show ?thesis + using host_candidates host assms(1) get_shadow_root_ok + apply(auto simp add: get_host_def known_ptrs_known_ptr + intro!: bind_is_OK_pure_I filter_M_pure_I filter_M_is_OK_I bind_pure_I split: list.splits)[1] + using assms(2) apply blast + apply (meson list.distinct(1) returns_result_eq) + by (meson list.distinct(1) list.inject returns_result_eq) +qed +end + +interpretation i_get_host_wf?: l_get_host_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_document + get_disconnected_document_locs known_ptr known_ptrs type_wf get_host get_host_locs get_shadow_root + get_shadow_root_locs get_child_nodes get_child_nodes_locs get_disconnected_nodes + get_disconnected_nodes_locs get_tag_name get_tag_name_locs heap_is_wellformed parent_child_rel + heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + by(auto simp add: l_get_host_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_host_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +locale l_get_host_wf = l_heap_is_wellformed_defs + l_known_ptrs + l_type_wf + l_get_host_defs + + assumes get_host_ok: + "heap_is_wellformed h \ known_ptrs h \ type_wf h \ + shadow_root_ptr |\| shadow_root_ptr_kinds h \ h \ ok (get_host shadow_root_ptr)" + +lemma get_host_wf_is_l_get_host_wf [instances]: + "l_get_host_wf heap_is_wellformed known_ptr known_ptrs type_wf get_host" + by(auto simp add: l_get_host_wf_def l_get_host_wf_axioms_def instances) + + +subsubsection \get\_root\_node\_si\ + +locale l_get_root_node_si_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_root_node_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_parent_wf + + l_get_parent_get_host_wf + + l_get_host_wf +begin +lemma get_root_node_si_ptr_in_heap: + assumes "h \ ok (get_root_node_si ptr)" + shows "ptr |\| object_ptr_kinds h" + using assms + unfolding get_root_node_si_def + using get_ancestors_si_ptr_in_heap + by auto + + +lemma get_ancestors_si_ok: + assumes "heap_is_wellformed h" and "known_ptrs h" and "type_wf h" + and "ptr |\| object_ptr_kinds h" + shows "h \ ok (get_ancestors_si ptr)" +proof (insert assms(1) assms(4), induct rule: heap_wellformed_induct_rev_si) + case (step child) + then show ?case + using assms(2) assms(3) + apply(auto simp add: get_ancestors_si_def[of child] assms(1) get_parent_parent_in_heap + intro!: bind_is_OK_pure_I + split: option.splits)[1] + using local.get_parent_ok apply blast + using get_host_ok assms(1) apply blast + by (meson assms(1) is_OK_returns_result_I local.get_shadow_root_ptr_in_heap + local.shadow_root_host_dual) +qed + +lemma get_ancestors_si_remains_not_in_ancestors: + assumes "heap_is_wellformed h" + and "heap_is_wellformed h'" + and "h \ get_ancestors_si ptr \\<^sub>r ancestors" + and "h' \ get_ancestors_si ptr \\<^sub>r ancestors'" + and "\p children children'. h \ get_child_nodes p \\<^sub>r children + \ h' \ get_child_nodes p \\<^sub>r children' \ set children' \ set children" + and "\p shadow_root_option shadow_root_option'. h \ get_shadow_root p \\<^sub>r shadow_root_option \ + h' \ get_shadow_root p \\<^sub>r shadow_root_option' \ (if shadow_root_option = None + then shadow_root_option' = None else shadow_root_option' = None \ + shadow_root_option' = shadow_root_option)" + and "node \ set ancestors" + and object_ptr_kinds_eq3: "object_ptr_kinds h = object_ptr_kinds h'" + and known_ptrs: "known_ptrs h" + and type_wf: "type_wf h" + and type_wf': "type_wf h'" + shows "node \ set ancestors'" +proof - + have object_ptr_kinds_M_eq: + "\ptrs. h \ object_ptr_kinds_M \\<^sub>r ptrs = h' \ object_ptr_kinds_M \\<^sub>r ptrs" + using object_ptr_kinds_eq3 + by(simp add: object_ptr_kinds_M_defs) + then have object_ptr_kinds_eq: "|h \ object_ptr_kinds_M|\<^sub>r = |h' \ object_ptr_kinds_M|\<^sub>r" + by(simp) + + show ?thesis + proof (insert assms(1) assms(3) assms(4) assms(7), induct ptr arbitrary: ancestors ancestors' + rule: heap_wellformed_induct_rev_si) + case (step child) + + obtain ancestors_remains where ancestors_remains: + "ancestors = child # ancestors_remains" + using \h \ get_ancestors_si child \\<^sub>r ancestors\ get_ancestors_si_never_empty + by(auto simp add: get_ancestors_si_def[of child] + elim!: bind_returns_result_E2 + split: option.splits) + obtain ancestors_remains' where ancestors_remains': + "ancestors' = child # ancestors_remains'" + using \h' \ get_ancestors_si child \\<^sub>r ancestors'\ get_ancestors_si_never_empty + by(auto simp add: get_ancestors_si_def[of child] + elim!: bind_returns_result_E2 + split: option.splits) + have "child |\| object_ptr_kinds h" + using local.get_ancestors_si_ptr_in_heap object_ptr_kinds_eq3 step.prems(2) by fastforce + + have "node \ child" + using ancestors_remains step.prems(3) by auto + + have 1: "\p parent. h' \ get_parent p \\<^sub>r Some parent \ h \ get_parent p \\<^sub>r Some parent" + proof - + fix p parent + assume "h' \ get_parent p \\<^sub>r Some parent" + then obtain children' where + children': "h' \ get_child_nodes parent \\<^sub>r children'" and + p_in_children': "p \ set children'" + using get_parent_child_dual by blast + obtain children where children: "h \ get_child_nodes parent \\<^sub>r children" + using get_child_nodes_ok assms(1) get_child_nodes_ptr_in_heap object_ptr_kinds_eq children' + known_ptrs + using type_wf type_wf' + by (metis \h' \ get_parent p \\<^sub>r Some parent\ get_parent_parent_in_heap is_OK_returns_result_E + local.known_ptrs_known_ptr object_ptr_kinds_eq3) + have "p \ set children" + using assms(5) children children' p_in_children' + by blast + then show "h \ get_parent p \\<^sub>r Some parent" + using child_parent_dual assms(1) children known_ptrs type_wf by blast + qed + + have 2: "\p host. h' \ get_host p \\<^sub>r host \ h \ get_host p \\<^sub>r host" + proof - + fix p host + assume "h' \ get_host p \\<^sub>r host" + then have "h' \ get_shadow_root host \\<^sub>r Some p" + using local.shadow_root_host_dual by blast + then have "h \ get_shadow_root host \\<^sub>r Some p" + by (metis assms(6) element_ptr_kinds_commutes is_OK_returns_result_I local.get_shadow_root_ok + local.get_shadow_root_ptr_in_heap node_ptr_kinds_commutes object_ptr_kinds_eq3 + option.distinct(1) returns_result_select_result type_wf) + then show "h \ get_host p \\<^sub>r host" + by (metis assms(1) is_OK_returns_result_E known_ptrs local.get_host_ok + local.get_shadow_root_shadow_root_ptr_in_heap local.shadow_root_host_dual + local.shadow_root_same_host type_wf) + + qed + + + show ?case + proof (cases "cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r child") + case None + then show ?thesis + using step(3) step(4) \node \ child\ + apply(auto simp add: get_ancestors_si_def[of child] + elim!: bind_returns_result_E2 + split: option.splits)[1] + by (metis "2" assms(1) l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M.shadow_root_same_host list.set_intros(2) + local.l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms local.shadow_root_host_dual step.hyps(2) + step.prems(3) type_wf) + next + case (Some node_child) + then + show ?thesis + using step(3) step(4) \node \ child\ + apply(auto simp add: get_ancestors_si_def[of child] + elim!: bind_returns_result_E2 + split: option.splits)[1] + apply (meson "1" option.distinct(1) returns_result_eq) + by (metis "1" list.set_intros(2) option.inject returns_result_eq step.hyps(1) step.prems(3)) + qed + qed +qed + + +lemma get_ancestors_si_ptrs_in_heap: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_ancestors_si ptr \\<^sub>r ancestors" + assumes "ptr' \ set ancestors" + shows "ptr' |\| object_ptr_kinds h" +proof (insert assms(4) assms(5), induct ancestors arbitrary: ptr) + case Nil + then show ?case + by(auto) +next + case (Cons a ancestors) + then obtain x where x: "h \ get_ancestors_si x \\<^sub>r a # ancestors" + by(auto simp add: get_ancestors_si_def[of a] elim!: bind_returns_result_E2 split: option.splits) + then have "x = a" + by(auto simp add: get_ancestors_si_def[of x] elim!: bind_returns_result_E2 split: option.splits) + then show ?case + proof (cases "ptr' = a") + case True + then show ?thesis + using Cons.hyps Cons.prems(2) get_ancestors_si_ptr_in_heap x + using \x = a\ by blast + next + case False + obtain ptr'' where ptr'': "h \ get_ancestors_si ptr'' \\<^sub>r ancestors" + using \ h \ get_ancestors_si x \\<^sub>r a # ancestors\ Cons.prems(2) False + by(auto simp add: get_ancestors_si_def[of x] elim!: bind_returns_result_E2 split: option.splits) + then show ?thesis + using Cons.hyps Cons.prems(2) False by auto + qed +qed + +lemma get_ancestors_si_reads: + assumes "heap_is_wellformed h" + shows "reads get_ancestors_si_locs (get_ancestors_si node_ptr) h h'" +proof (insert assms(1), induct rule: heap_wellformed_induct_rev_si) + case (step child) + then show ?case + using [[simproc del: Product_Type.unit_eq]] get_parent_reads[unfolded reads_def] + get_host_reads[unfolded reads_def] + apply(simp (no_asm) add: get_ancestors_si_def) + by(auto simp add: get_ancestors_si_locs_def get_parent_reads_pointers + intro!: reads_bind_pure reads_subset[OF check_in_heap_reads] + reads_subset[OF return_reads] reads_subset[OF get_parent_reads] + reads_subset[OF get_child_nodes_reads] reads_subset[OF get_host_reads] + split: option.splits) +qed + + +lemma get_ancestors_si_subset: + assumes "heap_is_wellformed h" + and "h \ get_ancestors_si ptr \\<^sub>r ancestors" + and "ancestor \ set ancestors" + and "h \ get_ancestors_si ancestor \\<^sub>r ancestor_ancestors" + and type_wf: "type_wf h" + and known_ptrs: "known_ptrs h" + shows "set ancestor_ancestors \ set ancestors" +proof (insert assms(1) assms(2) assms(3), induct ptr arbitrary: ancestors + rule: heap_wellformed_induct_rev_si) + case (step child) + have "child |\| object_ptr_kinds h" + using get_ancestors_si_ptr_in_heap step(3) by auto + (* then have "h \ check_in_heap child \\<^sub>r ()" + using returns_result_select_result by force *) + + + obtain tl_ancestors where tl_ancestors: "ancestors = child # tl_ancestors" + using step(3) + by(auto simp add: get_ancestors_si_def[of child] intro!: bind_pure_I + elim!: bind_returns_result_E2 split: option.splits) + show ?case + proof (induct "cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r child") + case None + show ?case + proof (induct "cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r child") + case None + then show ?case + using step(3) \None = cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r child\ + apply(auto simp add: get_ancestors_si_def[of child] elim!: bind_returns_result_E2)[1] + by (metis (no_types, lifting) assms(4) empty_iff empty_set select_result_I2 set_ConsD + step.prems(1) step.prems(2)) + next + case (Some shadow_root_child) + then + have "shadow_root_child |\| shadow_root_ptr_kinds h" + using \child |\| object_ptr_kinds h\ + by (metis (no_types, lifting) shadow_root_ptr_casts_commute shadow_root_ptr_kinds_commutes) + obtain host where host: "h \ get_host shadow_root_child \\<^sub>r host" + using get_host_ok assms + by (meson \shadow_root_child |\| shadow_root_ptr_kinds h\ is_OK_returns_result_E) + then + have "h \ get_ancestors_si (cast host) \\<^sub>r tl_ancestors" + using Some step(3) tl_ancestors None + by(auto simp add: get_ancestors_si_def[of child] intro!: bind_pure_returns_result_I + elim!: bind_returns_result_E2 split: option.splits dest: returns_result_eq) + then + show ?case + using step(2) Some host step(4) tl_ancestors + by (metis (no_types, lifting) assms(4) dual_order.trans eq_iff returns_result_eq set_ConsD + set_subset_Cons shadow_root_ptr_casts_commute step.prems(1)) + qed + next + case (Some child_node) + note s1 = Some + obtain parent_opt where parent_opt: "h \ get_parent child_node \\<^sub>r parent_opt" + using \child |\| object_ptr_kinds h\ assms(1) Some[symmetric] + get_parent_ok[OF type_wf known_ptrs] + by (metis (no_types, lifting) is_OK_returns_result_E known_ptrs get_parent_ok + l_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms node_ptr_casts_commute node_ptr_kinds_commutes) + then show ?case + proof (induct parent_opt) + case None + then have "ancestors = [child]" + using step(3) s1 + apply(simp add: get_ancestors_si_def) + by(auto elim!: bind_returns_result_E2 split: option.splits dest: returns_result_eq) + show ?case + using step(3) step(4) + apply(auto simp add: \ancestors = [child]\)[1] + using assms(4) returns_result_eq by fastforce + next + case (Some parent) + then + have "h \ get_ancestors_si parent \\<^sub>r tl_ancestors" + using s1 tl_ancestors step(3) + by(auto simp add: get_ancestors_si_def[of child] + elim!: bind_returns_result_E2 + split: option.splits dest: returns_result_eq) + show ?case + by (metis (no_types, lifting) Some.prems \h \ get_ancestors_si parent \\<^sub>r tl_ancestors\ + assms(4) eq_iff node_ptr_casts_commute order_trans s1 select_result_I2 set_ConsD + set_subset_Cons step.hyps(1) step.prems(1) step.prems(2) tl_ancestors) + qed + qed +qed + +lemma get_ancestors_si_also_parent: + assumes "heap_is_wellformed h" + and "h \ get_ancestors_si some_ptr \\<^sub>r ancestors" + and "cast child \ set ancestors" + and "h \ get_parent child \\<^sub>r Some parent" + and type_wf: "type_wf h" + and known_ptrs: "known_ptrs h" + shows "parent \ set ancestors" +proof - + obtain child_ancestors where child_ancestors: + "h \ get_ancestors_si (cast child) \\<^sub>r child_ancestors" + by (meson assms(1) assms(4) get_ancestors_si_ok is_OK_returns_result_I known_ptrs + local.get_parent_ptr_in_heap node_ptr_kinds_commutes returns_result_select_result + type_wf) + then have "parent \ set child_ancestors" + apply(simp add: get_ancestors_si_def) + by(auto elim!: bind_returns_result_E2 split: option.splits dest!: returns_result_eq[OF assms(4)] + get_ancestors_si_ptr) + then show ?thesis + using assms child_ancestors get_ancestors_si_subset by blast +qed + +lemma get_ancestors_si_also_host: + assumes "heap_is_wellformed h" + and "h \ get_ancestors_si some_ptr \\<^sub>r ancestors" + and "cast shadow_root \ set ancestors" + and "h \ get_host shadow_root \\<^sub>r host" + and type_wf: "type_wf h" + and known_ptrs: "known_ptrs h" + shows "cast host \ set ancestors" +proof - + obtain child_ancestors where child_ancestors: + "h \ get_ancestors_si (cast shadow_root) \\<^sub>r child_ancestors" + by (meson assms(1) assms(2) assms(3) get_ancestors_si_ok get_ancestors_si_ptrs_in_heap + is_OK_returns_result_E known_ptrs type_wf) + then have "cast host \ set child_ancestors" + apply(simp add: get_ancestors_si_def) + by(auto elim!: bind_returns_result_E2 split: option.splits dest!: returns_result_eq[OF assms(4)] + get_ancestors_si_ptr) + then show ?thesis + using assms child_ancestors get_ancestors_si_subset by blast +qed + +lemma get_ancestors_si_parent_child_rel: + assumes "heap_is_wellformed h" and "known_ptrs h" and "type_wf h" + assumes "h \ get_ancestors_si child \\<^sub>r ancestors" + assumes "((ptr, child) \ (parent_child_rel h)\<^sup>*)" + shows "ptr \ set ancestors" +proof (insert assms(5), induct ptr rule: heap_wellformed_induct_si[OF assms(1)]) + case (1 ptr) + then show ?case + proof (cases "ptr = child") + case True + then show ?thesis + using assms(4) local.get_ancestors_si_ptr by blast + next + case False + obtain ptr_child where + ptr_child: "(ptr, ptr_child) \ (parent_child_rel h) \ (ptr_child, child) \ (parent_child_rel h)\<^sup>*" + using converse_rtranclE[OF 1(3)] \ptr \ child\ + by metis + then obtain ptr_child_node + where ptr_child_ptr_child_node: "ptr_child = cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr_child_node" + using ptr_child node_ptr_casts_commute3 CD.parent_child_rel_node_ptr + by (metis ) + then obtain children where + children: "h \ get_child_nodes ptr \\<^sub>r children" and + ptr_child_node: "ptr_child_node \ set children" + proof - + assume a1: "\children. \h \ get_child_nodes ptr \\<^sub>r children; ptr_child_node \ set children\ + \ thesis" + + have "ptr |\| object_ptr_kinds h" + using CD.parent_child_rel_parent_in_heap ptr_child by blast + moreover have "ptr_child_node \ set |h \ get_child_nodes ptr|\<^sub>r" + by (metis calculation \known_ptrs h\ local.get_child_nodes_ok local.known_ptrs_known_ptr + CD.parent_child_rel_child ptr_child ptr_child_ptr_child_node + returns_result_select_result \type_wf h\) + ultimately show ?thesis + using a1 get_child_nodes_ok \type_wf h\ \known_ptrs h\ + by (meson local.known_ptrs_known_ptr returns_result_select_result) + qed + moreover have "(cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr_child_node, child) \ (parent_child_rel h)\<^sup>*" + using ptr_child ptr_child_ptr_child_node by auto + ultimately have "cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr_child_node \ set ancestors" + using 1 by auto + moreover have "h \ get_parent ptr_child_node \\<^sub>r Some ptr" + using assms(1) children ptr_child_node child_parent_dual + using \known_ptrs h\ \type_wf h\ by blast + ultimately show ?thesis + using get_ancestors_si_also_parent assms \type_wf h\ by blast + qed +qed + +lemma get_ancestors_si_parent_child_host_shadow_root_rel: + assumes "heap_is_wellformed h" and "known_ptrs h" and "type_wf h" + assumes "h \ get_ancestors_si child \\<^sub>r ancestors" + assumes "((ptr, child) \ (parent_child_rel h \ a_host_shadow_root_rel h)\<^sup>*)" + shows "ptr \ set ancestors" +proof (insert assms(5), induct ptr rule: heap_wellformed_induct_si[OF assms(1)]) + case (1 ptr) + then show ?case + proof (cases "ptr = child") + case True + then show ?thesis + using assms(4) local.get_ancestors_si_ptr by blast + next + case False + + obtain ptr_child where + ptr_child: "(ptr, ptr_child) \ (parent_child_rel h \ local.a_host_shadow_root_rel h) \ + (ptr_child, child) \ (parent_child_rel h \ local.a_host_shadow_root_rel h)\<^sup>*" + using converse_rtranclE[OF 1(3)] \ptr \ child\ + by metis + then show ?thesis + proof(cases "(ptr, ptr_child) \ parent_child_rel h") + case True + + then obtain ptr_child_node + where ptr_child_ptr_child_node: "ptr_child = cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr_child_node" + using ptr_child node_ptr_casts_commute3 CD.parent_child_rel_node_ptr + by (metis) + then obtain children where + children: "h \ get_child_nodes ptr \\<^sub>r children" and + ptr_child_node: "ptr_child_node \ set children" + proof - + assume a1: "\children. \h \ get_child_nodes ptr \\<^sub>r children; ptr_child_node \ set children\ + \ thesis" + + have "ptr |\| object_ptr_kinds h" + using CD.parent_child_rel_parent_in_heap True by blast + moreover have "ptr_child_node \ set |h \ get_child_nodes ptr|\<^sub>r" + by (metis True assms(2) assms(3) calculation local.CD.parent_child_rel_child + local.get_child_nodes_ok local.known_ptrs_known_ptr ptr_child_ptr_child_node + returns_result_select_result) + ultimately show ?thesis + using a1 get_child_nodes_ok \type_wf h\ \known_ptrs h\ + by (meson local.known_ptrs_known_ptr returns_result_select_result) + qed + moreover have "(cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr_child_node, child) \ + (parent_child_rel h \ local.a_host_shadow_root_rel h)\<^sup>*" + using ptr_child True ptr_child_ptr_child_node by auto + ultimately have "cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr_child_node \ set ancestors" + using 1 by auto + moreover have "h \ get_parent ptr_child_node \\<^sub>r Some ptr" + using assms(1) children ptr_child_node child_parent_dual + using \known_ptrs h\ \type_wf h\ by blast + ultimately show ?thesis + using get_ancestors_si_also_parent assms \type_wf h\ by blast + next + case False + then + obtain host where host: "ptr = cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host" + using ptr_child + by(auto simp add: a_host_shadow_root_rel_def) + then obtain shadow_root where shadow_root: "h \ get_shadow_root host \\<^sub>r Some shadow_root" + and ptr_child_shadow_root: "ptr_child = cast shadow_root" + using ptr_child False + apply(auto simp add: a_host_shadow_root_rel_def)[1] + by (metis (no_types, lifting) assms(3) local.get_shadow_root_ok select_result_I) + + moreover have "(cast shadow_root, child) \ (parent_child_rel h \ local.a_host_shadow_root_rel h)\<^sup>*" + using ptr_child ptr_child_shadow_root by blast + ultimately have "cast shadow_root \ set ancestors" + using "1.hyps"(2) host by blast + moreover have "h \ get_host shadow_root \\<^sub>r host" + by (metis assms(1) assms(2) assms(3) is_OK_returns_result_E local.get_host_ok + local.get_shadow_root_shadow_root_ptr_in_heap local.shadow_root_host_dual + local.shadow_root_same_host shadow_root) + ultimately show ?thesis + using get_ancestors_si_also_host assms(1) assms(2) assms(3) assms(4) host + by blast + qed + qed +qed + +lemma get_root_node_si_ok: + assumes "heap_is_wellformed h" and "known_ptrs h" and "type_wf h" + and "ptr |\| object_ptr_kinds h" + shows "h \ ok (get_root_node_si ptr)" + using assms get_ancestors_si_ok + by(auto simp add: get_root_node_si_def) + +lemma get_root_node_si_root_in_heap: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_root_node_si ptr \\<^sub>r root" + shows "root |\| object_ptr_kinds h" + using assms + apply(auto simp add: get_root_node_si_def elim!: bind_returns_result_E2)[1] + by (simp add: get_ancestors_si_never_empty get_ancestors_si_ptrs_in_heap) + +lemma get_root_node_si_same_no_parent: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_root_node_si ptr \\<^sub>r cast child" + shows "h \ get_parent child \\<^sub>r None" +proof (insert assms(1) assms(4), induct ptr rule: heap_wellformed_induct_rev_si) + case (step c) + then show ?case + proof (cases "cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r c") + case None + then show ?thesis + using step(3) + by(auto simp add: get_root_node_si_def get_ancestors_si_def[of c] + elim!: bind_returns_result_E2 + split: if_splits option.splits + intro!: step(2) bind_pure_returns_result_I) + next + case (Some child_node) + note s = this + then obtain parent_opt where parent_opt: "h \ get_parent child_node \\<^sub>r parent_opt" + using step(3) + apply(auto simp add: get_root_node_si_def get_ancestors_si_def + intro!: bind_pure_I + elim!: bind_returns_result_E2)[1] + by(auto split: option.splits) + then show ?thesis + proof(induct parent_opt) + case None + then show ?case + using Some get_root_node_si_no_parent returns_result_eq step.prems by fastforce + next + case (Some parent) + then show ?case + using step(3) s + apply(auto simp add: get_root_node_si_def get_ancestors_si_def[of c] + elim!: bind_returns_result_E2 split: option.splits list.splits if_splits)[1] + using assms(1) get_ancestors_si_never_empty apply blast + by(auto simp add: get_root_node_si_def + dest: returns_result_eq + intro!: step(1) bind_pure_returns_result_I) + qed + qed +qed +end + +interpretation i_get_root_node_si_wf?: l_get_root_node_si_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr known_ptrs + get_parent get_parent_locs get_child_nodes get_child_nodes_locs get_host get_host_locs + get_ancestors_si get_ancestors_si_locs get_root_node_si get_root_node_si_locs + get_disconnected_nodes get_disconnected_nodes_locs get_shadow_root get_shadow_root_locs + get_tag_name get_tag_name_locs heap_is_wellformed parent_child_rel heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + get_disconnected_document get_disconnected_document_locs + by(auto simp add: instances l_get_root_node_si_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def) +declare l_get_root_node_si_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsubsection \get\_disconnected\_document\ + +locale l_get_disconnected_document_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_disconnected_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_parent_wf + + l_get_parent +begin + +lemma get_disconnected_document_ok: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_parent node_ptr \\<^sub>r None" + shows "h \ ok (get_disconnected_document node_ptr)" +proof - + have "node_ptr |\| node_ptr_kinds h" + by (meson assms(4) is_OK_returns_result_I local.get_parent_ptr_in_heap) + have "\(\parent \ fset (object_ptr_kinds h). node_ptr \ set |h \ get_child_nodes parent|\<^sub>r)" + apply(auto)[1] + using assms(4) child_parent_dual[OF assms(1)] + assms(1) assms(2) assms(3) known_ptrs_known_ptr option.simps(3) + returns_result_eq returns_result_select_result + by (metis (no_types, lifting) CD.get_child_nodes_ok) + then + have "(\document_ptr \ fset (document_ptr_kinds h). node_ptr \ + set |h \ get_disconnected_nodes document_ptr|\<^sub>r)" + using heap_is_wellformed_children_disc_nodes + using \node_ptr |\| node_ptr_kinds h\ assms(1) by blast + then obtain some_owner_document where + "some_owner_document \ set (sorted_list_of_set (fset (document_ptr_kinds h)))" and + "node_ptr \ set |h \ get_disconnected_nodes some_owner_document|\<^sub>r" + by auto + + have h5: "\!x. x \ set (sorted_list_of_set (fset (document_ptr_kinds h))) \ + h \ Heap_Error_Monad.bind (get_disconnected_nodes x) + (\children. return (node_ptr \ set children)) \\<^sub>r True" + apply(auto intro!: bind_pure_returns_result_I)[1] + apply (smt CD.get_disconnected_nodes_ok CD.get_disconnected_nodes_pure + \\document_ptr\fset (document_ptr_kinds h). node_ptr \ + set |h \ get_disconnected_nodes document_ptr|\<^sub>r\ assms(2) + bind_pure_returns_result_I2 notin_fset return_returns_result select_result_I2) + + apply(auto elim!: bind_returns_result_E2 intro!: bind_pure_returns_result_I)[1] + using heap_is_wellformed_one_disc_parent assms(1) + by blast + let ?filter_M = "filter_M + (\document_ptr. + Heap_Error_Monad.bind (get_disconnected_nodes document_ptr) + (\disconnected_nodes. return (node_ptr \ set disconnected_nodes))) + (sorted_list_of_set (fset (document_ptr_kinds h)))" + have "h \ ok (?filter_M)" + using CD.get_disconnected_nodes_ok + by (smt CD.get_disconnected_nodes_pure DocumentMonad.ptr_kinds_M_ptr_kinds + DocumentMonad.ptr_kinds_ptr_kinds_M assms(2) bind_is_OK_pure_I bind_pure_I + document_ptr_kinds_M_def filter_M_is_OK_I l_ptr_kinds_M.ptr_kinds_M_ok return_ok + return_pure returns_result_select_result) + then + obtain candidates where candidates: "h \ filter_M + (\document_ptr. + Heap_Error_Monad.bind (get_disconnected_nodes document_ptr) + (\disconnected_nodes. return (node_ptr \ set disconnected_nodes))) + (sorted_list_of_set (fset (document_ptr_kinds h))) + \\<^sub>r candidates" + by auto + have "candidates = [some_owner_document]" + apply(rule filter_M_ex1[OF candidates \some_owner_document \ + set (sorted_list_of_set (fset (document_ptr_kinds h)))\ h5]) + using \node_ptr \ set |h \ get_disconnected_nodes some_owner_document|\<^sub>r\ + \some_owner_document \ set (sorted_list_of_set (fset (document_ptr_kinds h)))\ + by(auto simp add: CD.get_disconnected_nodes_ok assms(2) + intro!: bind_pure_I + intro!: bind_pure_returns_result_I) + then show ?thesis + using candidates \node_ptr |\| node_ptr_kinds h\ + apply(auto simp add: get_disconnected_document_def + intro!: bind_is_OK_pure_I filter_M_pure_I bind_pure_I + split: list.splits)[1] + apply (meson not_Cons_self2 returns_result_eq) + by (meson list.distinct(1) list.inject returns_result_eq) +qed +end + +interpretation i_get_disconnected_document_wf?: l_get_disconnected_document_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + get_child_nodes get_child_nodes_locs get_disconnected_nodes get_disconnected_nodes_locs + get_shadow_root get_shadow_root_locs get_tag_name get_tag_name_locs known_ptr type_wf + heap_is_wellformed parent_child_rel heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host get_host_locs + get_disconnected_document get_disconnected_document_locs known_ptrs get_parent get_parent_locs + by(auto simp add: l_get_disconnected_document_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_disconnected_document_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsubsection \get\_owner\_document\ + +locale l_get_owner_document_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_disconnected_nodes + + l_get_child_nodes + + l_get_owner_document\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_parent_wf + + l_known_ptrs + + l_get_root_node_si_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + assumes known_ptr_impl: "known_ptr = ShadowRootClass.known_ptr" +begin +lemma get_owner_document_disconnected_nodes: + assumes "heap_is_wellformed h" + assumes "h \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes" + assumes "node_ptr \ set disc_nodes" + assumes known_ptrs: "known_ptrs h" + assumes type_wf: "type_wf h" + shows "h \ get_owner_document (cast node_ptr) \\<^sub>r document_ptr" +proof - + have 2: "node_ptr |\| node_ptr_kinds h" + using assms + apply(auto simp add: heap_is_wellformed_def CD.heap_is_wellformed_def CD.a_all_ptrs_in_heap_def)[1] + using assms(1) local.heap_is_wellformed_disc_nodes_in_heap by blast + have 3: "document_ptr |\| document_ptr_kinds h" + using assms(2) get_disconnected_nodes_ptr_in_heap by blast + then have 4: "\(\parent_ptr. parent_ptr |\| object_ptr_kinds h \ + node_ptr \ set |h \ get_child_nodes parent_ptr|\<^sub>r)" + using CD.distinct_lists_no_parent assms + unfolding heap_is_wellformed_def CD.heap_is_wellformed_def by simp + moreover have "(\document_ptr. document_ptr |\| document_ptr_kinds h \ + node_ptr \ set |h \ get_disconnected_nodes document_ptr|\<^sub>r) \ + (\parent_ptr. parent_ptr |\| object_ptr_kinds h \ + node_ptr \ set |h \ get_child_nodes parent_ptr|\<^sub>r)" + using assms(1) 2 "3" assms(2) assms(3) by auto + ultimately have 0: "\!document_ptr\set |h \ document_ptr_kinds_M|\<^sub>r. + node_ptr \ set |h \ get_disconnected_nodes document_ptr|\<^sub>r" + using concat_map_distinct assms(1) known_ptrs_implies + by (smt CD.heap_is_wellformed_one_disc_parent DocumentMonad.ptr_kinds_ptr_kinds_M + disjoint_iff_not_equal local.get_disconnected_nodes_ok local.heap_is_wellformed_def + returns_result_select_result type_wf) + + + have "h \ get_parent node_ptr \\<^sub>r None" + using 4 2 + apply(auto simp add: get_parent_def + intro!: bind_pure_returns_result_I filter_M_pure_I bind_pure_I )[1] + apply(auto intro!: filter_M_empty_I bind_pure_I bind_pure_returns_result_I)[1] + using get_child_nodes_ok assms(4) type_wf + by (metis get_child_nodes_ok known_ptrs_known_ptr returns_result_select_result) + + + then have 4: "h \ get_root_node_si (cast node_ptr) \\<^sub>r cast node_ptr" + using get_root_node_si_no_parent + by simp + obtain document_ptrs where document_ptrs: "h \ document_ptr_kinds_M \\<^sub>r document_ptrs" + by simp + then have "h \ ok (filter_M (\document_ptr. do { + disconnected_nodes \ get_disconnected_nodes document_ptr; + return (((cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r node_ptr)) \ cast ` set disconnected_nodes) + }) document_ptrs)" + using assms(1) get_disconnected_nodes_ok type_wf + by(auto intro!: bind_is_OK_I2 filter_M_is_OK_I bind_pure_I) + then obtain candidates where + candidates: "h \ filter_M (\document_ptr. do { + disconnected_nodes \ get_disconnected_nodes document_ptr; + return (((cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r node_ptr)) \ cast ` set disconnected_nodes) + }) document_ptrs \\<^sub>r candidates" + by auto + + have filter: "filter (\document_ptr. |h \ do { + disconnected_nodes \ get_disconnected_nodes document_ptr; + return (cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r node_ptr \ cast ` set disconnected_nodes) + }|\<^sub>r) document_ptrs = [document_ptr]" + apply(rule filter_ex1) + using 0 document_ptrs apply(simp)[1] + apply (smt "0" "3" assms bind_is_OK_pure_I bind_pure_returns_result_I bind_pure_returns_result_I2 + bind_returns_result_E2 bind_returns_result_E3 document_ptr_kinds_M_def get_disconnected_nodes_ok + get_disconnected_nodes_pure image_eqI is_OK_returns_result_E l_ptr_kinds_M.ptr_kinds_ptr_kinds_M + return_ok return_returns_result returns_result_eq select_result_E select_result_I select_result_I2 + select_result_I2) + using assms(2) assms(3) + apply (metis (no_types, lifting) bind_pure_returns_result_I2 is_OK_returns_result_I + local.get_disconnected_nodes_pure node_ptr_inclusion return_returns_result select_result_I2) + using document_ptrs 3 apply(simp) + using document_ptrs + by simp + have "h \ filter_M (\document_ptr. do { + disconnected_nodes \ get_disconnected_nodes document_ptr; + return (((cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r node_ptr)) \ cast ` set disconnected_nodes) + }) document_ptrs \\<^sub>r [document_ptr]" + apply(rule filter_M_filter2) + using get_disconnected_nodes_ok document_ptrs 3 assms(1) type_wf filter + by(auto intro: bind_pure_I bind_is_OK_I2) + + with 4 document_ptrs have "h \ CD.a_get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r node_ptr () \\<^sub>r document_ptr" + by(auto simp add: CD.a_get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def + intro!: bind_pure_returns_result_I filter_M_pure_I bind_pure_I split: option.splits) + moreover have "known_ptr (cast node_ptr)" + using known_ptrs_known_ptr[OF known_ptrs, where ptr="cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r node_ptr"] 2 + known_ptrs_implies + by(simp) + ultimately show ?thesis + using 2 + apply(auto simp add: CD.a_get_owner_document_tups_def get_owner_document_def + a_get_owner_document_tups_def known_ptr_impl)[1] + apply(split invoke_splits, (rule conjI | rule impI)+)+ + apply(drule(1) known_ptr_not_shadow_root_ptr) + apply(drule(1) known_ptr_not_document_ptr) + apply(drule(1) known_ptr_not_character_data_ptr) + apply(drule(1) known_ptr_not_element_ptr) + apply(simp add: NodeClass.known_ptr_defs) + by(auto split: option.splits intro!: bind_pure_returns_result_I) +qed + +lemma in_disconnected_nodes_no_parent: + assumes "heap_is_wellformed h" + assumes "h \ get_parent node_ptr \\<^sub>r None" + assumes "h \ get_owner_document (cast node_ptr) \\<^sub>r owner_document" + assumes "h \ get_disconnected_nodes owner_document \\<^sub>r disc_nodes" + assumes "known_ptrs h" + assumes "type_wf h" + shows "node_ptr \ set disc_nodes" +proof - + have "\parent. parent |\| object_ptr_kinds h \ node_ptr \ set |h \ get_child_nodes parent|\<^sub>r" + using assms(2) + by (meson get_child_nodes_ok assms(1) assms(5) assms(6) local.child_parent_dual + local.known_ptrs_known_ptr option.distinct(1) returns_result_eq returns_result_select_result) + then show ?thesis + by (smt assms(1) assms(2) assms(3) assms(4) assms(5) assms(6) finite_set_in is_OK_returns_result_I + local.get_disconnected_nodes_ok local.get_owner_document_disconnected_nodes + local.get_parent_ptr_in_heap local.heap_is_wellformed_children_disc_nodes + returns_result_select_result select_result_I2) +qed + + +lemma get_owner_document_owner_document_in_heap_node: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ CD.a_get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r node_ptr () \\<^sub>r owner_document" + shows "owner_document |\| document_ptr_kinds h" +proof - + obtain root where + root: "h \ get_root_node_si (cast node_ptr) \\<^sub>r root" + using assms(4) + by(auto simp add: CD.a_get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def + elim!: bind_returns_result_E2 + split: option.splits) + + then show ?thesis + proof (cases "is_document_ptr root") + case True + then show ?thesis + using assms(4) root + apply(auto simp add: CD.a_get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def elim!: bind_returns_result_E2 + intro!: filter_M_pure_I bind_pure_I split: option.splits)[1] + apply(drule(1) returns_result_eq) apply(auto)[1] + using assms document_ptr_kinds_commutes get_root_node_si_root_in_heap + by blast + next + case False + have "known_ptr root" + using assms local.get_root_node_si_root_in_heap local.known_ptrs_known_ptr root by blast + have "root |\| object_ptr_kinds h" + using root + using assms local.get_root_node_si_root_in_heap + by blast + + have "\is_shadow_root_ptr root" + using root + using local.get_root_node_si_root_not_shadow_root by blast + then have "is_node_ptr_kind root" + using False \known_ptr root\ \root |\| object_ptr_kinds h\ + apply(simp add: known_ptr_impl known_ptr_defs DocumentClass.known_ptr_defs + CharacterDataClass.known_ptr_defs ElementClass.known_ptr_defs NodeClass.known_ptr_defs) + using is_node_ptr_kind_none by force + then + have "(\document_ptr \ fset (document_ptr_kinds h). +root \ cast ` set |h \ get_disconnected_nodes document_ptr|\<^sub>r)" + using local.child_parent_dual local.get_child_nodes_ok local.get_root_node_si_same_no_parent + local.heap_is_wellformed_children_disc_nodes local.known_ptrs_known_ptr node_ptr_casts_commute3 + node_ptr_inclusion node_ptr_kinds_commutes notin_fset option.distinct(1) returns_result_eq + returns_result_select_result root + by (metis (no_types, lifting) assms \root |\| object_ptr_kinds h\) + then obtain some_owner_document where + "some_owner_document |\| document_ptr_kinds h" and + "root \ cast ` set |h \ get_disconnected_nodes some_owner_document|\<^sub>r" + by auto + then + obtain candidates where + candidates: "h \ filter_M + (\document_ptr. + Heap_Error_Monad.bind (get_disconnected_nodes document_ptr) + (\disconnected_nodes. return (root \ cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ` set disconnected_nodes))) + (sorted_list_of_set (fset (document_ptr_kinds h))) + \\<^sub>r candidates" + by (metis (no_types, lifting) assms bind_is_OK_I2 bind_pure_I filter_M_is_OK_I finite_fset + is_OK_returns_result_E local.get_disconnected_nodes_ok local.get_disconnected_nodes_pure + notin_fset return_ok return_pure sorted_list_of_set(1)) + then have "some_owner_document \ set candidates" + apply(rule filter_M_in_result_if_ok) + using \some_owner_document |\| document_ptr_kinds h\ + \root \ cast ` set |h \ get_disconnected_nodes some_owner_document|\<^sub>r\ + apply(auto intro!: bind_pure_I bind_pure_returns_result_I)[1] + using \some_owner_document |\| document_ptr_kinds h\ + \root \ cast ` set |h \ get_disconnected_nodes some_owner_document|\<^sub>r\ + apply(auto intro!: bind_pure_I bind_pure_returns_result_I)[1] + using \some_owner_document |\| document_ptr_kinds h\ + \root \ cast ` set |h \ get_disconnected_nodes some_owner_document|\<^sub>r\ + apply(auto simp add: assms local.get_disconnected_nodes_ok + intro!: bind_pure_I bind_pure_returns_result_I)[1] + done + then have "candidates \ []" + by auto + then have "owner_document \ set candidates" + using assms(4) root + apply(auto simp add: CD.a_get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def elim!: bind_returns_result_E2 + intro!: filter_M_pure_I bind_pure_I split: option.splits)[1] + apply (metis candidates list.set_sel(1) returns_result_eq) + by (metis \is_node_ptr_kind root\ node_ptr_no_document_ptr_cast returns_result_eq) + + then show ?thesis + using candidates + by (meson bind_pure_I bind_returns_result_E2 filter_M_holds_for_result is_OK_returns_result_I + local.get_disconnected_nodes_ptr_in_heap local.get_disconnected_nodes_pure return_pure) + qed +qed + +lemma get_owner_document_owner_document_in_heap: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_owner_document ptr \\<^sub>r owner_document" + shows "owner_document |\| document_ptr_kinds h" + using assms + apply(auto simp add: get_owner_document_def a_get_owner_document_tups_def + CD.a_get_owner_document_tups_def)[1] + apply(split invoke_split_asm)+ +proof - + assume "h \ invoke [] ptr () \\<^sub>r owner_document" + then show "owner_document |\| document_ptr_kinds h" + by (meson invoke_empty is_OK_returns_result_I) +next + assume "h \ Heap_Error_Monad.bind (check_in_heap ptr) + (\_. (CD.a_get_owner_document\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r \ the \ cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r) ptr ()) + \\<^sub>r owner_document" + then show "owner_document |\| document_ptr_kinds h" + by(auto simp add: CD.a_get_owner_document\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def + elim!: bind_returns_result_E2 + split: if_splits) +next + assume 0: "heap_is_wellformed h" + and 1: "type_wf h" + and 2: "known_ptrs h" + and 3: "\ is_element_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr" + and 4: "is_character_data_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr" + and 5: "h \ Heap_Error_Monad.bind (check_in_heap ptr) + (\_. (CD.a_get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r \ the \ cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r) ptr ()) \\<^sub>r owner_document" + then show ?thesis + by (metis bind_returns_result_E2 check_in_heap_pure comp_apply + get_owner_document_owner_document_in_heap_node) +next + assume 0: "heap_is_wellformed h" + and 1: "type_wf h" + and 2: "known_ptrs h" + and 3: "is_element_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr" + and 4: "h \ Heap_Error_Monad.bind (check_in_heap ptr) + (\_. (CD.a_get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r \ the \ cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r) ptr ()) \\<^sub>r owner_document" + then show ?thesis + by (metis bind_returns_result_E2 check_in_heap_pure comp_apply + get_owner_document_owner_document_in_heap_node) +next + assume 0: "heap_is_wellformed h" + and 1: "type_wf h" + and 2: "known_ptrs h" + and 3: "\ is_element_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr" + and 4: "\ is_character_data_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr" + and 5: "\ is_document_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr" + and 6: "is_shadow_root_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr" + and 7: "h \ Heap_Error_Monad.bind (check_in_heap ptr) + (\_. (local.a_get_owner_document\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r \ the \ cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r) ptr ()) + \\<^sub>r owner_document" + then show "owner_document |\| document_ptr_kinds h" + apply(auto simp add: CD.a_get_owner_document\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def a_get_owner_document\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def + intro!: filter_M_pure_I bind_pure_I + elim!: bind_returns_result_E2 + split: if_splits option.splits)[1] + using get_owner_document_owner_document_in_heap_node by blast +qed + +lemma get_owner_document_ok: + assumes "heap_is_wellformed h" "known_ptrs h" "type_wf h" + assumes "ptr |\| object_ptr_kinds h" + shows "h \ ok (get_owner_document ptr)" +proof - + have "known_ptr ptr" + using assms(2) assms(4) local.known_ptrs_known_ptr + by blast + then show ?thesis + apply(simp add: get_owner_document_def a_get_owner_document_tups_def CD.a_get_owner_document_tups_def) + apply(split invoke_splits, (rule conjI | rule impI)+)+ + proof - + assume 0: "known_ptr ptr" + and 1: "\ is_element_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr" + and 2: "\ is_character_data_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr" + and 3: "\ is_document_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr" + and 4: "\ is_shadow_root_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr" + then show "h \ ok invoke [] ptr ()" + using NodeClass.a_known_ptr_def known_ptr_not_character_data_ptr known_ptr_not_document_ptr + known_ptr_not_shadow_root_ptr known_ptr_not_element_ptr known_ptr_impl + by blast + next + assume 0: "known_ptr ptr" + and 1: "\ is_element_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr" + and 2: "\ is_character_data_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr" + and 3: "\ is_document_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr" + then show "is_shadow_root_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr \ h \ ok Heap_Error_Monad.bind (check_in_heap ptr) + (\_. (local.a_get_owner_document\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r \ the \ cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r) ptr ())" + using assms(1) assms(2) assms(3) assms(4) + by(auto simp add: local.get_host_ok get_root_node_def + CD.a_get_owner_document\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def CD.a_get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def + a_get_owner_document\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def + intro!: bind_is_OK_pure_I filter_M_pure_I bind_pure_I filter_M_is_OK_I get_root_node_si_ok + get_disconnected_nodes_ok + intro!: local.get_shadow_root_ptr_in_heap local.shadow_root_host_dual + split: option.splits) + next + show "is_document_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr \ h \ ok Heap_Error_Monad.bind (check_in_heap ptr) + (\_. (local.CD.a_get_owner_document\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r \ the \ cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r) ptr ())" + using assms(4) + by(auto simp add: CD.a_get_owner_document\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def split: option.splits) + next + show "is_character_data_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr \ h \ ok Heap_Error_Monad.bind (check_in_heap ptr) + (\_. (local.CD.a_get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r \ the \ cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r) ptr ())" + using assms(1) assms(2) assms(3) assms(4) + by(auto simp add: local.get_host_ok get_root_node_def + CD.a_get_owner_document\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def CD.a_get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def + a_get_owner_document\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def + intro!: bind_is_OK_pure_I filter_M_pure_I bind_pure_I filter_M_is_OK_I get_root_node_si_ok + get_disconnected_nodes_ok + intro!: local.get_shadow_root_ptr_in_heap local.shadow_root_host_dual split: option.splits) + next + show "is_element_ptr\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr \ h \ ok Heap_Error_Monad.bind (check_in_heap ptr) + (\_. (local.CD.a_get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r \ the \ cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r) ptr ())" + using assms(1) assms(2) assms(3) assms(4) + by(auto simp add: local.get_host_ok get_root_node_def + CD.a_get_owner_document\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def CD.a_get_owner_document\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def + a_get_owner_document\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_def + intro!: bind_is_OK_pure_I filter_M_pure_I bind_pure_I filter_M_is_OK_I get_root_node_si_ok + get_disconnected_nodes_ok + intro!: local.get_shadow_root_ptr_in_heap local.shadow_root_host_dual + split: option.splits) + qed +qed +end +interpretation i_get_owner_document_wf?: l_get_owner_document_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + type_wf get_disconnected_nodes get_disconnected_nodes_locs known_ptr + get_child_nodes get_child_nodes_locs DocumentClass.known_ptr get_parent get_parent_locs + get_root_node_si get_root_node_si_locs CD.a_get_owner_document get_host get_host_locs + get_owner_document get_shadow_root get_shadow_root_locs get_tag_name get_tag_name_locs + heap_is_wellformed parent_child_rel heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_document + get_disconnected_document_locs known_ptrs get_ancestors_si get_ancestors_si_locs + by(auto simp add: l_get_owner_document_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_get_owner_document_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def + instances) +declare l_get_owner_document_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +lemma get_owner_document_wf_is_l_get_owner_document_wf [instances]: "l_get_owner_document_wf + heap_is_wellformed type_wf known_ptr known_ptrs get_disconnected_nodes get_owner_document + get_parent" + apply(auto simp add: l_get_owner_document_wf_def l_get_owner_document_wf_axioms_def instances)[1] + using get_owner_document_disconnected_nodes apply fast + using in_disconnected_nodes_no_parent apply fast + using get_owner_document_owner_document_in_heap apply fast + using get_owner_document_ok apply fast + done + + +subsubsection \remove\_child\ + +locale l_remove_child_wf2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_set_disconnected_nodes_get_disconnected_nodes + + l_get_child_nodes + + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_owner_document_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_remove_child\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_set_child_nodes_get_shadow_root + + l_set_disconnected_nodes_get_shadow_root + + l_set_child_nodes_get_tag_name + + l_set_disconnected_nodes_get_tag_name + + CD: l_remove_child_wf2\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma remove_child_preserves_type_wf: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ remove_child ptr child \\<^sub>h h'" + shows "type_wf h'" + using CD.remove_child_heap_is_wellformed_preserved(1) assms + unfolding heap_is_wellformed_def + by auto + +lemma remove_child_preserves_known_ptrs: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ remove_child ptr child \\<^sub>h h'" + shows "known_ptrs h'" + using CD.remove_child_heap_is_wellformed_preserved(2) assms + unfolding heap_is_wellformed_def + by auto + + +lemma remove_child_heap_is_wellformed_preserved: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ remove_child ptr child \\<^sub>h h'" + shows "heap_is_wellformed h'" +proof - + have "heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M h'" + using CD.remove_child_heap_is_wellformed_preserved(3) assms + unfolding heap_is_wellformed_def + by auto + + have shadow_root_eq: "\ptr' shadow_root_ptr_opt. h \ get_shadow_root ptr' \\<^sub>r shadow_root_ptr_opt = + h' \ get_shadow_root ptr' \\<^sub>r shadow_root_ptr_opt" + using get_shadow_root_reads remove_child_writes assms(4) + apply(rule reads_writes_preserved) + by(auto simp add: remove_child_locs_def set_child_nodes_get_shadow_root + set_disconnected_nodes_get_shadow_root) + then + have shadow_root_eq2: "\ptr'. |h \ get_shadow_root ptr'|\<^sub>r = |h' \ get_shadow_root ptr'|\<^sub>r" + by (meson select_result_eq) + + have tag_name_eq: "\ptr' tag. h \ get_tag_name ptr' \\<^sub>r tag = h' \ get_tag_name ptr' \\<^sub>r tag" + using get_tag_name_reads remove_child_writes assms(4) + apply(rule reads_writes_preserved) + by(auto simp add: remove_child_locs_def set_child_nodes_get_tag_name + set_disconnected_nodes_get_tag_name) + then + have tag_name_eq2: "\ptr'. |h \ get_tag_name ptr'|\<^sub>r = |h' \ get_tag_name ptr'|\<^sub>r" + by (meson select_result_eq) + + have object_ptr_kinds_eq: "object_ptr_kinds h = object_ptr_kinds h'" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h = object_ptr_kinds h'", + OF remove_child_writes assms(4)]) + unfolding remove_child_locs_def + using set_disconnected_nodes_pointers_preserved set_child_nodes_pointers_preserved + by (auto simp add: reflp_def transp_def) + + have shadow_root_ptr_kinds_eq: "shadow_root_ptr_kinds h = shadow_root_ptr_kinds h'" + using object_ptr_kinds_eq + by(auto simp add: shadow_root_ptr_kinds_def) + have element_ptr_kinds_eq: "element_ptr_kinds h = element_ptr_kinds h'" + using object_ptr_kinds_eq + by(auto simp add: element_ptr_kinds_def node_ptr_kinds_def) + + have "parent_child_rel h' \ parent_child_rel h" + using \heap_is_wellformed h\ heap_is_wellformed_def + using CD.remove_child_parent_child_rel_subset + using \known_ptrs h\ \type_wf h\ assms(4) + by simp + + show ?thesis + using \heap_is_wellformed h\ + using \heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M h'\ \parent_child_rel h' \ parent_child_rel h\ + apply(auto simp add: heap_is_wellformed_def CD.heap_is_wellformed_def CD.acyclic_heap_def + a_host_shadow_root_rel_def a_all_ptrs_in_heap_def a_distinct_lists_def a_shadow_root_valid_def + object_ptr_kinds_eq element_ptr_kinds_eq shadow_root_ptr_kinds_eq shadow_root_eq shadow_root_eq2 + tag_name_eq tag_name_eq2)[1] + by (meson acyclic_subset order_refl sup_mono) +qed + +lemma remove_preserves_type_wf: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ remove child \\<^sub>h h'" + shows "type_wf h'" + using CD.remove_heap_is_wellformed_preserved(1) assms + unfolding heap_is_wellformed_def + by auto + +lemma remove_preserves_known_ptrs: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ remove child \\<^sub>h h'" + shows "known_ptrs h'" + using CD.remove_heap_is_wellformed_preserved(2) assms + unfolding heap_is_wellformed_def + by auto + + +lemma remove_heap_is_wellformed_preserved: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ remove child \\<^sub>h h'" + shows "heap_is_wellformed h'" + using assms + by(auto simp add: remove_def elim!: bind_returns_heap_E2 + intro: remove_child_heap_is_wellformed_preserved + split: option.splits) + +lemma remove_child_removes_child: + "heap_is_wellformed h \ h \ remove_child ptr' child \\<^sub>h h' + \ h' \ get_child_nodes ptr \\<^sub>r children + \ known_ptrs h \ type_wf h + \ child \ set children" + using CD.remove_child_removes_child local.heap_is_wellformed_def by blast +lemma remove_child_removes_first_child: "heap_is_wellformed h \ type_wf h \ known_ptrs h \ + h \ get_child_nodes ptr \\<^sub>r node_ptr # children \ h \ remove_child ptr node_ptr \\<^sub>h h' \ + h' \ get_child_nodes ptr \\<^sub>r children" + using CD.remove_child_removes_first_child local.heap_is_wellformed_def by blast +lemma remove_removes_child: "heap_is_wellformed h \ type_wf h \ known_ptrs h \ + h \ get_child_nodes ptr \\<^sub>r node_ptr # children \ h \ remove node_ptr \\<^sub>h h' \ + h' \ get_child_nodes ptr \\<^sub>r children" + using CD.remove_removes_child local.heap_is_wellformed_def by blast +lemma remove_for_all_empty_children: "heap_is_wellformed h \ type_wf h \ known_ptrs h \ + h \ get_child_nodes ptr \\<^sub>r children \ h \ forall_M remove children \\<^sub>h h' \ + h' \ get_child_nodes ptr \\<^sub>r []" + using CD.remove_for_all_empty_children local.heap_is_wellformed_def by blast +end + +interpretation i_remove_child_wf2?: l_remove_child_wf2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + type_wf get_disconnected_nodes get_disconnected_nodes_locs set_disconnected_nodes + set_disconnected_nodes_locs known_ptr get_child_nodes get_child_nodes_locs get_shadow_root + get_shadow_root_locs get_tag_name get_tag_name_locs heap_is_wellformed parent_child_rel + heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host get_host_locs get_disconnected_document + get_disconnected_document_locs DocumentClass.known_ptr get_parent get_parent_locs get_root_node_si + get_root_node_si_locs CD.a_get_owner_document get_owner_document known_ptrs get_ancestors_si + get_ancestors_si_locs set_child_nodes set_child_nodes_locs remove_child remove_child_locs remove + by(auto simp add: l_remove_child_wf2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_remove_child_wf2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma remove_child_wf2_is_l_remove_child_wf2 [instances]: + "l_remove_child_wf2 type_wf known_ptr known_ptrs remove_child heap_is_wellformed get_child_nodes remove" + apply(auto simp add: l_remove_child_wf2_def l_remove_child_wf2_axioms_def instances)[1] + using remove_child_preserves_type_wf apply fast + using remove_child_preserves_known_ptrs apply fast + using remove_child_heap_is_wellformed_preserved apply (fast) + using remove_preserves_type_wf apply fast + using remove_preserves_known_ptrs apply fast + using remove_heap_is_wellformed_preserved apply (fast) + using remove_child_removes_child apply fast + using remove_child_removes_first_child apply fast + using remove_removes_child apply fast + using remove_for_all_empty_children apply fast + done + + + +subsubsection \adopt\_node\ + +locale l_adopt_node_wf2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_child_nodes + + l_get_disconnected_nodes + + l_set_child_nodes_get_shadow_root + + l_set_disconnected_nodes_get_shadow_root + + l_set_child_nodes_get_tag_name + + l_set_disconnected_nodes_get_tag_name + + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_root_node + + l_set_disconnected_nodes_get_child_nodes + + l_get_owner_document_wf + + l_remove_child_wf2 + + l_adopt_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_adopt_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_parent_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin + +lemma adopt_node_removes_child: + assumes wellformed: "heap_is_wellformed h" + and adopt_node: "h \ adopt_node owner_document node_ptr \\<^sub>h h2" + and children: "h2 \ get_child_nodes ptr \\<^sub>r children" + and known_ptrs: "known_ptrs h" + and type_wf: "type_wf h" + shows "node_ptr \ set children" +proof - + obtain old_document parent_opt h' where + old_document: "h \ get_owner_document (cast node_ptr) \\<^sub>r old_document" and + parent_opt: "h \ get_parent node_ptr \\<^sub>r parent_opt" and + h': "h \ (case parent_opt of Some parent \ remove_child parent node_ptr | None \ return () ) \\<^sub>h h'" + using adopt_node + by(auto simp add: adopt_node_def elim!: bind_returns_heap_E bind_returns_heap_E2[rotated, + OF get_owner_document_pure, rotated] bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] + bind_returns_heap_E2[rotated, OF get_disconnected_nodes_pure, rotated] split: if_splits) + + then have "h' \ get_child_nodes ptr \\<^sub>r children" + using adopt_node + apply(auto simp add: adopt_node_def dest!: bind_returns_heap_E3[rotated, OF old_document, rotated] + bind_returns_heap_E3[rotated, OF parent_opt, rotated] elim!: bind_returns_heap_E4[rotated, OF h', rotated])[1] + apply(auto split: if_splits elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_disconnected_nodes_pure, rotated])[1] + apply (simp add: set_disconnected_nodes_get_child_nodes children + reads_writes_preserved[OF get_child_nodes_reads set_disconnected_nodes_writes]) + using children by blast + show ?thesis + proof(insert parent_opt h', induct parent_opt) + case None + then show ?case + using child_parent_dual wellformed known_ptrs type_wf + \h' \ get_child_nodes ptr \\<^sub>r children\ returns_result_eq by fastforce + next + case (Some option) + then show ?case + using remove_child_removes_child \h' \ get_child_nodes ptr \\<^sub>r children\ known_ptrs type_wf + wellformed + by auto + qed +qed + +lemma adopt_node_preserves_wellformedness: + assumes "heap_is_wellformed h" + and "h \ adopt_node document_ptr child \\<^sub>h h'" + and known_ptrs: "known_ptrs h" + and type_wf: "type_wf h" + shows "heap_is_wellformed h'" and "known_ptrs h'" and "type_wf h'" +proof - + obtain old_document parent_opt h2 where + old_document: "h \ get_owner_document (cast child) \\<^sub>r old_document" and + parent_opt: "h \ get_parent child \\<^sub>r parent_opt" and + h2: "h \ (case parent_opt of Some parent \ remove_child parent child | None \ return ()) \\<^sub>h h2" and + h': "h2 \ (if document_ptr \ old_document then do { + old_disc_nodes \ get_disconnected_nodes old_document; + set_disconnected_nodes old_document (remove1 child old_disc_nodes); + disc_nodes \ get_disconnected_nodes document_ptr; + set_disconnected_nodes document_ptr (child # disc_nodes) + } else do { + return () + }) \\<^sub>h h'" + using assms(2) + by(auto simp add: adopt_node_def elim!: bind_returns_heap_E + dest!: pure_returns_heap_eq[rotated, OF get_owner_document_pure] + pure_returns_heap_eq[rotated, OF get_parent_pure]) + + have object_ptr_kinds_h_eq3: "object_ptr_kinds h = object_ptr_kinds h2" + using h2 apply(simp split: option.splits) + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h = object_ptr_kinds h'", + OF remove_child_writes]) + using remove_child_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have object_ptr_kinds_M_eq_h: + "\ptrs. h \ object_ptr_kinds_M \\<^sub>r ptrs = h2 \ object_ptr_kinds_M \\<^sub>r ptrs" + unfolding object_ptr_kinds_M_defs by simp + then have object_ptr_kinds_eq_h: "|h \ object_ptr_kinds_M|\<^sub>r = |h2 \ object_ptr_kinds_M|\<^sub>r" + by simp + then have node_ptr_kinds_eq_h: "|h \ node_ptr_kinds_M|\<^sub>r = |h2 \ node_ptr_kinds_M|\<^sub>r" + using node_ptr_kinds_M_eq by blast + + have wellformed_h2: "heap_is_wellformed h2" + using h2 remove_child_heap_is_wellformed_preserved known_ptrs type_wf + by (metis (no_types, lifting) assms(1) option.case_eq_if pure_returns_heap_eq return_pure) + have "type_wf h2" + using h2 remove_child_preserves_type_wf assms + by(auto split: option.splits) + have "known_ptrs h2" + using h2 remove_child_preserves_known_ptrs assms + by(auto split: option.splits) + + then have "heap_is_wellformed h' \ known_ptrs h' \ type_wf h'" + proof(cases "document_ptr = old_document") + case True + then show "heap_is_wellformed h' \ known_ptrs h' \ type_wf h'" + using h' wellformed_h2 \known_ptrs h2\ \type_wf h2\ by auto + next + case False + then obtain h3 old_disc_nodes disc_nodes_document_ptr_h3 where + docs_neq: "document_ptr \ old_document" and + old_disc_nodes: "h2 \ get_disconnected_nodes old_document \\<^sub>r old_disc_nodes" and + h3: "h2 \ set_disconnected_nodes old_document (remove1 child old_disc_nodes) \\<^sub>h h3" and + disc_nodes_document_ptr_h3: "h3 \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes_document_ptr_h3" and + h': "h3 \ set_disconnected_nodes document_ptr (child # disc_nodes_document_ptr_h3) \\<^sub>h h'" + using h' + by(auto elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_disconnected_nodes_pure, rotated] ) + + have object_ptr_kinds_h2_eq3: "object_ptr_kinds h2 = object_ptr_kinds h3" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h = object_ptr_kinds h'", + OF set_disconnected_nodes_writes h3]) + using set_disconnected_nodes_pointers_preserved set_child_nodes_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have object_ptr_kinds_M_eq_h2: + "\ptrs. h2 \ object_ptr_kinds_M \\<^sub>r ptrs = h3 \ object_ptr_kinds_M \\<^sub>r ptrs" + by(simp add: object_ptr_kinds_M_defs) + then have object_ptr_kinds_eq_h2: "|h2 \ object_ptr_kinds_M|\<^sub>r = |h3 \ object_ptr_kinds_M|\<^sub>r" + by(simp) + then have node_ptr_kinds_eq_h2: "|h2 \ node_ptr_kinds_M|\<^sub>r = |h3 \ node_ptr_kinds_M|\<^sub>r" + using node_ptr_kinds_M_eq by blast + then have node_ptr_kinds_eq3_h2: "node_ptr_kinds h2 = node_ptr_kinds h3" + by auto + have document_ptr_kinds_eq2_h2: "|h2 \ document_ptr_kinds_M|\<^sub>r = |h3 \ document_ptr_kinds_M|\<^sub>r" + using object_ptr_kinds_eq_h2 document_ptr_kinds_M_eq by auto + then have document_ptr_kinds_eq3_h2: "document_ptr_kinds h2 = document_ptr_kinds h3" + using object_ptr_kinds_eq_h2 document_ptr_kinds_M_eq by auto + have children_eq_h2: + "\ptr children. h2 \ get_child_nodes ptr \\<^sub>r children = h3 \ get_child_nodes ptr \\<^sub>r children" + using get_child_nodes_reads set_disconnected_nodes_writes h3 + apply(rule reads_writes_preserved) + by (simp add: set_disconnected_nodes_get_child_nodes) + then have children_eq2_h2: "\ptr. |h2 \ get_child_nodes ptr|\<^sub>r = |h3 \ get_child_nodes ptr|\<^sub>r" + using select_result_eq by force + + have object_ptr_kinds_h3_eq3: "object_ptr_kinds h3 = object_ptr_kinds h'" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h = object_ptr_kinds h'", + OF set_disconnected_nodes_writes h']) + using set_disconnected_nodes_pointers_preserved set_child_nodes_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have object_ptr_kinds_M_eq_h3: + "\ptrs. h3 \ object_ptr_kinds_M \\<^sub>r ptrs = h' \ object_ptr_kinds_M \\<^sub>r ptrs" + by(simp add: object_ptr_kinds_M_defs) + then have object_ptr_kinds_eq_h3: "|h3 \ object_ptr_kinds_M|\<^sub>r = |h' \ object_ptr_kinds_M|\<^sub>r" + by(simp) + then have node_ptr_kinds_eq_h3: "|h3 \ node_ptr_kinds_M|\<^sub>r = |h' \ node_ptr_kinds_M|\<^sub>r" + using node_ptr_kinds_M_eq by blast + then have node_ptr_kinds_eq3_h3: "node_ptr_kinds h3 = node_ptr_kinds h'" + by auto + have document_ptr_kinds_eq2_h3: "|h3 \ document_ptr_kinds_M|\<^sub>r = |h' \ document_ptr_kinds_M|\<^sub>r" + using object_ptr_kinds_eq_h3 document_ptr_kinds_M_eq by auto + then have document_ptr_kinds_eq3_h3: "document_ptr_kinds h3 = document_ptr_kinds h'" + using object_ptr_kinds_eq_h3 document_ptr_kinds_M_eq by auto + have children_eq_h3: + "\ptr children. h3 \ get_child_nodes ptr \\<^sub>r children = h' \ get_child_nodes ptr \\<^sub>r children" + using get_child_nodes_reads set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved) + by (simp add: set_disconnected_nodes_get_child_nodes) + then have children_eq2_h3: "\ptr. |h3 \ get_child_nodes ptr|\<^sub>r = |h' \ get_child_nodes ptr|\<^sub>r" + using select_result_eq by force + + have disconnected_nodes_eq_h2: "\doc_ptr disc_nodes. old_document \ doc_ptr \ + h2 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes = + h3 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using get_disconnected_nodes_reads set_disconnected_nodes_writes h3 + apply(rule reads_writes_preserved) + by (simp add: set_disconnected_nodes_get_disconnected_nodes_different_pointers) + then have disconnected_nodes_eq2_h2: "\doc_ptr. old_document \ doc_ptr \ + |h2 \ get_disconnected_nodes doc_ptr|\<^sub>r = |h3 \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + obtain disc_nodes_old_document_h2 where disc_nodes_old_document_h2: + "h2 \ get_disconnected_nodes old_document \\<^sub>r disc_nodes_old_document_h2" + using old_disc_nodes by blast + then have disc_nodes_old_document_h3: + "h3 \ get_disconnected_nodes old_document \\<^sub>r remove1 child disc_nodes_old_document_h2" + using h3 old_disc_nodes returns_result_eq set_disconnected_nodes_get_disconnected_nodes + by fastforce + have "distinct disc_nodes_old_document_h2" + using disc_nodes_old_document_h2 local.heap_is_wellformed_disconnected_nodes_distinct + wellformed_h2 by blast + + + have "type_wf h2" + proof (insert h2, induct parent_opt) + case None + then show ?case + using type_wf by simp + next + case (Some option) + then show ?case + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", OF remove_child_writes] + type_wf remove_child_types_preserved + by (simp add: reflp_def transp_def) + qed + then have "type_wf h3" + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", + OF set_disconnected_nodes_writes h3] + using set_disconnected_nodes_types_preserved + by(auto simp add: reflp_def transp_def) + then have "type_wf h'" + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", + OF set_disconnected_nodes_writes h'] + using set_disconnected_nodes_types_preserved + by(auto simp add: reflp_def transp_def) + + have disconnected_nodes_eq_h3: "\doc_ptr disc_nodes. document_ptr \ doc_ptr \ + h3 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes = + h' \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using get_disconnected_nodes_reads set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved) + by (simp add: set_disconnected_nodes_get_disconnected_nodes_different_pointers) + then have disconnected_nodes_eq2_h3: "\doc_ptr. document_ptr \ doc_ptr \ + |h3 \ get_disconnected_nodes doc_ptr|\<^sub>r = |h' \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + have disc_nodes_document_ptr_h2: + "h2 \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes_document_ptr_h3" + using disconnected_nodes_eq_h2 docs_neq disc_nodes_document_ptr_h3 by auto + have disc_nodes_document_ptr_h': + "h' \ get_disconnected_nodes document_ptr \\<^sub>r child # disc_nodes_document_ptr_h3" + using h' disc_nodes_document_ptr_h3 + using set_disconnected_nodes_get_disconnected_nodes by blast + + have document_ptr_in_heap: "document_ptr |\| document_ptr_kinds h2" + using disc_nodes_document_ptr_h3 document_ptr_kinds_eq2_h2 get_disconnected_nodes_ok assms(1) + unfolding heap_is_wellformed_def + using disc_nodes_document_ptr_h2 get_disconnected_nodes_ptr_in_heap by blast + have old_document_in_heap: "old_document |\| document_ptr_kinds h2" + using disc_nodes_old_document_h3 document_ptr_kinds_eq2_h2 get_disconnected_nodes_ok assms(1) + unfolding heap_is_wellformed_def + using get_disconnected_nodes_ptr_in_heap old_disc_nodes by blast + + have "child \ set disc_nodes_old_document_h2" + proof (insert parent_opt h2, induct parent_opt) + case None + then have "h = h2" + by(auto) + moreover have "CD.a_owner_document_valid h" + using assms(1) by(simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + ultimately show ?case + using old_document disc_nodes_old_document_h2 None(1) child_parent_dual[OF assms(1)] + in_disconnected_nodes_no_parent assms(1) known_ptrs type_wf by blast + next + case (Some option) + then show ?case + apply(simp split: option.splits) + using assms(1) disc_nodes_old_document_h2 old_document remove_child_in_disconnected_nodes + known_ptrs by blast + qed + have "child \ set (remove1 child disc_nodes_old_document_h2)" + using disc_nodes_old_document_h3 h3 known_ptrs wellformed_h2 + \distinct disc_nodes_old_document_h2\ by auto + have "child \ set disc_nodes_document_ptr_h3" + proof - + have "CD.a_distinct_lists h2" + using heap_is_wellformed_def CD.heap_is_wellformed_def wellformed_h2 by blast + then have 0: "distinct (concat (map (\document_ptr. + |h2 \ get_disconnected_nodes document_ptr|\<^sub>r) |h2 \ document_ptr_kinds_M|\<^sub>r))" + by(simp add: CD.a_distinct_lists_def) + show ?thesis + using distinct_concat_map_E(1)[OF 0] \child \ set disc_nodes_old_document_h2\ + disc_nodes_old_document_h2 disc_nodes_document_ptr_h2 + by (meson \type_wf h2\ docs_neq known_ptrs local.get_owner_document_disconnected_nodes + local.known_ptrs_preserved object_ptr_kinds_h_eq3 returns_result_eq wellformed_h2) + qed + + have child_in_heap: "child |\| node_ptr_kinds h" + using get_owner_document_ptr_in_heap[OF is_OK_returns_result_I[OF old_document]] + node_ptr_kinds_commutes by blast + have "CD.a_acyclic_heap h2" + using wellformed_h2 by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + have "parent_child_rel h' \ parent_child_rel h2" + proof + fix x + assume "x \ parent_child_rel h'" + then show "x \ parent_child_rel h2" + using object_ptr_kinds_h2_eq3 object_ptr_kinds_h3_eq3 children_eq2_h2 children_eq2_h3 + mem_Collect_eq object_ptr_kinds_M_eq_h3 select_result_eq split_cong + unfolding CD.parent_child_rel_def + by(simp) + qed + then have " CD.a_acyclic_heap h'" + using \ CD.a_acyclic_heap h2\ CD.acyclic_heap_def acyclic_subset by blast + + moreover have " CD.a_all_ptrs_in_heap h2" + using wellformed_h2 by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_all_ptrs_in_heap h3" + apply(auto simp add: CD.a_all_ptrs_in_heap_def node_ptr_kinds_eq3_h2 children_eq_h2)[1] + apply (metis \type_wf h'\ children_eq2_h3 children_eq_h2 children_eq_h3 known_ptrs + l_heap_is_wellformed.heap_is_wellformed_children_in_heap local.get_child_nodes_ok + local.known_ptrs_known_ptr local.l_heap_is_wellformed_axioms node_ptr_kinds_eq3_h2 + object_ptr_kinds_h2_eq3 object_ptr_kinds_h3_eq3 object_ptr_kinds_h_eq3 + returns_result_select_result wellformed_h2) + by (metis (no_types, hide_lams) disc_nodes_old_document_h2 disc_nodes_old_document_h3 + disconnected_nodes_eq2_h2 document_ptr_kinds_eq3_h2 finite_set_in select_result_I2 + set_remove1_subset subsetD) + then have "CD.a_all_ptrs_in_heap h'" + apply(auto simp add: CD.a_all_ptrs_in_heap_def node_ptr_kinds_eq3_h3 children_eq_h3)[1] + apply (metis (no_types, hide_lams) children_eq2_h3 finite_set_in object_ptr_kinds_h3_eq3 + subsetD) + by (metis (no_types, hide_lams) \child \ set disc_nodes_old_document_h2\ disc_nodes_document_ptr_h' + disc_nodes_document_ptr_h2 disc_nodes_old_document_h2 disconnected_nodes_eq2_h3 + document_ptr_kinds_eq3_h3 finite_set_in local.heap_is_wellformed_disc_nodes_in_heap + node_ptr_kinds_eq3_h2 node_ptr_kinds_eq3_h3 select_result_I2 set_ConsD subsetD wellformed_h2) + + moreover have "CD.a_owner_document_valid h2" + using wellformed_h2 by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_owner_document_valid h'" + apply(simp add: CD.a_owner_document_valid_def node_ptr_kinds_eq_h2 node_ptr_kinds_eq3_h3 + object_ptr_kinds_eq_h2 object_ptr_kinds_eq_h3 document_ptr_kinds_eq2_h2 document_ptr_kinds_eq2_h3 + children_eq2_h2 children_eq2_h3 ) + by (metis (no_types) disc_nodes_document_ptr_h' disc_nodes_document_ptr_h2 + disc_nodes_old_document_h2 disc_nodes_old_document_h3 disconnected_nodes_eq2_h2 + disconnected_nodes_eq2_h3 document_ptr_in_heap document_ptr_kinds_eq3_h2 document_ptr_kinds_eq3_h3 + in_set_remove1 list.set_intros(1) list.set_intros(2) node_ptr_kinds_eq3_h2 node_ptr_kinds_eq3_h3 + object_ptr_kinds_h2_eq3 object_ptr_kinds_h3_eq3 select_result_I2) + + have a_distinct_lists_h2: "CD.a_distinct_lists h2" + using wellformed_h2 by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_distinct_lists h'" + apply(auto simp add: CD.a_distinct_lists_def object_ptr_kinds_eq_h3 object_ptr_kinds_eq_h2 + children_eq2_h2 children_eq2_h3)[1] + proof - + assume 1: "distinct (concat (map (\ptr. |h' \ get_child_nodes ptr|\<^sub>r) + (sorted_list_of_set (fset (object_ptr_kinds h')))))" + and 2: "distinct (concat (map (\document_ptr. |h2 \ get_disconnected_nodes document_ptr|\<^sub>r) + (sorted_list_of_set (fset (document_ptr_kinds h2)))))" + and 3: "(\x\fset (object_ptr_kinds h'). set |h' \ get_child_nodes x|\<^sub>r) \ + (\x\fset (document_ptr_kinds h2). set |h2 \ get_disconnected_nodes x|\<^sub>r) = {}" + show "distinct (concat (map (\document_ptr. |h' \ get_disconnected_nodes document_ptr|\<^sub>r) + (sorted_list_of_set (fset (document_ptr_kinds h')))))" + proof(rule distinct_concat_map_I) + show "distinct (sorted_list_of_set (fset (document_ptr_kinds h')))" + by(auto simp add: document_ptr_kinds_M_def ) + next + fix x + assume a1: "x \ set (sorted_list_of_set (fset (document_ptr_kinds h')))" + have 4: "distinct |h2 \ get_disconnected_nodes x|\<^sub>r" + using a_distinct_lists_h2 "2" a1 concat_map_all_distinct document_ptr_kinds_eq2_h2 + document_ptr_kinds_eq2_h3 by fastforce + then show "distinct |h' \ get_disconnected_nodes x|\<^sub>r" + proof (cases "old_document \ x") + case True + then show ?thesis + proof (cases "document_ptr \ x") + case True + then show ?thesis + using disconnected_nodes_eq2_h2[OF \old_document \ x\] + disconnected_nodes_eq2_h3[OF \document_ptr \ x\] 4 + by(auto) + next + case False + then show ?thesis + using disc_nodes_document_ptr_h3 disc_nodes_document_ptr_h' 4 + \child \ set disc_nodes_document_ptr_h3\ + by(auto simp add: disconnected_nodes_eq2_h2[OF \old_document \ x\] ) + qed + next + case False + then show ?thesis + by (metis (no_types, hide_lams) \distinct disc_nodes_old_document_h2\ + disc_nodes_old_document_h3 disconnected_nodes_eq2_h3 distinct_remove1 docs_neq select_result_I2) + qed + next + fix x y + assume a0: "x \ set (sorted_list_of_set (fset (document_ptr_kinds h')))" + and a1: "y \ set (sorted_list_of_set (fset (document_ptr_kinds h')))" + and a2: "x \ y" + + moreover have 5: "set |h2 \ get_disconnected_nodes x|\<^sub>r \ + set |h2 \ get_disconnected_nodes y|\<^sub>r = {}" + using 2 calculation + by (auto simp add: document_ptr_kinds_eq3_h2 document_ptr_kinds_eq3_h3 + dest: distinct_concat_map_E(1)) + ultimately show "set |h' \ get_disconnected_nodes x|\<^sub>r \ + set |h' \ get_disconnected_nodes y|\<^sub>r = {}" + proof(cases "old_document = x") + case True + have "old_document \ y" + using \x \ y\ \old_document = x\ by simp + have "document_ptr \ x" + using docs_neq \old_document = x\ by auto + show ?thesis + proof(cases "document_ptr = y") + case True + then show ?thesis + using 5 True select_result_I2[OF disc_nodes_document_ptr_h'] + select_result_I2[OF disc_nodes_document_ptr_h2] + select_result_I2[OF disc_nodes_old_document_h2] + select_result_I2[OF disc_nodes_old_document_h3] \old_document = x\ + by (metis (no_types, lifting) \child \ set (remove1 child disc_nodes_old_document_h2)\ + \document_ptr \ x\ disconnected_nodes_eq2_h3 disjoint_iff_not_equal notin_set_remove1 set_ConsD) + next + case False + then show ?thesis + using 5 select_result_I2[OF disc_nodes_document_ptr_h'] + select_result_I2[OF disc_nodes_document_ptr_h2] + select_result_I2[OF disc_nodes_old_document_h2] + select_result_I2[OF disc_nodes_old_document_h3] + disconnected_nodes_eq2_h2 disconnected_nodes_eq2_h3 \old_document = x\ docs_neq + \old_document \ y\ + by (metis (no_types, lifting) disjoint_iff_not_equal notin_set_remove1) + qed + next + case False + then show ?thesis + proof(cases "old_document = y") + case True + then show ?thesis + proof(cases "document_ptr = x") + case True + show ?thesis + using 5 select_result_I2[OF disc_nodes_document_ptr_h'] + select_result_I2[OF disc_nodes_document_ptr_h2] + select_result_I2[OF disc_nodes_old_document_h2] + select_result_I2[OF disc_nodes_old_document_h3] + \old_document \ x\ \old_document = y\ \document_ptr = x\ + apply(simp) + by (metis (no_types, lifting) + \child \ set (remove1 child disc_nodes_old_document_h2)\ + disconnected_nodes_eq2_h3 disjoint_iff_not_equal notin_set_remove1) + next + case False + then show ?thesis + using 5 select_result_I2[OF disc_nodes_document_ptr_h'] + select_result_I2[OF disc_nodes_document_ptr_h2] + select_result_I2[OF disc_nodes_old_document_h2] + select_result_I2[OF disc_nodes_old_document_h3] \old_document \ x\ + \old_document = y\ \document_ptr \ x\ + by (metis (no_types, lifting) disconnected_nodes_eq2_h2 + disconnected_nodes_eq2_h3 disjoint_iff_not_equal docs_neq notin_set_remove1) + qed + next + case False + have "set |h2 \ get_disconnected_nodes y|\<^sub>r \ set disc_nodes_old_document_h2 = {}" + by (metis DocumentMonad.ptr_kinds_M_ok DocumentMonad.ptr_kinds_M_ptr_kinds False + \type_wf h2\ a1 disc_nodes_old_document_h2 document_ptr_kinds_M_def document_ptr_kinds_eq2_h2 + document_ptr_kinds_eq2_h3 l_ptr_kinds_M.ptr_kinds_ptr_kinds_M local.get_disconnected_nodes_ok + local.heap_is_wellformed_one_disc_parent returns_result_select_result wellformed_h2) + then show ?thesis + proof(cases "document_ptr = x") + case True + then have "document_ptr \ y" + using \x \ y\ by auto + have "set |h2 \ get_disconnected_nodes y|\<^sub>r \ set disc_nodes_old_document_h2 = {}" + using \set |h2 \ get_disconnected_nodes y|\<^sub>r \ set disc_nodes_old_document_h2 = {}\ + by blast + then show ?thesis + using 5 select_result_I2[OF disc_nodes_document_ptr_h'] + select_result_I2[OF disc_nodes_document_ptr_h2] + select_result_I2[OF disc_nodes_old_document_h2] + select_result_I2[OF disc_nodes_old_document_h3] \old_document \ x\ + \old_document \ y\ \document_ptr = x\ \document_ptr \ y\ + \child \ set disc_nodes_old_document_h2\ disconnected_nodes_eq2_h2 + disconnected_nodes_eq2_h3 \set |h2 \ get_disconnected_nodes y|\<^sub>r \ set disc_nodes_old_document_h2 = {}\ + by(auto) + next + case False + then show ?thesis + proof(cases "document_ptr = y") + case True + have f1: "set |h2 \ get_disconnected_nodes x|\<^sub>r \ set disc_nodes_document_ptr_h3 = {}" + using 2 a1 document_ptr_in_heap document_ptr_kinds_eq2_h2 + document_ptr_kinds_eq2_h3 \document_ptr \ x\ + select_result_I2[OF disc_nodes_document_ptr_h3, symmetric] + disconnected_nodes_eq2_h2[OF docs_neq[symmetric], symmetric] + by (simp add: "5" True) + moreover have f1: "set |h2 \ get_disconnected_nodes x|\<^sub>r \ +set |h2 \ get_disconnected_nodes old_document|\<^sub>r = {}" + using 2 a1 old_document_in_heap document_ptr_kinds_eq2_h2 + document_ptr_kinds_eq2_h3 \old_document \ x\ + by (metis (no_types, lifting) a0 distinct_concat_map_E(1) + document_ptr_kinds_eq3_h2 document_ptr_kinds_eq3_h3 finite_fset fmember.rep_eq + set_sorted_list_of_set) + ultimately show ?thesis + using 5 select_result_I2[OF disc_nodes_document_ptr_h'] + select_result_I2[OF disc_nodes_old_document_h2] \old_document \ x\ + \document_ptr \ x\ \document_ptr = y\ + \child \ set disc_nodes_old_document_h2\ disconnected_nodes_eq2_h2 + disconnected_nodes_eq2_h3 + by auto + next + case False + then show ?thesis + using 5 + select_result_I2[OF disc_nodes_old_document_h2] \old_document \ x\ + \document_ptr \ x\ \document_ptr \ y\ + \child \ set disc_nodes_old_document_h2\ disconnected_nodes_eq2_h2 + disconnected_nodes_eq2_h3 + by (metis \set |h2 \ get_disconnected_nodes y|\<^sub>r \ + set disc_nodes_old_document_h2 = {}\ empty_iff inf.idem) + qed + qed + qed + qed + qed + next + fix x xa xb + assume 0: "distinct (concat (map (\ptr. |h' \ get_child_nodes ptr|\<^sub>r) + (sorted_list_of_set (fset (object_ptr_kinds h')))))" + and 1: "distinct (concat (map (\document_ptr. |h2 \ get_disconnected_nodes document_ptr|\<^sub>r) + (sorted_list_of_set (fset (document_ptr_kinds h2)))))" + and 2: "(\x\fset (object_ptr_kinds h'). set |h' \ get_child_nodes x|\<^sub>r) \ + (\x\fset (document_ptr_kinds h2). set |h2 \ get_disconnected_nodes x|\<^sub>r) = {}" + and 3: "xa |\| object_ptr_kinds h'" + and 4: "x \ set |h' \ get_child_nodes xa|\<^sub>r" + and 5: "xb |\| document_ptr_kinds h'" + and 6: "x \ set |h' \ get_disconnected_nodes xb|\<^sub>r" + then show False + using \child \ set disc_nodes_old_document_h2\ disc_nodes_document_ptr_h' + disc_nodes_document_ptr_h2 disc_nodes_old_document_h2 disc_nodes_old_document_h3 + disconnected_nodes_eq2_h2 disconnected_nodes_eq2_h3 document_ptr_kinds_eq2_h2 + document_ptr_kinds_eq2_h3 old_document_in_heap + apply(auto)[1] + apply(cases "xb = old_document") + proof - + assume a1: "xb = old_document" + assume a2: "h2 \ get_disconnected_nodes old_document \\<^sub>r disc_nodes_old_document_h2" + assume a3: "h3 \ get_disconnected_nodes old_document \\<^sub>r remove1 child disc_nodes_old_document_h2" + assume a4: "x \ set |h' \ get_child_nodes xa|\<^sub>r" + assume "document_ptr_kinds h2 = document_ptr_kinds h'" + assume a5: "(\x\fset (object_ptr_kinds h'). set |h' \ get_child_nodes x|\<^sub>r) \ + (\x\fset (document_ptr_kinds h'). set |h2 \ get_disconnected_nodes x|\<^sub>r) = {}" + have f6: "old_document |\| document_ptr_kinds h'" + using a1 \xb |\| document_ptr_kinds h'\ by blast + have f7: "|h2 \ get_disconnected_nodes old_document|\<^sub>r = disc_nodes_old_document_h2" + using a2 by simp + have "x \ set disc_nodes_old_document_h2" + using f6 a3 a1 by (metis (no_types) \type_wf h'\ + \x \ set |h' \ get_disconnected_nodes xb|\<^sub>r\ disconnected_nodes_eq_h3 docs_neq + get_disconnected_nodes_ok returns_result_eq returns_result_select_result set_remove1_subset subsetCE) + then have "set |h' \ get_child_nodes xa|\<^sub>r \ set |h2 \ get_disconnected_nodes xb|\<^sub>r = {}" + using f7 f6 a5 a4 \xa |\| object_ptr_kinds h'\ + by fastforce + then show ?thesis + using \x \ set disc_nodes_old_document_h2\ a1 a4 f7 by blast + next + assume a1: "xb \ old_document" + assume a2: "h2 \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes_document_ptr_h3" + assume a3: "h2 \ get_disconnected_nodes old_document \\<^sub>r disc_nodes_old_document_h2" + assume a4: "xa |\| object_ptr_kinds h'" + assume a5: "h' \ get_disconnected_nodes document_ptr \\<^sub>r child # disc_nodes_document_ptr_h3" + assume a6: "old_document |\| document_ptr_kinds h'" + assume a7: "x \ set |h' \ get_disconnected_nodes xb|\<^sub>r" + assume a8: "x \ set |h' \ get_child_nodes xa|\<^sub>r" + assume a9: "document_ptr_kinds h2 = document_ptr_kinds h'" + assume a10: "\doc_ptr. old_document \ doc_ptr \ + |h2 \ get_disconnected_nodes doc_ptr|\<^sub>r = |h3 \ get_disconnected_nodes doc_ptr|\<^sub>r" + assume a11: "\doc_ptr. document_ptr \ doc_ptr \ |h3 \ get_disconnected_nodes doc_ptr|\<^sub>r = + |h' \ get_disconnected_nodes doc_ptr|\<^sub>r" + assume a12: "(\x\fset (object_ptr_kinds h'). set |h' \ get_child_nodes x|\<^sub>r) \ + (\x\fset (document_ptr_kinds h'). set |h2 \ get_disconnected_nodes x|\<^sub>r) = {}" + have f13: "\d. d \ set |h' \ document_ptr_kinds_M|\<^sub>r \ h2 \ ok get_disconnected_nodes d" + using a9 \type_wf h2\ get_disconnected_nodes_ok + by simp + then have f14: "|h2 \ get_disconnected_nodes old_document|\<^sub>r = disc_nodes_old_document_h2" + using a6 a3 by simp + have "x \ set |h2 \ get_disconnected_nodes xb|\<^sub>r" + using a12 a8 a4 \xb |\| document_ptr_kinds h'\ + by (meson UN_I disjoint_iff_not_equal fmember.rep_eq) + then have "x = child" + using f13 a11 a10 a7 a5 a2 a1 + by (metis (no_types, lifting) select_result_I2 set_ConsD) + then have "child \ set disc_nodes_old_document_h2" + using f14 a12 a8 a6 a4 + by (metis \type_wf h'\ adopt_node_removes_child assms(1) assms(2) type_wf + get_child_nodes_ok known_ptrs local.known_ptrs_known_ptr object_ptr_kinds_h2_eq3 + object_ptr_kinds_h3_eq3 object_ptr_kinds_h_eq3 returns_result_select_result) + then show ?thesis + using \child \ set disc_nodes_old_document_h2\ by fastforce + qed + qed + ultimately have "heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M h'" + using \CD.a_owner_document_valid h'\ CD.heap_is_wellformed_def + by simp + + + + have shadow_root_eq_h2: + "\ptr' shadow_root_ptr_opt. h2 \ get_shadow_root ptr' \\<^sub>r shadow_root_ptr_opt = + h3 \ get_shadow_root ptr' \\<^sub>r shadow_root_ptr_opt" + using get_shadow_root_reads set_disconnected_nodes_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: adopt_node_locs_def remove_child_locs_def set_child_nodes_get_shadow_root + set_disconnected_nodes_get_shadow_root) + then + have shadow_root_eq2_h2: "\ptr'. |h2 \ get_shadow_root ptr'|\<^sub>r = |h3 \ get_shadow_root ptr'|\<^sub>r" + by (meson select_result_eq) + + have shadow_root_eq_h3: + "\ptr' shadow_root_ptr_opt. h3 \ get_shadow_root ptr' \\<^sub>r shadow_root_ptr_opt = +h' \ get_shadow_root ptr' \\<^sub>r shadow_root_ptr_opt" + using get_shadow_root_reads set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: adopt_node_locs_def remove_child_locs_def set_child_nodes_get_shadow_root + set_disconnected_nodes_get_shadow_root) + then + have shadow_root_eq2_h3: "\ptr'. |h3 \ get_shadow_root ptr'|\<^sub>r = |h' \ get_shadow_root ptr'|\<^sub>r" + by (meson select_result_eq) + + have tag_name_eq_h2: "\ptr' tag. h2 \ get_tag_name ptr' \\<^sub>r tag = h3 \ get_tag_name ptr' \\<^sub>r tag" + using get_tag_name_reads set_disconnected_nodes_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: adopt_node_locs_def remove_child_locs_def set_child_nodes_get_tag_name + set_disconnected_nodes_get_tag_name) + then + have tag_name_eq2_h2: "\ptr'. |h2 \ get_tag_name ptr'|\<^sub>r = |h3 \ get_tag_name ptr'|\<^sub>r" + by (meson select_result_eq) + + have tag_name_eq_h3: "\ptr' tag. h3 \ get_tag_name ptr' \\<^sub>r tag = h' \ get_tag_name ptr' \\<^sub>r tag" + using get_tag_name_reads set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: adopt_node_locs_def remove_child_locs_def set_child_nodes_get_tag_name + set_disconnected_nodes_get_tag_name) + then + have tag_name_eq2_h3: "\ptr'. |h3 \ get_tag_name ptr'|\<^sub>r = |h' \ get_tag_name ptr'|\<^sub>r" + by (meson select_result_eq) + + have object_ptr_kinds_eq_h2: "object_ptr_kinds h2 = object_ptr_kinds h3" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h = object_ptr_kinds h'", + OF set_disconnected_nodes_writes h3]) + unfolding adopt_node_locs_def remove_child_locs_def + using set_disconnected_nodes_pointers_preserved set_child_nodes_pointers_preserved + by (auto simp add: reflp_def transp_def split: if_splits) + + have object_ptr_kinds_eq_h3: "object_ptr_kinds h3 = object_ptr_kinds h'" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h = object_ptr_kinds h'", + OF set_disconnected_nodes_writes h']) + unfolding adopt_node_locs_def remove_child_locs_def + using set_disconnected_nodes_pointers_preserved set_child_nodes_pointers_preserved + by (auto simp add: reflp_def transp_def split: if_splits) + + have shadow_root_ptr_kinds_eq_h2: "shadow_root_ptr_kinds h2 = shadow_root_ptr_kinds h3" + using object_ptr_kinds_eq_h2 + by(auto simp add: shadow_root_ptr_kinds_def) + have element_ptr_kinds_eq_h2: "element_ptr_kinds h2 = element_ptr_kinds h3" + using object_ptr_kinds_eq_h2 + by(auto simp add: element_ptr_kinds_def node_ptr_kinds_def) + + have shadow_root_ptr_kinds_eq_h3: "shadow_root_ptr_kinds h3 = shadow_root_ptr_kinds h'" + using object_ptr_kinds_eq_h3 + by(auto simp add: shadow_root_ptr_kinds_def) + have element_ptr_kinds_eq_h3: "element_ptr_kinds h3 = element_ptr_kinds h'" + using object_ptr_kinds_eq_h3 + by(auto simp add: element_ptr_kinds_def node_ptr_kinds_def) + + + have "known_ptrs h3" + using known_ptrs local.known_ptrs_preserved object_ptr_kinds_h2_eq3 object_ptr_kinds_h_eq3 + by blast + then have "known_ptrs h'" + using local.known_ptrs_preserved object_ptr_kinds_h3_eq3 by blast + + + show "heap_is_wellformed h' \ known_ptrs h' \ type_wf h'" + using \heap_is_wellformed h2\ + using \heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M h'\ \known_ptrs h'\ \type_wf h'\ + using \parent_child_rel h' \ parent_child_rel h2\ + apply(auto simp add: heap_is_wellformed_def CD.heap_is_wellformed_def CD.acyclic_heap_def + a_host_shadow_root_rel_def a_all_ptrs_in_heap_def a_distinct_lists_def a_shadow_root_valid_def + object_ptr_kinds_eq_h2 object_ptr_kinds_eq_h3 element_ptr_kinds_eq_h2 element_ptr_kinds_eq_h3 + shadow_root_ptr_kinds_eq_h2 shadow_root_ptr_kinds_eq_h3 shadow_root_eq_h2 shadow_root_eq_h3 + shadow_root_eq2_h2 shadow_root_eq2_h3 tag_name_eq_h2 tag_name_eq_h3 tag_name_eq2_h2 + tag_name_eq2_h3 CD.parent_child_rel_def children_eq2_h2 children_eq2_h3 object_ptr_kinds_h2_eq3 + object_ptr_kinds_h3_eq3)[1] + done + qed + then show "heap_is_wellformed h'" and "known_ptrs h'" and "type_wf h'" + by auto +qed + + +lemma adopt_node_node_in_disconnected_nodes: + assumes wellformed: "heap_is_wellformed h" + and adopt_node: "h \ adopt_node owner_document node_ptr \\<^sub>h h'" + and "h' \ get_disconnected_nodes owner_document \\<^sub>r disc_nodes" + and known_ptrs: "known_ptrs h" + and type_wf: "type_wf h" + shows "node_ptr \ set disc_nodes" +proof - + obtain old_document parent_opt h2 where + old_document: "h \ get_owner_document (cast node_ptr) \\<^sub>r old_document" and + parent_opt: "h \ get_parent node_ptr \\<^sub>r parent_opt" and + h2: "h \ (case parent_opt of Some parent \ remove_child parent node_ptr | None \ return ()) \\<^sub>h h2" and + h': "h2 \ (if owner_document \ old_document then do { + old_disc_nodes \ get_disconnected_nodes old_document; + set_disconnected_nodes old_document (remove1 node_ptr old_disc_nodes); + disc_nodes \ get_disconnected_nodes owner_document; + set_disconnected_nodes owner_document (node_ptr # disc_nodes) + } else do { + return () + }) \\<^sub>h h'" + using assms(2) + by(auto simp add: adopt_node_def elim!: bind_returns_heap_E + dest!: pure_returns_heap_eq[rotated, OF get_owner_document_pure] + pure_returns_heap_eq[rotated, OF get_parent_pure]) + + show ?thesis + proof (cases "owner_document = old_document") + case True + then show ?thesis + proof (insert parent_opt h2, induct parent_opt) + case None + then have "h = h'" + using h2 h' by(auto) + then show ?case + using in_disconnected_nodes_no_parent assms None old_document by blast + next + case (Some parent) + then show ?case + using remove_child_in_disconnected_nodes known_ptrs True h' assms(3) old_document + by auto + qed + next + case False + then show ?thesis + using assms(3) h' list.set_intros(1) select_result_I2 + set_disconnected_nodes_get_disconnected_nodes + apply(auto elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_disconnected_nodes_pure, rotated])[1] + proof - + fix x and h'a and xb + assume a1: "h' \ get_disconnected_nodes owner_document \\<^sub>r disc_nodes" + assume a2: "\h document_ptr disc_nodes h'. + h \ set_disconnected_nodes document_ptr disc_nodes \\<^sub>h h' \ + h' \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes" + assume "h'a \ set_disconnected_nodes owner_document (node_ptr # xb) \\<^sub>h h'" + then have "node_ptr # xb = disc_nodes" + using a2 a1 by (meson returns_result_eq) + then show ?thesis + by (meson list.set_intros(1)) + qed + qed +qed +end + +interpretation l_adopt_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M Shadow_DOM.get_owner_document Shadow_DOM.get_parent + Shadow_DOM.get_parent_locs Shadow_DOM.remove_child Shadow_DOM.remove_child_locs + get_disconnected_nodes get_disconnected_nodes_locs + set_disconnected_nodes set_disconnected_nodes_locs Shadow_DOM.adopt_node Shadow_DOM.adopt_node_locs + ShadowRootClass.known_ptr ShadowRootClass.type_wf Shadow_DOM.get_child_nodes + Shadow_DOM.get_child_nodes_locs + ShadowRootClass.known_ptrs Shadow_DOM.set_child_nodes Shadow_DOM.set_child_nodes_locs + Shadow_DOM.remove Shadow_DOM.heap_is_wellformed Shadow_DOM.parent_child_rel + by(auto simp add: l_adopt_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_adopt_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +interpretation i_adopt_node_wf2?: l_adopt_node_wf2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + type_wf known_ptr get_child_nodes get_child_nodes_locs get_disconnected_nodes + get_disconnected_nodes_locs set_child_nodes set_child_nodes_locs get_shadow_root get_shadow_root_locs + set_disconnected_nodes set_disconnected_nodes_locs get_tag_name get_tag_name_locs heap_is_wellformed + parent_child_rel heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host get_host_locs get_disconnected_document + get_disconnected_document_locs get_root_node get_root_node_locs get_parent get_parent_locs known_ptrs + get_owner_document remove_child remove_child_locs remove adopt_node adopt_node_locs + by(auto simp add: l_adopt_node_wf2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_adopt_node_wf2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +lemma adopt_node_wf_is_l_adopt_node_wf [instances]: + "l_adopt_node_wf type_wf known_ptr heap_is_wellformed parent_child_rel get_child_nodes + get_disconnected_nodes known_ptrs adopt_node" + apply(auto simp add: l_adopt_node_wf_def l_adopt_node_wf_axioms_def instances)[1] + using adopt_node_preserves_wellformedness apply blast + using adopt_node_removes_child apply blast + using adopt_node_node_in_disconnected_nodes apply blast + using adopt_node_removes_first_child apply blast + using adopt_node_document_in_heap apply blast + using adopt_node_preserves_wellformedness apply blast + using adopt_node_preserves_wellformedness apply blast + done + + +subsubsection \insert\_before\ + +locale l_insert_before_wf2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_child_nodes + + l_get_disconnected_nodes + + l_set_child_nodes_get_shadow_root + + l_set_disconnected_nodes_get_shadow_root + + l_set_child_nodes_get_tag_name + + l_set_disconnected_nodes_get_tag_name + + l_set_disconnected_nodes_get_disconnected_nodes + + l_set_child_nodes_get_disconnected_nodes + + l_set_disconnected_nodes_get_disconnected_nodes_wf + + l_set_disconnected_nodes_get_ancestors_si + + l_insert_before\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M _ _ _ _ _ _ get_ancestors_si get_ancestors_si_locs + + l_get_root_node_si_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_owner_document + + l_adopt_node + + l_adopt_node_wf + + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_adopt_node_get_shadow_root +begin +lemma insert_before_child_preserves: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ insert_before ptr node child \\<^sub>h h'" + shows "type_wf h'" and "known_ptrs h'" and "heap_is_wellformed h'" +proof - + obtain ancestors reference_child owner_document h2 h3 disconnected_nodes_h2 where + ancestors: "h \ get_ancestors_si ptr \\<^sub>r ancestors" and + node_not_in_ancestors: "cast node \ set ancestors" and + reference_child: + "h \ (if Some node = child then a_next_sibling node else return child) \\<^sub>r reference_child" and + owner_document: "h \ get_owner_document ptr \\<^sub>r owner_document" and + h2: "h \ adopt_node owner_document node \\<^sub>h h2" and + disconnected_nodes_h2: "h2 \ get_disconnected_nodes owner_document \\<^sub>r disconnected_nodes_h2" and + h3: "h2 \ set_disconnected_nodes owner_document (remove1 node disconnected_nodes_h2) \\<^sub>h h3" and + h': "h3 \ a_insert_node ptr node reference_child \\<^sub>h h'" + (* children: "h3 \ get_child_nodes ptr \\<^sub>r children" and *) + (* h': "h3 \ set_child_nodes ptr (insert_before_list node reference_child children) \\<^sub>h h'" *) + using assms(4) + by(auto simp add: insert_before_def a_ensure_pre_insertion_validity_def + elim!: bind_returns_heap_E bind_returns_result_E + bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] + bind_returns_heap_E2[rotated, OF get_child_nodes_pure, rotated] + bind_returns_heap_E2[rotated, OF get_disconnected_nodes_pure, rotated] + bind_returns_heap_E2[rotated, OF get_ancestors_pure, rotated] + bind_returns_heap_E2[rotated, OF next_sibling_pure, rotated] + bind_returns_heap_E2[rotated, OF get_owner_document_pure, rotated] + split: if_splits option.splits) + + have "type_wf h2" + using \type_wf h\ + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", OF adopt_node_writes h2] + using adopt_node_types_preserved + by(auto simp add: reflp_def transp_def) + then have "type_wf h3" + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", OF set_disconnected_nodes_writes h3] + using set_disconnected_nodes_types_preserved + by(auto simp add: reflp_def transp_def) + then show "type_wf h'" + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", OF insert_node_writes h'] + using set_child_nodes_types_preserved + by(auto simp add: reflp_def transp_def) + + have "object_ptr_kinds h = object_ptr_kinds h2" + using adopt_node_writes h2 + apply(rule writes_small_big) + using adopt_node_pointers_preserved + by(auto simp add: reflp_def transp_def) + moreover have "\ = object_ptr_kinds h3" + using set_disconnected_nodes_writes h3 + apply(rule writes_small_big) + using set_disconnected_nodes_pointers_preserved + by(auto simp add: reflp_def transp_def) + moreover have "\ = object_ptr_kinds h'" + using insert_node_writes h' + apply(rule writes_small_big) + using set_child_nodes_pointers_preserved + by(auto simp add: reflp_def transp_def) + + ultimately + show "known_ptrs h'" + using \known_ptrs h\ known_ptrs_preserved + by blast + + have "known_ptrs h2" + using \known_ptrs h\ known_ptrs_preserved \object_ptr_kinds h = object_ptr_kinds h2\ + by blast + then + have "known_ptrs h3" + using known_ptrs_preserved \object_ptr_kinds h2 = object_ptr_kinds h3\ + by blast + + have "known_ptr ptr" + by (meson get_owner_document_ptr_in_heap is_OK_returns_result_I \known_ptrs h\ + l_known_ptrs.known_ptrs_known_ptr l_known_ptrs_axioms owner_document) + + have object_ptr_kinds_M_eq3_h: "object_ptr_kinds h = object_ptr_kinds h2" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h = object_ptr_kinds h'", + OF adopt_node_writes h2]) + using adopt_node_pointers_preserved + apply blast + by (auto simp add: reflp_def transp_def) + then have object_ptr_kinds_M_eq_h: + "\ptrs. h \ object_ptr_kinds_M \\<^sub>r ptrs = h2 \ object_ptr_kinds_M \\<^sub>r ptrs" + by(simp add: object_ptr_kinds_M_defs ) + then have object_ptr_kinds_M_eq2_h: "|h \ object_ptr_kinds_M|\<^sub>r = |h2 \ object_ptr_kinds_M|\<^sub>r" + by simp + then have node_ptr_kinds_eq2_h: "|h \ node_ptr_kinds_M|\<^sub>r = |h2 \ node_ptr_kinds_M|\<^sub>r" + using node_ptr_kinds_M_eq by blast + + have wellformed_h2: "heap_is_wellformed h2" + using adopt_node_preserves_wellformedness[OF \heap_is_wellformed h\ h2] \known_ptrs h\ + \type_wf h\ + . + + have object_ptr_kinds_M_eq3_h2: "object_ptr_kinds h2 = object_ptr_kinds h3" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h = object_ptr_kinds h'", + OF set_disconnected_nodes_writes h3]) + unfolding a_remove_child_locs_def + using set_disconnected_nodes_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have object_ptr_kinds_M_eq_h2: + "\ptrs. h2 \ object_ptr_kinds_M \\<^sub>r ptrs = h3 \ object_ptr_kinds_M \\<^sub>r ptrs" + by(simp add: object_ptr_kinds_M_defs) + then have object_ptr_kinds_M_eq2_h2: "|h2 \ object_ptr_kinds_M|\<^sub>r = |h3 \ object_ptr_kinds_M|\<^sub>r" + by simp + then have node_ptr_kinds_eq2_h2: "|h2 \ node_ptr_kinds_M|\<^sub>r = |h3 \ node_ptr_kinds_M|\<^sub>r" + using node_ptr_kinds_M_eq by blast + have document_ptr_kinds_eq2_h2: "|h2 \ document_ptr_kinds_M|\<^sub>r = |h3 \ document_ptr_kinds_M|\<^sub>r" + using object_ptr_kinds_M_eq2_h2 document_ptr_kinds_M_eq by auto + + have object_ptr_kinds_M_eq3_h': "object_ptr_kinds h3 = object_ptr_kinds h'" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h = object_ptr_kinds h'", + OF insert_node_writes h']) unfolding a_remove_child_locs_def + using set_child_nodes_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have object_ptr_kinds_M_eq_h3: + "\ptrs. h3 \ object_ptr_kinds_M \\<^sub>r ptrs = h' \ object_ptr_kinds_M \\<^sub>r ptrs" + by(simp add: object_ptr_kinds_M_defs) + then have object_ptr_kinds_M_eq2_h3: "|h3 \ object_ptr_kinds_M|\<^sub>r = |h' \ object_ptr_kinds_M|\<^sub>r" + by simp + then have node_ptr_kinds_eq2_h3: "|h3 \ node_ptr_kinds_M|\<^sub>r = |h' \ node_ptr_kinds_M|\<^sub>r" + using node_ptr_kinds_M_eq by blast + have document_ptr_kinds_eq2_h3: "|h3 \ document_ptr_kinds_M|\<^sub>r = |h' \ document_ptr_kinds_M|\<^sub>r" + using object_ptr_kinds_M_eq2_h3 document_ptr_kinds_M_eq by auto + + + have shadow_root_eq_h2: + "\ptr' shadow_root. h \ get_shadow_root ptr' \\<^sub>r shadow_root = + h2 \ get_shadow_root ptr' \\<^sub>r shadow_root" + using get_shadow_root_reads adopt_node_writes h2 + apply(rule reads_writes_preserved) + using local.adopt_node_get_shadow_root by blast + + have disconnected_nodes_eq_h2: + "\doc_ptr disc_nodes. owner_document \ doc_ptr \ + h2 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes = + h3 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using get_disconnected_nodes_reads set_disconnected_nodes_writes h3 + apply(rule reads_writes_preserved) + by (auto simp add: set_disconnected_nodes_get_disconnected_nodes_different_pointers) + then have disconnected_nodes_eq2_h2: + "\doc_ptr. doc_ptr \ owner_document \ + |h2 \ get_disconnected_nodes doc_ptr|\<^sub>r = + |h3 \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + have disconnected_nodes_h3: + "h3 \ get_disconnected_nodes owner_document \\<^sub>r remove1 node disconnected_nodes_h2" + using h3 set_disconnected_nodes_get_disconnected_nodes + by blast + + have disconnected_nodes_eq_h3: + "\doc_ptr disc_nodes. h3 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes = + h' \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using get_disconnected_nodes_reads insert_node_writes h' + apply(rule reads_writes_preserved) + using set_child_nodes_get_disconnected_nodes by fast + then have disconnected_nodes_eq2_h3: + "\doc_ptr. |h3 \ get_disconnected_nodes doc_ptr|\<^sub>r = |h' \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + + have children_eq_h2: + "\ptr' children. h2 \ get_child_nodes ptr' \\<^sub>r children = h3 \ get_child_nodes ptr' \\<^sub>r children" + using get_child_nodes_reads set_disconnected_nodes_writes h3 + apply(rule reads_writes_preserved) + by (auto simp add: set_disconnected_nodes_get_child_nodes) + then have children_eq2_h2: "\ptr'. |h2 \ get_child_nodes ptr'|\<^sub>r = |h3 \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + + have children_eq_h3: + "\ptr' children. ptr \ ptr' \ + h3 \ get_child_nodes ptr' \\<^sub>r children = h' \ get_child_nodes ptr' \\<^sub>r children" + using get_child_nodes_reads insert_node_writes h' + apply(rule reads_writes_preserved) + by (auto simp add: set_child_nodes_get_child_nodes_different_pointers) + then have children_eq2_h3: + "\ptr'. ptr \ ptr' \ |h3 \ get_child_nodes ptr'|\<^sub>r = |h' \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + obtain children_h3 where children_h3: "h3 \ get_child_nodes ptr \\<^sub>r children_h3" + using h' a_insert_node_def by auto + have children_h': "h' \ get_child_nodes ptr \\<^sub>r insert_before_list node reference_child children_h3" + using h' \type_wf h3\ \known_ptr ptr\ + by(auto simp add: a_insert_node_def elim!: bind_returns_heap_E2 + dest!: set_child_nodes_get_child_nodes returns_result_eq[OF children_h3]) + + have ptr_in_heap: "ptr |\| object_ptr_kinds h3" + using children_h3 get_child_nodes_ptr_in_heap by blast + have node_in_heap: "node |\| node_ptr_kinds h" + using h2 adopt_node_child_in_heap by fast + have child_not_in_any_children: + "\p children. h2 \ get_child_nodes p \\<^sub>r children \ node \ set children" + using \heap_is_wellformed h\ h2 adopt_node_removes_child \type_wf h\ \known_ptrs h\ by auto + have "node \ set disconnected_nodes_h2" + using disconnected_nodes_h2 h2 adopt_node_node_in_disconnected_nodes assms(1) + \type_wf h\ \known_ptrs h\ by blast + have node_not_in_disconnected_nodes: + "\d. d |\| document_ptr_kinds h3 \ node \ set |h3 \ get_disconnected_nodes d|\<^sub>r" + proof - + fix d + assume "d |\| document_ptr_kinds h3" + show "node \ set |h3 \ get_disconnected_nodes d|\<^sub>r" + proof (cases "d = owner_document") + case True + then show ?thesis + using disconnected_nodes_h2 wellformed_h2 h3 remove_from_disconnected_nodes_removes + wellformed_h2 \d |\| document_ptr_kinds h3\ disconnected_nodes_h3 + by fastforce + next + case False + then have "set |h2 \ get_disconnected_nodes d|\<^sub>r \ set |h2 \ get_disconnected_nodes owner_document|\<^sub>r = {}" + using distinct_concat_map_E(1) wellformed_h2 + by (metis (no_types, lifting) \d |\| document_ptr_kinds h3\ \type_wf h2\ + disconnected_nodes_h2 document_ptr_kinds_M_def document_ptr_kinds_eq2_h2 + l_ptr_kinds_M.ptr_kinds_ptr_kinds_M local.get_disconnected_nodes_ok + local.heap_is_wellformed_one_disc_parent returns_result_select_result select_result_I2) + then show ?thesis + using disconnected_nodes_eq2_h2[OF False] \node \ set disconnected_nodes_h2\ + disconnected_nodes_h2 by fastforce + qed + qed + + have "cast node \ ptr" + using ancestors node_not_in_ancestors get_ancestors_ptr + by fast + + obtain ancestors_h2 where ancestors_h2: "h2 \ get_ancestors_si ptr \\<^sub>r ancestors_h2" + using get_ancestors_si_ok + by (metis \known_ptrs h2\ \type_wf h2\ is_OK_returns_result_E + object_ptr_kinds_M_eq3_h2 ptr_in_heap wellformed_h2) + have ancestors_h3: "h3 \ get_ancestors_si ptr \\<^sub>r ancestors_h2" + using get_ancestors_si_reads set_disconnected_nodes_writes h3 + apply(rule reads_writes_separate_forwards) + using \heap_is_wellformed h2\ apply simp + using ancestors_h2 apply simp + apply(auto simp add: get_ancestors_si_locs_def get_parent_locs_def)[1] + apply (simp add: local.get_ancestors_si_locs_def local.get_parent_reads_pointers + local.set_disconnected_nodes_get_ancestors_si) + using local.get_ancestors_si_locs_def local.set_disconnected_nodes_get_ancestors_si by blast + have node_not_in_ancestors_h2: "cast node \ set ancestors_h2" + using \heap_is_wellformed h\ \heap_is_wellformed h2\ ancestors ancestors_h2 + apply(rule get_ancestors_si_remains_not_in_ancestors) + using assms(2) assms(3) h2 local.adopt_node_children_subset apply blast + using shadow_root_eq_h2 node_not_in_ancestors object_ptr_kinds_M_eq2_h assms(2) assms(3) + \type_wf h2\ + by(auto dest: returns_result_eq) + + moreover + have "parent_child_rel h2 = parent_child_rel h3" + by(auto simp add: CD.parent_child_rel_def object_ptr_kinds_M_eq3_h2 children_eq2_h2) + have "parent_child_rel h' = insert (ptr, cast node) ((parent_child_rel h3))" + using children_h3 children_h' ptr_in_heap + apply(auto simp add: CD.parent_child_rel_def object_ptr_kinds_M_eq3_h' children_eq2_h3 + insert_before_list_node_in_set)[1] + apply (metis (no_types, lifting) children_eq2_h3 insert_before_list_in_set select_result_I2) + by (metis (no_types, lifting) children_eq2_h3 imageI insert_before_list_in_set select_result_I2) + have "CD.a_acyclic_heap h'" + proof - + have "acyclic (parent_child_rel h2)" + using wellformed_h2 + by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def CD.acyclic_heap_def) + then have "acyclic (parent_child_rel h3)" + by(auto simp add: CD.parent_child_rel_def object_ptr_kinds_M_eq3_h2 children_eq2_h2) + moreover have "cast node \ {x. (x, ptr) \ (parent_child_rel h2)\<^sup>*}" + using get_ancestors_si_parent_child_rel + using \known_ptrs h2\ \type_wf h2\ ancestors_h2 node_not_in_ancestors_h2 wellformed_h2 + by blast + then have "cast node \ {x. (x, ptr) \ (parent_child_rel h3)\<^sup>*}" + by(auto simp add: CD.parent_child_rel_def object_ptr_kinds_M_eq3_h2 children_eq2_h2) + ultimately show ?thesis + using \parent_child_rel h' = insert (ptr, cast node) ((parent_child_rel h3))\ + by(auto simp add: CD.acyclic_heap_def) + qed + + + moreover have "CD.a_all_ptrs_in_heap h2" + using wellformed_h2 by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + have "CD.a_all_ptrs_in_heap h'" + proof - + have "CD.a_all_ptrs_in_heap h3" + using \CD.a_all_ptrs_in_heap h2\ + apply(auto simp add: CD.a_all_ptrs_in_heap_def object_ptr_kinds_M_eq2_h2 + node_ptr_kinds_eq2_h2 children_eq_h2)[1] + using disconnected_nodes_eq2_h2 disconnected_nodes_h2 disconnected_nodes_h3 + using node_ptr_kinds_eq2_h2 apply auto[1] + apply (metis (no_types, lifting) children_eq2_h2 in_mono notin_fset object_ptr_kinds_M_eq3_h2) + by (metis (no_types, hide_lams) NodeMonad.ptr_kinds_ptr_kinds_M disconnected_nodes_eq2_h2 + disconnected_nodes_h2 disconnected_nodes_h3 document_ptr_kinds_commutes finite_set_in + node_ptr_kinds_eq2_h2 object_ptr_kinds_M_eq3_h2 select_result_I2 set_remove1_subset subsetD) + have "set children_h3 \ set |h' \ node_ptr_kinds_M|\<^sub>r" + using children_h3 \CD.a_all_ptrs_in_heap h3\ + apply(auto simp add: CD.a_all_ptrs_in_heap_def node_ptr_kinds_eq2_h3)[1] + using CD.parent_child_rel_child_nodes2 \known_ptr ptr\ + \parent_child_rel h2 = parent_child_rel h3\ \type_wf h2\ + local.parent_child_rel_child_in_heap node_ptr_kinds_commutes object_ptr_kinds_M_eq3_h' + object_ptr_kinds_M_eq3_h2 wellformed_h2 by blast + then have "set (insert_before_list node reference_child children_h3) \ set |h' \ node_ptr_kinds_M|\<^sub>r" + using node_in_heap + apply(auto simp add: node_ptr_kinds_eq2_h node_ptr_kinds_eq2_h2 node_ptr_kinds_eq2_h3)[1] + by (metis (no_types, hide_lams) contra_subsetD finite_set_in insert_before_list_in_set + node_ptr_kinds_commutes object_ptr_kinds_M_eq3_h object_ptr_kinds_M_eq3_h' object_ptr_kinds_M_eq3_h2) + then show ?thesis + using \CD.a_all_ptrs_in_heap h3\ + apply(auto simp add: object_ptr_kinds_M_eq3_h' CD.a_all_ptrs_in_heap_def node_ptr_kinds_def + node_ptr_kinds_eq2_h3 disconnected_nodes_eq_h3)[1] + using children_eq_h3 children_h' + apply (metis (no_types, lifting) children_eq2_h3 finite_set_in select_result_I2 subsetD) + by (metis (no_types, lifting) DocumentMonad.ptr_kinds_ptr_kinds_M disconnected_nodes_eq2_h3 + document_ptr_kinds_eq2_h3 finite_set_in subsetD) + qed + + + moreover have "CD.a_distinct_lists h2" + using wellformed_h2 by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def ) + then have "CD.a_distinct_lists h3" + proof(auto simp add: CD.a_distinct_lists_def object_ptr_kinds_M_eq2_h2 document_ptr_kinds_eq2_h2 + children_eq2_h2 intro!: distinct_concat_map_I) + fix x + assume 1: "x |\| document_ptr_kinds h3" + and 2: "distinct (concat (map (\document_ptr. |h2 \ get_disconnected_nodes document_ptr|\<^sub>r) +(sorted_list_of_set (fset (document_ptr_kinds h3)))))" + show "distinct |h3 \ get_disconnected_nodes x|\<^sub>r" + using distinct_concat_map_E(2)[OF 2] select_result_I2[OF disconnected_nodes_h3] + disconnected_nodes_eq2_h2 select_result_I2[OF disconnected_nodes_h2] 1 + by (metis (full_types) distinct_remove1 finite_fset fmember.rep_eq set_sorted_list_of_set) + next + fix x y xa + assume 1: "distinct (concat (map (\document_ptr. |h2 \ get_disconnected_nodes document_ptr|\<^sub>r) +(sorted_list_of_set (fset (document_ptr_kinds h3)))))" + and 2: "x |\| document_ptr_kinds h3" + and 3: "y |\| document_ptr_kinds h3" + and 4: "x \ y" + and 5: "xa \ set |h3 \ get_disconnected_nodes x|\<^sub>r" + and 6: "xa \ set |h3 \ get_disconnected_nodes y|\<^sub>r" + show False + proof (cases "x = owner_document") + case True + then have "y \ owner_document" + using 4 by simp + show ?thesis + using distinct_concat_map_E(1)[OF 1] + using 2 3 4 5 6 select_result_I2[OF disconnected_nodes_h3] + select_result_I2[OF disconnected_nodes_h2] + apply(auto simp add: True disconnected_nodes_eq2_h2[OF \y \ owner_document\])[1] + by (metis (no_types, hide_lams) disconnected_nodes_eq2_h2 disjoint_iff_not_equal + notin_set_remove1) + next + case False + then show ?thesis + proof (cases "y = owner_document") + case True + then show ?thesis + using distinct_concat_map_E(1)[OF 1] + using 2 3 4 5 6 select_result_I2[OF disconnected_nodes_h3] + select_result_I2[OF disconnected_nodes_h2] + apply(auto simp add: True disconnected_nodes_eq2_h2[OF \x \ owner_document\])[1] + by (metis (no_types, hide_lams) disconnected_nodes_eq2_h2 disjoint_iff_not_equal + notin_set_remove1) + next + case False + then show ?thesis + using distinct_concat_map_E(1)[OF 1, simplified, OF 2 3 4] 5 6 + using disconnected_nodes_eq2_h2 disconnected_nodes_h2 disconnected_nodes_h3 + disjoint_iff_not_equal finite_fset fmember.rep_eq notin_set_remove1 select_result_I2 + set_sorted_list_of_set + by (metis (no_types, lifting)) + qed + qed + next + fix x xa xb + assume 1: "(\x\fset (object_ptr_kinds h3). set |h3 \ get_child_nodes x|\<^sub>r) \ +(\x\fset (document_ptr_kinds h3). set |h2 \ get_disconnected_nodes x|\<^sub>r) = {}" + and 2: "xa |\| object_ptr_kinds h3" + and 3: "x \ set |h3 \ get_child_nodes xa|\<^sub>r" + and 4: "xb |\| document_ptr_kinds h3" + and 5: "x \ set |h3 \ get_disconnected_nodes xb|\<^sub>r" + have 6: "set |h3 \ get_child_nodes xa|\<^sub>r \ set |h2 \ get_disconnected_nodes xb|\<^sub>r = {}" + using 1 2 4 + by (metis \type_wf h2\ children_eq2_h2 document_ptr_kinds_commutes \known_ptrs h\ + local.get_child_nodes_ok local.get_disconnected_nodes_ok + local.heap_is_wellformed_children_disc_nodes_different local.known_ptrs_known_ptr + object_ptr_kinds_M_eq3_h object_ptr_kinds_M_eq3_h2 returns_result_select_result wellformed_h2) + show False + proof (cases "xb = owner_document") + case True + then show ?thesis + using select_result_I2[OF disconnected_nodes_h3,folded select_result_I2[OF disconnected_nodes_h2]] + by (metis (no_types, lifting) "3" "5" "6" disjoint_iff_not_equal notin_set_remove1) + next + case False + show ?thesis + using 2 3 4 5 6 unfolding disconnected_nodes_eq2_h2[OF False] by auto + qed + qed + then have "CD.a_distinct_lists h'" + proof(auto simp add: CD.a_distinct_lists_def document_ptr_kinds_eq2_h3 object_ptr_kinds_M_eq2_h3 + disconnected_nodes_eq2_h3 intro!: distinct_concat_map_I) + fix x + assume 1: "distinct (concat (map (\ptr. |h3 \ get_child_nodes ptr|\<^sub>r) +(sorted_list_of_set (fset (object_ptr_kinds h')))))" and + 2: "x |\| object_ptr_kinds h'" + have 3: "\p. p |\| object_ptr_kinds h' \ distinct |h3 \ get_child_nodes p|\<^sub>r" + using 1 by (auto elim: distinct_concat_map_E) + show "distinct |h' \ get_child_nodes x|\<^sub>r" + proof(cases "ptr = x") + case True + show ?thesis + using 3[OF 2] children_h3 children_h' + by(auto simp add: True insert_before_list_distinct + dest: child_not_in_any_children[unfolded children_eq_h2]) + next + case False + show ?thesis + using children_eq2_h3[OF False] 3[OF 2] by auto + qed + next + fix x y xa + assume 1:"distinct (concat (map (\ptr. |h3 \ get_child_nodes ptr|\<^sub>r) +(sorted_list_of_set (fset (object_ptr_kinds h')))))" + and 2: "x |\| object_ptr_kinds h'" + and 3: "y |\| object_ptr_kinds h'" + and 4: "x \ y" + and 5: "xa \ set |h' \ get_child_nodes x|\<^sub>r" + and 6: "xa \ set |h' \ get_child_nodes y|\<^sub>r" + have 7:"set |h3 \ get_child_nodes x|\<^sub>r \ set |h3 \ get_child_nodes y|\<^sub>r = {}" + using distinct_concat_map_E(1)[OF 1] 2 3 4 by auto + show False + proof (cases "ptr = x") + case True + then have "ptr \ y" + using 4 by simp + then show ?thesis + using children_h3 children_h' child_not_in_any_children[unfolded children_eq_h2] 5 6 + apply(auto simp add: True children_eq2_h3[OF \ptr \ y\])[1] + by (metis (no_types, hide_lams) "3" "7" \type_wf h3\ children_eq2_h3 disjoint_iff_not_equal + get_child_nodes_ok insert_before_list_in_set \known_ptrs h\ local.known_ptrs_known_ptr + object_ptr_kinds_M_eq3_h object_ptr_kinds_M_eq3_h' object_ptr_kinds_M_eq3_h2 + returns_result_select_result select_result_I2) + next + case False + then show ?thesis + proof (cases "ptr = y") + case True + then show ?thesis + using children_h3 children_h' child_not_in_any_children[unfolded children_eq_h2] 5 6 + apply(auto simp add: True children_eq2_h3[OF \ptr \ x\])[1] + by (metis (no_types, hide_lams) "2" "4" "7" IntI \known_ptrs h3\ \type_wf h'\ + children_eq_h3 empty_iff insert_before_list_in_set local.get_child_nodes_ok + local.known_ptrs_known_ptr object_ptr_kinds_M_eq3_h' returns_result_select_result select_result_I2) + next + case False + then show ?thesis + using children_eq2_h3[OF \ptr \ x\] children_eq2_h3[OF \ptr \ y\] 5 6 7 by auto + qed + qed + next + fix x xa xb + assume 1: " (\x\fset (object_ptr_kinds h'). set |h3 \ get_child_nodes x|\<^sub>r) \ +(\x\fset (document_ptr_kinds h'). set |h' \ get_disconnected_nodes x|\<^sub>r) = {} " + and 2: "xa |\| object_ptr_kinds h'" + and 3: "x \ set |h' \ get_child_nodes xa|\<^sub>r" + and 4: "xb |\| document_ptr_kinds h'" + and 5: "x \ set |h' \ get_disconnected_nodes xb|\<^sub>r" + have 6: "set |h3 \ get_child_nodes xa|\<^sub>r \ set |h' \ get_disconnected_nodes xb|\<^sub>r = {}" + using 1 2 3 4 5 + proof - + have "\h d. \ type_wf h \ d |\| document_ptr_kinds h \ h \ ok get_disconnected_nodes d" + using local.get_disconnected_nodes_ok by satx + then have "h' \ ok get_disconnected_nodes xb" + using "4" \type_wf h'\ by fastforce + then have f1: "h3 \ get_disconnected_nodes xb \\<^sub>r |h' \ get_disconnected_nodes xb|\<^sub>r" + by (simp add: disconnected_nodes_eq_h3) + have "xa |\| object_ptr_kinds h3" + using "2" object_ptr_kinds_M_eq3_h' by blast + then show ?thesis + using f1 \local.CD.a_distinct_lists h3\ CD.distinct_lists_no_parent by fastforce + qed + show False + proof (cases "ptr = xa") + case True + show ?thesis + using 6 node_not_in_disconnected_nodes 3 4 5 select_result_I2[OF children_h'] + select_result_I2[OF children_h3] True disconnected_nodes_eq2_h3 + by (metis (no_types, lifting) "2" DocumentMonad.ptr_kinds_ptr_kinds_M + \CD.a_distinct_lists h3\ \type_wf h'\ disconnected_nodes_eq_h3 CD.distinct_lists_no_parent + document_ptr_kinds_eq2_h3 get_disconnected_nodes_ok insert_before_list_in_set + object_ptr_kinds_M_eq3_h' returns_result_select_result) + + next + case False + then show ?thesis + using 1 2 3 4 5 children_eq2_h3[OF False] by fastforce + qed + qed + + moreover have "CD.a_owner_document_valid h2" + using wellformed_h2 by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_owner_document_valid h'" + apply(auto simp add: CD.a_owner_document_valid_def object_ptr_kinds_M_eq2_h2 + object_ptr_kinds_M_eq2_h3 node_ptr_kinds_eq2_h2 node_ptr_kinds_eq2_h3 document_ptr_kinds_eq2_h2 + document_ptr_kinds_eq2_h3 children_eq2_h2 )[1] thm children_eq2_h3 + apply(auto simp add: document_ptr_kinds_eq2_h2[simplified] document_ptr_kinds_eq2_h3[simplified] + object_ptr_kinds_M_eq2_h2[simplified] object_ptr_kinds_M_eq2_h3[simplified] + node_ptr_kinds_eq2_h2[simplified] node_ptr_kinds_eq2_h3[simplified])[1] + apply(auto simp add: disconnected_nodes_eq2_h3[symmetric])[1] + by (metis (no_types, lifting) Core_DOM_Functions.i_insert_before.insert_before_list_in_set + children_eq2_h3 children_h' children_h3 disconnected_nodes_eq2_h2 disconnected_nodes_h2 + disconnected_nodes_h3 finite_set_in in_set_remove1 is_OK_returns_result_I object_ptr_kinds_M_eq3_h' + ptr_in_heap returns_result_eq returns_result_select_result) + ultimately have "heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M h'" + by (simp add: CD.heap_is_wellformed_def) + + have shadow_root_eq_h2: + "\ptr' shadow_root_ptr_opt. h2 \ get_shadow_root ptr' \\<^sub>r shadow_root_ptr_opt = +h3 \ get_shadow_root ptr' \\<^sub>r shadow_root_ptr_opt" + using get_shadow_root_reads set_disconnected_nodes_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: adopt_node_locs_def remove_child_locs_def set_child_nodes_get_shadow_root + set_disconnected_nodes_get_shadow_root) + then + have shadow_root_eq2_h2: "\ptr'. |h2 \ get_shadow_root ptr'|\<^sub>r = |h3 \ get_shadow_root ptr'|\<^sub>r" + by (meson select_result_eq) + + have shadow_root_eq_h3: + "\ptr' shadow_root_ptr_opt. h3 \ get_shadow_root ptr' \\<^sub>r shadow_root_ptr_opt = +h' \ get_shadow_root ptr' \\<^sub>r shadow_root_ptr_opt" + using get_shadow_root_reads insert_node_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: adopt_node_locs_def remove_child_locs_def set_child_nodes_get_shadow_root + set_disconnected_nodes_get_shadow_root) + then + have shadow_root_eq2_h3: "\ptr'. |h3 \ get_shadow_root ptr'|\<^sub>r = |h' \ get_shadow_root ptr'|\<^sub>r" + by (meson select_result_eq) + + have tag_name_eq_h2: "\ptr' tag. h2 \ get_tag_name ptr' \\<^sub>r tag = h3 \ get_tag_name ptr' \\<^sub>r tag" + using get_tag_name_reads set_disconnected_nodes_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: adopt_node_locs_def remove_child_locs_def set_child_nodes_get_tag_name + set_disconnected_nodes_get_tag_name) + then + have tag_name_eq2_h2: "\ptr'. |h2 \ get_tag_name ptr'|\<^sub>r = |h3 \ get_tag_name ptr'|\<^sub>r" + by (meson select_result_eq) + + have tag_name_eq_h3: "\ptr' tag. h3 \ get_tag_name ptr' \\<^sub>r tag = h' \ get_tag_name ptr' \\<^sub>r tag" + using get_tag_name_reads insert_node_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: adopt_node_locs_def remove_child_locs_def set_child_nodes_get_tag_name + set_disconnected_nodes_get_tag_name) + then + have tag_name_eq2_h3: "\ptr'. |h3 \ get_tag_name ptr'|\<^sub>r = |h' \ get_tag_name ptr'|\<^sub>r" + by (meson select_result_eq) + + have object_ptr_kinds_eq_h2: "object_ptr_kinds h2 = object_ptr_kinds h3" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h = object_ptr_kinds h'", + OF set_disconnected_nodes_writes h3]) + unfolding adopt_node_locs_def remove_child_locs_def + using set_disconnected_nodes_pointers_preserved set_child_nodes_pointers_preserved + by (auto simp add: reflp_def transp_def split: if_splits) + + have object_ptr_kinds_eq_h3: "object_ptr_kinds h3 = object_ptr_kinds h'" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h = object_ptr_kinds h'", + OF insert_node_writes h']) + using set_disconnected_nodes_pointers_preserved set_child_nodes_pointers_preserved + by (auto simp add: reflp_def transp_def split: if_splits) + + have shadow_root_ptr_kinds_eq_h2: "shadow_root_ptr_kinds h2 = shadow_root_ptr_kinds h3" + using object_ptr_kinds_eq_h2 + by(auto simp add: shadow_root_ptr_kinds_def) + have element_ptr_kinds_eq_h2: "element_ptr_kinds h2 = element_ptr_kinds h3" + using object_ptr_kinds_eq_h2 + by(auto simp add: element_ptr_kinds_def node_ptr_kinds_def) + + have shadow_root_ptr_kinds_eq_h3: "shadow_root_ptr_kinds h3 = shadow_root_ptr_kinds h'" + using object_ptr_kinds_eq_h3 + by(auto simp add: shadow_root_ptr_kinds_def) + have element_ptr_kinds_eq_h3: "element_ptr_kinds h3 = element_ptr_kinds h'" + using object_ptr_kinds_eq_h3 + by(auto simp add: element_ptr_kinds_def node_ptr_kinds_def) + + + have "a_host_shadow_root_rel h2 = a_host_shadow_root_rel h3" + by(auto simp add: a_host_shadow_root_rel_def element_ptr_kinds_eq_h2 shadow_root_eq2_h2) + have "a_host_shadow_root_rel h3 = a_host_shadow_root_rel h'" + by(auto simp add: a_host_shadow_root_rel_def element_ptr_kinds_eq_h3 shadow_root_eq2_h3) + + have "cast node \ {x. (x, ptr) \ (parent_child_rel h3 \ a_host_shadow_root_rel h3)\<^sup>*}" + using get_ancestors_si_parent_child_host_shadow_root_rel + using \known_ptrs h2\ \local.a_host_shadow_root_rel h2 = local.a_host_shadow_root_rel h3\ + \parent_child_rel h2 = parent_child_rel h3\ \type_wf h2\ ancestors_h2 node_not_in_ancestors_h2 + wellformed_h2 + by auto + + have "acyclic (parent_child_rel h3 \ a_host_shadow_root_rel h3)" + using \heap_is_wellformed h2\ + by(auto simp add: heap_is_wellformed_def \parent_child_rel h2 = parent_child_rel h3\ + \a_host_shadow_root_rel h2 = a_host_shadow_root_rel h3\) + then + have "acyclic (parent_child_rel h' \ a_host_shadow_root_rel h')" + apply(auto simp add: \a_host_shadow_root_rel h3 = a_host_shadow_root_rel h'\ + \parent_child_rel h' = insert (ptr, cast node) ((parent_child_rel h3))\)[1] + using \cast node \ {x. (x, ptr) \ (parent_child_rel h3 \ a_host_shadow_root_rel h3)\<^sup>*}\ + by (simp add: \local.a_host_shadow_root_rel h3 = local.a_host_shadow_root_rel h'\) + then + show "heap_is_wellformed h'" + using \heap_is_wellformed h2\ + using \heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M h'\ + apply(auto simp add: heap_is_wellformed_def CD.heap_is_wellformed_def CD.acyclic_heap_def + a_all_ptrs_in_heap_def a_distinct_lists_def a_shadow_root_valid_def)[1] + by(auto simp add: object_ptr_kinds_eq_h2 object_ptr_kinds_eq_h3 element_ptr_kinds_eq_h2 + element_ptr_kinds_eq_h3 shadow_root_ptr_kinds_eq_h2 shadow_root_ptr_kinds_eq_h3 shadow_root_eq_h2 + shadow_root_eq_h3 shadow_root_eq2_h2 shadow_root_eq2_h3 tag_name_eq_h2 tag_name_eq_h3 + tag_name_eq2_h2 tag_name_eq2_h3) + +qed +end + +interpretation i_insert_before_wf?: l_insert_before_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_parent get_parent_locs + get_child_nodes get_child_nodes_locs set_child_nodes set_child_nodes_locs get_ancestors_si + get_ancestors_si_locs adopt_node adopt_node_locs set_disconnected_nodes set_disconnected_nodes_locs + get_disconnected_nodes get_disconnected_nodes_locs get_owner_document insert_before + insert_before_locs append_child type_wf known_ptr known_ptrs heap_is_wellformed parent_child_rel + by(simp add: l_insert_before_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_insert_before_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma insert_before_wf_is_l_insert_before_wf [instances]: + "l_insert_before_wf Shadow_DOM.heap_is_wellformed ShadowRootClass.type_wf +ShadowRootClass.known_ptr ShadowRootClass.known_ptrs + Shadow_DOM.insert_before Shadow_DOM.get_child_nodes" + apply(auto simp add: l_insert_before_wf_def l_insert_before_wf_axioms_def instances)[1] + using insert_before_removes_child apply fast + done + +lemma l_set_disconnected_nodes_get_disconnected_nodes_wf [instances]: "l_set_disconnected_nodes_get_disconnected_nodes_wf ShadowRootClass.type_wf +ShadowRootClass.known_ptr Shadow_DOM.heap_is_wellformed Shadow_DOM.parent_child_rel Shadow_DOM.get_child_nodes + get_disconnected_nodes get_disconnected_nodes_locs set_disconnected_nodes set_disconnected_nodes_locs" + apply(auto simp add: l_set_disconnected_nodes_get_disconnected_nodes_wf_def + l_set_disconnected_nodes_get_disconnected_nodes_wf_axioms_def instances)[1] + by (metis Diff_iff Shadow_DOM.i_heap_is_wellformed.heap_is_wellformed_disconnected_nodes_distinct + Shadow_DOM.i_remove_child.set_disconnected_nodes_get_disconnected_nodes insert_iff + returns_result_eq set_remove1_eq) + +interpretation l_get_root_node_si_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + type_wf known_ptr known_ptrs get_parent get_parent_locs get_child_nodes get_child_nodes_locs + get_host get_host_locs get_ancestors_si get_ancestors_si_locs get_root_node_si get_root_node_si_locs + get_disconnected_nodes get_disconnected_nodes_locs get_shadow_root get_shadow_root_locs + get_tag_name get_tag_name_locs heap_is_wellformed parent_child_rel heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + get_disconnected_document get_disconnected_document_locs + by(auto simp add: l_get_root_node_si_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_root_node_si_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +interpretation i_insert_before_wf2?: l_insert_before_wf2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr get_child_nodes + get_child_nodes_locs get_disconnected_nodes get_disconnected_nodes_locs set_child_nodes set_child_nodes_locs get_shadow_root get_shadow_root_locs set_disconnected_nodes set_disconnected_nodes_locs get_tag_name get_tag_name_locs heap_is_wellformed parent_child_rel get_ancestors_si get_ancestors_si_locs get_parent get_parent_locs adopt_node adopt_node_locs get_owner_document insert_before insert_before_locs append_child known_ptrs get_host get_host_locs get_root_node_si get_root_node_si_locs heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_document get_disconnected_document_locs + by(auto simp add: l_insert_before_wf2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_insert_before_wf2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +lemma insert_before_wf2_is_l_insert_before_wf2 [instances]: + "l_insert_before_wf2 ShadowRootClass.type_wf ShadowRootClass.known_ptr ShadowRootClass.known_ptrs +Shadow_DOM.insert_before + Shadow_DOM.heap_is_wellformed" + apply(auto simp add: l_insert_before_wf2_def l_insert_before_wf2_axioms_def instances)[1] + using insert_before_child_preserves apply(fast, fast, fast) + done + + +subsubsection \append\_child\ + +interpretation i_append_child_wf?: l_append_child_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_owner_document get_parent + get_parent_locs remove_child remove_child_locs + get_disconnected_nodes get_disconnected_nodes_locs + set_disconnected_nodes set_disconnected_nodes_locs + adopt_node adopt_node_locs known_ptr type_wf get_child_nodes + get_child_nodes_locs known_ptrs set_child_nodes + set_child_nodes_locs remove get_ancestors_si get_ancestors_si_locs + insert_before insert_before_locs append_child heap_is_wellformed + parent_child_rel + by(auto simp add: l_append_child_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_append_child_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma append_child_wf_is_l_append_child_wf [instances]: + "l_append_child_wf type_wf known_ptr known_ptrs append_child heap_is_wellformed" + apply(auto simp add: l_append_child_wf_def l_append_child_wf_axioms_def instances)[1] + using append_child_heap_is_wellformed_preserved by fast+ + + +subsubsection \to\_tree\_order\ + +interpretation i_to_tree_order_wf?: l_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr type_wf get_child_nodes + get_child_nodes_locs to_tree_order known_ptrs get_parent get_parent_locs heap_is_wellformed + parent_child_rel get_disconnected_nodes get_disconnected_nodes_locs + apply(auto simp add: l_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances)[1] + done +declare l_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma to_tree_order_wf_is_l_to_tree_order_wf [instances]: + "l_to_tree_order_wf heap_is_wellformed parent_child_rel type_wf known_ptr known_ptrs +to_tree_order get_parent get_child_nodes" + apply(auto simp add: l_to_tree_order_wf_def l_to_tree_order_wf_axioms_def instances)[1] + using to_tree_order_ok apply fast + using to_tree_order_ptrs_in_heap apply fast + using to_tree_order_parent_child_rel apply(fast, fast) + using to_tree_order_child2 apply blast + using to_tree_order_node_ptrs apply fast + using to_tree_order_child apply fast + using to_tree_order_ptr_in_result apply fast + using to_tree_order_parent apply fast + using to_tree_order_subset apply fast + done + + +paragraph \get\_root\_node\ + +interpretation i_to_tree_order_wf_get_root_node_wf?: l_to_tree_order_wf_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + known_ptr type_wf known_ptrs heap_is_wellformed parent_child_rel + get_child_nodes get_child_nodes_locs get_disconnected_nodes get_disconnected_nodes_locs + get_parent get_parent_locs get_ancestors get_ancestors_locs get_root_node get_root_node_locs + to_tree_order + by(auto simp add: l_to_tree_order_wf_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_to_tree_order_wf_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +lemma to_tree_order_wf_get_root_node_wf_is_l_to_tree_order_wf_get_root_node_wf [instances]: + "l_to_tree_order_wf_get_root_node_wf ShadowRootClass.type_wf ShadowRootClass.known_ptr +ShadowRootClass.known_ptrs to_tree_order Shadow_DOM.get_root_node + Shadow_DOM.heap_is_wellformed" + apply(auto simp add: l_to_tree_order_wf_get_root_node_wf_def + l_to_tree_order_wf_get_root_node_wf_axioms_def instances)[1] + using to_tree_order_get_root_node apply fast + using to_tree_order_same_root apply fast + done + + +subsubsection \to\_tree\_order\_si\ + +locale l_to_tree_order_si_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_child_nodes + + l_get_parent_get_host_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_to_tree_order_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma to_tree_order_si_ok: + assumes "heap_is_wellformed h" and "known_ptrs h" and "type_wf h" + and "ptr |\| object_ptr_kinds h" + shows "h \ ok (to_tree_order_si ptr)" +proof(insert assms(1) assms(4), induct rule: heap_wellformed_induct_si) + case (step parent) + have "known_ptr parent" + using assms(2) local.known_ptrs_known_ptr step.prems + by blast + then show ?case + using step + using assms(1) assms(2) assms(3) + using local.heap_is_wellformed_children_in_heap local.get_shadow_root_shadow_root_ptr_in_heap + by(auto simp add: to_tree_order_si_def[of parent] intro: get_child_nodes_ok get_shadow_root_ok + intro!: bind_is_OK_pure_I map_M_pure_I bind_pure_I map_M_ok_I split: option.splits) +qed +end + +interpretation i_to_tree_order_si_wf?: l_to_tree_order_si_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + type_wf known_ptr get_child_nodes get_child_nodes_locs get_disconnected_nodes + get_disconnected_nodes_locs get_shadow_root get_shadow_root_locs get_tag_name + get_tag_name_locs heap_is_wellformed parent_child_rel heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + get_host get_host_locs get_disconnected_document get_disconnected_document_locs + known_ptrs get_parent get_parent_locs to_tree_order_si + by(auto simp add: l_to_tree_order_si_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_to_tree_order_si_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsubsection \get\_assigned\_nodes\ + +lemma forall_M_small_big: "h \ forall_M f xs \\<^sub>h h' \ P h \ +(\h h' x. x \ set xs \ h \ f x \\<^sub>h h' \ P h \ P h') \ P h'" + by(induct xs arbitrary: h) (auto elim!: bind_returns_heap_E) + +locale l_assigned_nodes_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_assigned_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_heap_is_wellformed + + l_remove_child_wf2 + + l_append_child_wf + + l_remove_shadow_root_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin + +lemma assigned_nodes_distinct: + assumes "heap_is_wellformed h" + assumes "h \ assigned_nodes slot \\<^sub>r nodes" + shows "distinct nodes" +proof - + have "\ptr children. h \ get_child_nodes ptr \\<^sub>r children \ distinct children" + using assms(1) local.heap_is_wellformed_children_distinct by blast + then show ?thesis + using assms + apply(auto simp add: assigned_nodes_def elim!: bind_returns_result_E2 split: if_splits)[1] + by (simp add: filter_M_distinct) +qed + + +lemma flatten_dom_preserves: + assumes "heap_is_wellformed h" and "known_ptrs h" and "type_wf h" + assumes "h \ flatten_dom \\<^sub>h h'" + shows "heap_is_wellformed h'" and "known_ptrs h'" and "type_wf h'" +proof - + obtain tups h2 element_ptrs shadow_root_ptrs where + "h \ element_ptr_kinds_M \\<^sub>r element_ptrs" and + tups: "h \ map_filter_M2 (\element_ptr. do { + tag \ get_tag_name element_ptr; + assigned_nodes \ assigned_nodes element_ptr; + (if tag = ''slot'' \ assigned_nodes \ [] then +return (Some (element_ptr, assigned_nodes)) else return None)}) element_ptrs \\<^sub>r tups" + (is "h \ map_filter_M2 ?f element_ptrs \\<^sub>r tups") and + h2: "h \ forall_M (\(slot, assigned_nodes). do { + get_child_nodes (cast slot) \ forall_M remove; + forall_M (append_child (cast slot)) assigned_nodes + }) tups \\<^sub>h h2" and + "h2 \ shadow_root_ptr_kinds_M \\<^sub>r shadow_root_ptrs" and + h': "h2 \ forall_M (\shadow_root_ptr. do { + host \ get_host shadow_root_ptr; + get_child_nodes (cast host) \ forall_M remove; + get_child_nodes (cast shadow_root_ptr) \ forall_M (append_child (cast host)); + remove_shadow_root host + }) shadow_root_ptrs \\<^sub>h h'" + using \h \ flatten_dom \\<^sub>h h'\ + apply(auto simp add: flatten_dom_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF ElementMonad.ptr_kinds_M_pure, rotated] + bind_returns_heap_E2[rotated, OF ShadowRootMonad.ptr_kinds_M_pure, rotated])[1] + apply(drule pure_returns_heap_eq) + by(auto intro!: map_filter_M2_pure bind_pure_I) + have "heap_is_wellformed h2 \ known_ptrs h2 \ type_wf h2" + using h2 \heap_is_wellformed h\ \known_ptrs h\ \type_wf h\ + by(auto elim!: bind_returns_heap_E bind_returns_heap_E2[rotated, + OF get_child_nodes_pure, rotated] + elim!: forall_M_small_big[where P = "\h. heap_is_wellformed h \ known_ptrs h \ type_wf h", + simplified] + intro: remove_preserves_known_ptrs remove_heap_is_wellformed_preserved + remove_preserves_type_wf + append_child_preserves_known_ptrs append_child_heap_is_wellformed_preserved + append_child_preserves_type_wf) + then + show "heap_is_wellformed h'" and "known_ptrs h'" and "type_wf h'" + using h' + by(auto elim!: bind_returns_heap_E bind_returns_heap_E2[rotated, OF get_host_pure, rotated] + bind_returns_heap_E2[rotated, OF get_child_nodes_pure, rotated] + dest!: forall_M_small_big[where P = "\h. heap_is_wellformed h \ known_ptrs h \ type_wf h", + simplified] + intro: remove_preserves_known_ptrs remove_heap_is_wellformed_preserved + remove_preserves_type_wf + append_child_preserves_known_ptrs append_child_heap_is_wellformed_preserved + append_child_preserves_type_wf + remove_shadow_root_preserves + ) +qed +end + +interpretation i_assigned_nodes_wf?: l_assigned_nodes_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + known_ptr assigned_nodes assigned_nodes_flatten flatten_dom get_child_nodes get_child_nodes_locs + get_tag_name get_tag_name_locs get_root_node get_root_node_locs get_host get_host_locs find_slot + assigned_slot remove insert_before insert_before_locs append_child remove_shadow_root + remove_shadow_root_locs type_wf get_shadow_root get_shadow_root_locs set_shadow_root + set_shadow_root_locs get_parent get_parent_locs to_tree_order heap_is_wellformed parent_child_rel + get_disconnected_nodes get_disconnected_nodes_locs known_ptrs remove_child remove_child_locs + heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_document get_disconnected_document_locs + by(auto simp add: l_assigned_nodes_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_assigned_nodes_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +subsubsection \get\_shadow\_root\_safe\ + +locale l_get_shadow_root_safe_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes get_child_nodes_locs get_disconnected_nodes + get_disconnected_nodes_locs get_shadow_root get_shadow_root_locs get_tag_name get_tag_name_locs + known_ptr type_wf heap_is_wellformed parent_child_rel heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host + get_host_locs + + l_type_wf type_wf + + l_get_shadow_root_safe\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_shadow_root_safe get_shadow_root_safe_locs + get_shadow_root get_shadow_root_locs get_mode get_mode_locs + for known_ptr :: "(_::linorder) object_ptr \ bool" + and known_ptrs :: "(_) heap \ bool" + and type_wf :: "(_) heap \ bool" + and get_host :: "(_) shadow_root_ptr \ ((_) heap, exception, (_) element_ptr) prog" + and get_host_locs :: "((_) heap \ (_) heap \ bool) set" + and get_shadow_root :: + "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_shadow_root_safe :: + "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_safe_locs :: + "(_) element_ptr \ (_) shadow_root_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_child_nodes :: "(_::linorder) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_disconnected_nodes :: "(_) document_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_tag_name :: "(_) element_ptr \ ((_) heap, exception, char list) prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and heap_is_wellformed :: "(_) heap \ bool" + and parent_child_rel :: "(_) heap \ ((_) object_ptr \ (_) object_ptr) set" + and heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and get_mode :: "(_) shadow_root_ptr \ ((_) heap, exception, shadow_root_mode) prog" + and get_mode_locs :: "(_) shadow_root_ptr \ ((_) heap \ (_) heap \ bool) set" +begin + + +end + + +subsubsection \create\_element\ + +locale l_create_element_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_disconnected_nodes type_wf get_disconnected_nodes get_disconnected_nodes_locs + + l_set_tag_name type_wf set_tag_name set_tag_name_locs + + l_create_element_defs create_element + + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes get_child_nodes_locs get_disconnected_nodes + get_disconnected_nodes_locs + get_shadow_root get_shadow_root_locs get_tag_name get_tag_name_locs known_ptr type_wf + heap_is_wellformed parent_child_rel + heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host get_host_locs get_disconnected_document + get_disconnected_document_locs + + l_new_element_get_disconnected_nodes get_disconnected_nodes get_disconnected_nodes_locs + + l_set_tag_name_get_disconnected_nodes type_wf set_tag_name set_tag_name_locs + get_disconnected_nodes get_disconnected_nodes_locs + + l_create_element\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_nodes get_disconnected_nodes_locs set_disconnected_nodes + set_disconnected_nodes_locs set_tag_name set_tag_name_locs type_wf create_element known_ptr + type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_new_element_get_child_nodes type_wf known_ptr get_child_nodes get_child_nodes_locs + + l_set_tag_name_get_child_nodes type_wf set_tag_name set_tag_name_locs known_ptr + get_child_nodes get_child_nodes_locs + + l_set_tag_name_get_tag_name type_wf get_tag_name get_tag_name_locs set_tag_name set_tag_name_locs + + l_new_element_get_tag_name type_wf get_tag_name get_tag_name_locs + + l_set_disconnected_nodes_get_child_nodes set_disconnected_nodes set_disconnected_nodes_locs + get_child_nodes get_child_nodes_locs + + l_set_disconnected_nodes_get_shadow_root set_disconnected_nodes set_disconnected_nodes_locs + get_shadow_root get_shadow_root_locs + + l_set_disconnected_nodes_get_tag_name type_wf set_disconnected_nodes set_disconnected_nodes_locs + get_tag_name get_tag_name_locs + + l_set_disconnected_nodes type_wf set_disconnected_nodes set_disconnected_nodes_locs + + l_set_disconnected_nodes_get_disconnected_nodes type_wf get_disconnected_nodes + get_disconnected_nodes_locs set_disconnected_nodes set_disconnected_nodes_locs + + l_new_element_get_shadow_root type_wf get_shadow_root get_shadow_root_locs + + l_set_tag_name_get_shadow_root type_wf set_tag_name set_tag_name_locs get_shadow_root + get_shadow_root_locs + + l_new_element type_wf + + l_known_ptrs known_ptr known_ptrs + for known_ptr :: "(_::linorder) object_ptr \ bool" + and known_ptrs :: "(_) heap \ bool" + and type_wf :: "(_) heap \ bool" + and get_child_nodes :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_disconnected_nodes :: "(_) document_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" + and heap_is_wellformed :: "(_) heap \ bool" + and parent_child_rel :: "(_) heap \ ((_) object_ptr \ (_) object_ptr) set" + and set_tag_name :: "(_) element_ptr \ char list \ ((_) heap, exception, unit) prog" + and set_tag_name_locs :: "(_) element_ptr \ ((_) heap, exception, unit) prog set" + and set_disconnected_nodes :: + "(_) document_ptr \ (_) node_ptr list \ ((_) heap, exception, unit) prog" + and set_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap, exception, unit) prog set" + and create_element :: + "(_) document_ptr \ char list \ ((_) heap, exception, (_) element_ptr) prog" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_tag_name :: "(_) element_ptr \ ((_) heap, exception, char list) prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and get_host :: "(_) shadow_root_ptr \ ((_) heap, exception, (_) element_ptr) prog" + and get_host_locs :: "((_) heap \ (_) heap \ bool) set" + and get_disconnected_document :: "(_) node_ptr \ ((_) heap, exception, (_) document_ptr) prog" + and get_disconnected_document_locs :: "((_) heap \ (_) heap \ bool) set" + and known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_::linorder) object_ptr \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" +begin +lemma create_element_preserves_wellformedness: + assumes "heap_is_wellformed h" + and "h \ create_element document_ptr tag \\<^sub>h h'" + and "type_wf h" + and "known_ptrs h" + shows "heap_is_wellformed h'" and "type_wf h'" and "known_ptrs h'" +proof - + obtain new_element_ptr h2 h3 disc_nodes_h3 where + new_element_ptr: "h \ new_element \\<^sub>r new_element_ptr" and + h2: "h \ new_element \\<^sub>h h2" and + h3: "h2 \ set_tag_name new_element_ptr tag \\<^sub>h h3" and + disc_nodes_h3: "h3 \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes_h3" and + h': "h3 \ set_disconnected_nodes document_ptr (cast new_element_ptr # disc_nodes_h3) \\<^sub>h h'" + using assms(2) + by(auto simp add: create_element_def + elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF CD.get_disconnected_nodes_pure, rotated] ) + then have "h \ create_element document_ptr tag \\<^sub>r new_element_ptr" + apply(auto simp add: create_element_def intro!: bind_returns_result_I)[1] + apply (metis is_OK_returns_heap_I is_OK_returns_result_E old.unit.exhaust) + apply (metis is_OK_returns_heap_E is_OK_returns_result_I CD.get_disconnected_nodes_pure + pure_returns_heap_eq) + by (metis is_OK_returns_heap_I is_OK_returns_result_E old.unit.exhaust) + + have "new_element_ptr \ set |h \ element_ptr_kinds_M|\<^sub>r" + using new_element_ptr ElementMonad.ptr_kinds_ptr_kinds_M h2 + using new_element_ptr_not_in_heap by blast + then have "cast new_element_ptr \ set |h \ node_ptr_kinds_M|\<^sub>r" + by simp + then have "cast new_element_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r" + by simp + + have object_ptr_kinds_eq_h: "object_ptr_kinds h2 = object_ptr_kinds h |\| {|cast new_element_ptr|}" + using new_element_new_ptr h2 new_element_ptr by blast + then have node_ptr_kinds_eq_h: "node_ptr_kinds h2 = node_ptr_kinds h |\| {|cast new_element_ptr|}" + apply(simp add: node_ptr_kinds_def) + by force + then have element_ptr_kinds_eq_h: "element_ptr_kinds h2 = element_ptr_kinds h |\| {|new_element_ptr|}" + apply(simp add: element_ptr_kinds_def) + by force + have character_data_ptr_kinds_eq_h: "character_data_ptr_kinds h2 = character_data_ptr_kinds h" + using object_ptr_kinds_eq_h + by(auto simp add: node_ptr_kinds_def character_data_ptr_kinds_def) + have document_ptr_kinds_eq_h: "document_ptr_kinds h2 = document_ptr_kinds h" + using object_ptr_kinds_eq_h + by(auto simp add: document_ptr_kinds_def) + + have object_ptr_kinds_eq_h2: "object_ptr_kinds h3 = object_ptr_kinds h2" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h' = object_ptr_kinds h", + OF set_tag_name_writes h3]) + using set_tag_name_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have document_ptr_kinds_eq_h2: "document_ptr_kinds h3 = document_ptr_kinds h2" + by (auto simp add: document_ptr_kinds_def) + have node_ptr_kinds_eq_h2: "node_ptr_kinds h3 = node_ptr_kinds h2" + using object_ptr_kinds_eq_h2 + by(auto simp add: node_ptr_kinds_def) + then have element_ptr_kinds_eq_h2: "element_ptr_kinds h3 = element_ptr_kinds h2" + by(simp add: element_ptr_kinds_def) + + have object_ptr_kinds_eq_h3: "object_ptr_kinds h' = object_ptr_kinds h3" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h' = object_ptr_kinds h", + OF set_disconnected_nodes_writes h']) + using set_disconnected_nodes_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have document_ptr_kinds_eq_h3: "document_ptr_kinds h' = document_ptr_kinds h3" + by (auto simp add: document_ptr_kinds_def) + have node_ptr_kinds_eq_h3: "node_ptr_kinds h' = node_ptr_kinds h3" + using object_ptr_kinds_eq_h3 + by(auto simp add: node_ptr_kinds_def) + then have element_ptr_kinds_eq_h3: "element_ptr_kinds h' = element_ptr_kinds h3" + by(simp add: element_ptr_kinds_def) + + have "known_ptr (cast new_element_ptr)" + using \h \ create_element document_ptr tag \\<^sub>r new_element_ptr\ local.create_element_known_ptr + by blast + then + have "known_ptrs h2" + using known_ptrs_new_ptr object_ptr_kinds_eq_h \known_ptrs h\ h2 + by blast + then + have "known_ptrs h3" + using known_ptrs_preserved object_ptr_kinds_eq_h2 by blast + then + show "known_ptrs h'" + using known_ptrs_preserved object_ptr_kinds_eq_h3 by blast + + + have "document_ptr |\| document_ptr_kinds h" + using disc_nodes_h3 document_ptr_kinds_eq_h object_ptr_kinds_eq_h2 + CD.get_disconnected_nodes_ptr_in_heap \type_wf h\ document_ptr_kinds_def + by (metis is_OK_returns_result_I) + + have children_eq_h: "\(ptr'::(_) object_ptr) children. ptr' \ cast new_element_ptr + \ h \ get_child_nodes ptr' \\<^sub>r children = h2 \ get_child_nodes ptr' \\<^sub>r children" + using CD.get_child_nodes_reads h2 get_child_nodes_new_element[rotated, OF new_element_ptr h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have children_eq2_h: "\ptr'. ptr' \ cast new_element_ptr + \ |h \ get_child_nodes ptr'|\<^sub>r = |h2 \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + have "h2 \ get_child_nodes (cast new_element_ptr) \\<^sub>r []" + using new_element_ptr h2 new_element_ptr_in_heap[OF h2 new_element_ptr] + new_element_is_element_ptr[OF new_element_ptr] new_element_no_child_nodes + by blast + have tag_name_eq_h: + "\ptr' disc_nodes. ptr' \ new_element_ptr + \ h \ get_tag_name ptr' \\<^sub>r disc_nodes + = h2 \ get_tag_name ptr' \\<^sub>r disc_nodes" + using get_tag_name_reads h2 get_tag_name_new_element[rotated, OF new_element_ptr h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by(blast)+ + then have tag_name_eq2_h: "\ptr'. ptr' \ new_element_ptr + \ |h \ get_tag_name ptr'|\<^sub>r = |h2 \ get_tag_name ptr'|\<^sub>r" + using select_result_eq by force + have "h2 \ get_tag_name new_element_ptr \\<^sub>r ''''" + using new_element_ptr h2 new_element_ptr_in_heap[OF h2 new_element_ptr] + new_element_is_element_ptr[OF new_element_ptr] new_element_empty_tag_name + by blast + + + have disconnected_nodes_eq_h: + "\doc_ptr disc_nodes. h \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes + = h2 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using CD.get_disconnected_nodes_reads h2 get_disconnected_nodes_new_element[OF new_element_ptr h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have disconnected_nodes_eq2_h: + "\doc_ptr. |h \ get_disconnected_nodes doc_ptr|\<^sub>r = |h2 \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + + have children_eq_h2: + "\ptr' children. h2 \ get_child_nodes ptr' \\<^sub>r children = h3 \ get_child_nodes ptr' \\<^sub>r children" + using CD.get_child_nodes_reads set_tag_name_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: set_tag_name_get_child_nodes) + then have children_eq2_h2: "\ptr'. |h2 \ get_child_nodes ptr'|\<^sub>r = |h3 \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + have disconnected_nodes_eq_h2: + "\doc_ptr disc_nodes. h2 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes + = h3 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using CD.get_disconnected_nodes_reads set_tag_name_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: set_tag_name_get_disconnected_nodes) + then have disconnected_nodes_eq2_h2: + "\doc_ptr. |h2 \ get_disconnected_nodes doc_ptr|\<^sub>r = |h3 \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + have tag_name_eq_h2: + "\ptr' disc_nodes. ptr' \ new_element_ptr + \ h2 \ get_tag_name ptr' \\<^sub>r disc_nodes + = h3 \ get_tag_name ptr' \\<^sub>r disc_nodes" + apply(rule reads_writes_preserved[OF get_tag_name_reads set_tag_name_writes h3]) + by (metis local.set_tag_name_get_tag_name_different_pointers) + then have tag_name_eq2_h2: "\ptr'. ptr' \ new_element_ptr + \ |h2 \ get_tag_name ptr'|\<^sub>r = |h3 \ get_tag_name ptr'|\<^sub>r" + using select_result_eq by force + have "h2 \ get_tag_name new_element_ptr \\<^sub>r ''''" + using new_element_ptr h2 new_element_ptr_in_heap[OF h2 new_element_ptr] + new_element_is_element_ptr[OF new_element_ptr] new_element_empty_tag_name + by blast + + have "type_wf h2" + using \type_wf h\ new_element_types_preserved h2 by blast + then have "type_wf h3" + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", OF set_tag_name_writes h3] + using set_tag_name_types_preserved + by(auto simp add: reflp_def transp_def) + then show "type_wf h'" + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", OF set_disconnected_nodes_writes h'] + using set_disconnected_nodes_types_preserved + by(auto simp add: reflp_def transp_def) + + have children_eq_h3: + "\ptr' children. h3 \ get_child_nodes ptr' \\<^sub>r children = h' \ get_child_nodes ptr' \\<^sub>r children" + using CD.get_child_nodes_reads set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: set_disconnected_nodes_get_child_nodes) + then have children_eq2_h3: "\ptr'. |h3 \ get_child_nodes ptr'|\<^sub>r = |h' \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + have disconnected_nodes_eq_h3: + "\doc_ptr disc_nodes. document_ptr \ doc_ptr + \ h3 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes + = h' \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using CD.get_disconnected_nodes_reads set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: set_disconnected_nodes_get_disconnected_nodes_different_pointers) + then have disconnected_nodes_eq2_h3: + "\doc_ptr. document_ptr \ doc_ptr + \ |h3 \ get_disconnected_nodes doc_ptr|\<^sub>r = |h' \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + have tag_name_eq_h2: + "\ptr' disc_nodes. ptr' \ new_element_ptr + \ h2 \ get_tag_name ptr' \\<^sub>r disc_nodes + = h3 \ get_tag_name ptr' \\<^sub>r disc_nodes" + apply(rule reads_writes_preserved[OF get_tag_name_reads set_tag_name_writes h3]) + by (metis local.set_tag_name_get_tag_name_different_pointers) + then have tag_name_eq2_h2: "\ptr'. ptr' \ new_element_ptr + \ |h2 \ get_tag_name ptr'|\<^sub>r = |h3 \ get_tag_name ptr'|\<^sub>r" + using select_result_eq by force + + have disc_nodes_document_ptr_h2: "h2 \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes_h3" + using disconnected_nodes_eq_h2 disc_nodes_h3 by auto + then have disc_nodes_document_ptr_h: "h \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes_h3" + using disconnected_nodes_eq_h by auto + then have "cast new_element_ptr \ set disc_nodes_h3" + using \heap_is_wellformed h\ + using \cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr \ set |h \ node_ptr_kinds_M|\<^sub>r\ + a_all_ptrs_in_heap_def heap_is_wellformed_def + using NodeMonad.ptr_kinds_ptr_kinds_M local.heap_is_wellformed_disc_nodes_in_heap by blast + + have tag_name_eq_h3: + "\ptr' disc_nodes. h3 \ get_tag_name ptr' \\<^sub>r disc_nodes + = h' \ get_tag_name ptr' \\<^sub>r disc_nodes" + apply(rule reads_writes_preserved[OF get_tag_name_reads set_disconnected_nodes_writes h']) + using set_disconnected_nodes_get_tag_name + by blast + then have tag_name_eq2_h3: "\ptr'. |h3 \ get_tag_name ptr'|\<^sub>r = |h' \ get_tag_name ptr'|\<^sub>r" + using select_result_eq by force + + + have "acyclic (parent_child_rel h)" + using \heap_is_wellformed h\ + by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def CD.acyclic_heap_def) + also have "parent_child_rel h = parent_child_rel h2" + proof(auto simp add: CD.parent_child_rel_def)[1] + fix a x + assume 0: "a |\| object_ptr_kinds h" + and 1: "x \ set |h \ get_child_nodes a|\<^sub>r" + then show "a |\| object_ptr_kinds h2" + by (simp add: object_ptr_kinds_eq_h) + next + fix a x + assume 0: "a |\| object_ptr_kinds h" + and 1: "x \ set |h \ get_child_nodes a|\<^sub>r" + then show "x \ set |h2 \ get_child_nodes a|\<^sub>r" + by (metis ObjectMonad.ptr_kinds_ptr_kinds_M + \cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r\ children_eq2_h) + next + fix a x + assume 0: "a |\| object_ptr_kinds h2" + and 1: "x \ set |h2 \ get_child_nodes a|\<^sub>r" + then show "a |\| object_ptr_kinds h" + using object_ptr_kinds_eq_h \h2 \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr) \\<^sub>r []\ + by(auto) + next + fix a x + assume 0: "a |\| object_ptr_kinds h2" + and 1: "x \ set |h2 \ get_child_nodes a|\<^sub>r" + then show "x \ set |h \ get_child_nodes a|\<^sub>r" + by (metis (no_types, lifting) + \h2 \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr) \\<^sub>r []\ + children_eq2_h empty_iff empty_set image_eqI select_result_I2) + qed + also have "\ = parent_child_rel h3" + by(auto simp add: CD.parent_child_rel_def object_ptr_kinds_eq_h2 children_eq2_h2) + also have "\ = parent_child_rel h'" + by(auto simp add: CD.parent_child_rel_def object_ptr_kinds_eq_h3 children_eq2_h3) + finally have "CD.a_acyclic_heap h'" + by (simp add: CD.acyclic_heap_def) + + have "CD.a_all_ptrs_in_heap h" + using \heap_is_wellformed h\ by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_all_ptrs_in_heap h2" + apply(auto simp add: CD.a_all_ptrs_in_heap_def)[1] + apply (metis \known_ptrs h2\ \parent_child_rel h = parent_child_rel h2\ \type_wf h2\ assms(1) + assms(3) funion_iff CD.get_child_nodes_ok local.known_ptrs_known_ptr + local.parent_child_rel_child_in_heap CD.parent_child_rel_child_nodes2 node_ptr_kinds_commutes + node_ptr_kinds_eq_h returns_result_select_result) + by (metis (no_types, lifting) CD.get_child_nodes_ok CD.get_child_nodes_ptr_in_heap + \h2 \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr) \\<^sub>r []\ assms(3) assms(4) + children_eq_h disconnected_nodes_eq2_h document_ptr_kinds_eq_h finite_set_in is_OK_returns_result_I + local.known_ptrs_known_ptr node_ptr_kinds_commutes returns_result_select_result subsetD) + then have "CD.a_all_ptrs_in_heap h3" + by (simp add: children_eq2_h2 disconnected_nodes_eq2_h2 document_ptr_kinds_eq_h2 + CD.a_all_ptrs_in_heap_def node_ptr_kinds_eq_h2 object_ptr_kinds_eq_h2) + then have "CD.a_all_ptrs_in_heap h'" + by (smt children_eq2_h3 disc_nodes_h3 disconnected_nodes_eq2_h3 document_ptr_kinds_eq_h3 + element_ptr_kinds_commutes h' h2 local.CD.a_all_ptrs_in_heap_def + local.set_disconnected_nodes_get_disconnected_nodes new_element_ptr new_element_ptr_in_heap + node_ptr_kinds_eq_h2 node_ptr_kinds_eq_h3 notin_fset object_ptr_kinds_eq_h3 select_result_I2 + set_ConsD subset_code(1)) + + have "\p. p |\| object_ptr_kinds h \ cast new_element_ptr \ set |h \ get_child_nodes p|\<^sub>r" + using \heap_is_wellformed h\ \cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr \ set |h \ node_ptr_kinds_M|\<^sub>r\ + heap_is_wellformed_children_in_heap + by (meson NodeMonad.ptr_kinds_ptr_kinds_M CD.a_all_ptrs_in_heap_def assms(3) assms(4) fset_mp + fset_of_list_elem CD.get_child_nodes_ok known_ptrs_known_ptr returns_result_select_result) + then have "\p. p |\| object_ptr_kinds h2 \ cast new_element_ptr \ set |h2 \ get_child_nodes p|\<^sub>r" + using children_eq2_h + apply(auto simp add: object_ptr_kinds_eq_h)[1] + using \h2 \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr) \\<^sub>r []\ apply auto[1] + by (metis ObjectMonad.ptr_kinds_ptr_kinds_M + \cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r\) + then have "\p. p |\| object_ptr_kinds h3 \ cast new_element_ptr \ set |h3 \ get_child_nodes p|\<^sub>r" + using object_ptr_kinds_eq_h2 children_eq2_h2 by auto + then have new_element_ptr_not_in_any_children: + "\p. p |\| object_ptr_kinds h' \ cast new_element_ptr \ set |h' \ get_child_nodes p|\<^sub>r" + using object_ptr_kinds_eq_h3 children_eq2_h3 by auto + + have "CD.a_distinct_lists h" + using \heap_is_wellformed h\ + by (simp add: CD.heap_is_wellformed_def heap_is_wellformed_def) + then have "CD.a_distinct_lists h2" + using \h2 \ get_child_nodes (cast new_element_ptr) \\<^sub>r []\ + apply(auto simp add: CD.a_distinct_lists_def object_ptr_kinds_eq_h document_ptr_kinds_eq_h + disconnected_nodes_eq2_h intro!: distinct_concat_map_I)[1] + apply (metis distinct_sorted_list_of_set finite_fset sorted_list_of_set_insert) + apply(case_tac "x=cast new_element_ptr") + apply(auto simp add: children_eq2_h[symmetric] insort_split dest: distinct_concat_map_E(2))[1] + apply(auto simp add: children_eq2_h[symmetric] insort_split dest: distinct_concat_map_E(2))[1] + apply(auto simp add: children_eq2_h[symmetric] insort_split dest: distinct_concat_map_E(2))[1] + apply (metis IntI assms(1) assms(3) assms(4) empty_iff CD.get_child_nodes_ok + local.heap_is_wellformed_one_parent local.known_ptrs_known_ptr returns_result_select_result) + apply(auto simp add: children_eq2_h[symmetric] insort_split dest: distinct_concat_map_E(2))[1] + by (metis \ CD.a_distinct_lists h\ \type_wf h2\ disconnected_nodes_eq_h document_ptr_kinds_eq_h + CD.distinct_lists_no_parent get_disconnected_nodes_ok returns_result_select_result) + + then have " CD.a_distinct_lists h3" + by(auto simp add: CD.a_distinct_lists_def disconnected_nodes_eq2_h2 document_ptr_kinds_eq_h2 + children_eq2_h2 object_ptr_kinds_eq_h2) + then have " CD.a_distinct_lists h'" + proof(auto simp add: CD.a_distinct_lists_def disconnected_nodes_eq2_h3 children_eq2_h3 + object_ptr_kinds_eq_h3 document_ptr_kinds_eq_h3 + intro!: distinct_concat_map_I)[1] + fix x + assume "distinct (concat (map (\document_ptr. |h3 \ get_disconnected_nodes document_ptr|\<^sub>r) + (sorted_list_of_set (fset (document_ptr_kinds h3)))))" + and "x |\| document_ptr_kinds h3" + then show "distinct |h' \ get_disconnected_nodes x|\<^sub>r" + using document_ptr_kinds_eq_h3 disconnected_nodes_eq_h3 h' + set_disconnected_nodes_get_disconnected_nodes + by (metis (no_types, lifting) \cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr \ set disc_nodes_h3\ + \ CD.a_distinct_lists h3\ \type_wf h'\ disc_nodes_h3 distinct.simps(2) + CD.distinct_lists_disconnected_nodes get_disconnected_nodes_ok returns_result_eq + returns_result_select_result) + next + fix x y xa + assume "distinct (concat (map (\document_ptr. |h3 \ get_disconnected_nodes document_ptr|\<^sub>r) + (sorted_list_of_set (fset (document_ptr_kinds h3)))))" + and "x |\| document_ptr_kinds h3" + and "y |\| document_ptr_kinds h3" + and "x \ y" + and "xa \ set |h' \ get_disconnected_nodes x|\<^sub>r" + and "xa \ set |h' \ get_disconnected_nodes y|\<^sub>r" + moreover have "set |h3 \ get_disconnected_nodes x|\<^sub>r \ set |h3 \ get_disconnected_nodes y|\<^sub>r = {}" + using calculation by(auto dest: distinct_concat_map_E(1)) + ultimately show "False" + apply(-) + apply(cases "x = document_ptr") + apply(smt NodeMonad.ptr_kinds_ptr_kinds_M + \cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr \ set |h \ node_ptr_kinds_M|\<^sub>r\ \CD.a_all_ptrs_in_heap h\ + disc_nodes_h3 disconnected_nodes_eq2_h disconnected_nodes_eq2_h2 disconnected_nodes_eq2_h3 + disjoint_iff_not_equal document_ptr_kinds_eq_h document_ptr_kinds_eq_h2 finite_set_in h' + set_disconnected_nodes_get_disconnected_nodes + CD.a_all_ptrs_in_heap_def + select_result_I2 set_ConsD subsetD) + by (smt NodeMonad.ptr_kinds_ptr_kinds_M + \cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr \ set |h \ node_ptr_kinds_M|\<^sub>r\ \CD.a_all_ptrs_in_heap h\ + disc_nodes_document_ptr_h2 disconnected_nodes_eq2_h disconnected_nodes_eq2_h2 + disconnected_nodes_eq2_h3 + disjoint_iff_not_equal document_ptr_kinds_eq_h document_ptr_kinds_eq_h2 finite_set_in h' + l_set_disconnected_nodes_get_disconnected_nodes.set_disconnected_nodes_get_disconnected_nodes + CD.a_all_ptrs_in_heap_def local.l_set_disconnected_nodes_get_disconnected_nodes_axioms + select_result_I2 set_ConsD subsetD) + next + fix x xa xb + assume 2: "(\x\fset (object_ptr_kinds h3). set |h' \ get_child_nodes x|\<^sub>r) + \ (\x\fset (document_ptr_kinds h3). set |h3 \ get_disconnected_nodes x|\<^sub>r) = {}" + and 3: "xa |\| object_ptr_kinds h3" + and 4: "x \ set |h' \ get_child_nodes xa|\<^sub>r" + and 5: "xb |\| document_ptr_kinds h3" + and 6: "x \ set |h' \ get_disconnected_nodes xb|\<^sub>r" + show "False" + using disc_nodes_document_ptr_h disconnected_nodes_eq2_h3 + apply - + apply(cases "xb = document_ptr") + apply (metis (no_types, hide_lams) "3" "4" "6" + \\p. p |\| object_ptr_kinds h3 + \ cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr \ set |h3 \ get_child_nodes p|\<^sub>r\ + \ CD.a_distinct_lists h3\ children_eq2_h3 disc_nodes_h3 CD.distinct_lists_no_parent h' + select_result_I2 set_ConsD set_disconnected_nodes_get_disconnected_nodes) + by (metis "3" "4" "5" "6" \ CD.a_distinct_lists h3\ \type_wf h3\ children_eq2_h3 + CD.distinct_lists_no_parent get_disconnected_nodes_ok returns_result_select_result) + qed + + have "CD.a_owner_document_valid h" + using \heap_is_wellformed h\ by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_owner_document_valid h'" + using disc_nodes_h3 \document_ptr |\| document_ptr_kinds h\ + apply(auto simp add: CD.a_owner_document_valid_def)[1] + apply(auto simp add: object_ptr_kinds_eq_h object_ptr_kinds_eq_h3 )[1] + apply(auto simp add: object_ptr_kinds_eq_h2)[1] + apply(auto simp add: document_ptr_kinds_eq_h document_ptr_kinds_eq_h3 )[1] + apply(auto simp add: document_ptr_kinds_eq_h2)[1] + apply(auto simp add: node_ptr_kinds_eq_h node_ptr_kinds_eq_h3 )[1] + apply(auto simp add: node_ptr_kinds_eq_h2 node_ptr_kinds_eq_h )[1] + apply(auto simp add: children_eq2_h2[symmetric] children_eq2_h3[symmetric] + disconnected_nodes_eq2_h disconnected_nodes_eq2_h2 + disconnected_nodes_eq2_h3)[1] + apply (metis (no_types, lifting) document_ptr_kinds_eq_h h' list.set_intros(1) + local.set_disconnected_nodes_get_disconnected_nodes select_result_I2) + apply(simp add: object_ptr_kinds_eq_h) + by(metis (no_types, lifting) NodeMonad.ptr_kinds_ptr_kinds_M + \cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr \ set |h \ node_ptr_kinds_M|\<^sub>r\ children_eq2_h children_eq2_h2 + children_eq2_h3 disconnected_nodes_eq2_h disconnected_nodes_eq2_h2 disconnected_nodes_eq2_h3 + document_ptr_kinds_eq_h finite_set_in h' + l_set_disconnected_nodes_get_disconnected_nodes.set_disconnected_nodes_get_disconnected_nodes + list.set_intros(2) local.l_set_disconnected_nodes_get_disconnected_nodes_axioms + node_ptr_kinds_commutes select_result_I2) + + have "CD.a_heap_is_wellformed h'" + using \CD.a_acyclic_heap h'\ \CD.a_all_ptrs_in_heap h'\ \CD.a_distinct_lists h'\ + \CD.a_owner_document_valid h'\ + by(simp add: CD.a_heap_is_wellformed_def) + + + + + + have shadow_root_ptr_kinds_eq_h: "shadow_root_ptr_kinds h2 = shadow_root_ptr_kinds h" + using object_ptr_kinds_eq_h + by(auto simp add: shadow_root_ptr_kinds_def) + have shadow_root_ptr_kinds_eq_h2: "shadow_root_ptr_kinds h3 = shadow_root_ptr_kinds h2" + using object_ptr_kinds_eq_h2 + by(auto simp add: shadow_root_ptr_kinds_def) + have shadow_root_ptr_kinds_eq_h3: "shadow_root_ptr_kinds h' = shadow_root_ptr_kinds h3" + using object_ptr_kinds_eq_h3 + by(auto simp add: shadow_root_ptr_kinds_def) + + + + have shadow_root_eq_h: "\element_ptr shadow_root_opt. element_ptr \ new_element_ptr + \ h \ get_shadow_root element_ptr \\<^sub>r shadow_root_opt = +h2 \ get_shadow_root element_ptr \\<^sub>r shadow_root_opt" + proof - + fix element_ptr shadow_root_opt + assume "element_ptr \ new_element_ptr " + have "\P \ get_shadow_root_locs element_ptr. P h h2" + using get_shadow_root_new_element new_element_ptr h2 + using \element_ptr \ new_element_ptr\ by blast + then + have "preserved (get_shadow_root element_ptr) h h2" + using get_shadow_root_new_element[rotated, OF new_element_ptr h2] + using get_shadow_root_reads + by(simp add: reads_def) + then show "h \ get_shadow_root element_ptr \\<^sub>r shadow_root_opt = +h2 \ get_shadow_root element_ptr \\<^sub>r shadow_root_opt" + by (simp add: preserved_def) + qed + have shadow_root_none: "h2 \ get_shadow_root (new_element_ptr) \\<^sub>r None" + using new_element_ptr h2 new_element_ptr_in_heap[OF h2 new_element_ptr] + new_element_is_element_ptr[OF new_element_ptr] new_element_no_shadow_root + by blast + + have shadow_root_eq_h2: + "\ptr' children. h2 \ get_shadow_root ptr' \\<^sub>r children = h3 \ get_shadow_root ptr' \\<^sub>r children" + using get_shadow_root_reads set_tag_name_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: set_tag_name_get_shadow_root) + have shadow_root_eq_h3: + "\ptr' children. h3 \ get_shadow_root ptr' \\<^sub>r children = h' \ get_shadow_root ptr' \\<^sub>r children" + using get_shadow_root_reads set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved) + using set_disconnected_nodes_get_shadow_root + by(auto simp add: set_disconnected_nodes_get_shadow_root) + + + have "a_all_ptrs_in_heap h" + by (simp add: assms(1) local.a_all_ptrs_in_heap_def local.get_shadow_root_shadow_root_ptr_in_heap) + then have "a_all_ptrs_in_heap h2" + apply(auto simp add: a_all_ptrs_in_heap_def shadow_root_ptr_kinds_eq_h)[1] + using returns_result_eq shadow_root_eq_h shadow_root_none by fastforce + then have "a_all_ptrs_in_heap h3" + apply(auto simp add: a_all_ptrs_in_heap_def shadow_root_ptr_kinds_eq_h2)[1] + using shadow_root_eq_h2 by blast + then have "a_all_ptrs_in_heap h'" + apply(auto simp add: a_all_ptrs_in_heap_def shadow_root_ptr_kinds_eq_h3)[1] + by (simp add: shadow_root_eq_h3) + + have "a_distinct_lists h" + using assms(1) + by (simp add: heap_is_wellformed_def) + then have "a_distinct_lists h2" + apply(auto simp add: a_distinct_lists_def element_ptr_kinds_eq_h)[1] + apply(auto simp add: distinct_insort intro!: distinct_concat_map_I split: option.splits)[1] + apply(case_tac "x = new_element_ptr") + using shadow_root_none apply auto[1] + using shadow_root_eq_h + by (smt Diff_empty Diff_insert0 ElementMonad.ptr_kinds_M_ptr_kinds + ElementMonad.ptr_kinds_ptr_kinds_M assms(1) assms(3) finite_set_in h2 insort_split + local.get_shadow_root_ok local.shadow_root_same_host new_element_ptr new_element_ptr_not_in_heap + option.distinct(1) returns_result_select_result select_result_I2 shadow_root_none) + then have "a_distinct_lists h3" + by(auto simp add: a_distinct_lists_def element_ptr_kinds_eq_h2 select_result_eq[OF shadow_root_eq_h2]) + then have "a_distinct_lists h'" + by(auto simp add: a_distinct_lists_def element_ptr_kinds_eq_h3 select_result_eq[OF shadow_root_eq_h3]) + + + have "a_shadow_root_valid h" + using assms(1) + by (simp add: heap_is_wellformed_def) + then have "a_shadow_root_valid h2" + proof (unfold a_shadow_root_valid_def; safe) + fix shadow_root_ptr + assume "\shadow_root_ptr\fset (shadow_root_ptr_kinds h). \host\fset (element_ptr_kinds h). +|h \ get_tag_name host|\<^sub>r \ safe_shadow_root_element_types \ |h \ get_shadow_root host|\<^sub>r = Some shadow_root_ptr" + assume "shadow_root_ptr \ fset (shadow_root_ptr_kinds h2)" + + obtain previous_host where + "previous_host \ fset (element_ptr_kinds h)" and + "|h \ get_tag_name previous_host|\<^sub>r \ safe_shadow_root_element_types" and + "|h \ get_shadow_root previous_host|\<^sub>r = Some shadow_root_ptr" + by (metis \local.a_shadow_root_valid h\ \shadow_root_ptr \ fset (shadow_root_ptr_kinds h2)\ + local.a_shadow_root_valid_def shadow_root_ptr_kinds_eq_h) + moreover have "previous_host \ new_element_ptr" + using calculation(1) h2 new_element_ptr new_element_ptr_not_in_heap by auto + ultimately have "|h2 \ get_tag_name previous_host|\<^sub>r \ safe_shadow_root_element_types" and + "|h2 \ get_shadow_root previous_host|\<^sub>r = Some shadow_root_ptr" + using shadow_root_eq_h + apply (simp add: tag_name_eq2_h) + by (metis \previous_host \ new_element_ptr\ + \|h \ get_shadow_root previous_host|\<^sub>r = Some shadow_root_ptr\ + select_result_eq shadow_root_eq_h) + then + show "\host\fset (element_ptr_kinds h2). +|h2 \ get_tag_name host|\<^sub>r \ safe_shadow_root_element_types \ +|h2 \ get_shadow_root host|\<^sub>r = Some shadow_root_ptr" + by (meson \previous_host \ fset (element_ptr_kinds h)\ \previous_host \ new_element_ptr\ + assms(3) local.get_shadow_root_ok local.get_shadow_root_ptr_in_heap notin_fset + returns_result_select_result shadow_root_eq_h) + qed + then have "a_shadow_root_valid h3" + proof (unfold a_shadow_root_valid_def; safe) + fix shadow_root_ptr + assume "\shadow_root_ptr\fset (shadow_root_ptr_kinds h2). \host\fset (element_ptr_kinds h2). +|h2 \ get_tag_name host|\<^sub>r \ safe_shadow_root_element_types \ +|h2 \ get_shadow_root host|\<^sub>r = Some shadow_root_ptr" + assume "shadow_root_ptr \ fset (shadow_root_ptr_kinds h3)" + + obtain previous_host where + "previous_host \ fset (element_ptr_kinds h2)" and + "|h2 \ get_tag_name previous_host|\<^sub>r \ safe_shadow_root_element_types" and + "|h2 \ get_shadow_root previous_host|\<^sub>r = Some shadow_root_ptr" + by (metis \local.a_shadow_root_valid h2\ \shadow_root_ptr \ fset (shadow_root_ptr_kinds h3)\ + local.a_shadow_root_valid_def shadow_root_ptr_kinds_eq_h2) + moreover have "previous_host \ new_element_ptr" + using calculation(1) h3 new_element_ptr new_element_ptr_not_in_heap + using calculation(3) shadow_root_none by auto + ultimately have "|h2 \ get_tag_name previous_host|\<^sub>r \ safe_shadow_root_element_types" and + "|h2 \ get_shadow_root previous_host|\<^sub>r = Some shadow_root_ptr" + using shadow_root_eq_h2 + apply (simp add: tag_name_eq2_h2) + by (metis \previous_host \ new_element_ptr\ + \|h2 \ get_shadow_root previous_host|\<^sub>r = Some shadow_root_ptr\ select_result_eq + shadow_root_eq_h) + then + show "\host\fset (element_ptr_kinds h3). +|h3 \ get_tag_name host|\<^sub>r \ safe_shadow_root_element_types \ +|h3 \ get_shadow_root host|\<^sub>r = Some shadow_root_ptr" + by (smt \previous_host \ fset (element_ptr_kinds h2)\ \previous_host \ new_element_ptr\ + \type_wf h2\ \type_wf h3\ element_ptr_kinds_eq_h2 finite_set_in local.get_shadow_root_ok + returns_result_eq returns_result_select_result shadow_root_eq_h2 tag_name_eq2_h2) + qed + then have "a_shadow_root_valid h'" + apply(auto simp add: a_shadow_root_valid_def element_ptr_kinds_eq_h3 shadow_root_eq_h3 + shadow_root_ptr_kinds_eq_h3 tag_name_eq2_h3)[1] + by (smt \type_wf h3\ finite_set_in local.get_shadow_root_ok returns_result_select_result + select_result_I2 shadow_root_eq_h3) + + + + have "a_host_shadow_root_rel h = a_host_shadow_root_rel h2" + apply(auto simp add: a_host_shadow_root_rel_def element_ptr_kinds_eq_h shadow_root_eq_h)[1] + apply (smt assms(3) case_prod_conv h2 image_iff local.get_shadow_root_ok mem_Collect_eq + new_element_ptr new_element_ptr_not_in_heap returns_result_select_result select_result_I2 + shadow_root_eq_h) + using shadow_root_none apply auto[1] + by (metis (no_types, lifting) Collect_cong assms(3) case_prodE case_prodI h2 + host_shadow_root_rel_def host_shadow_root_rel_shadow_root local.a_host_shadow_root_rel_def + local.get_shadow_root_impl local.get_shadow_root_ok local.new_element_no_shadow_root + new_element_ptr option.distinct(1) returns_result_select_result select_result_I2 shadow_root_eq_h) + have "a_host_shadow_root_rel h2 = a_host_shadow_root_rel h3" + apply(auto simp add: a_host_shadow_root_rel_def element_ptr_kinds_eq_h2 shadow_root_eq_h2)[1] + apply (smt Collect_cong Shadow_DOM.a_host_shadow_root_rel_def assms(3) h2 + host_shadow_root_rel_shadow_root is_OK_returns_result_E local.get_shadow_root_impl + local.get_shadow_root_ok local.new_element_types_preserved select_result_I2 shadow_root_eq_h2 + split_cong) + apply (metis (no_types, lifting) Collect_cong \type_wf h3\ element_ptr_kinds_eq_h2 + host_shadow_root_rel_def host_shadow_root_rel_shadow_root local.a_host_shadow_root_rel_def + local.get_shadow_root_impl local.get_shadow_root_ok returns_result_select_result shadow_root_eq_h2 + split_cong) + done + have "a_host_shadow_root_rel h3 = a_host_shadow_root_rel h'" + apply(auto simp add: a_host_shadow_root_rel_def element_ptr_kinds_eq_h2 shadow_root_eq_h2)[1] + apply (metis (no_types, lifting) Collect_cong \type_wf h3\ case_prodE case_prodI + element_ptr_kinds_eq_h2 host_shadow_root_rel_def host_shadow_root_rel_shadow_root + local.a_host_shadow_root_rel_def local.get_shadow_root_impl local.get_shadow_root_ok + returns_result_select_result shadow_root_eq_h3) + apply (smt Collect_cong \type_wf h'\ \type_wf h2\ case_prodD case_prodI2 host_shadow_root_rel_def + host_shadow_root_rel_shadow_root is_OK_returns_result_E local.a_host_shadow_root_rel_def + local.get_shadow_root_impl local.get_shadow_root_ok select_result_I2 shadow_root_eq_h2 shadow_root_eq_h3) + done + + have "acyclic (parent_child_rel h \ a_host_shadow_root_rel h)" + using \heap_is_wellformed h\ + by (simp add: heap_is_wellformed_def) + have "parent_child_rel h \ a_host_shadow_root_rel h = +parent_child_rel h2 \ a_host_shadow_root_rel h2" + using \local.a_host_shadow_root_rel h = local.a_host_shadow_root_rel h2\ + \parent_child_rel h = parent_child_rel h2\ by auto + have "parent_child_rel h2 \ a_host_shadow_root_rel h2 = +parent_child_rel h3 \ a_host_shadow_root_rel h3" + using \local.a_host_shadow_root_rel h2 = local.a_host_shadow_root_rel h3\ + \parent_child_rel h2 = parent_child_rel h3\ by auto + have "parent_child_rel h' \ a_host_shadow_root_rel h' = +parent_child_rel h3 \ a_host_shadow_root_rel h3" + by (simp add: \local.a_host_shadow_root_rel h3 = local.a_host_shadow_root_rel h'\ + \parent_child_rel h3 = parent_child_rel h'\) + + have "acyclic (parent_child_rel h3 \ a_host_shadow_root_rel h3)" + using \acyclic (parent_child_rel h \ local.a_host_shadow_root_rel h)\ + \parent_child_rel h \ local.a_host_shadow_root_rel h = +parent_child_rel h2 \ local.a_host_shadow_root_rel h2\ + \parent_child_rel h2 \ local.a_host_shadow_root_rel h2 = +parent_child_rel h3 \ local.a_host_shadow_root_rel h3\ + by auto + then have "acyclic (parent_child_rel h' \ a_host_shadow_root_rel h')" + by(simp add: \parent_child_rel h' \ a_host_shadow_root_rel h' = +parent_child_rel h3 \ a_host_shadow_root_rel h3\) + + + show " heap_is_wellformed h' " + using \acyclic (parent_child_rel h' \ local.a_host_shadow_root_rel h')\ + by(simp add: heap_is_wellformed_def CD.heap_is_wellformed_impl + \local.CD.a_heap_is_wellformed h'\ \local.a_all_ptrs_in_heap h'\ \local.a_distinct_lists h'\ + \local.a_shadow_root_valid h'\) +qed +end + +interpretation i_create_element_wf?: l_create_element_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr known_ptrs type_wf + get_child_nodes get_child_nodes_locs get_disconnected_nodes get_disconnected_nodes_locs + heap_is_wellformed parent_child_rel set_tag_name set_tag_name_locs set_disconnected_nodes + set_disconnected_nodes_locs create_element get_shadow_root get_shadow_root_locs get_tag_name + get_tag_name_locs heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host get_host_locs get_disconnected_document + get_disconnected_document_locs DocumentClass.known_ptr DocumentClass.type_wf + by(auto simp add: l_create_element_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_create_element_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsubsection \create\_character\_data\ + +locale l_create_character_data_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_disconnected_nodes type_wf get_disconnected_nodes get_disconnected_nodes_locs + + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes get_child_nodes_locs get_disconnected_nodes + get_disconnected_nodes_locs + get_shadow_root get_shadow_root_locs get_tag_name get_tag_name_locs known_ptr type_wf + heap_is_wellformed parent_child_rel + heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host get_host_locs get_disconnected_document + get_disconnected_document_locs + + l_create_character_data\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_nodes get_disconnected_nodes_locs + set_disconnected_nodes set_disconnected_nodes_locs set_val set_val_locs create_character_data + known_ptr type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_new_character_data_get_disconnected_nodes + get_disconnected_nodes get_disconnected_nodes_locs + ++ l_set_val_get_disconnected_nodes +type_wf set_val set_val_locs get_disconnected_nodes get_disconnected_nodes_locs ++ l_new_character_data_get_child_nodes +type_wf known_ptr get_child_nodes get_child_nodes_locs ++ l_set_val_get_child_nodes +type_wf set_val set_val_locs known_ptr get_child_nodes get_child_nodes_locs ++ l_set_disconnected_nodes_get_child_nodes +set_disconnected_nodes set_disconnected_nodes_locs get_child_nodes get_child_nodes_locs ++ l_set_disconnected_nodes +type_wf set_disconnected_nodes set_disconnected_nodes_locs ++ l_set_disconnected_nodes_get_disconnected_nodes +type_wf get_disconnected_nodes get_disconnected_nodes_locs set_disconnected_nodes +set_disconnected_nodes_locs ++ l_set_val_get_shadow_root type_wf set_val set_val_locs get_shadow_root get_shadow_root_locs ++ l_set_disconnected_nodes_get_shadow_root set_disconnected_nodes set_disconnected_nodes_locs +get_shadow_root get_shadow_root_locs ++ l_new_character_data_get_tag_name +get_tag_name get_tag_name_locs ++ l_set_val_get_tag_name type_wf set_val set_val_locs get_tag_name get_tag_name_locs ++ l_get_tag_name type_wf get_tag_name get_tag_name_locs ++ l_set_disconnected_nodes_get_tag_name type_wf set_disconnected_nodes set_disconnected_nodes_locs +get_tag_name get_tag_name_locs ++ l_new_character_data +type_wf ++ l_known_ptrs +known_ptr known_ptrs +for known_ptr :: "(_::linorder) object_ptr \ bool" + and known_ptrs :: "(_) heap \ bool" + and type_wf :: "(_) heap \ bool" + and get_child_nodes :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_disconnected_nodes :: "(_) document_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" + and heap_is_wellformed :: "(_) heap \ bool" + and parent_child_rel :: "(_) heap \ ((_) object_ptr \ (_) object_ptr) set" + and set_tag_name :: "(_) element_ptr \ char list \ ((_) heap, exception, unit) prog" + and set_tag_name_locs :: "(_) element_ptr \ ((_) heap, exception, unit) prog set" + and set_disconnected_nodes :: "(_) document_ptr \ (_) node_ptr list \ ((_) heap, exception, unit) prog" + and set_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap, exception, unit) prog set" + and create_element :: "(_) document_ptr \ char list \ ((_) heap, exception, (_) element_ptr) prog" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_tag_name :: "(_) element_ptr \ ((_) heap, exception, char list) prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and get_host :: "(_) shadow_root_ptr \ ((_) heap, exception, (_) element_ptr) prog" + and get_host_locs :: "((_) heap \ (_) heap \ bool) set" + and get_disconnected_document :: "(_) node_ptr \ ((_) heap, exception, (_) document_ptr) prog" + and get_disconnected_document_locs :: "((_) heap \ (_) heap \ bool) set" + and set_val :: "(_) character_data_ptr \ char list \ ((_) heap, exception, unit) prog" + and set_val_locs :: "(_) character_data_ptr \ ((_) heap, exception, unit) prog set" + and create_character_data :: + "(_) document_ptr \ char list \ ((_) heap, exception, (_) character_data_ptr) prog" + and known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_::linorder) object_ptr \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" +begin +lemma create_character_data_preserves_wellformedness: + assumes "heap_is_wellformed h" + and "h \ create_character_data document_ptr text \\<^sub>h h'" + and "type_wf h" + and "known_ptrs h" + shows "heap_is_wellformed h'" and "type_wf h'" and "known_ptrs h'" +proof - + obtain new_character_data_ptr h2 h3 disc_nodes_h3 where + new_character_data_ptr: "h \ new_character_data \\<^sub>r new_character_data_ptr" and + h2: "h \ new_character_data \\<^sub>h h2" and + h3: "h2 \ set_val new_character_data_ptr text \\<^sub>h h3" and + disc_nodes_h3: "h3 \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes_h3" and + h': "h3 \ set_disconnected_nodes document_ptr (cast new_character_data_ptr # disc_nodes_h3) \\<^sub>h h'" + using assms(2) + by(auto simp add: CD.create_character_data_def + elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF CD.get_disconnected_nodes_pure, rotated] ) + then have "h \ create_character_data document_ptr text \\<^sub>r new_character_data_ptr" + apply(auto simp add: CD.create_character_data_def intro!: bind_returns_result_I)[1] + apply (metis is_OK_returns_heap_I is_OK_returns_result_E old.unit.exhaust) + apply (metis is_OK_returns_heap_E is_OK_returns_result_I local.CD.get_disconnected_nodes_pure + pure_returns_heap_eq) + by (metis is_OK_returns_heap_I is_OK_returns_result_E old.unit.exhaust) + + + have "new_character_data_ptr \ set |h \ character_data_ptr_kinds_M|\<^sub>r" + using new_character_data_ptr CharacterDataMonad.ptr_kinds_ptr_kinds_M h2 + using new_character_data_ptr_not_in_heap by blast + then have "cast new_character_data_ptr \ set |h \ node_ptr_kinds_M|\<^sub>r" + by simp + then have "cast new_character_data_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r" + by simp + + + + have object_ptr_kinds_eq_h: + "object_ptr_kinds h2 = object_ptr_kinds h |\| {|cast new_character_data_ptr|}" + using new_character_data_new_ptr h2 new_character_data_ptr by blast + then have node_ptr_kinds_eq_h: + "node_ptr_kinds h2 = node_ptr_kinds h |\| {|cast new_character_data_ptr|}" + apply(simp add: node_ptr_kinds_def) + by force + then have character_data_ptr_kinds_eq_h: + "character_data_ptr_kinds h2 = character_data_ptr_kinds h |\| {|new_character_data_ptr|}" + apply(simp add: character_data_ptr_kinds_def) + by force + have element_ptr_kinds_eq_h: "element_ptr_kinds h2 = element_ptr_kinds h" + using object_ptr_kinds_eq_h + by(auto simp add: node_ptr_kinds_def element_ptr_kinds_def) + have document_ptr_kinds_eq_h: "document_ptr_kinds h2 = document_ptr_kinds h" + using object_ptr_kinds_eq_h + by(auto simp add: document_ptr_kinds_def) + + have object_ptr_kinds_eq_h2: "object_ptr_kinds h3 = object_ptr_kinds h2" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h' = object_ptr_kinds h", + OF CD.set_val_writes h3]) + using CD.set_val_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have document_ptr_kinds_eq_h2: "document_ptr_kinds h3 = document_ptr_kinds h2" + by (auto simp add: document_ptr_kinds_def) + have node_ptr_kinds_eq_h2: "node_ptr_kinds h3 = node_ptr_kinds h2" + using object_ptr_kinds_eq_h2 + by(auto simp add: node_ptr_kinds_def) + + have object_ptr_kinds_eq_h3: "object_ptr_kinds h' = object_ptr_kinds h3" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h' = object_ptr_kinds h", + OF set_disconnected_nodes_writes h']) + using set_disconnected_nodes_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have document_ptr_kinds_eq_h3: "document_ptr_kinds h' = document_ptr_kinds h3" + by (auto simp add: document_ptr_kinds_def) + have node_ptr_kinds_eq_h3: "node_ptr_kinds h' = node_ptr_kinds h3" + using object_ptr_kinds_eq_h3 + by(auto simp add: node_ptr_kinds_def) + + have "known_ptr (cast new_character_data_ptr)" + using \h \ create_character_data document_ptr text \\<^sub>r new_character_data_ptr\ + local.create_character_data_known_ptr by blast + then + have "known_ptrs h2" + using known_ptrs_new_ptr object_ptr_kinds_eq_h \known_ptrs h\ h2 + by blast + then + have "known_ptrs h3" + using known_ptrs_preserved object_ptr_kinds_eq_h2 by blast + then + show "known_ptrs h'" + using known_ptrs_preserved object_ptr_kinds_eq_h3 by blast + + have "document_ptr |\| document_ptr_kinds h" + using disc_nodes_h3 document_ptr_kinds_eq_h object_ptr_kinds_eq_h2 + CD.get_disconnected_nodes_ptr_in_heap \type_wf h\ document_ptr_kinds_def + by (metis is_OK_returns_result_I) + + have children_eq_h: "\(ptr'::(_) object_ptr) children. ptr' \ cast new_character_data_ptr + \ h \ get_child_nodes ptr' \\<^sub>r children = h2 \ get_child_nodes ptr' \\<^sub>r children" + using CD.get_child_nodes_reads h2 + get_child_nodes_new_character_data[rotated, OF new_character_data_ptr h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have children_eq2_h: + "\ptr'. ptr' \ cast new_character_data_ptr + \ |h \ get_child_nodes ptr'|\<^sub>r = |h2 \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + have object_ptr_kinds_eq_h: + "object_ptr_kinds h2 = object_ptr_kinds h |\| {|cast new_character_data_ptr|}" + using new_character_data_new_ptr h2 new_character_data_ptr by blast + then have node_ptr_kinds_eq_h: + "node_ptr_kinds h2 = node_ptr_kinds h |\| {|cast new_character_data_ptr|}" + apply(simp add: node_ptr_kinds_def) + by force + then have character_data_ptr_kinds_eq_h: + "character_data_ptr_kinds h2 = character_data_ptr_kinds h |\| {|new_character_data_ptr|}" + apply(simp add: character_data_ptr_kinds_def) + by force + have element_ptr_kinds_eq_h: "element_ptr_kinds h2 = element_ptr_kinds h" + using object_ptr_kinds_eq_h + by(auto simp add: node_ptr_kinds_def element_ptr_kinds_def) + have document_ptr_kinds_eq_h: "document_ptr_kinds h2 = document_ptr_kinds h" + using object_ptr_kinds_eq_h + by(auto simp add: document_ptr_kinds_def) + + have object_ptr_kinds_eq_h2: "object_ptr_kinds h3 = object_ptr_kinds h2" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h' = object_ptr_kinds h", + OF CD.set_val_writes h3]) + using CD.set_val_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have document_ptr_kinds_eq_h2: "document_ptr_kinds h3 = document_ptr_kinds h2" + by (auto simp add: document_ptr_kinds_def) + have node_ptr_kinds_eq_h2: "node_ptr_kinds h3 = node_ptr_kinds h2" + using object_ptr_kinds_eq_h2 + by(auto simp add: node_ptr_kinds_def) + then have character_data_ptr_kinds_eq_h2: "character_data_ptr_kinds h3 = character_data_ptr_kinds h2" + by(simp add: character_data_ptr_kinds_def) + have element_ptr_kinds_eq_h2: "element_ptr_kinds h3 = element_ptr_kinds h2" + using node_ptr_kinds_eq_h2 + by(simp add: element_ptr_kinds_def) + + have object_ptr_kinds_eq_h3: "object_ptr_kinds h' = object_ptr_kinds h3" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h' = object_ptr_kinds h", + OF set_disconnected_nodes_writes h']) + using set_disconnected_nodes_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have document_ptr_kinds_eq_h3: "document_ptr_kinds h' = document_ptr_kinds h3" + by (auto simp add: document_ptr_kinds_def) + have node_ptr_kinds_eq_h3: "node_ptr_kinds h' = node_ptr_kinds h3" + using object_ptr_kinds_eq_h3 + by(auto simp add: node_ptr_kinds_def) + then have character_data_ptr_kinds_eq_h3: "character_data_ptr_kinds h' = character_data_ptr_kinds h3" + by(simp add: character_data_ptr_kinds_def) + have element_ptr_kinds_eq_h3: "element_ptr_kinds h' = element_ptr_kinds h3" + using node_ptr_kinds_eq_h3 + by(simp add: element_ptr_kinds_def) + + + have "document_ptr |\| document_ptr_kinds h" + using disc_nodes_h3 document_ptr_kinds_eq_h object_ptr_kinds_eq_h2 + CD.get_disconnected_nodes_ptr_in_heap \type_wf h\ document_ptr_kinds_def + by (metis is_OK_returns_result_I) + + have children_eq_h: "\(ptr'::(_) object_ptr) children. ptr' \ cast new_character_data_ptr + \ h \ get_child_nodes ptr' \\<^sub>r children = h2 \ get_child_nodes ptr' \\<^sub>r children" + using CD.get_child_nodes_reads h2 + get_child_nodes_new_character_data[rotated, OF new_character_data_ptr h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have children_eq2_h: "\ptr'. ptr' \ cast new_character_data_ptr + \ |h \ get_child_nodes ptr'|\<^sub>r = |h2 \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + + have "h2 \ get_child_nodes (cast new_character_data_ptr) \\<^sub>r []" + using new_character_data_ptr h2 new_character_data_ptr_in_heap[OF h2 new_character_data_ptr] + new_character_data_is_character_data_ptr[OF new_character_data_ptr] + new_character_data_no_child_nodes + by blast + have disconnected_nodes_eq_h: + "\doc_ptr disc_nodes. h \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes + = h2 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using CD.get_disconnected_nodes_reads h2 + get_disconnected_nodes_new_character_data[OF new_character_data_ptr h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have disconnected_nodes_eq2_h: + "\doc_ptr. |h \ get_disconnected_nodes doc_ptr|\<^sub>r = |h2 \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + have tag_name_eq_h: + "\ptr' disc_nodes. h \ get_tag_name ptr' \\<^sub>r disc_nodes + = h2 \ get_tag_name ptr' \\<^sub>r disc_nodes" + using get_tag_name_reads h2 + get_tag_name_new_character_data[OF new_character_data_ptr h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have tag_name_eq2_h: "\ptr'. |h \ get_tag_name ptr'|\<^sub>r = |h2 \ get_tag_name ptr'|\<^sub>r" + using select_result_eq by force + + have children_eq_h2: + "\ptr' children. h2 \ get_child_nodes ptr' \\<^sub>r children = h3 \ get_child_nodes ptr' \\<^sub>r children" + using CD.get_child_nodes_reads CD.set_val_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: set_val_get_child_nodes) + then have children_eq2_h2: + "\ptr'. |h2 \ get_child_nodes ptr'|\<^sub>r = |h3 \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + have disconnected_nodes_eq_h2: + "\doc_ptr disc_nodes. h2 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes + = h3 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using CD.get_disconnected_nodes_reads CD.set_val_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: set_val_get_disconnected_nodes) + then have disconnected_nodes_eq2_h2: + "\doc_ptr. |h2 \ get_disconnected_nodes doc_ptr|\<^sub>r = |h3 \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + have tag_name_eq_h2: + "\ptr' disc_nodes. h2 \ get_tag_name ptr' \\<^sub>r disc_nodes + = h3 \ get_tag_name ptr' \\<^sub>r disc_nodes" + using get_tag_name_reads CD.set_val_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: set_val_get_tag_name) + then have tag_name_eq2_h2: "\ptr'. |h2 \ get_tag_name ptr'|\<^sub>r = |h3 \ get_tag_name ptr'|\<^sub>r" + using select_result_eq by force + + have "type_wf h2" + using \type_wf h\ new_character_data_types_preserved h2 by blast + then have "type_wf h3" + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", OF CD.set_val_writes h3] + using set_val_types_preserved + by(auto simp add: reflp_def transp_def) + then show "type_wf h'" + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", OF set_disconnected_nodes_writes h'] + using set_disconnected_nodes_types_preserved + by(auto simp add: reflp_def transp_def) + + have children_eq_h3: + "\ptr' children. h3 \ get_child_nodes ptr' \\<^sub>r children = h' \ get_child_nodes ptr' \\<^sub>r children" + using CD.get_child_nodes_reads set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: set_disconnected_nodes_get_child_nodes) + then have children_eq2_h3: + " \ptr'. |h3 \ get_child_nodes ptr'|\<^sub>r = |h' \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + have disconnected_nodes_eq_h3: "\doc_ptr disc_nodes. document_ptr \ doc_ptr + \ h3 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes + = h' \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using CD.get_disconnected_nodes_reads set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: set_disconnected_nodes_get_disconnected_nodes_different_pointers) + then have disconnected_nodes_eq2_h3: "\doc_ptr. document_ptr \ doc_ptr + \ |h3 \ get_disconnected_nodes doc_ptr|\<^sub>r = |h' \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + have tag_name_eq_h3: + "\ptr' disc_nodes. h3 \ get_tag_name ptr' \\<^sub>r disc_nodes + = h' \ get_tag_name ptr' \\<^sub>r disc_nodes" + using get_tag_name_reads set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: set_disconnected_nodes_get_tag_name) + then have tag_name_eq2_h3: "\ptr'. |h3 \ get_tag_name ptr'|\<^sub>r = |h' \ get_tag_name ptr'|\<^sub>r" + using select_result_eq by force + + have disc_nodes_document_ptr_h2: "h2 \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes_h3" + using disconnected_nodes_eq_h2 disc_nodes_h3 by auto + then have disc_nodes_document_ptr_h: "h \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes_h3" + using disconnected_nodes_eq_h by auto + then have "cast new_character_data_ptr \ set disc_nodes_h3" + using \heap_is_wellformed h\ using \cast new_character_data_ptr \ set |h \ node_ptr_kinds_M|\<^sub>r\ + a_all_ptrs_in_heap_def heap_is_wellformed_def + using NodeMonad.ptr_kinds_ptr_kinds_M local.heap_is_wellformed_disc_nodes_in_heap by blast + + have "acyclic (parent_child_rel h)" + using \heap_is_wellformed h\ + by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def CD.acyclic_heap_def) + also have "parent_child_rel h = parent_child_rel h2" + proof(auto simp add: CD.parent_child_rel_def)[1] + fix a x + assume 0: "a |\| object_ptr_kinds h" + and 1: "x \ set |h \ get_child_nodes a|\<^sub>r" + then show "a |\| object_ptr_kinds h2" + by (simp add: object_ptr_kinds_eq_h) + next + fix a x + assume 0: "a |\| object_ptr_kinds h" + and 1: "x \ set |h \ get_child_nodes a|\<^sub>r" + then show "x \ set |h2 \ get_child_nodes a|\<^sub>r" + by (metis ObjectMonad.ptr_kinds_ptr_kinds_M + \cast new_character_data_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r\ children_eq2_h) + next + fix a x + assume 0: "a |\| object_ptr_kinds h2" + and 1: "x \ set |h2 \ get_child_nodes a|\<^sub>r" + then show "a |\| object_ptr_kinds h" + using object_ptr_kinds_eq_h \h2 \ get_child_nodes (cast new_character_data_ptr) \\<^sub>r []\ + by(auto) + next + fix a x + assume 0: "a |\| object_ptr_kinds h2" + and 1: "x \ set |h2 \ get_child_nodes a|\<^sub>r" + then show "x \ set |h \ get_child_nodes a|\<^sub>r" + by (metis (no_types, lifting) \h2 \ get_child_nodes (cast new_character_data_ptr) \\<^sub>r []\ + children_eq2_h empty_iff empty_set image_eqI select_result_I2) + qed + also have "\ = parent_child_rel h3" + by(auto simp add: CD.parent_child_rel_def object_ptr_kinds_eq_h2 children_eq2_h2) + also have "\ = parent_child_rel h'" + by(auto simp add: CD.parent_child_rel_def object_ptr_kinds_eq_h3 children_eq2_h3) + finally have "CD.a_acyclic_heap h'" + by (simp add: CD.acyclic_heap_def) + + have "CD.a_all_ptrs_in_heap h" + using \heap_is_wellformed h\ by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_all_ptrs_in_heap h2" + apply(auto simp add: CD.a_all_ptrs_in_heap_def)[1] + using node_ptr_kinds_eq_h \cast new_character_data_ptr \ set |h \ node_ptr_kinds_M|\<^sub>r\ + \h2 \ get_child_nodes (cast new_character_data_ptr) \\<^sub>r []\ + apply (metis (no_types, lifting) NodeMonad.ptr_kinds_ptr_kinds_M + \parent_child_rel h = parent_child_rel h2\ + children_eq2_h finite_set_in finsert_iff funion_finsert_right CD.parent_child_rel_child + CD.parent_child_rel_parent_in_heap node_ptr_kinds_commutes object_ptr_kinds_eq_h + select_result_I2 subsetD sup_bot.right_neutral) + by (metis (no_types, lifting) CD.get_child_nodes_ok CD.get_child_nodes_ptr_in_heap + \h2 \ get_child_nodes (cast\<^sub>c\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>_\<^sub>d\<^sub>a\<^sub>t\<^sub>a\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_character_data_ptr) \\<^sub>r []\ assms(3) assms(4) + children_eq_h disconnected_nodes_eq2_h document_ptr_kinds_eq_h finite_set_in + is_OK_returns_result_I local.known_ptrs_known_ptr node_ptr_kinds_commutes + returns_result_select_result subset_code(1)) + then have "CD.a_all_ptrs_in_heap h3" + by (simp add: children_eq2_h2 disconnected_nodes_eq2_h2 document_ptr_kinds_eq_h2 + CD.a_all_ptrs_in_heap_def node_ptr_kinds_eq_h2 object_ptr_kinds_eq_h2) + then have "CD.a_all_ptrs_in_heap h'" + by (smt character_data_ptr_kinds_commutes character_data_ptr_kinds_eq_h2 children_eq2_h3 + disc_nodes_h3 disconnected_nodes_eq2_h3 document_ptr_kinds_eq_h3 h' h2 + local.CD.a_all_ptrs_in_heap_def local.set_disconnected_nodes_get_disconnected_nodes + new_character_data_ptr new_character_data_ptr_in_heap node_ptr_kinds_eq_h3 notin_fset + object_ptr_kinds_eq_h3 select_result_I2 set_ConsD subset_code(1)) + + have "\p. p |\| object_ptr_kinds h \ cast new_character_data_ptr \ set |h \ get_child_nodes p|\<^sub>r" + using \heap_is_wellformed h\ \cast new_character_data_ptr \ set |h \ node_ptr_kinds_M|\<^sub>r\ + heap_is_wellformed_children_in_heap + by (meson NodeMonad.ptr_kinds_ptr_kinds_M CD.a_all_ptrs_in_heap_def assms(3) assms(4) fset_mp + fset_of_list_elem CD.get_child_nodes_ok known_ptrs_known_ptr returns_result_select_result) + then have "\p. p |\| object_ptr_kinds h2 \ +cast new_character_data_ptr \ set |h2 \ get_child_nodes p|\<^sub>r" + using children_eq2_h + apply(auto simp add: object_ptr_kinds_eq_h)[1] + using \h2 \ get_child_nodes (cast new_character_data_ptr) \\<^sub>r []\ apply auto[1] + by (metis ObjectMonad.ptr_kinds_ptr_kinds_M + \cast new_character_data_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r\) + then have "\p. p |\| object_ptr_kinds h3 \ +cast new_character_data_ptr \ set |h3 \ get_child_nodes p|\<^sub>r" + using object_ptr_kinds_eq_h2 children_eq2_h2 by auto + then have new_character_data_ptr_not_in_any_children: + "\p. p |\| object_ptr_kinds h' \ cast new_character_data_ptr \ set |h' \ get_child_nodes p|\<^sub>r" + using object_ptr_kinds_eq_h3 children_eq2_h3 by auto + + have "CD.a_distinct_lists h" + using \heap_is_wellformed h\ + by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_distinct_lists h2" + using \h2 \ get_child_nodes (cast new_character_data_ptr) \\<^sub>r []\ + apply(auto simp add: CD.a_distinct_lists_def object_ptr_kinds_eq_h document_ptr_kinds_eq_h + disconnected_nodes_eq2_h intro!: distinct_concat_map_I)[1] + apply (metis distinct_sorted_list_of_set finite_fset sorted_list_of_set_insert) + apply(case_tac "x=cast new_character_data_ptr") + apply(auto simp add: children_eq2_h[symmetric] insort_split dest: distinct_concat_map_E(2))[1] + apply(auto simp add: children_eq2_h[symmetric] insort_split dest: distinct_concat_map_E(2))[1] + apply(auto simp add: children_eq2_h[symmetric] insort_split dest: distinct_concat_map_E(2))[1] + apply (metis IntI assms(1) assms(3) assms(4) empty_iff CD.get_child_nodes_ok + local.heap_is_wellformed_one_parent local.known_ptrs_known_ptr + returns_result_select_result) + apply(auto simp add: children_eq2_h[symmetric] insort_split dest: distinct_concat_map_E(2))[1] + thm children_eq2_h + + using \CD.a_distinct_lists h\ \type_wf h2\ disconnected_nodes_eq_h document_ptr_kinds_eq_h + CD.distinct_lists_no_parent get_disconnected_nodes_ok returns_result_select_result + by metis + then have "CD.a_distinct_lists h3" + by(auto simp add: CD.a_distinct_lists_def disconnected_nodes_eq2_h2 document_ptr_kinds_eq_h2 + children_eq2_h2 object_ptr_kinds_eq_h2)[1] + then have "CD.a_distinct_lists h'" + proof(auto simp add: CD.a_distinct_lists_def disconnected_nodes_eq2_h3 children_eq2_h3 + object_ptr_kinds_eq_h3 document_ptr_kinds_eq_h3 intro!: distinct_concat_map_I)[1] + fix x + assume "distinct (concat (map (\document_ptr. |h3 \ get_disconnected_nodes document_ptr|\<^sub>r) + (sorted_list_of_set (fset (document_ptr_kinds h3)))))" + and "x |\| document_ptr_kinds h3" + then show "distinct |h' \ get_disconnected_nodes x|\<^sub>r" + using document_ptr_kinds_eq_h3 disconnected_nodes_eq_h3 h' + set_disconnected_nodes_get_disconnected_nodes + by (metis (no_types, hide_lams) + \cast\<^sub>c\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>_\<^sub>d\<^sub>a\<^sub>t\<^sub>a\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_character_data_ptr \ set disc_nodes_h3\ \type_wf h2\ assms(1) + disc_nodes_document_ptr_h disconnected_nodes_eq2_h2 disconnected_nodes_eq2_h3 + disconnected_nodes_eq_h distinct.simps(2) document_ptr_kinds_eq_h2 local.get_disconnected_nodes_ok + local.heap_is_wellformed_disconnected_nodes_distinct returns_result_select_result select_result_I2) + next + fix x y xa + assume "distinct (concat (map (\document_ptr. |h3 \ get_disconnected_nodes document_ptr|\<^sub>r) + (sorted_list_of_set (fset (document_ptr_kinds h3)))))" + and "x |\| document_ptr_kinds h3" + and "y |\| document_ptr_kinds h3" + and "x \ y" + and "xa \ set |h' \ get_disconnected_nodes x|\<^sub>r" + and "xa \ set |h' \ get_disconnected_nodes y|\<^sub>r" + moreover have "set |h3 \ get_disconnected_nodes x|\<^sub>r \ set |h3 \ get_disconnected_nodes y|\<^sub>r = {}" + using calculation by(auto dest: distinct_concat_map_E(1)) + ultimately show "False" + using NodeMonad.ptr_kinds_ptr_kinds_M + \cast\<^sub>c\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>_\<^sub>d\<^sub>a\<^sub>t\<^sub>a\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_character_data_ptr \ set |h \ node_ptr_kinds_M|\<^sub>r\ + + by (smt local.CD.a_all_ptrs_in_heap_def \CD.a_all_ptrs_in_heap h\ disc_nodes_document_ptr_h2 + disconnected_nodes_eq2_h + disconnected_nodes_eq2_h2 disconnected_nodes_eq2_h3 disjoint_iff_not_equal + document_ptr_kinds_eq_h document_ptr_kinds_eq_h2 finite_set_in h' + l_set_disconnected_nodes_get_disconnected_nodes.set_disconnected_nodes_get_disconnected_nodes + local.a_all_ptrs_in_heap_def local.l_set_disconnected_nodes_get_disconnected_nodes_axioms + select_result_I2 set_ConsD subsetD) + next + fix x xa xb + assume 2: "(\x\fset (object_ptr_kinds h3). set |h' \ get_child_nodes x|\<^sub>r) + \ (\x\fset (document_ptr_kinds h3). set |h3 \ get_disconnected_nodes x|\<^sub>r) = {}" + and 3: "xa |\| object_ptr_kinds h3" + and 4: "x \ set |h' \ get_child_nodes xa|\<^sub>r" + and 5: "xb |\| document_ptr_kinds h3" + and 6: "x \ set |h' \ get_disconnected_nodes xb|\<^sub>r" + show "False" + using disc_nodes_document_ptr_h disconnected_nodes_eq2_h3 + apply(cases "document_ptr = xb") + apply (metis (no_types, lifting) "3" "4" "5" "6" CD.distinct_lists_no_parent + \local.CD.a_distinct_lists h2\ \type_wf h'\ children_eq2_h2 children_eq2_h3 + disc_nodes_document_ptr_h2 document_ptr_kinds_eq_h3 h' local.get_disconnected_nodes_ok + local.set_disconnected_nodes_get_disconnected_nodes new_character_data_ptr_not_in_any_children + object_ptr_kinds_eq_h2 object_ptr_kinds_eq_h3 returns_result_eq returns_result_select_result + set_ConsD) + by (metis "3" "4" "5" "6" CD.distinct_lists_no_parent \local.CD.a_distinct_lists h3\ + \type_wf h3\ children_eq2_h3 local.get_disconnected_nodes_ok returns_result_select_result) + qed + + have "CD.a_owner_document_valid h" + using \heap_is_wellformed h\ by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_owner_document_valid h'" + using disc_nodes_h3 \document_ptr |\| document_ptr_kinds h\ + apply(simp add: CD.a_owner_document_valid_def) + apply(simp add: object_ptr_kinds_eq_h object_ptr_kinds_eq_h3 ) + apply(simp add: object_ptr_kinds_eq_h2) + apply(simp add: document_ptr_kinds_eq_h document_ptr_kinds_eq_h3 ) + apply(simp add: document_ptr_kinds_eq_h2) + apply(simp add: node_ptr_kinds_eq_h node_ptr_kinds_eq_h3 ) + apply(simp add: node_ptr_kinds_eq_h2 node_ptr_kinds_eq_h ) + apply(auto simp add: children_eq2_h2[symmetric] children_eq2_h3[symmetric] + disconnected_nodes_eq2_h + disconnected_nodes_eq2_h2 disconnected_nodes_eq2_h3)[1] + apply (metis (no_types, lifting) document_ptr_kinds_eq_h h' list.set_intros(1) + local.set_disconnected_nodes_get_disconnected_nodes select_result_I2) + apply(simp add: object_ptr_kinds_eq_h) + by (metis (mono_tags, lifting) + \cast\<^sub>c\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>_\<^sub>d\<^sub>a\<^sub>t\<^sub>a\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_character_data_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r\ + children_eq2_h disconnected_nodes_eq2_h3 document_ptr_kinds_eq_h finite_set_in h' + l_ptr_kinds_M.ptr_kinds_ptr_kinds_M + l_set_disconnected_nodes_get_disconnected_nodes.set_disconnected_nodes_get_disconnected_nodes + list.set_intros(2) local.l_set_disconnected_nodes_get_disconnected_nodes_axioms + object_ptr_kinds_M_def + select_result_I2) + + + + + + + have shadow_root_ptr_kinds_eq_h: "shadow_root_ptr_kinds h2 = shadow_root_ptr_kinds h" + using object_ptr_kinds_eq_h + by(auto simp add: shadow_root_ptr_kinds_def) + have shadow_root_ptr_kinds_eq_h2: "shadow_root_ptr_kinds h3 = shadow_root_ptr_kinds h2" + using object_ptr_kinds_eq_h2 + by(auto simp add: shadow_root_ptr_kinds_def) + have shadow_root_ptr_kinds_eq_h3: "shadow_root_ptr_kinds h' = shadow_root_ptr_kinds h3" + using object_ptr_kinds_eq_h3 + by(auto simp add: shadow_root_ptr_kinds_def) + + + + have shadow_root_eq_h: + "\character_data_ptr shadow_root_opt. h \ get_shadow_root character_data_ptr \\<^sub>r shadow_root_opt = +h2 \ get_shadow_root character_data_ptr \\<^sub>r shadow_root_opt" + using get_shadow_root_reads h2 get_shadow_root_new_character_data[rotated, OF h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + using local.get_shadow_root_locs_impl new_character_data_ptr apply blast + using local.get_shadow_root_locs_impl new_character_data_ptr by blast + + + have shadow_root_eq_h2: + "\ptr' children. h2 \ get_shadow_root ptr' \\<^sub>r children = h3 \ get_shadow_root ptr' \\<^sub>r children" + using get_shadow_root_reads set_val_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: set_val_get_shadow_root) + have shadow_root_eq_h3: + "\ptr' children. h3 \ get_shadow_root ptr' \\<^sub>r children = h' \ get_shadow_root ptr' \\<^sub>r children" + using get_shadow_root_reads set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved) + using set_disconnected_nodes_get_shadow_root + by(auto simp add: set_disconnected_nodes_get_shadow_root) + + + have "a_all_ptrs_in_heap h" + by (simp add: assms(1) local.a_all_ptrs_in_heap_def local.get_shadow_root_shadow_root_ptr_in_heap) + then have "a_all_ptrs_in_heap h2" + apply(auto simp add: a_all_ptrs_in_heap_def shadow_root_ptr_kinds_eq_h)[1] + using returns_result_eq shadow_root_eq_h by fastforce + then have "a_all_ptrs_in_heap h3" + apply(auto simp add: a_all_ptrs_in_heap_def shadow_root_ptr_kinds_eq_h2)[1] + using shadow_root_eq_h2 by blast + then have "a_all_ptrs_in_heap h'" + apply(auto simp add: a_all_ptrs_in_heap_def shadow_root_ptr_kinds_eq_h3)[1] + by (simp add: shadow_root_eq_h3) + + have "a_distinct_lists h" + using assms(1) + by (simp add: heap_is_wellformed_def) + then have "a_distinct_lists h2" + apply(auto simp add: a_distinct_lists_def character_data_ptr_kinds_eq_h)[1] + apply(auto simp add: distinct_insort intro!: distinct_concat_map_I split: option.splits)[1] + by (metis \type_wf h2\ assms(1) assms(3) local.get_shadow_root_ok local.shadow_root_same_host + returns_result_select_result shadow_root_eq_h) + then have "a_distinct_lists h3" + by(auto simp add: a_distinct_lists_def element_ptr_kinds_eq_h2 + select_result_eq[OF shadow_root_eq_h2]) + then have "a_distinct_lists h'" + by(auto simp add: a_distinct_lists_def element_ptr_kinds_eq_h3 + select_result_eq[OF shadow_root_eq_h3]) + + + have "a_shadow_root_valid h" + using assms(1) + by (simp add: heap_is_wellformed_def) + then have "a_shadow_root_valid h2" + by(auto simp add: a_shadow_root_valid_def shadow_root_ptr_kinds_eq_h element_ptr_kinds_eq_h + select_result_eq[OF shadow_root_eq_h] tag_name_eq2_h) + then have "a_shadow_root_valid h3" + by(auto simp add: a_shadow_root_valid_def shadow_root_ptr_kinds_eq_h2 element_ptr_kinds_eq_h2 + select_result_eq[OF shadow_root_eq_h2] tag_name_eq2_h2) + then have "a_shadow_root_valid h'" + by(auto simp add: a_shadow_root_valid_def shadow_root_ptr_kinds_eq_h3 element_ptr_kinds_eq_h3 + select_result_eq[OF shadow_root_eq_h3] tag_name_eq2_h3) + + + + have "a_host_shadow_root_rel h = a_host_shadow_root_rel h2" + by(auto simp add: a_host_shadow_root_rel_def element_ptr_kinds_eq_h + select_result_eq[OF shadow_root_eq_h]) + have "a_host_shadow_root_rel h2 = a_host_shadow_root_rel h3" + by(auto simp add: a_host_shadow_root_rel_def element_ptr_kinds_eq_h2 + select_result_eq[OF shadow_root_eq_h2]) + have "a_host_shadow_root_rel h3 = a_host_shadow_root_rel h'" + by(auto simp add: a_host_shadow_root_rel_def element_ptr_kinds_eq_h3 + select_result_eq[OF shadow_root_eq_h3]) + + have "acyclic (parent_child_rel h \ a_host_shadow_root_rel h)" + using \heap_is_wellformed h\ + by (simp add: heap_is_wellformed_def) + have "parent_child_rel h \ a_host_shadow_root_rel h = +parent_child_rel h2 \ a_host_shadow_root_rel h2" + using \local.a_host_shadow_root_rel h = local.a_host_shadow_root_rel h2\ + \parent_child_rel h = parent_child_rel h2\ by auto + have "parent_child_rel h2 \ a_host_shadow_root_rel h2 = +parent_child_rel h3 \ a_host_shadow_root_rel h3" + using \local.a_host_shadow_root_rel h2 = local.a_host_shadow_root_rel h3\ + \parent_child_rel h2 = parent_child_rel h3\ by auto + have "parent_child_rel h' \ a_host_shadow_root_rel h' = +parent_child_rel h3 \ a_host_shadow_root_rel h3" + by (simp add: \local.a_host_shadow_root_rel h3 = local.a_host_shadow_root_rel h'\ + \parent_child_rel h3 = parent_child_rel h'\) + + have "acyclic (parent_child_rel h3 \ a_host_shadow_root_rel h3)" + using \acyclic (parent_child_rel h \ local.a_host_shadow_root_rel h)\ + \parent_child_rel h \ local.a_host_shadow_root_rel h = parent_child_rel h2 \ +local.a_host_shadow_root_rel h2\ \parent_child_rel h2 \ local.a_host_shadow_root_rel h2 = +parent_child_rel h3 \ local.a_host_shadow_root_rel h3\ by auto + then have "acyclic (parent_child_rel h' \ a_host_shadow_root_rel h')" + by(simp add: \parent_child_rel h' \ a_host_shadow_root_rel h' = +parent_child_rel h3 \ a_host_shadow_root_rel h3\) + + + have "CD.a_heap_is_wellformed h'" + apply(simp add: CD.a_heap_is_wellformed_def) + by (simp add: \local.CD.a_acyclic_heap h'\ \local.CD.a_all_ptrs_in_heap h'\ + \local.CD.a_distinct_lists h'\ \local.CD.a_owner_document_valid h'\) + + show "heap_is_wellformed h' " + using \acyclic (parent_child_rel h' \ local.a_host_shadow_root_rel h')\ + by(simp add: heap_is_wellformed_def CD.heap_is_wellformed_impl + \local.CD.a_heap_is_wellformed h'\ \local.a_all_ptrs_in_heap h'\ \local.a_distinct_lists h'\ + \local.a_shadow_root_valid h'\) +qed +end + +subsubsection \create\_document\ + +locale l_create_document_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_child_nodes get_child_nodes_locs get_disconnected_nodes + get_disconnected_nodes_locs + get_shadow_root get_shadow_root_locs get_tag_name get_tag_name_locs known_ptr type_wf + heap_is_wellformed parent_child_rel + heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host get_host_locs get_disconnected_document + get_disconnected_document_locs + + l_new_document_get_disconnected_nodes + get_disconnected_nodes get_disconnected_nodes_locs + + l_create_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + create_document + + l_new_document_get_child_nodes + type_wf known_ptr get_child_nodes get_child_nodes_locs + + l_get_tag_name type_wf get_tag_name get_tag_name_locs + + l_new_document_get_tag_name get_tag_name get_tag_name_locs + + l_get_disconnected_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_nodes + get_disconnected_nodes_locs + + l_new_document + type_wf + + l_known_ptrs + known_ptr known_ptrs + for known_ptr :: "(_::linorder) object_ptr \ bool" + and type_wf :: "(_) heap \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and get_child_nodes :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_disconnected_nodes :: "(_) document_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_tag_name :: "(_) element_ptr \ ((_) heap, exception, char list) prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and get_host :: "(_) shadow_root_ptr \ ((_) heap, exception, (_) element_ptr) prog" + and get_host_locs :: "((_) heap \ (_) heap \ bool) set" + and get_disconnected_document :: "(_) node_ptr \ ((_) heap, exception, (_) document_ptr) prog" + and get_disconnected_document_locs :: "((_) heap \ (_) heap \ bool) set" + and heap_is_wellformed :: "(_) heap \ bool" + and parent_child_rel :: "(_) heap \ ((_) object_ptr \ (_) object_ptr) set" + and set_val :: "(_) character_data_ptr \ char list \ ((_) heap, exception, unit) prog" + and set_val_locs :: "(_) character_data_ptr \ ((_) heap, exception, unit) prog set" + and set_disconnected_nodes :: + "(_) document_ptr \ (_) node_ptr list \ ((_) heap, exception, unit) prog" + and set_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap, exception, unit) prog set" + and create_document :: "((_) heap, exception, (_) document_ptr) prog" + and known_ptrs :: "(_) heap \ bool" +begin + +lemma create_document_preserves_wellformedness: + assumes "heap_is_wellformed h" + and "h \ create_document \\<^sub>h h'" + and "type_wf h" + and "known_ptrs h" + shows "heap_is_wellformed h'" +proof - + obtain new_document_ptr where + new_document_ptr: "h \ new_document \\<^sub>r new_document_ptr" and + h': "h \ new_document \\<^sub>h h'" + using assms(2) + apply(simp add: create_document_def) + using new_document_ok by blast + + have "new_document_ptr \ set |h \ document_ptr_kinds_M|\<^sub>r" + using new_document_ptr DocumentMonad.ptr_kinds_ptr_kinds_M + using new_document_ptr_not_in_heap h' by blast + then have "cast new_document_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r" + by simp + + have "new_document_ptr |\| document_ptr_kinds h" + using new_document_ptr DocumentMonad.ptr_kinds_ptr_kinds_M + using new_document_ptr_not_in_heap h' by blast + then have "cast new_document_ptr |\| object_ptr_kinds h" + by simp + + have object_ptr_kinds_eq: "object_ptr_kinds h' = object_ptr_kinds h |\| {|cast new_document_ptr|}" + using new_document_new_ptr h' new_document_ptr by blast + then have node_ptr_kinds_eq: "node_ptr_kinds h' = node_ptr_kinds h" + apply(simp add: node_ptr_kinds_def) + by force + then have character_data_ptr_kinds_eq_h: "character_data_ptr_kinds h' = character_data_ptr_kinds h" + by(simp add: character_data_ptr_kinds_def) + have element_ptr_kinds_eq_h: "element_ptr_kinds h' = element_ptr_kinds h" + using object_ptr_kinds_eq + by(auto simp add: node_ptr_kinds_def element_ptr_kinds_def) + have document_ptr_kinds_eq_h: "document_ptr_kinds h' = document_ptr_kinds h |\| {|new_document_ptr|}" + using object_ptr_kinds_eq + apply(auto simp add: document_ptr_kinds_def)[1] + by (metis (no_types, lifting) document_ptr_kinds_commutes document_ptr_kinds_def finsertI1 + fset.map_comp) + have shadow_root_ptr_kinds_eq: "shadow_root_ptr_kinds h' = shadow_root_ptr_kinds h" + using object_ptr_kinds_eq + apply(simp add: shadow_root_ptr_kinds_def) + by force + + + have children_eq: + "\(ptr'::(_) object_ptr) children. ptr' \ cast new_document_ptr + \ h \ get_child_nodes ptr' \\<^sub>r children = h' \ get_child_nodes ptr' \\<^sub>r children" + using CD.get_child_nodes_reads h' get_child_nodes_new_document[rotated, OF new_document_ptr h'] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have children_eq2: "\ptr'. ptr' \ cast new_document_ptr + \ |h \ get_child_nodes ptr'|\<^sub>r = |h' \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + + + have "h' \ get_child_nodes (cast new_document_ptr) \\<^sub>r []" + using new_document_ptr h' new_document_ptr_in_heap[OF h' new_document_ptr] + new_document_is_document_ptr[OF new_document_ptr] new_document_no_child_nodes + by blast + have disconnected_nodes_eq_h: + "\doc_ptr disc_nodes. doc_ptr \ new_document_ptr + \ h \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes = +h' \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using CD.get_disconnected_nodes_reads h' get_disconnected_nodes_new_document_different_pointers + new_document_ptr + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by (metis(full_types) \\thesis. (\new_document_ptr. + \h \ new_document \\<^sub>r new_document_ptr; h \ new_document \\<^sub>h h'\ \ thesis) \ thesis\ + local.get_disconnected_nodes_new_document_different_pointers new_document_ptr)+ + then have disconnected_nodes_eq2_h: "\doc_ptr. doc_ptr \ new_document_ptr + \ |h \ get_disconnected_nodes doc_ptr|\<^sub>r = |h' \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + have "h' \ get_disconnected_nodes new_document_ptr \\<^sub>r []" + using h' local.new_document_no_disconnected_nodes new_document_ptr by blast + + have "type_wf h'" + using \type_wf h\ new_document_types_preserved h' by blast + + have "acyclic (parent_child_rel h)" + using \heap_is_wellformed h\ + by (auto simp add: heap_is_wellformed_def CD.heap_is_wellformed_def CD.acyclic_heap_def) + also have "parent_child_rel h = parent_child_rel h'" + proof(auto simp add: CD.parent_child_rel_def)[1] + fix a x + assume 0: "a |\| object_ptr_kinds h" + and 1: "x \ set |h \ get_child_nodes a|\<^sub>r" + then show "a |\| object_ptr_kinds h'" + by (simp add: object_ptr_kinds_eq) + next + fix a x + assume 0: "a |\| object_ptr_kinds h" + and 1: "x \ set |h \ get_child_nodes a|\<^sub>r" + then show "x \ set |h' \ get_child_nodes a|\<^sub>r" + by (metis ObjectMonad.ptr_kinds_ptr_kinds_M + \cast new_document_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r\ children_eq2) + next + fix a x + assume 0: "a |\| object_ptr_kinds h'" + and 1: "x \ set |h' \ get_child_nodes a|\<^sub>r" + then show "a |\| object_ptr_kinds h" + using object_ptr_kinds_eq \h' \ get_child_nodes (cast new_document_ptr) \\<^sub>r []\ + by(auto) + next + fix a x + assume 0: "a |\| object_ptr_kinds h'" + and 1: "x \ set |h' \ get_child_nodes a|\<^sub>r" + then show "x \ set |h \ get_child_nodes a|\<^sub>r" + by (metis (no_types, lifting) \h' \ get_child_nodes (cast new_document_ptr) \\<^sub>r []\ + children_eq2 empty_iff empty_set image_eqI select_result_I2) + qed + finally have "CD.a_acyclic_heap h'" + by (simp add: CD.acyclic_heap_def) + + have "CD.a_all_ptrs_in_heap h" + using \heap_is_wellformed h\ by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def ) + then have "CD.a_all_ptrs_in_heap h'" + apply(auto simp add: CD.a_all_ptrs_in_heap_def)[1] + using ObjectMonad.ptr_kinds_ptr_kinds_M + \cast\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_document_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r\ + \parent_child_rel h = parent_child_rel h'\ assms(1) children_eq fset_of_list_elem + local.heap_is_wellformed_children_in_heap CD.parent_child_rel_child + CD.parent_child_rel_parent_in_heap node_ptr_kinds_eq + apply (metis (no_types, lifting) + \h' \ get_child_nodes (cast\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_document_ptr) \\<^sub>r []\ + children_eq2 finite_set_in finsert_iff funion_finsert_right object_ptr_kinds_eq + select_result_I2 subsetD sup_bot.right_neutral) + by (metis (no_types, lifting) \h' \ get_disconnected_nodes new_document_ptr \\<^sub>r []\ \type_wf h'\ + assms(1) disconnected_nodes_eq_h empty_iff empty_set local.get_disconnected_nodes_ok + local.heap_is_wellformed_disc_nodes_in_heap node_ptr_kinds_eq returns_result_select_result + select_result_I2) + + have "CD.a_distinct_lists h" + using \heap_is_wellformed h\ + by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_distinct_lists h'" + using \h' \ get_disconnected_nodes new_document_ptr \\<^sub>r []\ + \h' \ get_child_nodes (cast new_document_ptr) \\<^sub>r []\ + + apply(auto simp add: children_eq2[symmetric] CD.a_distinct_lists_def insort_split + object_ptr_kinds_eq + document_ptr_kinds_eq_h disconnected_nodes_eq2_h intro!: distinct_concat_map_I)[1] + apply (metis distinct_sorted_list_of_set finite_fset sorted_list_of_set_insert) + + apply(auto simp add: dest: distinct_concat_map_E)[1] + apply(auto simp add: dest: distinct_concat_map_E)[1] + using \new_document_ptr |\| document_ptr_kinds h\ + apply(auto simp add: distinct_insort dest: distinct_concat_map_E)[1] + apply (metis assms(1) assms(3) disconnected_nodes_eq2_h get_disconnected_nodes_ok + local.heap_is_wellformed_disconnected_nodes_distinct + returns_result_select_result) + proof - + fix x :: "(_) document_ptr" and y :: "(_) document_ptr" and xa :: "(_) node_ptr" + assume a1: "x \ y" + assume a2: "x |\| document_ptr_kinds h" + assume a3: "x \ new_document_ptr" + assume a4: "y |\| document_ptr_kinds h" + assume a5: "y \ new_document_ptr" + assume a6: "distinct (concat (map (\document_ptr. |h \ get_disconnected_nodes document_ptr|\<^sub>r) + (sorted_list_of_set (fset (document_ptr_kinds h)))))" + assume a7: "xa \ set |h' \ get_disconnected_nodes x|\<^sub>r" + assume a8: "xa \ set |h' \ get_disconnected_nodes y|\<^sub>r" + have f9: "xa \ set |h \ get_disconnected_nodes x|\<^sub>r" + using a7 a3 disconnected_nodes_eq2_h by presburger + have f10: "xa \ set |h \ get_disconnected_nodes y|\<^sub>r" + using a8 a5 disconnected_nodes_eq2_h by presburger + have f11: "y \ set (sorted_list_of_set (fset (document_ptr_kinds h)))" + using a4 by simp + have "x \ set (sorted_list_of_set (fset (document_ptr_kinds h)))" + using a2 by simp + then show False + using f11 f10 f9 a6 a1 by (meson disjoint_iff_not_equal distinct_concat_map_E(1)) + next + fix x xa xb + assume 0: "h' \ get_disconnected_nodes new_document_ptr \\<^sub>r []" + and 1: "h' \ get_child_nodes (cast\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_document_ptr) \\<^sub>r []" + and 2: "distinct (concat (map (\ptr. |h \ get_child_nodes ptr|\<^sub>r) + (sorted_list_of_set (fset (object_ptr_kinds h)))))" + and 3: "distinct (concat (map (\document_ptr. |h \ get_disconnected_nodes document_ptr|\<^sub>r) + (sorted_list_of_set (fset (document_ptr_kinds h)))))" + and 4: "(\x\fset (object_ptr_kinds h). set |h \ get_child_nodes x|\<^sub>r) + \ (\x\fset (document_ptr_kinds h). set |h \ get_disconnected_nodes x|\<^sub>r) = {}" + and 5: "x \ set |h \ get_child_nodes xa|\<^sub>r" + and 6: "x \ set |h' \ get_disconnected_nodes xb|\<^sub>r" + and 7: "xa |\| object_ptr_kinds h" + and 8: "xa \ cast\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_document_ptr" + and 9: "xb |\| document_ptr_kinds h" + and 10: "xb \ new_document_ptr" + then show "False" + + by (metis \CD.a_distinct_lists h\ assms(3) disconnected_nodes_eq2_h + CD.distinct_lists_no_parent get_disconnected_nodes_ok + returns_result_select_result) + qed + + have "CD.a_owner_document_valid h" + using \heap_is_wellformed h\ by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_owner_document_valid h'" + apply(auto simp add: CD.a_owner_document_valid_def)[1] + by (metis \cast\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_document_ptr |\| object_ptr_kinds h\ + children_eq2 disconnected_nodes_eq2_h document_ptr_kinds_commutes finite_set_in funion_iff + node_ptr_kinds_eq object_ptr_kinds_eq) + + + have shadow_root_eq_h: "\character_data_ptr shadow_root_opt. +h \ get_shadow_root character_data_ptr \\<^sub>r shadow_root_opt = +h' \ get_shadow_root character_data_ptr \\<^sub>r shadow_root_opt" + using get_shadow_root_reads assms(2) get_shadow_root_new_document[rotated, OF h'] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + using local.get_shadow_root_locs_impl new_document_ptr apply blast + using local.get_shadow_root_locs_impl new_document_ptr by blast + + + have "a_all_ptrs_in_heap h" + by (simp add: assms(1) local.a_all_ptrs_in_heap_def local.get_shadow_root_shadow_root_ptr_in_heap) + then have "a_all_ptrs_in_heap h'" + apply(auto simp add: a_all_ptrs_in_heap_def shadow_root_ptr_kinds_eq document_ptr_kinds_eq_h)[1] + using shadow_root_eq_h by fastforce + + have "a_distinct_lists h" + using assms(1) + by (simp add: heap_is_wellformed_def) + then have "a_distinct_lists h'" + apply(auto simp add: a_distinct_lists_def character_data_ptr_kinds_eq_h)[1] + apply(auto simp add: distinct_insort intro!: distinct_concat_map_I split: option.splits)[1] + by (metis \type_wf h'\ assms(1) assms(3) local.get_shadow_root_ok local.shadow_root_same_host + returns_result_select_result shadow_root_eq_h) + + + have tag_name_eq_h: + "\ptr' disc_nodes. h \ get_tag_name ptr' \\<^sub>r disc_nodes + = h' \ get_tag_name ptr' \\<^sub>r disc_nodes" + using get_tag_name_reads h' + get_tag_name_new_document[OF new_document_ptr h'] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + + have "a_shadow_root_valid h" + using assms(1) + by (simp add: heap_is_wellformed_def) + then have "a_shadow_root_valid h'" + using new_document_is_document_ptr[OF new_document_ptr] + by(auto simp add: a_shadow_root_valid_def element_ptr_kinds_eq_h document_ptr_kinds_eq_h + shadow_root_ptr_kinds_eq select_result_eq[OF shadow_root_eq_h] select_result_eq[OF tag_name_eq_h]) + + + have "a_host_shadow_root_rel h = a_host_shadow_root_rel h'" + by(auto simp add: a_host_shadow_root_rel_def element_ptr_kinds_eq_h + select_result_eq[OF shadow_root_eq_h]) + + have "acyclic (parent_child_rel h \ a_host_shadow_root_rel h)" + using \heap_is_wellformed h\ + by (simp add: heap_is_wellformed_def) + moreover + have "parent_child_rel h \ a_host_shadow_root_rel h = +parent_child_rel h' \ a_host_shadow_root_rel h'" + by (simp add: \local.a_host_shadow_root_rel h = local.a_host_shadow_root_rel h'\ + \parent_child_rel h = parent_child_rel h'\) + ultimately have "acyclic (parent_child_rel h' \ a_host_shadow_root_rel h')" + by simp + + have "CD.a_heap_is_wellformed h'" + apply(simp add: CD.a_heap_is_wellformed_def) + by (simp add: \local.CD.a_acyclic_heap h'\ \local.CD.a_all_ptrs_in_heap h'\ + \local.CD.a_distinct_lists h'\ \local.CD.a_owner_document_valid h'\) + + show "heap_is_wellformed h'" + using CD.heap_is_wellformed_impl \acyclic (parent_child_rel h' \ local.a_host_shadow_root_rel h')\ + \local.CD.a_heap_is_wellformed h'\ \local.a_all_ptrs_in_heap h'\ \local.a_distinct_lists h'\ + \local.a_shadow_root_valid h'\ local.heap_is_wellformed_def by auto +qed +end + +interpretation l_create_document_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr type_wf DocumentClass.type_wf get_child_nodes + get_child_nodes_locs get_disconnected_nodes get_disconnected_nodes_locs get_shadow_root + get_shadow_root_locs get_tag_name get_tag_name_locs + heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host get_host_locs get_disconnected_document + get_disconnected_document_locs heap_is_wellformed parent_child_rel set_val set_val_locs + set_disconnected_nodes set_disconnected_nodes_locs create_document known_ptrs + by(auto simp add: l_create_document_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) + + +subsubsection \attach\_shadow\_root\ + +locale l_attach_shadow_root_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_disconnected_nodes + type_wf get_disconnected_nodes get_disconnected_nodes_locs + + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + get_child_nodes get_child_nodes_locs get_disconnected_nodes get_disconnected_nodes_locs + get_shadow_root get_shadow_root_locs get_tag_name get_tag_name_locs known_ptr type_wf + heap_is_wellformed parent_child_rel + heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host get_host_locs get_disconnected_document + get_disconnected_document_locs + + l_attach_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr set_shadow_root set_shadow_root_locs set_mode + set_mode_locs attach_shadow_root type_wf get_tag_name get_tag_name_locs get_shadow_root + get_shadow_root_locs + + l_new_shadow_root_get_disconnected_nodes + get_disconnected_nodes get_disconnected_nodes_locs + ++ l_set_mode_get_disconnected_nodes +type_wf set_mode set_mode_locs get_disconnected_nodes get_disconnected_nodes_locs ++ l_new_shadow_root_get_child_nodes +type_wf known_ptr get_child_nodes get_child_nodes_locs ++ l_new_shadow_root_get_tag_name +type_wf get_tag_name get_tag_name_locs ++ l_set_mode_get_child_nodes +type_wf set_mode set_mode_locs known_ptr get_child_nodes get_child_nodes_locs ++ l_set_shadow_root_get_child_nodes +type_wf set_shadow_root set_shadow_root_locs known_ptr get_child_nodes get_child_nodes_locs ++ l_set_shadow_root +type_wf set_shadow_root set_shadow_root_locs ++ l_set_shadow_root_get_disconnected_nodes +set_shadow_root set_shadow_root_locs get_disconnected_nodes get_disconnected_nodes_locs ++ l_set_mode_get_shadow_root type_wf set_mode set_mode_locs get_shadow_root get_shadow_root_locs ++ l_set_shadow_root_get_shadow_root type_wf set_shadow_root set_shadow_root_locs +get_shadow_root get_shadow_root_locs ++ l_new_character_data_get_tag_name +get_tag_name get_tag_name_locs ++ l_set_mode_get_tag_name type_wf set_mode set_mode_locs get_tag_name get_tag_name_locs ++ l_get_tag_name type_wf get_tag_name get_tag_name_locs ++ l_set_shadow_root_get_tag_name set_shadow_root set_shadow_root_locs get_tag_name get_tag_name_locs ++ l_new_shadow_root +type_wf ++ l_known_ptrs +known_ptr known_ptrs +for known_ptr :: "(_::linorder) object_ptr \ bool" + and known_ptrs :: "(_) heap \ bool" + and type_wf :: "(_) heap \ bool" + and get_child_nodes :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_disconnected_nodes :: "(_) document_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" + and heap_is_wellformed :: "(_) heap \ bool" + and parent_child_rel :: "(_) heap \ ((_) object_ptr \ (_) object_ptr) set" + and set_tag_name :: "(_) element_ptr \ char list \ ((_) heap, exception, unit) prog" + and set_tag_name_locs :: "(_) element_ptr \ ((_) heap, exception, unit) prog set" + and set_disconnected_nodes :: "(_) document_ptr \ (_) node_ptr list \ ((_) heap, exception, unit) prog" + and set_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap, exception, unit) prog set" + and create_element :: "(_) document_ptr \ char list \ ((_) heap, exception, (_) element_ptr) prog" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_tag_name :: "(_) element_ptr \ ((_) heap, exception, char list) prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and get_host :: "(_) shadow_root_ptr \ ((_) heap, exception, (_) element_ptr) prog" + and get_host_locs :: "((_) heap \ (_) heap \ bool) set" + and get_disconnected_document :: "(_) node_ptr \ ((_) heap, exception, (_) document_ptr) prog" + and get_disconnected_document_locs :: "((_) heap \ (_) heap \ bool) set" + and set_val :: "(_) character_data_ptr \ char list \ ((_) heap, exception, unit) prog" + and set_val_locs :: "(_) character_data_ptr \ ((_) heap, exception, unit) prog set" + and create_character_data :: + "(_) document_ptr \ char list \ ((_) heap, exception, (_) character_data_ptr) prog" + and known_ptr\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_::linorder) object_ptr \ bool" + and type_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M :: "(_) heap \ bool" + and set_shadow_root :: "(_) element_ptr \ (_) shadow_root_ptr option \ (_, unit) dom_prog" + and set_shadow_root_locs :: "(_) element_ptr \ (_, unit) dom_prog set" + and set_mode :: "(_) shadow_root_ptr \ shadow_root_mode \ (_, unit) dom_prog" + and set_mode_locs :: "(_) shadow_root_ptr \ (_, unit) dom_prog set" + and attach_shadow_root :: "(_) element_ptr \ shadow_root_mode \ (_, (_) shadow_root_ptr) dom_prog" +begin +lemma attach_shadow_root_child_preserves: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ attach_shadow_root element_ptr new_mode \\<^sub>h h'" + shows "type_wf h'" and "known_ptrs h'" and "heap_is_wellformed h'" +proof - + obtain h2 h3 new_shadow_root_ptr element_tag_name where + element_tag_name: "h \ get_tag_name element_ptr \\<^sub>r element_tag_name" and + "element_tag_name \ safe_shadow_root_element_types" and + prev_shadow_root: "h \ get_shadow_root element_ptr \\<^sub>r None" and + h2: "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h2" and + new_shadow_root_ptr: "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr" and + h3: "h2 \ set_mode new_shadow_root_ptr new_mode \\<^sub>h h3" and + h': "h3 \ set_shadow_root element_ptr (Some new_shadow_root_ptr) \\<^sub>h h'" + using assms(4) + by(auto simp add: attach_shadow_root_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_tag_name_pure, rotated] + bind_returns_heap_E2[rotated, OF get_shadow_root_pure, rotated] split: if_splits) + + have "h \ attach_shadow_root element_ptr new_mode \\<^sub>r new_shadow_root_ptr" + thm bind_pure_returns_result_I[OF get_tag_name_pure] + apply(unfold attach_shadow_root_def)[1] + using element_tag_name + apply(rule bind_pure_returns_result_I[OF get_tag_name_pure]) + apply(rule bind_pure_returns_result_I) + using \element_tag_name \ safe_shadow_root_element_types\ apply(simp) + using \element_tag_name \ safe_shadow_root_element_types\ apply(simp) + using prev_shadow_root + apply(rule bind_pure_returns_result_I[OF get_shadow_root_pure]) + apply(rule bind_pure_returns_result_I) + apply(simp) + apply(simp) + using h2 new_shadow_root_ptr h3 h' + by(auto intro!: bind_returns_result_I + intro: is_OK_returns_result_E[OF is_OK_returns_heap_I[OF h3]] + is_OK_returns_result_E[OF is_OK_returns_heap_I[OF h']]) + + have "new_shadow_root_ptr \ set |h \ shadow_root_ptr_kinds_M|\<^sub>r" + using new_shadow_root_ptr ShadowRootMonad.ptr_kinds_ptr_kinds_M h2 + using new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_ptr_not_in_heap by blast + then have "cast new_shadow_root_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r" + by simp + + + + have object_ptr_kinds_eq_h: + "object_ptr_kinds h2 = object_ptr_kinds h |\| {|cast new_shadow_root_ptr|}" + using new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_new_ptr h2 new_shadow_root_ptr by blast + then have document_ptr_kinds_eq_h: + "document_ptr_kinds h2 = document_ptr_kinds h" + apply(simp add: document_ptr_kinds_def) + by force + have shadow_root_ptr_kinds_eq_h: + "shadow_root_ptr_kinds h2 = shadow_root_ptr_kinds h |\| {|new_shadow_root_ptr|}" + using object_ptr_kinds_eq_h + apply(simp add: shadow_root_ptr_kinds_def) + by force + have element_ptr_kinds_eq_h: "element_ptr_kinds h2 = element_ptr_kinds h" + using object_ptr_kinds_eq_h + by(auto simp add: node_ptr_kinds_def element_ptr_kinds_def) + + have object_ptr_kinds_eq_h2: "object_ptr_kinds h3 = object_ptr_kinds h2" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h' = object_ptr_kinds h", + OF set_mode_writes h3]) + using set_mode_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have document_ptr_kinds_eq_h2: "document_ptr_kinds h3 = document_ptr_kinds h2" + by (auto simp add: document_ptr_kinds_def) + have shadow_root_ptr_kinds_eq_h2: "shadow_root_ptr_kinds h3 = shadow_root_ptr_kinds h2" + using object_ptr_kinds_eq_h2 + by (auto simp add: shadow_root_ptr_kinds_def) + have node_ptr_kinds_eq_h2: "node_ptr_kinds h3 = node_ptr_kinds h2" + using object_ptr_kinds_eq_h2 + by(auto simp add: node_ptr_kinds_def) + + have object_ptr_kinds_eq_h3: "object_ptr_kinds h' = object_ptr_kinds h3" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h' = object_ptr_kinds h", + OF set_shadow_root_writes h']) + using set_shadow_root_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have document_ptr_kinds_eq_h3: "document_ptr_kinds h' = document_ptr_kinds h3" + by (auto simp add: document_ptr_kinds_def) + have shadow_root_ptr_kinds_eq_h3: "shadow_root_ptr_kinds h' = shadow_root_ptr_kinds h3" + using object_ptr_kinds_eq_h3 + by (auto simp add: shadow_root_ptr_kinds_def) + have node_ptr_kinds_eq_h3: "node_ptr_kinds h' = node_ptr_kinds h3" + using object_ptr_kinds_eq_h3 + by(auto simp add: node_ptr_kinds_def) + + have "known_ptr (cast new_shadow_root_ptr)" + using \h \ attach_shadow_root element_ptr new_mode \\<^sub>r new_shadow_root_ptr\ + create_shadow_root_known_ptr by blast + then + have "known_ptrs h2" + using known_ptrs_new_ptr object_ptr_kinds_eq_h \known_ptrs h\ h2 + by blast + then + have "known_ptrs h3" + using known_ptrs_preserved object_ptr_kinds_eq_h2 by blast + then + show "known_ptrs h'" + using known_ptrs_preserved object_ptr_kinds_eq_h3 by blast + + have "element_ptr |\| element_ptr_kinds h" + by (meson \h \ attach_shadow_root element_ptr new_mode \\<^sub>r new_shadow_root_ptr\ + is_OK_returns_result_I local.attach_shadow_root_element_ptr_in_heap) + + + have children_eq_h: "\(ptr'::(_) object_ptr) children. ptr' \ cast new_shadow_root_ptr + \ h \ get_child_nodes ptr' \\<^sub>r children = h2 \ get_child_nodes ptr' \\<^sub>r children" + using CD.get_child_nodes_reads h2 get_child_nodes_new_shadow_root[rotated, OF new_shadow_root_ptr h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have children_eq2_h: + "\ptr'. ptr' \ cast new_shadow_root_ptr + \ |h \ get_child_nodes ptr'|\<^sub>r = |h2 \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + have object_ptr_kinds_eq_h: + "object_ptr_kinds h2 = object_ptr_kinds h |\| {|cast new_shadow_root_ptr|}" + using new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_new_ptr h2 new_shadow_root_ptr object_ptr_kinds_eq_h by blast + then have node_ptr_kinds_eq_h: + "node_ptr_kinds h2 = node_ptr_kinds h" + apply(simp add: node_ptr_kinds_def) + by force + then have character_data_ptr_kinds_eq_h: + "character_data_ptr_kinds h2 = character_data_ptr_kinds h" + apply(simp add: character_data_ptr_kinds_def) + done + have element_ptr_kinds_eq_h: "element_ptr_kinds h2 = element_ptr_kinds h" + using object_ptr_kinds_eq_h + by(auto simp add: node_ptr_kinds_def element_ptr_kinds_def) + + have object_ptr_kinds_eq_h2: "object_ptr_kinds h3 = object_ptr_kinds h2" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h' = object_ptr_kinds h", + OF set_mode_writes h3]) + using set_mode_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have document_ptr_kinds_eq_h2: "document_ptr_kinds h3 = document_ptr_kinds h2" + by (auto simp add: document_ptr_kinds_def) + have node_ptr_kinds_eq_h2: "node_ptr_kinds h3 = node_ptr_kinds h2" + using object_ptr_kinds_eq_h2 + by(auto simp add: node_ptr_kinds_def) + then have character_data_ptr_kinds_eq_h2: "character_data_ptr_kinds h3 = character_data_ptr_kinds h2" + by(simp add: character_data_ptr_kinds_def) + have element_ptr_kinds_eq_h2: "element_ptr_kinds h3 = element_ptr_kinds h2" + using node_ptr_kinds_eq_h2 + by(simp add: element_ptr_kinds_def) + + have object_ptr_kinds_eq_h3: "object_ptr_kinds h' = object_ptr_kinds h3" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h' = object_ptr_kinds h", + OF set_shadow_root_writes h']) + using set_shadow_root_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have document_ptr_kinds_eq_h3: "document_ptr_kinds h' = document_ptr_kinds h3" + by (auto simp add: document_ptr_kinds_def) + have node_ptr_kinds_eq_h3: "node_ptr_kinds h' = node_ptr_kinds h3" + using object_ptr_kinds_eq_h3 + by(auto simp add: node_ptr_kinds_def) + then have character_data_ptr_kinds_eq_h3: "character_data_ptr_kinds h' = character_data_ptr_kinds h3" + by(simp add: character_data_ptr_kinds_def) + have element_ptr_kinds_eq_h3: "element_ptr_kinds h' = element_ptr_kinds h3" + using node_ptr_kinds_eq_h3 + by(simp add: element_ptr_kinds_def) + + + have children_eq_h: "\(ptr'::(_) object_ptr) children. ptr' \ cast new_shadow_root_ptr + \ h \ get_child_nodes ptr' \\<^sub>r children = h2 \ get_child_nodes ptr' \\<^sub>r children" + using CD.get_child_nodes_reads h2 get_child_nodes_new_shadow_root[rotated, OF new_shadow_root_ptr h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have children_eq2_h: "\ptr'. ptr' \ cast new_shadow_root_ptr + \ |h \ get_child_nodes ptr'|\<^sub>r = |h2 \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + + have "h2 \ get_child_nodes (cast new_shadow_root_ptr) \\<^sub>r []" + using h2 local.new_shadow_root_no_child_nodes new_shadow_root_ptr by auto + + have disconnected_nodes_eq_h: + "\doc_ptr disc_nodes. h \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes + = h2 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using get_disconnected_nodes_reads h2 + get_disconnected_nodes_new_shadow_root[rotated, OF h2,rotated,OF new_shadow_root_ptr] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by (metis (no_types, lifting))+ + then have disconnected_nodes_eq2_h: + "\doc_ptr. |h \ get_disconnected_nodes doc_ptr|\<^sub>r = |h2 \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + + have tag_name_eq_h: + "\ptr' disc_nodes. h \ get_tag_name ptr' \\<^sub>r disc_nodes + = h2 \ get_tag_name ptr' \\<^sub>r disc_nodes" + using get_tag_name_reads h2 + get_tag_name_new_shadow_root[OF new_shadow_root_ptr h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have tag_name_eq2_h: "\ptr'. |h \ get_tag_name ptr'|\<^sub>r = |h2 \ get_tag_name ptr'|\<^sub>r" + using select_result_eq by force + + have children_eq_h2: + "\ptr' children. h2 \ get_child_nodes ptr' \\<^sub>r children = h3 \ get_child_nodes ptr' \\<^sub>r children" + using CD.get_child_nodes_reads set_mode_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: set_mode_get_child_nodes) + then have children_eq2_h2: + "\ptr'. |h2 \ get_child_nodes ptr'|\<^sub>r = |h3 \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + have disconnected_nodes_eq_h2: + "\doc_ptr disc_nodes. h2 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes + = h3 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using get_disconnected_nodes_reads set_mode_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: set_mode_get_disconnected_nodes) + then have disconnected_nodes_eq2_h2: + "\doc_ptr. |h2 \ get_disconnected_nodes doc_ptr|\<^sub>r = |h3 \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + have tag_name_eq_h2: + "\ptr' disc_nodes. h2 \ get_tag_name ptr' \\<^sub>r disc_nodes + = h3 \ get_tag_name ptr' \\<^sub>r disc_nodes" + using get_tag_name_reads set_mode_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: set_mode_get_tag_name) + then have tag_name_eq2_h2: "\ptr'. |h2 \ get_tag_name ptr'|\<^sub>r = |h3 \ get_tag_name ptr'|\<^sub>r" + using select_result_eq by force + + have "type_wf h2" + using \type_wf h\ new_shadow_root_types_preserved h2 by blast + then have "type_wf h3" + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", OF set_mode_writes h3] + using set_mode_types_preserved + by(auto simp add: reflp_def transp_def) + then show "type_wf h'" + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", OF set_shadow_root_writes h'] + using set_shadow_root_types_preserved + by(auto simp add: reflp_def transp_def) + + have children_eq_h3: + "\ptr' children. h3 \ get_child_nodes ptr' \\<^sub>r children = h' \ get_child_nodes ptr' \\<^sub>r children" + using CD.get_child_nodes_reads set_shadow_root_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: set_shadow_root_get_child_nodes) + then have children_eq2_h3: + " \ptr'. |h3 \ get_child_nodes ptr'|\<^sub>r = |h' \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + have disconnected_nodes_eq_h3: "\doc_ptr disc_nodes. h3 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes + = h' \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using get_disconnected_nodes_reads set_shadow_root_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: set_shadow_root_get_disconnected_nodes) + then have disconnected_nodes_eq2_h3: + "\doc_ptr. |h3 \ get_disconnected_nodes doc_ptr|\<^sub>r = |h' \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + have tag_name_eq_h3: + "\ptr' disc_nodes. h3 \ get_tag_name ptr' \\<^sub>r disc_nodes + = h' \ get_tag_name ptr' \\<^sub>r disc_nodes" + using get_tag_name_reads set_shadow_root_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: set_shadow_root_get_tag_name) + then have tag_name_eq2_h3: "\ptr'. |h3 \ get_tag_name ptr'|\<^sub>r = |h' \ get_tag_name ptr'|\<^sub>r" + using select_result_eq by force + + have "acyclic (parent_child_rel h)" + using \heap_is_wellformed h\ + by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def CD.acyclic_heap_def) + also have "parent_child_rel h = parent_child_rel h2" + proof(auto simp add: CD.parent_child_rel_def)[1] + fix a x + assume 0: "a |\| object_ptr_kinds h" + and 1: "x \ set |h \ get_child_nodes a|\<^sub>r" + then show "a |\| object_ptr_kinds h2" + by (simp add: object_ptr_kinds_eq_h) + next + fix a x + assume 0: "a |\| object_ptr_kinds h" + and 1: "x \ set |h \ get_child_nodes a|\<^sub>r" + then show "x \ set |h2 \ get_child_nodes a|\<^sub>r" + by (metis ObjectMonad.ptr_kinds_ptr_kinds_M + \cast new_shadow_root_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r\ children_eq2_h) + next + fix a x + assume 0: "a |\| object_ptr_kinds h2" + and 1: "x \ set |h2 \ get_child_nodes a|\<^sub>r" + then show "a |\| object_ptr_kinds h" + using object_ptr_kinds_eq_h \h2 \ get_child_nodes (cast new_shadow_root_ptr) \\<^sub>r []\ + by(auto) + next + fix a x + assume 0: "a |\| object_ptr_kinds h2" + and 1: "x \ set |h2 \ get_child_nodes a|\<^sub>r" + then show "x \ set |h \ get_child_nodes a|\<^sub>r" + by (metis (no_types, lifting) \h2 \ get_child_nodes (cast new_shadow_root_ptr) \\<^sub>r []\ + children_eq2_h empty_iff empty_set image_eqI select_result_I2) + qed + also have "\ = parent_child_rel h3" + by(auto simp add: CD.parent_child_rel_def object_ptr_kinds_eq_h2 children_eq2_h2) + also have "\ = parent_child_rel h'" + by(auto simp add: CD.parent_child_rel_def object_ptr_kinds_eq_h3 children_eq2_h3) + finally have "CD.a_acyclic_heap h'" + by (simp add: CD.acyclic_heap_def) + + have "CD.a_all_ptrs_in_heap h" + using \heap_is_wellformed h\ by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_all_ptrs_in_heap h2" + apply(auto simp add: CD.a_all_ptrs_in_heap_def)[1] + using node_ptr_kinds_eq_h + \h2 \ get_child_nodes (cast new_shadow_root_ptr) \\<^sub>r []\ + apply (metis (no_types, lifting) CD.get_child_nodes_ok CD.l_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms + \known_ptrs h2\ \parent_child_rel h = parent_child_rel h2\ \type_wf h2\ assms(1) assms(2) + l_heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.parent_child_rel_child local.known_ptrs_known_ptr + local.parent_child_rel_child_in_heap node_ptr_kinds_commutes returns_result_select_result) + by (metis assms(1) assms(2) disconnected_nodes_eq2_h document_ptr_kinds_eq_h + local.get_disconnected_nodes_ok local.heap_is_wellformed_disc_nodes_in_heap node_ptr_kinds_eq_h + returns_result_select_result) + then have "CD.a_all_ptrs_in_heap h3" + by (simp add: children_eq2_h2 disconnected_nodes_eq2_h2 document_ptr_kinds_eq_h2 + CD.a_all_ptrs_in_heap_def node_ptr_kinds_eq_h2 object_ptr_kinds_eq_h2) + then have "CD.a_all_ptrs_in_heap h'" + by (simp add: children_eq2_h3 disconnected_nodes_eq2_h3 document_ptr_kinds_eq_h3 + CD.a_all_ptrs_in_heap_def node_ptr_kinds_eq_h3 object_ptr_kinds_eq_h3) + + have "CD.a_distinct_lists h" + using \heap_is_wellformed h\ + by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_distinct_lists h2" + using \h2 \ get_child_nodes (cast new_shadow_root_ptr) \\<^sub>r []\ children_eq2_h + apply(auto simp add: select_result_eq[OF disconnected_nodes_eq_h] CD.a_distinct_lists_def + insort_split object_ptr_kinds_eq_h + document_ptr_kinds_eq_h disconnected_nodes_eq2_h intro!: distinct_concat_map_I + dest: distinct_concat_map_E)[1] + apply (metis distinct_sorted_list_of_set finite_fset sorted_list_of_set_insert) + apply(auto simp add: dest: distinct_concat_map_E)[1] + apply(case_tac "x = cast new_shadow_root_ptr") + using \h2 \ get_child_nodes (cast new_shadow_root_ptr) \\<^sub>r []\ children_eq2_h apply blast + apply(case_tac "y = cast new_shadow_root_ptr") + using \h2 \ get_child_nodes (cast new_shadow_root_ptr) \\<^sub>r []\ children_eq2_h apply blast + proof - + fix x y :: "(_) object_ptr" + fix xa :: "(_) node_ptr" + assume a1: "distinct (concat (map (\ptr. |h \ get_child_nodes ptr|\<^sub>r) +(sorted_list_of_set (fset (object_ptr_kinds h)))))" + assume "x \ y" + assume "xa \ set |h2 \ get_child_nodes x|\<^sub>r" + assume "xa \ set |h2 \ get_child_nodes y|\<^sub>r" + assume "x |\| object_ptr_kinds h" + assume "x \ cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_shadow_root_ptr" + assume "y |\| object_ptr_kinds h" + assume "y \ cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_shadow_root_ptr" + show False + using distinct_concat_map_E(1)[OF a1, of x y] + using \x |\| object_ptr_kinds h\ \y |\| object_ptr_kinds h\ + using \xa \ set |h2 \ get_child_nodes x|\<^sub>r\ \xa \ set |h2 \ get_child_nodes y|\<^sub>r\ + using \x \ y\ + by(auto simp add: children_eq2_h[OF \x \ cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_shadow_root_ptr\] + children_eq2_h[OF \y \ cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_shadow_root_ptr\]) + next + fix x :: "(_) node_ptr" + fix xa :: "(_) object_ptr" + fix xb :: "(_) document_ptr" + assume "(\x\fset (object_ptr_kinds h). set |h \ get_child_nodes x|\<^sub>r) \ +(\x\fset (document_ptr_kinds h). set |h2 \ get_disconnected_nodes x|\<^sub>r) = {}" + assume "x \ set |h2 \ get_child_nodes xa|\<^sub>r" + assume "xb |\| document_ptr_kinds h" + assume "x \ set |h2 \ get_disconnected_nodes xb|\<^sub>r" + assume "xa |\| object_ptr_kinds h" + assume "xa \ cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_shadow_root_ptr" + have "set |h \ get_child_nodes xa|\<^sub>r \ set |h2 \ get_disconnected_nodes xb|\<^sub>r = {}" + by (metis (no_types, lifting) CD.get_child_nodes_ok \xa |\| object_ptr_kinds h\ + \xb |\| document_ptr_kinds h\ assms(1) assms(2) assms(3) disconnected_nodes_eq2_h + is_OK_returns_result_E local.get_disconnected_nodes_ok + local.heap_is_wellformed_children_disc_nodes_different local.known_ptrs_known_ptr select_result_I2) + then + show "False" + using \x \ set |h2 \ get_child_nodes xa|\<^sub>r\ \x \ set |h2 \ get_disconnected_nodes xb|\<^sub>r\ + \xa \ cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_shadow_root_ptr\ children_eq2_h by auto + qed + + then have "CD.a_distinct_lists h3" + by(auto simp add: CD.a_distinct_lists_def disconnected_nodes_eq2_h2 document_ptr_kinds_eq_h2 + children_eq2_h2 object_ptr_kinds_eq_h2)[1] + then have "CD.a_distinct_lists h'" + by(auto simp add: CD.a_distinct_lists_def disconnected_nodes_eq2_h3 children_eq2_h3 + object_ptr_kinds_eq_h3 document_ptr_kinds_eq_h3 intro!: distinct_concat_map_I) + + have "CD.a_owner_document_valid h" + using \heap_is_wellformed h\ by (simp add: heap_is_wellformed_def CD.heap_is_wellformed_def) + then have "CD.a_owner_document_valid h'" + (* using disc_nodes_h3 \document_ptr |\| document_ptr_kinds h\ *) + apply(simp add: CD.a_owner_document_valid_def) + apply(simp add: object_ptr_kinds_eq_h object_ptr_kinds_eq_h3 ) + apply(simp add: object_ptr_kinds_eq_h2) + apply(simp add: document_ptr_kinds_eq_h document_ptr_kinds_eq_h3 ) + apply(simp add: document_ptr_kinds_eq_h2) + apply(simp add: node_ptr_kinds_eq_h node_ptr_kinds_eq_h3 ) + apply(simp add: node_ptr_kinds_eq_h2 node_ptr_kinds_eq_h ) + apply(auto simp add: children_eq2_h2[symmetric] children_eq2_h3[symmetric] + disconnected_nodes_eq2_h + disconnected_nodes_eq2_h2 disconnected_nodes_eq2_h3)[1] + by (metis CD.get_child_nodes_ok CD.get_child_nodes_ptr_in_heap + \cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_shadow_root_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r\ assms(2) assms(3) + children_eq2_h children_eq_h document_ptr_kinds_eq_h finite_set_in is_OK_returns_result_I + l_ptr_kinds_M.ptr_kinds_ptr_kinds_M local.known_ptrs_known_ptr object_ptr_kinds_M_def + returns_result_select_result) + + have shadow_root_eq_h: + "\character_data_ptr shadow_root_opt. h \ get_shadow_root character_data_ptr \\<^sub>r shadow_root_opt = +h2 \ get_shadow_root character_data_ptr \\<^sub>r shadow_root_opt" + using get_shadow_root_reads h2 get_shadow_root_new_shadow_root[rotated, OF h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + using local.get_shadow_root_locs_impl new_shadow_root_ptr apply blast + using local.get_shadow_root_locs_impl new_shadow_root_ptr by blast + + + have shadow_root_eq_h2: + "\ptr' children. h2 \ get_shadow_root ptr' \\<^sub>r children = h3 \ get_shadow_root ptr' \\<^sub>r children" + using get_shadow_root_reads set_mode_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: set_mode_get_shadow_root) + have shadow_root_eq_h3: + "\ptr' children. element_ptr \ ptr' \ h3 \ get_shadow_root ptr' \\<^sub>r children = +h' \ get_shadow_root ptr' \\<^sub>r children" + using get_shadow_root_reads set_shadow_root_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: set_shadow_root_get_shadow_root_different_pointers) + have shadow_root_h3: "h' \ get_shadow_root element_ptr \\<^sub>r Some new_shadow_root_ptr" + using \type_wf h3\ h' local.set_shadow_root_get_shadow_root by blast + + + have "a_all_ptrs_in_heap h" + by (simp add: assms(1) local.a_all_ptrs_in_heap_def local.get_shadow_root_shadow_root_ptr_in_heap) + then have "a_all_ptrs_in_heap h2" + apply(auto simp add: a_all_ptrs_in_heap_def shadow_root_ptr_kinds_eq_h)[1] + using returns_result_eq shadow_root_eq_h by fastforce + then have "a_all_ptrs_in_heap h3" + apply(auto simp add: a_all_ptrs_in_heap_def shadow_root_ptr_kinds_eq_h2)[1] + using shadow_root_eq_h2 by blast + then have "a_all_ptrs_in_heap h'" + apply(auto simp add: a_all_ptrs_in_heap_def shadow_root_ptr_kinds_eq_h3)[1] + apply(case_tac "shadow_root_ptr = new_shadow_root_ptr") + using h2 new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_ptr_in_heap new_shadow_root_ptr shadow_root_ptr_kinds_eq_h2 apply blast + using \type_wf h3\ h' local.set_shadow_root_get_shadow_root returns_result_eq shadow_root_eq_h3 + apply fastforce + done + + have "a_distinct_lists h" + using assms(1) + by (simp add: heap_is_wellformed_def) + then have "a_distinct_lists h2" + apply(auto simp add: a_distinct_lists_def character_data_ptr_kinds_eq_h)[1] + apply(auto simp add: distinct_insort intro!: distinct_concat_map_I split: option.splits)[1] + by (metis \type_wf h2\ assms(1) assms(2) local.get_shadow_root_ok local.shadow_root_same_host + returns_result_select_result shadow_root_eq_h) + then have "a_distinct_lists h3" + by(auto simp add: a_distinct_lists_def element_ptr_kinds_eq_h2 + select_result_eq[OF shadow_root_eq_h2]) + then have "a_distinct_lists h'" + apply(auto simp add: a_distinct_lists_def element_ptr_kinds_eq_h3 + select_result_eq[OF shadow_root_eq_h3])[1] + apply(auto simp add: distinct_insort intro!: distinct_concat_map_I split: option.splits)[1] + by (smt \type_wf h3\ assms(1) assms(2) h' h2 local.get_shadow_root_ok + local.get_shadow_root_shadow_root_ptr_in_heap local.set_shadow_root_get_shadow_root + local.shadow_root_same_host new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_ptr_not_in_heap new_shadow_root_ptr + returns_result_select_result select_result_I2 shadow_root_eq_h shadow_root_eq_h2 shadow_root_eq_h3) + + + have "a_shadow_root_valid h" + using assms(1) + by (simp add: heap_is_wellformed_def) + then + have "a_shadow_root_valid h'" + proof(unfold a_shadow_root_valid_def; safe) + fix shadow_root_ptr + assume "\shadow_root_ptr\fset (shadow_root_ptr_kinds h). \host\fset (element_ptr_kinds h). +|h \ get_tag_name host|\<^sub>r \ safe_shadow_root_element_types \ +|h \ get_shadow_root host|\<^sub>r = Some shadow_root_ptr" + assume "a_shadow_root_valid h" + assume "shadow_root_ptr \ fset (shadow_root_ptr_kinds h')" + show "\host\fset (element_ptr_kinds h'). +|h' \ get_tag_name host|\<^sub>r \ safe_shadow_root_element_types \ |h' \ get_shadow_root host|\<^sub>r = +Some shadow_root_ptr" + proof (cases "shadow_root_ptr = new_shadow_root_ptr") + case True + have "element_ptr \ fset (element_ptr_kinds h')" + by (simp add: \element_ptr |\| element_ptr_kinds h\ element_ptr_kinds_eq_h + element_ptr_kinds_eq_h2 element_ptr_kinds_eq_h3) + moreover have "|h' \ get_tag_name element_ptr|\<^sub>r \ safe_shadow_root_element_types" + by (smt \\thesis. (\h2 h3 new_shadow_root_ptr element_tag_name. +\h \ get_tag_name element_ptr \\<^sub>r element_tag_name; +element_tag_name \ safe_shadow_root_element_types; +h \ get_shadow_root element_ptr \\<^sub>r None; h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h2; +h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr; h2 \ set_mode new_shadow_root_ptr new_mode \\<^sub>h h3; +h3 \ set_shadow_root element_ptr (Some new_shadow_root_ptr) \\<^sub>h h'\ \ thesis) \ thesis\ + select_result_I2 tag_name_eq2_h tag_name_eq2_h2 tag_name_eq2_h3) + moreover have "|h' \ get_shadow_root element_ptr|\<^sub>r = Some shadow_root_ptr" + using shadow_root_h3 + by (simp add: True) + ultimately + show ?thesis + by meson + next + case False + then obtain host where host: "host \ fset (element_ptr_kinds h)" and + "|h \ get_tag_name host|\<^sub>r \ safe_shadow_root_element_types" and + "|h \ get_shadow_root host|\<^sub>r = Some shadow_root_ptr" + using \shadow_root_ptr \ fset (shadow_root_ptr_kinds h')\ + using \\shadow_root_ptr\fset (shadow_root_ptr_kinds h). \host\fset (element_ptr_kinds h). +|h \ get_tag_name host|\<^sub>r \ safe_shadow_root_element_types \ +|h \ get_shadow_root host|\<^sub>r = Some shadow_root_ptr\ + apply(simp add: shadow_root_ptr_kinds_eq_h3 shadow_root_ptr_kinds_eq_h2 + shadow_root_ptr_kinds_eq_h) + by (meson finite_set_in) + moreover have "host \ element_ptr" + using calculation(3) prev_shadow_root by auto + ultimately show ?thesis + using element_ptr_kinds_eq_h3 element_ptr_kinds_eq_h2 element_ptr_kinds_eq_h + by (smt \type_wf h'\ assms(2) finite_set_in local.get_shadow_root_ok returns_result_eq + returns_result_select_result shadow_root_eq_h shadow_root_eq_h2 shadow_root_eq_h3 tag_name_eq2_h + tag_name_eq2_h2 tag_name_eq2_h3) + qed + qed + + + have "a_host_shadow_root_rel h = a_host_shadow_root_rel h2" + by(auto simp add: a_host_shadow_root_rel_def element_ptr_kinds_eq_h + select_result_eq[OF shadow_root_eq_h]) + have "a_host_shadow_root_rel h2 = a_host_shadow_root_rel h3" + by(auto simp add: a_host_shadow_root_rel_def element_ptr_kinds_eq_h2 + select_result_eq[OF shadow_root_eq_h2]) + have "a_host_shadow_root_rel h' = {(cast element_ptr, cast new_shadow_root_ptr)} \ +a_host_shadow_root_rel h3" + apply(auto simp add: a_host_shadow_root_rel_def element_ptr_kinds_eq_h3 )[1] + apply(case_tac "element_ptr \ aa") + using select_result_eq[OF shadow_root_eq_h3] apply (simp add: image_iff) + using select_result_eq[OF shadow_root_eq_h3] + apply (metis (no_types, lifting) + \local.a_host_shadow_root_rel h = local.a_host_shadow_root_rel h2\ + \local.a_host_shadow_root_rel h2 = local.a_host_shadow_root_rel h3\ \type_wf h3\ + host_shadow_root_rel_def local.get_shadow_root_impl local.get_shadow_root_ok + option.distinct(1) prev_shadow_root returns_result_select_result) + apply (metis (mono_tags, lifting) \\ptr'. (\x. element_ptr \ ptr') \ +|h3 \ get_shadow_root ptr'|\<^sub>r = |h' \ get_shadow_root ptr'|\<^sub>r\ case_prod_conv image_iff + is_OK_returns_result_I mem_Collect_eq option.inject returns_result_eq + returns_result_select_result shadow_root_h3) + using element_ptr_kinds_eq_h3 local.get_shadow_root_ptr_in_heap shadow_root_h3 apply fastforce + using Shadow_DOM.a_host_shadow_root_rel_def \\ptr'. (\x. element_ptr \ ptr') \ +|h3 \ get_shadow_root ptr'|\<^sub>r = |h' \ get_shadow_root ptr'|\<^sub>r\ \type_wf h3\ case_prodE case_prodI + host_shadow_root_rel_shadow_root image_iff local.get_shadow_root_impl local.get_shadow_root_ok + mem_Collect_eq option.discI prev_shadow_root returns_result_select_result select_result_I2 + shadow_root_eq_h shadow_root_eq_h2 + apply(auto)[1] + by (smt case_prodI mem_Collect_eq option.distinct(1) pair_imageI returns_result_eq returns_result_select_result) + have "acyclic (parent_child_rel h \ a_host_shadow_root_rel h)" + using \heap_is_wellformed h\ + by (simp add: heap_is_wellformed_def) + have "parent_child_rel h \ a_host_shadow_root_rel h = +parent_child_rel h2 \ a_host_shadow_root_rel h2" + using \local.a_host_shadow_root_rel h = local.a_host_shadow_root_rel h2\ + \parent_child_rel h = parent_child_rel h2\ by auto + have "parent_child_rel h2 \ a_host_shadow_root_rel h2 = +parent_child_rel h3 \ a_host_shadow_root_rel h3" + using \local.a_host_shadow_root_rel h2 = local.a_host_shadow_root_rel h3\ + \parent_child_rel h2 = parent_child_rel h3\ by auto + have "parent_child_rel h' \ a_host_shadow_root_rel h' = +{(cast element_ptr, cast new_shadow_root_ptr)} \ parent_child_rel h3 \ a_host_shadow_root_rel h3" + by (simp add: \local.a_host_shadow_root_rel h' = +{(cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r element_ptr, cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_shadow_root_ptr)} \ +local.a_host_shadow_root_rel h3\ \parent_child_rel h3 = parent_child_rel h'\) + + have "\a b. (a, b) \ parent_child_rel h3 \ a \ cast new_shadow_root_ptr" + using CD.parent_child_rel_parent_in_heap \parent_child_rel h = parent_child_rel h2\ + \parent_child_rel h2 = parent_child_rel h3\ document_ptr_kinds_commutes + by (metis h2 new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_ptr_not_in_heap new_shadow_root_ptr shadow_root_ptr_kinds_commutes) + moreover + have "\a b. (a, b) \ a_host_shadow_root_rel h3 \ a \ cast new_shadow_root_ptr" + using shadow_root_eq_h2 + by(auto simp add: a_host_shadow_root_rel_def) + moreover + have "cast new_shadow_root_ptr \ {x. (x, cast element_ptr) \ (parent_child_rel h3 \ +a_host_shadow_root_rel h3)\<^sup>*}" + by (metis (no_types, lifting) UnE calculation(1) calculation(2) + cast_shadow_root_ptr_not_node_ptr(1) converse_rtranclE mem_Collect_eq) + moreover + have "acyclic (parent_child_rel h3 \ a_host_shadow_root_rel h3)" + using \acyclic (parent_child_rel h \ local.a_host_shadow_root_rel h)\ + \parent_child_rel h \ local.a_host_shadow_root_rel h = +parent_child_rel h2 \ local.a_host_shadow_root_rel h2\ \parent_child_rel h2 \ +local.a_host_shadow_root_rel h2 = parent_child_rel h3 \ local.a_host_shadow_root_rel h3\ + by auto + ultimately have "acyclic (parent_child_rel h' \ a_host_shadow_root_rel h')" + by(simp add: \parent_child_rel h' \ a_host_shadow_root_rel h' = +{(cast element_ptr, cast new_shadow_root_ptr)} \ parent_child_rel h3 \ +a_host_shadow_root_rel h3\) + + have "CD.a_heap_is_wellformed h'" + apply(simp add: CD.a_heap_is_wellformed_def) + by (simp add: \local.CD.a_acyclic_heap h'\ \local.CD.a_all_ptrs_in_heap h'\ + \local.CD.a_distinct_lists h'\ \local.CD.a_owner_document_valid h'\) + + show "heap_is_wellformed h' " + using \acyclic (parent_child_rel h' \ local.a_host_shadow_root_rel h')\ + by(simp add: heap_is_wellformed_def CD.heap_is_wellformed_impl \local.CD.a_heap_is_wellformed h'\ + \local.a_all_ptrs_in_heap h'\ \local.a_distinct_lists h'\ \local.a_shadow_root_valid h'\) +qed +end + +interpretation l_attach_shadow_root_wf?: l_attach_shadow_root_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr known_ptrs type_wf + get_child_nodes get_child_nodes_locs get_disconnected_nodes get_disconnected_nodes_locs + heap_is_wellformed parent_child_rel set_tag_name set_tag_name_locs set_disconnected_nodes + set_disconnected_nodes_locs create_element get_shadow_root get_shadow_root_locs get_tag_name + get_tag_name_locs heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host get_host_locs get_disconnected_document + get_disconnected_document_locs set_val set_val_locs create_character_data DocumentClass.known_ptr + DocumentClass.type_wf set_shadow_root set_shadow_root_locs set_mode set_mode_locs attach_shadow_root + by(auto simp add: l_attach_shadow_root_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_attach_shadow_root_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +end diff --git a/Shadow_DOM/Shadow_DOM_Tests.thy b/Shadow_DOM/Shadow_DOM_Tests.thy new file mode 100644 index 0000000..bff0673 --- /dev/null +++ b/Shadow_DOM/Shadow_DOM_Tests.thy @@ -0,0 +1,42 @@ +(*********************************************************************************** + * Copyright (c) 2016-2020 The University of Sheffield, UK + * 2019-2020 University of Exeter, UK + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-2-Clause + ***********************************************************************************) + +section\Shadow DOM Tests\ + +theory Shadow_DOM_Tests + imports + "tests/slots" + "tests/slots_fallback" + "tests/Shadow_DOM_Document_adoptNode" + "tests/Shadow_DOM_Document_getElementById" + "tests/Shadow_DOM_Node_insertBefore" + "tests/Shadow_DOM_Node_removeChild" +begin +end diff --git a/Shadow_DOM/classes/ShadowRootClass.thy b/Shadow_DOM/classes/ShadowRootClass.thy new file mode 100644 index 0000000..e677614 --- /dev/null +++ b/Shadow_DOM/classes/ShadowRootClass.thy @@ -0,0 +1,460 @@ +(*********************************************************************************** + * Copyright (c) 2016-2020 The University of Sheffield, UK + * 2019-2020 University of Exeter, UK + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************************\***) + +section \The Shadow DOM Data Model\ + +theory ShadowRootClass + imports + Core_DOM.ShadowRootPointer + Core_DOM.DocumentClass +begin + +subsection \ShadowRoot\ + +datatype shadow_root_mode = Open | Closed +record ('node_ptr, 'element_ptr, 'character_data_ptr) RShadowRoot = RObject + + nothing :: unit + mode :: shadow_root_mode + child_nodes :: "('node_ptr, 'element_ptr, 'character_data_ptr) node_ptr list" +type_synonym ('node_ptr, 'element_ptr, 'character_data_ptr, 'ShadowRoot) ShadowRoot + = "('node_ptr, 'element_ptr, 'character_data_ptr, 'ShadowRoot option) RShadowRoot_scheme" +register_default_tvars "('node_ptr, 'element_ptr, 'character_data_ptr, 'ShadowRoot) ShadowRoot" +type_synonym ('node_ptr, 'element_ptr, 'character_data_ptr, 'shadow_root_ptr, 'Object, 'Node, + 'Element, 'CharacterData, 'Document, + 'ShadowRoot) Object + = "('node_ptr, 'element_ptr, 'character_data_ptr, 'shadow_root_ptr, ('node_ptr, 'element_ptr, +'character_data_ptr, 'ShadowRoot option) + RShadowRoot_ext + 'Object, 'Node, 'Element, 'CharacterData, 'Document) Object" +register_default_tvars "('node_ptr, 'element_ptr, 'character_data_ptr, 'shadow_root_ptr, 'Object, +'Node, 'Element, 'CharacterData, + 'Document, 'ShadowRoot) Object" + +type_synonym ('object_ptr, 'node_ptr, 'element_ptr, 'character_data_ptr, 'document_ptr, + 'shadow_root_ptr, 'Object, 'Node, + 'Element, 'CharacterData, 'Document, 'ShadowRoot) heap + = "('object_ptr, 'node_ptr, 'element_ptr, 'character_data_ptr, 'document_ptr, 'shadow_root_ptr, +('node_ptr, 'element_ptr, + 'character_data_ptr, 'ShadowRoot option) RShadowRoot_ext + 'Object, 'Node, 'Element, +'CharacterData, 'Document) heap" +register_default_tvars "('object_ptr, 'node_ptr, 'element_ptr, 'character_data_ptr, 'document_ptr, +'shadow_root_ptr, 'Object, + 'Node, 'Element, 'CharacterData, 'Document, 'ShadowRoot) heap" +type_synonym "heap\<^sub>f\<^sub>i\<^sub>n\<^sub>a\<^sub>l" = "(unit, unit, unit, unit, unit, unit, unit, unit, unit, unit, unit, unit) heap" + + + +definition shadow_root_ptr_kinds :: "(_) heap \ (_) shadow_root_ptr fset" + where + "shadow_root_ptr_kinds heap = +the |`| (cast |`| (ffilter is_shadow_root_ptr_kind (object_ptr_kinds heap)))" + +lemma shadow_root_ptr_kinds_simp [simp]: + "shadow_root_ptr_kinds (Heap (fmupd (cast shadow_root_ptr) shadow_root (the_heap h))) = +{|shadow_root_ptr|} |\| shadow_root_ptr_kinds h" + apply(auto simp add: shadow_root_ptr_kinds_def)[1] + by force + +definition shadow_root_ptrs :: "(_) heap \ (_) shadow_root_ptr fset" + where + "shadow_root_ptrs heap = ffilter is_shadow_root_ptr (shadow_root_ptr_kinds heap)" + +definition cast\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t :: "(_) Object \ (_) ShadowRoot option" + where + "cast\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t obj = (case RObject.more obj of + Inr (Inr (Inl shadow_root)) \ Some (RObject.extend (RObject.truncate obj) shadow_root) + | _ \ None)" +adhoc_overloading cast cast\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t + +definition cast\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t:: "(_) ShadowRoot \ (_) Object" + where + "cast\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t shadow_root = +(RObject.extend (RObject.truncate shadow_root) (Inr (Inr (Inl (RObject.more shadow_root)))))" +adhoc_overloading cast cast\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t + +definition is_shadow_root_kind :: "(_) Object \ bool" + where + "is_shadow_root_kind ptr \ cast\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t ptr \ None" + +lemma shadow_root_ptr_kinds_heap_upd [simp]: + "shadow_root_ptr_kinds (Heap (fmupd (cast shadow_root_ptr) shadow_root (the_heap h))) = +{|shadow_root_ptr|} |\| shadow_root_ptr_kinds h" + apply(auto simp add: shadow_root_ptr_kinds_def)[1] + by force + +lemma shadow_root_ptr_kinds_commutes [simp]: + "cast shadow_root_ptr |\| object_ptr_kinds h \ shadow_root_ptr |\| shadow_root_ptr_kinds h" + apply(auto simp add: object_ptr_kinds_def shadow_root_ptr_kinds_def)[1] + by (metis (no_types, lifting) shadow_root_ptr_casts_commute2 shadow_root_ptr_shadow_root_ptr_cast + ffmember_filter fimage_eqI + fset.map_comp option.sel) + +definition get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t :: "(_) shadow_root_ptr \ (_) heap \ (_) ShadowRoot option" + where + "get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h = Option.bind (get (cast shadow_root_ptr) h) cast" +adhoc_overloading get get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t + +locale l_type_wf_def\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t +begin +definition a_type_wf :: "(_) heap \ bool" + where + "a_type_wf h = (DocumentClass.type_wf h \ (\shadow_root_ptr \ fset (shadow_root_ptr_kinds h). +get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h \ None))" +end +global_interpretation l_type_wf_def\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t defines type_wf = a_type_wf . +lemmas type_wf_defs = a_type_wf_def + +locale l_type_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t = l_type_wf type_wf for type_wf :: "((_) heap \ bool)" + + assumes type_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t: "type_wf h \ ShadowRootClass.type_wf h" + +sublocale l_type_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t \ l_type_wf\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t + apply(unfold_locales) + by (metis (full_types) ShadowRootClass.type_wf_def a_type_wf_def l_type_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_axioms + l_type_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) + +lemma type_wf_implies_previous: "type_wf h \ DocumentClass.type_wf h" + by(simp add: type_wf_defs) + +locale l_get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_lemmas = l_type_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t +begin +sublocale l_get\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t_lemmas by unfold_locales +lemma get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_type_wf: + assumes "type_wf h" + shows "shadow_root_ptr |\| shadow_root_ptr_kinds h \ get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h \ None" + using l_type_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_axioms assms + apply(simp add: type_wf_defs get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def l_type_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) + by (metis is_none_bind is_none_simps(1) is_none_simps(2) local.get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_type_wf notin_fset + shadow_root_ptr_kinds_commutes) +end + +global_interpretation l_get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_lemmas type_wf by unfold_locales + +definition put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t :: "(_) shadow_root_ptr \ (_) ShadowRoot \ (_) heap \ (_) heap" + where + "put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr shadow_root = put (cast shadow_root_ptr) (cast shadow_root)" +adhoc_overloading put put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t + +lemma put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ptr_in_heap: + assumes "put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr shadow_root h = h'" + shows "shadow_root_ptr |\| shadow_root_ptr_kinds h'" + using assms + unfolding put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def + by (metis shadow_root_ptr_kinds_commutes put\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_ptr_in_heap) + +lemma put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_put_ptrs: + assumes "put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr shadow_root h = h'" + shows "object_ptr_kinds h' = object_ptr_kinds h |\| {|cast shadow_root_ptr|}" + using assms + by (simp add: put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def put\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_put_ptrs) + + +lemma cast\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_inject [simp]: "cast\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x = cast\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t y \ x = y" + apply(simp add: cast\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def RObject.extend_def) + by (metis (full_types) RObject.surjective old.unit.exhaust) + +lemma cast\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_none [simp]: + "cast\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t obj = None \ \ (\shadow_root. cast\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t shadow_root = obj)" + apply(auto simp add: cast\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def cast\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def RObject.extend_def + split: sum.splits)[1] + by (metis (full_types) RObject.select_convs(2) RObject.surjective old.unit.exhaust) + +lemma cast\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_some [simp]: + "cast\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t obj = Some shadow_root \ cast shadow_root = obj" + by(auto simp add: cast\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def cast\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def RObject.extend_def split: sum.splits) + +lemma cast\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_inv [simp]: "cast\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>2\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t (cast\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t shadow_root) = Some shadow_root" + by simp + +lemma cast_shadow_root_not_node [simp]: + "cast\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t shadow_root \ cast\<^sub>N\<^sub>o\<^sub>d\<^sub>e\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t node" + "cast\<^sub>N\<^sub>o\<^sub>d\<^sub>e\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t node \ cast\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t shadow_root" + by(auto simp add: cast\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def cast\<^sub>N\<^sub>o\<^sub>d\<^sub>e\<^sub>2\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def RObject.extend_def) + + +lemma get_shadow_root_ptr_simp1 [simp]: + "get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr (put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr shadow_root h) = Some shadow_root" + by(auto simp add: get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) +lemma get_shadow_root_ptr_simp2 [simp]: + "shadow_root_ptr \ shadow_root_ptr' + \ get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr (put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr' shadow_root h) = +get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h" + by(auto simp add: get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) + +lemma get_shadow_root_ptr_simp3 [simp]: + "get\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t element_ptr (put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr f h) = get\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t element_ptr h" + by(auto simp add: get\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_def get\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) +lemma get_shadow_root_ptr_simp4 [simp]: + "get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr (put\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t element_ptr f h) = get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h" + by(auto simp add: get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def put\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_def put\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def) +lemma get_shadow_root_ptr_simp5 [simp]: + "get\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a character_data_ptr (put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr f h) = get\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a character_data_ptr h" + by(auto simp add: get\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a_def get\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) +lemma get_shadow_root_ptr_simp6 [simp]: + "get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr (put\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a character_data_ptr f h) = get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h" + by(auto simp add: get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def put\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a_def put\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def) +lemma get_shadow_root_ptr_simp7 [simp]: + "get\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t document_ptr (put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr f h) = get\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t document_ptr h" + by(auto simp add: get\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t_def get\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) +lemma get_shadow_root_ptr_simp8 [simp]: + "get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr (put\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t document_ptr f h) = get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h" + by(auto simp add: get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def put\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t_def put\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def) + +lemma new\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t [simp]: + assumes "new\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t h = (new_element_ptr, h')" + shows "get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t ptr h = get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t ptr h'" + using assms + by(auto simp add: new\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_def Let_def) + +lemma new\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a_get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t [simp]: + assumes "new\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a h = (new_character_data_ptr, h')" + shows "get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t ptr h = get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t ptr h'" + using assms + by(auto simp add: new\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a_def Let_def) + +lemma new\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t_get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t [simp]: + assumes "new\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t h = (new_document_ptr, h')" + shows "get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t ptr h = get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t ptr h'" + using assms + by(auto simp add: new\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t_def Let_def) + + +abbreviation "create_shadow_root_obj mode_arg child_nodes_arg + \ \ RObject.nothing = (), RShadowRoot.nothing = (), mode = mode_arg, +RShadowRoot.child_nodes = child_nodes_arg, \ = None \" + +definition new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t :: "(_)heap \ ((_) shadow_root_ptr \ (_) heap)" + where + "new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t h = (let new_shadow_root_ptr = +shadow_root_ptr.Ref (Suc (fMax (shadow_root_ptr.the_ref |`| (shadow_root_ptrs h)))) in + (new_shadow_root_ptr, put new_shadow_root_ptr (create_shadow_root_obj Open []) h))" + +lemma new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ptr_in_heap: + assumes "new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t h = (new_shadow_root_ptr, h')" + shows "new_shadow_root_ptr |\| shadow_root_ptr_kinds h'" + using assms + unfolding new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def Let_def + using put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ptr_in_heap by blast + +lemma new_shadow_root_ptr_new: + "shadow_root_ptr.Ref (Suc (fMax (finsert 0 (shadow_root_ptr.the_ref |`| shadow_root_ptrs h)))) |\| +shadow_root_ptrs h" + by (metis Suc_n_not_le_n shadow_root_ptr.sel(1) fMax_ge fimage_finsert finsertI1 finsertI2 set_finsert) + +lemma new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ptr_not_in_heap: + assumes "new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t h = (new_shadow_root_ptr, h')" + shows "new_shadow_root_ptr |\| shadow_root_ptr_kinds h" + using assms + unfolding new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def + by (metis Pair_inject shadow_root_ptrs_def fMax_finsert fempty_iff ffmember_filter + fimage_is_fempty is_shadow_root_ptr_ref max_0L new_shadow_root_ptr_new) + +lemma new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_new_ptr: + assumes "new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t h = (new_shadow_root_ptr, h')" + shows "object_ptr_kinds h' = object_ptr_kinds h |\| {|cast new_shadow_root_ptr|}" + using assms + by (metis Pair_inject new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_put_ptrs) + +lemma new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_is_shadow_root_ptr: + assumes "new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t h = (new_shadow_root_ptr, h')" + shows "is_shadow_root_ptr new_shadow_root_ptr" + using assms + by(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def Let_def) + + +lemma new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t [simp]: + assumes "new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t h = (new_shadow_root_ptr, h')" + assumes "ptr \ cast new_shadow_root_ptr" + shows "get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr h = get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr h'" + using assms + by(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def Let_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) + +lemma new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_get\<^sub>N\<^sub>o\<^sub>d\<^sub>e [simp]: + assumes "new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t h = (new_shadow_root_ptr, h')" + shows "get\<^sub>N\<^sub>o\<^sub>d\<^sub>e ptr h = get\<^sub>N\<^sub>o\<^sub>d\<^sub>e ptr h'" + using assms + apply(simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def Let_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) + by(auto simp add: get\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def) + +lemma new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_get\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t [simp]: + assumes "new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t h = (new_shadow_root_ptr, h')" + shows "get\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t ptr h = get\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t ptr h'" + using assms + by(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def Let_def) + +lemma new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_get\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a [simp]: + assumes "new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t h = (new_shadow_root_ptr, h')" + shows "get\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a ptr h = get\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a ptr h'" + using assms + by(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def Let_def) + +lemma new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_get\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t [simp]: + assumes "new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t h = (new_shadow_root_ptr, h')" + shows "get\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t ptr h = get\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t ptr h'" + using assms + apply(simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def Let_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) + by(auto simp add: get\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t_def) + +lemma new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t [simp]: + assumes "new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t h = (new_shadow_root_ptr, h')" + assumes "ptr \ new_shadow_root_ptr" + shows "get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t ptr h = get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t ptr h'" + using assms + by(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def Let_def) + + +locale l_known_ptr\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t +begin +definition a_known_ptr :: "(_) object_ptr \ bool" + where + "a_known_ptr ptr = (known_ptr ptr \ is_shadow_root_ptr ptr)" + +lemma known_ptr_not_shadow_root_ptr: "a_known_ptr ptr \ \is_shadow_root_ptr ptr \ known_ptr ptr" + by(simp add: a_known_ptr_def) +lemma known_ptr_new_shadow_root_ptr: "a_known_ptr ptr \ \known_ptr ptr \ is_shadow_root_ptr ptr" + using l_known_ptr\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t.known_ptr_not_shadow_root_ptr by blast + +end +global_interpretation l_known_ptr\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t defines known_ptr = a_known_ptr . +lemmas known_ptr_defs = a_known_ptr_def + +locale l_known_ptrs\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t = l_known_ptr known_ptr for known_ptr :: "(_) object_ptr \ bool" +begin +definition a_known_ptrs :: "(_) heap \ bool" + where + "a_known_ptrs h = (\ptr \ fset (object_ptr_kinds h). known_ptr ptr)" + +lemma known_ptrs_known_ptr: "a_known_ptrs h \ ptr |\| object_ptr_kinds h \ known_ptr ptr" + apply(simp add: a_known_ptrs_def) + using notin_fset by fastforce + +lemma known_ptrs_preserved: + "object_ptr_kinds h = object_ptr_kinds h' \ a_known_ptrs h = a_known_ptrs h'" + by(auto simp add: a_known_ptrs_def) +lemma known_ptrs_subset: + "object_ptr_kinds h' |\| object_ptr_kinds h \ a_known_ptrs h \ a_known_ptrs h'" + by (simp add: less_eq_fset.rep_eq local.a_known_ptrs_def subsetD) +lemma known_ptrs_new_ptr: + "object_ptr_kinds h' = object_ptr_kinds h |\| {|new_ptr|} \ known_ptr new_ptr \ +a_known_ptrs h \ a_known_ptrs h'" + by(simp add: a_known_ptrs_def) +end +global_interpretation l_known_ptrs\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t known_ptr defines known_ptrs = a_known_ptrs . +lemmas known_ptrs_defs = a_known_ptrs_def + +lemma known_ptrs_is_l_known_ptrs [instances]: "l_known_ptrs known_ptr known_ptrs" + using known_ptrs_known_ptr known_ptrs_preserved l_known_ptrs_def known_ptrs_subset + known_ptrs_new_ptr + by blast + + +lemma shadow_root_get_put_1 [simp]: + "get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr (put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr shadow_root h) = Some shadow_root" + by(auto simp add: get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) +lemma shadow_root_different_get_put [simp]: + "shadow_root_ptr \ shadow_root_ptr' \ +get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr (put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr' shadow_root h) = get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h" + by(auto simp add: get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) + + +lemma shadow_root_get_put_2 [simp]: + "get\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t element_ptr (put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr f h) = get\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t element_ptr h" + by(auto simp add: get\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_def get\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) +lemma shadow_root_get_put_3 [simp]: + "get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t element_ptr (put\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t shadow_root_ptr f h) = get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t element_ptr h" + by(auto simp add: get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def put\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_def put\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def) +lemma shadow_root_get_put_4 [simp]: + "get\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a character_data_ptr (put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr f h) = get\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a character_data_ptr h" + by(auto simp add: get\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a_def get\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) +lemma shadow_root_get_put_5 [simp]: + "get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t character_data_ptr (put\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a shadow_root_ptr f h) = get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t character_data_ptr h" + by(auto simp add: get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def put\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a_def put\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def) +lemma shadow_root_get_put_6 [simp]: + "get\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t document_ptr (put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr f h) = get\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t document_ptr h" + by(auto simp add: get\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t_def get\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) +lemma shadow_root_get_put_7 [simp]: + "get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t document_ptr (put\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t shadow_root_ptr f h) = get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t document_ptr h" + by(auto simp add: get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def put\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t_def put\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def) + +lemma known_ptrs_implies: "DocumentClass.known_ptrs h \ ShadowRootClass.known_ptrs h" + by(auto simp add: DocumentClass.known_ptrs_defs DocumentClass.known_ptr_defs + ShadowRootClass.known_ptrs_defs ShadowRootClass.known_ptr_defs) + +definition delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t :: "(_) shadow_root_ptr \ (_) heap \ (_) heap option" where + "delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr = delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t (cast shadow_root_ptr)" + +lemma delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_pointer_removed: + assumes "delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t ptr h = Some h'" + shows "ptr |\| shadow_root_ptr_kinds h'" + using assms + by(auto simp add: delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_pointer_removed delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def shadow_root_ptr_kinds_def + split: if_splits) + +lemma delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_pointer_ptr_in_heap: + assumes "delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t ptr h = Some h'" + shows "ptr |\| shadow_root_ptr_kinds h" + using assms + apply(auto simp add: delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_pointer_ptr_in_heap delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def split: if_splits)[1] + using delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_pointer_ptr_in_heap + by fastforce + +lemma delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ok: + assumes "ptr |\| shadow_root_ptr_kinds h" + shows "delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t ptr h \ None" + using assms + by (simp add: delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_ok delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) + +lemma shadow_root_delete_get_1 [simp]: + "delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h = Some h' \ get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h' = None" + by(auto simp add: delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def split: if_splits) +lemma shadow_root_different_delete_get [simp]: + "shadow_root_ptr \ shadow_root_ptr' \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr' h = Some h' \ +get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h' = get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h" + by(auto simp add: delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def split: if_splits) + + +lemma shadow_root_delete_get_2 [simp]: + "delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h = Some h' \ object_ptr \ cast shadow_root_ptr \ +get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t object_ptr h' = get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t object_ptr h" + by(auto simp add: delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def split: if_splits) +lemma shadow_root_delete_get_3 [simp]: + "delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h = Some h' \ get\<^sub>N\<^sub>o\<^sub>d\<^sub>e node_ptr h' = get\<^sub>N\<^sub>o\<^sub>d\<^sub>e node_ptr h" + by(auto simp add: get\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def) +lemma shadow_root_delete_get_4 [simp]: + "delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h = Some h' \ get\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t element_ptr h' = get\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t element_ptr h" + by(simp add: get\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_def) +lemma shadow_root_delete_get_5 [simp]: + "delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h = Some h' \ +get\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a character_data_ptr h' = get\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a character_data_ptr h" + by(simp add: get\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a_def) +lemma shadow_root_delete_get_6 [simp]: + "delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h = Some h' \ get\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t document_ptr h' = get\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t document_ptr h" + by(simp add: get\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t_def) +lemma shadow_root_delete_get_7 [simp]: + "delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h = Some h' \ shadow_root_ptr' \ shadow_root_ptr \ +get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr' h' = get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr' h" + by(auto simp add: delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def split: if_splits) +end diff --git a/Shadow_DOM/document/root.bib b/Shadow_DOM/document/root.bib new file mode 100644 index 0000000..20591e9 --- /dev/null +++ b/Shadow_DOM/document/root.bib @@ -0,0 +1,518 @@ +@STRING{j-fac = "Formal Aspects of Computing" } +@STRING{pub-springer={Springer-Verlag} } +@STRING{pub-springer:adr={Heidelberg} } +@STRING{s-lncs = "Lecture Notes in Computer Science" } + +@Book{ nipkow.ea:isabelle:2002, + author = {Tobias Nipkow and Lawrence C. Paulson and Markus Wenzel}, + title = {Isabelle/HOL---A Proof Assistant for Higher-Order Logic}, + publisher = pub-springer, + address = pub-springer:adr, + series = s-lncs, + volume = 2283, + doi = {10.1007/3-540-45949-9}, + abstract = {This book is a self-contained introduction to interactive proof in higher-order logic (HOL), using + the proof assistant Isabelle2002. It is a tutorial for potential users rather than a monograph for + researchers. The book has three parts. + + 1. Elementary Techniques shows how to model functional programs in higher-order logic. Early examples + involve lists and the natural numbers. Most proofs are two steps long, consisting of induction on a + chosen variable followed by the auto tactic. But even this elementary part covers such advanced topics + as nested and mutual recursion. 2. Logic and Sets presents a collection of lower-level tactics that + you can use to apply rules selectively. It also describes Isabelle/HOL's treatment of sets, functions + and relations and explains how to define sets inductively. One of the examples concerns the theory of + model checking, and another is drawn from a classic textbook on formal languages. 3. Advanced Material + describes a variety of other topics. Among these are the real numbers, records and overloading. + Advanced techniques are described involving induction and recursion. A whole chapter is devoted to an + extended example: the verification of a security protocol. }, + year = 2002, + acknowledgement={brucker, 2007-02-19}, + bibkey = {nipkow.ea:isabelle:2002} +} + +@Misc{ dom-specification, + year = 2016, + month = {DOM Living Standard -- Last Updated 20 October 2016}, + day = 20, + url = {https://dom.spec.whatwg.org/}, + organization = {Web Hypertext Application Technology Working Group (WHATWG)}, + note = {An archived copy of the version from 20 October 2016 is available at + \url{https://git.logicalhacking.com/BrowserSecurity/fDOM-idl/}.} +} + +@InProceedings{ brucker.ea:core-dom:2018, + author = {Achim D. Brucker and Michael Herzberg}, + title = {A Formal Semantics of the Core {DOM} in {Isabelle/HOL}}, + booktitle = {Proceedings of the Web Programming, Design, Analysis, And Implementation (WPDAI) track at WWW 2018}, + location = {Lyon, France}, + url = {https://www.brucker.ch/bibliography/abstract/brucker.ea-fdom-2018}, + year = 2018, + abstract = {At its core, the Document Object Model (DOM) defines a tree-like data structure for representing + documents in general and HTML documents in particular. It forms the heart of any rendering engine of + modern web browsers. Formalizing the key concepts of the DOM is a pre-requisite for the formal + reasoning over client-side JavaScript programs as well as for the analysis of security concepts in + modern web browsers. In this paper, we present a formalization of the core DOM, with focus on the + node-tree and the operations defined on node-trees, in Isabelle/HOL. We use the formalization to + verify the functional correctness of the most important functions defined in the DOM standard. + Moreover, our formalization is (1) extensible, i.e., can be extended without the need of re-proving + already proven properties and (2) executable, i.e., we can generate executable code from our + specification. }, + keywords = {Document Object Model, DOM, Formal Semantics, Isabelle/HOL}, + classification= {conference}, + areas = {formal methods, software}, + public = {yes} +} + +@Article{ klein:operating:2009, + author = {Gerwin Klein}, + title = {Operating System Verification --- An Overview}, + journal = {S\={a}dhan\={a}}, + publisher = pub-springer, + year = 2009, + volume = 34, + number = 1, + month = feb, + pages = {27--69}, + abstract = {This paper gives a high-level introduction to the topic of formal, interactive, machine-checked + software verification in general, and the verification of operating systems code in particular. We + survey the state of the art, the advantages and limitations of machine-checked code proofs, and + describe two specific ongoing larger-scale verification projects in more detail.} +} + +@InProceedings{ gardner.ea:securing:2009, + author = {Ryan W. Gardner and Sujata Garera and Matthew W. Pagano and Matthew Green and Aviel D. Rubin}, + title = {Securing medical records on smart phones}, + booktitle = {ACM workshop on Security and privacy in medical and home-care systems (SPIMACS)}, + year = 2009, + isbn = {978-1-60558-790-5}, + pages = {31--40}, + location = {Chicago, Illinois, USA}, + doi = {10.1145/1655084.1655090}, + address = pub-acm:adr, + publisher = pub-acm, + abstract = {There is an inherent conflict between the desire to maintain privacy of one's medical records and the + need to make those records available during an emergency. To satisfy both objectives, we introduce a + flexible architecture for the secure storage of medical records on smart phones. In our system, a + person can view her records at any time, and emergency medical personnel can view the records as long + as the person is present (even if she is unconscious). Our solution allows for efficient revocation of + access rights and is robust against adversaries who can access the phone's storage offline.} +} + +@InProceedings{ raad.ea:dom:2016, + author = {Azalea Raad and Jos{\'{e}} Fragoso Santos and Philippa Gardner}, + title = {{DOM:} Specification and Client Reasoning}, + booktitle = {Programming Languages and Systems - 14th Asian Symposium, {APLAS} 2016, Hanoi, Vietnam, November + 21-23, 2016, Proceedings}, + pages = {401--422}, + year = 2016, + crossref = {igarashi:programming:2016}, + doi = {10.1007/978-3-319-47958-3_21}, + abstract = {We present an axiomatic specification of a key fragment of DOM using structural separation logic. + This specification allows us to develop modular reasoning about client programs that call the DOM.} +} + +@InProceedings{ bohannon.ea:featherweight:2010, + author = {Aaron Bohannon and Benjamin C. Pierce}, + title = {Featherweight {F}irefox: {F}ormalizing the Core of a Web Browser}, + booktitle = {Usenix Conference on Web Application Development (WebApps)}, + year = 2010, + month = jun, + url = {http://www.cis.upenn.edu/~bohannon/browser-model/}, + abstract = {We offer a formal specification of the core functionality of a web browser in the form of a + small-step operational semantics. The specification accurately models the asyn- chronous nature of web + browsers and covers the basic as- pects of windows, DOM trees, cookies, HTTP requests and responses, + user input, and a minimal scripting lan- guage with first-class functions, dynamic evaluation, and + AJAX requests. No security enforcement mechanisms are included{\^a}instead, the model is intended to + serve as a basis for formalizing and experimenting with different security policies and mechanisms. We + survey the most interesting design choices and discuss how our model re- lates to real web browsers.} +} + +@Proceedings{ joyce.ea:higher:1994, + editor = {Jeffrey J. Joyce and Carl-Johan H. Seger}, + title = {Higher Order Logic Theorem Proving and Its Applications (HUG)}, + booktitle = {Higher Order Logic Theorem Proving and Its Applications (HUG)}, + publisher = pub-springer, + address = pub-springer:adr, + series = s-lncs, + abstract = {Theorem proving based techniques for formal hardware verification have been evolving constantly and + researchers are getting able to reason about more complex issues than it was possible or practically + feasible in the past. It is often the case that a model of a system is built in a formal logic and + then reasoning about this model is carried out in the logic. Concern is growing on how to consistently + interface a model built in a formal logic with an informal CAD environment. Researchers have been + investigating how to define the formal semantics of hardware description languages so that one can + formally reason about models informally dealt with in a CAD environment. At the University of + Cambridge, the embedding of hardware description languages in a logic is classified in two categories: + deep embedding and shallow embedding. In this paper we argue that there are degrees of formality in + shallow embedding a language in a logic. The choice of the degree of formality is a trade-off between + the security of the embedding and the amount and complexity of the proof effort in the logic. We also + argue that the design of a language could consider this verifiability issue. There are choices in the + design of a language that can make it easier to improve the degree of formality, without implying + serious drawbacks for the CAD environment.}, + volume = 780, + year = 1994, + doi = {10.1007/3-540-57826-9}, + isbn = {3-540-57826-9}, + acknowledgement={brucker, 2007-02-19} +} + +@Misc{ whatwg:dom:2017, + key = {whatwg}, + author = {{WHATWG}}, + url = {https://dom.spec.whatwg.org/commit-snapshots/6253e53af2fbfaa6d25ad09fd54280d8083b2a97/}, + month = mar, + year = 2017, + day = 24, + title = {{DOM} -- Living Standard}, + note = {Last Updated 24 {March} 2017}, + institution = {WHATWG} +} + +@Misc{ whatwg:html:2017, + key = {whatwg}, + author = {{WHATWG}}, + url = {https://html.spec.whatwg.org/}, + month = apr, + year = 2017, + day = 13, + title = {{HTML} -- Living Standard}, + note = {Last Updated 13 {April} 2017}, + institution = {WHATWG} +} + +@Misc{ w3c:dom:2015, + key = {w3c}, + author = {{W3C}}, + url = {https://www.w3.org/TR/dom/}, + month = nov, + year = 2015, + day = 19, + title = {{W3C} {DOM4}}, + institution = {W3C} +} + +@Proceedings{ igarashi:programming:2016, + editor = {Atsushi Igarashi}, + title = {Programming Languages and Systems - 14th Asian Symposium, {APLAS} 2016, Hanoi, Vietnam, November + 21-23, 2016, Proceedings}, + series = {Lecture Notes in Computer Science}, + volume = 10017, + year = 2016, + doi = {10.1007/978-3-319-47958-3}, + isbn = {978-3-319-47957-6} +} + +@InProceedings{ gardner.ea:dom:2008, + author = {Philippa Gardner and Gareth Smith and Mark J. Wheelhouse and Uri Zarfaty}, + title = {{DOM:} Towards a Formal Specification}, + booktitle = {{PLAN-X} 2008, Programming Language Technologies for XML, An {ACM} {SIGPLAN} Workshop colocated with + {POPL} 2008, San Francisco, California, USA, January 9, 2008}, + year = 2008, + crossref = {plan-x:2008}, + url = {http://gemo.futurs.inria.fr/events/PLANX2008/papers/p18.pdf}, + abstract = {The W3C Document Object Model (DOM) specifies an XML up- date library. DOM is written in English, and + is therefore not compo- sitional and not complete. We provide a first step towards a compo- sitional + specification of DOM. Unlike DOM, we are able to work with a minimal set of commands and obtain a + complete reason- ing for straight-line code. Our work transfers O{\^a}Hearn, Reynolds and Yang{\^a}s + local Hoare reasoning for analysing heaps to XML, viewing XML as an in-place memory store as does DOM. + In par- ticular, we apply recent work by Calcagno, Gardner and Zarfaty on local Hoare reasoning about + a simple tree-update language to DOM, showing that our reasoning scales to DOM. Our reasoning not only + formally specifies a significant subset of DOM Core Level 1, but can also be used to verify e.g. + invariant properties of simple Javascript programs.} +} + +@InProceedings{ jang.ea:establishing:2012, + author = {Dongseok Jang and Zachary Tatlock and Sorin Lerner}, + title = {Establishing Browser Security Guarantees through Formal Shim Verification}, + booktitle = {Proceedings of the 21th {USENIX} Security Symposium, Bellevue, WA, USA, August 8-10, 2012}, + pages = {113--128}, + year = 2012, + crossref = {kohno:proceedings:2012}, + url = {https://www.usenix.org/conference/usenixsecurity12/technical-sessions/presentation/jang}, + abstract = { Web browsers mediate access to valuable private data in domains ranging from health care to banking. + Despite this critical role, attackers routinely exploit browser vulnerabilities to exfiltrate private + data and take over the un- derlying system. We present Q UARK , a browser whose kernel has been + implemented and verified in Coq. We give a specification of our kernel, show that the implementation + satisfies the specification, and finally show that the specification implies several security + properties, including tab non-interference, cookie integrity and confidentiality, and address bar + integrity. } +} + +@Proceedings{ kohno:proceedings:2012, + editor = {Tadayoshi Kohno}, + title = {Proceedings of the 21th {USENIX} Security Symposium, Bellevue, WA, USA, August 8-10, 2012}, + publisher = {{USENIX} Association}, + year = 2012, + timestamp = {Thu, 15 May 2014 09:12:27 +0200} +} + +@Proceedings{ plan-x:2008, + title = {{PLAN-X} 2008, Programming Language Technologies for XML, An {ACM} {SIGPLAN} Workshop colocated with + {POPL} 2008, San Francisco, California, USA, January 9, 2008}, + year = 2008, + timestamp = {Fri, 18 Jan 2008 13:01:04 +0100} +} + +@Article{ brucker.ea:extensible:2008-b, + abstract = {We present an extensible encoding of object-oriented data models into HOL. Our encoding is supported + by a datatype package that leverages the use of the shallow embedding technique to object-oriented + specification and programming languages. The package incrementally compiles an object-oriented data + model, i.e., a class model, to a theory containing object-universes, constructors, accessor functions, + coercions (casts) between dynamic and static types, characteristic sets, and co-inductive class + invariants. The package is conservative, i.e., all properties are derived entirely from constant + definitions, including the constraints over object structures. As an application, we use the package + for an object-oriented core-language called IMP++, for which we formally prove the correctness of a + Hoare-Logic with respect to a denotational semantics.}, + address = {Heidelberg}, + author = {Achim D. Brucker and Burkhart Wolff}, + doi = {10.1007/s10817-008-9108-3}, + issn = {0168-7433}, + issue = 3, + journal = {Journal of Automated Reasoning}, + keywords = {object-oriented data models, HOL, theorem proving, verification}, + language = {USenglish}, + pages = {219--249}, + pdf = {https://www.brucker.ch/bibliography/download/2008/brucker.ea-extensible-2008-b.pdf}, + publisher = {Springer-Verlag}, + title = {An Extensible Encoding of Object-oriented Data Models in HOL}, + url = {https://www.brucker.ch/bibliography/abstract/brucker.ea-extensible-2008-b}, + volume = 41, + year = 2008 +} + +@PhDThesis{ brucker:interactive:2007, + abstract = {We present a semantic framework for object-oriented specification languages. We develop this + framework as a conservative shallow embedding in Isabelle/HOL. Using only conservative extensions + guarantees by construction the consistency of our formalization. Moreover, we show how our framework + can be used to build an interactive proof environment, called HOL-OCL, for object-oriented + specifications in general and for UML/OCL in particular.\\\\Our main contributions are an extensible + encoding of object-oriented data structures in HOL, a datatype package for object-oriented + specifications, and the development of several equational and tableaux calculi for object-oriented + specifications. Further, we show that our formal framework can be the basis of a formal + machine-checked semantics for OCL that is compliant to the OCL 2.0 standard.}, + abstract_de = {In dieser Arbeit wird ein semantisches Rahmenwerk f{\"u}r objektorientierte Spezifikationen + vorgestellt. Das Rahmenwerk ist als konservative, flache Einbettung in Isabelle/HOL realisiert. Durch + die Beschr{\"a}nkung auf konservative Erweiterungen kann die logische Konsistenz der Einbettung + garantiert werden. Das semantische Rahmenwerk wird verwendet, um das interaktives Beweissystem HOL-OCL + f{\"u}r objektorientierte Spezifikationen im Allgemeinen und insbesondere f{\"u}r UML/OCL zu + entwickeln.\\\\Die Hauptbeitr{\"a}ge dieser Arbeit sind die Entwicklung einer erweiterbaren Kodierung + objektorientierter Datenstrukturen in HOL, ein Datentyp-Paket f{\"u}r objektorientierte + Spezifikationen und die Entwicklung verschiedener Kalk{\"u}le f{\"u}r objektorientierte + Spezifikationen. Zudem zeigen wir, wie das formale Rahmenwerk verwendet werden kann, um eine formale, + maschinell gepr{\"u}fte Semantik f{\"u}r OCL anzugeben, die konform zum Standard f{\"u}r OCL 2.0 ist.}, + author = {Achim D. Brucker}, + keywords = {OCL, UML, formal semantics, theorem proving, Isabelle, HOL-OCL}, + month = {mar}, + note = {ETH Dissertation No. 17097.}, + pdf = {https://www.brucker.ch/bibliography/download/2007/brucker-interactive-2007.pdf}, + school = {ETH Zurich}, + title = {An Interactive Proof Environment for Object-oriented Specifications}, + url = {https://www.brucker.ch/bibliography/abstract/brucker-interactive-2007}, + year = 2007 +} + +@InCollection{ brucker.ea:standard-compliance-testing:2018, + talk = {talk:brucker.ea:standard-compliance-testing:2018}, + abstract = {Most popular technologies are based on informal or semiformal standards that lack a rigid formal + semantics. Typical examples include web technologies such as the DOM or HTML, which are defined by the + Web Hypertext Application Technology Working Group (WHATWG) and the World Wide Web Consortium (W3C). + While there might be API specifications and test cases meant to assert the compliance of a certain + implementation, the actual standard is rarely accompanied by a formal model that would lend itself + for, e.g., verifying the security or safety properties of real systems. + + Even when such a formalization of a standard exists, two important questions arise: first, to what + extend does the formal model comply to the standard and, second, to what extend does the + implementation comply to the formal model and the assumptions made during the verification? In this + paper, we present an approach that brings all three involved artifacts - the (semi-)formal standard, + the formalization of the standard, and the implementations - closer together by combining + verification, symbolic execution, and specification based testing.}, + keywords = {standard compliance, compliance tests, DOM}, + location = {Toulouse, France}, + author = {Achim D. Brucker and Michael Herzberg}, + booktitle = {{TAP} 2018: Tests And Proofs}, + language = {USenglish}, + publisher = pub-springer, + address = pub-springer:adr, + series = s-lncs, + number = 10889, + editor = {Cathrine Dubois and Burkhart Wolff}, + title = {Formalizing (Web) Standards: An Application of Test and Proof}, + categories = {holtestgen, websecurity}, + classification= {conference}, + areas = {formal methods, software engineering}, + public = {yes}, + year = 2018, + doi = {10.1007/978-3-319-92994-1_9}, + pages = {159--166}, + isbn = {978-3-642-38915-3}, + pdf = {http://www.brucker.ch/bibliography/download/2018/brucker.ea-standard-compliance-testing-2018.pdf}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-standard-compliance-testing-2018} +} + +@InCollection{ brucker.ea:interactive:2005, + keywords = {symbolic test case generations, black box testing, white box testing, theorem proving, interactive + testing}, + abstract = {HOL-TestGen is a test environment for specification-based unit testing build upon the proof assistant + Isabelle/HOL\@. While there is considerable skepticism with regard to interactive theorem provers in + testing communities, we argue that they are a natural choice for (automated) symbolic computations + underlying systematic tests. This holds in particular for the development on non-trivial formal test + plans of complex software, where some parts of the overall activity require inherently guidance by a + test engineer. In this paper, we present the underlying methods for both black box and white box + testing in interactive unit test scenarios. HOL-TestGen can also be understood as a unifying technical + and conceptual framework for presenting and investigating the variety of unit test techniques in a + logically consistent way. }, + location = {Edinburgh}, + author = {Achim D. Brucker and Burkhart Wolff}, + booktitle = {Formal Approaches to Testing of Software}, + language = {USenglish}, + publisher = pub-springer, + address = pub-springer:adr, + series = s-lncs, + number = 3997, + doi = {10.1007/11759744_7}, + isbn = {3-540-25109-X}, + editor = {Wolfgang Grieskamp and Carsten Weise}, + pdf = {http://www.brucker.ch/bibliography/download/2005/brucker.ea-interactive-2005.pdf}, + project = {CSFMDOS}, + title = {Interactive Testing using {HOL}-{TestGen}}, + classification= {workshop}, + areas = {formal methods, software}, + categories = {holtestgen}, + year = 2005, + public = {yes}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-interactive-2005} +} + +@Article{ brucker.ea:theorem-prover:2012, + author = {Achim D. Brucker and Burkhart Wolff}, + journal = j-fac, + publisher = pub-springer, + address = pub-springer:adr, + language = {USenglish}, + categories = {holtestgen}, + title = {On Theorem Prover-based Testing}, + year = 2013, + issn = {0934-5043}, + pages = {683--721}, + volume = 25, + number = 5, + classification= {journal}, + areas = {formal methods, software}, + public = {yes}, + doi = {10.1007/s00165-012-0222-y}, + keywords = {test case generation, domain partitioning, test sequence, theorem proving, HOL-TestGen}, + abstract = {HOL-TestGen is a specification and test case generation environment extending the interactive theorem + prover Isabelle/HOL. As such, HOL-TestGen allows for an integrated workflow supporting interactive + theorem proving, test case generation, and test data generation. + + The HOL-TestGen method is two-staged: first, the original formula is partitioned into test cases by + transformation into a normal form called test theorem. Second, the test cases are analyzed for ground + instances (the test data) satisfying the constraints of the test cases. Particular emphasis is put on + the control of explicit test-hypotheses which can be proven over concrete programs. + + Due to the generality of the underlying framework, our system can be used for black-box unit, + sequence, reactive sequence and white-box test scenarios. Although based on particularly clean + theoretical foundations, the system can be applied for substantial case-studies. }, + pdf = {http://www.brucker.ch/bibliography/download/2012/brucker.ea-theorem-prover-2012.pdf}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-theorem-prover-2012} +} + +@Article{ brucker.ea:afp-core-dom:2018, + abstract = {In this AFP entry, we formalize the core of the Document Object Model (DOM). At its core, the DOM + defines a tree-like data structure for representing documents in general and HTML documents in + particular. It is the heart of any modern web browser. Formalizing the key concepts of the DOM is a + prerequisite for the formal reasoning over client-side JavaScript programs and for the analysis of + security concepts in modern web browsers. We present a formalization of the core DOM, with focus on + the node-tree and the operations defined on node-trees, in Isabelle/HOL. We use the formalization to + verify the functional correctness of the most important functions defined in the DOM standard. + Moreover, our formalization is 1) extensible, i.e., can be extended without the need of re-proving + already proven properties and 2) executable, i.e., we can generate executable code from our + specification.}, + author = {Achim D. Brucker and Michael Herzberg}, + date = {2018-12-26}, + file = {https://www.brucker.ch/bibliography/download/2018/brucker.ea-afp-core-dom-outline-2018.pdf}, + filelabel = {Outline}, + issn = {2150-914x}, + journal = {Archive of Formal Proofs}, + month = {dec}, + note = {\url{http://www.isa-afp.org/entries/Core_DOM.html}, Formal proof development}, + pdf = {https://www.brucker.ch/bibliography/download/2018/brucker.ea-afp-core-dom-2018.pdf}, + title = {The Core {DOM}}, + url = {https://www.brucker.ch/bibliography/abstract/brucker.ea-afp-core-dom-2018-a}, + year = 2018 +} + +@InCollection{ brucker.ea:web-components:2019, + abstract = {The trend towards ever more complex client-side web applications is unstoppable. Compared to + traditional software development, client-side web development lacks a well-established component + model, i.e., a method for easily and safely reusing already developed functionality. To address this + issue, the web community started to adopt shadow trees as part of the Document Object Model (DOM): + shadow trees allow developers to "partition" a DOM instance into parts that should be safely + separated, e.g., code modifying one part should not, unintentionally, affect other parts of the + DOM.\\\\While shadow trees provide the technical basis for defining web components, the DOM standard + neither defines the concept of web components nor specifies the safety properties that web components + should guarantee. Consequently, the standard also does not discuss how or even if the methods for + modifying the DOM respect component boundaries. In this paper, we present a formally verified model of + web components and define safety properties which ensure that different web components can only + interact with each other using well-defined interfaces. Moreover, our verification of the application + programming interface (API) of the DOM revealed numerous invariants that implementations of the DOM + API need to preserve to ensure the integrity of components.}, + address = {Heidelberg}, + author = {Achim D. Brucker and Michael Herzberg}, + booktitle = {Formal Aspects of Component Software (FACS)}, + doi = {10.1007/978-3-030-40914-2_3}, + editor = {Sung-Shik Jongmans and Farhad Arbab}, + isbn = {3-540-25109-X}, + keywords = {Web Component, Shadow Tree, DOM, Isabelle/HOL}, + language = {USenglish}, + location = {Amsterdam, The Netherlands}, + number = 12018, + pdf = {https://www.brucker.ch/bibliography/download/2019/brucker.ea-web-components-2019.pdf}, + publisher = {Springer-Verlag}, + series = {Lecture Notes in Computer Science}, + title = {A Formally Verified Model of Web Components}, + url = {https://www.brucker.ch/bibliography/abstract/brucker.ea-web-components-2019}, + year = 2020 +} + +@Article{ brucker.ea:afp-dom-components:2020, + author = {Achim D. Brucker and Michael Herzberg}, + title = {A Formalization of Web Components}, + journal = {Archive of Formal Proofs}, + month = sep, + year = 2020, + date = {2020-09-28}, + note = {\url{http://www.isa-afp.org/entries/DOM_Components.html}, Formal proof development}, + issn = {2150-914x}, + public = {yes}, + classification= {formal}, + categories = {websecurity}, + pdf = {download/2020/brucker.ea-afp-dom-components-2020.pdf}, + filelabel = {Outline}, + file = {download/2020/brucker.ea-afp-dom-components-outline-2020.pdf}, + areas = {formal methods, security, software engineering} +} + +@Article{ brucker.ea:afp-dom-components:2020-a, + author = {Achim D. Brucker and Michael Herzberg}, + title = {A Formalization of Web Components}, + journal = {Archive of Formal Proofs}, + month = sep, + year = 2020, + date = {2020-09-28}, + note = {\url{http://www.isa-afp.org/entries/DOM_Components.html}, Formal proof development}, + issn = {2150-914x}, + public = {yes}, + classification= {formal}, + categories = {websecurity}, + pdf = {download/2020/brucker.ea-afp-dom-components-2020.pdf}, + filelabel = {Outline}, + file = {download/2020/brucker.ea-afp-dom-components-outline-2020.pdf}, + areas = {formal methods, security, software engineering} +} +@PhdThesis{herzberg:web-components:2020, + author = {Michael Herzberg}, + title = {Formal Foundations for Provably Safe Web Components}, + school = {The University of Sheffield}, + year = {2020} +} + diff --git a/Shadow_DOM/document/root.tex b/Shadow_DOM/document/root.tex new file mode 100644 index 0000000..631815f --- /dev/null +++ b/Shadow_DOM/document/root.tex @@ -0,0 +1,216 @@ +\documentclass[10pt,DIV16,a4paper,abstract=true,twoside=semi,openright] +{scrreprt} +\usepackage[USenglish]{babel} +\usepackage[numbers, sort&compress]{natbib} +\usepackage{isabelle,isabellesym} +\usepackage{booktabs} +\usepackage{paralist} +\usepackage{graphicx} +\usepackage{amssymb} +\usepackage{xspace} +\usepackage{xcolor} +\usepackage{listings} +\lstloadlanguages{HTML} +\usepackage[]{mathtools} +\usepackage[pdfpagelabels, pageanchor=false, plainpages=false]{hyperref} +\lstdefinestyle{html}{language=XML, + basicstyle=\ttfamily, + commentstyle=\itshape, + keywordstyle=\color{blue}, + ndkeywordstyle=\color{blue}, +} +\lstdefinestyle{displayhtml}{style=html, + floatplacement={tbp}, + captionpos=b, + framexleftmargin=0pt, + basicstyle=\ttfamily\scriptsize, + backgroundcolor=\color{black!2}, + frame=lines, +} +\lstnewenvironment{html}[1][]{\lstset{style=displayhtml, #1}}{} +\def\inlinehtml{\lstinline[style=html, columns=fullflexible]} + +\pagestyle{headings} +\isabellestyle{default} +\setcounter{tocdepth}{1} +\newcommand{\ie}{i.\,e.\xspace} +\newcommand{\eg}{e.\,g.\xspace} +\newcommand{\thy}{\isabellecontext} +\renewcommand{\isamarkupsection}[1]{% + \begingroup% + \def\isacharunderscore{\textunderscore}% + \section{#1 (\thy)}% + \endgroup% +} + +\title{Shadow DOM\\\medskip \Large + A Formal Model of the Document Object Model \emph{with Shadow Roots}}% + + + +\author{% + \href{https://www.brucker.ch/}{Achim~D.~Brucker}\footnotemark[1] + \and + \href{https://www.michael-herzberg.de/}{Michael Herzberg}\footnotemark[2] +} + +\publishers{ + \footnotemark[1]~Department of Computer Science, University of Exeter, Exeter, UK\texorpdfstring{\\}{, } + \texttt{a.brucker@exeter.ac.uk}\\[2em] + % + \footnotemark[2]~ Department of Computer Science, The University of Sheffield, Sheffield, UK\texorpdfstring{\\}{, } + \texttt{msherzberg1@sheffield.ac.uk} +} +\begin{document} + \maketitle + \begin{abstract} + \begin{quote} + In this AFP entry, we extend our formalization of the core DOM + (AFP entry \href{https://www.isa-afp.org/entries/Core_DOM.html} + {Core\_DOM}) with \emph{Shadow Roots}. Shadow roots are a recent + proposal of the web community to support a component-based + development approach for client-side web applications. + + Shadow roots are a significant extension to the DOM standard + and, as web standards are condemned to be backward compatible, + such extensions often result in complex specification that may + contain unwanted subtleties that can be detected by a + formalization. + + Our Isabelle/HOL formalization is, in the sense of + object-orientation, an extension of our formalization of the + core DOM and enjoys the same basic properties, i.e., it is + \begin{inparaenum} + \item \emph{extensible}, i.e., can be extended without the need of + re-proving already proven properties and + \item \emph{executable}, i.e., we can generate executable code + from our specification. + \end{inparaenum} + We exploit the executability to show that our formalization + complies to the official standard of the W3C, respectively, + the WHATWG. + + \bigskip + \noindent{\textbf{Keywords:}} + Document Object Model, DOM, Shadow Root, Web Component, Formal + Semantics, Isabelle/HOL + \end{quote} + \end{abstract} + + +\tableofcontents +\cleardoublepage + +\chapter{Introduction} + +In a world in which more and more applications are offered as services +on the internet, web browsers start to take on a similarly central +role in our daily IT infrastructure as operating systems. Thus, web +browsers should be developed as rigidly and formally as operating +systems. While formal methods are a well-established technique in the +development of operating systems (see, +\eg,~\citet{klein:operating:2009} for an overview of formal +verification of operating systems), there are few proposals for +improving the development of web browsers using formal +approaches~\cite{gardner.ea:dom:2008,raad.ea:dom:2016,jang.ea:establishing:2012,bohannon.ea:featherweight:2010}. + +In~\cite{brucker.ea:afp-core-dom:2018}, we formalized the core of the +Document Object Model (DOM) in Isabelle/HOL\@. The +DOM~\cite{whatwg:dom:2017,w3c:dom:2015} is \emph{the} central data +structure of all modern web browsers. In this work, we extend the +formalization presented in~\cite{brucker.ea:afp-core-dom:2018} with +support for \emph{shadow trees}. Shadow trees are a recent addition to +the DOM standard~\cite{whatwg:dom:2017} that promise support for web +components. As we will see, this promise is not fully achieved and, +for example, the DOM standard itself does not formally define what a +component should be. In this work, we focus on a standard compliant +representation of the DOM with shadow +trees. As~\cite{brucker.ea:afp-core-dom:2018}, our formalization has +the following properties: +\begin{itemize} +\item It provides a \emph{consistency guarantee.} Since all + definitions in our formal semantics are conservative and all rules + are derived, the logical consistency of the DOM node-tree is reduced + to the consistency of HOL. +\item It serves as a \emph{technical basis for a proof system.} Based + on the derived rules and specific setup of proof tactics over + node-trees, our formalization provides a generic proof environment + for the verification of programs manipulating node-trees. +\item It is \emph{executable}, which allows to validate its compliance + to the standard by evaluating the compliance test suite on the + formal model and +\item It is \emph{extensible} in the sense + of~\cite{brucker.ea:extensible:2008-b,brucker:interactive:2007}, + \ie, properties proven over the core DOM do not need to be re-proven + for object-oriented extensions such as the HTML document model. +\end{itemize} + +In this AFP entry, we limit ourselves to the faithful formalization of +the DOM. As the DOM standard does not formally define web components, +we address the question of formally defining web components and +discussing their safety properties +elsewhere~\cite{brucker.ea:afp-dom-components:2020,brucker.ea:web-components:2019}. + +The rest of this document is automatically generated from the +formalization in Isabelle/HOL, i.e., all content is checked by +Isabelle (we refer readers interested in a more high-level presentation +and additional explanations to~\cite{herzberg:web-components:2020,brucker.ea:web-components:2019}. +The structure follows the theory dependencies +(see \autoref{fig:session-graph}): first, we +formalize the DOM with Shadow Roots (\autoref{cha:dom}) and then +formalize we the relevant compliance test cases in +\autoref{cha:tests}. + +\begin{figure} + \centering + \includegraphics[height=.9\textheight]{session_graph} + \caption{The Dependency Graph of the Isabelle Theories.\label{fig:session-graph}} +\end{figure} + +\clearpage + +\chapter{The Shadow DOM} +\label{cha:dom} +In this chapter, we introduce the formalization of the core DOM +\emph{with Shadow Roots}, i.e., the most important algorithms for +querying or modifying the Shadow DOM, as defined in the standard. + +\input{ShadowRootClass.tex} +\input{ShadowRootMonad.tex} +\input{Shadow_DOM.tex} + + +\chapter{Test Suite} +\label{cha:tests} +In this chapter, we present the formalized compliance test cases for +the core DOM. As our formalization is executable, we can +(symbolically) execute the test cases on top of our model. Executing +these test cases successfully shows that our model is compliant to the +official DOM standard. As future work, we plan to generate test cases +from our formal model (e.g., +using~\cite{brucker.ea:interactive:2005,brucker.ea:theorem-prover:2012}) +to improve the quality of the official compliance test suite. For more +details on the relation of test and proof in the context of web +standards, we refer the reader to +\cite{brucker.ea:standard-compliance-testing:2018}. + +\input{Shadow_DOM_BaseTest.tex} +\input{slots.tex} +\input{slots_fallback.tex} +\input{Shadow_DOM_Document_adoptNode.tex} +\input{Shadow_DOM_Document_getElementById.tex} +\input{Shadow_DOM_Node_insertBefore.tex} +\input{Shadow_DOM_Node_removeChild.tex} +\input{Shadow_DOM_Tests.tex} + + +{\small + \bibliographystyle{abbrvnat} + \bibliography{root} +} +\end{document} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: t +%%% End: diff --git a/Shadow_DOM/monads/ShadowRootMonad.thy b/Shadow_DOM/monads/ShadowRootMonad.thy new file mode 100644 index 0000000..dde5182 --- /dev/null +++ b/Shadow_DOM/monads/ShadowRootMonad.thy @@ -0,0 +1,711 @@ +(*********************************************************************************** + * Copyright (c) 2016-2020 The University of Sheffield, UK + * 2019-2020 University of Exeter, UK + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-2-Clause + ***********************************************************************************) + +section\Shadow Root Monad\ +theory ShadowRootMonad + imports + "Core_DOM.DocumentMonad" + "../classes/ShadowRootClass" +begin + + +type_synonym ('object_ptr, 'node_ptr, 'element_ptr, 'character_data_ptr, 'document_ptr, + 'shadow_root_ptr, 'Object, 'Node, 'Element, 'CharacterData, 'Document, 'ShadowRoot, 'result) dom_prog + = "((_) heap, exception, 'result) prog" +register_default_tvars "('object_ptr, 'node_ptr, 'element_ptr, 'character_data_ptr, 'document_ptr, +'shadow_root_ptr, 'Object, 'Node, 'Element, 'CharacterData, 'Document, 'ShadowRoot, 'result) dom_prog" + + + +global_interpretation l_ptr_kinds_M shadow_root_ptr_kinds defines shadow_root_ptr_kinds_M = a_ptr_kinds_M . +lemmas shadow_root_ptr_kinds_M_defs = a_ptr_kinds_M_def + +lemma shadow_root_ptr_kinds_M_eq: + assumes "|h \ object_ptr_kinds_M|\<^sub>r = |h' \ object_ptr_kinds_M|\<^sub>r" + shows "|h \ shadow_root_ptr_kinds_M|\<^sub>r = |h' \ shadow_root_ptr_kinds_M|\<^sub>r" + using assms + by(auto simp add: shadow_root_ptr_kinds_M_defs object_ptr_kinds_M_defs shadow_root_ptr_kinds_def) + + + +global_interpretation l_dummy defines get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t = "l_get_M.a_get_M get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t" . +lemma get_M_is_l_get_M: "l_get_M get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t type_wf shadow_root_ptr_kinds" + apply(simp add: get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_type_wf l_get_M_def) + by (metis ObjectClass.get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_type_wf ObjectClass.type_wf_defs bind_eq_None_conv + shadow_root_ptr_kinds_commutes get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def option.simps(3)) +lemmas get_M_defs = get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def[unfolded l_get_M.a_get_M_def[OF get_M_is_l_get_M]] + +adhoc_overloading get_M get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t + +locale l_get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_lemmas = l_type_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t +begin +sublocale l_get_M\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a_lemmas by unfold_locales + +interpretation l_get_M get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t type_wf shadow_root_ptr_kinds + apply(unfold_locales) + apply (simp add: get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_type_wf local.type_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t) + by (meson ShadowRootMonad.get_M_is_l_get_M l_get_M_def) +lemmas get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ok = get_M_ok[folded get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def] +lemmas get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ptr_in_heap = get_M_ptr_in_heap[folded get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def] +end + +global_interpretation l_get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_lemmas type_wf by unfold_locales + + +global_interpretation l_put_M type_wf shadow_root_ptr_kinds get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t rewrites + "a_get_M = get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t" defines put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t = a_put_M + apply (simp add: get_M_is_l_get_M l_put_M_def) + by (simp add: get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def) + +lemmas put_M_defs = a_put_M_def +adhoc_overloading put_M put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t + + +locale l_put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_lemmas = l_type_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t +begin +sublocale l_put_M\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a_lemmas by unfold_locales + +interpretation l_put_M type_wf shadow_root_ptr_kinds get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t + apply(unfold_locales) + apply (simp add: get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_type_wf local.type_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t) + by (meson ShadowRootMonad.get_M_is_l_get_M l_get_M_def) +lemmas put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ok = put_M_ok[folded put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def] +end + +global_interpretation l_put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_lemmas type_wf by unfold_locales + + +lemma shadow_root_put_get [simp]: "h \ put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr setter v \\<^sub>h h' + \ (\x. getter (setter (\_. v) x) = v) + \ h' \ get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr getter \\<^sub>r v" + by(auto simp add: put_M_defs get_M_defs split: option.splits) +lemma get_M_Mshadow_root_preserved1 [simp]: + "shadow_root_ptr \ shadow_root_ptr' + \ h \ put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr setter v \\<^sub>h h' + \ preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr' getter) h h'" + by(auto simp add: put_M_defs get_M_defs preserved_def split: option.splits dest: get_heap_E) +lemma shadow_root_put_get_preserved [simp]: + "h \ put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr setter v \\<^sub>h h' + \ (\x. getter (setter (\_. v) x) = getter x) + \ preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr' getter) h h'" + apply(cases "shadow_root_ptr = shadow_root_ptr'") + by(auto simp add: put_M_defs get_M_defs preserved_def split: option.splits dest: get_heap_E) + +lemma get_M_Mshadow_root_preserved2 [simp]: + "h \ put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr setter v \\<^sub>h h' \ preserved (get_M\<^sub>N\<^sub>o\<^sub>d\<^sub>e node_ptr getter) h h'" + by(auto simp add: put_M_defs get_M_defs NodeMonad.get_M_defs get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def + put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def get\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def preserved_def split: option.splits dest: get_heap_E) + +lemma get_M_Mshadow_root_preserved3 [simp]: + "cast shadow_root_ptr \ object_ptr + \ h \ put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr setter v \\<^sub>h h' + \ preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t object_ptr getter) h h'" + by(auto simp add: put_M_defs get_M_defs get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def ObjectMonad.get_M_defs + preserved_def split: option.splits dest: get_heap_E) +lemma get_M_Mshadow_root_preserved4 [simp]: + "h \ put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr setter v \\<^sub>h h' + \ (\x. getter (cast (setter (\_. v) x)) = getter (cast x)) + \ preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t object_ptr getter) h h'" + apply(cases "cast shadow_root_ptr \ object_ptr")[1] + by(auto simp add: put_M_defs get_M_defs get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def + ObjectMonad.get_M_defs preserved_def + split: option.splits bind_splits dest: get_heap_E) + +lemma get_M_Mshadow_root_preserved5 [simp]: + "cast shadow_root_ptr \ object_ptr + \ h \ put_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t object_ptr setter v \\<^sub>h h' + \ preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr getter) h h'" + by(auto simp add: ObjectMonad.put_M_defs get_M_defs get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def ObjectMonad.get_M_defs + preserved_def split: option.splits dest: get_heap_E) + +lemma get_M_Mshadow_root_preserved6 [simp]: + "h \ put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr setter v \\<^sub>h h' \ preserved (get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t element_ptr getter) h h'" + by(auto simp add: put_M_defs ElementMonad.get_M_defs preserved_def + split: option.splits dest: get_heap_E) +lemma get_M_Mshadow_root_preserved7 [simp]: + "h \ put_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t element_ptr setter v \\<^sub>h h' \ preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr getter) h h'" + by(auto simp add: ElementMonad.put_M_defs get_M_defs preserved_def + split: option.splits dest: get_heap_E) +lemma get_M_Mshadow_root_preserved8 [simp]: + "h \ put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr setter v \\<^sub>h h' + \ preserved (get_M\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a character_data_ptr getter) h h'" + by(auto simp add: put_M_defs CharacterDataMonad.get_M_defs preserved_def + split: option.splits dest: get_heap_E) +lemma get_M_Mshadow_root_preserved9 [simp]: + "h \ put_M\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a character_data_ptr setter v \\<^sub>h h' + \ preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr getter) h h'" + by(auto simp add: CharacterDataMonad.put_M_defs get_M_defs preserved_def + split: option.splits dest: get_heap_E) +lemma get_M_Mshadow_root_preserved10 [simp]: + "(\x. getter (cast (setter (\_. v) x)) = getter (cast x)) + \ h \ put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr setter v \\<^sub>h h' \ preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t object_ptr getter) h h'" + apply(cases "cast shadow_root_ptr = object_ptr") + by(auto simp add: put_M_defs get_M_defs ObjectMonad.get_M_defs NodeMonad.get_M_defs get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def + get\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def preserved_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def put\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def bind_eq_Some_conv + split: option.splits) + +lemma new_element_get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t: + "h \ new_element \\<^sub>h h' \ preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t ptr getter) h h'" + by(auto simp add: new_element_def get_M_defs preserved_def + split: prod.splits option.splits elim!: bind_returns_result_E bind_returns_heap_E) + +lemma new_character_data_get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t: + "h \ new_character_data \\<^sub>h h' \ preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t ptr getter) h h'" + by(auto simp add: new_character_data_def get_M_defs preserved_def + split: prod.splits option.splits elim!: bind_returns_result_E bind_returns_heap_E) + +lemma new_document_get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t: + "h \ new_document \\<^sub>h h' \ preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t ptr getter) h h'" + by(auto simp add: new_document_def get_M_defs preserved_def + split: prod.splits option.splits elim!: bind_returns_result_E bind_returns_heap_E) + + +definition delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M :: "(_) shadow_root_ptr \ (_, unit) dom_prog" where + "delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr = do { + h \ get_heap; + (case delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr h of + Some h \ return_heap h | + None \ error HierarchyRequestError) + }" +adhoc_overloading delete_M delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M + +lemma delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_ok [simp]: + assumes "shadow_root_ptr |\| shadow_root_ptr_kinds h" + shows "h \ ok (delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr)" + using assms + by(auto simp add: delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def split: prod.splits) + +lemma delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_ptr_in_heap: + assumes "h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h'" + shows "shadow_root_ptr |\| shadow_root_ptr_kinds h" + using assms + by(auto simp add: delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def split: if_splits) + +lemma delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_ptr_not_in_heap: + assumes "h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h'" + shows "shadow_root_ptr |\| shadow_root_ptr_kinds h'" + using assms + apply(auto simp add: delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def split: if_splits)[1] + by (metis comp_apply fmdom_notI fmdrop_lookup heap.sel object_ptr_kinds_def shadow_root_ptr_kinds_commutes) + +lemma delete_shadow_root_pointers: + assumes "h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h'" + shows "object_ptr_kinds h = object_ptr_kinds h' |\| {|cast shadow_root_ptr|}" + using assms + apply(auto simp add: delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def split: option.splits)[1] + apply (metis (no_types, lifting) ObjectClass.a_type_wf_def ObjectClass.get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_type_wf delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def + delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_pointer_ptr_in_heap fmlookup_drop get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def heap.sel option.sel + shadow_root_ptr_kinds_commutes) + using delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_pointer_ptr_in_heap apply blast + by (metis (no_types, lifting) ObjectClass.a_type_wf_def ObjectClass.get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_type_wf delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def + delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_pointer_ptr_in_heap fmlookup_drop get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def heap.sel option.sel + shadow_root_ptr_kinds_commutes) + +lemma delete_shadow_root_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t: "h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h' \ +ptr \ cast shadow_root_ptr \ preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr getter) h h'" + by(auto simp add: delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def ObjectMonad.get_M_defs preserved_def + split: prod.splits option.splits if_splits elim!: bind_returns_heap_E) +lemma delete_shadow_root_get_M\<^sub>N\<^sub>o\<^sub>d\<^sub>e: "h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h' \ +preserved (get_M\<^sub>N\<^sub>o\<^sub>d\<^sub>e ptr getter) h h'" + by(auto simp add: delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def NodeMonad.get_M_defs ObjectMonad.get_M_defs + preserved_def split: prod.splits option.splits if_splits elim!: bind_returns_heap_E) +lemma delete_shadow_root_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t: "h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h' \ +preserved (get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t ptr getter) h h'" + by(auto simp add: delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def ElementMonad.get_M_defs NodeMonad.get_M_defs + ObjectMonad.get_M_defs preserved_def split: prod.splits option.splits if_splits elim!: bind_returns_heap_E) +lemma delete_shadow_root_get_M\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a: "h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h' \ +preserved (get_M\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a ptr getter) h h'" + by(auto simp add: delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def CharacterDataMonad.get_M_defs + NodeMonad.get_M_defs ObjectMonad.get_M_defs preserved_def split: prod.splits option.splits if_splits + elim!: bind_returns_heap_E) +lemma delete_shadow_root_get_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t: "h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h' \ +preserved (get_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t ptr getter) h h'" + by(auto simp add: delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def DocumentMonad.get_M_defs ObjectMonad.get_M_defs + preserved_def split: prod.splits option.splits if_splits elim!: bind_returns_heap_E) +lemma delete_shadow_root_get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t: "h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h' \ +shadow_root_ptr \ shadow_root_ptr' \ preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr' getter) h h'" + by(auto simp add: delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def get_M_defs ObjectMonad.get_M_defs + preserved_def split: prod.splits option.splits if_splits elim!: bind_returns_heap_E) + + +lemma shadow_root_put_get_1 [simp]: "shadow_root_ptr \ shadow_root_ptr' \ +h \ put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr setter v \\<^sub>h h' \ +preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr' getter) h h'" + by(auto simp add: put_M_defs get_M_defs preserved_def split: option.splits dest: get_heap_E) +lemma shadow_root_put_get_2 [simp]: "(\x. getter (setter (\_. v) x) = getter x) \ +h \ put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr setter v \\<^sub>h h' \ +preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr' getter) h h'" + by (cases "shadow_root_ptr = shadow_root_ptr'") (auto simp add: put_M_defs get_M_defs preserved_def + split: option.splits dest: get_heap_E) +lemma shadow_root_put_get_3 [simp]: "h \ put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr setter v \\<^sub>h h' \ +preserved (get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t element_ptr getter) h h'" + by(auto simp add: put_M_defs ElementMonad.get_M_defs preserved_def split: option.splits + dest: get_heap_E) +lemma shadow_root_put_get_4 [simp]: "h \ put_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t element_ptr setter v \\<^sub>h h' \ +preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr getter) h h'" + by(auto simp add: ElementMonad.put_M_defs get_M_defs preserved_def split: option.splits + dest: get_heap_E) +lemma shadow_root_put_get_5 [simp]: "h \ put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr setter v \\<^sub>h h' \ +preserved (get_M\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a character_data_ptr getter) h h'" + by(auto simp add: put_M_defs CharacterDataMonad.get_M_defs preserved_def split: option.splits + dest: get_heap_E) +lemma shadow_root_put_get_6 [simp]: "h \ put_M\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a character_data_ptr setter v \\<^sub>h h' \ +preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr getter) h h'" + by(auto simp add: CharacterDataMonad.put_M_defs get_M_defs preserved_def split: option.splits + dest: get_heap_E) +lemma shadow_root_put_get_7 [simp]: "h \ put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr setter v \\<^sub>h h' \ +preserved (get_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t document_ptr getter) h h'" + by(auto simp add: put_M_defs DocumentMonad.get_M_defs preserved_def split: option.splits + dest: get_heap_E) +lemma shadow_root_put_get_8 [simp]: "h \ put_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t document_ptr setter v \\<^sub>h h' \ +preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr getter) h h'" + by(auto simp add: DocumentMonad.put_M_defs get_M_defs preserved_def split: option.splits + dest: get_heap_E) +lemma shadow_root_put_get_9 [simp]: "(\x. getter (cast (setter (\_. v) x)) = getter (cast x)) \ +h \ put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr setter v \\<^sub>h h' \ preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t object_ptr getter) h h'" + by (cases "cast shadow_root_ptr = object_ptr") (auto simp add: put_M_defs get_M_defs + ObjectMonad.get_M_defs NodeMonad.get_M_defs get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def get\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def preserved_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def + put\<^sub>N\<^sub>o\<^sub>d\<^sub>e_def bind_eq_Some_conv split: option.splits) + +subsection \new\_M\ + +definition new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M :: "(_, (_) shadow_root_ptr) dom_prog" + where + "new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M = do { + h \ get_heap; + (new_ptr, h') \ return (new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t h); + return_heap h'; + return new_ptr + }" + +lemma new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_ok [simp]: + "h \ ok new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M" + by(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def split: prod.splits) + +lemma new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_ptr_in_heap: + assumes "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h'" + and "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr" + shows "new_shadow_root_ptr |\| shadow_root_ptr_kinds h'" + using assms + unfolding new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def + by(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def Let_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ptr_in_heap is_OK_returns_result_I + elim!: bind_returns_result_E bind_returns_heap_E) + +lemma new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_ptr_not_in_heap: + assumes "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h'" + and "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr" + shows "new_shadow_root_ptr |\| shadow_root_ptr_kinds h" + using assms new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ptr_not_in_heap + by(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def split: prod.splits elim!: bind_returns_result_E bind_returns_heap_E) + +lemma new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_new_ptr: + assumes "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h'" + and "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr" + shows "object_ptr_kinds h' = object_ptr_kinds h |\| {|cast new_shadow_root_ptr|}" + using assms new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_new_ptr + by(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def split: prod.splits elim!: bind_returns_result_E bind_returns_heap_E) + +lemma new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_is_shadow_root_ptr: + assumes "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr" + shows "is_shadow_root_ptr new_shadow_root_ptr" + using assms new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_is_shadow_root_ptr + by(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def elim!: bind_returns_result_E split: prod.splits) + +lemma new_shadow_root_mode: + assumes "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h'" + assumes "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr" + shows "h' \ get_M new_shadow_root_ptr mode \\<^sub>r Open" + using assms + by(auto simp add: get_M_defs new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def Let_def + split: option.splits prod.splits elim!: bind_returns_result_E bind_returns_heap_E) + +lemma new_shadow_root_children: + assumes "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h'" + assumes "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr" + shows "h' \ get_M new_shadow_root_ptr child_nodes \\<^sub>r []" + using assms + by(auto simp add: get_M_defs new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def Let_def + split: option.splits prod.splits elim!: bind_returns_result_E bind_returns_heap_E) + +lemma new_shadow_root_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t: + "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr + \ ptr \ cast new_shadow_root_ptr \ preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr getter) h h'" + by(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def ObjectMonad.get_M_defs preserved_def + split: prod.splits option.splits elim!: bind_returns_result_E bind_returns_heap_E) +lemma new_shadow_root_get_M\<^sub>N\<^sub>o\<^sub>d\<^sub>e: + "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr + \ preserved (get_M\<^sub>N\<^sub>o\<^sub>d\<^sub>e ptr getter) h h'" + by(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def NodeMonad.get_M_defs preserved_def + split: prod.splits option.splits elim!: bind_returns_result_E bind_returns_heap_E) +lemma new_shadow_root_get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t: + "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr + \ preserved (get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t ptr getter) h h'" + by(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def ElementMonad.get_M_defs preserved_def + split: prod.splits option.splits elim!: bind_returns_result_E bind_returns_heap_E) +lemma new_shadow_root_get_M\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a: + "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr + \ preserved (get_M\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a ptr getter) h h'" + by(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def CharacterDataMonad.get_M_defs preserved_def + split: prod.splits option.splits elim!: bind_returns_result_E bind_returns_heap_E) +lemma new_shadow_root_get_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t: + "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' + \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr + \ preserved (get_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t ptr getter) h h'" + by(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def DocumentMonad.get_M_defs preserved_def + split: prod.splits option.splits elim!: bind_returns_result_E bind_returns_heap_E) +lemma new_shadow_root_get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t: + "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' + \ h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr \ ptr \ new_shadow_root_ptr + \ preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t ptr getter) h h'" + by(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def get_M_defs preserved_def + split: prod.splits option.splits elim!: bind_returns_result_E bind_returns_heap_E) + + +subsection \modified heaps\ + +lemma shadow_root_get_put_1 [simp]: "get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr (put\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr obj h) = (if ptr = cast shadow_root_ptr +then cast obj else get shadow_root_ptr h)" + by(auto simp add: get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def split: option.splits Option.bind_splits) + +lemma shadow_root_ptr_kinds_new[simp]: "shadow_root_ptr_kinds (put\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr obj h) = shadow_root_ptr_kinds h |\| +(if is_shadow_root_ptr_kind ptr then {|the (cast ptr)|} else {||})" + by(auto simp add: shadow_root_ptr_kinds_def split: option.splits) + +lemma type_wf_put_I: + assumes "type_wf h" + assumes "DocumentClass.type_wf (put\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr obj h)" + assumes "is_shadow_root_ptr_kind ptr \ is_shadow_root_kind obj" + shows "type_wf (put\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr obj h)" + using assms + by(auto simp add: type_wf_defs is_shadow_root_kind_def split: option.splits) + +lemma type_wf_put_ptr_not_in_heap_E: + assumes "type_wf (put\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr obj h)" + assumes "ptr |\| object_ptr_kinds h" + shows "type_wf h" + using assms + by(auto simp add: type_wf_defs elim!: DocumentMonad.type_wf_put_ptr_not_in_heap_E + split: option.splits if_splits) + +lemma type_wf_put_ptr_in_heap_E: + assumes "type_wf (put\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr obj h)" + assumes "ptr |\| object_ptr_kinds h" + assumes "DocumentClass.type_wf h" + assumes "is_shadow_root_ptr_kind ptr \ is_shadow_root_kind (the (get ptr h))" + shows "type_wf h" + using assms + apply(auto simp add: type_wf_defs elim!: DocumentMonad.type_wf_put_ptr_in_heap_E + split: option.splits if_splits)[1] + by (metis (no_types, hide_lams) ObjectClass.a_type_wf_def ObjectClass.get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_type_wf + bind.bind_lunit finite_set_in get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def is_shadow_root_kind_def option.exhaust_sel) + + +subsection \type\_wf\ + +lemma new_element_type_wf_preserved [simp]: + assumes "h \ new_element \\<^sub>h h'" + shows "type_wf h = type_wf h'" +proof - + obtain new_element_ptr where "h \ new_element \\<^sub>r new_element_ptr" + using assms + by (meson is_OK_returns_heap_I is_OK_returns_result_E) + with assms have "object_ptr_kinds h' = object_ptr_kinds h |\| {|cast new_element_ptr|}" + using new_element_new_ptr by auto + then have "shadow_root_ptr_kinds h = shadow_root_ptr_kinds h'" + unfolding shadow_root_ptr_kinds_def by auto + with assms show ?thesis + by(auto simp add: ElementMonad.new_element_def type_wf_defs Let_def elim!: bind_returns_heap_E + split: prod.splits) +qed + +lemma put_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_tag_name_type_wf_preserved [simp]: + assumes "h \ put_M element_ptr tag_name_update v \\<^sub>h h'" + shows "type_wf h = type_wf h'" +proof - + have "object_ptr_kinds h = object_ptr_kinds h'" + using writes_singleton assms object_ptr_kinds_preserved unfolding all_args_def by fastforce + then have "shadow_root_ptr_kinds h = shadow_root_ptr_kinds h'" + unfolding shadow_root_ptr_kinds_def by simp + with assms show ?thesis + by(auto simp add: ElementMonad.put_M_defs type_wf_defs) +qed +lemma put_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_child_nodes_type_wf_preserved [simp]: + assumes "h \ put_M element_ptr RElement.child_nodes_update v \\<^sub>h h'" + shows "type_wf h = type_wf h'" +proof - + have "object_ptr_kinds h = object_ptr_kinds h'" + using writes_singleton assms object_ptr_kinds_preserved unfolding all_args_def by fastforce + then have "shadow_root_ptr_kinds h = shadow_root_ptr_kinds h'" + unfolding shadow_root_ptr_kinds_def by simp + with assms show ?thesis + by(auto simp add: ElementMonad.put_M_defs type_wf_defs) +qed +lemma put_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_attrs_type_wf_preserved [simp]: + assumes "h \ put_M element_ptr attrs_update v \\<^sub>h h'" + shows "type_wf h = type_wf h'" +proof - + have "object_ptr_kinds h = object_ptr_kinds h'" + using writes_singleton assms object_ptr_kinds_preserved unfolding all_args_def by fastforce + then have "shadow_root_ptr_kinds h = shadow_root_ptr_kinds h'" + unfolding shadow_root_ptr_kinds_def by simp + with assms show ?thesis + by(auto simp add: ElementMonad.put_M_defs type_wf_defs) +qed +lemma put_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t_shadow_root_opt_type_wf_preserved [simp]: + assumes "h \ put_M element_ptr shadow_root_opt_update v \\<^sub>h h'" + shows "type_wf h = type_wf h'" +proof - + have "object_ptr_kinds h = object_ptr_kinds h'" + using writes_singleton assms object_ptr_kinds_preserved unfolding all_args_def by fastforce + then have "shadow_root_ptr_kinds h = shadow_root_ptr_kinds h'" + unfolding shadow_root_ptr_kinds_def by simp + with assms show ?thesis + by(auto simp add: ElementMonad.put_M_defs type_wf_defs) +qed + +lemma new_character_data_type_wf_preserved [simp]: + assumes "h \ new_character_data \\<^sub>h h'" + shows "type_wf h = type_wf h'" +proof - + obtain new_character_data_ptr where "h \ new_character_data \\<^sub>r new_character_data_ptr" + using assms + by (meson is_OK_returns_heap_I is_OK_returns_result_E) + with assms have "object_ptr_kinds h' = object_ptr_kinds h |\| {|cast new_character_data_ptr|}" + using new_character_data_new_ptr by auto + then have "shadow_root_ptr_kinds h = shadow_root_ptr_kinds h'" + unfolding shadow_root_ptr_kinds_def by auto + with assms show ?thesis + by(auto simp add: CharacterDataMonad.new_character_data_def type_wf_defs Let_def + elim!: bind_returns_heap_E split: prod.splits) +qed +lemma put_M\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a_val_type_wf_preserved [simp]: + assumes "h \ put_M character_data_ptr val_update v \\<^sub>h h'" + shows "type_wf h = type_wf h'" +proof - + have "object_ptr_kinds h = object_ptr_kinds h'" + using writes_singleton assms object_ptr_kinds_preserved unfolding all_args_def by fastforce + then have "shadow_root_ptr_kinds h = shadow_root_ptr_kinds h'" + unfolding shadow_root_ptr_kinds_def by simp + with assms show ?thesis + by(auto simp add: CharacterDataMonad.put_M_defs type_wf_defs) +qed + +lemma new_document_type_wf_preserved [simp]: + assumes "h \ new_document \\<^sub>h h'" + shows "type_wf h = type_wf h'" +proof - + obtain new_document_ptr where "h \ new_document \\<^sub>r new_document_ptr" + using assms + by (meson is_OK_returns_heap_I is_OK_returns_result_E) + with assms have "object_ptr_kinds h' = object_ptr_kinds h |\| {|cast new_document_ptr|}" + using new_document_new_ptr by auto + then have "shadow_root_ptr_kinds h = shadow_root_ptr_kinds h'" + unfolding shadow_root_ptr_kinds_def by auto + with assms show ?thesis + by(auto simp add: DocumentMonad.new_document_def type_wf_defs Let_def elim!: bind_returns_heap_E + split: prod.splits) +qed + +lemma put_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t_doctype_type_wf_preserved [simp]: + assumes "h \ put_M document_ptr doctype_update v \\<^sub>h h'" + shows "type_wf h = type_wf h'" +proof - + have "object_ptr_kinds h = object_ptr_kinds h'" + using writes_singleton assms object_ptr_kinds_preserved unfolding all_args_def by fastforce + then have "shadow_root_ptr_kinds h = shadow_root_ptr_kinds h'" + unfolding shadow_root_ptr_kinds_def by simp + with assms show ?thesis + by(auto simp add: DocumentMonad.put_M_defs type_wf_defs) +qed +lemma put_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t_document_element_type_wf_preserved [simp]: + assumes "h \ put_M document_ptr document_element_update v \\<^sub>h h'" + shows "type_wf h = type_wf h'" +proof - + have "object_ptr_kinds h = object_ptr_kinds h'" + using writes_singleton assms object_ptr_kinds_preserved unfolding all_args_def by fastforce + then have "shadow_root_ptr_kinds h = shadow_root_ptr_kinds h'" + unfolding shadow_root_ptr_kinds_def by simp + with assms show ?thesis + by(auto simp add: DocumentMonad.put_M_defs type_wf_defs) +qed +lemma put_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t_disconnected_nodes_type_wf_preserved [simp]: + assumes "h \ put_M document_ptr disconnected_nodes_update v \\<^sub>h h'" + shows "type_wf h = type_wf h'" +proof - + have "object_ptr_kinds h = object_ptr_kinds h'" + using writes_singleton assms object_ptr_kinds_preserved unfolding all_args_def by fastforce + then have "shadow_root_ptr_kinds h = shadow_root_ptr_kinds h'" + unfolding shadow_root_ptr_kinds_def by simp + with assms show ?thesis + by(auto simp add: DocumentMonad.put_M_defs type_wf_defs) +qed + +lemma put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_mode_type_wf_preserved [simp]: + "h \ put_M shadow_root_ptr mode_update v \\<^sub>h h' \ type_wf h = type_wf h'" + by(auto simp add: get_M_defs is_shadow_root_kind_def type_wf_defs ElementClass.type_wf_defs + NodeClass.type_wf_defs ElementMonad.get_M_defs ObjectClass.type_wf_defs + CharacterDataClass.type_wf_defs DocumentClass.type_wf_defs put_M_defs + put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def + dest!: get_heap_E + elim!: bind_returns_heap_E2 + intro!: type_wf_put_I DocumentMonad.type_wf_put_I CharacterDataMonad.type_wf_put_I + ElementMonad.type_wf_put_I NodeMonad.type_wf_put_I ObjectMonad.type_wf_put_I + split: option.splits) + + +lemma put_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_child_nodes_type_wf_preserved [simp]: + "h \ put_M shadow_root_ptr RShadowRoot.child_nodes_update v \\<^sub>h h' \ type_wf h = type_wf h'" + by(auto simp add: get_M_defs is_shadow_root_kind_def type_wf_defs ElementClass.type_wf_defs + NodeClass.type_wf_defs ElementMonad.get_M_defs ObjectClass.type_wf_defs + CharacterDataClass.type_wf_defs DocumentClass.type_wf_defs put_M_defs + put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def + dest!: get_heap_E + elim!: bind_returns_heap_E2 + intro!: type_wf_put_I DocumentMonad.type_wf_put_I CharacterDataMonad.type_wf_put_I + ElementMonad.type_wf_put_I NodeMonad.type_wf_put_I ObjectMonad.type_wf_put_I + split: option.splits) + + +lemma shadow_root_ptr_kinds_small: + assumes "\object_ptr. preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t object_ptr RObject.nothing) h h'" + shows "shadow_root_ptr_kinds h = shadow_root_ptr_kinds h'" + by(simp add: shadow_root_ptr_kinds_def preserved_def object_ptr_kinds_preserved_small[OF assms]) + +lemma shadow_root_ptr_kinds_preserved: + assumes "writes SW setter h h'" + assumes "h \ setter \\<^sub>h h'" + assumes "\h h'. \w \ SW. h \ w \\<^sub>h h' \ +(\object_ptr. preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t object_ptr RObject.nothing) h h')" + shows "shadow_root_ptr_kinds h = shadow_root_ptr_kinds h'" + using writes_small_big[OF assms] + apply(simp add: reflp_def transp_def preserved_def shadow_root_ptr_kinds_def) + by (metis assms object_ptr_kinds_preserved) + +lemma new_shadow_root_known_ptr: + assumes "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr" + shows "known_ptr (cast new_shadow_root_ptr)" + using assms + apply(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def Let_def a_known_ptr_def + elim!: bind_returns_result_E2 split: prod.splits)[1] + using assms new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_is_shadow_root_ptr by blast + +lemma new_shadow_root_type_wf_preserved [simp]: "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' \ type_wf h = type_wf h'" + apply(auto simp add: new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def Let_def put\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def put\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t_def + ShadowRootClass.type_wf\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t ShadowRootClass.type_wf\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a ShadowRootClass.type_wf\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t + ShadowRootClass.type_wf\<^sub>N\<^sub>o\<^sub>d\<^sub>e ShadowRootClass.type_wf\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t + is_node_ptr_kind_none new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_ptr_not_in_heap + elim!: bind_returns_heap_E type_wf_put_ptr_not_in_heap_E + intro!: type_wf_put_I DocumentMonad.type_wf_put_I ElementMonad.type_wf_put_I + CharacterDataMonad.type_wf_put_I + NodeMonad.type_wf_put_I ObjectMonad.type_wf_put_I + split: if_splits)[1] + by(auto simp add: type_wf_defs DocumentClass.type_wf_defs ElementClass.type_wf_defs + CharacterDataClass.type_wf_defs + NodeClass.type_wf_defs ObjectClass.type_wf_defs is_shadow_root_kind_def is_document_kind_def + split: option.splits)[1] + +locale l_new_shadow_root = l_type_wf + + assumes new_shadow_root_types_preserved: "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h' \ type_wf h = type_wf h'" + +lemma new_shadow_root_is_l_new_shadow_root [instances]: "l_new_shadow_root type_wf" + using l_new_shadow_root.intro new_shadow_root_type_wf_preserved + by blast + +lemma type_wf_preserved_small: + assumes "\object_ptr. preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t object_ptr RObject.nothing) h h'" + assumes "\node_ptr. preserved (get_M\<^sub>N\<^sub>o\<^sub>d\<^sub>e node_ptr RNode.nothing) h h'" + assumes "\element_ptr. preserved (get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t element_ptr RElement.nothing) h h'" + assumes "\character_data_ptr. preserved (get_M\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a character_data_ptr RCharacterData.nothing) h h'" + assumes "\document_ptr. preserved (get_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t document_ptr RDocument.nothing) h h'" + assumes "\shadow_root_ptr. preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr RShadowRoot.nothing) h h'" + shows "type_wf h = type_wf h'" + using type_wf_preserved_small[OF assms(1) assms(2) assms(3) assms(4) assms(5)] + allI[OF assms(6), of id, simplified] shadow_root_ptr_kinds_small[OF assms(1)] + apply(auto simp add: type_wf_defs preserved_def get_M_defs shadow_root_ptr_kinds_small[OF assms(1)] + split: option.splits)[1] + apply(force) + apply(force) + done + +lemma new_element_is_l_new_element [instances]: + "l_new_element type_wf" + using l_new_element.intro new_element_type_wf_preserved + by blast + +lemma new_character_data_is_l_new_character_data [instances]: + "l_new_character_data type_wf" + using l_new_character_data.intro new_character_data_type_wf_preserved + by blast + +lemma new_document_is_l_new_document [instances]: + "l_new_document type_wf" + using l_new_document.intro new_document_type_wf_preserved + by blast + +lemma type_wf_preserved: + assumes "writes SW setter h h'" + assumes "h \ setter \\<^sub>h h'" + assumes "\h h' w. w \ SW \ h \ w \\<^sub>h h' \ +\object_ptr. preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t object_ptr RObject.nothing) h h'" + assumes "\h h' w. w \ SW \ h \ w \\<^sub>h h' \ +\node_ptr. preserved (get_M\<^sub>N\<^sub>o\<^sub>d\<^sub>e node_ptr RNode.nothing) h h'" + assumes "\h h' w. w \ SW \ h \ w \\<^sub>h h' \ +\element_ptr. preserved (get_M\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t element_ptr RElement.nothing) h h'" + assumes "\h h' w. w \ SW \ h \ w \\<^sub>h h' \ +\character_data_ptr. preserved (get_M\<^sub>C\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>D\<^sub>a\<^sub>t\<^sub>a character_data_ptr RCharacterData.nothing) h h'" + assumes "\h h' w. w \ SW \ h \ w \\<^sub>h h' \ +\document_ptr. preserved (get_M\<^sub>D\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t document_ptr RDocument.nothing) h h'" + assumes "\h h' w. w \ SW \ h \ w \\<^sub>h h' \ +\shadow_root_ptr. preserved (get_M\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t shadow_root_ptr RShadowRoot.nothing) h h'" + shows "type_wf h = type_wf h'" +proof - + have "\h h' w. w \ SW \ h \ w \\<^sub>h h' \ type_wf h = type_wf h'" + using assms type_wf_preserved_small by fast + with assms(1) assms(2) show ?thesis + apply(rule writes_small_big) + by(auto simp add: reflp_def transp_def) +qed + +lemma type_wf_drop: "type_wf h \ type_wf (Heap (fmdrop ptr (the_heap h)))" + apply(auto simp add: type_wf_defs)[1] + using type_wf_drop + apply blast + by (metis (no_types, lifting) DocumentClass.type_wf\<^sub>E\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t ElementClass.get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_type_wf + ElementMonad.type_wf_drop fmember.rep_eq fmlookup_drop get\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def get\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def + object_ptr_kinds_code5 shadow_root_ptr_kinds_commutes) + +lemma delete_shadow_root_type_wf_preserved [simp]: + assumes "h \ delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M shadow_root_ptr \\<^sub>h h'" + assumes "type_wf h" + shows "type_wf h'" + using assms + using type_wf_drop + by(auto simp add: delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M_def delete\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_def delete\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def split: if_splits) +end diff --git a/Shadow_DOM/tests/Document-adoptNode.html b/Shadow_DOM/tests/Document-adoptNode.html new file mode 100644 index 0000000..75d4531 --- /dev/null +++ b/Shadow_DOM/tests/Document-adoptNode.html @@ -0,0 +1,36 @@ + + +Document.adoptNode + + + +
+x + diff --git a/Shadow_DOM/tests/Document-getElementById.html b/Shadow_DOM/tests/Document-getElementById.html new file mode 100644 index 0000000..d565ef0 --- /dev/null +++ b/Shadow_DOM/tests/Document-getElementById.html @@ -0,0 +1,251 @@ + + +Document.getElementById + + + + + +
+ +
+ +
+ +
+

P

+ +
+ +
+
+
+
+
+ + + + diff --git a/Shadow_DOM/tests/Node-insertBefore.html b/Shadow_DOM/tests/Node-insertBefore.html new file mode 100644 index 0000000..db2675b --- /dev/null +++ b/Shadow_DOM/tests/Node-insertBefore.html @@ -0,0 +1,288 @@ + +Node.insertBefore + + + +
+ + diff --git a/Shadow_DOM/tests/Node-removeChild.html b/Shadow_DOM/tests/Node-removeChild.html new file mode 100644 index 0000000..83c4c3d --- /dev/null +++ b/Shadow_DOM/tests/Node-removeChild.html @@ -0,0 +1,66 @@ + +Node.removeChild + + + + +
+ + + diff --git a/Shadow_DOM/tests/Shadow_DOM_BaseTest.thy b/Shadow_DOM/tests/Shadow_DOM_BaseTest.thy new file mode 100644 index 0000000..962bed2 --- /dev/null +++ b/Shadow_DOM/tests/Shadow_DOM_BaseTest.thy @@ -0,0 +1,373 @@ +(*********************************************************************************** + * Copyright (c) 2016-2020 The University of Sheffield, UK + * 2019-2020 University of Exeter, UK + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-2-Clause + ***********************************************************************************) + +section\Shadow DOM Base Tests\ + +theory Shadow_DOM_BaseTest + imports + "../Shadow_DOM" +begin + + +definition "assert_throws e p = do { + h \ get_heap; + (if (h \ p \\<^sub>e e) then return () else error AssertException) +}" +notation assert_throws ("assert'_throws'(_, _')") + +definition "test p h \ h \ ok p" + + +definition field_access :: "(string \ (_, (_) object_ptr option) dom_prog) \ string \ +(_, (_) object_ptr option) dom_prog" (infix "." 80) + where + "field_access m field = m field" + +definition assert_equals :: "'a \ 'a \ (_, unit) dom_prog" + where + "assert_equals l r = (if l = r then return () else error AssertException)" +definition assert_equals_with_message :: "'a \ 'a \ 'b \ (_, unit) dom_prog" + where + "assert_equals_with_message l r _ = (if l = r then return () else error AssertException)" +notation assert_equals ("assert'_equals'(_, _')") +notation assert_equals_with_message ("assert'_equals'(_, _, _')") +notation assert_equals ("assert'_array'_equals'(_, _')") +notation assert_equals_with_message ("assert'_array'_equals'(_, _, _')") + +definition assert_not_equals :: "'a \ 'a \ (_, unit) dom_prog" + where + "assert_not_equals l r = (if l \ r then return () else error AssertException)" +definition assert_not_equals_with_message :: "'a \ 'a \ 'b \ (_, unit) dom_prog" + where + "assert_not_equals_with_message l r _ = (if l \ r then return () else error AssertException)" +notation assert_not_equals ("assert'_not'_equals'(_, _')") +notation assert_not_equals_with_message ("assert'_not'_equals'(_, _, _')") +notation assert_not_equals ("assert'_array'_not'_equals'(_, _')") +notation assert_not_equals_with_message ("assert'_array'_not'_equals'(_, _, _')") + +(* TODO: why don't the code equations of noop work here? *) +definition removeWhiteSpaceOnlyTextNodes :: "((_) object_ptr option) \ (_, unit) dom_prog" + where + "removeWhiteSpaceOnlyTextNodes _ = return ()" + + +subsection \Making the functions under test compatible with untyped languages such as JavaScript\ + +fun set_attribute_with_null :: "((_) object_ptr option) \ attr_key \ attr_value \ (_, unit) dom_prog" + where + "set_attribute_with_null (Some ptr) k v = (case cast ptr of + Some element_ptr \ set_attribute element_ptr k (Some v))" +fun set_attribute_with_null2 :: "((_) object_ptr option) \ attr_key \ attr_value option \ (_, unit) dom_prog" + where + "set_attribute_with_null2 (Some ptr) k v = (case cast ptr of + Some element_ptr \ set_attribute element_ptr k v)" +notation set_attribute_with_null ("_ . setAttribute'(_, _')") +notation set_attribute_with_null2 ("_ . setAttribute'(_, _')") + +fun get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_with_null :: "((_) object_ptr option) \ (_, (_) object_ptr option list) dom_prog" + where + "get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_with_null (Some ptr) = do { + children \ get_child_nodes ptr; + return (map (Some \ cast) children) + }" +notation get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_with_null ("_ . childNodes") + +fun create_element_with_null :: "((_) object_ptr option) \ string \ (_, ((_) object_ptr option)) dom_prog" + where + "create_element_with_null (Some owner_document_obj) tag = (case cast owner_document_obj of + Some owner_document \ do { + element_ptr \ create_element owner_document tag; + return (Some (cast element_ptr))})" +notation create_element_with_null ("_ . createElement'(_')") + +fun create_character_data_with_null :: "((_) object_ptr option) \ string \ (_, ((_) object_ptr option)) dom_prog" + where + "create_character_data_with_null (Some owner_document_obj) tag = (case cast owner_document_obj of + Some owner_document \ do { + character_data_ptr \ create_character_data owner_document tag; + return (Some (cast character_data_ptr))})" +notation create_character_data_with_null ("_ . createTextNode'(_')") + +definition create_document_with_null :: "string \ (_, ((_::linorder) object_ptr option)) dom_prog" + where + "create_document_with_null title = do { + new_document_ptr \ create_document; + html \ create_element new_document_ptr ''html''; + append_child (cast new_document_ptr) (cast html); + heap \ create_element new_document_ptr ''heap''; + append_child (cast html) (cast heap); + body \ create_element new_document_ptr ''body''; + append_child (cast html) (cast body); + return (Some (cast new_document_ptr)) + }" +abbreviation "create_document_with_null2 _ _ _ \ create_document_with_null ''''" +notation create_document_with_null ("createDocument'(_')") +notation create_document_with_null2 ("createDocument'(_, _, _')") + +fun get_element_by_id_with_null :: + "((_::linorder) object_ptr option) \ string \ (_, ((_) object_ptr option)) dom_prog" + where + "get_element_by_id_with_null (Some ptr) id' = do { + element_ptr_opt \ get_element_by_id ptr id'; + (case element_ptr_opt of + Some element_ptr \ return (Some (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r element_ptr)) + | None \ return None)}" + | "get_element_by_id_with_null _ _ = error SegmentationFault" +notation get_element_by_id_with_null ("_ . getElementById'(_')") + +fun get_elements_by_class_name_with_null :: + "((_::linorder) object_ptr option) \ string \ (_, ((_) object_ptr option) list) dom_prog" + where + "get_elements_by_class_name_with_null (Some ptr) class_name = + get_elements_by_class_name ptr class_name \ map_M (return \ Some \ cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r)" +notation get_elements_by_class_name_with_null ("_ . getElementsByClassName'(_')") + +fun get_elements_by_tag_name_with_null :: + "((_::linorder) object_ptr option) \ string \ (_, ((_) object_ptr option) list) dom_prog" + where + "get_elements_by_tag_name_with_null (Some ptr) tag = + get_elements_by_tag_name ptr tag \ map_M (return \ Some \ cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r)" +notation get_elements_by_tag_name_with_null ("_ . getElementsByTagName'(_')") + +fun insert_before_with_null :: + "((_::linorder) object_ptr option) \ ((_) object_ptr option) \ ((_) object_ptr option) \ +(_, ((_) object_ptr option)) dom_prog" + where + "insert_before_with_null (Some ptr) (Some child_obj) ref_child_obj_opt = (case cast child_obj of + Some child \ do { + (case ref_child_obj_opt of + Some ref_child_obj \ insert_before ptr child (cast ref_child_obj) + | None \ insert_before ptr child None); + return (Some child_obj)} + | None \ error HierarchyRequestError)" +notation insert_before_with_null ("_ . insertBefore'(_, _')") + +fun append_child_with_null :: + "((_::linorder) object_ptr option) \ ((_) object_ptr option) \ (_, unit) dom_prog" + where + "append_child_with_null (Some ptr) (Some child_obj) = (case cast child_obj of + Some child \ append_child ptr child + | None \ error SegmentationFault)" +notation append_child_with_null ("_ . appendChild'(_')") +code_thms append_child_with_null +fun get_body :: "((_::linorder) object_ptr option) \ (_, ((_) object_ptr option)) dom_prog" + where + "get_body ptr = do { + ptrs \ ptr . getElementsByTagName(''body''); + return (hd ptrs) + }" +notation get_body ("_ . body") + +fun get_document_element_with_null :: + "((_::linorder) object_ptr option) \ (_, ((_) object_ptr option)) dom_prog" + where + "get_document_element_with_null (Some ptr) = (case cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr of + Some document_ptr \ do { + element_ptr_opt \ get_M document_ptr document_element; + return (case element_ptr_opt of + Some element_ptr \ Some (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r element_ptr) + | None \ None)})" +notation get_document_element_with_null ("_ . documentElement") + +fun get_owner_document_with_null :: "((_::linorder) object_ptr option) \ (_, ((_) object_ptr option)) dom_prog" + where + "get_owner_document_with_null (Some ptr) = (do { + document_ptr \ get_owner_document ptr; + return (Some (cast\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r document_ptr))})" +notation get_owner_document_with_null ("_ . ownerDocument") + +fun remove_with_null :: "((_::linorder) object_ptr option) \ (_, ((_) object_ptr option)) dom_prog" + where + "remove_with_null (Some child) = (case cast child of + Some child_node \ do { + remove child_node; + return (Some child)} + | None \ error NotFoundError)" + | "remove_with_null None = error TypeError" +notation remove_with_null ("_ . remove'(')") + +fun remove_child_with_null :: + "((_::linorder) object_ptr option) \ ((_) object_ptr option) \ (_, ((_) object_ptr option)) dom_prog" + where + "remove_child_with_null (Some ptr) (Some child) = (case cast child of + Some child_node \ do { + remove_child ptr child_node; + return (Some child)} + | None \ error NotFoundError)" + | "remove_child_with_null None _ = error TypeError" + | "remove_child_with_null _ None = error TypeError" +notation remove_child_with_null ("_ . removeChild") + +fun get_tag_name_with_null :: "((_) object_ptr option) \ (_, attr_value) dom_prog" + where + "get_tag_name_with_null (Some ptr) = (case cast ptr of + Some element_ptr \ get_M element_ptr tag_name)" +notation get_tag_name_with_null ("_ . tagName") + +abbreviation "remove_attribute_with_null ptr k \ set_attribute_with_null2 ptr k None" +notation remove_attribute_with_null ("_ . removeAttribute'(_')") + +fun get_attribute_with_null :: "((_) object_ptr option) \ attr_key \ (_, attr_value option) dom_prog" + where + "get_attribute_with_null (Some ptr) k = (case cast ptr of + Some element_ptr \ get_attribute element_ptr k)" +fun get_attribute_with_null2 :: "((_) object_ptr option) \ attr_key \ (_, attr_value) dom_prog" + where + "get_attribute_with_null2 (Some ptr) k = (case cast ptr of + Some element_ptr \ do { + a \ get_attribute element_ptr k; + return (the a)})" +notation get_attribute_with_null ("_ . getAttribute'(_')") +notation get_attribute_with_null2 ("_ . getAttribute'(_')") + +fun get_parent_with_null :: "((_::linorder) object_ptr option) \ (_, (_) object_ptr option) dom_prog" + where + "get_parent_with_null (Some ptr) = (case cast ptr of + Some node_ptr \ get_parent node_ptr)" +notation get_parent_with_null ("_ . parentNode") + +fun first_child_with_null :: "((_) object_ptr option) \ (_, ((_) object_ptr option)) dom_prog" + where + "first_child_with_null (Some ptr) = do { + child_opt \ first_child ptr; + return (case child_opt of + Some child \ Some (cast child) + | None \ None)}" +notation first_child_with_null ("_ . firstChild") + +fun adopt_node_with_null :: + "((_::linorder) object_ptr option) \ ((_) object_ptr option) \ (_, ((_) object_ptr option)) dom_prog" + where + "adopt_node_with_null (Some ptr) (Some child) = (case cast ptr of + Some document_ptr \ (case cast child of + Some child_node \ do { + adopt_node document_ptr child_node; + return (Some child)}))" +notation adopt_node_with_null ("_ . adoptNode'(_')") + + +fun get_shadow_root_with_null :: "((_) object_ptr option) \ (_, (_) object_ptr option) dom_prog" + where + "get_shadow_root_with_null (Some ptr) = (case cast ptr of + Some element_ptr \ do { + shadow_root \ get_shadow_root element_ptr; + (case shadow_root of Some sr \ return (Some (cast sr)) + | None \ return None)})" +notation get_shadow_root_with_null ("_ . shadowRoot") + + +subsection \Making the functions under test compatible with untyped languages such as JavaScript\ +fun get_element_by_id_si_with_null :: + "(_::linorder) object_ptr option \ string \ (_, (_) object_ptr option) dom_prog" + where + "get_element_by_id_si_with_null (Some ptr) id' = do { + element_ptr_opt \ get_element_by_id_si ptr id'; + (case element_ptr_opt of + Some element_ptr \ return (Some (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r element_ptr)) + | None \ return None)}" + | "get_element_by_id_si_with_null _ _ = error SegmentationFault" + +fun find_slot_closed_with_null :: + "(_::linorder) object_ptr option \ (_, (_) object_ptr option) dom_prog" + where + "find_slot_closed_with_null (Some ptr) = (case cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr of + Some node_ptr \ do { + element_ptr_opt \ find_slot True node_ptr; + (case element_ptr_opt of + Some element_ptr \ return (Some (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r element_ptr)) + | None \ return None)} + | None \ error SegmentationFault)" + | "find_slot_closed_with_null None = error SegmentationFault" +notation find_slot_closed_with_null ("_ . assignedSlot") + +fun assigned_nodes_with_null :: + "(_::linorder) object_ptr option \ (_, (_) object_ptr option list) dom_prog" + where + "assigned_nodes_with_null (Some ptr) = (case cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr of + Some element_ptr \ do { + l \ assigned_nodes element_ptr; + return (map Some (map cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r l))} + | None \ error SegmentationFault)" + | "assigned_nodes_with_null None = error SegmentationFault" +notation assigned_nodes_with_null ("_ . assignedNodes'(')") + +fun assigned_nodes_flatten_with_null :: + "(_::linorder) object_ptr option \ (_, (_) object_ptr option list) dom_prog" + where + "assigned_nodes_flatten_with_null (Some ptr) = (case cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr of + Some element_ptr \ do { + l \ assigned_nodes_flatten element_ptr; + return (map Some (map cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r l))} + | None \ error SegmentationFault)" + | "assigned_nodes_flatten_with_null None = error SegmentationFault" +notation assigned_nodes_flatten_with_null ("_ . assignedNodes'(True')") + +fun get_assigned_elements_with_null :: + "(_::linorder) object_ptr option \ (_, (_) object_ptr option list) dom_prog" + where + "get_assigned_elements_with_null (Some ptr) = (case cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr of + Some element_ptr \ do { + l \ assigned_nodes element_ptr; + l \ map_filter_M (return \ cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r) l; + return (map Some (map cast l))} + | None \ error SegmentationFault)" + | "get_assigned_elements_with_null None = error SegmentationFault" +notation get_assigned_elements_with_null ("_ . assignedElements'(')") + +fun get_assigned_elements_flatten_with_null :: + "(_::linorder) object_ptr option \ (_, (_) object_ptr option list) dom_prog" + where + "get_assigned_elements_flatten_with_null (Some ptr) = (case cast\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ptr of + Some element_ptr \ do { + l \ assigned_nodes_flatten element_ptr; + return (map Some (map cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r l))} + | None \ error SegmentationFault)" + | "get_assigned_elements_flatten_with_null None = error SegmentationFault" +notation get_assigned_elements_flatten_with_null ("_ . assignedElements'(True')") + +fun createTestTree :: + "(_::linorder) object_ptr option \ (_, string \ (_, (_) object_ptr option) dom_prog) dom_prog" + where + "createTestTree (Some ref) = do { + tups \ to_tree_order_si ref \ map_filter_M (\ptr. do { + (case cast ptr of + Some element_ptr \ do { + iden_opt \ get_attribute element_ptr ''id''; + (case iden_opt of + Some iden \ return (Some (iden, ptr)) + | None \ return None) + } + | None \ return None)}); + return (return \ map_of tups) + }" + | "createTestTree None = error SegmentationFault" + + +end diff --git a/Shadow_DOM/tests/Shadow_DOM_Document_adoptNode.thy b/Shadow_DOM/tests/Shadow_DOM_Document_adoptNode.thy new file mode 100644 index 0000000..024a66b --- /dev/null +++ b/Shadow_DOM/tests/Shadow_DOM_Document_adoptNode.thy @@ -0,0 +1,114 @@ +(*********************************************************************************** + * Copyright (c) 2016-2020 The University of Sheffield, UK + * 2019-2020 University of Exeter, UK + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-2-Clause + ***********************************************************************************) + +(* This file is automatically generated, please do not modify! *) + +section\Testing Document\_adoptNode\ +text\This theory contains the test cases for Document\_adoptNode.\ + +theory Shadow_DOM_Document_adoptNode +imports + "Shadow_DOM_BaseTest" +begin + +definition Document_adoptNode_heap :: heap\<^sub>f\<^sub>i\<^sub>n\<^sub>a\<^sub>l where + "Document_adoptNode_heap = create_heap [(cast (document_ptr.Ref 1), cast (create_document_obj html (Some (cast (element_ptr.Ref 1))) [])), + (cast (element_ptr.Ref 1), cast (create_element_obj ''html'' [cast (element_ptr.Ref 2), cast (element_ptr.Ref 8)] fmempty None)), + (cast (element_ptr.Ref 2), cast (create_element_obj ''head'' [cast (element_ptr.Ref 3), cast (element_ptr.Ref 4), cast (element_ptr.Ref 5), cast (element_ptr.Ref 6), cast (element_ptr.Ref 7)] fmempty None)), + (cast (element_ptr.Ref 3), cast (create_element_obj ''meta'' [] (fmap_of_list [(''charset'', ''utf-8'')]) None)), + (cast (element_ptr.Ref 4), cast (create_element_obj ''title'' [cast (character_data_ptr.Ref 1)] fmempty None)), + (cast (character_data_ptr.Ref 1), cast (create_character_data_obj ''Document.adoptNode'')), + (cast (element_ptr.Ref 5), cast (create_element_obj ''link'' [] (fmap_of_list [(''rel'', ''help''), (''href'', ''https://dom.spec.whatwg.org/#dom-document-adoptnode'')]) None)), + (cast (element_ptr.Ref 6), cast (create_element_obj ''script'' [] (fmap_of_list [(''src'', ''/resources/testharness.js'')]) None)), + (cast (element_ptr.Ref 7), cast (create_element_obj ''script'' [] (fmap_of_list [(''src'', ''/resources/testharnessreport.js'')]) None)), + (cast (element_ptr.Ref 8), cast (create_element_obj ''body'' [cast (element_ptr.Ref 9), cast (element_ptr.Ref 10), cast (element_ptr.Ref 11)] fmempty None)), + (cast (element_ptr.Ref 9), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''log'')]) None)), + (cast (element_ptr.Ref 10), cast (create_element_obj ''x<'' [cast (character_data_ptr.Ref 2)] fmempty None)), + (cast (character_data_ptr.Ref 2), cast (create_character_data_obj ''x'')), + (cast (element_ptr.Ref 11), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 3)] fmempty None)), + (cast (character_data_ptr.Ref 3), cast (create_character_data_obj ''%3C%3Cscript%3E%3E''))]" + +definition Document_adoptNode_document :: "(unit, unit, unit, unit, unit, unit) object_ptr option" where "Document_adoptNode_document = Some (cast (document_ptr.Ref 1))" + + +text \"Adopting an Element called 'x<' should work."\ + +lemma "test (do { + tmp0 \ Document_adoptNode_document . getElementsByTagName(''x<''); + y \ return (tmp0 ! 0); + child \ y . firstChild; + tmp1 \ y . parentNode; + tmp2 \ Document_adoptNode_document . body; + assert_equals(tmp1, tmp2); + tmp3 \ y . ownerDocument; + assert_equals(tmp3, Document_adoptNode_document); + tmp4 \ Document_adoptNode_document . adoptNode(y); + assert_equals(tmp4, y); + tmp5 \ y . parentNode; + assert_equals(tmp5, None); + tmp6 \ y . firstChild; + assert_equals(tmp6, child); + tmp7 \ y . ownerDocument; + assert_equals(tmp7, Document_adoptNode_document); + tmp8 \ child . ownerDocument; + assert_equals(tmp8, Document_adoptNode_document); + doc \ createDocument(None, None, None); + tmp9 \ doc . adoptNode(y); + assert_equals(tmp9, y); + tmp10 \ y . parentNode; + assert_equals(tmp10, None); + tmp11 \ y . firstChild; + assert_equals(tmp11, child); + tmp12 \ y . ownerDocument; + assert_equals(tmp12, doc); + tmp13 \ child . ownerDocument; + assert_equals(tmp13, doc) +}) Document_adoptNode_heap" + by eval + + +text \"Adopting an Element called ':good:times:' should work."\ + +lemma "test (do { + x \ Document_adoptNode_document . createElement('':good:times:''); + tmp0 \ Document_adoptNode_document . adoptNode(x); + assert_equals(tmp0, x); + doc \ createDocument(None, None, None); + tmp1 \ doc . adoptNode(x); + assert_equals(tmp1, x); + tmp2 \ x . parentNode; + assert_equals(tmp2, None); + tmp3 \ x . ownerDocument; + assert_equals(tmp3, doc) +}) Document_adoptNode_heap" + by eval + + +end diff --git a/Shadow_DOM/tests/Shadow_DOM_Document_getElementById.thy b/Shadow_DOM/tests/Shadow_DOM_Document_getElementById.thy new file mode 100644 index 0000000..fbcf887 --- /dev/null +++ b/Shadow_DOM/tests/Shadow_DOM_Document_getElementById.thy @@ -0,0 +1,278 @@ +(*********************************************************************************** + * Copyright (c) 2016-2020 The University of Sheffield, UK + * 2019-2020 University of Exeter, UK + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-2-Clause + ***********************************************************************************) + +(* This file is automatically generated, please do not modify! *) + +section\Testing Document\_getElementById\ +text\This theory contains the test cases for Document\_getElementById.\ + +theory Shadow_DOM_Document_getElementById +imports + "Shadow_DOM_BaseTest" +begin + +definition Document_getElementById_heap :: heap\<^sub>f\<^sub>i\<^sub>n\<^sub>a\<^sub>l where + "Document_getElementById_heap = create_heap [(cast (document_ptr.Ref 1), cast (create_document_obj html (Some (cast (element_ptr.Ref 1))) [])), + (cast (element_ptr.Ref 1), cast (create_element_obj ''html'' [cast (element_ptr.Ref 2), cast (element_ptr.Ref 9)] fmempty None)), + (cast (element_ptr.Ref 2), cast (create_element_obj ''head'' [cast (element_ptr.Ref 3), cast (element_ptr.Ref 4), cast (element_ptr.Ref 5), cast (element_ptr.Ref 6), cast (element_ptr.Ref 7), cast (element_ptr.Ref 8)] fmempty None)), + (cast (element_ptr.Ref 3), cast (create_element_obj ''meta'' [] (fmap_of_list [(''charset'', ''utf-8'')]) None)), + (cast (element_ptr.Ref 4), cast (create_element_obj ''title'' [cast (character_data_ptr.Ref 1)] fmempty None)), + (cast (character_data_ptr.Ref 1), cast (create_character_data_obj ''Document.getElementById'')), + (cast (element_ptr.Ref 5), cast (create_element_obj ''link'' [] (fmap_of_list [(''rel'', ''author''), (''title'', ''Tetsuharu OHZEKI''), (''href'', ''mailto:saneyuki.snyk@gmail.com'')]) None)), + (cast (element_ptr.Ref 6), cast (create_element_obj ''link'' [] (fmap_of_list [(''rel'', ''help''), (''href'', ''https://dom.spec.whatwg.org/#dom-document-getelementbyid'')]) None)), + (cast (element_ptr.Ref 7), cast (create_element_obj ''script'' [] (fmap_of_list [(''src'', ''/resources/testharness.js'')]) None)), + (cast (element_ptr.Ref 8), cast (create_element_obj ''script'' [] (fmap_of_list [(''src'', ''/resources/testharnessreport.js'')]) None)), + (cast (element_ptr.Ref 9), cast (create_element_obj ''body'' [cast (element_ptr.Ref 10), cast (element_ptr.Ref 11), cast (element_ptr.Ref 12), cast (element_ptr.Ref 13), cast (element_ptr.Ref 16), cast (element_ptr.Ref 19)] fmempty None)), + (cast (element_ptr.Ref 10), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''log'')]) None)), + (cast (element_ptr.Ref 11), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', '''')]) None)), + (cast (element_ptr.Ref 12), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''test1'')]) None)), + (cast (element_ptr.Ref 13), cast (create_element_obj ''div'' [cast (element_ptr.Ref 14), cast (element_ptr.Ref 15)] (fmap_of_list [(''id'', ''test5''), (''data-name'', ''1st'')]) None)), + (cast (element_ptr.Ref 14), cast (create_element_obj ''p'' [cast (character_data_ptr.Ref 2)] (fmap_of_list [(''id'', ''test5''), (''data-name'', ''2nd'')]) None)), + (cast (character_data_ptr.Ref 2), cast (create_character_data_obj ''P'')), + (cast (element_ptr.Ref 15), cast (create_element_obj ''input'' [] (fmap_of_list [(''id'', ''test5''), (''type'', ''submit''), (''value'', ''Submit''), (''data-name'', ''3rd'')]) None)), + (cast (element_ptr.Ref 16), cast (create_element_obj ''div'' [cast (element_ptr.Ref 17)] (fmap_of_list [(''id'', ''outer'')]) None)), + (cast (element_ptr.Ref 17), cast (create_element_obj ''div'' [cast (element_ptr.Ref 18)] (fmap_of_list [(''id'', ''middle'')]) None)), + (cast (element_ptr.Ref 18), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''inner'')]) None)), + (cast (element_ptr.Ref 19), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 3)] fmempty None)), + (cast (character_data_ptr.Ref 3), cast (create_character_data_obj ''%3C%3Cscript%3E%3E''))]" + +definition Document_getElementById_document :: "(unit, unit, unit, unit, unit, unit) object_ptr option" where "Document_getElementById_document = Some (cast (document_ptr.Ref 1))" + + +text \"Document.getElementById with a script-inserted element"\ + +lemma "test (do { + gBody \ Document_getElementById_document . body; + TEST_ID \ return ''test2''; + test \ Document_getElementById_document . createElement(''div''); + test . setAttribute(''id'', TEST_ID); + gBody . appendChild(test); + result \ Document_getElementById_document . getElementById(TEST_ID); + assert_not_equals(result, None, ''should not be null.''); + tmp0 \ result . tagName; + assert_equals(tmp0, ''div'', ''should have appended element's tag name''); + gBody . removeChild(test); + removed \ Document_getElementById_document . getElementById(TEST_ID); + assert_equals(removed, None, ''should not get removed element.'') +}) Document_getElementById_heap" + by eval + + +text \"update `id` attribute via setAttribute/removeAttribute"\ + +lemma "test (do { + gBody \ Document_getElementById_document . body; + TEST_ID \ return ''test3''; + test \ Document_getElementById_document . createElement(''div''); + test . setAttribute(''id'', TEST_ID); + gBody . appendChild(test); + UPDATED_ID \ return ''test3-updated''; + test . setAttribute(''id'', UPDATED_ID); + e \ Document_getElementById_document . getElementById(UPDATED_ID); + assert_equals(e, test, ''should get the element with id.''); + old \ Document_getElementById_document . getElementById(TEST_ID); + assert_equals(old, None, ''shouldn't get the element by the old id.''); + test . removeAttribute(''id''); + e2 \ Document_getElementById_document . getElementById(UPDATED_ID); + assert_equals(e2, None, ''should return null when the passed id is none in document.'') +}) Document_getElementById_heap" + by eval + + +text \"Ensure that the id attribute only affects elements present in a document"\ + +lemma "test (do { + TEST_ID \ return ''test4-should-not-exist''; + e \ Document_getElementById_document . createElement(''div''); + e . setAttribute(''id'', TEST_ID); + tmp0 \ Document_getElementById_document . getElementById(TEST_ID); + assert_equals(tmp0, None, ''should be null''); + tmp1 \ Document_getElementById_document . body; + tmp1 . appendChild(e); + tmp2 \ Document_getElementById_document . getElementById(TEST_ID); + assert_equals(tmp2, e, ''should be the appended element'') +}) Document_getElementById_heap" + by eval + + +text \"in tree order, within the context object's tree"\ + +lemma "test (do { + gBody \ Document_getElementById_document . body; + TEST_ID \ return ''test5''; + target \ Document_getElementById_document . getElementById(TEST_ID); + assert_not_equals(target, None, ''should not be null''); + tmp0 \ target . getAttribute(''data-name''); + assert_equals(tmp0, ''1st'', ''should return the 1st''); + element4 \ Document_getElementById_document . createElement(''div''); + element4 . setAttribute(''id'', TEST_ID); + element4 . setAttribute(''data-name'', ''4th''); + gBody . appendChild(element4); + target2 \ Document_getElementById_document . getElementById(TEST_ID); + assert_not_equals(target2, None, ''should not be null''); + tmp1 \ target2 . getAttribute(''data-name''); + assert_equals(tmp1, ''1st'', ''should be the 1st''); + tmp2 \ target2 . parentNode; + tmp2 . removeChild(target2); + target3 \ Document_getElementById_document . getElementById(TEST_ID); + assert_not_equals(target3, None, ''should not be null''); + tmp3 \ target3 . getAttribute(''data-name''); + assert_equals(tmp3, ''4th'', ''should be the 4th'') +}) Document_getElementById_heap" + by eval + + +text \"Modern browsers optimize this method with using internal id cache. This test checks that their optimization should effect only append to `Document`, not append to `Node`."\ + +lemma "test (do { + TEST_ID \ return ''test6''; + s \ Document_getElementById_document . createElement(''div''); + s . setAttribute(''id'', TEST_ID); + tmp0 \ Document_getElementById_document . createElement(''div''); + tmp0 . appendChild(s); + tmp1 \ Document_getElementById_document . getElementById(TEST_ID); + assert_equals(tmp1, None, ''should be null'') +}) Document_getElementById_heap" + by eval + + +text \"changing attribute's value via `Attr` gotten from `Element.attribute`."\ + +lemma "test (do { + gBody \ Document_getElementById_document . body; + TEST_ID \ return ''test7''; + element \ Document_getElementById_document . createElement(''div''); + element . setAttribute(''id'', TEST_ID); + gBody . appendChild(element); + target \ Document_getElementById_document . getElementById(TEST_ID); + assert_equals(target, element, ''should return the element before changing the value''); + element . setAttribute(''id'', (TEST_ID @ ''-updated'')); + target2 \ Document_getElementById_document . getElementById(TEST_ID); + assert_equals(target2, None, ''should return null after updated id via Attr.value''); + target3 \ Document_getElementById_document . getElementById((TEST_ID @ ''-updated'')); + assert_equals(target3, element, ''should be equal to the updated element.'') +}) Document_getElementById_heap" + by eval + + +text \"update `id` attribute via element.id"\ + +lemma "test (do { + gBody \ Document_getElementById_document . body; + TEST_ID \ return ''test12''; + test \ Document_getElementById_document . createElement(''div''); + test . setAttribute(''id'', TEST_ID); + gBody . appendChild(test); + UPDATED_ID \ return (TEST_ID @ ''-updated''); + test . setAttribute(''id'', UPDATED_ID); + e \ Document_getElementById_document . getElementById(UPDATED_ID); + assert_equals(e, test, ''should get the element with id.''); + old \ Document_getElementById_document . getElementById(TEST_ID); + assert_equals(old, None, ''shouldn't get the element by the old id.''); + test . setAttribute(''id'', ''''); + e2 \ Document_getElementById_document . getElementById(UPDATED_ID); + assert_equals(e2, None, ''should return null when the passed id is none in document.'') +}) Document_getElementById_heap" + by eval + + +text \"where insertion order and tree order don't match"\ + +lemma "test (do { + gBody \ Document_getElementById_document . body; + TEST_ID \ return ''test13''; + container \ Document_getElementById_document . createElement(''div''); + container . setAttribute(''id'', (TEST_ID @ ''-fixture'')); + gBody . appendChild(container); + element1 \ Document_getElementById_document . createElement(''div''); + element1 . setAttribute(''id'', TEST_ID); + element2 \ Document_getElementById_document . createElement(''div''); + element2 . setAttribute(''id'', TEST_ID); + element3 \ Document_getElementById_document . createElement(''div''); + element3 . setAttribute(''id'', TEST_ID); + element4 \ Document_getElementById_document . createElement(''div''); + element4 . setAttribute(''id'', TEST_ID); + container . appendChild(element2); + container . appendChild(element4); + container . insertBefore(element3, element4); + container . insertBefore(element1, element2); + test \ Document_getElementById_document . getElementById(TEST_ID); + assert_equals(test, element1, ''should return 1st element''); + container . removeChild(element1); + test \ Document_getElementById_document . getElementById(TEST_ID); + assert_equals(test, element2, ''should return 2nd element''); + container . removeChild(element2); + test \ Document_getElementById_document . getElementById(TEST_ID); + assert_equals(test, element3, ''should return 3rd element''); + container . removeChild(element3); + test \ Document_getElementById_document . getElementById(TEST_ID); + assert_equals(test, element4, ''should return 4th element''); + container . removeChild(element4) +}) Document_getElementById_heap" + by eval + + +text \"Inserting an id by inserting its parent node"\ + +lemma "test (do { + gBody \ Document_getElementById_document . body; + TEST_ID \ return ''test14''; + a \ Document_getElementById_document . createElement(''a''); + b \ Document_getElementById_document . createElement(''b''); + a . appendChild(b); + b . setAttribute(''id'', TEST_ID); + tmp0 \ Document_getElementById_document . getElementById(TEST_ID); + assert_equals(tmp0, None); + gBody . appendChild(a); + tmp1 \ Document_getElementById_document . getElementById(TEST_ID); + assert_equals(tmp1, b) +}) Document_getElementById_heap" + by eval + + +text \"Document.getElementById must not return nodes not present in document"\ + +lemma "test (do { + TEST_ID \ return ''test15''; + outer \ Document_getElementById_document . getElementById(''outer''); + middle \ Document_getElementById_document . getElementById(''middle''); + inner \ Document_getElementById_document . getElementById(''inner''); + tmp0 \ Document_getElementById_document . getElementById(''middle''); + outer . removeChild(tmp0); + new_el \ Document_getElementById_document . createElement(''h1''); + new_el . setAttribute(''id'', ''heading''); + inner . appendChild(new_el); + tmp1 \ Document_getElementById_document . getElementById(''heading''); + assert_equals(tmp1, None) +}) Document_getElementById_heap" + by eval + + +end diff --git a/Shadow_DOM/tests/Shadow_DOM_Node_insertBefore.thy b/Shadow_DOM/tests/Shadow_DOM_Node_insertBefore.thy new file mode 100644 index 0000000..0f463f8 --- /dev/null +++ b/Shadow_DOM/tests/Shadow_DOM_Node_insertBefore.thy @@ -0,0 +1,129 @@ +(*********************************************************************************** + * Copyright (c) 2016-2020 The University of Sheffield, UK + * 2019-2020 University of Exeter, UK + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-2-Clause + ***********************************************************************************) + +(* This file is automatically generated, please do not modify! *) + +section\Testing Node\_insertBefore\ +text\This theory contains the test cases for Node\_insertBefore.\ + +theory Shadow_DOM_Node_insertBefore +imports + "Shadow_DOM_BaseTest" +begin + +definition Node_insertBefore_heap :: heap\<^sub>f\<^sub>i\<^sub>n\<^sub>a\<^sub>l where + "Node_insertBefore_heap = create_heap [(cast (document_ptr.Ref 1), cast (create_document_obj html (Some (cast (element_ptr.Ref 1))) [])), + (cast (element_ptr.Ref 1), cast (create_element_obj ''html'' [cast (element_ptr.Ref 2), cast (element_ptr.Ref 6)] fmempty None)), + (cast (element_ptr.Ref 2), cast (create_element_obj ''head'' [cast (element_ptr.Ref 3), cast (element_ptr.Ref 4), cast (element_ptr.Ref 5)] fmempty None)), + (cast (element_ptr.Ref 3), cast (create_element_obj ''title'' [cast (character_data_ptr.Ref 1)] fmempty None)), + (cast (character_data_ptr.Ref 1), cast (create_character_data_obj ''Node.insertBefore'')), + (cast (element_ptr.Ref 4), cast (create_element_obj ''script'' [] (fmap_of_list [(''src'', ''/resources/testharness.js'')]) None)), + (cast (element_ptr.Ref 5), cast (create_element_obj ''script'' [] (fmap_of_list [(''src'', ''/resources/testharnessreport.js'')]) None)), + (cast (element_ptr.Ref 6), cast (create_element_obj ''body'' [cast (element_ptr.Ref 7), cast (element_ptr.Ref 8)] fmempty None)), + (cast (element_ptr.Ref 7), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''log'')]) None)), + (cast (element_ptr.Ref 8), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 2)] fmempty None)), + (cast (character_data_ptr.Ref 2), cast (create_character_data_obj ''%3C%3Cscript%3E%3E''))]" + +definition Node_insertBefore_document :: "(unit, unit, unit, unit, unit, unit) object_ptr option" where "Node_insertBefore_document = Some (cast (document_ptr.Ref 1))" + + +text \"Calling insertBefore an a leaf node Text must throw HIERARCHY\_REQUEST\_ERR."\ + +lemma "test (do { + node \ Node_insertBefore_document . createTextNode(''Foo''); + tmp0 \ Node_insertBefore_document . createTextNode(''fail''); + assert_throws(HierarchyRequestError, node . insertBefore(tmp0, None)) +}) Node_insertBefore_heap" + by eval + + +text \"Calling insertBefore with an inclusive ancestor of the context object must throw HIERARCHY\_REQUEST\_ERR."\ + +lemma "test (do { + tmp1 \ Node_insertBefore_document . body; + tmp2 \ Node_insertBefore_document . getElementById(''log''); + tmp0 \ Node_insertBefore_document . body; + assert_throws(HierarchyRequestError, tmp0 . insertBefore(tmp1, tmp2)); + tmp4 \ Node_insertBefore_document . documentElement; + tmp5 \ Node_insertBefore_document . getElementById(''log''); + tmp3 \ Node_insertBefore_document . body; + assert_throws(HierarchyRequestError, tmp3 . insertBefore(tmp4, tmp5)) +}) Node_insertBefore_heap" + by eval + + +text \"Calling insertBefore with a reference child whose parent is not the context node must throw a NotFoundError."\ + +lemma "test (do { + a \ Node_insertBefore_document . createElement(''div''); + b \ Node_insertBefore_document . createElement(''div''); + c \ Node_insertBefore_document . createElement(''div''); + assert_throws(NotFoundError, a . insertBefore(b, c)) +}) Node_insertBefore_heap" + by eval + + +text \"If the context node is a document, inserting a document or text node should throw a HierarchyRequestError."\ + +lemma "test (do { + doc \ createDocument(''title''); + doc2 \ createDocument(''title2''); + tmp0 \ doc . documentElement; + assert_throws(HierarchyRequestError, doc . insertBefore(doc2, tmp0)); + tmp1 \ doc . createTextNode(''text''); + tmp2 \ doc . documentElement; + assert_throws(HierarchyRequestError, doc . insertBefore(tmp1, tmp2)) +}) Node_insertBefore_heap" + by eval + + +text \"Inserting a node before itself should not move the node"\ + +lemma "test (do { + a \ Node_insertBefore_document . createElement(''div''); + b \ Node_insertBefore_document . createElement(''div''); + c \ Node_insertBefore_document . createElement(''div''); + a . appendChild(b); + a . appendChild(c); + tmp0 \ a . childNodes; + assert_array_equals(tmp0, [b, c]); + tmp1 \ a . insertBefore(b, b); + assert_equals(tmp1, b); + tmp2 \ a . childNodes; + assert_array_equals(tmp2, [b, c]); + tmp3 \ a . insertBefore(c, c); + assert_equals(tmp3, c); + tmp4 \ a . childNodes; + assert_array_equals(tmp4, [b, c]) +}) Node_insertBefore_heap" + by eval + + +end diff --git a/Shadow_DOM/tests/Shadow_DOM_Node_removeChild.thy b/Shadow_DOM/tests/Shadow_DOM_Node_removeChild.thy new file mode 100644 index 0000000..1cd043f --- /dev/null +++ b/Shadow_DOM/tests/Shadow_DOM_Node_removeChild.thy @@ -0,0 +1,160 @@ +(*********************************************************************************** + * Copyright (c) 2016-2020 The University of Sheffield, UK + * 2019-2020 University of Exeter, UK + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-2-Clause + ***********************************************************************************) + +(* This file is automatically generated, please do not modify! *) + +section\Testing Node\_removeChild\ +text\This theory contains the test cases for Node\_removeChild.\ + +theory Shadow_DOM_Node_removeChild +imports + "Shadow_DOM_BaseTest" +begin + +definition Node_removeChild_heap :: heap\<^sub>f\<^sub>i\<^sub>n\<^sub>a\<^sub>l where + "Node_removeChild_heap = create_heap [(cast (document_ptr.Ref 1), cast (create_document_obj html (Some (cast (element_ptr.Ref 1))) [])), + (cast (element_ptr.Ref 1), cast (create_element_obj ''html'' [cast (element_ptr.Ref 2), cast (element_ptr.Ref 7)] fmempty None)), + (cast (element_ptr.Ref 2), cast (create_element_obj ''head'' [cast (element_ptr.Ref 3), cast (element_ptr.Ref 4), cast (element_ptr.Ref 5), cast (element_ptr.Ref 6)] fmempty None)), + (cast (element_ptr.Ref 3), cast (create_element_obj ''title'' [cast (character_data_ptr.Ref 1)] fmempty None)), + (cast (character_data_ptr.Ref 1), cast (create_character_data_obj ''Node.removeChild'')), + (cast (element_ptr.Ref 4), cast (create_element_obj ''script'' [] (fmap_of_list [(''src'', ''/resources/testharness.js'')]) None)), + (cast (element_ptr.Ref 5), cast (create_element_obj ''script'' [] (fmap_of_list [(''src'', ''/resources/testharnessreport.js'')]) None)), + (cast (element_ptr.Ref 6), cast (create_element_obj ''script'' [] (fmap_of_list [(''src'', ''creators.js'')]) None)), + (cast (element_ptr.Ref 7), cast (create_element_obj ''body'' [cast (element_ptr.Ref 8), cast (element_ptr.Ref 9), cast (element_ptr.Ref 10)] fmempty None)), + (cast (element_ptr.Ref 8), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''log'')]) None)), + (cast (element_ptr.Ref 9), cast (create_element_obj ''iframe'' [] (fmap_of_list [(''src'', ''about:blank'')]) None)), + (cast (element_ptr.Ref 10), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 2)] fmempty None)), + (cast (character_data_ptr.Ref 2), cast (create_character_data_obj ''%3C%3Cscript%3E%3E''))]" + +definition Node_removeChild_document :: "(unit, unit, unit, unit, unit, unit) object_ptr option" where "Node_removeChild_document = Some (cast (document_ptr.Ref 1))" + + +text \"Passing a detached Element to removeChild should not affect it."\ + +lemma "test (do { + doc \ return Node_removeChild_document; + s \ doc . createElement(''div''); + tmp0 \ s . ownerDocument; + assert_equals(tmp0, doc); + tmp1 \ Node_removeChild_document . body; + assert_throws(NotFoundError, tmp1 . removeChild(s)); + tmp2 \ s . ownerDocument; + assert_equals(tmp2, doc) +}) Node_removeChild_heap" + by eval + + +text \"Passing a non-detached Element to removeChild should not affect it."\ + +lemma "test (do { + doc \ return Node_removeChild_document; + s \ doc . createElement(''div''); + tmp0 \ doc . documentElement; + tmp0 . appendChild(s); + tmp1 \ s . ownerDocument; + assert_equals(tmp1, doc); + tmp2 \ Node_removeChild_document . body; + assert_throws(NotFoundError, tmp2 . removeChild(s)); + tmp3 \ s . ownerDocument; + assert_equals(tmp3, doc) +}) Node_removeChild_heap" + by eval + + +text \"Calling removeChild on an Element with no children should throw NOT\_FOUND\_ERR."\ + +lemma "test (do { + doc \ return Node_removeChild_document; + s \ doc . createElement(''div''); + tmp0 \ doc . body; + tmp0 . appendChild(s); + tmp1 \ s . ownerDocument; + assert_equals(tmp1, doc); + assert_throws(NotFoundError, s . removeChild(doc)) +}) Node_removeChild_heap" + by eval + + +text \"Passing a detached Element to removeChild should not affect it."\ + +lemma "test (do { + doc \ createDocument(''''); + s \ doc . createElement(''div''); + tmp0 \ s . ownerDocument; + assert_equals(tmp0, doc); + tmp1 \ Node_removeChild_document . body; + assert_throws(NotFoundError, tmp1 . removeChild(s)); + tmp2 \ s . ownerDocument; + assert_equals(tmp2, doc) +}) Node_removeChild_heap" + by eval + + +text \"Passing a non-detached Element to removeChild should not affect it."\ + +lemma "test (do { + doc \ createDocument(''''); + s \ doc . createElement(''div''); + tmp0 \ doc . documentElement; + tmp0 . appendChild(s); + tmp1 \ s . ownerDocument; + assert_equals(tmp1, doc); + tmp2 \ Node_removeChild_document . body; + assert_throws(NotFoundError, tmp2 . removeChild(s)); + tmp3 \ s . ownerDocument; + assert_equals(tmp3, doc) +}) Node_removeChild_heap" + by eval + + +text \"Calling removeChild on an Element with no children should throw NOT\_FOUND\_ERR."\ + +lemma "test (do { + doc \ createDocument(''''); + s \ doc . createElement(''div''); + tmp0 \ doc . body; + tmp0 . appendChild(s); + tmp1 \ s . ownerDocument; + assert_equals(tmp1, doc); + assert_throws(NotFoundError, s . removeChild(doc)) +}) Node_removeChild_heap" + by eval + + +text \"Passing a value that is not a Node reference to removeChild should throw TypeError."\ + +lemma "test (do { + tmp0 \ Node_removeChild_document . body; + assert_throws(TypeError, tmp0 . removeChild(None)) +}) Node_removeChild_heap" + by eval + + +end diff --git a/Shadow_DOM/tests/my_get_owner_document.html b/Shadow_DOM/tests/my_get_owner_document.html new file mode 100644 index 0000000..2220ab8 --- /dev/null +++ b/Shadow_DOM/tests/my_get_owner_document.html @@ -0,0 +1,28 @@ + + + + + +
+
+ +
+
+
+ + + diff --git a/Shadow_DOM/tests/my_get_owner_document.thy b/Shadow_DOM/tests/my_get_owner_document.thy new file mode 100644 index 0000000..4c121e7 --- /dev/null +++ b/Shadow_DOM/tests/my_get_owner_document.thy @@ -0,0 +1,81 @@ +(*********************************************************************************** + * Copyright (c) 2016-2020 The University of Sheffield, UK + * 2019-2020 University of Exeter, UK + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-2-Clause + ***********************************************************************************) + +(* This file is automatically generated, please do not modify! *) + +section\Testing my\_get\_owner\_document\ +text\This theory contains the test cases for my\_get\_owner\_document.\ + +theory my_get_owner_document +imports + "Shadow_DOM_BaseTest" +begin + +definition my_get_owner_document_heap :: "heap\<^sub>f\<^sub>i\<^sub>n\<^sub>a\<^sub>l" where + "my_get_owner_document_heap = create_heap [(cast (document_ptr.Ref 1), cast (create_document_obj html (Some (cast (element_ptr.Ref 1))) [])), + (cast (element_ptr.Ref 1), cast (create_element_obj ''html'' [cast (element_ptr.Ref 2), cast (element_ptr.Ref 3)] fmempty None)), + (cast (element_ptr.Ref 2), cast (create_element_obj ''head'' [] fmempty None)), + (cast (element_ptr.Ref 3), cast (create_element_obj ''body'' [cast (element_ptr.Ref 4), cast (element_ptr.Ref 8)] fmempty None)), + (cast (element_ptr.Ref 4), cast (create_element_obj ''div'' [cast (element_ptr.Ref 5)] (fmap_of_list [(''id'', ''test'')]) None)), + (cast (element_ptr.Ref 5), cast (create_element_obj ''div'' [cast (element_ptr.Ref 6)] (fmap_of_list [(''id'', ''host'')]) (Some (cast (shadow_root_ptr.Ref 1))))), + (cast (element_ptr.Ref 6), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c1''), (''slot'', ''slot1'')]) None)), + (cast (shadow_root_ptr.Ref 1), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 7)])), + (cast (element_ptr.Ref 7), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1'')]) None)), + (cast (element_ptr.Ref 8), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 1)] fmempty None)), + (cast (character_data_ptr.Ref 1), cast (create_character_data_obj ''%3C%3Cscript%3E%3E''))]" + +definition my_get_owner_document_document :: "(unit, unit, unit, unit, unit, unit) object_ptr option" where "my_get_owner_document_document = Some (cast (document_ptr.Ref 1))" + + +text \'ownerDocument inside shadow tree returns the outer document.'\ + +lemma "test (do { + tmp0 \ my_get_owner_document_document . getElementById(''test''); + n \ createTestTree(tmp0); + tmp1 \ n . ''s1''; + tmp2 \ tmp1 . ownerDocument; + assert_equals(tmp2, my_get_owner_document_document) +}) my_get_owner_document_heap" + by eval + + +text \'ownerDocument outside shadow tree returns the outer document.'\ + +lemma "test (do { + tmp0 \ my_get_owner_document_document . getElementById(''test''); + n \ createTestTree(tmp0); + tmp1 \ n . ''c1''; + tmp2 \ tmp1 . ownerDocument; + assert_equals(tmp2, my_get_owner_document_document) +}) my_get_owner_document_heap" + by eval + + +end diff --git a/Shadow_DOM/tests/slots-fallback.html b/Shadow_DOM/tests/slots-fallback.html new file mode 100644 index 0000000..e705e18 --- /dev/null +++ b/Shadow_DOM/tests/slots-fallback.html @@ -0,0 +1,253 @@ + +Shadow DOM: Slots and fallback contents + + + + + +
+
+ +
+
+ + + +
+
+ +
+
+ + + +
+
+ +
+
+
+ + + +
+
+ +
+
+
+ + + +
+
+ +
+
+
+ + diff --git a/Shadow_DOM/tests/slots.html b/Shadow_DOM/tests/slots.html new file mode 100644 index 0000000..948d389 --- /dev/null +++ b/Shadow_DOM/tests/slots.html @@ -0,0 +1,526 @@ + +Shadow DOM: Slots and assignments + + + + + +
+
+ +
+
+
+ + + +
+
+ +
+
+
+ + + +
+ +
+ + + +
+ +
+
+ +
+ +
+
+
+
+
+ + + +
+
+ +
+
+
+
+
+ + + +
+
+ +
+
+
+
+
+
+
+ + + +
+
+ +
+
+
+
+
+ + + +
+
+ +
+
+
+
+ + + +
+
+ +
+
+
+ + + +
+
+ +
+
+
+ + + +
+
+ +
+
+
+ + + +
+
+ +
+
+
+ + + +
+
+ +
+
+
+
+
+
+ + diff --git a/Shadow_DOM/tests/slots.thy b/Shadow_DOM/tests/slots.thy new file mode 100644 index 0000000..130fef5 --- /dev/null +++ b/Shadow_DOM/tests/slots.thy @@ -0,0 +1,947 @@ +(*********************************************************************************** + * Copyright (c) 2016-2020 The University of Sheffield, UK + * 2019-2020 University of Exeter, UK + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-2-Clause + ***********************************************************************************) + +(* This file is automatically generated, please do not modify! *) + +section\Testing slots\ +text\This theory contains the test cases for slots.\ + +theory slots +imports + "Shadow_DOM_BaseTest" +begin + +definition slots_heap :: "heap\<^sub>f\<^sub>i\<^sub>n\<^sub>a\<^sub>l" where + "slots_heap = create_heap [(cast (document_ptr.Ref 1), cast (create_document_obj html (Some (cast (element_ptr.Ref 1))) [])), + (cast (element_ptr.Ref 1), cast (create_element_obj ''html'' [cast (element_ptr.Ref 2), cast (element_ptr.Ref 8)] fmempty None)), + (cast (element_ptr.Ref 2), cast (create_element_obj ''head'' [cast (element_ptr.Ref 3), cast (element_ptr.Ref 4), cast (element_ptr.Ref 5), cast (element_ptr.Ref 6), cast (element_ptr.Ref 7)] fmempty None)), + (cast (element_ptr.Ref 3), cast (create_element_obj ''title'' [cast (character_data_ptr.Ref 1)] fmempty None)), + (cast (character_data_ptr.Ref 1), cast (create_character_data_obj ''Shadow%20DOM%3A%20Slots%20and%20assignments'')), + (cast (element_ptr.Ref 4), cast (create_element_obj ''meta'' [] (fmap_of_list [(''name'', ''author''), (''title'', ''Hayato Ito''), (''href'', ''mailto:hayato@google.com'')]) None)), + (cast (element_ptr.Ref 5), cast (create_element_obj ''script'' [] (fmap_of_list [(''src'', ''/resources/testharness.js'')]) None)), + (cast (element_ptr.Ref 6), cast (create_element_obj ''script'' [] (fmap_of_list [(''src'', ''/resources/testharnessreport.js'')]) None)), + (cast (element_ptr.Ref 7), cast (create_element_obj ''script'' [] (fmap_of_list [(''src'', ''resources/shadow-dom.js'')]) None)), + (cast (element_ptr.Ref 8), cast (create_element_obj ''body'' [cast (element_ptr.Ref 9), cast (element_ptr.Ref 13), cast (element_ptr.Ref 14), cast (element_ptr.Ref 18), cast (element_ptr.Ref 19), cast (element_ptr.Ref 21), cast (element_ptr.Ref 22), cast (element_ptr.Ref 30), cast (element_ptr.Ref 31), cast (element_ptr.Ref 39), cast (element_ptr.Ref 40), cast (element_ptr.Ref 48), cast (element_ptr.Ref 49), cast (element_ptr.Ref 57), cast (element_ptr.Ref 58), cast (element_ptr.Ref 64), cast (element_ptr.Ref 65), cast (element_ptr.Ref 71), cast (element_ptr.Ref 72), cast (element_ptr.Ref 78), cast (element_ptr.Ref 79), cast (element_ptr.Ref 85), cast (element_ptr.Ref 86), cast (element_ptr.Ref 92), cast (element_ptr.Ref 93), cast (element_ptr.Ref 112)] fmempty None)), + (cast (element_ptr.Ref 9), cast (create_element_obj ''div'' [cast (element_ptr.Ref 10)] (fmap_of_list [(''id'', ''test_basic'')]) None)), + (cast (element_ptr.Ref 10), cast (create_element_obj ''div'' [cast (element_ptr.Ref 11)] (fmap_of_list [(''id'', ''host'')]) (Some (cast (shadow_root_ptr.Ref 1))))), + (cast (element_ptr.Ref 11), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c1''), (''slot'', ''slot1'')]) None)), + (cast (shadow_root_ptr.Ref 1), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 12)])), + (cast (element_ptr.Ref 12), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1'')]) None)), + (cast (element_ptr.Ref 13), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 2)] fmempty None)), + (cast (character_data_ptr.Ref 2), cast (create_character_data_obj ''%3C%3Cscript%3E%3E'')), + (cast (element_ptr.Ref 14), cast (create_element_obj ''div'' [cast (element_ptr.Ref 15)] (fmap_of_list [(''id'', ''test_basic_closed'')]) None)), + (cast (element_ptr.Ref 15), cast (create_element_obj ''div'' [cast (element_ptr.Ref 16)] (fmap_of_list [(''id'', ''host'')]) (Some (cast (shadow_root_ptr.Ref 2))))), + (cast (element_ptr.Ref 16), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c1''), (''slot'', ''slot1'')]) None)), + (cast (shadow_root_ptr.Ref 2), cast (create_shadow_root_obj Closed [cast (element_ptr.Ref 17)])), + (cast (element_ptr.Ref 17), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1'')]) None)), + (cast (element_ptr.Ref 18), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 3)] fmempty None)), + (cast (character_data_ptr.Ref 3), cast (create_character_data_obj ''%3C%3Cscript%3E%3E'')), + (cast (element_ptr.Ref 19), cast (create_element_obj ''div'' [cast (element_ptr.Ref 20)] (fmap_of_list [(''id'', ''test_slot_not_in_shadow'')]) None)), + (cast (element_ptr.Ref 20), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s1'')]) None)), + (cast (element_ptr.Ref 21), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 4)] fmempty None)), + (cast (character_data_ptr.Ref 4), cast (create_character_data_obj ''%3C%3Cscript%3E%3E'')), + (cast (element_ptr.Ref 22), cast (create_element_obj ''div'' [cast (element_ptr.Ref 23), cast (element_ptr.Ref 25)] (fmap_of_list [(''id'', ''test_slot_not_in_shadow_2'')]) None)), + (cast (element_ptr.Ref 23), cast (create_element_obj ''slot'' [cast (element_ptr.Ref 24)] (fmap_of_list [(''id'', ''s1'')]) None)), + (cast (element_ptr.Ref 24), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c1'')]) None)), + (cast (element_ptr.Ref 25), cast (create_element_obj ''slot'' [cast (element_ptr.Ref 26), cast (element_ptr.Ref 27)] (fmap_of_list [(''id'', ''s2'')]) None)), + (cast (element_ptr.Ref 26), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c2'')]) None)), + (cast (element_ptr.Ref 27), cast (create_element_obj ''slot'' [cast (element_ptr.Ref 28), cast (element_ptr.Ref 29)] (fmap_of_list [(''id'', ''s3'')]) None)), + (cast (element_ptr.Ref 28), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c3_1'')]) None)), + (cast (element_ptr.Ref 29), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c3_2'')]) None)), + (cast (element_ptr.Ref 30), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 5)] fmempty None)), + (cast (character_data_ptr.Ref 5), cast (create_character_data_obj ''%3C%3Cscript%3E%3E'')), + (cast (element_ptr.Ref 31), cast (create_element_obj ''div'' [cast (element_ptr.Ref 32)] (fmap_of_list [(''id'', ''test_slot_name_matching'')]) None)), + (cast (element_ptr.Ref 32), cast (create_element_obj ''div'' [cast (element_ptr.Ref 33), cast (element_ptr.Ref 34), cast (element_ptr.Ref 35)] (fmap_of_list [(''id'', ''host'')]) (Some (cast (shadow_root_ptr.Ref 3))))), + (cast (element_ptr.Ref 33), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c1''), (''slot'', ''slot1'')]) None)), + (cast (element_ptr.Ref 34), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c2''), (''slot'', ''slot2'')]) None)), + (cast (element_ptr.Ref 35), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c3''), (''slot'', ''yyy'')]) None)), + (cast (shadow_root_ptr.Ref 3), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 36), cast (element_ptr.Ref 37), cast (element_ptr.Ref 38)])), + (cast (element_ptr.Ref 36), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1'')]) None)), + (cast (element_ptr.Ref 37), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s2''), (''name'', ''slot2'')]) None)), + (cast (element_ptr.Ref 38), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s3''), (''name'', ''xxx'')]) None)), + (cast (element_ptr.Ref 39), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 6)] fmempty None)), + (cast (character_data_ptr.Ref 6), cast (create_character_data_obj ''%3C%3Cscript%3E%3E'')), + (cast (element_ptr.Ref 40), cast (create_element_obj ''div'' [cast (element_ptr.Ref 41)] (fmap_of_list [(''id'', ''test_no_direct_host_child'')]) None)), + (cast (element_ptr.Ref 41), cast (create_element_obj ''div'' [cast (element_ptr.Ref 42), cast (element_ptr.Ref 43), cast (element_ptr.Ref 44)] (fmap_of_list [(''id'', ''host'')]) (Some (cast (shadow_root_ptr.Ref 4))))), + (cast (element_ptr.Ref 42), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c1''), (''slot'', ''slot1'')]) None)), + (cast (element_ptr.Ref 43), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c2''), (''slot'', ''slot1'')]) None)), + (cast (element_ptr.Ref 44), cast (create_element_obj ''div'' [cast (element_ptr.Ref 45)] fmempty None)), + (cast (element_ptr.Ref 45), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c3''), (''slot'', ''slot1'')]) None)), + (cast (shadow_root_ptr.Ref 4), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 46), cast (element_ptr.Ref 47)])), + (cast (element_ptr.Ref 46), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1'')]) None)), + (cast (element_ptr.Ref 47), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s2''), (''name'', ''slot1'')]) None)), + (cast (element_ptr.Ref 48), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 7)] fmempty None)), + (cast (character_data_ptr.Ref 7), cast (create_character_data_obj ''%3C%3Cscript%3E%3E'')), + (cast (element_ptr.Ref 49), cast (create_element_obj ''div'' [cast (element_ptr.Ref 50)] (fmap_of_list [(''id'', ''test_default_slot'')]) None)), + (cast (element_ptr.Ref 50), cast (create_element_obj ''div'' [cast (element_ptr.Ref 51), cast (element_ptr.Ref 52), cast (element_ptr.Ref 53)] (fmap_of_list [(''id'', ''host'')]) (Some (cast (shadow_root_ptr.Ref 5))))), + (cast (element_ptr.Ref 51), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c1'')]) None)), + (cast (element_ptr.Ref 52), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c2''), (''slot'', '''')]) None)), + (cast (element_ptr.Ref 53), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c3''), (''slot'', ''foo'')]) None)), + (cast (shadow_root_ptr.Ref 5), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 54), cast (element_ptr.Ref 55), cast (element_ptr.Ref 56)])), + (cast (element_ptr.Ref 54), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1'')]) None)), + (cast (element_ptr.Ref 55), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s2'')]) None)), + (cast (element_ptr.Ref 56), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s3'')]) None)), + (cast (element_ptr.Ref 57), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 8)] fmempty None)), + (cast (character_data_ptr.Ref 8), cast (create_character_data_obj ''%3C%3Cscript%3E%3E'')), + (cast (element_ptr.Ref 58), cast (create_element_obj ''div'' [cast (element_ptr.Ref 59)] (fmap_of_list [(''id'', ''test_slot_in_slot'')]) None)), + (cast (element_ptr.Ref 59), cast (create_element_obj ''div'' [cast (element_ptr.Ref 60), cast (element_ptr.Ref 61)] (fmap_of_list [(''id'', ''host'')]) (Some (cast (shadow_root_ptr.Ref 6))))), + (cast (element_ptr.Ref 60), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c1''), (''slot'', ''slot2'')]) None)), + (cast (element_ptr.Ref 61), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c2''), (''slot'', ''slot1'')]) None)), + (cast (shadow_root_ptr.Ref 6), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 62)])), + (cast (element_ptr.Ref 62), cast (create_element_obj ''slot'' [cast (element_ptr.Ref 63)] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1'')]) None)), + (cast (element_ptr.Ref 63), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s2''), (''name'', ''slot2'')]) None)), + (cast (element_ptr.Ref 64), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 9)] fmempty None)), + (cast (character_data_ptr.Ref 9), cast (create_character_data_obj ''%3C%3Cscript%3E%3E'')), + (cast (element_ptr.Ref 65), cast (create_element_obj ''div'' [cast (element_ptr.Ref 66)] (fmap_of_list [(''id'', ''test_slot_is_assigned_to_slot'')]) None)), + (cast (element_ptr.Ref 66), cast (create_element_obj ''div'' [cast (element_ptr.Ref 67)] (fmap_of_list [(''id'', ''host1'')]) (Some (cast (shadow_root_ptr.Ref 7))))), + (cast (element_ptr.Ref 67), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c1''), (''slot'', ''slot1'')]) None)), + (cast (shadow_root_ptr.Ref 7), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 68)])), + (cast (element_ptr.Ref 68), cast (create_element_obj ''div'' [cast (element_ptr.Ref 69)] (fmap_of_list [(''id'', ''host2'')]) (Some (cast (shadow_root_ptr.Ref 8))))), + (cast (element_ptr.Ref 69), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1''), (''slot'', ''slot2'')]) None)), + (cast (shadow_root_ptr.Ref 8), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 70)])), + (cast (element_ptr.Ref 70), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s2''), (''name'', ''slot2'')]) None)), + (cast (element_ptr.Ref 71), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 10)] fmempty None)), + (cast (character_data_ptr.Ref 10), cast (create_character_data_obj ''%3C%3Cscript%3E%3E'')), + (cast (element_ptr.Ref 72), cast (create_element_obj ''div'' [cast (element_ptr.Ref 73)] (fmap_of_list [(''id'', ''test_open_closed'')]) None)), + (cast (element_ptr.Ref 73), cast (create_element_obj ''div'' [cast (element_ptr.Ref 74)] (fmap_of_list [(''id'', ''host1'')]) (Some (cast (shadow_root_ptr.Ref 9))))), + (cast (element_ptr.Ref 74), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c1''), (''slot'', ''slot1'')]) None)), + (cast (shadow_root_ptr.Ref 9), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 75)])), + (cast (element_ptr.Ref 75), cast (create_element_obj ''div'' [cast (element_ptr.Ref 76)] (fmap_of_list [(''id'', ''host2'')]) (Some (cast (shadow_root_ptr.Ref 10))))), + (cast (element_ptr.Ref 76), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1''), (''slot'', ''slot2'')]) None)), + (cast (shadow_root_ptr.Ref 10), cast (create_shadow_root_obj Closed [cast (element_ptr.Ref 77)])), + (cast (element_ptr.Ref 77), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s2''), (''name'', ''slot2'')]) None)), + (cast (element_ptr.Ref 78), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 11)] fmempty None)), + (cast (character_data_ptr.Ref 11), cast (create_character_data_obj ''%3C%3Cscript%3E%3E'')), + (cast (element_ptr.Ref 79), cast (create_element_obj ''div'' [cast (element_ptr.Ref 80)] (fmap_of_list [(''id'', ''test_closed_closed'')]) None)), + (cast (element_ptr.Ref 80), cast (create_element_obj ''div'' [cast (element_ptr.Ref 81)] (fmap_of_list [(''id'', ''host1'')]) (Some (cast (shadow_root_ptr.Ref 11))))), + (cast (element_ptr.Ref 81), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c1''), (''slot'', ''slot1'')]) None)), + (cast (shadow_root_ptr.Ref 11), cast (create_shadow_root_obj Closed [cast (element_ptr.Ref 82)])), + (cast (element_ptr.Ref 82), cast (create_element_obj ''div'' [cast (element_ptr.Ref 83)] (fmap_of_list [(''id'', ''host2'')]) (Some (cast (shadow_root_ptr.Ref 12))))), + (cast (element_ptr.Ref 83), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1''), (''slot'', ''slot2'')]) None)), + (cast (shadow_root_ptr.Ref 12), cast (create_shadow_root_obj Closed [cast (element_ptr.Ref 84)])), + (cast (element_ptr.Ref 84), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s2''), (''name'', ''slot2'')]) None)), + (cast (element_ptr.Ref 85), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 12)] fmempty None)), + (cast (character_data_ptr.Ref 12), cast (create_character_data_obj ''%3C%3Cscript%3E%3E'')), + (cast (element_ptr.Ref 86), cast (create_element_obj ''div'' [cast (element_ptr.Ref 87)] (fmap_of_list [(''id'', ''test_closed_open'')]) None)), + (cast (element_ptr.Ref 87), cast (create_element_obj ''div'' [cast (element_ptr.Ref 88)] (fmap_of_list [(''id'', ''host1'')]) (Some (cast (shadow_root_ptr.Ref 13))))), + (cast (element_ptr.Ref 88), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c1''), (''slot'', ''slot1'')]) None)), + (cast (shadow_root_ptr.Ref 13), cast (create_shadow_root_obj Closed [cast (element_ptr.Ref 89)])), + (cast (element_ptr.Ref 89), cast (create_element_obj ''div'' [cast (element_ptr.Ref 90)] (fmap_of_list [(''id'', ''host2'')]) (Some (cast (shadow_root_ptr.Ref 14))))), + (cast (element_ptr.Ref 90), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1''), (''slot'', ''slot2'')]) None)), + (cast (shadow_root_ptr.Ref 14), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 91)])), + (cast (element_ptr.Ref 91), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s2''), (''name'', ''slot2'')]) None)), + (cast (element_ptr.Ref 92), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 13)] fmempty None)), + (cast (character_data_ptr.Ref 13), cast (create_character_data_obj ''%3C%3Cscript%3E%3E'')), + (cast (element_ptr.Ref 93), cast (create_element_obj ''div'' [cast (element_ptr.Ref 94)] (fmap_of_list [(''id'', ''test_complex'')]) None)), + (cast (element_ptr.Ref 94), cast (create_element_obj ''div'' [cast (element_ptr.Ref 95), cast (element_ptr.Ref 96), cast (element_ptr.Ref 97), cast (element_ptr.Ref 98)] (fmap_of_list [(''id'', ''host1'')]) (Some (cast (shadow_root_ptr.Ref 15))))), + (cast (element_ptr.Ref 95), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c1''), (''slot'', ''slot1'')]) None)), + (cast (element_ptr.Ref 96), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c2''), (''slot'', ''slot2'')]) None)), + (cast (element_ptr.Ref 97), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c3'')]) None)), + (cast (element_ptr.Ref 98), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c4''), (''slot'', ''slot-none'')]) None)), + (cast (shadow_root_ptr.Ref 15), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 99)])), + (cast (element_ptr.Ref 99), cast (create_element_obj ''div'' [cast (element_ptr.Ref 100), cast (element_ptr.Ref 101), cast (element_ptr.Ref 102), cast (element_ptr.Ref 103), cast (element_ptr.Ref 104), cast (element_ptr.Ref 105), cast (element_ptr.Ref 106), cast (element_ptr.Ref 107)] (fmap_of_list [(''id'', ''host2'')]) (Some (cast (shadow_root_ptr.Ref 16))))), + (cast (element_ptr.Ref 100), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1''), (''slot'', ''slot5'')]) None)), + (cast (element_ptr.Ref 101), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s2''), (''name'', ''slot2''), (''slot'', ''slot6'')]) None)), + (cast (element_ptr.Ref 102), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s3'')]) None)), + (cast (element_ptr.Ref 103), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s4''), (''name'', ''slot4''), (''slot'', ''slot-none'')]) None)), + (cast (element_ptr.Ref 104), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c5''), (''slot'', ''slot5'')]) None)), + (cast (element_ptr.Ref 105), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c6''), (''slot'', ''slot6'')]) None)), + (cast (element_ptr.Ref 106), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c7'')]) None)), + (cast (element_ptr.Ref 107), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c8''), (''slot'', ''slot-none'')]) None)), + (cast (shadow_root_ptr.Ref 16), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 108), cast (element_ptr.Ref 109), cast (element_ptr.Ref 110), cast (element_ptr.Ref 111)])), + (cast (element_ptr.Ref 108), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s5''), (''name'', ''slot5'')]) None)), + (cast (element_ptr.Ref 109), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s6''), (''name'', ''slot6'')]) None)), + (cast (element_ptr.Ref 110), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s7'')]) None)), + (cast (element_ptr.Ref 111), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''s8''), (''name'', ''slot8'')]) None)), + (cast (element_ptr.Ref 112), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 14)] fmempty None)), + (cast (character_data_ptr.Ref 14), cast (create_character_data_obj ''%3C%3Cscript%3E%3E''))]" + +definition slots_document :: "(unit, unit, unit, unit, unit, unit) object_ptr option" where "slots_document = Some (cast (document_ptr.Ref 1))" + + +text \'Slots: Basic.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_basic''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_basic''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp3 \ tmp2 . assignedSlot; + tmp4 \ n . ''s1''; + assert_equals(tmp3, tmp4); + tmp5 \ n . ''s1''; + tmp6 \ tmp5 . assignedNodes(); + tmp7 \ n . ''c1''; + assert_array_equals(tmp6, [tmp7]) +}) slots_heap" + by eval + + +text \'Slots: Basic, elements only.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_basic''); + n \ createTestTree(tmp0); + tmp1 \ n . ''s1''; + tmp2 \ tmp1 . assignedElements(); + tmp3 \ n . ''c1''; + assert_array_equals(tmp2, [tmp3]) +}) slots_heap" + by eval + + +text \'Slots: Slots in closed.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_basic_closed''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_basic_closed''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp3 \ tmp2 . assignedSlot; + assert_equals(tmp3, None); + tmp4 \ n . ''s1''; + tmp5 \ tmp4 . assignedNodes(); + tmp6 \ n . ''c1''; + assert_array_equals(tmp5, [tmp6]) +}) slots_heap" + by eval + + +text \'Slots: Slots in closed, elements only.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_basic_closed''); + n \ createTestTree(tmp0); + tmp1 \ n . ''s1''; + tmp2 \ tmp1 . assignedElements(); + tmp3 \ n . ''c1''; + assert_array_equals(tmp2, [tmp3]) +}) slots_heap" + by eval + + +text \'Slots: Slots not in a shadow tree.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_slot_not_in_shadow''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_slot_not_in_shadow''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''s1''; + tmp3 \ tmp2 . assignedNodes(); + assert_array_equals(tmp3, []) +}) slots_heap" + by eval + + +text \'Slots: Slots not in a shadow tree, elements only.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_slot_not_in_shadow''); + n \ createTestTree(tmp0); + tmp1 \ n . ''s1''; + tmp2 \ tmp1 . assignedElements(); + assert_array_equals(tmp2, []) +}) slots_heap" + by eval + + +text \'Slots: Distributed nodes for Slots not in a shadow tree.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_slot_not_in_shadow_2''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_slot_not_in_shadow_2''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp3 \ tmp2 . assignedSlot; + assert_equals(tmp3, None); + tmp4 \ n . ''c2''; + tmp5 \ tmp4 . assignedSlot; + assert_equals(tmp5, None); + tmp6 \ n . ''c3_1''; + tmp7 \ tmp6 . assignedSlot; + assert_equals(tmp7, None); + tmp8 \ n . ''c3_2''; + tmp9 \ tmp8 . assignedSlot; + assert_equals(tmp9, None); + tmp10 \ n . ''s1''; + tmp11 \ tmp10 . assignedNodes(); + assert_array_equals(tmp11, []); + tmp12 \ n . ''s2''; + tmp13 \ tmp12 . assignedNodes(); + assert_array_equals(tmp13, []); + tmp14 \ n . ''s3''; + tmp15 \ tmp14 . assignedNodes(); + assert_array_equals(tmp15, []); + tmp16 \ n . ''s1''; + tmp17 \ tmp16 . assignedNodes(True); + assert_array_equals(tmp17, []); + tmp18 \ n . ''s2''; + tmp19 \ tmp18 . assignedNodes(True); + assert_array_equals(tmp19, []); + tmp20 \ n . ''s3''; + tmp21 \ tmp20 . assignedNodes(True); + assert_array_equals(tmp21, []) +}) slots_heap" + by eval + + +text \'Slots: Name matching'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_slot_name_matching''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_slot_name_matching''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp3 \ tmp2 . assignedSlot; + tmp4 \ n . ''s1''; + assert_equals(tmp3, tmp4); + tmp5 \ n . ''c2''; + tmp6 \ tmp5 . assignedSlot; + tmp7 \ n . ''s2''; + assert_equals(tmp6, tmp7); + tmp8 \ n . ''c3''; + tmp9 \ tmp8 . assignedSlot; + assert_equals(tmp9, None) +}) slots_heap" + by eval + + +text \'Slots: No direct host child.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_no_direct_host_child''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_no_direct_host_child''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp3 \ tmp2 . assignedSlot; + tmp4 \ n . ''s1''; + assert_equals(tmp3, tmp4); + tmp5 \ n . ''c2''; + tmp6 \ tmp5 . assignedSlot; + tmp7 \ n . ''s1''; + assert_equals(tmp6, tmp7); + tmp8 \ n . ''c3''; + tmp9 \ tmp8 . assignedSlot; + assert_equals(tmp9, None); + tmp10 \ n . ''s1''; + tmp11 \ tmp10 . assignedNodes(); + tmp12 \ n . ''c1''; + tmp13 \ n . ''c2''; + assert_array_equals(tmp11, [tmp12, tmp13]) +}) slots_heap" + by eval + + +text \'Slots: Default Slot.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_default_slot''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_default_slot''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp3 \ tmp2 . assignedSlot; + tmp4 \ n . ''s2''; + assert_equals(tmp3, tmp4); + tmp5 \ n . ''c2''; + tmp6 \ tmp5 . assignedSlot; + tmp7 \ n . ''s2''; + assert_equals(tmp6, tmp7); + tmp8 \ n . ''c3''; + tmp9 \ tmp8 . assignedSlot; + assert_equals(tmp9, None) +}) slots_heap" + by eval + + +text \'Slots: Slot in Slot does not matter in assignment.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_slot_in_slot''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_slot_in_slot''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp3 \ tmp2 . assignedSlot; + tmp4 \ n . ''s2''; + assert_equals(tmp3, tmp4); + tmp5 \ n . ''c2''; + tmp6 \ tmp5 . assignedSlot; + tmp7 \ n . ''s1''; + assert_equals(tmp6, tmp7) +}) slots_heap" + by eval + + +text \'Slots: Slot is assigned to another slot'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_slot_is_assigned_to_slot''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_slot_is_assigned_to_slot''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp3 \ tmp2 . assignedSlot; + tmp4 \ n . ''s1''; + assert_equals(tmp3, tmp4); + tmp5 \ n . ''s1''; + tmp6 \ tmp5 . assignedSlot; + tmp7 \ n . ''s2''; + assert_equals(tmp6, tmp7); + tmp8 \ n . ''s1''; + tmp9 \ tmp8 . assignedNodes(); + tmp10 \ n . ''c1''; + assert_array_equals(tmp9, [tmp10]); + tmp11 \ n . ''s2''; + tmp12 \ tmp11 . assignedNodes(); + tmp13 \ n . ''s1''; + assert_array_equals(tmp12, [tmp13]); + tmp14 \ n . ''s1''; + tmp15 \ tmp14 . assignedNodes(True); + tmp16 \ n . ''c1''; + assert_array_equals(tmp15, [tmp16]); + tmp17 \ n . ''s2''; + tmp18 \ tmp17 . assignedNodes(True); + tmp19 \ n . ''c1''; + assert_array_equals(tmp18, [tmp19]) +}) slots_heap" + by eval + + +text \'Slots: Open > Closed.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_open_closed''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_open_closed''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp3 \ tmp2 . assignedSlot; + tmp4 \ n . ''s1''; + assert_equals(tmp3, tmp4); + tmp5 \ n . ''s1''; + tmp6 \ tmp5 . assignedSlot; + assert_equals(tmp6, None, ''A slot in a closed shadow tree should not be accessed via assignedSlot''); + tmp7 \ n . ''s1''; + tmp8 \ tmp7 . assignedNodes(); + tmp9 \ n . ''c1''; + assert_array_equals(tmp8, [tmp9]); + tmp10 \ n . ''s2''; + tmp11 \ tmp10 . assignedNodes(); + tmp12 \ n . ''s1''; + assert_array_equals(tmp11, [tmp12]); + tmp13 \ n . ''s1''; + tmp14 \ tmp13 . assignedNodes(True); + tmp15 \ n . ''c1''; + assert_array_equals(tmp14, [tmp15]); + tmp16 \ n . ''s2''; + tmp17 \ tmp16 . assignedNodes(True); + tmp18 \ n . ''c1''; + assert_array_equals(tmp17, [tmp18]) +}) slots_heap" + by eval + + +text \'Slots: Closed > Closed.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_closed_closed''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_closed_closed''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp3 \ tmp2 . assignedSlot; + assert_equals(tmp3, None, ''A slot in a closed shadow tree should not be accessed via assignedSlot''); + tmp4 \ n . ''s1''; + tmp5 \ tmp4 . assignedSlot; + assert_equals(tmp5, None, ''A slot in a closed shadow tree should not be accessed via assignedSlot''); + tmp6 \ n . ''s1''; + tmp7 \ tmp6 . assignedNodes(); + tmp8 \ n . ''c1''; + assert_array_equals(tmp7, [tmp8]); + tmp9 \ n . ''s2''; + tmp10 \ tmp9 . assignedNodes(); + tmp11 \ n . ''s1''; + assert_array_equals(tmp10, [tmp11]); + tmp12 \ n . ''s1''; + tmp13 \ tmp12 . assignedNodes(True); + tmp14 \ n . ''c1''; + assert_array_equals(tmp13, [tmp14]); + tmp15 \ n . ''s2''; + tmp16 \ tmp15 . assignedNodes(True); + tmp17 \ n . ''c1''; + assert_array_equals(tmp16, [tmp17]) +}) slots_heap" + by eval + + +text \'Slots: Closed > Open.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_closed_open''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_closed_open''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp3 \ tmp2 . assignedSlot; + assert_equals(tmp3, None, ''A slot in a closed shadow tree should not be accessed via assignedSlot''); + tmp4 \ n . ''s1''; + tmp5 \ tmp4 . assignedSlot; + tmp6 \ n . ''s2''; + assert_equals(tmp5, tmp6); + tmp7 \ n . ''s1''; + tmp8 \ tmp7 . assignedNodes(); + tmp9 \ n . ''c1''; + assert_array_equals(tmp8, [tmp9]); + tmp10 \ n . ''s2''; + tmp11 \ tmp10 . assignedNodes(); + tmp12 \ n . ''s1''; + assert_array_equals(tmp11, [tmp12]); + tmp13 \ n . ''s1''; + tmp14 \ tmp13 . assignedNodes(True); + tmp15 \ n . ''c1''; + assert_array_equals(tmp14, [tmp15]); + tmp16 \ n . ''s2''; + tmp17 \ tmp16 . assignedNodes(True); + tmp18 \ n . ''c1''; + assert_array_equals(tmp17, [tmp18]) +}) slots_heap" + by eval + + +text \'Slots: Complex case: Basi line.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_complex''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_complex''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp3 \ tmp2 . assignedSlot; + tmp4 \ n . ''s1''; + assert_equals(tmp3, tmp4); + tmp5 \ n . ''c2''; + tmp6 \ tmp5 . assignedSlot; + tmp7 \ n . ''s2''; + assert_equals(tmp6, tmp7); + tmp8 \ n . ''c3''; + tmp9 \ tmp8 . assignedSlot; + tmp10 \ n . ''s3''; + assert_equals(tmp9, tmp10); + tmp11 \ n . ''c4''; + tmp12 \ tmp11 . assignedSlot; + assert_equals(tmp12, None); + tmp13 \ n . ''s1''; + tmp14 \ tmp13 . assignedSlot; + tmp15 \ n . ''s5''; + assert_equals(tmp14, tmp15); + tmp16 \ n . ''s2''; + tmp17 \ tmp16 . assignedSlot; + tmp18 \ n . ''s6''; + assert_equals(tmp17, tmp18); + tmp19 \ n . ''s3''; + tmp20 \ tmp19 . assignedSlot; + tmp21 \ n . ''s7''; + assert_equals(tmp20, tmp21); + tmp22 \ n . ''s4''; + tmp23 \ tmp22 . assignedSlot; + assert_equals(tmp23, None); + tmp24 \ n . ''c5''; + tmp25 \ tmp24 . assignedSlot; + tmp26 \ n . ''s5''; + assert_equals(tmp25, tmp26); + tmp27 \ n . ''c6''; + tmp28 \ tmp27 . assignedSlot; + tmp29 \ n . ''s6''; + assert_equals(tmp28, tmp29); + tmp30 \ n . ''c7''; + tmp31 \ tmp30 . assignedSlot; + tmp32 \ n . ''s7''; + assert_equals(tmp31, tmp32); + tmp33 \ n . ''c8''; + tmp34 \ tmp33 . assignedSlot; + assert_equals(tmp34, None); + tmp35 \ n . ''s1''; + tmp36 \ tmp35 . assignedNodes(); + tmp37 \ n . ''c1''; + assert_array_equals(tmp36, [tmp37]); + tmp38 \ n . ''s2''; + tmp39 \ tmp38 . assignedNodes(); + tmp40 \ n . ''c2''; + assert_array_equals(tmp39, [tmp40]); + tmp41 \ n . ''s3''; + tmp42 \ tmp41 . assignedNodes(); + tmp43 \ n . ''c3''; + assert_array_equals(tmp42, [tmp43]); + tmp44 \ n . ''s4''; + tmp45 \ tmp44 . assignedNodes(); + assert_array_equals(tmp45, []); + tmp46 \ n . ''s5''; + tmp47 \ tmp46 . assignedNodes(); + tmp48 \ n . ''s1''; + tmp49 \ n . ''c5''; + assert_array_equals(tmp47, [tmp48, tmp49]); + tmp50 \ n . ''s6''; + tmp51 \ tmp50 . assignedNodes(); + tmp52 \ n . ''s2''; + tmp53 \ n . ''c6''; + assert_array_equals(tmp51, [tmp52, tmp53]); + tmp54 \ n . ''s7''; + tmp55 \ tmp54 . assignedNodes(); + tmp56 \ n . ''s3''; + tmp57 \ n . ''c7''; + assert_array_equals(tmp55, [tmp56, tmp57]); + tmp58 \ n . ''s8''; + tmp59 \ tmp58 . assignedNodes(); + assert_array_equals(tmp59, []); + tmp60 \ n . ''s1''; + tmp61 \ tmp60 . assignedNodes(True); + tmp62 \ n . ''c1''; + assert_array_equals(tmp61, [tmp62]); + tmp63 \ n . ''s2''; + tmp64 \ tmp63 . assignedNodes(True); + tmp65 \ n . ''c2''; + assert_array_equals(tmp64, [tmp65]); + tmp66 \ n . ''s3''; + tmp67 \ tmp66 . assignedNodes(True); + tmp68 \ n . ''c3''; + assert_array_equals(tmp67, [tmp68]); + tmp69 \ n . ''s4''; + tmp70 \ tmp69 . assignedNodes(True); + assert_array_equals(tmp70, []); + tmp71 \ n . ''s5''; + tmp72 \ tmp71 . assignedNodes(True); + tmp73 \ n . ''c1''; + tmp74 \ n . ''c5''; + assert_array_equals(tmp72, [tmp73, tmp74]); + tmp75 \ n . ''s6''; + tmp76 \ tmp75 . assignedNodes(True); + tmp77 \ n . ''c2''; + tmp78 \ n . ''c6''; + assert_array_equals(tmp76, [tmp77, tmp78]); + tmp79 \ n . ''s7''; + tmp80 \ tmp79 . assignedNodes(True); + tmp81 \ n . ''c3''; + tmp82 \ n . ''c7''; + assert_array_equals(tmp80, [tmp81, tmp82]); + tmp83 \ n . ''s8''; + tmp84 \ tmp83 . assignedNodes(True); + assert_array_equals(tmp84, []) +}) slots_heap" + by eval + + +text \'Slots: Mutation: appendChild.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_complex''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_complex''; + removeWhiteSpaceOnlyTextNodes(tmp1); + d1 \ slots_document . createElement(''div''); + d1 . setAttribute(''slot'', ''slot1''); + tmp2 \ n . ''host1''; + tmp2 . appendChild(d1); + tmp3 \ n . ''s1''; + tmp4 \ tmp3 . assignedNodes(); + tmp5 \ n . ''c1''; + assert_array_equals(tmp4, [tmp5, d1]); + tmp6 \ d1 . assignedSlot; + tmp7 \ n . ''s1''; + assert_equals(tmp6, tmp7); + tmp8 \ n . ''s5''; + tmp9 \ tmp8 . assignedNodes(True); + tmp10 \ n . ''c1''; + tmp11 \ n . ''c5''; + assert_array_equals(tmp9, [tmp10, d1, tmp11]) +}) slots_heap" + by eval + + +text \'Slots: Mutation: Change slot= attribute 1.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_complex''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_complex''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp2 . setAttribute(''slot'', ''slot-none''); + tmp3 \ n . ''s1''; + tmp4 \ tmp3 . assignedNodes(); + assert_array_equals(tmp4, []); + tmp5 \ n . ''c1''; + tmp6 \ tmp5 . assignedSlot; + assert_equals(tmp6, None); + tmp7 \ n . ''s5''; + tmp8 \ tmp7 . assignedNodes(True); + tmp9 \ n . ''c5''; + assert_array_equals(tmp8, [tmp9]) +}) slots_heap" + by eval + + +text \'Slots: Mutation: Change slot= attribute 2.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_complex''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_complex''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp2 . setAttribute(''slot'', ''slot2''); + tmp3 \ n . ''s1''; + tmp4 \ tmp3 . assignedNodes(); + assert_array_equals(tmp4, []); + tmp5 \ n . ''s2''; + tmp6 \ tmp5 . assignedNodes(); + tmp7 \ n . ''c1''; + tmp8 \ n . ''c2''; + assert_array_equals(tmp6, [tmp7, tmp8]); + tmp9 \ n . ''c1''; + tmp10 \ tmp9 . assignedSlot; + tmp11 \ n . ''s2''; + assert_equals(tmp10, tmp11); + tmp12 \ n . ''s5''; + tmp13 \ tmp12 . assignedNodes(True); + tmp14 \ n . ''c5''; + assert_array_equals(tmp13, [tmp14]); + tmp15 \ n . ''s6''; + tmp16 \ tmp15 . assignedNodes(True); + tmp17 \ n . ''c1''; + tmp18 \ n . ''c2''; + tmp19 \ n . ''c6''; + assert_array_equals(tmp16, [tmp17, tmp18, tmp19]) +}) slots_heap" + by eval + + +text \'Slots: Mutation: Change slot= attribute 3.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_complex''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_complex''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c4''; + tmp2 . setAttribute(''slot'', ''slot1''); + tmp3 \ n . ''s1''; + tmp4 \ tmp3 . assignedNodes(); + tmp5 \ n . ''c1''; + tmp6 \ n . ''c4''; + assert_array_equals(tmp4, [tmp5, tmp6]); + tmp7 \ n . ''c4''; + tmp8 \ tmp7 . assignedSlot; + tmp9 \ n . ''s1''; + assert_equals(tmp8, tmp9); + tmp10 \ n . ''s5''; + tmp11 \ tmp10 . assignedNodes(True); + tmp12 \ n . ''c1''; + tmp13 \ n . ''c4''; + tmp14 \ n . ''c5''; + assert_array_equals(tmp11, [tmp12, tmp13, tmp14]) +}) slots_heap" + by eval + + +text \'Slots: Mutation: Remove a child.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_complex''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_complex''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp2 . remove(); + tmp3 \ n . ''s1''; + tmp4 \ tmp3 . assignedNodes(); + assert_array_equals(tmp4, []); + tmp5 \ n . ''c1''; + tmp6 \ tmp5 . assignedSlot; + assert_equals(tmp6, None); + tmp7 \ n . ''s5''; + tmp8 \ tmp7 . assignedNodes(True); + tmp9 \ n . ''c5''; + assert_array_equals(tmp8, [tmp9]) +}) slots_heap" + by eval + + +text \'Slots: Mutation: Add a slot: after.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_complex''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_complex''; + removeWhiteSpaceOnlyTextNodes(tmp1); + slot \ slots_document . createElement(''slot''); + slot . setAttribute(''name'', ''slot1''); + tmp2 \ n . ''host2''; + tmp2 . appendChild(slot); + tmp3 \ slot . assignedNodes(); + assert_array_equals(tmp3, []) +}) slots_heap" + by eval + + +text \'Slots: Mutation: Add a slot: before.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_complex''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_complex''; + removeWhiteSpaceOnlyTextNodes(tmp1); + slot \ slots_document . createElement(''slot''); + slot . setAttribute(''name'', ''slot1''); + tmp3 \ n . ''s1''; + tmp2 \ n . ''host2''; + tmp2 . insertBefore(slot, tmp3); + tmp4 \ slot . assignedNodes(); + tmp5 \ n . ''c1''; + assert_array_equals(tmp4, [tmp5]); + tmp6 \ n . ''c1''; + tmp7 \ tmp6 . assignedSlot; + assert_equals(tmp7, slot); + tmp8 \ n . ''s7''; + tmp9 \ tmp8 . assignedNodes(); + tmp10 \ n . ''s3''; + tmp11 \ n . ''c7''; + assert_array_equals(tmp9, [slot, tmp10, tmp11]); + tmp12 \ n . ''s7''; + tmp13 \ tmp12 . assignedNodes(True); + tmp14 \ n . ''c1''; + tmp15 \ n . ''c3''; + tmp16 \ n . ''c7''; + assert_array_equals(tmp13, [tmp14, tmp15, tmp16]) +}) slots_heap" + by eval + + +text \'Slots: Mutation: Remove a slot.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_complex''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_complex''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''s1''; + tmp2 . remove(); + tmp3 \ n . ''s1''; + tmp4 \ tmp3 . assignedNodes(); + assert_array_equals(tmp4, []); + tmp5 \ n . ''c1''; + tmp6 \ tmp5 . assignedSlot; + assert_equals(tmp6, None); + tmp7 \ n . ''s5''; + tmp8 \ tmp7 . assignedNodes(); + tmp9 \ n . ''c5''; + assert_array_equals(tmp8, [tmp9]); + tmp10 \ n . ''s5''; + tmp11 \ tmp10 . assignedNodes(True); + tmp12 \ n . ''c5''; + assert_array_equals(tmp11, [tmp12]) +}) slots_heap" + by eval + + +text \'Slots: Mutation: Change slot name= attribute.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_complex''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_complex''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''s1''; + tmp2 . setAttribute(''name'', ''slot2''); + tmp3 \ n . ''s1''; + tmp4 \ tmp3 . assignedNodes(); + tmp5 \ n . ''c2''; + assert_array_equals(tmp4, [tmp5]); + tmp6 \ n . ''c1''; + tmp7 \ tmp6 . assignedSlot; + assert_equals(tmp7, None); + tmp8 \ n . ''c2''; + tmp9 \ tmp8 . assignedSlot; + tmp10 \ n . ''s1''; + assert_equals(tmp9, tmp10); + tmp11 \ n . ''s5''; + tmp12 \ tmp11 . assignedNodes(); + tmp13 \ n . ''s1''; + tmp14 \ n . ''c5''; + assert_array_equals(tmp12, [tmp13, tmp14]); + tmp15 \ n . ''s5''; + tmp16 \ tmp15 . assignedNodes(True); + tmp17 \ n . ''c2''; + tmp18 \ n . ''c5''; + assert_array_equals(tmp16, [tmp17, tmp18]) +}) slots_heap" + by eval + + +text \'Slots: Mutation: Change slot slot= attribute.'\ + +lemma "test (do { + tmp0 \ slots_document . getElementById(''test_complex''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test_complex''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''s1''; + tmp2 . setAttribute(''slot'', ''slot6''); + tmp3 \ n . ''s1''; + tmp4 \ tmp3 . assignedNodes(); + tmp5 \ n . ''c1''; + assert_array_equals(tmp4, [tmp5]); + tmp6 \ n . ''s5''; + tmp7 \ tmp6 . assignedNodes(); + tmp8 \ n . ''c5''; + assert_array_equals(tmp7, [tmp8]); + tmp9 \ n . ''s6''; + tmp10 \ tmp9 . assignedNodes(); + tmp11 \ n . ''s1''; + tmp12 \ n . ''s2''; + tmp13 \ n . ''c6''; + assert_array_equals(tmp10, [tmp11, tmp12, tmp13]); + tmp14 \ n . ''s6''; + tmp15 \ tmp14 . assignedNodes(True); + tmp16 \ n . ''c1''; + tmp17 \ n . ''c2''; + tmp18 \ n . ''c6''; + assert_array_equals(tmp15, [tmp16, tmp17, tmp18]) +}) slots_heap" + by eval + + +end diff --git a/Shadow_DOM/tests/slots_fallback.thy b/Shadow_DOM/tests/slots_fallback.thy new file mode 100644 index 0000000..d0d4e78 --- /dev/null +++ b/Shadow_DOM/tests/slots_fallback.thy @@ -0,0 +1,507 @@ +(*********************************************************************************** + * Copyright (c) 2016-2020 The University of Sheffield, UK + * 2019-2020 University of Exeter, UK + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-2-Clause + ***********************************************************************************) + +(* This file is automatically generated, please do not modify! *) + +section\Testing slots\_fallback\ +text\This theory contains the test cases for slots\_fallback.\ + +theory slots_fallback +imports + "Shadow_DOM_BaseTest" +begin + +definition slots_fallback_heap :: "heap\<^sub>f\<^sub>i\<^sub>n\<^sub>a\<^sub>l" where + "slots_fallback_heap = create_heap [(cast (document_ptr.Ref 1), cast (create_document_obj html (Some (cast (element_ptr.Ref 1))) [])), + (cast (element_ptr.Ref 1), cast (create_element_obj ''html'' [cast (element_ptr.Ref 2), cast (element_ptr.Ref 8)] fmempty None)), + (cast (element_ptr.Ref 2), cast (create_element_obj ''head'' [cast (element_ptr.Ref 3), cast (element_ptr.Ref 4), cast (element_ptr.Ref 5), cast (element_ptr.Ref 6), cast (element_ptr.Ref 7)] fmempty None)), + (cast (element_ptr.Ref 3), cast (create_element_obj ''title'' [cast (character_data_ptr.Ref 1)] fmempty None)), + (cast (character_data_ptr.Ref 1), cast (create_character_data_obj ''Shadow%20DOM%3A%20Slots%20and%20fallback%20contents'')), + (cast (element_ptr.Ref 4), cast (create_element_obj ''meta'' [] (fmap_of_list [(''name'', ''author''), (''title'', ''Hayato Ito''), (''href'', ''mailto:hayato@google.com'')]) None)), + (cast (element_ptr.Ref 5), cast (create_element_obj ''script'' [] (fmap_of_list [(''src'', ''/resources/testharness.js'')]) None)), + (cast (element_ptr.Ref 6), cast (create_element_obj ''script'' [] (fmap_of_list [(''src'', ''/resources/testharnessreport.js'')]) None)), + (cast (element_ptr.Ref 7), cast (create_element_obj ''script'' [] (fmap_of_list [(''src'', ''resources/shadow-dom.js'')]) None)), + (cast (element_ptr.Ref 8), cast (create_element_obj ''body'' [cast (element_ptr.Ref 9), cast (element_ptr.Ref 13), cast (element_ptr.Ref 14), cast (element_ptr.Ref 19), cast (element_ptr.Ref 20), cast (element_ptr.Ref 26), cast (element_ptr.Ref 27), cast (element_ptr.Ref 33), cast (element_ptr.Ref 34), cast (element_ptr.Ref 46)] fmempty None)), + (cast (element_ptr.Ref 9), cast (create_element_obj ''div'' [cast (element_ptr.Ref 10)] (fmap_of_list [(''id'', ''test1'')]) None)), + (cast (element_ptr.Ref 10), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''host'')]) (Some (cast (shadow_root_ptr.Ref 1))))), + (cast (shadow_root_ptr.Ref 1), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 11)])), + (cast (element_ptr.Ref 11), cast (create_element_obj ''slot'' [cast (element_ptr.Ref 12)] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1'')]) None)), + (cast (element_ptr.Ref 12), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''f1'')]) None)), + (cast (element_ptr.Ref 13), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 2)] fmempty None)), + (cast (character_data_ptr.Ref 2), cast (create_character_data_obj ''%3C%3Cscript%3E%3E'')), + (cast (element_ptr.Ref 14), cast (create_element_obj ''div'' [cast (element_ptr.Ref 15)] (fmap_of_list [(''id'', ''test2'')]) None)), + (cast (element_ptr.Ref 15), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''host'')]) (Some (cast (shadow_root_ptr.Ref 2))))), + (cast (shadow_root_ptr.Ref 2), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 16)])), + (cast (element_ptr.Ref 16), cast (create_element_obj ''slot'' [cast (element_ptr.Ref 17)] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1'')]) None)), + (cast (element_ptr.Ref 17), cast (create_element_obj ''slot'' [cast (element_ptr.Ref 18)] (fmap_of_list [(''id'', ''s2''), (''name'', ''slot2'')]) None)), + (cast (element_ptr.Ref 18), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''f1'')]) None)), + (cast (element_ptr.Ref 19), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 3)] fmempty None)), + (cast (character_data_ptr.Ref 3), cast (create_character_data_obj ''%3C%3Cscript%3E%3E'')), + (cast (element_ptr.Ref 20), cast (create_element_obj ''div'' [cast (element_ptr.Ref 21)] (fmap_of_list [(''id'', ''test3'')]) None)), + (cast (element_ptr.Ref 21), cast (create_element_obj ''div'' [cast (element_ptr.Ref 22)] (fmap_of_list [(''id'', ''host'')]) (Some (cast (shadow_root_ptr.Ref 3))))), + (cast (element_ptr.Ref 22), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c1''), (''slot'', ''slot1'')]) None)), + (cast (shadow_root_ptr.Ref 3), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 23)])), + (cast (element_ptr.Ref 23), cast (create_element_obj ''slot'' [cast (element_ptr.Ref 24)] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1'')]) None)), + (cast (element_ptr.Ref 24), cast (create_element_obj ''slot'' [cast (element_ptr.Ref 25)] (fmap_of_list [(''id'', ''s2''), (''name'', ''slot2'')]) None)), + (cast (element_ptr.Ref 25), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''f1'')]) None)), + (cast (element_ptr.Ref 26), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 4)] fmempty None)), + (cast (character_data_ptr.Ref 4), cast (create_character_data_obj ''%3C%3Cscript%3E%3E'')), + (cast (element_ptr.Ref 27), cast (create_element_obj ''div'' [cast (element_ptr.Ref 28)] (fmap_of_list [(''id'', ''test4'')]) None)), + (cast (element_ptr.Ref 28), cast (create_element_obj ''div'' [cast (element_ptr.Ref 29)] (fmap_of_list [(''id'', ''host'')]) (Some (cast (shadow_root_ptr.Ref 4))))), + (cast (element_ptr.Ref 29), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c1''), (''slot'', ''slot2'')]) None)), + (cast (shadow_root_ptr.Ref 4), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 30)])), + (cast (element_ptr.Ref 30), cast (create_element_obj ''slot'' [cast (element_ptr.Ref 31)] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1'')]) None)), + (cast (element_ptr.Ref 31), cast (create_element_obj ''slot'' [cast (element_ptr.Ref 32)] (fmap_of_list [(''id'', ''s2''), (''name'', ''slot2'')]) None)), + (cast (element_ptr.Ref 32), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''f1'')]) None)), + (cast (element_ptr.Ref 33), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 5)] fmempty None)), + (cast (character_data_ptr.Ref 5), cast (create_character_data_obj ''%3C%3Cscript%3E%3E'')), + (cast (element_ptr.Ref 34), cast (create_element_obj ''div'' [cast (element_ptr.Ref 35)] (fmap_of_list [(''id'', ''test5'')]) None)), + (cast (element_ptr.Ref 35), cast (create_element_obj ''div'' [cast (element_ptr.Ref 36)] (fmap_of_list [(''id'', ''host1'')]) (Some (cast (shadow_root_ptr.Ref 5))))), + (cast (element_ptr.Ref 36), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''c1''), (''slot'', ''slot1'')]) None)), + (cast (shadow_root_ptr.Ref 5), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 37)])), + (cast (element_ptr.Ref 37), cast (create_element_obj ''div'' [cast (element_ptr.Ref 38)] (fmap_of_list [(''id'', ''host2'')]) (Some (cast (shadow_root_ptr.Ref 6))))), + (cast (element_ptr.Ref 38), cast (create_element_obj ''slot'' [cast (element_ptr.Ref 39), cast (element_ptr.Ref 41)] (fmap_of_list [(''id'', ''s2''), (''name'', ''slot2''), (''slot'', ''slot3'')]) None)), + (cast (element_ptr.Ref 39), cast (create_element_obj ''slot'' [cast (element_ptr.Ref 40)] (fmap_of_list [(''id'', ''s1''), (''name'', ''slot1'')]) None)), + (cast (element_ptr.Ref 40), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''f1'')]) None)), + (cast (element_ptr.Ref 41), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''f2'')]) None)), + (cast (shadow_root_ptr.Ref 6), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 42)])), + (cast (element_ptr.Ref 42), cast (create_element_obj ''slot'' [cast (element_ptr.Ref 43), cast (element_ptr.Ref 45)] (fmap_of_list [(''id'', ''s4''), (''name'', ''slot4'')]) None)), + (cast (element_ptr.Ref 43), cast (create_element_obj ''slot'' [cast (element_ptr.Ref 44)] (fmap_of_list [(''id'', ''s3''), (''name'', ''slot3'')]) None)), + (cast (element_ptr.Ref 44), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''f3'')]) None)), + (cast (element_ptr.Ref 45), cast (create_element_obj ''div'' [] (fmap_of_list [(''id'', ''f4'')]) None)), + (cast (element_ptr.Ref 46), cast (create_element_obj ''script'' [cast (character_data_ptr.Ref 6)] fmempty None)), + (cast (character_data_ptr.Ref 6), cast (create_character_data_obj ''%3C%3Cscript%3E%3E''))]" + +definition slots_fallback_document :: "(unit, unit, unit, unit, unit, unit) object_ptr option" where "slots_fallback_document = Some (cast (document_ptr.Ref 1))" + + +text \'Slots fallback: Basic.'\ + +lemma "test (do { + tmp0 \ slots_fallback_document . getElementById(''test1''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test1''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''f1''; + tmp3 \ tmp2 . assignedSlot; + assert_equals(tmp3, None); + tmp4 \ n . ''s1''; + tmp5 \ tmp4 . assignedNodes(); + assert_array_equals(tmp5, []); + tmp6 \ n . ''s1''; + tmp7 \ tmp6 . assignedNodes(True); + tmp8 \ n . ''f1''; + assert_array_equals(tmp7, [tmp8]) +}) slots_fallback_heap" + by eval + + +text \'Slots fallback: Basic, elements only.'\ + +lemma "test (do { + tmp0 \ slots_fallback_document . getElementById(''test1''); + n \ createTestTree(tmp0); + tmp1 \ n . ''s1''; + tmp2 \ tmp1 . assignedElements(); + assert_array_equals(tmp2, []); + tmp3 \ n . ''s1''; + tmp4 \ tmp3 . assignedElements(True); + tmp5 \ n . ''f1''; + assert_array_equals(tmp4, [tmp5]) +}) slots_fallback_heap" + by eval + + +text \'Slots fallback: Slots in Slots.'\ + +lemma "test (do { + tmp0 \ slots_fallback_document . getElementById(''test2''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test2''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''f1''; + tmp3 \ tmp2 . assignedSlot; + assert_equals(tmp3, None); + tmp4 \ n . ''s1''; + tmp5 \ tmp4 . assignedNodes(); + assert_array_equals(tmp5, []); + tmp6 \ n . ''s2''; + tmp7 \ tmp6 . assignedNodes(); + assert_array_equals(tmp7, []); + tmp8 \ n . ''s1''; + tmp9 \ tmp8 . assignedNodes(True); + tmp10 \ n . ''f1''; + assert_array_equals(tmp9, [tmp10]); + tmp11 \ n . ''s2''; + tmp12 \ tmp11 . assignedNodes(True); + tmp13 \ n . ''f1''; + assert_array_equals(tmp12, [tmp13]) +}) slots_fallback_heap" + by eval + + +text \'Slots fallback: Slots in Slots, elements only.'\ + +lemma "test (do { + tmp0 \ slots_fallback_document . getElementById(''test2''); + n \ createTestTree(tmp0); + tmp1 \ n . ''s1''; + tmp2 \ tmp1 . assignedElements(); + assert_array_equals(tmp2, []); + tmp3 \ n . ''s2''; + tmp4 \ tmp3 . assignedElements(); + assert_array_equals(tmp4, []); + tmp5 \ n . ''s1''; + tmp6 \ tmp5 . assignedElements(True); + tmp7 \ n . ''f1''; + assert_array_equals(tmp6, [tmp7]); + tmp8 \ n . ''s2''; + tmp9 \ tmp8 . assignedElements(True); + tmp10 \ n . ''f1''; + assert_array_equals(tmp9, [tmp10]) +}) slots_fallback_heap" + by eval + + +text \'Slots fallback: Fallback contents should not be used if a node is assigned.'\ + +lemma "test (do { + tmp0 \ slots_fallback_document . getElementById(''test3''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test3''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp3 \ tmp2 . assignedSlot; + tmp4 \ n . ''s1''; + assert_equals(tmp3, tmp4); + tmp5 \ n . ''f1''; + tmp6 \ tmp5 . assignedSlot; + assert_equals(tmp6, None); + tmp7 \ n . ''s1''; + tmp8 \ tmp7 . assignedNodes(); + tmp9 \ n . ''c1''; + assert_array_equals(tmp8, [tmp9]); + tmp10 \ n . ''s2''; + tmp11 \ tmp10 . assignedNodes(); + assert_array_equals(tmp11, []); + tmp12 \ n . ''s1''; + tmp13 \ tmp12 . assignedNodes(True); + tmp14 \ n . ''c1''; + assert_array_equals(tmp13, [tmp14]); + tmp15 \ n . ''s2''; + tmp16 \ tmp15 . assignedNodes(True); + tmp17 \ n . ''f1''; + assert_array_equals(tmp16, [tmp17]) +}) slots_fallback_heap" + by eval + + +text \'Slots fallback: Slots in Slots: Assigned nodes should be used as fallback contents of another slot'\ + +lemma "test (do { + tmp0 \ slots_fallback_document . getElementById(''test4''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test4''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp3 \ tmp2 . assignedSlot; + tmp4 \ n . ''s2''; + assert_equals(tmp3, tmp4); + tmp5 \ n . ''f1''; + tmp6 \ tmp5 . assignedSlot; + assert_equals(tmp6, None); + tmp7 \ n . ''s1''; + tmp8 \ tmp7 . assignedNodes(); + assert_array_equals(tmp8, []); + tmp9 \ n . ''s2''; + tmp10 \ tmp9 . assignedNodes(); + tmp11 \ n . ''c1''; + assert_array_equals(tmp10, [tmp11]); + tmp12 \ n . ''s1''; + tmp13 \ tmp12 . assignedNodes(True); + tmp14 \ n . ''c1''; + assert_array_equals(tmp13, [tmp14]); + tmp15 \ n . ''s2''; + tmp16 \ tmp15 . assignedNodes(True); + tmp17 \ n . ''c1''; + assert_array_equals(tmp16, [tmp17]) +}) slots_fallback_heap" + by eval + + +text \'Slots fallback: Complex case.'\ + +lemma "test (do { + tmp0 \ slots_fallback_document . getElementById(''test5''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test5''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''s1''; + tmp3 \ tmp2 . assignedNodes(); + tmp4 \ n . ''c1''; + assert_array_equals(tmp3, [tmp4]); + tmp5 \ n . ''s2''; + tmp6 \ tmp5 . assignedNodes(); + assert_array_equals(tmp6, []); + tmp7 \ n . ''s3''; + tmp8 \ tmp7 . assignedNodes(); + tmp9 \ n . ''s2''; + assert_array_equals(tmp8, [tmp9]); + tmp10 \ n . ''s4''; + tmp11 \ tmp10 . assignedNodes(); + assert_array_equals(tmp11, []); + tmp12 \ n . ''s1''; + tmp13 \ tmp12 . assignedNodes(True); + tmp14 \ n . ''c1''; + assert_array_equals(tmp13, [tmp14]); + tmp15 \ n . ''s2''; + tmp16 \ tmp15 . assignedNodes(True); + tmp17 \ n . ''c1''; + tmp18 \ n . ''f2''; + assert_array_equals(tmp16, [tmp17, tmp18]); + tmp19 \ n . ''s3''; + tmp20 \ tmp19 . assignedNodes(True); + tmp21 \ n . ''c1''; + tmp22 \ n . ''f2''; + assert_array_equals(tmp20, [tmp21, tmp22]); + tmp23 \ n . ''s4''; + tmp24 \ tmp23 . assignedNodes(True); + tmp25 \ n . ''c1''; + tmp26 \ n . ''f2''; + tmp27 \ n . ''f4''; + assert_array_equals(tmp24, [tmp25, tmp26, tmp27]) +}) slots_fallback_heap" + by eval + + +text \'Slots fallback: Complex case, elements only.'\ + +lemma "test (do { + tmp0 \ slots_fallback_document . getElementById(''test5''); + n \ createTestTree(tmp0); + tmp1 \ n . ''s1''; + tmp2 \ tmp1 . assignedElements(); + tmp3 \ n . ''c1''; + assert_array_equals(tmp2, [tmp3]); + tmp4 \ n . ''s2''; + tmp5 \ tmp4 . assignedElements(); + assert_array_equals(tmp5, []); + tmp6 \ n . ''s3''; + tmp7 \ tmp6 . assignedElements(); + tmp8 \ n . ''s2''; + assert_array_equals(tmp7, [tmp8]); + tmp9 \ n . ''s4''; + tmp10 \ tmp9 . assignedElements(); + assert_array_equals(tmp10, []); + tmp11 \ n . ''s1''; + tmp12 \ tmp11 . assignedElements(True); + tmp13 \ n . ''c1''; + assert_array_equals(tmp12, [tmp13]); + tmp14 \ n . ''s2''; + tmp15 \ tmp14 . assignedElements(True); + tmp16 \ n . ''c1''; + tmp17 \ n . ''f2''; + assert_array_equals(tmp15, [tmp16, tmp17]); + tmp18 \ n . ''s3''; + tmp19 \ tmp18 . assignedElements(True); + tmp20 \ n . ''c1''; + tmp21 \ n . ''f2''; + assert_array_equals(tmp19, [tmp20, tmp21]); + tmp22 \ n . ''s4''; + tmp23 \ tmp22 . assignedElements(True); + tmp24 \ n . ''c1''; + tmp25 \ n . ''f2''; + tmp26 \ n . ''f4''; + assert_array_equals(tmp23, [tmp24, tmp25, tmp26]) +}) slots_fallback_heap" + by eval + + +text \'Slots fallback: Mutation. Append fallback contents.'\ + +lemma "test (do { + tmp0 \ slots_fallback_document . getElementById(''test5''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test5''; + removeWhiteSpaceOnlyTextNodes(tmp1); + d1 \ slots_fallback_document . createElement(''div''); + tmp2 \ n . ''s2''; + tmp2 . appendChild(d1); + tmp3 \ n . ''s1''; + tmp4 \ tmp3 . assignedNodes(True); + tmp5 \ n . ''c1''; + assert_array_equals(tmp4, [tmp5]); + tmp6 \ n . ''s2''; + tmp7 \ tmp6 . assignedNodes(True); + tmp8 \ n . ''c1''; + tmp9 \ n . ''f2''; + assert_array_equals(tmp7, [tmp8, tmp9, d1]); + tmp10 \ n . ''s3''; + tmp11 \ tmp10 . assignedNodes(True); + tmp12 \ n . ''c1''; + tmp13 \ n . ''f2''; + assert_array_equals(tmp11, [tmp12, tmp13, d1]); + tmp14 \ n . ''s4''; + tmp15 \ tmp14 . assignedNodes(True); + tmp16 \ n . ''c1''; + tmp17 \ n . ''f2''; + tmp18 \ n . ''f4''; + assert_array_equals(tmp15, [tmp16, tmp17, d1, tmp18]) +}) slots_fallback_heap" + by eval + + +text \'Slots fallback: Mutation. Remove fallback contents.'\ + +lemma "test (do { + tmp0 \ slots_fallback_document . getElementById(''test5''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test5''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''f2''; + tmp2 . remove(); + tmp3 \ n . ''s1''; + tmp4 \ tmp3 . assignedNodes(True); + tmp5 \ n . ''c1''; + assert_array_equals(tmp4, [tmp5]); + tmp6 \ n . ''s2''; + tmp7 \ tmp6 . assignedNodes(True); + tmp8 \ n . ''c1''; + assert_array_equals(tmp7, [tmp8]); + tmp9 \ n . ''s3''; + tmp10 \ tmp9 . assignedNodes(True); + tmp11 \ n . ''c1''; + assert_array_equals(tmp10, [tmp11]); + tmp12 \ n . ''s4''; + tmp13 \ tmp12 . assignedNodes(True); + tmp14 \ n . ''c1''; + tmp15 \ n . ''f4''; + assert_array_equals(tmp13, [tmp14, tmp15]) +}) slots_fallback_heap" + by eval + + +text \'Slots fallback: Mutation. Assign a node to a slot so that fallback contens are no longer used.'\ + +lemma "test (do { + tmp0 \ slots_fallback_document . getElementById(''test5''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test5''; + removeWhiteSpaceOnlyTextNodes(tmp1); + d2 \ slots_fallback_document . createElement(''div''); + d2 . setAttribute(''slot'', ''slot2''); + tmp2 \ n . ''host1''; + tmp2 . appendChild(d2); + tmp3 \ n . ''s2''; + tmp4 \ tmp3 . assignedNodes(); + assert_array_equals(tmp4, [d2]); + tmp5 \ n . ''s2''; + tmp6 \ tmp5 . assignedNodes(True); + assert_array_equals(tmp6, [d2]); + tmp7 \ n . ''s3''; + tmp8 \ tmp7 . assignedNodes(True); + assert_array_equals(tmp8, [d2]); + tmp9 \ n . ''s4''; + tmp10 \ tmp9 . assignedNodes(True); + tmp11 \ n . ''f4''; + assert_array_equals(tmp10, [d2, tmp11]) +}) slots_fallback_heap" + by eval + + +text \'Slots fallback: Mutation. Remove an assigned node from a slot so that fallback contens will be used.'\ + +lemma "test (do { + tmp0 \ slots_fallback_document . getElementById(''test5''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test5''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''c1''; + tmp2 . remove(); + tmp3 \ n . ''s1''; + tmp4 \ tmp3 . assignedNodes(); + assert_array_equals(tmp4, []); + tmp5 \ n . ''s1''; + tmp6 \ tmp5 . assignedNodes(True); + tmp7 \ n . ''f1''; + assert_array_equals(tmp6, [tmp7]); + tmp8 \ n . ''s2''; + tmp9 \ tmp8 . assignedNodes(True); + tmp10 \ n . ''f1''; + tmp11 \ n . ''f2''; + assert_array_equals(tmp9, [tmp10, tmp11]); + tmp12 \ n . ''s3''; + tmp13 \ tmp12 . assignedNodes(True); + tmp14 \ n . ''f1''; + tmp15 \ n . ''f2''; + assert_array_equals(tmp13, [tmp14, tmp15]); + tmp16 \ n . ''s4''; + tmp17 \ tmp16 . assignedNodes(True); + tmp18 \ n . ''f1''; + tmp19 \ n . ''f2''; + tmp20 \ n . ''f4''; + assert_array_equals(tmp17, [tmp18, tmp19, tmp20]) +}) slots_fallback_heap" + by eval + + +text \'Slots fallback: Mutation. Remove a slot which is a fallback content of another slot.'\ + +lemma "test (do { + tmp0 \ slots_fallback_document . getElementById(''test5''); + n \ createTestTree(tmp0); + tmp1 \ n . ''test5''; + removeWhiteSpaceOnlyTextNodes(tmp1); + tmp2 \ n . ''s1''; + tmp2 . remove(); + tmp3 \ n . ''s1''; + tmp4 \ tmp3 . assignedNodes(); + assert_array_equals(tmp4, []); + tmp5 \ n . ''s1''; + tmp6 \ tmp5 . assignedNodes(True); + assert_array_equals(tmp6, [], ''fall back contents should be empty because s1 is not in a shadow tree.''); + tmp7 \ n . ''s2''; + tmp8 \ tmp7 . assignedNodes(True); + tmp9 \ n . ''f2''; + assert_array_equals(tmp8, [tmp9]); + tmp10 \ n . ''s3''; + tmp11 \ tmp10 . assignedNodes(True); + tmp12 \ n . ''f2''; + assert_array_equals(tmp11, [tmp12]); + tmp13 \ n . ''s4''; + tmp14 \ tmp13 . assignedNodes(True); + tmp15 \ n . ''f2''; + tmp16 \ n . ''f4''; + assert_array_equals(tmp14, [tmp15, tmp16]) +}) slots_fallback_heap" + by eval + + +end