123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- // Copyright (c) 2001, 2003 Per M.A. Bothner and Brainfood Inc.
- // This is free software; for terms and warranty disclaimer see ./COPYING.
- package gnu.lists;
- import java.io.*;
- /** A "pair" object, as used in Lisp-like languages.
- * When used to implement a list, the 'car' field contains an
- * element's value, and the 'cdr' field points to either the next Pair
- * or LList.Empty (which represents the end of the list). (The names
- * "car" and "cdr" [pronounced "coulder"] are historical; better names
- * might be "value" and "next".) While a Pair is normally usued to
- * implement a linked list, sometimes the 'cdr' field points to some
- * other non-list object; this is traditionally callled a "dotted list".
- */
- public class Pair extends LList implements Externalizable
- {
- protected Object car;
- protected Object cdr;
- /** A special pair used to indicate incomplete input. */
- public static final Pair incompleteListMarker
- = new ImmutablePair("<incomplete>", LList.Empty);
- public Pair (Object carval, Object cdrval)
- {
- car = carval;
- cdr = cdrval;
- }
- public Pair ()
- {
- }
- public Object getCar () { return car; }
- public Object getCdr () { return cdr; }
- public void setCar(Object car) { this.car = car; }
- public void setCdr(Object cdr) { this.cdr = cdr; }
- /** May go away soon. */
- public void setCarBackdoor (Object car) { this.car = car; }
- public void setCdrBackdoor (Object cdr) { this.cdr = cdr; }
- public int size()
- {
- int n = listLength(this, true);
- if (n >= 0)
- return n;
- if (n == -1)
- return Integer.MAX_VALUE;
- throw new RuntimeException("not a true list");
- }
- public boolean isEmpty()
- {
- return false;
- }
- // A generalization of LList.list_length
- // FIXME is this needed, given listLength?
- public int length ()
- {
- // Based on list-length implementation in
- // Guy L Steele jr: "Common Lisp: The Language", 2nd edition, page 414
- int n = 0;
- Object slow = this;
- Object fast = this;
- for (;;)
- {
- if (fast == Empty)
- return n;
- if (! (fast instanceof Pair))
- {
- if (fast instanceof Sequence)
- {
- int j = ((Sequence) fast).size();
- return j >= 0 ? n + j : j;
- }
- return -2;
- }
- Pair fast_pair = (Pair) fast;
- Object fast_pair_cdr = fast_pair.getCdr();
- if (fast_pair_cdr == Empty)
- return n+1;
- if (fast == slow && n > 0)
- return -1;
- if (! (fast_pair_cdr instanceof Pair))
- {
- n++;
- fast = fast_pair_cdr;
- continue;
- }
- if (!(slow instanceof Pair))
- return -2;
- slow = ((Pair)slow).getCdr();
- fast = ((Pair)fast_pair_cdr).getCdr();
- n += 2;
- }
- }
- public boolean hasNext (int ipos)
- {
- if (ipos <= 0)
- return ipos == 0;
- return PositionManager.getPositionObject(ipos).hasNext();
- }
- public int nextPos (int ipos)
- {
- if (ipos <= 0)
- {
- if (ipos < 0)
- return 0;
- return PositionManager.manager
- .register(new LListPosition(this, 1, true));
- }
- LListPosition it = (LListPosition) PositionManager.getPositionObject(ipos);
- return it.gotoNext() ? ipos : 0;
- }
- public Object getPosNext (int ipos)
- {
- if (ipos <= 0)
- return ipos == 0 ? getCar() : eofValue;
- return PositionManager.getPositionObject(ipos).getNext();
- }
- public Object getPosPrevious (int ipos)
- {
- if (ipos <= 0)
- return ipos == 0 ? eofValue : lastPair().getCar();
- return PositionManager.getPositionObject(ipos).getPrevious();
- }
- public Pair lastPair()
- {
- Pair pair = this;
- for (;;)
- {
- Object next = pair.getCdr();
- if (next instanceof Pair)
- pair = (Pair) next;
- else
- return pair;
- }
- }
- /*
- public void print(java.io.PrintWriter ps)
- {
- ps.print("(");
- printNoParen(this, ps);
- ps.print(")");
- }
- */
- static public boolean equals (Pair pair1, Pair pair2)
- {
- if (pair1 == pair2)
- return true;
- if (pair1 == null || pair2 == null)
- return false;
- for (;;)
- {
- Object x1 = pair1.getCar();
- Object x2 = pair2.getCar();
- if (x1 != x2 && (x1 == null || ! x1.equals(x2)))
- return false;
- x1 = pair1.getCdr();
- x2 = pair2.getCdr();
- if (x1 == x2)
- return true;
- if (x1 == null || x2 == null)
- return false;
- if (! (x1 instanceof Pair) || !(x2 instanceof Pair))
- return x1.equals(x2);
- pair1 = (Pair) x1;
- pair2 = (Pair) x2;
-
- }
- }
- /* #ifdef JAVA2 */
- static public int compareTo (Pair pair1, Pair pair2)
- {
- if (pair1 == pair2)
- return 0;
- if (pair1 == null )
- return -1;
- if (pair2 == null)
- return 1;
- for (;;)
- {
- Object x1 = pair1.getCar();
- Object x2 = pair2.getCar();
- int d = ((Comparable) x1).compareTo((Comparable) x2);
- if (d != 0)
- return d;
- x1 = pair1.cdr;
- x2 = pair2.cdr;
- if (x1 == x2)
- return 0;
- if (x1 == null)
- return -1;
- if (x2 == null)
- return 1;
- if (! (x1 instanceof Pair) || !(x2 instanceof Pair))
- return ((Comparable) x1).compareTo((Comparable) x2);
- pair1 = (Pair) x1;
- pair2 = (Pair) x2;
- }
- }
- public int compareTo(Object obj)
- {
- if (obj == Empty)
- return 1;
- else
- return compareTo(this, (Pair) obj);
- }
- /* #endif */
- public Object get (int index)
- {
- Pair pair = this;
- int i = index;
- while (i > 0)
- {
- i--;
- Object pair_cdr = pair.getCdr();
- if (pair_cdr instanceof Pair)
- pair = (Pair)pair_cdr;
- else if (pair_cdr instanceof Sequence)
- return ((Sequence)pair_cdr).get(i);
- else
- break;
- }
- if (i == 0)
- return pair.getCar();
- else
- throw new IndexOutOfBoundsException ();
- }
- public boolean equals (Object obj)
- {
- if ((obj != null) && (obj instanceof Pair))
- return equals (this, (Pair) obj);
- else
- return false;
- }
- public static Pair make (Object car, Object cdr)
- {
- return new Pair (car, cdr);
- }
- public Object[] toArray()
- {
- int len = size(); // size()
- Object[] arr = new Object[len];
- int i = 0;
- Sequence rest = this;
- for ( ; i < len && rest instanceof Pair; i++)
- {
- Pair pair = (Pair) rest;
- arr[i] = pair.getCar();
- rest = (Sequence) pair.getCdr();
- }
- int prefix = i;
- for ( ; i < len; i++)
- {
- arr[i] = rest.get(i - prefix);
- }
- return arr;
- }
- public Object[] toArray(Object[] arr)
- {
- int alen = arr.length;
- int len = length();
- if (len > alen)
- {
- // FIXME Collection spec requires arr to keep same run-time type
- arr = new Object[len];
- alen = len;
- }
- int i = 0;
- Sequence rest = this;
- for ( ; i < len && rest instanceof Pair; i++)
- {
- Pair pair = (Pair) rest;
- arr[i] = pair.getCar();
- rest = (Sequence) pair.getCdr();
- }
- int prefix = i;
- for ( ; i < len; i++)
- {
- arr[i] = rest.get(i - prefix);
- }
- if (len < alen)
- arr[len] = null;
- return arr;
- }
- /**
- * @serialData Write the car followed by the cdr.
- */
- public void writeExternal(ObjectOutput out) throws IOException
- {
- out.writeObject(car);
- out.writeObject(cdr);
- }
- public void readExternal(ObjectInput in)
- throws IOException, ClassNotFoundException
- {
- car = in.readObject();
- cdr = in.readObject();
- }
- /** Needed to override readResolve in LList. */
- public Object readResolve() throws ObjectStreamException
- {
- return this;
- }
- };
|