// File: SchemeUtil.java
// Date: 7/4/2008
package org.bot.jscheme;
/**
* Collection static scheme interpreter utilities.
*/
public abstract class SchemeUtil {
public static Object error(String message) {
System.err.println("ERROR: " + message);
throw new RuntimeException(message);
}
/**
* Like Common Lisp first; car of a Pair, or null for anything else.
*/
public static Object first(Object x) {
return (x instanceof Pair) ? ((Pair) x).getFirst() : null;
}
public static Object third(Object x) {
return first(rest(rest(x)));
}
/**
* Like Common Lisp rest; car of a Pair, or null for anything else.
* "A cons cell is composed of two pointers; the car operation
* extracts the first pointer, and the cdr operation extracts the second."
*
* "Thus, the expression (car (cons x y)) evaluates to x,
* and (cdr (cons x y)) evaluates to y."
*/
public static Object rest(Object x) {
return (x instanceof Pair) ? ((Pair) x).getRest() : null;
}
/**
* Like Common Lisp second.
*/
public static Object second(Object x) {
return first(rest(x));
}
/**
* The length of a list, or zero for a non-list.
*/
public static int length(Object x) {
int len = 0;
while (x instanceof Pair) {
len++;
x = ((Pair)x).getRest();
}
return len;
}
/**
* Creates a two element list.
*/
public static Pair list(Object a, Object b) {
return new Pair(a, new Pair(b, null));
}
/**
* Creates a one element list.
*/
public static Pair list(Object a) {
return new Pair(a, null);
}
/**
* cons(x, y) is the same as new Pair(x, y).
*
* Cons presents and interesting function that is fundamental to lisp.
* Here are some examples of cons usage (tested in common lisp).
* <code>
* (cons 1 2):
* Pair pair = SchemeUtil.cons("1", "2");
* assertEquals("" + pair, "(1 . 2)");
*
* (cons 1 nil):
* Pair pair = SchemeUtil.cons("1", null);
* assertEquals("" + pair, "(1)");
*
* (cons 1 (cons 2 nil)):
*
* Pair pair = SchemeUtil.cons("1", SchemeUtil.cons("2", null));
* assertEquals("" + pair, "(1 2)");
*
* </code>
*/
public static Pair cons(Object a, Object b) {
return new Pair(a, b);
}
private static void stringifyObjectArray(final Object [] x, final StringBuffer buf) {
Object[] v = (Object[]) x;
buf.append("#(");
for (int i = 0; i < v.length; i++) {
stringify(v[i], buf);
if (i != v.length - 1) {
buf.append(' ');
}
} // End of For
buf.append(')');
}
/**
* Convert a Scheme object to its printed representation, as a java String
* (not a Scheme string).
*/
public static void stringify(Object x, final StringBuffer buf) {
if (x == null) {
buf.append("()");
} else if (x instanceof Double) {
double d = ((Double)x).doubleValue();
buf.append(d);
} else if (x instanceof Character) {
buf.append(x);
} else if (x instanceof Pair) {
((Pair) x).stringifyPair(buf);
} else if (x instanceof char[]) {
char[] chars = (char[]) x;
for (int i = 0; i < chars.length; i++) {
buf.append(chars[i]);
} // End of For
} else if (x instanceof Object []) {
stringifyObjectArray((Object []) x, buf);
} else if (x == Boolean.TRUE) {
buf.append("#t");
} else if (x == Boolean.FALSE) {
buf.append("#f");
} else {
buf.append(x);
}
} // End of Method
/**
* Convert x to a Java String giving its external representation.
*/
public static String stringify(Object x) {
StringBuffer buf = new StringBuffer();
stringify(x, buf);
return buf.toString();
}
} // End of the Class