예제 #1
0
        public override object Evaluate(Water.List expressions)
        {
            //Push a stack frame
            Water.Environment.Push();


            // Evaluate local variables.
            Water.List expressions_to_eval = expressions.Copy();
            Water.List values  = new Water.List();
            bool       hasRest = false;

            foreach (Water.Identifier parameter in this.Parameters)
            {
                if (hasRest)
                {
                    throw new Water.Error("Cannot have parameters after a rest parameter in function " + this._name);
                }

                if (IsRest(parameter))
                {
                    //Add the rest.
                    Water.List rest = new Water.List();
                    foreach (object expression in expressions_to_eval)
                    {
                        rest.Add(Water.Evaluator.Evaluate(expression));
                    }
                    expressions_to_eval.Clear();
                    values.Add(rest);
                    hasRest = true;
                }
                else if (IsOptional(parameter))
                {
                    //If it doesn't exist add null.
                    if (expressions_to_eval.Count == 0)
                    {
                        values.Add(null);
                    }
                    else
                    {
                        object value = Water.Evaluator.Evaluate(expressions_to_eval.First());
                        values.Add(value);

                        expressions_to_eval = expressions_to_eval.NotFirst();
                    }
                }
                else if (IsUnevaluated(parameter))
                {
                    values.Add(expressions_to_eval.First());

                    expressions_to_eval = expressions_to_eval.NotFirst();
                }
                else
                {
                    //Throw exception if null.
                    if (expressions_to_eval.Count == 0)
                    {
                        throw new Water.Error("Parameter is required: " + parameter.Value);
                    }
                    else
                    {
                        object value = Water.Evaluator.Evaluate(expressions_to_eval.First());
                        if (value == null)
                        {
                            throw new Water.Error("Parameter is required: " + parameter.Value);
                        }
                        values.Add(value);

                        expressions_to_eval = expressions_to_eval.NotFirst();
                    }
                }
            }
            if (expressions_to_eval.Count > 0)
            {
                throw new Water.Error("Too many expressions passed to function: " + this._name);
            }


            // Push local variables.
            int i = 0;

            foreach (Water.Identifier parameter in this.Parameters)
            {
                if (Water.Environment.IsConstant(parameter.Value))
                {
                    throw new Water.Error("Constant \"" + parameter.Value + "\" is already defined.");
                }
                if (IsOptional(parameter))
                {
                    string name = GetOptional(parameter);
                    Water.Environment.DefineVariable(name, values[i]);
                }
                else if (IsRest(parameter))
                {
                    string name = GetRest(parameter);
                    Water.Environment.DefineVariable(name, values[i]);
                }
                else if (IsUnevaluated(parameter))
                {
                    string name = GetUnevaluated(parameter);
                    Water.Environment.DefineVariable(name, values[i]);
                }
                else
                {
                    Water.Environment.DefineVariable(parameter.Value, values[i]);
                }
                i++;
            }


            //Interpret the function.
            Water.Interpreter.Interpret(new StatementIterator(this.Statements, false));


            //Pop a stack frame.
            Water.Environment.Pop();


            object returnValue = Water.Environment.ReturnValue;

            Water.Environment.Return      = false;
            Water.Environment.ReturnValue = null;
            return(returnValue);
        }