
class LispFuns extends Prims {

    public static Object second(Object obj) {
	return ((Pair) (((Pair) obj) .cdr)).car;
    }
    
    public static Object third(Object obj) {
	return ((Pair) ((Pair) (((Pair) obj) .cdr)).cdr).car;
    }

    public static Object cddr(Object obj) {
	return ((Pair) (((Pair) obj) .cdr)).cdr;
    }

    public static Object newline() {
	stdout.pwtr.print("\n");
	return box(false);
    }	

    public static Object display(Object obj) {	// not quite right...
	if (obj.getClass() == String.class)
	    stdout.pwtr.print(obj);
	else write(obj);
	stdout.pwtr.flush();
	return obj;
    }

    public static Object write(Object obj) {
	if (obj == null) {
	    stdout.pwtr.print("()"); return null;
	}
	Class type = obj.getClass();
	if (type == Lisp.Pair.class) {
	    stdout.pwtr.print("(");
	    if (listP_j(obj)) writeseq(obj);
	    else {
		write(car(obj));
		stdout.pwtr.print(" . ");
		write(cdr(obj));
	    }
	    stdout.pwtr.print( ")");
	} else if (type == Lisp.Symbol.class) {
	    stdout.pwtr.print(((Symbol) obj).pname);
	} else if (type == String.class) {
	    stdout.pwtr.print("\""); stdout.pwtr.print(obj); stdout.pwtr.print("\"");
	} else
	    stdout.pwtr.print(obj);
	
	stdout.pwtr.flush();
	return obj;
    }

    static void writeseq(Object the_list) {
	if (the_list != null) {
	    write(car(the_list));
	    if (cdr(the_list) != null) {
		stdout.pwtr.print(" ");
		writeseq(cdr(the_list));
	    }
	}
    }

    public static Object not(Object val) {
	return box(!((Boolean) val).booleanValue());
    }

    public static Object plus(Object a, Object b) {
	return box(((Double) a).doubleValue() + ((Double) b).doubleValue());
    }

    public static Object minus(Object a, Object b) {
	return box(((Double) a).doubleValue() - ((Double) b).doubleValue());
    }

    public static Object times(Object a, Object b) {
	return box(((Double) a).doubleValue() * ((Double) b).doubleValue());
    }

    public static Object pairP(Object obj) {
 	return box(pairP_j(obj));
    }

    public static Object listP(Object obj) {
	return box(listP_j(obj));
    }

    static Object reverse_aux(Object rest, Object so_far) {
	if (rest == null) return so_far;
	return reverse_aux( cdr(rest), cons( car(rest), so_far));
    }

    public static Object reverse(Object the_list) {
	return reverse_aux(the_list, null);
    }
    
    public static Object length(Object the_list) {
	return box(length_j(the_list));
    }

    public static Object eof_objectP(Object arg) {
	if (arg == eof_sym) return box(true);
	else return box(false);
    }

    public static Object read() {
	Object tok = stdin.nextToken();
	if (lparen(tok)) return read_rest(null);
	else return tok;
    }

    static Object read_rest(Object so_far) {
	Object tok = stdin.nextToken();
	if (rparen(tok)) return reverse_aux(so_far, null);
	stdin.pushBack();
	return read_rest( cons( read(), so_far));
    }

    public static Object eqvP (Object a, Object b) {
	return box(a.equals(b));
    }

    public static Object eqP (Object a, Object b) {
	return box (a == b);
    }
}
