Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
0
        private static bool MergeAddition(ExpressionBase left, ExpressionBase right, out ExpressionBase result)
        {
            // if either side is a string, combine to a larger string
            if (left.Type == ExpressionType.StringConstant || right.Type == ExpressionType.StringConstant)
            {
                var builder = new StringBuilder();
                left.AppendStringLiteral(builder);
                right.AppendStringLiteral(builder);

                result = new StringConstantExpression(builder.ToString());
                return(true);
            }

            // if either side is a float, convert both to float
            if (left.Type == ExpressionType.FloatConstant || right.Type == ExpressionType.FloatConstant)
            {
                if (!ConvertToFloat(ref left, ref right, out result))
                {
                    return(false);
                }

                result = new FloatConstantExpression(((FloatConstantExpression)left).Value + ((FloatConstantExpression)right).Value);
                return(true);
            }

            if (left.Type == ExpressionType.IntegerConstant && right.Type == ExpressionType.IntegerConstant)
            {
                result = new IntegerConstantExpression(((IntegerConstantExpression)left).Value + ((IntegerConstantExpression)right).Value);
                return(true);
            }

            result = new ParseErrorExpression("Cannot add expressions");
            return(false);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Determines whether the expression evaluates to true for the provided <paramref name="scope" />
        /// </summary>
        /// <param name="scope">The scope object containing variable values.</param>
        /// <param name="error">[out] The error that prevented evaluation (or null if successful).</param>
        /// <returns>
        /// The result of evaluating the expression
        /// </returns>
        public override bool IsTrue(InterpreterScope scope, out ParseErrorExpression error)
        {
            bool result = Left.IsTrue(scope, out error);

            if (error != null)
            {
                return(false);
            }

            switch (Operation)
            {
            case ConditionalOperation.And:
                if (result)
                {
                    result = Right.IsTrue(scope, out error);
                }
                break;

            case ConditionalOperation.Or:
                if (!result)
                {
                    result = Right.IsTrue(scope, out error);
                }
                break;

            case ConditionalOperation.Not:
                result = !result;
                break;
            }

            return(result);
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
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);
        }
