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

-- list.sa: Array based list
-- Author: Benedict A. Gomes <gomes@samosa.ICSI.Berkeley.EDU>

class LIST{ETP} < $LIST{ETP} is
   -- An extensible array implementation. This implementation is based
   -- on FLIST and may be viewed as a 'safe' version of FLIST without
   -- writebacks
   
   private attr arr: FLIST{ETP};

   create: SAME is
      res ::= new;
      res.arr := #FLIST{ETP}(5);
      return res;
   end;
   
   create_sized(n: INT): SAME post result.size = n is
      -- Create a list with "n" empty locations
      if n = 0 then return  #SAME;
      else
	 res ::= new;
	 res.arr := FLIST{ETP}::create_empty_sized(n);
	 return res;
      end;
   end; 

   create(a: ARRAY{ETP}): SAME is
      -- Create an array which contains the elements of "a"
      as_elt:$ELT{ETP} := a;
      return create(as_elt);
   end;

   create(a: $ELT{ETP}): SAME is
      -- Convert "a" into a list
      res: SAME := #;
      loop res.append(a.elt!) end;
      return res;
   end;
   
   is_empty:BOOL is return size = 0 end;
   
   resize(n: INT) pre ~void(self) is
      -- Allocate a new array and copy whatever will fit of the
      -- old portion.  Changes the actual size
      resarr::=FLIST{ETP}::create_empty_sized(n);
      i ::= 0; loop until!(i = n); resarr[i] := elt!;  i := i + 1; end;
      arr := resarr;
   end;

   copy:SAME is
      -- A copy of self.
      res: SAME := create_sized(size);
      loop i ::= size.times!;
	 res[i] := [i];
      end;
      return res;
   end;

   copy_from(src:$ELT{ETP}) is
      -- Copy as many elements from `src' to self as will fit.
      loop set!(src.elt!) end;
   end;
   
   remove_index(i: INT) is arr.delete_ordered(i) end;
   -- Remove the element associated with the index 'i'
   
   insert_after(l:INT,v:ETP) pre  ~void(self) is
      -- Insert v at location i, pushing elements upward
      arr := arr.insert_after(l,v);
   end;

   insert_before(l: INT, v: ETP) pre ~void(self) is
      arr := arr.insert_before(l,v);
   end;
   
   insert_all_after(l: INT, e: $CONTAINER{ETP}) pre ~void(self) is
      arr := arr.insert_all_after(l,e);
   end;
   
   insert_all_before(l: INT, e: $CONTAINER{ETP}) pre ~void(self) is
      arr := arr.insert_all_before(l,e);
   end;

   append(a:ETP) is
      -- Append element "a", even if a is void
      arr := arr.push(a); 
   end;
   
   append_all(a:$CONTAINER{ETP}) is
      -- Append a into self
      if void(a) then return 
      else loop  arr := arr.push(a.elt!); end;   end;
   end;

   clear pre ~void(self) is
      -- Set each array element to void. Set size to zero
      arr.clear
   end;

   aget(i: INT): ETP pre has_ind(i) is return arr[i] end;
   
   aset(i: INT,v: ETP) pre has_ind(i) is arr[i] := v end;

   size: INT is return arr.size end;
   

   has(e: ETP): BOOL is  return arr.has(e) end;
      -- True if array contains "e"

   has_ind(i: INT): BOOL is return ~void(self) and 0<=i and i < size end;
   
   has_range(beg,num: INT): BOOL is
      if ~void(self) then
	 return 0<=beg and beg<size  and num>= 0 and beg+num<=size;
      else return false end;
   end;

   equals(a: $RO_ARR{ETP}):BOOL is return arr.equals(a) end;
   
   ind!:INT is
      -- Yield the indices of self in order. Self may be void.
      i::=0; sz::=size; loop until!(i>=sz); yield i; i := i+1; end;
   end;

   elt!: ETP is
      -- Yield each element of self in order. Self may be void.
      if ~void(self) then
	 sz: INT := size; i::=0;
	 loop until!(i = sz);  yield arr[i];  i := i + 1; end;
      end 
   end;
   
   set!(val:ETP) is
      -- Set successive elements of self to the values of `val'.       
      sz: INT := size; i::=0;
      loop until!(i = sz); arr[i] := val;  yield; i := i + 1; end;
   end;      

   str: STR is return ELT_ALG{ETP}::str(self) end;
      -- Prints out a string version of the array of the components 
      -- that are under $STR, and their associated indices

   insert_after(l:INT,v:ETP):SAME pre  ~void(self) is
      -- Insert v at location i, pushing elements upward
      res ::= copy; res.insert_after(l,v); return res;
   end;

   insert_before(l:INT,v:ETP):SAME pre  ~void(self) is
      -- The indices of all subsequent elements, from initial[ind] onward
      -- will be shifted upward by 1
      res ::= copy; res.insert_before(l,v); return res;
   end;
   
   insert_all_after(l: INT, e: $CONTAINER{ETP}):SAME pre ~void(self) is
      -- Insert the elements of the list in order after the element
      -- initial[ind]. The indices of all subsequent elements from
      -- initial[ind+1]will be shifted upward
      res ::= copy; res.insert_all_after(l,e); return res;
   end;
   
   insert_all_before(l: INT, e: $CONTAINER{ETP}):SAME pre ~void(self) is
      --   Insert the elements of "val" in order, before "ind". The indices
      -- of all indices from initial[ind] upward to the end will be
      -- shifted upward
      res ::= copy; res.insert_all_before(l,e); return res;
   end;

   append(a:ETP):SAME is
      -- Append element "a", even if a is void
      res ::= copy; res.append(a); return res;
   end;
   
   append_all(a:$CONTAINER{ETP}):SAME is
      -- Append a into self
      res ::= copy; res.append_all(a); return res;
   end;

end;
-------------------------------------------------------------------

	 
   
