VSL - The data.SL_stack Structure
# Copyright 2011 Petter Urkedal
#
# This file is part of the Viz Standard Library <http://www.vizlang.org/>.
#
# The Viz Standard Library (VSL) is free software: you can redistribute it
# and/or modify it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
#
# The VSL is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
# more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with the VSL. If not, see <http://www.gnu.org/licenses/>.
# 0. Pure Stack
#
# This provides a pure stack datatype with logarithmic time access to
# arbitrary frames and logarithmic space and time overhead for push. It is
# implemented as a skip-list with deterministic back-links.
open prelude.ubiquitous
sealed with
type t α
val is_empty : t α → bool
val depth : t α → int
val empty : t α
val push : α → t α → t α
val pop : t α → option (α × t α)
val pop_e : t α → α × t α
val top : t α → option α
val top_e : t α → α
val drop : t α → t α
val drop_n : int → t α → t α
val get : int → t α → option α
val get_e : int → t α → α
val dump : (α → string) → t α → io unit
type t α
inj empty
inj node : α → int → array (t α) → t α
let is_empty at empty% be true
at node _ _ _ be false
let depth at empty% be 0
at node _ n _ be n
let getlink i
at empty% fail "getlink on empty stack"
at node _ _ links be array.get i links
let top
at empty% be none
at node x _ _ be some x
let top_e
at empty% fail "top_e called on empty stack."
at node x _ _ be x
let drop
at empty% be empty
at node _ _ links be array.get 0 links
let drop_n dn
at empty% be empty
at s@(node x n links)
if dn = 0 be s
if dn ≥ n be empty
let n_dst be n - dn
let ascend (bitno, n, s)
let bit be int.shift bitno 1
if int.bitand bit n = 0 be ascend (bitno + 1, n, s)
let n' be int.bitand n (int.bitnot bit)
if n' < n_dst be (bitno, n - n_dst, s)
be ascend (bitno + 1, n', getlink bitno s)
let descend (bitno, dn, s)
if dn = 0 be s
let bitno' be bitno - 1
let bit' be int.shift bitno' 1
if int.bitand bit' dn = 0 be descend (bitno', dn, s)
let dn' be int.bitand (int.bitnot bit') dn
be descend (bitno', dn', getlink bitno' s)
be descend (ascend (0, n, s))
let push x
at empty%
be node x 1 (array.init 1 (_ ↦ empty))
at s'@(node _ n' _)
let n be n' + 1
let n_links be int.floor_log2 (int.bitxor n n' + 1)
let links, _
be array.init_fold n_links
what at (bit, sC, nC)
let sC' be drop_n (bit + nC - n) sC
let nC' be n - bit
let bit' be int.shift 1 bit
be (sC', (bit', sC', nC'))
(1, s', n')
be node x n links
let pop
at empty% be none
at node x _ links be some (x, array.get 0 links)
let pop_e
at empty% fail "pop_e called on empty stack"
at node x _ links be (x, array.get 0 links)
let get dn be top ∘ drop_n dn
let get_e dn be top_e ∘ drop_n dn
open effect
let! dump show_elt
at empty% do print " empty\n"
at node x n links
do print " value = " >> print (show_elt x)
do print ";\tdepth = " >> print (int.show n)
do print "; links ="
do array.iter that links which!
at empty% do print " ∅"
at node _ n _ do print " " >> print (int.show n)
do print "\n"
do dump show_elt (array.get 0 links)