// Copyright (c) 1996-2002 Brian D. Carlstrom

package bdc.scheme;

import bdc.util.FastStringBuffer;

/**
    Pair represents a Scheme cons cell.
*/
public class Pair
{

    /**
        historically car means contents of address register.
        in a linked list, it is a pointer to the data value.
    */
    public Object car;

    /**
        historically car means contents of decrement register
        in a linked list, it is a pointer to the next pair
    */
    public Object cdr;

    /**
        Create a cons cell.
    */
    public Pair (Object car,
                 Object cdr)
    {
        this.car = car;
        this.cdr = cdr;
    }

    /**
        Scheme prints cons cells in a way that takes into
        consideration that they used for lists.

        A loose definition of list says that the cdr of the pair
        is always another pair or its the empty list.

        So if the pair is not a list it prints the values seperated with a dot.
        This is called a dotted pair.

        (cons 'a 'b) => (a . b)
        (cons (cons 'a 'b) 'c) => ((a . b) . c)

        When it prints a list it basically omits anything that would
        print like ". (" as well as the trailing closing paren.

        This somtimes can lead to some dotted pairs if elements
        of the list are not themselves lists.

        (cons 'a (cons 'b '())) => (a . (b .())) => (a b)
        (cons 'a (cons 'b (cons 'c (cons 'd '())))) = > (a b c d)
        (cons (cons 'a 'b) (cons 'c 'd)) => ((a . b) c . d)

        Printing is guarteed to terminiate in circular list structure.
        "list?" does check for circularity so we could call it before
        printing if we wanted to be safe.
*/
    public String toString ()
    {
        FastStringBuffer result = new FastStringBuffer();
        result.append("(");
        result.append(Writer.write(car));
        Pair pair = this;
        while (pair.cdr != Scheme.Null) {
            if (!(pair.cdr instanceof Pair)) {
                result.append(" . ");
                result.append(Writer.write(pair.cdr));
                result.append(")");
                return(result.toString());
            }
            pair = (Pair)pair.cdr;
            result.append(" ");
            result.append(Writer.write(pair.car));
        }
        result.append(')');
        return result.toString();
    }
}
