Example #1
0
        /// <summary>
        /// Updates the provided scope with the new variable value.
        /// </summary>
        /// <param name="scope">The scope object containing variable values and function parameters.</param>
        /// <returns>
        ///   <c>null</c> if successful, or a <see cref="ParseErrorExpression" /> if not.
        /// </returns>
        public ParseErrorExpression Evaluate(InterpreterScope scope)
        {
            var assignmentScope = new InterpreterScope(scope)
            {
                Context = this
            };
            ExpressionBase result;

            var functionDefinition = Value as FunctionDefinitionExpression;

            if (functionDefinition != null)
            {
                scope.AddFunction(functionDefinition);
                result = new FunctionReferenceExpression(functionDefinition.Name.Name);
            }
            else
            {
                if (!Value.ReplaceVariables(assignmentScope, out result))
                {
                    return((ParseErrorExpression)result);
                }
            }

            return(scope.AssignVariable(Variable, result));
        }
Example #2
0
        /// <summary>
        /// Creates a new scope for calling a function and populates values for parameters passed to the function.
        /// </summary>
        /// <param name="function">The function defining the parameters to populate.</param>
        /// <param name="scope">The outer scope containing the function call.</param>
        /// <param name="error">[out] A <see cref="ParseErrorExpression"/> indicating why constructing the new scope failed.</param>
        /// <returns>The new scope, <c>null</c> if an error occurred - see <paramref name="error"/> for error details.</returns>
        public InterpreterScope GetParameters(FunctionDefinitionExpression function, InterpreterScope scope, out ExpressionBase error)
        {
            var parameterScope = new InterpreterScope(scope);

            var providedParameters = new List <string>(function.Parameters.Count);

            foreach (var parameter in function.Parameters)
            {
                providedParameters.Add(parameter.Name);
            }

            ArrayExpression varargs = null;

            if (providedParameters.Remove("..."))
            {
                varargs = new ArrayExpression();
                parameterScope.AssignVariable(new VariableExpression("varargs"), varargs);
            }

            var parameterCount = providedParameters.Count;

            int  index           = 0;
            bool namedParameters = false;

            foreach (var parameter in Parameters)
            {
                var assignedParameter = parameter as AssignmentExpression;
                if (assignedParameter != null)
                {
                    if (!providedParameters.Remove(assignedParameter.Variable.Name))
                    {
                        if (!function.Parameters.Any(p => p.Name == assignedParameter.Variable.Name))
                        {
                            error = new ParseErrorExpression(String.Format("'{0}' does not have a '{1}' parameter", function.Name.Name, assignedParameter.Variable.Name), parameter);
                            return(null);
                        }

                        error = new ParseErrorExpression(String.Format("'{0}' already has a value", assignedParameter.Variable.Name), assignedParameter.Variable);
                        return(null);
                    }

                    var assignmentScope = new InterpreterScope(scope)
                    {
                        Context = assignedParameter
                    };

                    ExpressionBase value;
                    if (!assignedParameter.Value.ReplaceVariables(assignmentScope, out value))
                    {
                        error = new ParseErrorExpression(value, assignedParameter.Value);
                        return(null);
                    }

                    assignedParameter.Value.CopyLocation(value);

                    parameterScope.DefineVariable(new VariableDefinitionExpression(assignedParameter.Variable), value);
                    namedParameters = true;
                }
                else
                {
                    if (namedParameters)
                    {
                        error = new ParseErrorExpression("Non-named parameter following named parameter", parameter);
                        return(null);
                    }

                    if (index >= parameterCount && varargs == null)
                    {
                        error = new ParseErrorExpression("Too many parameters passed to function", parameter);
                        return(null);
                    }

                    var variableName    = (index < parameterCount) ? function.Parameters.ElementAt(index).Name : "...";
                    var assignmentScope = new InterpreterScope(scope)
                    {
                        Context = new AssignmentExpression(new VariableExpression(variableName), parameter)
                    };

                    ExpressionBase value;
                    if (!parameter.ReplaceVariables(assignmentScope, out value))
                    {
                        error = new ParseErrorExpression(value, parameter);
                        return(null);
                    }

                    parameter.CopyLocation(value);

                    if (index < parameterCount)
                    {
                        providedParameters.Remove(variableName);
                        parameterScope.DefineVariable(new VariableDefinitionExpression(variableName), value);
                    }
                    else
                    {
                        varargs.Entries.Add(value);
                    }
                }

                ++index;
            }

            foreach (var parameter in providedParameters)
            {
                ExpressionBase value;
                if (!function.DefaultParameters.TryGetValue(parameter, out value))
                {
                    error = new ParseErrorExpression(String.Format("Required parameter '{0}' not provided", parameter), FunctionName);
                    return(null);
                }

                var assignmentScope = new InterpreterScope(scope)
                {
                    Context = new AssignmentExpression(new VariableExpression(parameter), value)
                };
                if (!value.ReplaceVariables(assignmentScope, out value))
                {
                    error = new ParseErrorExpression(value, this);
                    return(null);
                }

                parameterScope.DefineVariable(new VariableDefinitionExpression(parameter), value);
            }

            error = null;
            return(parameterScope);
        }