Ejemplo n.º 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)
        {
            // user-defined functions should be evaluated (expanded) immediately.
            if (!Evaluate(scope, out result))
            {
                return(false);
            }

            if (result == null)
            {
                var functionCall = scope.GetContext <FunctionCallExpression>();
                if (functionCall != null)
                {
                    result = new ParseErrorExpression(Name.Name + " did not return a value", functionCall.FunctionName);
                }
                else
                {
                    result = new ParseErrorExpression(Name.Name + " did not return a value");
                }

                return(false);
            }

            return(true);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Gets the dictionary parameter from the <paramref name="scope"/> or <see cref="DefaultParameters"/> collections.
        /// </summary>
        /// <param name="scope">The scope.</param>
        /// <param name="name">The name of the parameter.</param>
        /// <param name="parseError">[out] The error that occurred.</param>
        /// <returns>The parameter value, or <c>null</c> if an error occurred.</b></returns>
        protected DictionaryExpression GetDictionaryParameter(InterpreterScope scope, string name, out ExpressionBase parseError)
        {
            var parameter = GetParameter(scope, name, out parseError);

            if (parameter == null)
            {
                return(null);
            }

            var typedParameter = parameter as DictionaryExpression;

            if (typedParameter == null)
            {
                var originalParameter = LocateParameter(scope, name);
                if (originalParameter != null)
                {
                    parameter = originalParameter;
                }

                parseError = new ParseErrorExpression(name + " is not a dictionary", parameter);
                return(null);
            }

            parseError = null;
            return(typedParameter);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Gets the variable reference from the <paramref name="scope"/> or <see cref="DefaultParameters"/> collections.
        /// </summary>
        /// <param name="scope">The scope.</param>
        /// <param name="name">The name of the parameter.</param>
        /// <param name="parseError">[out] The error that occurred.</param>
        /// <returns>The variable reference, or <c>null</c> if an error occurred.</b></returns>
        protected VariableReferenceExpression GetReferenceParameter(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 typedParameter = parameter as VariableReferenceExpression;

            if (typedParameter == null)
            {
                var originalParameter = LocateParameter(scope, name);
                if (originalParameter != null)
                {
                    parameter = originalParameter;
                }

                parseError = new ParseErrorExpression(name + " is not a reference", parameter);
                return(null);
            }

            parseError = null;
            return(typedParameter);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Gets the boolean parameter from the <paramref name="scope"/> or <see cref="DefaultParameters"/> collections.
        /// </summary>
        /// <param name="scope">The scope.</param>
        /// <param name="name">The name of the parameter.</param>
        /// <param name="parseError">[out] The error that occurred.</param>
        /// <returns>The parameter value, or <c>null</c> if an error occurred.</b></returns>
        protected BooleanConstantExpression GetBooleanParameter(InterpreterScope scope, string name, out ExpressionBase parseError)
        {
            var parameter = GetParameter(scope, name, out parseError);

            if (parameter == null)
            {
                return(null);
            }

            var typedParameter = parameter as BooleanConstantExpression;

            if (typedParameter == null)
            {
                var originalParameter = LocateParameter(scope, name);
                if (originalParameter != null)
                {
                    parameter = originalParameter;
                }

                parseError = new ParseErrorExpression(name + " is not a boolean", parameter);
                return(null);
            }

            parseError = null;
            return(typedParameter);
        }
Ejemplo n.º 10
0
        private bool GetSingleParameter(FunctionDefinitionExpression function, InterpreterScope parameterScope, out ExpressionBase error)
        {
            var funcParameter = function.Parameters.First();

            ExpressionBase value = Parameters.First();

            if (value.IsConstant)
            {
                // already a basic type, just proceed to storing it
                error = null;
            }
            else
            {
                var assignedParameter = value as AssignmentExpression;
                if (assignedParameter == null)
                {
                    assignedParameter = new AssignmentExpression(new VariableExpression(funcParameter.Name), value);
                }
                else if (funcParameter.Name != assignedParameter.Variable.Name)
                {
                    error = new ParseErrorExpression(String.Format("'{0}' does not have a '{1}' parameter", function.Name.Name, assignedParameter.Variable.Name), value);
                    return(true);
                }

                value = GetParameter(parameterScope, parameterScope, assignedParameter);
                error = value as ParseErrorExpression;
                if (error != null)
                {
                    return(true);
                }
            }

            parameterScope.DefineVariable(new VariableDefinitionExpression(funcParameter.Name), value);
            return(true);
        }
Ejemplo n.º 11
0
        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));
        }
Ejemplo n.º 12
0
        private static bool MergeModulus(ExpressionBase left, ExpressionBase right, out ExpressionBase result)
        {
            // if either side is a float, convert both to float
            if (left.Type == ExpressionType.FloatConstant || right.Type == ExpressionType.FloatConstant)
            {
                if (!ConvertToFloat(ref left, ref right, out result))
                {
                    return(false);
                }

                if (((FloatConstantExpression)right).Value == 0.0)
                {
                    result = new ParseErrorExpression("Division by zero");
                    return(false);
                }

                result = new FloatConstantExpression(((FloatConstantExpression)left).Value % ((FloatConstantExpression)right).Value);
                return(true);
            }

            if (left.Type == ExpressionType.IntegerConstant && right.Type == ExpressionType.IntegerConstant)
            {
                if (((IntegerConstantExpression)right).Value == 0)
                {
                    result = new ParseErrorExpression("Division by zero");
                    return(false);
                }

                result = new IntegerConstantExpression(((IntegerConstantExpression)left).Value % ((IntegerConstantExpression)right).Value);
                return(true);
            }

            result = new ParseErrorExpression("Cannot modulus expressions");
            return(false);
        }
Ejemplo n.º 13
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)
        {
            // FunctionDefinition.ReplaceVariables is called when evaluating a function for an assignment.
            // For user functions (see UserFunctionDefinition.ReplaceVariables) - it will just evaluate the
            // function call and return the result. Several internal functions have very special Evaluate
            // handling that should not be executed when defining variables. Those functions rely on this
            // behavior to just evaluate the parameters without calling Evaluate. There are some built-in
            // functions that should call Evaluate when ReplaceVariables is called. They will override
            // ReplaceVariables to do that.
            var parameters = new ExpressionBase[Parameters.Count];
            int i          = 0;

            foreach (var parameterName in Parameters)
            {
                // do a direct lookup here. calling GetParameter will discard the VariableReference
                // and we want to preserve those for now.
                var parameter = scope.GetVariable(parameterName.Name);
                if (parameter == null)
                {
                    result = new ParseErrorExpression("No value provided for " + parameterName.Name + " parameter", parameterName);
                    return(false);
                }

                parameters[i++] = parameter;
            }

            result = new FunctionCallExpression(Name.Name, parameters);
            CopyLocation(result);
            return(true);
        }
