Esempio n. 1
0
        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);
        }