multimap_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>  <--------------

-- multimap_incl.sa: Multimap include partial class
-- Author: Benedict A. Gomes <gomes@samosa.ICSI.Berkeley.EDU>


partial class RO_MULTIMAP_INCL{ITP,TTP}

partial class RO_MULTIMAP_INCL{ITP,TTP} is -- Partial class that for the read only multimap abstraction, class -- $RO_MULTIMAP{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 COMPARE{TUP{ITP,TTP}}; -- Please see the abstraction $RO_MULTIMAP for comments about these -- stubs stub ind!:ITP; stub n_targets(i:ITP):INT; stub target!(once i:ITP):TTP; stub add(e:TUP{ITP,TTP}):SAME; stub delete(e:TUP{ITP,TTP}):SAME; stub delete_all(e:TUP{ITP,TTP}):SAME; stub unique!:TUP{ITP,TTP}; stub size:INT; stub copy:SAME; stub has(e:TUP{ITP,TTP}):BOOL; stub elt!:TUP{ITP,TTP}; -- Methods not required by the $RO_MULTIMAP abstraction. They can be safely -- redefined away, if not needed stub create:SAME; create(arg:$ELT{TUP{ITP,TTP}}):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 $RO_MULTIMAP abstraction -- add(k:ITP,e:TTP):SAME is return add(#TUP{ITP,TTP}(k,e)); end; -- Shortcut for for add(#TUP{ITP,TTP}(k,e)) delete(k:ITP,e:TTP):SAME is -- Shortcut for for delete(e:TUP{ITP,TTP}) return delete(#TUP{ITP,TTP}(k,e)) end; delete_ind(k:ITP):SAME is -- Returns a new multimap in which all occurences of the tuple -- (k,_) have been deleted -- Introduced in $RO_MULTIMAP res ::= copy; loop res.delete(k,target!(k)); end; return res; end; has_ind(k:ITP):BOOL is -- Returns true if this map has an index equal to 'e' -- -- result is true iff self contains a tuple (_,e) return n_targets(k) > 0 end; n_ind:INT is -- Return the number of unique indices in this multimap res::=0; loop discard ::= ind!; res := res+1; end; return res; end; pair!:TUP{ITP,TTP} is -- Yields all elements of self in an unspecified order. An alias for -- "elt!" loop yield elt!; end; end; count(arg:TUP{ITP,TTP}):INT is -- Return the number of occurences of 'arg' in the container res:INT := 0; loop e ::= elt!; if elt_eq(arg,e) then res := res + 1; end; end; return res; end; n_unique:INT is -- Return the number of unique pairs in 'self' res:INT := 0; loop discard ::= unique!; res := res+1; end; return res; end; is_subset_of(arg:$RO_BAG{TUP{ITP,TTP}}):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 ::= unique!; if count(e) > arg.count(e) then return false; end; end; return true; end; concat(arg:$ELT{TUP{ITP,TTP}}):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=multimap 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{TUP{ITP,TTP}}):SAME is -- Returns a multimap 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:TUP{ITP,TTP} := 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{TUP{ITP,TTP}}):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:SAME := copy; loop e ::= unique!; num_to_delete: INT := (count(e) - arg.count(e)).max(0); loop num_to_delete.times!; res := res.delete(e); end; end; return res end; diff(arg:$RO_BAG{TUP{ITP,TTP}}):SAME is -- Returns a bag containing all the elements of self that are -- not in 'arg' For elements that occur multiple times in self, -- the number of occurences in the result is reduced by the -- number of occurences in 'arg' -- -- result=bag of all e s.t. result.count(e)=self.count(e)-arg.count(e)>0 res:SAME := copy; loop e ::= unique!; num_to_delete: INT := arg.count(e); loop num_to_delete.times!; res := res.delete(e); end; end; return res end; sym_diff(arg:$RO_BAG{TUP{ITP,TTP}}):SAME is -- Returns a bag containing all the elements of self that are not -- in 'arg' and in 'arg' but not in self. For elements that occur -- in both, the result contains the absolute value fo the difference -- in the number of occurences. -- -- result=bag of all e s.t. -- result.count(e)=|self.count(e)-arg.count(e)|>0 union:SAME := union(arg); intersect:SAME := intersection(arg); return union.diff(intersect); end; is_empty:BOOL is -- Return true if the size = 0. return size = 0; end; equals(c:$RO_BAG{TUP{ITP,TTP}}):BOOL is -- Return true if self contains all the elements of 'c' and vice -- versa. if size /= c.size then return false end; loop if ~has(c.elt!) then return false end; end; return true; end; as_array:ARRAY{TUP{ITP,TTP}} is -- Return the elements of the container as an array res ::= #ARRAY{TUP{ITP,TTP}}(size); loop res.set!(elt!) end; return res; end; str: STR is return ELT_ALG{TUP{ITP,TTP}}::str(self); end; -- Return a string representation of self end;

partial class MULTIMAP_INCL{ITP,TTP}

partial class MULTIMAP_INCL{ITP,TTP} is -- Partial class that for the multimap abstraction class $MULTIMAP{ITP,TTP}. -- 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_MULTIMAP_INCL{ITP,TTP}; -- -- Please see the abstraction $MULTIMAP for comments -- stub aset(k:ITP,e:TTP); stub delete(k:ITP,e:TTP); stub delete(k:ITP); stub delete_all(k:ITP,e:TTP); stub ind!:ITP; stub target!(i:ITP):TTP; stub unique!:TUP{ITP,TTP}; stub size:INT; stub copy:SAME; stub has(e:TUP{ITP,TTP}):BOOL; stub elt!:TUP{ITP,TTP}; -- **** To satisfy the $MULTIMAP abstraction as_value:VMULTIMAP{ITP,TTP} is -- Return the value associated with this reference type return #VMULTIMAP{ITP,TTP}(self); end; clear post size = 0 is -- Delete all elements of self f:ARRAY{TUP{ITP,TTP}} := #(n_unique); loop f.set!(unique!); end; loop delete_all(f.elt!); end; #ERR+str; end; delete(e:TUP{ITP,TTP}) is -- Delete at most one instance of the tuple (e.t1,e.t2) from 'self' delete(e.t1,e.t2) end; delete_all(e:TUP{ITP,TTP}) is -- Delete all instances of the tuple (e.t1,e.t2) from 'self' delete_all(e.t1,e.t2) end; to_union(arg: $RO_BAG{TUP{ITP,TTP}}) is -- Turn this bag into the union of self and 'arg' -- self <- initial(self).union(arg) loop arg_elt:TUP{ITP,TTP} := arg.elt!; if ~has(arg_elt) then [arg_elt.t1] := arg_elt.t2; else if arg.count(arg_elt) > count(arg_elt) then [arg_elt.t1] := arg_elt.t2; end; end; end; end; to_intersection(arg:$RO_BAG{TUP{ITP,TTP}}) 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{TUP{ITP,TTP}}(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:TUP{ITP,TTP}) is -- Add the tuple (e.t1,e.t2) to self [e.t1] := e.t2 end; add(e:TUP{ITP,TTP}):SAME is -- Result is a new multimap containing all the elements of self and 'e' res ::= copy; res[e.t1] := e.t2; return res; end; delete(e:TUP{ITP,TTP}):SAME is -- Result is a new multimap 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 ::= copy; res.delete(e); return res; end; delete_all(e:TUP{ITP,TTP}):SAME is -- Result is a new multimap ontaining all the elements of self except for -- any elements equal to 'e' res ::= copy; res.delete_all(e.t1,e.t2); return res; end; end;