Ejemplo n.º 14
0
 public void AddEvaluationError(ParseErrorExpression error)
 {
     lock (_evaluationErrors)
     {
         _evaluationErrors.Add(error);
     }
 }
Ejemplo n.º 15
0
        public bool GetExpressionsForLine(List <ExpressionBase> expressions, int line)
        {
            bool result = false;

            foreach (var group in GetGroupsForLine(line))
            {
                result |= group.GetExpressionsForLine(expressions, line);
            }

            lock (_evaluationErrors)
            {
                foreach (var error in _evaluationErrors)
                {
                    var unknownVariableError = error.InnermostError as UnknownVariableParseErrorExpression;
                    if (unknownVariableError != null && unknownVariableError.Location.Start.Line <= line &&
                        unknownVariableError.Location.End.Line >= line)
                    {
                        if (!expressions.Contains(unknownVariableError))
                        {
                            expressions.Add(unknownVariableError);
                        }

                        result = true;
                    }

                    ParseErrorExpression mostSignificantError = null;
                    var scan = error;
                    do
                    {
                        if (scan.Location.Start.Line <= line && scan.Location.End.Line >= line)
                        {
                            // scan is more significant than current error, use it
                            mostSignificantError = scan;
                        }
                        else if (mostSignificantError != null &&
                                 scan.Location.Start.Line >= mostSignificantError.Location.Start.Line &&
                                 scan.Location.End.Line < mostSignificantError.Location.End.Line)
                        {
                            // scan is more significant than current error, but not part of line, ignore it
                            mostSignificantError = null;
                            break;
                        }

                        scan = scan.InnerError;
                    } while (scan != null);

                    if (mostSignificantError != null)
                    {
                        if (!expressions.Contains(mostSignificantError))
                        {
                            expressions.Add(mostSignificantError);
                        }

                        result = true;
                    }
                }
            }

            return(result);
        }
Ejemplo n.º 16
0
        public void AddParseError(ParseErrorExpression error)
        {
            if (_parseErrors == null)
            {
                _parseErrors = new List <ParseErrorExpression>();
            }

            _parseErrors.Add(error);
        }
Ejemplo n.º 17
0
        private void GetContainerIndex(InterpreterScope scope, out ExpressionBase container, out ExpressionBase index)
        {
            if (Index.Type == ExpressionType.FunctionCall)
            {
                var expression = (FunctionCallExpression)Index;
                if (!expression.ReplaceVariables(scope, out index))
                {
                    container = index;
                    return;
                }
            }
            else if (!Index.ReplaceVariables(scope, out index))
            {
                container = index;
                return;
            }

            var indexed = Variable as IndexedVariableExpression;

            if (indexed != null)
            {
                indexed.ReplaceVariables(scope, out container);
                return;
            }

            container = scope.GetVariable(Variable.Name);
            if (container == null)
            {
                container = new UnknownVariableParseErrorExpression("Unknown variable: " + Variable.Name, Variable);
                return;
            }

            var variableReference = container as VariableReferenceExpression;

            if (variableReference != null)
            {
                container = variableReference.Expression;
            }

            var array = container as ArrayExpression;

            if (array != null)
            {
                var intIndex = index as IntegerConstantExpression;
                if (intIndex == null)
                {
                    container = new ParseErrorExpression("Index does not evaluate to an integer constant", index);
                }
                else if (intIndex.Value < 0 || intIndex.Value >= array.Entries.Count)
                {
                    container = new ParseErrorExpression(String.Format("Index {0} not in range 0-{1}", intIndex.Value, array.Entries.Count - 1), index);
                }
            }
        }
Ejemplo n.º 18
0
        private static bool MergeBitwiseAnd(ExpressionBase left, ExpressionBase right, out ExpressionBase result)
        {
            if (left.Type == ExpressionType.IntegerConstant && right.Type == ExpressionType.IntegerConstant)
            {
                result = new IntegerConstantExpression(((IntegerConstantExpression)left).Value & ((IntegerConstantExpression)right).Value);
                return(true);
            }

            result = new ParseErrorExpression("Cannot bitwise and expressions");
            return(false);
        }
