private bool ContainsStatement(IStatement dependencySt, IStatement ist)
 {
     if (ReferenceEquals(dependencySt, ist))
     {
         return(true);
     }
     if (dependencySt is AnyStatement)
     {
         AnyStatement anySt = (AnyStatement)dependencySt;
         bool         found = false;
         ForEachStatement(anySt, st =>
         {
             if (ContainsStatement(st, ist))
             {
                 found = true;
             }
         });
         return(found);
     }
     if (dependencySt is IExpressionStatement && ist is IExpressionStatement)
     {
         IExpressionStatement es  = (IExpressionStatement)dependencySt;
         IExpressionStatement ies = (IExpressionStatement)ist;
         return(CodeBuilder.Instance.ContainsExpression(es.Expression, ies.Expression));
     }
     return(false);
 }
        private static IStatement Replace(IStatement stmt, Converter <IStatement, IStatement> converter)
        {
            IStatement newStmt = converter(stmt);

            if (!ReferenceEquals(newStmt, stmt))
            {
                return(newStmt);
            }
            else if (stmt is AnyStatement)
            {
                AnyStatement anySt    = (AnyStatement)stmt;
                AnyStatement newAnySt = new AnyStatement();
                bool         replaced = false;
                foreach (IStatement ist in anySt.Statements)
                {
                    newStmt = Replace(ist, converter);
                    if (!ReferenceEquals(newStmt, ist))
                    {
                        replaced = true;
                    }
                    if (newStmt != null)
                    {
                        // flatten nested Any statements
                        if (newStmt is AnyStatement)
                        {
                            newAnySt.Statements.AddRange(((AnyStatement)newStmt).Statements);
                        }
                        else
                        {
                            newAnySt.Statements.Add(newStmt);
                        }
                    }
                }
                if (replaced)
                {
                    if (newAnySt.Statements.Count == 0)
                    {
                        return(null);
                    }
                    else
                    {
                        return(newAnySt);
                    }
                }
                else
                {
                    return(stmt);
                }
            }
            else
            {
                return(stmt);
            }
        }
 private void ForEachStatement(AnyStatement anySt, Action <IStatement> action)
 {
     foreach (IStatement ist in anySt.Statements)
     {
         if (ist is AnyStatement)
         {
             ForEachStatement((AnyStatement)ist, action);
         }
         else
         {
             action(ist);
         }
     }
 }
        public void AddClones(Converter <IStatement, IEnumerable <IStatement> > getClones)
        {
            List <IStatement> toRemove = new List <IStatement>();
            Dictionary <IStatement, DependencyType> toAdd       = new Dictionary <IStatement, DependencyType>(new IdentityComparer <IStatement>());
            Dictionary <IStatement, IOffsetInfo>    toAddOffset = new Dictionary <IStatement, IOffsetInfo>(new IdentityComparer <IStatement>());

            foreach (KeyValuePair <IStatement, DependencyType> entry in dependencyTypeOf)
            {
                IStatement stmt = entry.Key;
                if (stmt is AnyStatement)
                {
                    AnyStatement anySt    = (AnyStatement)stmt;
                    AnyStatement newAnySt = new AnyStatement();
                    bool         changed  = false;
                    foreach (IStatement ist in anySt.Statements)
                    {
                        newAnySt.Statements.Add(ist);
                        var clones = getClones(ist);
                        if (clones != null)
                        {
                            changed = true;
                            // flatten nested Any statements
                            newAnySt.Statements.AddRange(clones);
                        }
                    }
                    if (changed)
                    {
                        toRemove.Add(stmt);
                        toAdd.Add(newAnySt, entry.Value);
                    }
                }
                else
                {
                    var clones = getClones(stmt);
                    if (clones != null)
                    {
                        DependencyType type = entry.Value;
                        IOffsetInfo    offsetIndices;
                        offsetIndexOf.TryGetValue(stmt, out offsetIndices);
                        if (type > 0)
                        {
                            foreach (var clone in clones)
                            {
                                Add(toAdd, type, clone);
                                if (offsetIndices != default(OffsetInfo))
                                {
                                    AddOffsetIndices(toAddOffset, offsetIndices, clone);
                                }
                            }
                        }
                    }
                }
            }
            foreach (IStatement ist in toRemove)
            {
                dependencyTypeOf.Remove(ist);
                offsetIndexOf.Remove(ist);
            }
            foreach (KeyValuePair <IStatement, DependencyType> entry in toAdd)
            {
                Add(entry.Value, entry.Key);
            }
            foreach (KeyValuePair <IStatement, IOffsetInfo> entry in toAddOffset)
            {
                AddOffsetIndices(entry.Value, entry.Key);
            }
        }
        public void Replace(Converter <IStatement, IStatement> converter)
        {
            List <IStatement> toRemove = new List <IStatement>();
            Dictionary <IStatement, DependencyType> toAdd       = new Dictionary <IStatement, DependencyType>(new IdentityComparer <IStatement>());
            Dictionary <IStatement, IOffsetInfo>    toAddOffset = new Dictionary <IStatement, IOffsetInfo>(new IdentityComparer <IStatement>());

            foreach (KeyValuePair <IStatement, DependencyType> entry in dependencyTypeOf)
            {
                IStatement stmt    = entry.Key;
                IStatement newStmt = Replace(stmt, converter);
                if (!ReferenceEquals(newStmt, stmt))
                {
                    toRemove.Add(stmt);
                    if (newStmt != null)
                    {
                        DependencyType type = entry.Value;
                        IOffsetInfo    offsetIndices;
                        offsetIndexOf.TryGetValue(stmt, out offsetIndices);
                        if (newStmt is AnyStatement)
                        {
                            AnyStatement   anySt     = (AnyStatement)newStmt;
                            DependencyType anyTypes  = DependencyType.Requirement | DependencyType.SkipIfUniform;
                            DependencyType otherType = type & ~anyTypes;
                            if (otherType > 0)
                            {
                                // must split Any for these types
                                ForEachStatement(anySt, ist =>
                                {
                                    Add(toAdd, otherType, ist);
                                    if (offsetIndices != default(OffsetInfo))
                                    {
                                        AddOffsetIndices(toAddOffset, offsetIndices, ist);
                                    }
                                });
                                type &= anyTypes;
                            }
                        }
                        if (type > 0)
                        {
                            Add(toAdd, type, newStmt);
                            if (offsetIndices != default(OffsetInfo))
                            {
                                AddOffsetIndices(toAddOffset, offsetIndices, newStmt);
                            }
                        }
                    }
                }
            }
            foreach (IStatement ist in toRemove)
            {
                dependencyTypeOf.Remove(ist);
                offsetIndexOf.Remove(ist);
            }
            foreach (KeyValuePair <IStatement, DependencyType> entry in toAdd)
            {
                Add(entry.Value, entry.Key);
            }
            foreach (KeyValuePair <IStatement, IOffsetInfo> entry in toAddOffset)
            {
                AddOffsetIndices(entry.Value, entry.Key);
            }
        }