Exemple #1
0
        /// <summary>
        /// Replaces the variables in the expression with values from <paramref name="scope" />.
        /// </summary>
        /// <param name="scope">The scope object containing variable values.</param>
        /// <param name="result">[out] The new expression containing the replaced variables.</param>
        /// <returns>
        ///   <c>true</c> if substitution was successful, <c>false</c> if something went wrong, in which case <paramref name="result" /> will likely be a <see cref="ParseErrorExpression" />.
        /// </returns>
        public override bool ReplaceVariables(InterpreterScope scope, out ExpressionBase result)
        {
            var functionDefinition = scope.GetFunction(FunctionName.Name);

            if (functionDefinition == null)
            {
                result = new ParseErrorExpression("Unknown function: " + FunctionName.Name, FunctionName);
                return(false);
            }

            var functionScope = GetParameters(functionDefinition, scope, out result);

            if (functionScope == null)
            {
                return(false);
            }

            if (functionScope.Depth >= 100)
            {
                result = new ParseErrorExpression("Maximum recursion depth exceeded", this);
                return(false);
            }

            functionScope.Context = this;
            if (!functionDefinition.ReplaceVariables(functionScope, out result))
            {
                return(false);
            }

            CopyLocation(result);
            return(true);
        }
        public override bool?IsTrue(InterpreterScope scope, out ParseErrorExpression error)
        {
            ExpressionBase result;

            if (!Evaluate(scope, true, out result))
            {
                error = result as ParseErrorExpression;
                return(null);
            }

            var functionCall = result as FunctionCallExpression;

            if (functionCall != null) // prevent recursion
            {
                error = null;

                var funcDef = scope.GetFunction(functionCall.FunctionName.Name);
                if (funcDef is Functions.AlwaysTrueFunction)
                {
                    return(true);
                }

                if (funcDef is Functions.AlwaysFalseFunction)
                {
                    return(false);
                }

                return(null);
            }

            return(result.IsTrue(scope, out error));
        }
Exemple #3
0
        /// <summary>
        /// Gets the return value from calling a function.
        /// </summary>
        /// <param name="scope">The scope object containing variable values.</param>
        /// <param name="result">[out] The new expression containing the function result.</param>
        /// <returns>
        ///   <c>true</c> if invocation was successful, <c>false</c> if something went wrong, in which case <paramref name="result" /> will likely be a <see cref="ParseErrorExpression" />.
        /// </returns>
        public bool Evaluate(InterpreterScope scope, out ExpressionBase result)
        {
            var functionDefinition = scope.GetFunction(FunctionName.Name);

            if (functionDefinition == null)
            {
                result = new ParseErrorExpression("Unknown function: " + FunctionName.Name, FunctionName);
                return(false);
            }

            var functionScope = GetParameters(functionDefinition, scope, out result);

            if (functionScope == null)
            {
                return(false);
            }

            if (functionScope.Depth >= 100)
            {
                result = new ParseErrorExpression("Maximum recursion depth exceeded", this);
                return(false);
            }

            functionScope.Context = this;
            if (!functionDefinition.Evaluate(functionScope, out result))
            {
                return(false);
            }

            scope.ReturnValue = result;
            return(true);
        }
Exemple #4
0
        protected FunctionDefinitionExpression GetFunctionParameter(InterpreterScope scope, string name, out ExpressionBase parseError)
        {
            var parameter = scope.GetVariable(name);

            if (parameter == null)
            {
                parseError = new ParseErrorExpression("No value provided for " + name + " parameter");
                return(null);
            }

            var functionDefinition = parameter as FunctionDefinitionExpression;

            if (functionDefinition == null)
            {
                var functionReference = parameter as FunctionReferenceExpression;
                if (functionReference == null)
                {
                    parseError = new ParseErrorExpression(name + " must be a function reference");
                    return(null);
                }

                functionDefinition = scope.GetFunction(functionReference.Name);
                if (functionDefinition == null)
                {
                    parseError = new ParseErrorExpression("Undefined function: " + functionReference.Name);
                    return(null);
                }
            }

            parseError = null;
            return(functionDefinition);
        }
