next up previous
Next: 10 Pairクラス Up: ソフトウェア特論 講義資料 JavaによるScheme言語処理系: Jscheme Previous: 8 InputPortクラス

9 SchemeUtilsクラス

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日