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); }