llist.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
-------------------------> GNU Sather - sourcefile <-------------------------
-- Copyright (C) 2000 by K Hopper, University of Waikato, New Zealand --
-- This file is part of the GNU Sather library. It is free software; you may --
-- redistribute and/or modify it under the terms of the GNU Library General --
-- Public License (LGPL) as published by the Free Software Foundation; --
-- either version 2 of the license, or (at your option) any later version. --
-- This library 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 Doc/LGPL for more details. --
-- The license text is also available from: Free Software Foundation, Inc., --
-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
--------------> Please email comments to <bug-sather@gnu.org> <--------------
class LL_NODE{T}
class LL_NODE{T} is
-- This class is for the private use of the class LLIST (linked list).
-- This implementation has a node which is the data value and another which
-- is the next item in the list. This is very close to an explicit pointer
-- in non-object oriented languages!
-- Version 1.1 Apr 97. Copyright K Hopper, U of Waikato
-- Development History
-- -------------------
-- Date Who By Detail
-- ---- ------ ------
-- 18 Jul 96 ds Original
-- 4 Apr 97 kh Changed for CARD instead of INT
attr data : T ;
attr next : SAME ;
create(
val : T,
next : SAME
) : SAME is
-- This simple creation routine merely sets the values in a new node
-- which it returns.
me : SAME := new ;
me.data := val ;
me.next := next ;
return me
end ;
is_eq(
other : SAME
) : BOOL is
-- This predicate returns true if and only if self and other are 'object
-- equal.
return SYS::ob_eq(self,other)
end ;
end ; -- LL_NODE{T}
class LLIST{T}
class LLIST{T} is
-- This class is a linked list implementation of a list. It contains
-- the notion of current position which can be advanced and also 'rewound'.
-- Elements can be inserted either before or after a particular position as
-- well as deletion of the 'current' object.
--
-- The list has a header which prevents confusion with an empty list.
-- Data are stored in linked nodes which are 'private' to this class.
-- Version 1.2 Nov 98. Copyright K Hopper, U of Waikato
-- Development History
-- -------------------
-- Date Who By Detail
-- ---- ------ ------
-- 5 Sep 96 bv Original
-- 3 Apr 97 kh Changed for CARD instead of INT
-- 6 Nov 98 kh Refinded from 1.2, added pre/post conditions.
-- 16 Dec 99 kh included CONTAINER partial class.
include CONTAINER{T} ;
readonly attr size : CARD ;
-- This returns the number of elements stored in the list.
private attr first,
prev,
curr,
last : LL_NODE{T} ;
create : SAME is
-- This routine returns a new empty linked list. Its successful
-- operation relies on the fact that all 'new' objects in Sather have
-- a zero/null value!
return new
end ;
is_empty : BOOL
pre ~void(self)
post (result = (size = 0))
is
-- This predicate returns true if and only if the list is empty.
return size = 0
end ;
at_last : BOOL
pre ~void(self)
and ~is_empty
post (result = (last = curr))
is
-- This predicate returns true if and only if the current element is
-- the last element.
return last = curr
end ;
at_end : BOOL
pre ~void(self)
post result = void(curr)
is
-- This predicate returns true if and only if the list is empty or
-- the current node is void (which signifies 'beyond' the last node'.
return void(curr)
end ;
rewind
pre ~void(self)
post (curr = first)
and void(prev)
is
-- This routine sets the current position to be the first element in
-- the list.
curr := first ;
prev := void
end ;
current : T
pre ~void(self)
and ~is_empty
and ~at_end
post (result = curr.data)
is
-- This routine returns the value of the current list element.
return curr.data
end ;
advance
pre ~void(self)
and ~is_empty
and ~at_end
post (prev = initial(curr))
and (curr = prev.next)
is
-- This routine advances the current position in the list by one.
prev := curr ;
curr := curr.next
end ;
insert_after(
val : T
)
pre ~void(self)
and ~is_empty
and ~at_end
post (size = (initial(size) + 1))
and (curr.next.data = val)
is
-- This routine inserts the given item after the current element. It
-- does not change current.
if void(curr.next) then
assert curr = last ;
last := LL_NODE{T}::create(val,void) ;
curr.next := last
else
curr.next := LL_NODE{T}::create(val,curr.next)
end ;
size := size + 1
end ;
insert_before(
val : T
)
pre ~void(self)
post (size = (initial(size) + 1))
and (prev.data = val)
is
-- This routine inserts the new element before the current position.
-- This does not change the value of current.
if is_empty then
first := LL_NODE{T}::create(val,void) ;
last := first ;
prev := first ;
elsif void(prev) then
assert first = curr ;
first := LL_NODE{T}::create(val,curr) ;
prev := first
else
prev.next := LL_NODE{T}::create(val,curr) ;
prev := prev.next
end ;
if void(curr) then
last := prev
end ;
size := size + 1
end ;
insert_front(
val : T
)
pre ~void(self)
post (size = (initial(size) + 1))
and (first.data = val)
is
-- This routine inserts an element at the front of the list.
if void(first) then
assert void(last)
and void(curr) ;
first := LL_NODE{T}::create(val,void) ;
last := first ;
curr := first
else
first := LL_NODE{T}::create(val,first) ;
if void(prev) then
assert curr = first ;
prev := first
end
end ;
size := size + 1
end ;
insert_back(
val : T
)
pre ~void(self)
post (size = (initial(size) + 1))
and (last.data = val)
is
-- This routine inserts the new element val at the end of the list.
if void(last) then
assert void(first) ;
last := LL_NODE{T}::create(val,void) ;
first := last ;
curr := last
else
last.next := LL_NODE{T}::create(val,void) ;
last := last.next
end ;
size := size + 1
end ;
delete
pre ~void(self)
and ~is_empty
and ~at_end
post (void(prev)
and (curr = first))
or (prev.next = curr)
is
-- This routine deletes the current object and advvances to the next
-- item in the list.
at_last : BOOL := curr = last ;
if void(prev) then
assert first = curr ;
first := curr.next ;
curr := first
else
curr := curr.next ;
prev.next := curr
end ;
if at_last then
last := prev
end ;
size := size - 1
end ;
delete_all
pre ~void(self)
post is_empty
and at_end
is
-- This routine deletes all elements from the list.
first := void ;
curr := void ;
last := void ;
prev := void ;
size := 0
end ;
elt! : T
pre ~void(self)
post true
is
-- This iter yields all elements in the list in order. It is
-- re-entrant.
loc : LL_NODE{T} := first ;
loop
until!(void(loc)) ;
yield loc.data ;
loc := loc.next
end
end ;
end ; -- LLIST{T}