home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
sa104os2.zip
/
SATHR104.ZIP
/
SATHER
/
LIBRARY
/
FLIST.SA
< prev
next >
Wrap
Text File
|
1995-02-05
|
11KB
|
269 lines
-- Copyright (C) International Computer Science Institute, 1994. COPYRIGHT --
-- NOTICE: This code is provided "AS IS" WITHOUT ANY WARRANTY and is subject --
-- to the terms of the SATHER LIBRARY GENERAL PUBLIC LICENSE contained in --
-- the file "Doc/License" of the Sather distribution. The license is also --
-- available from ICSI, 1947 Center St., Suite 600, Berkeley CA 94704, USA. --
--------> Please email comments to "sather-bugs@icsi.berkeley.edu". <----------
-- flist.sa: Array-based lists of elements of type T.
-------------------------------------------------------------------
class FLIST{T} is
-- Array-based lists of elements of type T.
-- These are extensible stacks based on amortized doubling.
-- They may often be used as replacements for linked lists.
-- Like linked lists (which are widely used as containers in
-- languages like Lisp), they serve as general container
-- objects for holding collections of other objects. They are
-- often a more efficient abstraction, however, because less
-- allocation and deallocation must occur, because they keep
-- successive elements in successive memory locations, because
-- they don't require storage for the links in a linked list,
-- and they support efficient access by array index. Linked
-- lists also support insertion and deletion into the middle
-- of the list. A variant of FLIST{T} named GLIST{T} will often
-- be useful in applications which require these operations.
-- AQUEUE{T} is a similar structure supporting queue ops. The
-- set operations `union', `intersection', `difference', and
-- `sym_difference' and the searching operation `index_of' are
-- implemented by brute force search. If extensive use is made
-- of these operations, one should consider the use of other
-- data structures such as BITVEC or FSET{T}.
private include AREF{T} aget->private aref_aget,
aset->private aref_aset; -- Storage for the stack elements.
private attr loc:INT; -- The index to insert the next element.
elt_eq(e1,e2:T):BOOL is
-- The test for element equality used by the following routines.
-- Uses object equality by default. May be redefined in descendants.
typecase e1
when $IS_EQ{T} then return e1.is_eq(e2)
-- else return SYS::ob_eq(e1,e2) end end; -- NLP
else; end; return SYS::ob_eq(e1,e2); end; -- NLP
invariant:BOOL is
-- Illegal state if false.
if void(self) then return true end;
return loc.is_bet(0,asize) and asize>0 end;
size:INT is
-- The current size. Self may be void.
-- if void(self) then return 0 else return loc end end; -- NLP
if void(self) then return 0; end; return loc; end; -- NLP
create:SAME is return void; end;
create(n:INT):SAME
-- A new empty FLIST capable of storing `n' elements without extra
-- space allocation.
pre n>=1 is
return new(n) end;
copy:SAME is
-- A copy of self.
if void(self) then return void end;
r::=new(asize); loop r:=r.push(elt!) end; return r end;
aget(ind:INT):T
-- The element of self with index `ind'. Self may not be void.
pre ~void(self) and ind.is_bet(0,loc-1) is
return aref_aget(ind) end;
aset(ind:INT,val:T)
-- Set the element of self with index `ind' to `val'. Self may
-- not be void.
pre ~void(self) and ind.is_bet(0,loc-1) is
aref_aset(ind,val) end;
push(e:T):SAME is
-- Add a new element to the end of the list and return the list.
-- If self is void, create a new list. Usage: `l:=l.push(e)'.
r:SAME;
if void(self) then r:=new(5)
elsif loc<asize then r:=self
else r:=new(2*asize); r.loc:=loc;
loop r.aset!(elt!) end;
clear; end;
r.loc:=r.loc+1; r[r.loc-1]:=e; return r end;
pop:T is
-- Return the top element and shrink the list.
-- Void if the list is empty or void.
if size=0 then return void end;
r::=[loc-1]; [loc-1]:=void; loc:=loc-1; return r end;
top:T is
-- The value of the top of the list.
-- Void if the list is empty or void.
if size=0 then return void end;
return [loc-1] end;
is_eq(l:SAME):BOOL is
-- True if self and `l' have the same number of elements and each
-- element of self is equal to the corresponding element of `l'.
-- Self may be void.
if void(self) then return l.size=0
elsif void(l) then return loc=0
elsif loc/=l.loc then return false
else
loop if ~elt_eq(elt!,l.elt!) then return false end end end;
return true end;
is_empty:BOOL is
-- True if the list is empty or void.
return size=0 end;
clear is
-- Clear the list. Self may be void.
if is_empty then return else aclear; loc:=0 end end;
array:ARRAY{T} is
-- An array containing the elements of self. Void if self is void.
if void(self) then return void end;
r::=#ARRAY{T}(loc);
loop r.set!(elt!) end; return r end;
elt!:T is
-- Yield the elements of self in order. Self may be void.
-- Don't insert elements while calling this.
if ~void(self) then
loop yield aelt!(0,loc) end end end;
elt!(beg:INT):T
-- Yield the elements of self starting at `beg'.
-- Don't insert elements while calling this.
pre ~void(self) and beg.is_bet(0,loc-1) is
loop yield aelt!(beg,loc-beg) end end;
elt!(beg, num:INT):T
-- Yield `num' successive elements starting at index `beg'.
-- Don't insert elements while calling this.
pre ~void(self) and beg.is_bet(0,loc-1) and
num.is_bet(0,loc-beg) is
loop yield aelt!(beg,num) end end;
private is_legal_elts_arg(beg,num,step:INT):BOOL is
-- True if the arguments are legal values for `elts'.
if ~beg.is_bet(0,loc-1) then return false end;
if step>0 then return num.is_bet(0,(loc-beg+step-1)/step);
elsif step<0 then return num.is_bet(0,(beg-step)/-step);
-- else return false end end; -- NLP
end; return false; end; -- NLP
elt!(beg, num, step:INT):T
-- Yield `num' elements starting at `beg' stepping by `step'.
pre ~void(self) and is_legal_elts_arg(beg,num,step) is
loop yield aelt!(beg,num,step) end end;
ind!:INT is
-- Yield the indices of the list. Self may be void.
if ~void(self) then
loop yield 0.upto!(loc-1) end end end;
index_of(e:T):INT is
-- The list index of `e'. -1 if the list is void or the
-- element is not present (not fast). Consider using FSET{T}.
if ~void(self) then
loop r::=ind!; if elt_eq(e,[r]) then return r end end end;
return -1 end;
contains(e:T):BOOL is
-- True if `e' is contained in self.
loop if elt_eq(e,elt!) then return true end end;
return false end;
push_if_new(e:T):SAME is
-- Push `e' if it is not already present in the list.
-- Self may be void.
-- Usage is: `l:=l.push_if_new(e)'. Consider using FSET{T}.
-- if contains(e) then return self else return push(e) end end; -- NLP
if contains(e) then return self; end; return push(e); end; -- NLP
append(l:SAME):SAME
-- Append `l' to the end of self and return the result.
-- Self may be void. `l' mustn't equal self unless void.
pre ~SYS::ob_eq(l,self) or void(self) is
r::=copy; loop r:=r.push(l.elt!) end; return r end;
concat(l:SAME):SAME
-- Append 'l' destructively. 'l' mustn't equal self
-- unless void.
pre ~SYS::ob_eq(l,self) or void(self) is
res::=self;
if ~void(l) then loop res:=res.push(l.elt!) end end;
return (res);
end;
union(l:SAME):SAME is
-- A new list containing the elements in self unioned with
-- those in `l'. Doesn't modify self or `l'. Self may be void.
-- Consider using FSET{T} for better performance.
r::=copy; loop r:=r.push_if_new(l.elt!) end; return r end;
intersect(l:SAME):SAME is
-- A new list containing the elements in both self and `l'.
-- Doesn't modify self or `l'. Consider FSET{T} for better
-- performance. Self may be void.
r:SAME;
loop e::=elt!; if l.contains(e) then r:=r.push(e) end end;
return r end;
difference(l:SAME):SAME is
-- A new list containing the elements of self not in `l'.
-- Doesn't modify self or `l'. Consider FSET{T} for better
-- performance. Self may be void.
r:SAME;
loop e::=elt!; if ~l.contains(e) then r:=r.push(e) end end;
return r end;
sym_difference(l:SAME):SAME is
-- A new list containing the elements in self or `l' but
-- not both. Doesn't modify self or `l'. Consider FSET{T} for
-- better performance. Self may be void.
r:SAME;
loop e::=elt!; if ~l.contains(e) then r:=r.push(e) end end;
loop e::=l.elt!; if ~contains(e) then r:=r.push(e) end end;
return r end;
sublist(beg,num:INT):SAME
-- A new list with `num' entries copied from self starting
-- at `beg'. Self may not be void.
pre ~void(self) and
beg.is_bet(0,loc-1) and num.is_bet(0,loc-beg) is
r::=new(num+5); r.loc:=num; r.acopy(0,num,beg,self); return r end;
to_reverse is
-- Reverse the order of the elements in self. Self may be void.
if void(self) then return end;
loop i::=(loc/2).times!;
u::=loc-i-1; t::=[i]; [i]:=[u]; [u]:=t end end;
delete(ind:INT)
-- Delete the element with index `ind' and move the last element
-- in its place. Self may not be void.
pre ~void(self) and ind.is_bet(0,loc-1) is
loc:=loc-1; [ind]:=[loc]; v:T; [loc]:=v end;
map(map:FMAP{T,T}):SAME is
-- If an element of self is a key in FMAP
-- it is replaced with the corresponding
-- target. Self may be void.
if void(self) then
return void;
-- else -- NLP
end; -- NLP
res::=copy;
loop
i::=0.upto!(loc-1);
if map.test(res[i]) then
res[i]:=map.get(res[i]);
end;
end;
-- return res end end; -- NLP
return res; end; -- NLP
end; -- class FLIST{T}
-------------------------------------------------------------------