Theory ElementPointer

(***********************************************************************************
 * Copyright (c) 2016-2018 The University of Sheffield, 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‹Element›
text‹In this theory, we introduce the typed pointers for the class Element.›   
theory ElementPointer
  imports
    NodePointer
begin

datatype 'element_ptr element_ptr = Ref (the_ref: ref) | Ext 'element_ptr
register_default_tvars "'element_ptr element_ptr" 

type_synonym ('node_ptr, 'element_ptr) node_ptr
  = "('element_ptr element_ptr + 'node_ptr) node_ptr"
register_default_tvars "('node_ptr, 'element_ptr) node_ptr" 
type_synonym ('object_ptr, 'node_ptr, 'element_ptr) object_ptr
  = "('object_ptr, 'element_ptr element_ptr + 'node_ptr) object_ptr"
register_default_tvars "('object_ptr, 'node_ptr, 'element_ptr) object_ptr" 


definition castelement_ptr2element_ptr :: "(_) element_ptr  (_) element_ptr"
  where
    "castelement_ptr2element_ptr = id"

definition castelement_ptr2node_ptr :: "(_) element_ptr  (_) node_ptr"
  where
    "castelement_ptr2node_ptr ptr = node_ptr.Ext (Inl ptr)"

abbreviation castelement_ptr2object_ptr :: "(_) element_ptr  (_) object_ptr"
  where
    "castelement_ptr2object_ptr ptr  castnode_ptr2object_ptr (castelement_ptr2node_ptr ptr)"

definition castnode_ptr2element_ptr :: "(_) node_ptr  (_) element_ptr option"
  where
    "castnode_ptr2element_ptr node_ptr = (case node_ptr of node_ptr.Ext (Inl element_ptr) 
                                           Some element_ptr | _  None)"

abbreviation castobject_ptr2element_ptr :: "(_) object_ptr  (_) element_ptr option"
  where
    "castobject_ptr2element_ptr ptr  (case castobject_ptr2node_ptr ptr of 
                                  Some node_ptr  castnode_ptr2element_ptr node_ptr 
                                | None  None)"

adhoc_overloading cast castelement_ptr2node_ptr castelement_ptr2object_ptr 
  castnode_ptr2element_ptr castobject_ptr2element_ptr castelement_ptr2element_ptr

consts is_element_ptr_kind :: 'a
definition is_element_ptr_kindnode_ptr :: "(_) node_ptr  bool"
  where
    "is_element_ptr_kindnode_ptr ptr = (case castnode_ptr2element_ptr ptr of Some _  True | _  False)"

abbreviation is_element_ptr_kindobject_ptr :: "(_) object_ptr  bool"
  where
    "is_element_ptr_kindobject_ptr ptr  (case cast ptr of 
                                             Some node_ptr  is_element_ptr_kindnode_ptr node_ptr 
                                           | None  False)"

adhoc_overloading is_element_ptr_kind is_element_ptr_kindobject_ptr is_element_ptr_kindnode_ptr
lemmas is_element_ptr_kind_def = is_element_ptr_kindnode_ptr_def

consts is_element_ptr :: 'a
definition is_element_ptrelement_ptr :: "(_) element_ptr  bool"
  where
    "is_element_ptrelement_ptr ptr = (case ptr of element_ptr.Ref _  True | _  False)"

abbreviation is_element_ptrnode_ptr :: "(_) node_ptr  bool"
  where
    "is_element_ptrnode_ptr ptr  (case cast ptr of 
                                   Some element_ptr  is_element_ptrelement_ptr element_ptr 
                                 | _  False)"

abbreviation is_element_ptrobject_ptr :: "(_) object_ptr  bool"
  where
    "is_element_ptrobject_ptr ptr  (case cast ptr of 
                                    Some node_ptr  is_element_ptrnode_ptr node_ptr 
                                  | None  False)"

adhoc_overloading is_element_ptr is_element_ptrobject_ptr is_element_ptrnode_ptr is_element_ptrelement_ptr
lemmas is_element_ptr_def = is_element_ptrelement_ptr_def

