Пример #1
0
        /// <summary>
        /// Prepares operation for every descendant index of target array.
        /// </summary>
        /// <param name="operation">The operation.</param>
        /// <returns>Array where the input arrays is merged into.</returns>
        private void mergeArrays(MergeOperation operation)
        {
            AssociativeArray    targetArray      = Structure.GetArray(operation.TargetIndex);
            ArrayDescriptor     targetDescriptor = Structure.GetDescriptor(targetArray);
            ContainerOperations collectIndexes   = new ContainerOperations(this, targetDescriptor.Builder(), operation.TargetIndex, targetDescriptor.UnknownIndex);

            foreach (var operationData in operation.Indexes)
            {
                MemoryIndex index    = operationData.Item1;
                Snapshot    snapshot = operationData.Item2;

                AssociativeArray arrayValue;
                if (snapshot.Structure.TryGetArray(index, out arrayValue))
                {
                    ArrayDescriptor descriptor = snapshot.Structure.GetDescriptor(arrayValue);
                    collectIndexes.AddContainer(descriptor, snapshot);
                }
                else
                {
                    collectIndexes.SetUndefined();
                }
            }

            collectIndexes.MergeContainers();
        }
Пример #2
0
        /// <summary>
        /// Creates merge operations for all indexes in the target collection. Source indexes for the operation are
        /// retreived from the source collections. When there is missing index in some collection the operation set
        /// to undefined.
        ///
        /// This method is for both phases of analysis.
        /// </summary>
        public void MergeContainers()
        {
            // Process all names which has unassociated index and creates one
            foreach (string indexName in undefinedIndexes)
            {
                targetContainer.Indexes[indexName] = targetIndex.CreateIndex(indexName);
            }

            foreach (var index in targetContainer.Indexes)
            {
                MergeOperation operation = new MergeOperation(index.Value);
                worker.addOperation(operation);

                if (isUndefined)
                {
                    operation.SetUndefined();
                }

                foreach (var source in sources)
                {
                    ReadonlyIndexContainer container = source.Item1;
                    Snapshot snapshot = source.Item2;

                    MemoryIndex containerIndex;
                    if (container.Indexes.TryGetValue(index.Key, out containerIndex))
                    {
                        operation.Add(containerIndex, snapshot);
                    }
                    else
                    {
                        operation.Add(container.UnknownIndex, snapshot);
                    }
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Processes single merge operation - prepares all valid values and alias informations from the source indexes.
        /// When the source indexes contains some array values prepares operation for every descendant index and merge the
        /// array into one which will be stored in the target memory entry.
        /// </summary>
        /// <param name="operation">The operation.</param>
        private void processMergeOperation(MergeOperation operation)
        {
            HashSet <Value> values = new HashSet <Value>();

            foreach (var operationData in operation.Indexes)
            {
                MemoryIndex index    = operationData.Item1;
                Snapshot    snapshot = operationData.Item2;

                MemoryEntry entry = snapshot.Infos.GetMemoryEntry(index);
                HashSetTools.AddAll(values, entry.PossibleValues);
            }

            if (Structure.HasArray(operation.TargetIndex))
            {
                mergeArrays(operation);
            }

            if (operation.IsUndefined)
            {
                values.Add(targetSnapshot.UndefinedValue);
            }

            Structure.SetMemoryEntry(operation.TargetIndex, new MemoryEntry(values));
        }
Пример #4
0
        private MergeOperation getOperation()
        {
            MergeOperation operation = operationStack.First.Value;

            operationStack.RemoveFirst();

            return(operation);
        }
Пример #5
0
        private void processMerge()
        {
            while (operationStack.Count > 0)
            {
                MergeOperation operation = getOperation();

                processMergeOperation(operation);
            }
        }
Пример #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ContainerOperations"/> class.
        /// </summary>
        /// <param name="worker">The worker.</param>
        /// <param name="targetContainer">The target container.</param>
        /// <param name="targetIndex">Index of the target.</param>
        /// <param name="unknownIndex">Index of the unknown.</param>
        public ContainerOperations(
            IMergeWorker worker,
            IWriteableIndexContainer targetContainer,
            MemoryIndex targetIndex,
            MemoryIndex unknownIndex)
        {
            this.targetContainer = targetContainer;
            this.worker          = worker;
            this.targetIndex     = targetIndex;

            unknownOperation = new MergeOperation(unknownIndex);
            worker.addOperation(unknownOperation);
        }
Пример #7
0
        /// <summary>
        /// Prepares operation for every descendant index and merge the array into one which will be
        /// stored in the target memory entry.
        /// </summary>
        /// <param name="operation">The operation.</param>
        /// <returns>Array where the input arrays is merged into.</returns>
        private Value mergeArrays(MergeOperation operation)
        {
            ArrayDescriptorBuilder builder = new ArrayDescriptorBuilder();

            builder.SetParentVariable(operation.TargetIndex);
            builder.SetUnknownField(operation.TargetIndex.CreateUnknownIndex());

            ContainerOperations collectVariables = new ContainerOperations(this, builder, operation.TargetIndex, builder.UnknownIndex);

            // Collecting possible indexes of merged array
            AssociativeArray targetArray = null;

            foreach (var operationData in operation.Indexes)
            {
                MemoryIndex index    = operationData.Item1;
                Snapshot    snapshot = operationData.Item2;

                AssociativeArray arrayValue;
                if (snapshot.Structure.TryGetArray(index, out arrayValue))
                {
                    // Target array value will be the firs one
                    if (targetArray == null)
                    {
                        if (index.Equals(operation.TargetIndex))
                        {
                            targetArray = arrayValue;
                        }
                    }

                    ArrayDescriptor descriptor = snapshot.Structure.GetDescriptor(arrayValue);
                    collectVariables.CollectIndexes(snapshot, index, descriptor);
                }
                else
                {
                    collectVariables.SetUndefined();
                }
            }

            if (targetArray == null)
            {
                targetArray = targetSnapshot.CreateArray();
            }
            builder.SetArrayValue(targetArray);

            collectVariables.MergeContainers();

            Structure.SetArray(operation.TargetIndex, targetArray);
            Structure.SetDescriptor(targetArray, builder.Build());

            return(targetArray);
        }
Пример #8
0
        public void MergeIndexes(MemoryIndex targetIndex, MemoryIndex sourceIndex)
        {
            if (!sourceIndex.IsPrefixOf(targetIndex) && !targetIndex.IsPrefixOf(sourceIndex))
            {
                MergeOperation operation = new MergeOperation(targetIndex);
                operation.Add(targetIndex, targetSnapshot);
                operation.Add(sourceIndex, targetSnapshot);
                operation.IsRoot = true;
                addOperation(operation);

                arrayCount = 2;

                processMerge();
            }
        }
Пример #9
0
        /// <summary>
        /// Main method of merge algorithm.
        ///
        /// iI first phase prepares new empty data collection. Then collects all root memory locations and
        /// prepares their operations. As the final step process all merge operations which traverses the
        /// memory tree and merges data from all source indexes.
        /// </summary>
        internal void Merge()
        {
            ContainerOperations[] collectVariables = new ContainerOperations[targetSnapshot.CallLevel + 1];
            ContainerOperations[] collectControl   = new ContainerOperations[targetSnapshot.CallLevel + 1];
            MergeOperation        returnOperation  = new MergeOperation();

            for (int x = 0; x <= targetSnapshot.CallLevel; x++)
            {
                IndexContainer variables = Structure.Variables[x];
                collectVariables[x] = new ContainerOperations(this, variables, variables.UnknownIndex, variables.UnknownIndex);

                IndexContainer control = Structure.ContolVariables[x];
                collectControl[x] = new ContainerOperations(this, control, control.UnknownIndex, control.UnknownIndex);
            }

            foreach (Snapshot snapshot in sourceSnapshots)
            {
                for (int sourceLevel = 0, targetLevel = 0; targetLevel <= targetSnapshot.CallLevel; sourceLevel++, targetLevel++)
                {
                    if (sourceLevel == snapshot.CallLevel && snapshot.CallLevel != targetSnapshot.CallLevel)
                    {
                        if (isCallMerge)
                        {
                            break;
                        }
                        else
                        {
                            targetLevel = targetSnapshot.CallLevel;
                        }
                    }

                    collectVariables[targetLevel].AddContainer(snapshot.Structure.Variables[sourceLevel], snapshot);
                    collectControl[targetLevel].AddContainer(snapshot.Structure.ContolVariables[sourceLevel], snapshot);
                }
            }

            mergeObjects();

            for (int x = 0; x <= targetSnapshot.CallLevel; x++)
            {
                collectVariables[x].MergeContainers();
                collectControl[x].MergeContainers();
                mergeTemporary(x);
            }

            processMerge();
        }
Пример #10
0
        /// <summary>
        /// Gets all values which can be in target memory entry. If sources contains some arrays merge this arrays together
        /// and traverse their indexes.
        /// </summary>
        /// <param name="operation">The operation.</param>
        /// <param name="visitor">The visitor.</param>
        /// <returns>Values for the target memory entry.</returns>
        private HashSet <Value> getValues(MergeOperation operation, CollectComposedValuesVisitor visitor)
        {
            HashSet <Value> values        = visitor.Values;
            bool            noScalarValue = visitor.Values.Count == 0;

            if (visitor.Arrays.Count > 0)
            {
                values.Add(mergeArrays(operation));
            }

            foreach (ObjectValue value in visitor.Objects)
            {
                values.Add(value);
            }

            return(values);
        }
Пример #11
0
        /// <summary>
        /// Creates merge operations for all temporary indexes in the target structure.
        /// </summary>
        /// <param name="index">The index.</param>
        private void mergeTemporary(int index)
        {
            foreach (var temp in Structure.Temporary[index])
            {
                MergeOperation operation = new MergeOperation(temp);
                addOperation(operation);

                foreach (Snapshot snapshot in sourceSnapshots)
                {
                    if (snapshot.Structure.IsDefined(temp))
                    {
                        operation.Add(temp, snapshot);
                    }
                    else
                    {
                        operation.SetUndefined();
                    }
                }
            }
        }
Пример #12
0
        /// <summary>
        /// Processes single merge operation - prepares all valid values and alias informations from the source indexes.
        /// When the source indexes contains some array values prepares operation for every descendant index and merge the
        /// array into one which will be stored in the target memory entry.
        /// </summary>
        /// <param name="operation">The operation.</param>
        private void processMergeOperation(MergeOperation operation)
        {
            CollectComposedValuesVisitor visitor    = new CollectComposedValuesVisitor();
            ReferenceCollector           references = new ReferenceCollector();

            // Collect all data from source indexes
            foreach (var operationData in operation.Indexes)
            {
                MemoryIndex index    = operationData.Item1;
                Snapshot    snapshot = operationData.Item2;

                MemoryEntry entry = snapshot.Structure.GetMemoryEntry(index);
                visitor.VisitMemoryEntry(entry);

                MemoryAlias aliases;
                if (snapshot.Structure.TryGetAliases(index, out aliases))
                {
                    references.CollectMust(aliases.MustAliasses, targetSnapshot.CallLevel);
                    references.CollectMay(aliases.MayAliasses, targetSnapshot.CallLevel);
                }
                else
                {
                    references.InvalidateMust();
                }
            }

            references.SetAliases(operation.TargetIndex, this, !operation.IsUndefined);

            //repares the set of values - array values are traversed
            HashSet <Value> values = getValues(operation, visitor);

            // If some index in operation can be undefined add undefined value into result
            if (operation.IsUndefined)
            {
                values.Add(targetSnapshot.UndefinedValue);
            }

            Structure.SetMemoryEntry(operation.TargetIndex, new MemoryEntry(values));
            Structure.SetObjects(operation.TargetIndex, new ObjectValueContainer(visitor.Objects));
        }
Пример #13
0
        private void processMergeOperation(MergeOperation operation)
        {
            CollectComposedValuesVisitor visitor    = new CollectComposedValuesVisitor();
            ReferenceCollector           references = new ReferenceCollector();

            foreach (var item in operation.Indexes)
            {
                Snapshot    snapshot = item.Item2;
                MemoryIndex index    = item.Item1;
                MemoryEntry entry    = snapshot.Structure.GetMemoryEntry(index);
                visitor.VisitMemoryEntry(entry);

                MemoryAlias aliases;
                if (snapshot.Structure.TryGetAliases(index, out aliases))
                {
                    references.CollectMust(aliases.MustAliasses, snapshot.CallLevel);
                    references.CollectMay(aliases.MayAliasses, snapshot.CallLevel);
                }
                else
                {
                    references.InvalidateMust();
                }
            }

            if (references.HasAliases && !operation.IsRoot)
            {
                if (!operation.IsUndefined && operation.Indexes.Count == 1 && references.HasMustAliases)
                {
                    if (targetSnapshot == operation.Indexes.First().Item2)
                    {
                        references.AddMustAlias(operation.Indexes.First().Item1);
                    }
                }
                else
                {
                    HashSet <MemoryIndex> referenceIndexes = new HashSet <MemoryIndex>();
                    foreach (var item in operation.Indexes)
                    {
                        MemoryIndex index    = item.Item1;
                        Snapshot    snapshot = item.Item2;

                        if (index != operation.TargetIndex && targetSnapshot == snapshot)
                        {
                            referenceIndexes.Add(index);
                        }
                    }

                    references.CollectMay(referenceIndexes, targetSnapshot.CallLevel);
                }
            }

            references.SetAliases(operation.TargetIndex, targetSnapshot, !operation.IsUndefined);

            HashSet <Value> values = getValues(operation.TargetIndex, visitor, operation.IsUndefined);

            if (operation.IsUndefined)
            {
                values.Add(targetSnapshot.UndefinedValue);
            }

            targetSnapshot.Structure.SetMemoryEntry(operation.TargetIndex, new MemoryEntry(values));
        }
Пример #14
0
        /// <summary>
        /// Main method of merge algorithm.
        ///
        /// in first phase prepares new empty structure and data collections. Then collects all root memory locations
        /// and prepares their operations. As the final step process all merge operations which traverses the memory tree
        /// and creates new memory locations in target structure with the data from all source indexes.
        /// </summary>
        internal void Merge()
        {
            ContainerOperations[] collectVariables = new ContainerOperations[targetSnapshot.CallLevel + 1];
            ContainerOperations[] collectControl   = new ContainerOperations[targetSnapshot.CallLevel + 1];
            MergeOperation        returnOperation  = new MergeOperation();

            // Prepares empty structure for target snapshot
            for (int x = 0; x <= targetSnapshot.CallLevel; x++)
            {
                IndexContainer variables = new IndexContainer(VariableIndex.CreateUnknown(x));
                Structure.Variables[x] = variables;
                collectVariables[x]    = new ContainerOperations(this, variables, variables.UnknownIndex, variables.UnknownIndex);

                IndexContainer control = new IndexContainer(ControlIndex.CreateUnknown(x));
                Structure.ContolVariables[x] = control;
                collectControl[x]            = new ContainerOperations(this, control, control.UnknownIndex, control.UnknownIndex);

                Structure.Temporary[x] = new IndexSet <TemporaryIndex>();
                Structure.Arrays[x]    = new IndexSet <AssociativeArray>();
            }

            // Collects all objects and root locations from the source objects
            foreach (Snapshot snapshot in sourceSnapshots)
            {
                collectObjects(snapshot);

                for (int sourceLevel = 0, targetLevel = 0; targetLevel <= targetSnapshot.CallLevel; sourceLevel++, targetLevel++)
                {
                    // Local levels of snaphot has to be merged together no matter to call level of each snapshot.
                    if (sourceLevel == snapshot.CallLevel && snapshot.CallLevel != targetSnapshot.CallLevel)
                    {
                        if (isCallMerge)
                        {
                            // When this is the call merge the local level is forgotten
                            break;
                        }
                        else
                        {
                            targetLevel = targetSnapshot.CallLevel;
                        }
                    }

                    // Gets all root locations
                    collectVariables[targetLevel].CollectIndexes(snapshot, Structure.Variables[targetLevel].UnknownIndex, snapshot.Structure.Variables[sourceLevel]);
                    collectControl[targetLevel].CollectIndexes(snapshot, Structure.ContolVariables[targetLevel].UnknownIndex, snapshot.Structure.ContolVariables[sourceLevel]);
                    collectTemporary(snapshot, sourceLevel, targetLevel);
                }

                mergeDeclarations(Structure.FunctionDecl, snapshot.Structure.FunctionDecl);
                mergeDeclarations(Structure.ClassDecl, snapshot.Structure.ClassDecl);

                // When is it call merge remember which arrays was forgotten in order to support arrays in returns
                if (isCallMerge)
                {
                    foreach (AssociativeArray array in snapshot.Structure.Arrays.Local)
                    {
                        Structure.AddCallArray(array, snapshot);
                    }
                }
            }

            mergeObjects();

            // Prepares operations for all root locations
            for (int x = 0; x <= targetSnapshot.CallLevel; x++)
            {
                collectVariables[x].MergeContainers();
                collectControl[x].MergeContainers();
                mergeTemporary(x);
            }

            processMerge();

            // Build aliases
            foreach (var alias in memoryAliases)
            {
                Structure.SetAlias(alias.Key, alias.Value.Build());
            }
        }
Пример #15
0
 /// <summary>
 /// Adds operation into stack of merge worker.
 /// </summary>
 /// <param name="operation">The operation.</param>
 public void addOperation(MergeOperation operation)
 {
     operationStack.AddLast(operation);
 }
Пример #16
0
 private void addOperation(MergeOperation operation)
 {
     operationStack.AddLast(operation);
 }
Пример #17
0
        private AssociativeArray mergeArrays(
            MemoryIndex targetIndex,
            HashSet <AssociativeArray> arrays,
            bool includeUndefined)
        {
            AssociativeArray arrayValue;

            if (!targetSnapshot.Structure.TryGetArray(targetIndex, out arrayValue))
            {
                arrayValue = targetSnapshot.CreateArray(targetIndex);
            }
            ArrayDescriptor newDescriptor = targetSnapshot.Structure.GetDescriptor(arrayValue);

            MergeOperation unknownMerge = new MergeOperation(newDescriptor.UnknownIndex);

            unknownMerge.SetUndefined();
            addOperation(unknownMerge);

            HashSet <string> indexNames = new HashSet <string>();

            foreach (AssociativeArray array in arrays)
            {
                foreach (Tuple <Snapshot, ArrayDescriptor> item in getArrayDescriptor(array))
                {
                    Snapshot        snapshot   = item.Item1;
                    ArrayDescriptor descriptor = item.Item2;

                    unknownMerge.Add(descriptor.UnknownIndex, snapshot);

                    foreach (var index in descriptor.Indexes)
                    {
                        indexNames.Add(index.Key);
                    }
                }
            }

            foreach (string indexName in indexNames)
            {
                MergeOperation operation = new MergeOperation();

                if (includeUndefined)
                {
                    operation.SetUndefined();
                }

                foreach (var array in arrays)
                {
                    foreach (Tuple <Snapshot, ArrayDescriptor> item in getArrayDescriptor(array))
                    {
                        Snapshot        snapshot   = item.Item1;
                        ArrayDescriptor descriptor = item.Item2;

                        MemoryIndex sourceIndex;
                        if (descriptor.Indexes.TryGetValue(indexName, out sourceIndex))
                        {
                            operation.Add(sourceIndex, snapshot);
                        }
                        else
                        {
                            operation.Add(descriptor.UnknownIndex, snapshot);
                        }
                    }
                }

                MemoryIndex arrayIndex;
                if (!newDescriptor.Indexes.TryGetValue(indexName, out arrayIndex))
                {
                    arrayIndex = targetSnapshot.CreateIndex(indexName, arrayValue, true, false);
                }
                operation.SetTargetIndex(arrayIndex);
                addOperation(operation);
            }

            return(arrayValue);
        }