Library zoo_std.xtdlchain

Require Import zoo.prelude.
Require Import zoo.base.
Require Import zoo_std.xdlchain.
Require Export zoo_std.xtdlchain__code.
Require Import zoo_std.xtdlchain__types.
Require Import zoo.options.

Implicit Type node : location.
Implicit Type nodes : list location.
Implicit Type v next prev src dst : val.

Section zoo۰G.
  Context `{zoo۰G : !ZooG Σ}.

  Definition xtdlchain hdr src nodes dst : iProp Σ :=
    xdlchain src nodes dst
    [∗ list] node nodes, headers۰at node hdr.

  #[global] Instance xtdlchaintimeless hdr src nodes dst :
    Timeless (xtdlchain hdr src nodes dst).

  Lemma xtdlchainnil hdr src dst :
     xtdlchain hdr src [] dst.

  Lemma xtdlchainsingleton hdr src node dst :
    xtdlchain hdr src [node] dst ⊣⊢
      node ↦ₕ hdr
      node.[prev] src
      node.[next] dst.
  Lemma xtdlchainsingleton₁ hdr src node dst :
    xtdlchain hdr src [node] dst
      node ↦ₕ hdr
      node.[prev] src
      node.[next] dst.
  Lemma xtdlchainsingleton₂ hdr src node dst :
    node ↦ₕ hdr
    node.[prev] src -∗
    node.[next] dst -∗
    xtdlchain hdr src [node] dst.

  Lemma xtdlchaincons {hdr src} nodes node nodes' dst :
    nodes = node :: nodes'
    xtdlchain hdr src nodes dst ⊣⊢
      node ↦ₕ hdr
      node.[prev] src
      node.[next] from_option #@{location} dst (head nodes')
      xtdlchain hdr #node nodes' dst.
  Lemma xtdlchaincons₁ {hdr src} nodes node nodes' dst :
    nodes = node :: nodes'
    xtdlchain hdr src nodes dst
      node ↦ₕ hdr
      node.[prev] src
      node.[next] from_option #@{location} dst (head nodes')
      xtdlchain hdr #node nodes' dst.
  Lemma xtdlchaincons₂ hdr src node nodes dst :
    node ↦ₕ hdr
    node.[prev] src -∗
    node.[next] from_option #@{location} dst (head nodes) -∗
    xtdlchain hdr #node nodes dst -∗
    xtdlchain hdr src (node :: nodes) dst.

  Lemma xtdlchainapp {hdr src} nodes nodes1 nodes2 dst :
    nodes = nodes1 ++ nodes2
    xtdlchain hdr src nodes dst ⊣⊢
      xtdlchain hdr src nodes1 (from_option #@{location} dst (head nodes2))
      xtdlchain hdr (from_option #@{location} src (last nodes1)) nodes2 dst.
  Lemma xtdlchainapp₁ {hdr src} nodes nodes1 nodes2 dst :
    nodes = nodes1 ++ nodes2
    xtdlchain hdr src nodes dst
      xtdlchain hdr src nodes1 (from_option #@{location} dst (head nodes2))
      xtdlchain hdr (from_option #@{location} src (last nodes1)) nodes2 dst.
  Lemma xtdlchainapp₂ hdr src nodes1 nodes2 dst :
    xtdlchain hdr src nodes1 (from_option #@{location} dst (head nodes2)) -∗
    xtdlchain hdr (from_option #@{location} src (last nodes1)) nodes2 dst -∗
    xtdlchain hdr src (nodes1 ++ nodes2) dst.

  Lemma xtdlchainsnoc {hdr src} nodes nodes' node dst :
    nodes = nodes' ++ [node]
    xtdlchain hdr src nodes dst ⊣⊢
      xtdlchain hdr src nodes' #node
      node ↦ₕ hdr
      node.[prev] from_option #@{location} src (last nodes')
      node.[next] dst.
  Lemma xtdlchainsnoc₁ {hdr src} nodes nodes' node dst :
    nodes = nodes' ++ [node]
    xtdlchain hdr src nodes dst
      xtdlchain hdr src nodes' #node
      node ↦ₕ hdr
      node.[prev] from_option #@{location} src (last nodes')
      node.[next] dst.
  Lemma xtdlchainsnoc₂ hdr src nodes node dst :
    xtdlchain hdr src nodes #node -∗
    node ↦ₕ hdr -∗
    node.[prev] from_option #@{location} src (last nodes) -∗
    node.[next] dst -∗
    xtdlchain hdr src (nodes ++ [node]) dst.

  Lemma xtdlchainlast {hdr src nodes} node dst :
    last nodes = Some node
    xtdlchain hdr src nodes dst
       nodes',
      nodes = nodes' ++ [node]
      xtdlchain hdr src nodes' #node
      node ↦ₕ hdr
      node.[prev] from_option #@{location} src (last nodes')
      node.[next] dst.

  Lemma xtdlchainlookup {hdr src nodes} i node dst :
    nodes !! i = Some node
    xtdlchain hdr src nodes dst ⊣⊢
      xtdlchain hdr src (take i nodes) #node
      node ↦ₕ hdr
      node.[prev] from_option #@{location} src (last $ take i nodes)
      node.[next] from_option #@{location} dst (head $ drop ˖i nodes)
      xtdlchain hdr #node (drop ˖i nodes) dst.
  Lemma xtdlchainlookup₁ {hdr src nodes} i node dst :
    nodes !! i = Some node
    xtdlchain hdr src nodes dst
      xtdlchain hdr src (take i nodes) #node
      node ↦ₕ hdr
      node.[prev] from_option #@{location} src (last $ take i nodes)
      node.[next] from_option #@{location} dst (head $ drop ˖i nodes)
      xtdlchain hdr #node (drop ˖i nodes) dst.
  Lemma xtdlchainlookup₂ {hdr src nodes} i node prev next dst :
    nodes !! i = Some node
    prev = from_option #@{location} src (last $ take i nodes)
    next = from_option #@{location} dst (head $ drop ˖i nodes)
    xtdlchain hdr src (take i nodes) #node -∗
    node ↦ₕ hdr -∗
    node.[prev] prev -∗
    node.[next] next -∗
    xtdlchain hdr #node (drop ˖i nodes) dst -∗
    xtdlchain hdr src nodes dst.

  Lemma xtdlchainlookupacc {hdr src nodes} i node dst :
    nodes !! i = Some node
    xtdlchain hdr src nodes dst
      node ↦ₕ hdr
      node.[prev] from_option #@{location} src (last $ take i nodes)
      node.[next] from_option #@{location} dst (head $ drop ˖i nodes)
      ( node.[prev] from_option #@{location} src (last $ take i nodes) -∗
        node.[next] from_option #@{location} dst (head $ drop ˖i nodes) -∗
        xtdlchain hdr src nodes dst
      ).

  Lemma xtdlchainlookupheader {hdr src nodes} i node dst :
    nodes !! i = Some node
    xtdlchain hdr src nodes dst
    node ↦ₕ hdr.

  Lemma xtdlchainexclusive hdr src1 src2 nodes dst1 dst2 :
    0 < length nodes
    xtdlchain hdr src1 nodes dst1 -∗
    xtdlchain hdr src2 nodes dst2 -∗
    False.

  Lemma xtdlchainNoDup hdr src nodes dst :
    xtdlchain hdr src nodes dst
    NoDup nodes.

  Lemma xtdlchain٠prevspec {hdr src nodes node} nodes' dst E :
    nodes = node :: nodes'
    {{{
      xtdlchain hdr src nodes dst
    }}}
      (#node).{prev} @ E
    {{{
      RET src;
      xtdlchain hdr src nodes dst
    }}}.
  Lemma xtdlchain٠prevspeclookup {hdr src nodes} i node dst E :
    nodes !! i = Some node
    {{{
      xtdlchain hdr src nodes dst
    }}}
      (#node).{prev} @ E
    {{{
      RET from_option #@{location} src (last $ take i nodes);
      xtdlchain hdr src nodes dst
    }}}.
  Lemma xtdlchain٠prevspechead {hdr src nodes} node dst E :
    head nodes = Some node
    {{{
      xtdlchain hdr src nodes dst
    }}}
      (#node).{prev} @ E
    {{{
      RET src;
      xtdlchain hdr src nodes dst
    }}}.

  Lemma xtdlchain٠nextspec {hdr src nodes node} nodes' dst E :
    nodes = node :: nodes'
    {{{
      xtdlchain hdr src nodes dst
    }}}
      (#node).{next} @ E
    {{{
      RET from_option #@{location} dst (head nodes');
      xtdlchain hdr src nodes dst
    }}}.
  Lemma xtdlchain٠nextspeclookup {hdr src nodes} i node dst E :
    nodes !! i = Some node
    {{{
      xtdlchain hdr src nodes dst
    }}}
      (#node).{next} @ E
    {{{
      RET from_option #@{location} dst (head $ drop ˖i nodes);
      xtdlchain hdr src nodes dst
    }}}.
  Lemma xtdlchain٠nextspeclast {hdr src nodes} node dst E :
    last nodes = Some node
    {{{
      xtdlchain hdr src nodes dst
    }}}
      (#node).{next} @ E
    {{{
      RET dst;
      xtdlchain hdr src nodes dst
    }}}.

  Lemma xtdlchain٠set_prevspec {hdr src nodes node} nodes' dst v E :
    nodes = node :: nodes'
    {{{
      xtdlchain hdr src nodes dst
    }}}
      #node <-{prev} v @ E
    {{{
      RET ();
      xtdlchain hdr v nodes dst
    }}}.
  Lemma xtdlchain٠set_prevspeclookup {hdr src nodes} i node dst v E :
    nodes !! i = Some node
    {{{
      xtdlchain hdr src nodes dst
    }}}
      #node <-{prev} v @ E
    {{{
      RET ();
      xtdlchain hdr src (take i nodes) #node
      xtdlchain hdr v (drop i nodes) dst
    }}}.
  Lemma xtdlchain٠set_prevspechead {hdr src nodes} node dst v E :
    head nodes = Some node
    {{{
      xtdlchain hdr src nodes dst
    }}}
      #node <-{prev} v @ E
    {{{
      RET ();
      xtdlchain hdr v nodes dst
    }}}.

  Lemma xtdlchain٠set_nextspec {hdr src nodes node} nodes' dst v E :
    nodes = node :: nodes'
    {{{
      xtdlchain hdr src nodes dst
    }}}
      #node <-{next} v @ E
    {{{
      RET ();
      xtdlchain hdr src [node] v
      xtdlchain hdr #node nodes' dst
    }}}.
  Lemma xtdlchain٠set_nextspeclookup {hdr src nodes} i node dst v E :
    nodes !! i = Some node
    {{{
      xtdlchain hdr src nodes dst
    }}}
      #node <-{next} v @ E
    {{{
      RET ();
      xtdlchain hdr src (take ˖i nodes) v
      xtdlchain hdr #node (drop ˖i nodes) dst
    }}}.
  Lemma xtdlchain٠set_nextspeclast {hdr src nodes} node dst v E :
    last nodes = Some node
    {{{
      xtdlchain hdr src nodes dst
    }}}
      #node <-{next} v @ E
    {{{
      RET ();
      xtdlchain hdr src nodes v
    }}}.
End zoo۰G.

Require zoo_std.xtdlchain__opaque.

#[global] Opaque xtdlchain.