next up previous
Next: 3 Primitiveクラス Up: ソフトウェア特論 講義資料 JavaによるScheme言語処理系: Jscheme Previous: 1.3 Scheme.javaの全体

2 Envionmentクラス

Schemeの処理系が走る環境を表現するクラスがEnvironmentです. Environmentクラスは,SchemeUtilsクラスのサブクラスで, vars, vals, parentをインスタンス変数として持ちます. Environmentクラスには,シンボルを探し出すlookup, シンボルに値を入れるdefine, シンボルを追加するset, 組込みPrimitiveをdefineするdefPrim, 引数の数と値の数が同じであるかどうかを調べる numberArgsOKなどのメソッドがあります.

package jscheme;

/** Environments allow you to look up
 * the value of a variable, given
 * its name.  Keep a list of variables and
 * values, and a pointer to the parent environment.
 *  If a variable list ends in a symbol rather
 * than null, it means that symbol is bound to
 * the remainder of the values list. 
 * @author Peter Norvig,
 * peter@norvig.com http://www.norvig.com 
 * Copyright 1998 Peter Norvig,
 * see http://www.norvig.com/license.html */

public class Environment extends SchemeUtils {
    public Object vars;
    public Object vals;
    public Environment parent;
    
    /** A constructor to extend an environment
     * with var/val pairs. */

    public Environment(Object vars,
              Object vals, Environment parent) {
        this.vars = vars;
        this.vals = vals;
        this.parent = parent;
        if (!numberArgsOK(vars, vals))
           warn("wrong number of arguments: expected "
                 + vars + " got " + vals);
    }

    /** Construct an empty environment:
         no bindings. **/
    public Environment() {}

    /** Find the value of a symbol,
        in this environment or a parent. */

    public Object lookup (String symbol) {
        Object varList = vars, valList = vals;
        // See if the symbol is bound locally
        while (varList != null) {
            if (first(varList) == symbol) {
                return first(valList);
            } else if (varList == symbol) {
                return valList;
            } else {
                varList = rest(varList);
                valList = rest(valList);
            }
        }
        // If not, try to look for the parent
        if (parent != null)
           return parent.lookup(symbol);
        else
           return error("Unbound variable: "
                        + symbol);
    }
    
    /** Add a new variable,value pair to
         this environment. */

     public Object define(Object var, Object val) {
         vars = cons(var, vars);
         vals = cons(val, vals);
         if (val instanceof Procedure 
             && ((Procedure)val).name
                 .equals("anonymous procedure"))
             ((Procedure)val).name = var.toString();
         return var;
     }

  /** Set the value of an existing variable **/
  public Object set(Object var, Object val) {
    if (!(var instanceof String)) 
      return error("Attempt to set a non-symbol: " 
                          + stringify(var));;
    String symbol = (String) var;
    Object varList = vars, valList = vals;
    // See if the symbol is bound locally
    while (varList != null) {
      if (first(varList) == symbol) {
        return setFirst(valList, val);
      } else if (rest(varList) == symbol) {
        return setRest(valList, val);
      } else {
        varList = rest(varList);
        valList = rest(valList);
      }
    }
    // If not, try to look for the parent
    if (parent != null)
      return parent.set(symbol, val);
    else
      return error("Unbound variable: " + symbol);
  }

    public Environment defPrim(String name,
                              int id, int minArgs) {
      define(name, new Primitive(id,
                                 minArgs, minArgs));
      return this;
    }

    public Environment defPrim(String name,
                               int id,
                               int minArgs,
                               int maxArgs) {
      define(name, new Primitive(id,
                                 minArgs, maxArgs));
      return this;
    }

    /** See if there is an appropriate number of
        vals for these vars. **/

    boolean numberArgsOK(Object vars,
                         Object vals) {
      return ((vars == null && vals == null)
              || (vars instanceof String)
              || (vars instanceof Pair &&
                  vals instanceof Pair &&
                  numberArgsOK(((Pair)vars).rest,
                               ((Pair)vals).rest)));
    }
}


generated through LaTeX2HTML. M.Inaba 平成18年5月6日