// @(#)$Id: intlist.C,v 1.5 1999/04/11 15:57:38 leavens Exp $

#include "intlist.h"

listelem::listelem(int val, listelem * next) throw()
  : car(val), cdr(next)
{
}

inline int listelem::get_value() const throw()
{
  return car;
}

inline listelem * listelem::get_next() const throw()
{
  return cdr;
}

inline void listelem::set_value(int i) throw()
{
  car = i;
}

inline void listelem::set_next(listelem *l) throw()
{
  cdr = l;
}

list  empty() throw()
{
  return 0;
}

bool  isempty( list l )	throw()
{
  return l == 0;
}
  
bool  equal( list l1, list l2 )	throw()
{
  if (isempty(l1)) {
    return (isempty(l2));
  } else if (isempty(l2)) {
    return false;
  } else {
    return (l1->get_value() == l2->get_value())
           && equal(l1->get_next(), l2->get_next());
  }
}

int   top( list l ) throw()
{
  return l->get_value();
}

list  rest( list l ) throw()
{
  return l->get_next();
}

list  append( int i, list l ) throw()
{ 
  return new listelem(i,l); 
}

list  copy( list l ) throw()
{
  if (isempty(l)) {
    return empty();
  } else {
    return append(top(l), copy(rest(l)));
  }
}

list  conc( list l1, list l2 ) throw()
{ 
  if (isempty(l1)) {
    return l2;
  }
  list l1_ptr = l1;
  while (!isempty(rest(l1_ptr))) {
    //@ assert widen(l1_ptr) \in list_objs(l1, pre)
    l1_ptr = rest(l1_ptr);
  }
  //@ assert widen(l1_ptr) \in list_objs(l1, pre)
  //@        /\ isempty(rest(l1_ptr))
  l1_ptr->set_next(l2);
  return l1;
}

