Next: 10 Pairクラス
Up: ソフトウェア特論 講義資料 JavaによるScheme言語処理系: Jscheme
Previous: 8 InputPortクラス
SchemeUtilsは抽象クラスで,
Schemeクラス,Environmentクラス,Procedureクラス,
InputPortクラス,Pairクラスの親クラスとなっています.
package jscheme;
/** @author Peter Norvig,
* peter@norvig.com http://www.norvig.com
* Copyright 1998 Peter Norvig,
* see http://www.norvig.com/license.html **/
import java.io.*;
public abstract class SchemeUtils {
/** Same as Boolean.TRUE. **/
public static final Boolean TRUE = Boolean.TRUE;
/** Same as Boolean.FALSE. **/
public static final Boolean FALSE = Boolean.FALSE;
public static Double ZERO = new Double(0.0);
public static Double ONE = new Double(1.0);
//////// Conversion Routines ///////
// The following convert or coerce objects
// to the right type.
/** Convert boolean to Boolean. **/
public static Boolean truth(boolean x)
{ return x ? TRUE : FALSE; }
/** Convert Scheme object to boolean.
Only #f is false, others are true. **/
public static boolean truth(Object x)
{ return x != FALSE; }
/** Convert double to Double. Caches 0 and 1;
makes new for others. **/
public static Double num(double x) {
return (x == 0.0) ?
ZERO : (x == 1.0)
? ONE : new Double(x); }
/** Converts a Scheme object to a double,
or calls error. **/
public static double num(Object x) {
if (x instanceof Number)
return ((Number)x).doubleValue();
else
return num(
error("expected a number, got: " + x));
}
/** Converts a Scheme object to a char,
or calls error. **/
public static char chr(Object x) {
if (x instanceof Character)
return ((Character)x).charValue();
else
return chr(error("expected a char, got: "
+ x));
}
/** Converts a char to a Character. **/
public static Character chr(char ch) {
return new Character(ch);
}
/** Coerces a Scheme object to a Scheme string,
which is a char[]. **/
public static char[] str(Object x) {
if (x instanceof char[]) return (char[])x;
else
return str(error("expected a string, got: "
+ x));
}
/** Coerces a Scheme object to a Scheme symbol,
which is a string. **/
public static String sym(Object x) {
if (x instanceof String) return (String)x;
else return sym(error("expected a symbol, got: "
+ x));
}
/** Coerces a Scheme object to a Scheme vector,
which is a Object[]. **/
public static Object[] vec(Object x) {
if (x instanceof Object[]) return (Object[])x;
else
return vec(error("expected a vector, got: "
+ x));
}
/** Coerces a Scheme object to
* a Scheme input port, which is an InputPort.
* If the argument is null, returns interpreter.input. **/
public static InputPort
inPort(Object x, Scheme interp) {
if (x == null) return interp.input;
else if (x instanceof InputPort)
return (InputPort)x;
else
return inPort(
error("expected an input port, got: "
+ x),
interp);
}
/** Coerces a Scheme object to a Scheme
* input port, which is a PrintWriter.
* If the argument is null,
* returns System.out. **/
public static PrintWriter
outPort(Object x, Scheme interp) {
if (x == null) return interp.output;
else if (x instanceof PrintWriter)
return (PrintWriter)x;
else
return outPort(
error("expected an output port, got: "
+ x),
interp);
}
////////// Error Routines ///////////
/** A continuable error.
* Prints an error message and then prompts for
* a value to eval and return. **/
public static Object error(String message) {
System.err.println("**** ERROR: " + message);
throw new RuntimeException(message);
}
public static Object warn(String message) {
System.err.println("**** WARNING: " + message);
return "<warn>";
}
////// Basic manipulation Routines //////
// The following are used throughout the code.
/** 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).first : null;
}
/** Like Common Lisp rest;
* car of a Pair,
* or null for anything else. **/
public static Object rest(Object x) {
return (x instanceof Pair) ?
((Pair)x).rest : null;
}
/** Like Common Lisp (setf (first ... **/
public static Object
setFirst(Object x, Object y) {
return (x instanceof Pair) ?
((Pair)x).first = y
: error("Attempt to set-car of a non-Pair:"
+ stringify(x));
}
/** Like Common Lisp (setf (rest ... **/
public static Object
setRest(Object x, Object y) {
return (x instanceof Pair) ?
((Pair)x).rest = y
: error("Attempt to set-cdr of a non-Pair:"
+ stringify(x));
}
/** Like Common Lisp second. **/
public static Object second(Object x) {
return first(rest(x));
}
/** Like Common Lisp third. **/
public static Object third(Object x) {
return first(rest(rest(x)));
}
/** 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);
}
/** listStar(args) is like Common Lisp
* (apply #'list* args) **/
public static Object listStar(Object args) {
if (rest(args) == null)
return first(args);
else
return cons(first(args),
listStar(rest(args)));
}
/** cons(x, y) is the same as new Pair(x, y). **/
public static Pair cons(Object a, Object b) {
return new Pair(a, b);
}
/** Reverse the elements of a list. **/
public static Object reverse(Object x) {
Object result = null;
while (x instanceof Pair) {
result = cons(first(x), result);
x = rest(x);
}
return result;
}
/** Check if two objects are equal. **/
public static boolean equal(Object x, Object y) {
if (x == null || y == null) {
return x == y;
} else if (x instanceof char[]) {
if (!(y instanceof char[])) return false;
char[] xc = (char[])x, yc = (char[])y;
if (xc.length != yc.length) return false;
for (int i = xc.length - 1; i >= 0; i--) {
if (xc[i] != yc[i]) return false;
}
return true;
} else if (x instanceof Object[]) {
if (!(y instanceof Object[])) return false;
Object[] xo = (Object[])x, yo = (Object[])y;
if (xo.length != yo.length) return false;
for (int i = xo.length - 1; i >= 0; i--) {
if (!equal(xo[i],yo[i])) return false;
}
return true;
} else {
return x.equals(y);
}
}
/** Check if two objects are == or are
equal numbers or characters. **/
public static boolean eqv(Object x, Object y) {
return x == y
|| (x instanceof Double && x.equals(y))
|| (x instanceof Character && x.equals(y));
}
/** 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).rest;
}
return len;
}
/** Convert a list of characters to
a Scheme string, which is a char[]. **/
public static char[] listToString(Object chars) {
char[] str = new char[length(chars)];
for (int i = 0; chars instanceof Pair; i++) {
str[i] = chr(first(chars));
chars = rest(chars);
}
return str;
}
/** Convert a list of Objects to a Scheme vector,
which is a Object[]. **/
public static Object[] listToVector(Object objs) {
Object[] vec = new Object[length(objs)];
for (int i = 0; objs instanceof Pair; i++) {
vec[i] = first(objs);
objs = rest(objs);
}
return vec;
}
/** Write the object to a port.
* If quoted is true, use "str" and #\c,
* otherwise use str and c. **/
public static Object
write(Object x,
PrintWriter port, boolean quoted) {
port.print(stringify(x, quoted));
port.flush();
return x;
}
/** Convert a vector to a List. **/
public static Pair vectorToList(Object x) {
if (x instanceof Object[]) {
Object[] vec = (Object[])x;
Pair result = null;
for (int i = vec.length - 1; i >= 0; i--)
result = cons(vec[i], result);
return result;
} else {
error("expected a vector, got: " + x);
return null;
}
}
/** Convert a Scheme object to its printed
* representation, as a java String
* (not a Scheme string). If quoted is true,
* use "str" and #\c, otherwise use str and c.
* You need to pass in a StringBuffer that is used
* to accumulate the results.
* (If the interface didn't work that way, the
* system would use lots of little internal
* StringBuffers. But note that
* you can still call <tt>stringify(x)</tt> and
* a new StringBuffer will
* be created for you. **/
static void stringify(Object x,
boolean quoted, StringBuffer buf) {
if (x == null)
buf.append("()");
else if (x instanceof Double) {
double d = ((Double)x).doubleValue();
if (Math.round(d) == d)
buf.append((long)d); else buf.append(d);
} else if (x instanceof Character) {
if (quoted) buf.append("#\\");
buf.append(x);
} else if (x instanceof Pair) {
((Pair)x).stringifyPair(quoted, buf);
} else if (x instanceof char[]) {
char[] chars = (char[])x;
if (quoted) buf.append('"');
for (int i = 0; i < chars.length; i++) {
if (quoted && chars[i] == '"')
buf.append('\\');
buf.append(chars[i]);
}
if (quoted) buf.append('"');
} else if (x instanceof Object[]) {
Object[] v = (Object[])x;
buf.append("#(");
for (int i=0; i<v.length; i++) {
stringify(v[i], quoted, buf);
if (i != v.length-1) buf.append(' ');
}
buf.append(')');
} else if (x == TRUE) {
buf.append("#t");
} else if (x == FALSE) {
buf.append("#f");
} else {
buf.append(x);
}
}
/** Convert x to a Java String giving
* its external representation.
* Strings and characters are quoted. **/
static String stringify(Object x) {
return stringify(x, true);
}
/** Convert x to a Java String giving its
* external representation.
* Strings and characters are quoted iff
* <tt>quoted</tt> is true.. **/
static String stringify(Object x, boolean quoted) {
StringBuffer buf = new StringBuffer();
stringify(x, quoted, buf);
return buf.toString();
}
/** For debugging purposes, prints output. **/
static Object p(Object x) {
System.out.println(stringify(x));
return x;
}
/** For debugging purposes, prints output. **/
static Object p(String msg, Object x) {
System.out.println(msg + ": " + stringify(x));
return x;
}
}
generated through LaTeX2HTML. M.Inaba 平成18年5月6日