Theory ElementClass
section‹Element›
text‹In this theory, we introduce the types for the Element class.›
theory ElementClass
imports
"NodeClass"
"ShadowRootPointer"
begin
text‹The type @{type "DOMString"} is a type synonym for @{type "string"}, define
in \autoref{sec:Core_DOM_Basic_Datatypes}.›
type_synonym attr_key = DOMString
type_synonym attr_value = DOMString
type_synonym attrs = "(attr_key, attr_value) fmap"
type_synonym tag_name = DOMString
record ('node_ptr, 'element_ptr, 'character_data_ptr, 'shadow_root_ptr) RElement = RNode +
nothing :: unit
tag_name :: tag_name
child_nodes :: "('node_ptr, 'element_ptr, 'character_data_ptr) node_ptr list"
attrs :: attrs
shadow_root_opt :: "'shadow_root_ptr shadow_root_ptr option"
type_synonym
('node_ptr, 'element_ptr, 'character_data_ptr, 'shadow_root_ptr, 'Element) Element
= "('node_ptr, 'element_ptr, 'character_data_ptr, 'shadow_root_ptr, 'Element option)
RElement_scheme"
register_default_tvars
"('node_ptr, 'element_ptr, 'character_data_ptr, 'shadow_root_ptr, 'Element) Element"
type_synonym
('node_ptr, 'element_ptr, 'character_data_ptr, 'shadow_root_ptr, 'Node, 'Element) Node
= "(('node_ptr, 'element_ptr, 'character_data_ptr, 'shadow_root_ptr, 'Element option) RElement_ext
+ 'Node) Node"
register_default_tvars
"('node_ptr, 'element_ptr, 'character_data_ptr, 'shadow_root_ptr, 'Node, 'Element) Node"
type_synonym
('node_ptr, 'element_ptr, 'character_data_ptr, 'shadow_root_ptr, 'Object, 'Node, 'Element) Object
= "('Object, ('node_ptr, 'element_ptr, 'character_data_ptr, 'shadow_root_ptr, 'Element option)
RElement_ext + 'Node) Object"
register_default_tvars
"('node_ptr, 'element_ptr, 'character_data_ptr, 'shadow_root_ptr, 'Object, 'Node, 'Element) Object"
type_synonym
('object_ptr, 'node_ptr, 'element_ptr, 'character_data_ptr, 'document_ptr, 'shadow_root_ptr,
'Object, 'Node, 'Element) heap
= "('document_ptr document_ptr + 'shadow_root_ptr shadow_root_ptr + 'object_ptr,
'element_ptr element_ptr + 'character_data_ptr character_data_ptr + 'node_ptr, 'Object,
('node_ptr, 'element_ptr, 'character_data_ptr, 'shadow_root_ptr, 'Element option) RElement_ext +
'Node) heap"
register_default_tvars
"('object_ptr, 'node_ptr, 'element_ptr, 'character_data_ptr, 'document_ptr, 'shadow_root_ptr,
'Object, 'Node, 'Element) heap"
type_synonym heap⇩f⇩i⇩n⇩a⇩l = "(unit, unit, unit, unit, unit, unit, unit, unit, unit) heap"
definition element_ptr_kinds :: "(_) heap ⇒ (_) element_ptr fset"
where
"element_ptr_kinds heap =
the |`| (cast⇩n⇩o⇩d⇩e⇩_⇩p⇩t⇩r⇩2⇩e⇩l⇩e⇩m⇩e⇩n⇩t⇩_⇩p⇩t⇩r |`| (ffilter is_element_ptr_kind (node_ptr_kinds heap)))"
lemma element_ptr_kinds_simp [simp]:
"element_ptr_kinds (Heap (fmupd (cast element_ptr) element (the_heap h))) =
{|element_ptr|} |∪| element_ptr_kinds h"
by (auto simp add: element_ptr_kinds_def)
definition element_ptrs :: "(_) heap ⇒ (_) element_ptr fset"
where
"element_ptrs heap = ffilter is_element_ptr (element_ptr_kinds heap)"
definition cast⇩N⇩o⇩d⇩e⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t :: "(_) Node ⇒ (_) Element option"
where
"cast⇩N⇩o⇩d⇩e⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t node =
(case RNode.more node of Inl element ⇒ Some (RNode.extend (RNode.truncate node) element) | _ ⇒ None)"
adhoc_overloading cast cast⇩N⇩o⇩d⇩e⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t
abbreviation cast⇩O⇩b⇩j⇩e⇩c⇩t⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t :: "(_) Object ⇒ (_) Element option"
where
"cast⇩O⇩b⇩j⇩e⇩c⇩t⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t obj ≡ (case cast⇩O⇩b⇩j⇩e⇩c⇩t⇩2⇩N⇩o⇩d⇩e obj of Some node ⇒ cast⇩N⇩o⇩d⇩e⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t node | None ⇒ None)"
adhoc_overloading cast cast⇩O⇩b⇩j⇩e⇩c⇩t⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t
definition cast⇩E⇩l⇩e⇩m⇩e⇩n⇩t⇩2⇩N⇩o⇩d⇩e :: "(_) Element ⇒ (_) Node"
where
"cast⇩E⇩l⇩e⇩m⇩e⇩n⇩t⇩2⇩N⇩o⇩d⇩e element = RNode.extend (RNode.truncate element) (Inl (RNode.more element))"
adhoc_overloading cast cast⇩E⇩l⇩e⇩m⇩e⇩n⇩t⇩2⇩N⇩o⇩d⇩e
abbreviation cast⇩E⇩l⇩e⇩m⇩e⇩n⇩t⇩2⇩O⇩b⇩j⇩e⇩c⇩t :: "(_) Element ⇒ (_) Object"
where
"cast⇩E⇩l⇩e⇩m⇩e⇩n⇩t⇩2⇩O⇩b⇩j⇩e⇩c⇩t ptr ≡ cast⇩N⇩o⇩d⇩e⇩2⇩O⇩b⇩j⇩e⇩c⇩t (cast⇩E⇩l⇩e⇩m⇩e⇩n⇩t⇩2⇩N⇩o⇩d⇩e ptr)"
adhoc_overloading cast cast⇩E⇩l⇩e⇩m⇩e⇩n⇩t⇩2⇩O⇩b⇩j⇩e⇩c⇩t
consts is_element_kind :: 'a
definition is_element_kind⇩N⇩o⇩d⇩e :: "(_) Node ⇒ bool"
where
"is_element_kind⇩N⇩o⇩d⇩e ptr ⟷ cast⇩N⇩o⇩d⇩e⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t ptr ≠ None"
adhoc_overloading is_element_kind is_element_kind⇩N⇩o⇩d⇩e
lemmas is_element_kind_def = is_element_kind⇩N⇩o⇩d⇩e_def
abbreviation is_element_kind⇩O⇩b⇩j⇩e⇩c⇩t :: "(_) Object ⇒ bool"
where
"is_element_kind⇩O⇩b⇩j⇩e⇩c⇩t ptr ≡ cast⇩O⇩b⇩j⇩e⇩c⇩t⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t ptr ≠ None"
adhoc_overloading is_element_kind is_element_kind⇩O⇩b⇩j⇩e⇩c⇩t
lemma element_ptr_kinds_commutes [simp]:
"cast element_ptr |∈| node_ptr_kinds h ⟷ element_ptr |∈| element_ptr_kinds h"
proof (rule iffI)
show "cast element_ptr |∈| node_ptr_kinds h ⟹ element_ptr |∈| element_ptr_kinds h"
by (metis (no_types, opaque_lifting) element_ptr_casts_commute2 element_ptr_kinds_def
ffmember_filter fimage_eqI is_element_ptr_kind_cast option.sel)
next
show "element_ptr |∈| element_ptr_kinds h ⟹ cast element_ptr |∈| node_ptr_kinds h"
by (auto simp: node_ptr_kinds_def element_ptr_kinds_def)
qed
definition get⇩E⇩l⇩e⇩m⇩e⇩n⇩t :: "(_) element_ptr ⇒ (_) heap ⇒ (_) Element option"
where
"get⇩E⇩l⇩e⇩m⇩e⇩n⇩t element_ptr h = Option.bind (get⇩N⇩o⇩d⇩e (cast element_ptr) h) cast"
adhoc_overloading get get⇩E⇩l⇩e⇩m⇩e⇩n⇩t
locale l_type_wf_def⇩E⇩l⇩e⇩m⇩e⇩n⇩t
begin
definition a_type_wf :: "(_) heap ⇒ bool"
where
"a_type_wf h = (NodeClass.type_wf h ∧ (∀element_ptr ∈ fset (element_ptr_kinds h).
get⇩E⇩l⇩e⇩m⇩e⇩n⇩t element_ptr h ≠ None))"
end
global_interpretation l_type_wf_def⇩E⇩l⇩e⇩m⇩e⇩n⇩t defines type_wf = a_type_wf .
lemmas type_wf_defs = a_type_wf_def
locale l_type_wf⇩E⇩l⇩e⇩m⇩e⇩n⇩t = l_type_wf type_wf for type_wf :: "((_) heap ⇒ bool)" +
assumes type_wf⇩E⇩l⇩e⇩m⇩e⇩n⇩t: "type_wf h ⟹ ElementClass.type_wf h"
sublocale l_type_wf⇩E⇩l⇩e⇩m⇩e⇩n⇩t ⊆ l_type_wf⇩N⇩o⇩d⇩e
apply(unfold_locales)
using NodeClass.a_type_wf_def
by (meson ElementClass.a_type_wf_def l_type_wf⇩E⇩l⇩e⇩m⇩e⇩n⇩t_axioms l_type_wf⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def)
locale l_get⇩E⇩l⇩e⇩m⇩e⇩n⇩t_lemmas = l_type_wf⇩E⇩l⇩e⇩m⇩e⇩n⇩t
begin
sublocale l_get⇩N⇩o⇩d⇩e_lemmas by unfold_locales
lemma get⇩E⇩l⇩e⇩m⇩e⇩n⇩t_type_wf:
assumes "type_wf h"
shows "element_ptr |∈| element_ptr_kinds h ⟷ get⇩E⇩l⇩e⇩m⇩e⇩n⇩t element_ptr h ≠ None"
proof (rule iffI)
show "element_ptr |∈| element_ptr_kinds h ⟹ get element_ptr h ≠ None"
using ElementClass.a_type_wf_def assms type_wf⇩E⇩l⇩e⇩m⇩e⇩n⇩t by blast
next
show "get element_ptr h ≠ None ⟹ element_ptr |∈| element_ptr_kinds h"
by (metis NodeClass.get⇩N⇩o⇩d⇩e_type_wf assms bind.bind_lzero element_ptr_kinds_commutes
get⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def local.type_wf⇩N⇩o⇩d⇩e)
qed
end
global_interpretation l_get⇩E⇩l⇩e⇩m⇩e⇩n⇩t_lemmas type_wf
by unfold_locales
definition put⇩E⇩l⇩e⇩m⇩e⇩n⇩t :: "(_) element_ptr ⇒ (_) Element ⇒ (_) heap ⇒ (_) heap"
where
"put⇩E⇩l⇩e⇩m⇩e⇩n⇩t element_ptr element = put⇩N⇩o⇩d⇩e (cast element_ptr) (cast element)"
adhoc_overloading put put⇩E⇩l⇩e⇩m⇩e⇩n⇩t
lemma put⇩E⇩l⇩e⇩m⇩e⇩n⇩t_ptr_in_heap:
assumes "put⇩E⇩l⇩e⇩m⇩e⇩n⇩t element_ptr element h = h'"
shows "element_ptr |∈| element_ptr_kinds h'"
using assms
unfolding put⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def element_ptr_kinds_def
by (metis element_ptr_kinds_commutes element_ptr_kinds_def put⇩N⇩o⇩d⇩e_ptr_in_heap)
lemma put⇩E⇩l⇩e⇩m⇩e⇩n⇩t_put_ptrs:
assumes "put⇩E⇩l⇩e⇩m⇩e⇩n⇩t element_ptr element h = h'"
shows "object_ptr_kinds h' = object_ptr_kinds h |∪| {|cast element_ptr|}"
using assms
by (simp add: put⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def put⇩N⇩o⇩d⇩e_put_ptrs)
lemma cast⇩E⇩l⇩e⇩m⇩e⇩n⇩t⇩2⇩N⇩o⇩d⇩e_inject [simp]:
"cast⇩E⇩l⇩e⇩m⇩e⇩n⇩t⇩2⇩N⇩o⇩d⇩e x = cast⇩E⇩l⇩e⇩m⇩e⇩n⇩t⇩2⇩N⇩o⇩d⇩e y ⟷ x = y"
apply(simp add: cast⇩E⇩l⇩e⇩m⇩e⇩n⇩t⇩2⇩N⇩o⇩d⇩e_def RObject.extend_def RNode.extend_def)
by (metis (full_types) RNode.surjective old.unit.exhaust)
lemma cast⇩N⇩o⇩d⇩e⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t_none [simp]:
"cast⇩N⇩o⇩d⇩e⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t node = None ⟷ ¬ (∃element. cast⇩E⇩l⇩e⇩m⇩e⇩n⇩t⇩2⇩N⇩o⇩d⇩e element = node)"
apply(auto simp add: cast⇩N⇩o⇩d⇩e⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def cast⇩E⇩l⇩e⇩m⇩e⇩n⇩t⇩2⇩N⇩o⇩d⇩e_def RObject.extend_def RNode.extend_def
split: sum.splits)[1]
by (metis (full_types) RNode.select_convs(2) RNode.surjective old.unit.exhaust)
lemma cast⇩N⇩o⇩d⇩e⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t_some [simp]:
"cast⇩N⇩o⇩d⇩e⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t node = Some element ⟷ cast⇩E⇩l⇩e⇩m⇩e⇩n⇩t⇩2⇩N⇩o⇩d⇩e element = node"
by(auto simp add: cast⇩N⇩o⇩d⇩e⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def cast⇩E⇩l⇩e⇩m⇩e⇩n⇩t⇩2⇩N⇩o⇩d⇩e_def RObject.extend_def RNode.extend_def
split: sum.splits)
lemma cast⇩N⇩o⇩d⇩e⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t_inv [simp]: "cast⇩N⇩o⇩d⇩e⇩2⇩E⇩l⇩e⇩m⇩e⇩n⇩t (cast⇩E⇩l⇩e⇩m⇩e⇩n⇩t⇩2⇩N⇩o⇩d⇩e element) = Some element"
by simp
lemma get_elment_ptr_simp1 [simp]:
"get⇩E⇩l⇩e⇩m⇩e⇩n⇩t element_ptr (put⇩E⇩l⇩e⇩m⇩e⇩n⇩t element_ptr element h) = Some element"
by(auto simp add: get⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def put⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def)
lemma get_elment_ptr_simp2 [simp]:
"element_ptr ≠ element_ptr'
⟹ get⇩E⇩l⇩e⇩m⇩e⇩n⇩t element_ptr (put⇩E⇩l⇩e⇩m⇩e⇩n⇩t element_ptr' element h) = get⇩E⇩l⇩e⇩m⇩e⇩n⇩t element_ptr h"
by(auto simp add: get⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def put⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def)
abbreviation "create_element_obj tag_name_arg child_nodes_arg attrs_arg shadow_root_opt_arg
≡ ⦇ RObject.nothing = (), RNode.nothing = (), RElement.nothing = (),
tag_name = tag_name_arg, Element.child_nodes = child_nodes_arg, attrs = attrs_arg,
shadow_root_opt = shadow_root_opt_arg, … = None ⦈"
definition new⇩E⇩l⇩e⇩m⇩e⇩n⇩t :: "(_) heap ⇒ ((_) element_ptr × (_) heap)"
where
"new⇩E⇩l⇩e⇩m⇩e⇩n⇩t h =
(let new_element_ptr = element_ptr.Ref (Suc (fMax (finsert 0 (element_ptr.the_ref
|`| (element_ptrs h)))))
in
(new_element_ptr, put new_element_ptr (create_element_obj '''' [] fmempty None) h))"
lemma new⇩E⇩l⇩e⇩m⇩e⇩n⇩t_ptr_in_heap:
assumes "new⇩E⇩l⇩e⇩m⇩e⇩n⇩t h = (new_element_ptr, h')"
shows "new_element_ptr |∈| element_ptr_kinds h'"
using assms
unfolding new⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def Let_def
using put⇩E⇩l⇩e⇩m⇩e⇩n⇩t_ptr_in_heap by blast
lemma new_element_ptr_new:
"element_ptr.Ref (Suc (fMax (finsert 0 (element_ptr.the_ref |`| element_ptrs h)))) |∉| element_ptrs h"
by (metis Suc_n_not_le_n element_ptr.sel(1) fMax_ge fimage_finsert finsertI1 finsertI2 set_finsert)
lemma new⇩E⇩l⇩e⇩m⇩e⇩n⇩t_ptr_not_in_heap:
assumes "new⇩E⇩l⇩e⇩m⇩e⇩n⇩t h = (new_element_ptr, h')"
shows "new_element_ptr |∉| element_ptr_kinds h"
using assms
unfolding new⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def
by (metis Pair_inject element_ptrs_def ffmember_filter new_element_ptr_new is_element_ptr_ref)
lemma new⇩E⇩l⇩e⇩m⇩e⇩n⇩t_new_ptr:
assumes "new⇩E⇩l⇩e⇩m⇩e⇩n⇩t h = (new_element_ptr, h')"
shows "object_ptr_kinds h' = object_ptr_kinds h |∪| {|cast new_element_ptr|}"
using assms
by (metis Pair_inject new⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def put⇩E⇩l⇩e⇩m⇩e⇩n⇩t_put_ptrs)
lemma new⇩E⇩l⇩e⇩m⇩e⇩n⇩t_is_element_ptr:
assumes "new⇩E⇩l⇩e⇩m⇩e⇩n⇩t h = (new_element_ptr, h')"
shows "is_element_ptr new_element_ptr"
using assms
by(auto simp add: new⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def Let_def)
lemma new⇩E⇩l⇩e⇩m⇩e⇩n⇩t_get⇩O⇩b⇩j⇩e⇩c⇩t [simp]:
assumes "new⇩E⇩l⇩e⇩m⇩e⇩n⇩t h = (new_element_ptr, h')"
assumes "ptr ≠ cast new_element_ptr"
shows "get⇩O⇩b⇩j⇩e⇩c⇩t ptr h = get⇩O⇩b⇩j⇩e⇩c⇩t ptr h'"
using assms
by(auto simp add: new⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def Let_def put⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def put⇩N⇩o⇩d⇩e_def)
lemma new⇩E⇩l⇩e⇩m⇩e⇩n⇩t_get⇩N⇩o⇩d⇩e [simp]:
assumes "new⇩E⇩l⇩e⇩m⇩e⇩n⇩t h = (new_element_ptr, h')"
assumes "ptr ≠ cast new_element_ptr"
shows "get⇩N⇩o⇩d⇩e ptr h = get⇩N⇩o⇩d⇩e ptr h'"
using assms
by(auto simp add: new⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def Let_def put⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def)
lemma new⇩E⇩l⇩e⇩m⇩e⇩n⇩t_get⇩E⇩l⇩e⇩m⇩e⇩n⇩t [simp]:
assumes "new⇩E⇩l⇩e⇩m⇩e⇩n⇩t h = (new_element_ptr, h')"
assumes "ptr ≠ new_element_ptr"
shows "get⇩E⇩l⇩e⇩m⇩e⇩n⇩t ptr h = get⇩E⇩l⇩e⇩m⇩e⇩n⇩t ptr h'"
using assms
by(auto simp add: new⇩E⇩l⇩e⇩m⇩e⇩n⇩t_def Let_def)
locale l_known_ptr⇩E⇩l⇩e⇩m⇩e⇩n⇩t
begin
definition a_known_ptr :: "(_) object_ptr ⇒ bool"
where
"a_known_ptr ptr = (known_ptr ptr ∨ is_element_ptr ptr)"
lemma known_ptr_not_element_ptr: "¬is_element_ptr ptr ⟹ a_known_ptr ptr ⟹ known_ptr ptr"
by(simp add: a_known_ptr_def)
end
global_interpretation l_known_ptr⇩E⇩l⇩e⇩m⇩e⇩n⇩t defines known_ptr = a_known_ptr .
lemmas known_ptr_defs = a_known_ptr_def
locale l_known_ptrs⇩E⇩l⇩e⇩m⇩e⇩n⇩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:
"ptr |∈| object_ptr_kinds h ⟹ a_known_ptrs h ⟹ known_ptr ptr"
by (simp add: a_known_ptrs_def)
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: a_known_ptrs_def less_eq_fset.rep_eq 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⇩E⇩l⇩e⇩m⇩e⇩n⇩t known_ptr defines known_ptrs = a_known_ptrs .
lemmas known_ptrs_defs = a_known_ptrs_def
lemma known_ptrs_is_l_known_ptrs: "l_known_ptrs known_ptr known_ptrs"
using known_ptrs_known_ptr known_ptrs_preserved known_ptrs_subset known_ptrs_new_ptr l_known_ptrs_def by blast
end