internal override void Execute(RuleExecution execution)
 {
     RuleExpressionWalker.Evaluate(execution, exprStatement.Expression);
 }
        internal override bool Validate(RuleValidation validation)
        {
            bool               success = false;
            string             message;
            RuleExpressionInfo lhsExprInfo = null;

            if (assignStatement.Left == null)
            {
                ValidationError error = new ValidationError(Messages.NullAssignLeft, ErrorNumbers.Error_LeftOperandMissing);
                error.UserData[RuleUserDataKeys.ErrorObject] = assignStatement;
                validation.Errors.Add(error);
            }
            else
            {
                lhsExprInfo = validation.ExpressionInfo(assignStatement.Left);
                if (lhsExprInfo == null)
                {
                    lhsExprInfo = RuleExpressionWalker.Validate(validation, assignStatement.Left, true);
                }
            }

            RuleExpressionInfo rhsExprInfo = null;

            if (assignStatement.Right == null)
            {
                ValidationError error = new ValidationError(Messages.NullAssignRight, ErrorNumbers.Error_RightOperandMissing);
                error.UserData[RuleUserDataKeys.ErrorObject] = assignStatement;
                validation.Errors.Add(error);
            }
            else
            {
                rhsExprInfo = RuleExpressionWalker.Validate(validation, assignStatement.Right, false);
            }

            if (lhsExprInfo != null && rhsExprInfo != null)
            {
                Type expressionType = rhsExprInfo.ExpressionType;
                Type assignmentType = lhsExprInfo.ExpressionType;

                if (assignmentType == typeof(NullLiteral))
                {
                    // Can't assign to a null literal.
                    ValidationError error = new ValidationError(Messages.NullAssignLeft, ErrorNumbers.Error_LeftOperandInvalidType);
                    error.UserData[RuleUserDataKeys.ErrorObject] = assignStatement;
                    validation.Errors.Add(error);
                    success = false;
                }
                else if (assignmentType == expressionType)
                {
                    // Easy case, they're both the same type.
                    success = true;
                }
                else
                {
                    // The types aren't the same, but it still might be a legal assignment.
                    if (!RuleValidation.TypesAreAssignable(expressionType, assignmentType, assignStatement.Right, out ValidationError error))
                    {
                        if (error == null)
                        {
                            message = string.Format(CultureInfo.CurrentCulture, Messages.AssignNotAllowed, RuleDecompiler.DecompileType(expressionType), RuleDecompiler.DecompileType(assignmentType));
                            error   = new ValidationError(message, ErrorNumbers.Error_OperandTypesIncompatible);
                        }
                        error.UserData[RuleUserDataKeys.ErrorObject] = assignStatement;
                        validation.Errors.Add(error);
                    }
                    else
                    {
                        success = true;
                    }
                }
            }

            return(success);
        }
 internal override void AnalyzeUsage(RuleAnalysis analysis)
 {
     RuleExpressionWalker.AnalyzeUsage(analysis, exprStatement.Expression, false, false, null);
 }
        internal void AnalyzeReadWrite(RuleAnalysis analysis, CodeExpression targetExpression, RulePathQualifier targetQualifier, CodeExpressionCollection argumentExpressions, ParameterInfo[] parameters, List <CodeExpression> attributedExpressions)
        {
            if (string.IsNullOrEmpty(attributePath))
            {
                // If the suffix is null or empty, this means the RuleAttributeTarget has no dependencies.
                if (attributeTarget == RuleAttributeTarget.This)
                {
                    // The target object has no dependencies.
                    attributedExpressions.Add(targetExpression);
                }
                else if (attributeTarget == RuleAttributeTarget.Parameter)
                {
                    // ALL arguments have no dependencies.
                    for (int i = 0; i < argumentExpressions.Count; ++i)
                    {
                        attributedExpressions.Add(argumentExpressions[i]);
                    }
                }
            }
            else
            {
                string suffix = attributePath;

                bool isRead  = !analysis.ForWrites;
                bool isWrite = analysis.ForWrites;

                if (attributeTarget == RuleAttributeTarget.This)
                {
                    // Target is "This", so perform the analysis on the target expression.

                    // Remove the optional "this/" token if present.
                    string optionalPrefix = "this/";
                    if (suffix.StartsWith(optionalPrefix, StringComparison.Ordinal))
                    {
                        suffix = suffix.Substring(optionalPrefix.Length);
                    }

                    RuleExpressionWalker.AnalyzeUsage(analysis, targetExpression, isRead, isWrite, new RulePathQualifier(suffix, targetQualifier));
                    attributedExpressions.Add(targetExpression);
                }
                else if (attributeTarget == RuleAttributeTarget.Parameter)
                {
                    string paramName = null;

                    int firstSlash = suffix.IndexOf('/');
                    if (firstSlash >= 0)
                    {
                        paramName = suffix.Substring(0, firstSlash);
                        suffix    = suffix.Substring(firstSlash + 1);
                    }
                    else
                    {
                        paramName = suffix;
                        suffix    = null;
                    }

                    // Find the ParameterInfo that corresponds to this attribute path.
                    ParameterInfo param = Array.Find <ParameterInfo>(parameters,
                                                                     delegate(ParameterInfo p) { return(p.Name == paramName); });
                    if (param != null)
                    {
                        RulePathQualifier qualifier = string.IsNullOrEmpty(suffix) ? null : new RulePathQualifier(suffix, null);

                        // 99.9% of the time, the parameter usage attribute only applies to one argument.  However,
                        // if this attribute corresponds to the last parameter, then just assume that all the trailing
                        // arguments correspond.  (In other words, if the caller passed more arguments then there
                        // are parameters, we assume it was a params array.)
                        //
                        // Usually this loop will only execute once.
                        int end = param.Position + 1;
                        if (param.Position == parameters.Length - 1)
                        {
                            end = argumentExpressions.Count;
                        }

                        for (int i = param.Position; i < end; ++i)
                        {
                            CodeExpression argExpr = argumentExpressions[i];
                            RuleExpressionWalker.AnalyzeUsage(analysis, argExpr, isRead, isWrite, qualifier);
                            attributedExpressions.Add(argExpr);
                        }
                    }
                }
            }
        }