consts is_element_ptr_ext :: 'a
abbreviation "is_element_ptr_extelement_ptr ptr  ¬ is_element_ptrelement_ptr ptr"

abbreviation "is_element_ptr_extnode_ptr ptr  is_element_ptr_kind ptr  (¬ is_element_ptrnode_ptr ptr)"

abbreviation "is_element_ptr_extobject_ptr ptr  is_element_ptr_kind ptr  (¬ is_element_ptrobject_ptr ptr)"
adhoc_overloading is_element_ptr_ext is_element_ptr_extobject_ptr is_element_ptr_extnode_ptr


instantiation element_ptr :: (linorder) linorder
begin
definition 
  less_eq_element_ptr :: "(_::linorder) element_ptr  (_)element_ptr  bool"
  where 
    "less_eq_element_ptr x y  (case x of Ext i  (case y of Ext j  i  j | Ref _  False)
                                        | Ref i  (case y of Ext _  True | Ref j  i  j))"
definition 
  less_element_ptr :: "(_::linorder) element_ptr  (_) element_ptr  bool"
  where "less_element_ptr x y  x  y  ¬ y  x"
instance 
  apply(standard) 
  by(auto simp add: less_eq_element_ptr_def less_element_ptr_def split: element_ptr.splits)
end

lemma is_element_ptr_ref [simp]: "is_element_ptr (element_ptr.Ref n)"
  by(simp add: is_element_ptrelement_ptr_def)

lemma element_ptr_casts_commute [simp]:
  "castnode_ptr2element_ptr node_ptr = Some element_ptr  castelement_ptr2node_ptr element_ptr = node_ptr"
  unfolding castnode_ptr2element_ptr_def castelement_ptr2node_ptr_def
  by(auto split: node_ptr.splits sum.splits)

lemma element_ptr_casts_commute2 [simp]: 
  "(castnode_ptr2element_ptr (castelement_ptr2node_ptr element_ptr) = Some element_ptr)"
  by simp

lemma element_ptr_casts_commute3 [simp]:
  assumes "is_element_ptr_kindnode_ptr node_ptr"
  shows "castelement_ptr2node_ptr (the (castnode_ptr2element_ptr node_ptr)) = node_ptr"
  using assms
  by(auto simp add: is_element_ptr_kind_def castelement_ptr2node_ptr_def castnode_ptr2element_ptr_def 
      split: node_ptr.splits sum.splits)

lemma is_element_ptr_kind_obtains:
  assumes "is_element_ptr_kind node_ptr"
  obtains element_ptr where "node_ptr = castelement_ptr2node_ptr element_ptr"
  by (metis assms is_element_ptr_kind_def case_optionE element_ptr_casts_commute)

lemma is_element_ptr_kind_none:
  assumes "¬is_element_ptr_kind node_ptr"
  shows "castnode_ptr2element_ptr node_ptr = None"
  using assms
  unfolding is_element_ptr_kind_def castnode_ptr2element_ptr_def
  by(auto split: node_ptr.splits sum.splits)

lemma is_element_ptr_kind_cast [simp]: 
  "is_element_ptr_kind (castelement_ptr2node_ptr element_ptr)"
  by (metis element_ptr_casts_commute is_element_ptr_kind_none option.distinct(1))

lemma castelement_ptr2node_ptr_inject [simp]: 
  "castelement_ptr2node_ptr x = castelement_ptr2node_ptr y  x = y"
  by(simp add: castelement_ptr2node_ptr_def)

lemma castnode_ptr2element_ptr_ext_none [simp]: 
  "castnode_ptr2element_ptr (node_ptr.Ext (Inr (Inr node_ext_ptr))) = None"
  by(simp add: castnode_ptr2element_ptr_def)

lemma is_element_ptr_implies_kind [dest]: "is_element_ptrnode_ptr ptr  is_element_ptr_kindnode_ptr ptr"
  by(auto split: option.splits)

end