public IObject Eval(INode node, Enviroment enviroment) { switch (node) { // 文 case Root root: return(this.EvalRootProgram(root.Statements, enviroment)); case ExpressionStatement statement: return(this.Eval(statement.Expression, enviroment)); case BlockStatement blockStatement: return(this.EvalBlockStatement(blockStatement, enviroment)); case ReturnStatement returnStatement: var value = this.Eval(returnStatement.ReturnValue, enviroment); if (this.IsError(value)) { return(value); } return(new ReturnValue(value)); case LetStatement letStatement: var letValue = this.Eval(letStatement.Value, enviroment); if (this.IsError(letValue)) { return(letValue); } enviroment.Set(letStatement.Name.Value, letValue); break; // 式 case PrefixExpression prefixExpression: var right = this.Eval(prefixExpression.Right, enviroment); if (this.IsError(right)) { return(right); } return(this.EvalPrefixExpression(prefixExpression.Operator, right, enviroment)); case InfixExpression infixExpression: var ifLeft = this.Eval(infixExpression.Left, enviroment); if (this.IsError(ifLeft)) { return(ifLeft); } var ifRight = this.Eval(infixExpression.Right, enviroment); if (this.IsError(ifRight)) { return(ifRight); } return(this.EvalInfixExpression( infixExpression.Operator, ifLeft, ifRight, enviroment )); case IfExpression ifExpression: return(this.EvalIfExpression(ifExpression, enviroment)); case IntegerLiteral integerLiteral: return(new IntegerObject(integerLiteral.Value)); case BooleanLiteral booleanLiteral: return(this.ToBooleanObject(booleanLiteral.Value)); case Identifier identifier: return(this.EvalIdentifier(identifier, enviroment)); case FunctionLiteral functionLiteral: return(new FunctionObject() { Parameters = functionLiteral.Parameters, Body = functionLiteral.Body, Enviroment = enviroment, }); case CallExpression callExpression: var fn = this.Eval(callExpression.Function, enviroment); if (this.IsError(fn)) { return(fn); } var args = this.EvalExpressions(callExpression.Arguments, enviroment); if (this.IsError(args.FirstOrDefault())) { return(args.First()); } return(this.ApplyFunction(fn, args)); } return(null); }