Ejemplo n.º 1
0
        /// <summary>
        /// Dump a compound statement
        /// </summary>
        /// <param name="code"></param>
        /// <param name="indent"></param>
        /// <returns></returns>
        public static IEnumerable <string> DumpCode(this IStatementCompound code, string indent = "")
        {
            if (code is IBookingStatementBlock)
            {
                var bs = code as IBookingStatementBlock;
                yield return(string.Format("{0}There are {1} declared variables", indent, bs.DeclaredVariables.Count()));

                foreach (var var in bs.DeclaredVariables)
                {
                    string initalValue = "default()";
                    if (var.InitialValue != null && var.InitialValue != null)
                    {
                        initalValue = var.InitialValue.RawValue;
                    }

                    yield return(string.Format(indent + "  " + var.Type.Name + " " + var.ParameterName + " = " + initalValue + ";"));
                }
            }
            yield return(string.Format("{0}Lines of code:", indent));

            foreach (var l in code.CodeItUp())
            {
                yield return(string.Format("{0}  {1}", indent, l));
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Are we allowed to move this statement to be the first statement in this block?
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        private static bool MoveToFirst(IStatementCompound parent, IStatement item)
        {
            // If we can't move, then don't.
            if ((item as ICMStatementInfo).NeverLift)
            {
                return(false);
            }

            // Loop through each statement, and see if we can go past each one.

            foreach (var cStatement in parent.Statements)
            {
                if (cStatement == item)
                {
                    return(true);
                }
                if (!StatementCommutes(cStatement, item))
                {
                    return(false);
                }
            }

            // That is weird. It never appeared here!
            throw new InvalidOperationException();
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Add a statement to the current "cursor" point.
        /// </summary>
        /// <param name="s"></param>
        public void Add(IStatement s)
        {
            if (s == null)
            {
                throw new ArgumentNullException("Cannot add a statement that is null");
            }

            CurrentScopePointer.Add(s);

            ///
            /// Change the statement scope if there something that goes down a level.
            ///

            if (s is IBookingStatementBlock)
            {
                _scopeState.Push(CurrentScope);
            }

            if (s is IStatementCompound)
            {
                CurrentScopePointer = s as IStatementCompound;
            }
            if (s is IBookingStatementBlock)
            {
                PreviousDeclarationScopePointer = CurrentDeclarationScopePointer;
                CurrentDeclarationScopePointer  = s as IBookingStatementBlock;
                Depth++;
            }
        }
Ejemplo n.º 4
0
        private static bool CheckQueryCodeBlock(IStatementCompound codeBlock, IStatement parent)
        {
            if (parent != codeBlock.Parent)
            {
                Console.WriteLine("ERROR: satement {0} does not point back to proper parent {1}", codeBlock.ToString(), parent.ToString());
                return(false);
            }
            foreach (var s in codeBlock.Statements)
            {
                if (s is IStatementCompound)
                {
                    var r = CheckQueryCodeBlock(s as IStatementCompound, codeBlock);
                    if (!r)
                    {
                        return(r);
                    }
                }
                else
                {
                    if (s.Parent != codeBlock)
                    {
                        Console.WriteLine("ERROR: statement {0} does not point back to proper parent {1}", s.ToString(), codeBlock.ToString());
                        return(false);
                    }
                }
            }

            return(true);
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Chunk the quries up into blocks and return a function block (2D array).
 /// </summary>
 /// <param name="queryBlocks"></param>
 /// <param name="queriesPerFunction"></param>
 /// <returns></returns>
 private IEnumerable<IEnumerable<string>> TranslateQueryBlocks(IStatementCompound[] queryBlocks, int queriesPerFunction, int numberBlocks)
 {
     for (int i = 0; i < numberBlocks; i++)
     {
         var queires = queryBlocks.Skip(queriesPerFunction * i).Take(queriesPerFunction);
         yield return TranslateOneQueryBlockSet(queires);
     }
 }
        /// <summary>
        /// We have a statement. Loop down through everything and see if we can't find
        /// another statement that will "take" it.
        /// </summary>
        /// <param name="s"></param>
        /// <param name="codeStack"></param>
        /// <returns></returns>
        private static IStatementCompound MoveStatementIntoCodeStack(IStatementCompound parent, IStatement s, IStatementCompound[] codeStack)
        {
            // Never move a statement that doesn't want to move. :-)
            if (s is ICMStatementInfo)
            {
                if ((s as ICMStatementInfo).NeverLift)
                {
                    return(null);
                }
            }

            // Walk the code stack and find someone that can take us.

            foreach (var stack in codeStack)
            {
                var r = stack.CombineAndMark(s, s.Parent as IBookingStatementBlock, false);
                if (r != null)
                {
                    parent.Remove(s);

                    // During the CombineAndMark there is a chance that a declaration has been orphaned.
                    // If aBoolean_23 was declared in parent, it may also be declared up where it was moved to.
                    // If that is the case, we need to remove it.
                    if (parent is IBookingStatementBlock && r.Parent is IBookingStatementBlock)
                    {
                        var newParent = r.Parent as IBookingStatementBlock;
                        var oldParent = parent as IBookingStatementBlock;

                        var varsToRemove = from declVar in oldParent.DeclaredVariables
                                           from parVars in newParent.DeclaredVariables
                                           where declVar.ParameterName == parVars.ParameterName
                                           select declVar;
                        foreach (var declVar in varsToRemove.ToArray())
                        {
                            oldParent.Remove(declVar);
                        }
                    }

                    // We have to be a little careful here. The statement should be added at the right
                    // place. Since the statement works inside parent, and it works inside stack, then
                    // it should work in stack, just before parent.

                    var stackStatement = FindStatementHolder(stack, parent);
                    if (!stack.IsBefore(r, parent))
                    {
                        stack.Remove(r);
                        stack.AddBefore(r, parent);
                    }

                    return(stack);
                }
            }
            return(null);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Find a statement that may be inside a compound statement - return the top level statement that
        /// contains it. Throw if we can't find it.
        /// </summary>
        /// <param name="block"></param>
        /// <param name="statement"></param>
        /// <returns></returns>
        private IStatement findStatementThatContains(IStatementCompound block, IStatement statement)
        {
            var m = block.Statements.Where(s => ContainsStatement(s, statement)).FirstOrDefault();

            if (m == null)
            {
                throw new ArgumentException("Unable to find the requested statement in the block");
            }

            return(m);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Given a statement in an compound block, return the order it is. Or throw if we can't find it.
        /// </summary>
        /// <param name="blockWithoutModified"></param>
        /// <param name="statement"></param>
        /// <returns></returns>
        private int findStatementIndex(IStatementCompound block, IStatement statement)
        {
            var r = from s in block.Statements.Zip(Enumerable.Range(1, 5000), (st, cnt) => Tuple.Create(st, cnt))
                    where s.Item1 == statement
                    select s;
            var match = r.FirstOrDefault();

            if (match == null)
            {
                throw new ArgumentException("Unable to find the statement in the sequence");
            }

            return(match.Item2);
        }
        /// <summary>
        /// s is in some code block in parent. Find the statement in parent that contains (or is) s.
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="s"></param>
        /// <returns></returns>
        private static IStatement FindStatementHolder(IStatementCompound parent, IStatement s)
        {
            var finalParent = s;

            while (finalParent != null && finalParent != parent)
            {
                finalParent = finalParent.Parent;
            }
            if (finalParent == null)
            {
                throw new ArgumentException("Statement s does not seem to be contained in parent");
            }
            return(finalParent);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Recursively add the items in...
        /// </summary>
        /// <param name="iBookingStatementBlock"></param>
        /// <returns></returns>
        private int CountStatements(IStatementCompound s)
        {
            int cnt = 0;
            foreach (var substatement in s.Statements)
            {
                cnt++;
                if (substatement is IStatementCompound)
                {
                    cnt += CountStatements(substatement as IStatementCompound);
                }
            }

            return cnt;
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Recursively add the items in...
        /// </summary>
        /// <param name="iBookingStatementBlock"></param>
        /// <returns></returns>
        private int CountStatements(IStatementCompound s)
        {
            int cnt = 0;

            foreach (var substatement in s.Statements)
            {
                cnt++;
                if (substatement is IStatementCompound)
                {
                    cnt += CountStatements(substatement as IStatementCompound);
                }
            }

            return(cnt);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Given a statement that has bubble-up info in it, we will try to move
        /// it up one.
        /// </summary>
        /// <param name="statements"></param>
        /// <param name="item"></param>
        /// <remarks>For now only support bubbling up one level</remarks>
        private static bool BubbleUp(IStatementCompound parent, IStatement item)
        {
            // First, is the parent statement that we can bubble up past?
            var cmpInfo = parent as ICMCompoundStatementInfo;

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

            // OK, now lets see if we can bubble it up one level.
            if (!cmpInfo.AllowNormalBubbleUp)
            {
                return(false);
            }

            // Next job - if this isn't the first statement, then we have to
            // be able to move it past all the other statements.

            if (!MoveToFirst(parent, item))
            {
                return(false);
            }

            // Finally, does this guy need anything from the compound statement?

            var declared         = cmpInfo.DeclaredVariables;
            var inputs           = (item as ICMStatementInfo).DependentVariables;
            var requiredDeclared = declared.Select(p => p.RawValue).Intersect(inputs);

            if (requiredDeclared.Count() > 0)
            {
                return(false);
            }

            // And does this statement idempotent? "a = a + 1" has the side effect of altering
            // a - so if it is repeated it won't have the same result. On the other hand,
            // "a = 10" will always have the same effect. The former should not be lifted
            // out of a loop.
            if (parent is IStatementLoop &&
                !StatementIdempotent(item))
            {
                return(false);
            }

            // OK, now insert it one level up, just before the parent. MoveStatementUpOneLevel
            return(MoveStatementUpOneLevel(item));
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Add a declaration to a booking parent, if there is one. Return true if we could.
        /// </summary>
        /// <param name="s"></param>
        /// <param name="varToDeclare"></param>
        /// <returns></returns>
        private static bool AddBookingToParentOf(IStatementCompound s, IDeclaredParameter varToDeclare)
        {
            var parent = s.Parent;

            while (parent != null)
            {
                var book = parent as IBookingStatementBlock;
                if (book != null)
                {
                    book.Add(varToDeclare);
                    return(true);
                }
            }

            return(false);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Loop through optimizable statements
        /// </summary>
        /// <param name="statements"></param>
        /// <returns>If we have modified something that has bubble up one level, we return true. This means we've messed up the statement list at the outer level and the optimization loop needs to be re-run.</returns>
        private static bool VisitOptimizableStatements(IStatementCompound statements)
        {
            bool returnModified = false;

            bool modified = true;

            while (modified)
            {
                modified = false;
                var opter = new BlockRenamer(statements.FindBookingParent(), statements.FindBookingParent());
                foreach (var item in statements.Statements)
                {
                    // If it is a compound statement, there may be statements that are "invariant" in it,
                    // so we can lift them out.
                    if (item is IStatementCompound)
                    {
                        // If the statement is a compound statement, then we try to go down a level.
                        modified = VisitOptimizableStatements(item as IStatementCompound);
                    }

                    // Perhaps the whole statement could be pulled up?
                    if (!modified && (item is ICMStatementInfo))
                    {
                        // if we have optimize info, then see what we can do with it.
                        modified = BubbleUp(statements, item);
                        if (modified)
                        {
                            returnModified = true;
                        }
                    }

                    // Finally, check to see if this statement is identical to anyone else further up or not.
                    if (!modified)
                    {
                        modified = BubleUpAndCombine(statements, item, opter);
                    }

                    // If anything was modified, we need to re-run since all the various pointers, etc., will have
                    // been changed.
                    if (modified)
                    {
                        break;
                    }
                }
            }
            return(returnModified);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Find the statement of a particular type, or return null.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="statementType"></param>
        /// <returns></returns>
        public static T FindStatement <T>(this IStatementCompound source)
            where T : class
        {
            var here = source.Statements.Where(s => s.GetType() == typeof(T)).FirstOrDefault();

            if (here != null)
            {
                return((T)here);
            }

            return(source.Statements
                   .Where(sc => sc is IStatementCompound)
                   .Cast <IStatementCompound>()
                   .Select(s => s.FindStatement <T>())
                   .Where(found => found != null)
                   .FirstOrDefault());
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Returns the statement where the parameter was declared, or null.
        /// </summary>
        /// <param name="source"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public static IBookingStatementBlock FindDeclarationStatement(this IStatementCompound source, IDeclaredParameter param)
        {
            if (source is IBookingStatementBlock)
            {
                var book  = source as IBookingStatementBlock;
                var found = book.DeclaredVariables.Where(v => v.ParameterName == param.ParameterName).Any();
                if (found)
                {
                    return(book);
                }
            }

            return(source.Statements
                   .Where(s => s is IStatementCompound)
                   .Cast <IStatementCompound>()
                   .Select(s => s.FindDeclarationStatement(param))
                   .Where(v => v != null)
                   .FirstOrDefault());
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Loop through optimizable statements
        /// </summary>
        /// <param name="statements"></param>
        /// <returns>If we have modified something that has bubble up one level, we return true. This means we've messed up the statement list at the outer level and the optimization loop needs to be re-run.</returns>
        private static bool VisitOptimizableStatements(IStatementCompound statements)
        {
            bool returnModified = false;

            bool modified = true;
            while (modified)
            {
                modified = false;
                var opter = new BlockRenamer(statements.FindBookingParent(), statements.FindBookingParent());
                foreach (var item in statements.Statements)
                {
                    // If it is a compound statement, there may be statements that are "invariant" in it,
                    // so we can lift them out.
                    if (item is IStatementCompound)
                    {
                        // If the statement is a compound statement, then we try to go down a level.
                        modified = VisitOptimizableStatements(item as IStatementCompound);
                    }

                    // Perhaps the whole statement could be pulled up?
                    if (!modified && (item is ICMStatementInfo))
                    {
                        // if we have optimize info, then see what we can do with it.
                        modified = BubbleUp(statements, item);
                        if (modified)
                            returnModified = true;
                    }

                    // Finally, check to see if this statement is identical to anyone else further up or not.
                    if (!modified)
                    {
                        modified = BubleUpAndCombine(statements, item, opter);
                    }

                    // If anything was modified, we need to re-run since all the various pointers, etc., will have
                    // been changed.
                    if (modified)
                        break;
                }
            }
            return returnModified;
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Given a block of code, try to find statements that should be lifted up. For each statement
        /// that we find, see if there is one in the list that is "identical" - in short - already there.
        /// </summary>
        /// <param name="block">Examine this block for statements that can be lifted</param>
        /// <param name="codeStack">The list of parents where we might put this statement</param>
        private static void VisitCodeBlock(IStatementCompound block)
        {
            // Do decent first scan.
            foreach (var s in block.Statements.RetryFromStartIfModified())
            {
                if (s is IStatementCompound)
                {
                    VisitCodeBlock(s as IStatementCompound);
                }
            }

            // Now look at each item in the block and see if we can't find something above us that contains
            // the very same thing. In order to pop any statement up we must
            // 1. Be able to move it to the front of whatever block we are in
            // 2. Find a statement previous to this block above us that will combine with it.

            foreach (var s in block.Statements.RetryFromStartIfModified())
            {
                FindEquivalentAboveAndCombine(block, s);
            }
        }
Ejemplo n.º 19
0
 /// <summary>
 /// If a result of a statement is declared in the parent block, then move it up one.
 /// </summary>
 /// <param name="parent"></param>
 /// <param name="item"></param>
 /// <returns></returns>
 private static bool MoveDeclaredResultsUp(IStatementCompound parent, IStatement item)
 {
     if (item is ICMStatementInfo && parent is IBookingStatementBlock)
     {
         var results           = (item as ICMStatementInfo).ResultVariables;
         var booking           = (parent as IBookingStatementBlock);
         var declaredVariables = new HashSet <string>(booking.DeclaredVariables.Select(p => p.RawValue));
         var declaredResults   = results.Intersect(declaredVariables).ToArray();
         foreach (var varToMove in declaredResults)
         {
             var declVarToMove = booking.DeclaredVariables.Where(p => p.RawValue == varToMove).First();
             booking.Remove(declVarToMove);
             if (!(AddBookingToParentOf(parent, declVarToMove)))
             {
                 booking.Add(declVarToMove);
                 return(false);
             }
         }
     }
     return(true);
 }
Ejemplo n.º 20
0
        public static IStatementCompound GetDeepestStatementLevel(IStatementCompound target)
        {
            IStatementCompound result = target;

            IStatementCompound last = result;

            while (last != null)
            {
                result = last;
                if (result.Statements == null)
                {
                    last = null;
                }
                else
                {
                    last = result.Statements.LastOrDefault() as IStatementCompound;
                }
            }

            return(result);
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Given a block of code, try to find statements that should be lifted up. For each statement
        /// that we find, see if there is one in the list that is "identical" - in short - already there.
        /// </summary>
        /// <param name="block">Examine this block for statements that can be lifted</param>
        /// <param name="codeStack">The list of parents where we might put this statement</param>
        private static void VisitCodeBlock(IStatementCompound block)
        {
            // Do decent first scan.
            foreach (var s in block.Statements.RetryFromStartIfModified())
            {
                if (s is IStatementCompound)
                {
                    VisitCodeBlock(s as IStatementCompound);
                }
            }

            // Now look at each item in the block and see if we can't find something above us that contains
            // the very same thing. In order to pop any statement up we must
            // 1. Be able to move it to the front of whatever block we are in
            // 2. Find a statement previous to this block above us that will combine with it.

            foreach (var s in block.Statements.RetryFromStartIfModified())
            {
                FindEquivalentAboveAndCombine(block, s);
            }
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Move to the first one, seeing if we can combine as we go.
        /// We will attempt two things:
        /// 1. Is the statement above the "same"? If so, try to eliminate the down-level statement.
        /// 2. Can it be combined?
        /// </summary>
        /// <param name="statements"></param>
        /// <param name="item"></param>
        private static bool MoveFirstWithCombine(IStatementCompound statements, IStatement item, ICodeOptimizationService opter)
        {
            // First, move this forward as far as we can, and try to combine as we go.
            var previousStatements = statements.Statements.TakeWhile(s => s != item);

            // Now, see if we can move past each statement. If we can, see if they can be combined.
            foreach (var s in previousStatements.Reverse())
            {
                if (MakeStatmentsEquivalent(s, item))
                {
                    return(true);
                }
                else if (StatementCommutes(s, item))
                {
                    if (s.TryCombineStatement(item, opter))
                    {
                        statements.Remove(item);
                        return(true);
                    }
                }
            }

            return(false);
        }
Ejemplo n.º 23
0
 /// <summary>
 /// s is in some code block in parent. Find the statement in parent that contains (or is) s.
 /// </summary>
 /// <param name="parent"></param>
 /// <param name="s"></param>
 /// <returns></returns>
 private static IStatement FindStatementHolder(IStatementCompound parent, IStatement s)
 {
     var finalParent = s;
     while (finalParent != null && finalParent != parent)
     {
         finalParent = finalParent.Parent;
     }
     if (finalParent == null)
         throw new ArgumentException("Statement s does not seem to be contained in parent");
     return finalParent;
 }
Ejemplo n.º 24
0
        /// <summary>
        /// We have a statement. Loop down through everything and see if we can't find
        /// another statement that will "take" it.
        /// </summary>
        /// <param name="s"></param>
        /// <param name="codeStack"></param>
        /// <returns></returns>
        private static IStatementCompound MoveStatementIntoCodeStack(IStatementCompound parent, IStatement s, IStatementCompound[] codeStack)
        {
            // Never move a statement that doesn't want to move. :-)
            if (s is ICMStatementInfo)
            {
                if ((s as ICMStatementInfo).NeverLift)
                    return null;
            }

            // Walk the code stack and find someone that can take us.

            foreach (var stack in codeStack)
            {
                var r = stack.CombineAndMark(s, s.Parent as IBookingStatementBlock, false);
                if (r != null)
                {
                    parent.Remove(s);

                    // During the CombineAndMark there is a chance that a declaration has been orphaned.
                    // If aBoolean_23 was declared in parent, it may also be declared up where it was moved to.
                    // If that is the case, we need to remove it.
                    if (parent is IBookingStatementBlock && r.Parent is IBookingStatementBlock)
                    {
                        var newParent = r.Parent as IBookingStatementBlock;
                        var oldParent = parent as IBookingStatementBlock;

                        var varsToRemove = from declVar in oldParent.DeclaredVariables
                                           from parVars in newParent.DeclaredVariables
                                           where declVar.ParameterName == parVars.ParameterName
                                           select declVar;
                        foreach (var declVar in varsToRemove.ToArray())
                        {
                            oldParent.Remove(declVar);
                        }
                    }

                    // We have to be a little careful here. The statement should be added at the right
                    // place. Since the statement works inside parent, and it works inside stack, then
                    // it should work in stack, just before parent.

                    var stackStatement = FindStatementHolder(stack, parent);
                    if (!stack.IsBefore(r, parent))
                    {
                        stack.Remove(r);
                        stack.AddBefore(r, parent);
                    }

                    return stack;
                }
            }
            return null;
        }
        /// <summary>
        /// Find a statement that may be inside a compound statement - return the top level statement that
        /// contains it. Throw if we can't find it.
        /// </summary>
        /// <param name="block"></param>
        /// <param name="statement"></param>
        /// <returns></returns>
        private IStatement findStatementThatContains(IStatementCompound block, IStatement statement)
        {
            var m = block.Statements.Where(s => ContainsStatement(s, statement)).FirstOrDefault();
            if (m == null)
                throw new ArgumentException("Unable to find the requested statement in the block");

            return m;
        }
        /// <summary>
        /// Given a statement in an compound block, return the order it is. Or throw if we can't find it.
        /// </summary>
        /// <param name="blockWithoutModified"></param>
        /// <param name="statement"></param>
        /// <returns></returns>
        private int findStatementIndex(IStatementCompound block, IStatement statement)
        {
            var r = from s in block.Statements.Zip(Enumerable.Range(1, 5000), (st, cnt) => Tuple.Create(st, cnt))
                    where s.Item1 == statement
                    select s;
            var match = r.FirstOrDefault();
            if (match == null)
                throw new ArgumentException("Unable to find the statement in the sequence");

            return match.Item2;
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Move to the first one, seeing if we can combine as we go.
        /// We will attempt two things:
        /// 1. Is the statement above the "same"? If so, try to eliminate the down-level statement.
        /// 2. Can it be combined?
        /// </summary>
        /// <param name="statements"></param>
        /// <param name="item"></param>
        private static bool MoveFirstWithCombine(IStatementCompound statements, IStatement item, ICodeOptimizationService opter)
        {
            // First, move this forward as far as we can, and try to combine as we go.
            var previousStatements = statements.Statements.TakeWhile(s => s != item);

            // Now, see if we can move past each statement. If we can, see if they can be combined.
            foreach (var s in previousStatements.Reverse())
            {
                if (MakeStatmentsEquivalent(s, item))
                {
                    return true;
                }
                else if (StatementCommutes(s, item))
                {
                    if (s.TryCombineStatement(item, opter))
                    {
                        statements.Remove(item);
                        return true;
                    }
                }
            }

            return false;
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Are we allowed to move this statement to be the first statement in this block?
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        private static bool MoveToFirst(IStatementCompound parent, IStatement item)
        {
            // If we can't move, then don't.
            if ((item as ICMStatementInfo).NeverLift)
                return false;

            // Loop through each statement, and see if we can go past each one.

            foreach (var cStatement in parent.Statements)
            {
                if (cStatement == item)
                    return true;
                if (!StatementCommutes(cStatement, item))
                {
                    return false;
                }
            }

            // That is weird. It never appeared here!
            throw new InvalidOperationException();
        }
Ejemplo n.º 29
0
 /// <summary>
 /// See if we can't propagate this up, trying to combine it or bubble it up if there is something identical further up.
 /// </summary>
 /// <param name="statements"></param>
 /// <param name="item"></param>
 /// <param name="opter"></param>
 /// <returns></returns>
 private static bool BubleUpAndCombine(IStatementCompound statements, IStatement item, ICodeOptimizationService opter)
 {
     return(MoveFirstWithCombine(statements, item, opter));
 }
Ejemplo n.º 30
0
 /// <summary>
 /// See if we can't propagate this up, trying to combine it or bubble it up if there is something identical further up.
 /// </summary>
 /// <param name="statements"></param>
 /// <param name="item"></param>
 /// <param name="opter"></param>
 /// <returns></returns>
 private static bool BubleUpAndCombine(IStatementCompound statements, IStatement item, ICodeOptimizationService opter)
 {
     return MoveFirstWithCombine(statements, item, opter);
 }
Ejemplo n.º 31
0
        /// <summary>
        /// Add a statement to the current "cursor" point.
        /// </summary>
        /// <param name="s"></param>
        public void Add(IStatement s)
        {
            if (s == null)
            {
                throw new ArgumentNullException("Cannot add a statement that is null");
            }

            CurrentScopePointer.Add(s);

            ///
            /// Change the statement scope if there something that goes down a level.
            /// 

            if (s is IBookingStatementBlock)
            {
                _scopeState.Push(CurrentScope);
            }

            if (s is IStatementCompound)
                CurrentScopePointer = s as IStatementCompound;
            if (s is IBookingStatementBlock)
            {
                PreviousDeclarationScopePointer = CurrentDeclarationScopePointer;
                CurrentDeclarationScopePointer = s as IBookingStatementBlock;
                Depth++;
            }
        }
Ejemplo n.º 32
0
 /// <summary>
 /// Remember the code body for later use, along with the result that we will be
 /// returning.
 /// </summary>
 /// <param name="statements"></param>
 /// <param name="resultExpression"></param>
 public void SetCodeBody(IStatementCompound statements)
 {
     StatementBlock = statements;
 }
Ejemplo n.º 33
0
        /// <summary>
        /// Add in the code blocks. Must not be null. We will do our best to combine query
        /// blocks into one big one! So watch it! :-)
        /// </summary>
        /// <param name="codeBlocks"></param>
        internal void AddQueryBlocks(IStatementCompound[] codeBlocks)
        {
            if (codeBlocks == null || codeBlocks.Any(i => i == null) || codeBlocks.Length == 0)
                throw new ArgumentException("Queries must have code blocks and they can't be null and there must be at least one");

            foreach (var statement in codeBlocks)
            {
                bool combined = false;
                foreach (var qb in _queryBlocks)
                {
                    combined = qb.TryCombineStatement(statement, null);
                    if (combined)
                        break;
                }

                if (!combined)
                    _queryBlocks.Add(statement);
            }
        }
Ejemplo n.º 34
0
        /// <summary>
        /// sToPop is a member of block, and can be or is the first statement. We see if we can pop it up
        /// a level, and then start a scan for an equivalent statement, marching up the list. If we
        /// find an equivalent statement, we will perform the combination and removal.
        /// </summary>
        /// <param name="block">The block of statements that holds sToPop</param>
        /// <param name="sToPop">The statement to try to up level.</param>
        /// <param name="previousStatements">Statements before this one in this block. This block might not actually contain this statement, in which case we must have this!</param>
        /// <param name="followingStatements">Statements after this one in this block. This block might not actually contain this statement, in which case we must have this!</param>
        /// <returns>True if something was done to the statement, false if we aborted for whatever reason.</returns>
        private static bool FindEquivalentAboveAndCombine(IStatementCompound block, IStatement sToPop,
            IEnumerable<IStatement> previousStatements = null,
            IEnumerable<IStatement> followingStatements = null,
            IStatement betweenStatement = null
            )
        {
            // Can we combine these guys? This is when one sits in the other.
            if (!(block is IStatementLoop) && block.TryCombineStatement(sToPop, new BlockRenamer(sToPop.Parent.FindBookingParent(), block.FindBookingParent())))
            {
                sToPop.FindCompoundParent().Remove(sToPop);
                return false;
            }


            // If we can't get data flow information about a statement, then we can't do anything.
            var sInfo = sToPop as ICMStatementInfo;
            if (sInfo == null)
            {
                return false;
            }

            // For this next step we need to fetch the list of statements above us. Either it has
            // been supplied to us, or we will have to generate it.
            if (previousStatements == null)
            {
                previousStatements = block.Statements.TakeWhile(s => s != sInfo).Reverse();
                followingStatements = block.Statements.SkipWhile(s => s != sInfo).Skip(1);
                betweenStatement = sToPop;
            }

            // Make sure we can get the statement to the top of the block. As we move it
            // forward, we want to also see if we can combine it in a straight-up way
            // with each statement as we go by it.
            bool madeItToTheFront = true;
            foreach (var prevStatement in previousStatements)
            {
                if (MakeStatmentsEquivalent(prevStatement, sToPop))
                {
                    return true;
                }
                if (!StatementCommutes(prevStatement, sToPop))
                {
                    madeItToTheFront = false;
                }
            }

            // Next, lets see if there isn't a statement *after* this one that we can combine it with. However,
            // to do this, we have to move the statements *after* forward previous to this one. So a little painful.
            // No need to do this if we working at the level of the statement: this ground will automatically be covered
            // later in the loop.
            if (betweenStatement != sToPop && betweenStatement is ICMCompoundStatementInfo)
            {
                foreach (var followStatement in followingStatements)
                {
                    if (followStatement is ICMStatementInfo)
                    {
                        // Can we commute this statement from where it is to before the statement we are working on?
                        if (StatementCommutes(followStatement, followingStatements.TakeWhile(f => f != followStatement).Reverse()))
                        {
                            // Next is the tricky part. We are now sitting one down from the block that contains
                            // the sToPop statement. Can we move it up above the block? If the statements are the same,
                            // then we know it is ok to move it pass all the contents of the block (otherwise we would not be here).
                            // But what if it is an if statement, and the if statement depends on something in sToPop? Then
                            // we can't move it.
                            var betweenAsBlock = betweenStatement as ICMCompoundStatementInfo;
                            if (betweenAsBlock.CommutesWithGatingExpressions(followStatement as ICMStatementInfo))
                            {
                                if (MakeStatmentsEquivalent(followStatement, sToPop))
                                {
                                    // To keep continuity and unitarity, this follow statement now has to be moved before the betweenStatement!
                                    var parent = followStatement.Parent as IStatementCompound;
                                    parent.Remove(followStatement);
                                    parent.AddBefore(followStatement, betweenStatement);
                                    return true;
                                }
                            }
                        }
                    }
                }
            }

            // Now the only option left is to pop it up one level. We can do that only if we were able to
            // shift the statement all the way to the front.
            if (!madeItToTheFront)
            {
                return false;
            }

            // The statement can be moved to the top of the block, and isn't the same as
            // anything else we passed. Can we pull it out one level?
            // The key to answering this is: are all the variables it needs defined at the next
            // level up? And if not, are the missing ones simply declared down here and need to be moved up?
            var nParent = block.Parent.FindBookingParent();
            if (nParent == null)
            {
                return false;
            }

            var sDependent = sInfo.DependentVariables;
            var availAtParent = nParent.AllDeclaredVariables.Select(n => n.RawValue).Intersect(sDependent);
            IEnumerable<string> declaredInBlock = Enumerable.Empty<string>();
            if (block is IBookingStatementBlock)
            {
                declaredInBlock = (block as IBookingStatementBlock).DeclaredVariables.Select(np => np.RawValue).Intersect(sDependent);
            }
            if ((availAtParent.Count() + declaredInBlock.Count()) != sDependent.Count())
            {
                return false;
            }

            // If this there is a variable declared in the block internally, then we can't lift it up and out.
            // Also make sure that we can lift it past if there is a gating expression.
            if (block is ICMCompoundStatementInfo)
            {
                var compoundInfo = block as ICMCompoundStatementInfo;
                if (compoundInfo.InternalResultVarialbes.Select(p => p.RawValue).Intersect(sDependent).Any())
                {
                    return false;
                }
                if (!compoundInfo.CommutesWithGatingExpressions(sInfo))
                {
                    return false;
                }
            }

            // If we are going to try to lift past a loop, we have to make sure the statement is idempotent.
            if (block is IStatementLoop && !StatementIdempotent(sToPop))
            {
                return false;
            }

            // And the next figure out where we are in the list of statements.
            var nPrevStatements = nParent.Statements.TakeWhile(ps => ps != block).Reverse();
            var nFollowStatements = nParent.Statements.SkipWhile(ps => ps != block).Skip(1);

            // And repeat one level up with some tail recursion!
            var statementMoved = FindEquivalentAboveAndCombine(nParent, sToPop, nPrevStatements, nFollowStatements, block);

            // There is one other thing to try. If we couldn't move it above us (e.g. statementMoved is false), it could be
            // we can leave the statement here, rather than in its original location.
            if (!statementMoved)
            {
                var parentsToBlock = sToPop
                    .WalkParents(false)
                    .TakeWhile(s => s != block)
                    .Concat(new IStatementCompound[] { block }).ToArray();

                // If no lifting out of some statement between us and the statement, then don't do it.
                var parentsNotOK = parentsToBlock
                    .Where(s => s is ICMCompoundStatementInfo)
                    .Cast<ICMCompoundStatementInfo>()
                    .Where(s => !s.AllowNormalBubbleUp);
                if (parentsNotOK.Any())
                {
                    return false;
                }

                // The next thing we have to double check is that we can do the lifting, and nothing we are going to
                // lift is going to impact some variable.
                var dependents = sInfo.DependentVariables;
                var dependentAffected = parentsToBlock
                    .Select(p => p.CheckForVariableAsInternalResult(dependents))
                    .Where(t => t);
                if (dependentAffected.Any())
                {
                    return false;
                }

                return MoveStatement(sToPop, block);
            }

            return statementMoved;
        }
Ejemplo n.º 35
0
        /// <summary>
        /// Given a statement that has bubble-up info in it, we will try to move
        /// it up one.
        /// </summary>
        /// <param name="statements"></param>
        /// <param name="item"></param>
        /// <remarks>For now only support bubbling up one level</remarks>
        private static bool BubbleUp(IStatementCompound parent, IStatement item)
        {
            // First, is the parent statement that we can bubble up past?
            var cmpInfo = parent as ICMCompoundStatementInfo;
            if (cmpInfo == null)
                return false;

            // OK, now lets see if we can bubble it up one level.
            if (!cmpInfo.AllowNormalBubbleUp)
                return false;

            // Next job - if this isn't the first statement, then we have to
            // be able to move it past all the other statements.

            if (!MoveToFirst(parent, item))
            {
                return false;
            }

            // Finally, does this guy need anything from the compound statement?

            var declared = cmpInfo.DeclaredVariables;
            var inputs = (item as ICMStatementInfo).DependentVariables;
            var requiredDeclared = declared.Select(p => p.RawValue).Intersect(inputs);
            if (requiredDeclared.Count() > 0)
                return false;

            // And does this statement idempotent? "a = a + 1" has the side effect of altering
            // a - so if it is repeated it won't have the same result. On the other hand,
            // "a = 10" will always have the same effect. The former should not be lifted
            // out of a loop.
            if (parent is IStatementLoop
                && !StatementIdempotent(item))
                return false;

            // OK, now insert it one level up, just before the parent. MoveStatementUpOneLevel
            return MoveStatementUpOneLevel(item);
        }
Ejemplo n.º 36
0
        /// <summary>
        /// sToPop is a member of block, and can be or is the first statement. We see if we can pop it up
        /// a level, and then start a scan for an equivalent statement, marching up the list. If we
        /// find an equivalent statement, we will perform the combination and removal.
        /// </summary>
        /// <param name="block">The block of statements that holds sToPop</param>
        /// <param name="sToPop">The statement to try to up level.</param>
        /// <param name="previousStatements">Statements before this one in this block. This block might not actually contain this statement, in which case we must have this!</param>
        /// <param name="followingStatements">Statements after this one in this block. This block might not actually contain this statement, in which case we must have this!</param>
        /// <returns>True if something was done to the statement, false if we aborted for whatever reason.</returns>
        private static bool FindEquivalentAboveAndCombine(IStatementCompound block, IStatement sToPop,
                                                          IEnumerable <IStatement> previousStatements  = null,
                                                          IEnumerable <IStatement> followingStatements = null,
                                                          IStatement betweenStatement = null
                                                          )
        {
            // Can we combine these guys? This is when one sits in the other.
            if (!(block is IStatementLoop) && block.TryCombineStatement(sToPop, new BlockRenamer(sToPop.Parent.FindBookingParent(), block.FindBookingParent())))
            {
                sToPop.FindCompoundParent().Remove(sToPop);
                return(false);
            }


            // If we can't get data flow information about a statement, then we can't do anything.
            var sInfo = sToPop as ICMStatementInfo;

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

            // For this next step we need to fetch the list of statements above us. Either it has
            // been supplied to us, or we will have to generate it.
            if (previousStatements == null)
            {
                previousStatements  = block.Statements.TakeWhile(s => s != sInfo).Reverse();
                followingStatements = block.Statements.SkipWhile(s => s != sInfo).Skip(1);
                betweenStatement    = sToPop;
            }

            // Make sure we can get the statement to the top of the block. As we move it
            // forward, we want to also see if we can combine it in a straight-up way
            // with each statement as we go by it.
            bool madeItToTheFront = true;

            foreach (var prevStatement in previousStatements)
            {
                if (MakeStatmentsEquivalent(prevStatement, sToPop))
                {
                    return(true);
                }
                if (!StatementCommutes(prevStatement, sToPop))
                {
                    madeItToTheFront = false;
                }
            }

            // Next, lets see if there isn't a statement *after* this one that we can combine it with. However,
            // to do this, we have to move the statements *after* forward previous to this one. So a little painful.
            // No need to do this if we working at the level of the statement: this ground will automatically be covered
            // later in the loop.
            if (betweenStatement != sToPop && betweenStatement is ICMCompoundStatementInfo)
            {
                foreach (var followStatement in followingStatements)
                {
                    if (followStatement is ICMStatementInfo)
                    {
                        // Can we commute this statement from where it is to before the statement we are working on?
                        if (StatementCommutes(followStatement, followingStatements.TakeWhile(f => f != followStatement).Reverse()))
                        {
                            // Next is the tricky part. We are now sitting one down from the block that contains
                            // the sToPop statement. Can we move it up above the block? If the statements are the same,
                            // then we know it is ok to move it pass all the contents of the block (otherwise we would not be here).
                            // But what if it is an if statement, and the if statement depends on something in sToPop? Then
                            // we can't move it.
                            var betweenAsBlock = betweenStatement as ICMCompoundStatementInfo;
                            if (betweenAsBlock.CommutesWithGatingExpressions(followStatement as ICMStatementInfo))
                            {
                                if (MakeStatmentsEquivalent(followStatement, sToPop))
                                {
                                    // To keep continuity and unitarity, this follow statement now has to be moved before the betweenStatement!
                                    var parent = followStatement.Parent as IStatementCompound;
                                    parent.Remove(followStatement);
                                    parent.AddBefore(followStatement, betweenStatement);
                                    return(true);
                                }
                            }
                        }
                    }
                }
            }

            // Now the only option left is to pop it up one level. We can do that only if we were able to
            // shift the statement all the way to the front.
            if (!madeItToTheFront)
            {
                return(false);
            }

            // The statement can be moved to the top of the block, and isn't the same as
            // anything else we passed. Can we pull it out one level?
            // The key to answering this is: are all the variables it needs defined at the next
            // level up? And if not, are the missing ones simply declared down here and need to be moved up?
            var nParent = block.Parent.FindBookingParent();

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

            var sDependent    = sInfo.DependentVariables;
            var availAtParent = nParent.AllDeclaredVariables.Select(n => n.RawValue).Intersect(sDependent);
            IEnumerable <string> declaredInBlock = Enumerable.Empty <string>();

            if (block is IBookingStatementBlock)
            {
                declaredInBlock = (block as IBookingStatementBlock).DeclaredVariables.Select(np => np.RawValue).Intersect(sDependent);
            }
            if ((availAtParent.Count() + declaredInBlock.Count()) != sDependent.Count())
            {
                return(false);
            }

            // If this there is a variable declared in the block internally, then we can't lift it up and out.
            // Also make sure that we can lift it past if there is a gating expression.
            if (block is ICMCompoundStatementInfo)
            {
                var compoundInfo = block as ICMCompoundStatementInfo;
                if (compoundInfo.InternalResultVarialbes.Select(p => p.RawValue).Intersect(sDependent).Any())
                {
                    return(false);
                }
                if (!compoundInfo.CommutesWithGatingExpressions(sInfo))
                {
                    return(false);
                }
            }

            // If we are going to try to lift past a loop, we have to make sure the statement is idempotent.
            if (block is IStatementLoop && !StatementIdempotent(sToPop))
            {
                return(false);
            }

            // And the next figure out where we are in the list of statements.
            var nPrevStatements   = nParent.Statements.TakeWhile(ps => ps != block).Reverse();
            var nFollowStatements = nParent.Statements.SkipWhile(ps => ps != block).Skip(1);

            // And repeat one level up with some tail recursion!
            var statementMoved = FindEquivalentAboveAndCombine(nParent, sToPop, nPrevStatements, nFollowStatements, block);

            // There is one other thing to try. If we couldn't move it above us (e.g. statementMoved is false), it could be
            // we can leave the statement here, rather than in its original location.
            if (!statementMoved)
            {
                var parentsToBlock = sToPop
                                     .WalkParents(false)
                                     .TakeWhile(s => s != block)
                                     .Concat(new IStatementCompound[] { block }).ToArray();

                // If no lifting out of some statement between us and the statement, then don't do it.
                var parentsNotOK = parentsToBlock
                                   .Where(s => s is ICMCompoundStatementInfo)
                                   .Cast <ICMCompoundStatementInfo>()
                                   .Where(s => !s.AllowNormalBubbleUp);
                if (parentsNotOK.Any())
                {
                    return(false);
                }

                // The next thing we have to double check is that we can do the lifting, and nothing we are going to
                // lift is going to impact some variable.
                var dependents        = sInfo.DependentVariables;
                var dependentAffected = parentsToBlock
                                        .Select(p => p.CheckForVariableAsInternalResult(dependents))
                                        .Where(t => t);
                if (dependentAffected.Any())
                {
                    return(false);
                }

                return(MoveStatement(sToPop, block));
            }

            return(statementMoved);
        }
Ejemplo n.º 37
0
        /// <summary>
        /// Add a declaration to a booking parent, if there is one. Return true if we could.
        /// </summary>
        /// <param name="s"></param>
        /// <param name="varToDeclare"></param>
        /// <returns></returns>
        private static bool AddBookingToParentOf(IStatementCompound s, IDeclaredParameter varToDeclare)
        {
            var parent = s.Parent;
            while (parent != null)
            {
                var book = parent as IBookingStatementBlock;
                if (book != null)
                {
                    book.Add(varToDeclare);
                    return true;
                }
            }

            return false;
        }
Ejemplo n.º 38
0
 /// <summary>
 /// Remember the code body for later use, along with the result that we will be
 /// returning.
 /// </summary>
 /// <param name="statements"></param>
 /// <param name="resultExpression"></param>
 public void SetCodeBody(IStatementCompound statements)
 {
     StatementBlock = statements;
 }
Ejemplo n.º 39
0
 /// <summary>
 /// If a result of a statement is declared in the parent block, then move it up one.
 /// </summary>
 /// <param name="parent"></param>
 /// <param name="item"></param>
 /// <returns></returns>
 private static bool MoveDeclaredResultsUp(IStatementCompound parent, IStatement item)
 {
     if (item is ICMStatementInfo && parent is IBookingStatementBlock)
     {
         var results = (item as ICMStatementInfo).ResultVariables;
         var booking = (parent as IBookingStatementBlock);
         var declaredVariables = new HashSet<string>(booking.DeclaredVariables.Select(p => p.RawValue));
         var declaredResults = results.Intersect(declaredVariables).ToArray();
         foreach (var varToMove in declaredResults)
         {
             var declVarToMove = booking.DeclaredVariables.Where(p => p.RawValue == varToMove).First();
             booking.Remove(declVarToMove);
             if (!(AddBookingToParentOf(parent, declVarToMove)))
             {
                 booking.Add(declVarToMove);
                 return false;
             }
         }
     }
     return true;
 }