コード例 #1
0
        /// <summary>
        /// Appends numbers indicating the block a statement belongs to.
        /// <remarks>
        /// A statement written in the format:
        ///
        /// > var nested = from x in a
        /// >              from y in b
        /// >              select x + y;
        /// >
        /// > var fetch = from x in nested
        /// >             from y in b
        /// >             select x + y;
        ///
        /// will be rewritten as:
        ///
        /// > a.SelectMany(
        /// >   x => b,
        /// >   x, y => x + y
        /// > ).SelectMany(
        /// >   x => b
        /// >   x, y =>  x + y
        /// > );
        ///
        /// Because there are two variables named "x", and these
        /// expressions are written inline, we need to number them,
        /// in case they end up in the same applicative group.
        /// </remarks>
        /// </summary>
        public static IEnumerable <QueryStatement> NumberBlocks(List <QueryStatement> statements)
        {
            var blockNumber      = 0;
            var statementCounter = 0;
            var numStatements    = statements.Count();
            var isFirst          = true;

            foreach (var statement in statements)
            {
                statementCounter++;
                // SplitBind functions that take one non-transparent parameter are binding the entire result from another monad.
                // This will hide any variables that were in scope in that monad.
                statement.StartsBlock = isFirst;
                if (statement.Match(
                        bind => bind.BindVariables.ParameterNames.Count == 1 &&
                        !ParseExpression.IsTransparent(bind.Expressions.Bind.Parameters.First()),
                        let => false)
                    )
                {
                    blockNumber++;
                    statement.StartsBlock = true;
                }
                statement.BlockNumber = blockNumber;
                if (statementCounter == numStatements)
                {
                    statement.IsFinal = true;
                }
                isFirst = false;
                yield return(statement);
            }
        }
コード例 #2
0
 /// <summary>
 /// We only want to rewrite transparent identifier accessors.
 /// </summary>
 protected override Expression VisitMember(MemberExpression node)
 {
     if (ParseExpression.IsFromTransparent(node) && !ParseExpression.IsTransparentMember(node))
     {
         return(RewritePropertyAccess(node));
     }
     return(base.VisitMember(node));
 }
コード例 #3
0
        /// <summary>
        /// Gets the variables in a (bind, project) pair.
        /// </summary>
        private static QueryStatement GetVariables(BindProjectPair pair)
        {
            var project = pair.Project;
            var isLet   = project.Parameters.Any(param => param.Name.StartsWith(LET_PREFIX));

            if (isLet)
            {
                var letParam      = project.Parameters.ElementAt(1);
                var letName       = letParam.Name;
                var originalName  = Regex.Split(letName, LET_PREFIX)[1];
                var letExpression = Expression.Lambda(project.Body, project.Parameters.First(),
                                                      Expression.Parameter(letParam.Type, originalName));
                var letVariables = ParseExpression.GetExpressionVariables(letExpression);
                return(new LetStatement(originalName, letExpression, letVariables));
            }
            var bindVars    = ParseExpression.GetExpressionVariables(pair.Bind);
            var projectVars = ParseExpression.GetExpressionVariables(project);

            return(new BindProjectStatement(pair, bindVars, projectVars)
            {
                IsSelect = pair.IsSelect
            });
        }