bag_incl.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
-------------------------> GNU Sather - sourcefile <-------------------------
-- Copyright (C) 1995 by International Computer Science Institute --
-- 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> <--------------
-- Author: Benedict A. Gomes <gomes@samosa.ICSI.Berkeley.EDU>
partial class RO_BAG_INCL{ETP}
partial class RO_BAG_INCL{ETP} is
-- Partial class that for the read only bag abstraction, class
-- $RO_BAG{ETP}. For more information on the relationship between
-- the abstract classes, partial classes and actual implementations
-- please see the class comment class in the abstraction.
-- RTP is the return type of various operations in this bag
-- abstraction
--
-- This partial class implements some of the operations required by
-- the abstraction in terms of a set of core functions which are
-- stubs in this partial class. These stubs must be replaced by
-- real function in any descendant that actually implements the
-- abstraction. Particular implementations may replace also some of
-- the non-stub operations by substantially more efficient
-- versions, that make use of properties of the actual
-- implementation.
--
include COMPARE{ETP};
--
-- Stubs
--
stub count(arg:ETP):INT;
-- Return the number of occurences of 'arg' in the container
stub add(e:ETP):SAME;
stub delete(e:ETP):SAME;
stub delete_all(e:ETP):SAME;
stub copy:SAME;
stub elt!: ETP;
stub size:INT;
stub has(e:ETP):BOOL;
--
-- Methods not required by the $RO_BAG abstraction. They can be safely
-- redefined away, if not needed
stub create:SAME;
create(arg:$ELT{ETP}):SAME is
-- Create a new bag out of the elements of 'arg'
res: SAME := #;
loop res := res.add(arg.elt!) end;
return res;
end;
create(arg:ARRAY{ETP}):SAME is
-- Create a new bag from the elements of the array 'arg'
-- The reason for having a separate routine in this case is to
-- permit type inference to be used so that a user may write
-- a:BAG{INT} := #(|1,2,3|);
res: SAME := #;
loop res := res.add(arg.elt!) end;
return res;
end;
--
-- Methods required by the $RO_BAG abstraction
--
n_unique:INT is
-- Return the number of unique elements
res:INT := 0;
loop discard ::= unique!; res := res+1; end;
return res;
end;
is_subset_of(arg:$RO_BAG{ETP}):BOOL is
-- Returns true if 'self' is a subset of 'arg'. For elements that occur
-- multiple times, the number of occurences of the element in 'arg'
-- must be greater than or equal to the number of occurences in self
--
-- result=true iff for all e in self: count(e) <= arg.count(e)
loop e ::= elt!;
if count(e) > arg.count(e) then return false; end;
end;
return true;
end;
concat(arg:$ELT{ETP}):SAME is
-- Returns a bag containing all the elements of self and 'arg'.
-- For elements that occur multiple times, the result contains
-- the sum of the number of occurences in self and 'arg'
--
-- result=bag of all e s.t. result.count(e)=self.count(e)+arg.count(e)>0
res ::= copy;
loop res := res.add(arg.elt!); end;
return res;
end;
union(arg: $RO_BAG{ETP}):SAME is
-- Returns a bag containing the elements of 'self' and 'arg'.
-- For elements that occur multiple times, the result contains
-- the maximum number of occurences in either self or 'arg'
-- This definition permits the union of sets to be consistent
-- with the union of bags.
--
-- result=bag of all e s.t.
-- result.count(e)= max(self.count(e),arg.count(e)) > 0
res ::= copy;
loop arg_elt:ETP := arg.elt!;
if ~res.has(arg_elt) then res := res.add(arg_elt);
else
if arg.count(arg_elt) > res.count(arg_elt) then
res := res.add(arg_elt);
end;
end;
end;
return res
end;
intersection(arg: $RO_BAG{ETP}):SAME is
-- Returns a bag containing the elements common to self and 'arg'
-- For elements that occur multiple times, the result contains
-- the minimum number of occurrences in either self or 'arg'
--
-- result=bag of all e s.t.
-- result.count(e)=min(self.count(e),arg.count(e)) > 0
res ::= copy;
loop
e ::= unique!;
num_to_delete: INT := (count(e) - arg.count(e));
if num_to_delete > 0 then
loop num_to_delete.times!; res := res.delete(e); end;
end;
end;
return res
end;
-- For the $CONTAINER abstraction
is_empty:BOOL is
-- Return true if the size = 0.
return size = 0;
end;
equals(c:$RO_BAG{ETP}):BOOL is
-- Return true if self.value = c.value
if size /= c.size then return false end;
loop e:ETP := c.unique!;
if count(e) /= c.count(e) then return false end;
end;
return true;
end;
as_array:ARRAY{ETP} is
-- Return the elements of the container as an array
res ::= #ARRAY{ETP}(size);
loop res.set!(elt!) end;
return res;
end;
str: STR is return ELT_ALG{ETP}::str(self); end;
-- Return a string representation of self
end;
partial class BAG_INCL{ETP}
partial class BAG_INCL{ETP} is
-- Partial class that for the bag abstraction, class $BAG{ETP}.
-- For more information on the relationship between the abstract
-- classes, partial classes and actual implementations please see
-- the class comment class in the abstraction.
--
-- This partial class implements some of the operations required by
-- the abstraction in terms of a set of core functions which are
-- stubs in this partial class. These stubs must be replaced by
-- real function in any descendant that actually implements the
-- abstraction. Particular implementations may replace also some of
-- the non-stub operations by substantially more efficient
-- versions, that make use of properties of the actual
-- implementation.
include RO_BAG_INCL{ETP};
stub count(e:ETP):INT;
stub add(e:ETP);
stub delete(e:ETP);
stub delete_all(e:ETP);
stub copy:SAME;
stub elt!: ETP;
stub size:INT;
stub has(e:ETP):BOOL;
--
-- Methods not required by the $BAG abstraction
--
create(arg:$ELT{ETP}):SAME is
-- Create a new bag out of the elements of 'arg'
res: SAME := #;
loop res := res.add(arg.elt!) end;
return res;
end;
--
-- Methods required by the $BAG abstraction
--
as_value:VBAG{ETP} is return #VBAG{ETP}(self) end;
-- Return the value associated with this reference to a set
clear post size = 0 is
-- Delete all elements of self
f:ARRAY{ETP} := #(n_unique);
loop f.set!(unique!); end;
loop delete_all(f.elt!); end;
end;
-- Implementation note: with the following routines, care must be
-- taken to ensure that the collection being iterated over is not
-- being modified at the same time. Thus it is best to always
-- iterate over 'arg', since self is being modified
to_concat(arg:$ELT{ETP}) is
-- Concatenate the elemetns of 'arg' to this bag
-- self <- initial(self).add_bag(arg)
loop add(arg.elt!); end;
end;
to_union(arg: $RO_BAG{ETP}) is
-- Turn this bag into the union of self and 'arg'
-- self <- initial(self).union(arg)
loop arg_elt:ETP := arg.elt!;
if ~has(arg_elt) then add(arg_elt);
else
if arg.count(arg_elt) > count(arg_elt) then add(arg_elt); end;
end;
end;
end;
to_intersection(arg:$RO_BAG{ETP}) is
-- Turn this bag into the intersection of self and 'arg'
-- self <- initial(self).intersection(arg)
-- Copy the unique elts so that we don't iterate while
-- deleting
f ::= #ARRAY{ETP}(n_unique); loop f.set!(unique!) end;
loop e ::= f.elt!;
if ~arg.has(e) then delete_all(e); end;
end;
-- For elements in the intersection, reduce the number
-- of repetitions to the min number of occurences
loop e ::= arg.unique!;
num_to_delete:INT := count(e) - arg.count(e);
if num_to_delete > 0 then
loop num_to_delete.times!; delete(e); end;
end;
end;
end;
add(e:ETP):SAME is
-- Result is a new bag containing all the elements of self and 'e'
res:SAME := copy; res.add(e); return res;
end;
delete(e:ETP):SAME is
-- Result is a new bag containing all the elements of self except for
-- an element equal to 'e', if one exists. If more than one element
-- is equal to 'e', delete only one of them
res:SAME := copy; res.delete(e); return res;
end;
delete_all(e:ETP):SAME is
-- Result is a new bag containing all the elements of self except for
-- any elements equal to 'e'
res:SAME := copy; res.delete_all(e); return res;
end;
end;