Ejemplo n.º 19
0
        public static ParseErrorExpression WrapError(ParseErrorExpression error, string message, ExpressionBase expression)
        {
            if (error.Location.End == expression.Location.End && error.Location.Start == expression.Location.Start)
            {
                return(error);
            }

            return(new ParseErrorExpression(message, expression)
            {
                InnerError = error
            });
        }
Ejemplo n.º 20
0
        internal static ParseErrorExpression ParseError(PositionalTokenizer tokenizer, string message, int line, int column)
        {
            var error = new ParseErrorExpression(message, line, column, tokenizer.Line, tokenizer.Column);

            var expressionTokenizer = tokenizer as ExpressionTokenizer;

            if (expressionTokenizer != null)
            {
                expressionTokenizer.AddError(error);
            }

            return(error);
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Gets the  parameter from the <paramref name="scope"/> or <see cref="DefaultParameters"/> collections.
        /// </summary>
        /// <param name="scope">The scope.</param>
        /// <param name="name">The name of the parameter.</param>
        /// <param name="parseError">[out] The error that occurred.</param>
        /// <returns>The parameter value, or <c>null</c> if an error occurred.</b></returns>
        protected ExpressionBase GetParameter(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);
            }

            parseError = null;
            return(parameter);
        }
Ejemplo n.º 22
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 Invoke(InterpreterScope scope, out ExpressionBase result)
        {
            if (Evaluate(scope, out result))
            {
                return(true);
            }

            if (result.Location.Start.Line == 0)
            {
                result = new ParseErrorExpression(result, FunctionName);
            }

            return(false);
        }
Ejemplo n.º 23
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 container, index;

            GetContainerIndex(scope, out container, out index);

            switch (container.Type)
            {
            case ExpressionType.Dictionary:
                result = ((DictionaryExpression)container).GetEntry(index);
                if (result == null)
                {
                    var builder = new StringBuilder();
                    builder.Append("No entry in dictionary for key: ");
                    index.AppendString(builder);
                    result = new ParseErrorExpression(builder.ToString(), Index);
                    return(false);
                }
                break;

            case ExpressionType.Array:
                result = ((ArrayExpression)container).Entries[((IntegerConstantExpression)index).Value];
                break;

            case ExpressionType.ParseError:
                result = container;
                return(false);

            default:
            {
                var builder = new StringBuilder();
                builder.Append("Cannot index: ");
                Variable.AppendString(builder);
                builder.Append(" (");
                builder.Append(container.Type);
                builder.Append(')');
                result = new ParseErrorExpression(builder.ToString(), Variable);
            }
                return(false);
            }

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

            return(result.ReplaceVariables(scope, out result));
        }
Ejemplo n.º 24
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)
        {
            if (!Evaluate(scope, out result))
            {
                return(false);
            }

            if (result == null)
            {
                result = new ParseErrorExpression(FunctionName.Name + " did not return a value", FunctionName);
                return(false);
            }

            CopyLocation(result);
            return(true);
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Gets the string parameter from the <paramref name="scope"/> or <see cref="DefaultParameters"/> collections.
        /// </summary>
        /// <param name="scope">The scope.</param>
        /// <param name="name">The name of the parameter.</param>
        /// <param name="parseError">[out] The error that occurred.</param>
        /// <returns>The parameter value, or <c>null</c> if an error occurred.</b></returns>
        protected StringConstantExpression GetStringParameter(InterpreterScope scope, string name, out ExpressionBase parseError)
        {
            var parameter = GetParameter(scope, name, out parseError);

            if (parameter == null)
            {
                return(null);
            }

            var typedParameter = parameter as StringConstantExpression;

            if (typedParameter == null)
            {
                parseError = new ParseErrorExpression(name + " is not a string", parameter);
                return(null);
            }

            parseError = null;
            return(typedParameter);
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Gets a parameter from the <paramref name="scope"/> or <see cref="DefaultParameters"/> collections.
        /// </summary>
        /// <param name="scope">The scope.</param>
        /// <param name="name">The name of the parameter.</param>
        /// <param name="parseError">[out] The error that occurred.</param>
        /// <returns>The parameter value, or <c>null</c> if an error occurred.</b></returns>
        protected ExpressionBase GetParameter(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);
            }

            parseError = null;

            // if it's a variable reference, return the referenced object.
            if (parameter.Type == ExpressionType.VariableReference)
            {
                return(((VariableReferenceExpression)parameter).Expression);
            }

            // WARNING: variable references may still exist within a varargs object
            return(parameter);
        }
