#ifndef LIST_H
#define LIST_H

#include <generic.h>

/*----------------------------------------------------------------------- 
 * Demeter defines lists in the following way:
 * For each repetition class A the macro declare(list,A_) is called.
 * This macro is defined in generic.h as: declare(a,t) name2(a,declare)(t),
 * where name2 is another macro in generic.h that concatenates its two
 * arguments. So for each repetition class A the macro listdeclare(A_)
 * is called which is defined in this file.
 * listdeclare(A_) defines a class (struct) A_list_ which becomes the 
 * superclass of class A_List, i.e. A_List inherits from class A_list_.
 * We also define a class A_list_iterator that is used to iterate through
 * a list.
 *-----------------------------------------------------------------------*/


#define list(type) name2(type,list_)
/* Used in listdeclare(type) where type is 'A_' for class A. Thus this macro
   produces for class A the string A_list_ */


#define list_iterator(type) name2(type,list_iterator)
/* Used for the iterator class. type is 'A_" for class A. Thus, 
   list_iterator(type) produces for class A the string A_list_iterator */


#define listdeclare(type)						\
struct list(type) : public repetition {					\
  	list(type)() {}							\
  	list(type)( type a ) : repetition( ent( a ) ) {}		\
       ~list(type)() {} 						\
  int	insert( type a) { return repetition::insert( ent(a) ); }	\
  int	append( type a) { return repetition::append( ent(a) ); }	\
  type	get() { return type( repetition::get() ); }			\
  int	list_length() { return repetition::list_length(); }		\
  type	car() { return type( repetition::car() ); }			\
  type	lastexp() { return type (repetition::lastexp() ); }		\
  type	n_th( int a ) { return type (repetition::n_th(a) ); }		\
  int	conc(ent a, ent b) { return repetition::conc(a,b); }		\
  void  concatenate( list(type) *lst )					\
	{ repetition::concatenate( (repetition*)lst ); }		\
  int   member(ent a, PFC fn) { return repetition::member(a,fn); }      \
  list(type)* remove(ent a, PFC fn) { return (list(type)*) repetition::remove(a,fn); } \
  void dremove(ent a, PFC fn) { repetition::dremove(a,fn); } \
  list(type)* lisp_append(list(type)* a) {return (list(type)*) repetition::lisp_append((NonEmptyList*) a); } \
};									\
									\
struct list_iterator(type) : repetition_iterator {			\
  list_iterator(type)							\
    ( const list(type) &s ) : repetition_iterator( s ) {} \
  type operator()() 							\
     { return type( repetition_iterator::operator()() ); } 		\
};

#endif