Exemple #5
0
        /// <summary>
        /// Replaces the variables in the expression with values from <paramref name="scope" />.
        /// </summary>
        /// <param name="scope">The scope object containing variable values.</param>
        /// <param name="result">[out] The new expression containing the replaced variables.</param>
        /// <returns>
        ///   <c>true</c> if substitution was successful, <c>false</c> if something went wrong, in which case <paramref name="result" /> will likely be a <see cref="ParseErrorExpression" />.
        /// </returns>
        public override bool ReplaceVariables(InterpreterScope scope, out ExpressionBase result)
        {
            ExpressionBase value = scope.GetVariable(Name);

            if (value == null)
            {
                var func = scope.GetFunction(Name);
                if (func != null)
                {
                    // special wrapper for returning a function as a variable
                    result = new FunctionReferenceExpression(Name);
                    result.CopyLocation(this);
                    return(true);
                }

                result = new UnknownVariableParseErrorExpression("Unknown variable: " + Name, this);
                return(false);
            }

            return(value.ReplaceVariables(scope, out result));
        }
Exemple #6
0
        /// <summary>
        /// Replaces the variables in the expression with values from <paramref name="scope" />.
        /// </summary>
        /// <param name="scope">The scope object containing variable values.</param>
        /// <param name="result">[out] The new expression containing the replaced variables.</param>
        /// <returns>
        ///   <c>true</c> if substitution was successful, <c>false</c> if something went wrong, in which case <paramref name="result" /> will likely be a <see cref="ParseErrorExpression" />.
        /// </returns>
        public override bool ReplaceVariables(InterpreterScope scope, out ExpressionBase result)
        {
            ExpressionBase value = scope.GetVariable(Name);

            if (value == null)
            {
                var func = scope.GetFunction(Name);
                if (func != null)
                {
                    result = new ParseErrorExpression("Function used like a variable: " + Name, this);
                }
                else
                {
                    result = new ParseErrorExpression("Unknown variable: " + Name, this);
                }

                return(false);
            }

            return(value.ReplaceVariables(scope, out result));
        }
        private bool Evaluate(InterpreterScope scope, bool inAssignment, out ExpressionBase result)
        {
            var functionDefinition = scope.GetFunction(FunctionName.Name);

            if (functionDefinition == null)
            {
                if (scope.GetVariable(FunctionName.Name) != null)
                {
                    result = new UnknownVariableParseErrorExpression(FunctionName.Name + " is not a function", FunctionName);
                }
                else
                {
                    result = new UnknownVariableParseErrorExpression("Unknown function: " + FunctionName.Name, FunctionName);
                }

                return(false);
            }

            var functionParametersScope = GetParameters(functionDefinition, scope, out result);

            if (functionParametersScope == null || result is ParseErrorExpression)
            {
                return(false);
            }

            if (functionParametersScope.Depth >= 100)
            {
                result = new ParseErrorExpression("Maximum recursion depth exceeded", this);
                return(false);
            }

            functionParametersScope.Context = this;
            if (inAssignment)
            {
                // in assignment, just replace variables
                functionDefinition.ReplaceVariables(functionParametersScope, out result);

                if (result.Type == ExpressionType.FunctionCall)
                {
                    // if the result is a function call, check for any variable references. it can't be marked
                    // as fully expanded if any variable references are present.
                    var functionCall = (FunctionCallExpression)result;
                    if (!functionCall.Parameters.Any(p => p is VariableReferenceExpression))
                    {
                        functionCall._fullyExpanded = true;
                    }

                    // if there was no change, also mark the source as fully expanded.
                    if (result == this)
                    {
                        _fullyExpanded = true;
                    }

                    // when expanding the parameters, a new functionCall object will be created without a name
                    // location. if that has happened, replace the temporary name object with the real one.
                    if (functionCall.FunctionName.Location.Start.Line == 0 && functionCall.FunctionName.Name == FunctionName.Name)
                    {
                        functionCall.FunctionName = FunctionName;
                    }
                }
            }
            else
            {
                // not in assignment, evaluate the function
                functionDefinition.Evaluate(functionParametersScope, out result);
            }

            var error = result as ParseErrorExpression;

            if (error != null)
            {
                if (error.Location.Start.Line == 0)
                {
                    this.CopyLocation(error);
                }
                result = ParseErrorExpression.WrapError(error, FunctionName.Name + " call failed", FunctionName);
                return(false);
            }

            return(true);
        }