///////////////////////////////////////////////////////////////////////////////
//                             Lisaac Compiler                               //
//                                                                           //
//                   LSIIT - ULP - CNRS - INRIA - FRANCE                     //
//                                                                           //
//   This program is free software: you can redistribute it and/or modify    //
//   it under the terms of the GNU General Public License as published by    //
//   the Free Software Foundation, either version 3 of the License, or       //
//   (at your option) any later version.                                     //
//                                                                           //
//   This program 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 the           //
//   GNU General Public License for more details.                            //
//                                                                           //
//   You should have received a copy of the GNU General Public License       //
//   along with this program.  If not, see <http://www.gnu.org/licenses/>.   //
//                                                                           //
//                     http://isaacproject.u-strasbg.fr/                     //
///////////////////////////////////////////////////////////////////////////////
Section Header
  
  + name        := TYPES;

  - copyright   := "2003-2007 Benoit Sonntag";

  
  - author      := "Sonntag Benoit (bsonntag@loria.fr)";
  - comment     := "Aliser TYPE collection.";
  
Section Inherit  
  
  - parent_object:OBJECT := OBJECT;
  
Section TYPES
  
  + storage:NATIVE_ARRAY[TYPE];
  // Internal access to storage location.
  
Section LISAAC
  
  - size:INTEGER;
  
Section Public
  
  - lower:INTEGER := 0;
  
  + upper:INTEGER := -1; // Upper index bound.
  
  - count:INTEGER <- upper + 1;
  
  - is_empty:BOOLEAN <- upper = -1;
  
  - first:TYPE <- 
  [ -? {! is_empty}; ]
  (
    storage.item 0
  );

  - second:TYPE <- 
  [ -? {upper >= 1}; ]
  (
    storage.item 1
  );
  
  - last:TYPE <- 
  [ -? {! is_empty}; ]
  (
    storage.item upper
  );
  
  - item i:INTEGER :TYPE <-
  [ -? {i.in_range lower to upper}; ]
  (
    storage.item i
  )
  [ +? {Result != NULL};            ];

  - '==' Right 60 other:TYPES :BOOLEAN <-
  ( 
    (Self = other) || 
    {
      (upper = other.upper) && 
      {(is_empty) || {storage.fast_memcmp (other.storage) until (upper + 1)}}
    }
  );

  - '<=' Right 60 other:TYPES :BOOLEAN <-
  // True, if `Self' is include in `other'.
  ( + result:BOOLEAN;
    + j1,j2:INTEGER;
    + t:TYPE;
    
    (upper <= other.upper).if {
      j1 := j2 := lower;
      result := TRUE;
      {(j1 <= upper) && {result}}.while_do {
	t := item j1;
	{(j2 <= other.upper) && {other.item j2 != t}}.while_do {
	  j2 := j2 + 1;
	};
	result := (j2 <= other.upper);
	j1 := j1 + 1;
      };      
    };
    result    
  );
  
  - hash_code:INTEGER <-
  ( + result:INTEGER;
    
    (! is_empty).if {
      result := (upper << 8) + last.index;
    };
    result
  );
  
  //
  // Display.
  //
  
  - print <-
  (
    (! is_empty).if {
      (lower).to (upper - 1) do { j:INTEGER;
	item j.print; 
	'('.print;
	item j.index.print;     
	") x ".print;
      };
      last.print;
      '('.print;
      last.index.print;     
      ')'.print;
    } else {
      "<Vide>".print;
    };
  );
  
Section TYPES_TMP
  
  - create tab:TYPES_TMP :TYPES <-
  ( + result:TYPES;
          
    result := clone;
    result.make tab;
    result
  );
  
  - make tab:TYPES_TMP <-
  ( + up:INTEGER;
    
    up := tab.upper;
    storage := NATIVE_ARRAY[TYPE].calloc_intern (up + 1);
    storage.copy_from (tab.storage) until up;
    upper := up;    
    size := size + count * 4;    
  );