处理 begin
遍历语句,然后返回最后一条语句的值:
else if (first.Value == "begin") {
SObject result = null;
foreach (SExpression statement in this.Children.Skip(1)) {
result = statement.Evaluate(scope);
}
return result;
}
处理 func
利用 SExpression 构建 SFunction ,然后返回:
else if (first.Value == "func") {
SExpression body = this.Children[2];
String[] parameters = this.Children[1].Children.Select(exp => exp.Value).ToArray();
SScope newScope = new SScope(scope);
return new SFunction(body, parameters, newScope);
}
处理 list
首先把 list 里的元素依次求值,然后创建 SList :
else if (first.Value == "list") {
return new SList(this.Children.Skip(1).Select(exp => exp.Evaluate(scope)));
}
处理内置操作
首先得到参数的表达式,然后调用对应的内置函数:
else if (SScope.BuiltinFunctions.ContainsKey(first.Value)) {
var arguments = this.Children.Skip(1).ToArray();
return SScope.BuiltinFunctions[first.Value](arguments, scope);
}
处理自定义函数调用
自定义函数调用有两种情况:
-
非具名函数调用:((func (x) (* x x)) 3)
具名函数调用:(square 3)
调用自定义函数时应使用新的作用域,所以为 SFunction 增加 Update 方法:
public SFunction Update(SObject[] arguments) {
var existingArguments = this.Parameters.Select(p => this.Scope.FindInTop(p)).Where(obj => obj != null);
var newArguments = existingArguments.Concat(arguments).ToArray();
SScope newScope = this.Scope.Parent.SpawnScopeWith(this.Parameters, newArguments);
return new SFunction(this.Body, this.Parameters, newScope);
}
为了便于创建自定义作用域,并判断函数的参数是否被赋值,为 SScope 增加 SpawnScopeWith 和 FindInTop 方法:
public SScope SpawnScopeWith(String[] names, SObject[] values) {
(names.Length >= values.Length).OrThrows("Too many arguments.");
SScope scope = new SScope(this);
for (Int32 i = 0; i < values.Length; i++) {
scope.variableTable.Add(names[i], values[i]);
}
return scope;
}
public SObject FindInTop(String name) {
if (variableTable.ContainsKey(name)) {
return variableTable[name];
}
return null;
}
下面是函数调用的实现:
else {
SFunction function = first.Value == "(" ? (SFunction)first.Evaluate(scope) : (SFunction)scope.Find(first.Value);
var arguments = this.Children.Skip(1).Select(s => s.Evaluate(scope)).ToArray();
return function.Update(arguments).Evaluate();
}
完整的求值代码










