
/******************************************************************************
* MODULE     : list
* DESCRIPTION: linked lists with reference counting
* COPYRIGHT  : (C) 1999  Joris van der Hoeven
*******************************************************************************
* This software falls under the GNU general public license and comes WITHOUT
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
* If you don't have this file, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
******************************************************************************/

#include <tree.gen.h>

#module list (T)
#import tree

struct list_rep<T>;

class list<T> {
#import concrete_null (list<T>, list_rep<T>)
  inline list<T> (T item);
  inline list<T> (T item, list<T> next);
  inline list<T> (T item1, T item2, list<T> next);
  inline list<T> (T item1, T item2, T item3, list<T> next);
  T& operator [] (int i);
  operator tree ();

  friend inline bool atom (list<T> l);
};

extern int list_count;
class list_rep<T>: concrete_struct {
public:
  T       item;
  list<T> next;

  inline list_rep<T> (T item2, list<T> next2): item(item2), next(next2) {
    DEBUG(list_count++); }
  inline ~list_rep<T> () { DEBUG(list_count--); }
  friend class list<T>;
};

#import code_concrete_null (list<T>, list_rep<T>)
inline list<T>::list<T> (T item): rep (new list_rep<T>(item, list<T> ())) {}
inline list<T>::list<T> (T item, list<T> next):
  rep (new list_rep<T>(item, next)) {}
inline list<T>::list<T> (T item1, T item2, list<T> next):
  rep (new list_rep<T>(item1, list<T> (item2, next))) {}
inline list<T>::list<T> (T item1, T item2, T item3, list<T> next):
  rep (new list_rep<T>(item1, list<T> (item2, item3, next))) {}
inline bool atom (list<T> l) { return (!nil (l)) && nil (l->next); }

int      N (list<T> l);
list<T>  copy (list<T> l);
list<T>  operator * (list<T> l1, T x);
list<T>  operator * (list<T> l1, list<T> l2);
list<T>  head (list<T> l, int n=1);
list<T>  tail (list<T> l, int n=1);
T&       last_item (list<T> l);
list<T>& suppress_last (list<T>& l);
list<T>  revert (list<T> l);

ostream& operator << (ostream& out, list<T> l);
list<T>& operator << (list<T>& l, T item);
list<T>& operator << (list<T>& l1, list<T> l2);
list<T>& operator >> (T item, list<T>& l);
list<T>& operator << (T& item, list<T>& l);
bool     operator == (list<T> l1, list<T> l2);
bool     operator != (list<T> l1, list<T> l2);
bool     operator < (list<T> l1, list<T> l2);
bool     operator <= (list<T> l1, list<T> l2);

#endmodule // list (T)
