Next: 3 Primitiveクラス
Up: ソフトウェア特論 講義資料 JavaによるScheme言語処理系: Jscheme
Previous: 1.3 Scheme.javaの全体
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日