Ejemplo n.º 27
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));
        }
Ejemplo n.º 28
0
 public void AddError(ParseErrorExpression error)
 {
     _expressionGroup.AddParseError(error);
 }
Ejemplo n.º 29
0
        /// <summary>
        /// Determines whether the expression evaluates to true for the provided <paramref name="scope" />
        /// </summary>
        /// <param name="scope">The scope object containing variable values.</param>
        /// <param name="error">[out] The error that prevented evaluation (or null if successful).</param>
        /// <returns>
        /// The result of evaluating the expression
        /// </returns>
        public override bool IsTrue(InterpreterScope scope, out ParseErrorExpression error)
        {
            ExpressionBase left, right;

            if (!Left.ReplaceVariables(scope, out left))
            {
                error = left as ParseErrorExpression;
                return(false);
            }

            if (!Right.ReplaceVariables(scope, out right))
            {
                error = right as ParseErrorExpression;
                return(false);
            }

            error = null;

            var integerLeft = left as IntegerConstantExpression;

            if (integerLeft != null)
            {
                var integerRight = right as IntegerConstantExpression;
                if (integerRight == null)
                {
                    return(false);
                }

                switch (Operation)
                {
                case ComparisonOperation.Equal:
                    return(integerLeft.Value == integerRight.Value);

                case ComparisonOperation.NotEqual:
                    return(integerLeft.Value != integerRight.Value);

                case ComparisonOperation.GreaterThan:
                    return(integerLeft.Value > integerRight.Value);

                case ComparisonOperation.GreaterThanOrEqual:
                    return(integerLeft.Value >= integerRight.Value);

                case ComparisonOperation.LessThan:
                    return(integerLeft.Value < integerRight.Value);

                case ComparisonOperation.LessThanOrEqual:
                    return(integerLeft.Value <= integerRight.Value);

                default:
                    return(false);
                }
            }

            var stringLeft = left as StringConstantExpression;

            if (stringLeft != null)
            {
                var stringRight = right as StringConstantExpression;
                if (stringRight == null)
                {
                    return(false);
                }

                switch (Operation)
                {
                case ComparisonOperation.Equal:
                    return(stringLeft.Value == stringRight.Value);

                case ComparisonOperation.NotEqual:
                    return(stringLeft.Value != stringRight.Value);

                case ComparisonOperation.GreaterThan:
                    return(String.Compare(stringLeft.Value, stringRight.Value) > 0);

                case ComparisonOperation.GreaterThanOrEqual:
                    return(String.Compare(stringLeft.Value, stringRight.Value) >= 0);

                case ComparisonOperation.LessThan:
                    return(String.Compare(stringLeft.Value, stringRight.Value) < 0);

                case ComparisonOperation.LessThanOrEqual:
                    return(String.Compare(stringLeft.Value, stringRight.Value) <= 0);

                default:
                    return(false);
                }
            }

            return(false);
        }
Ejemplo n.º 30
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 = function.CreateCaptureScope(scope);

            // optimization for no parameter function
            if (function.Parameters.Count == 0 && Parameters.Count == 0)
            {
                error = null;
                return(parameterScope);
            }

            // optimization for single parameter function
            if (function.Parameters.Count == 1 && Parameters.Count == 1)
            {
                if (GetSingleParameter(function, parameterScope, out error))
                {
                    return(parameterScope);
                }

                if (error != null)
                {
                    return(null);
                }
            }

            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.DefineVariable(new VariableDefinitionExpression("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 value = GetParameter(parameterScope, scope, assignedParameter);
                    error = value as ParseErrorExpression;
                    if (error != null)
                    {
                        return(null);
                    }

                    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 : "...";

                    assignedParameter = new AssignmentExpression(new VariableExpression(variableName), parameter);
                    var value = GetParameter(parameterScope, scope, assignedParameter);
                    error = value as ParseErrorExpression;
                    if (error != null)
                    {
                        return(null);
                    }

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