/// <summary> /// Stores given collection as the source of indexes and adds its unknown index into unknown operation. /// Also gets all indexes from the source collection and inserts it into target collection. /// /// This method is for the first phase of anaysis. /// </summary> /// <param name="sourceSnapshot">The source snapshot.</param> /// <param name="sourceIndex">Index of the source.</param> /// <param name="sourceContainer">The source container.</param> public void CollectIndexes( Snapshot sourceSnapshot, MemoryIndex sourceIndex, IReadonlyIndexContainer sourceContainer) { sources.Add(new Tuple <IReadonlyIndexContainer, Snapshot>(sourceContainer, sourceSnapshot)); unknownOperation.Add(sourceContainer.UnknownIndex, sourceSnapshot); bool indexEquals = targetIndex.Equals(sourceIndex); foreach (var index in sourceContainer.Indexes) { MemoryIndex containerIndex; if (targetContainer.TryGetIndex(index.Key, out containerIndex)) { if (containerIndex == null && indexEquals) { writeableTargetContainer.AddIndex(index.Key, index.Value); undefinedIndexes.Remove(index.Key); } } else if (indexEquals) { writeableTargetContainer.AddIndex(index.Key, index.Value); } else { writeableTargetContainer.AddIndex(index.Key, null); undefinedIndexes.Add(index.Key); } } }
/// <summary> /// Initializes a new instance of the <see cref="CopyIndexContainer"/> class. /// /// Content of given container is copied to the new container. /// </summary> /// <param name="container">The container.</param> public CopyIndexContainer(IReadonlyIndexContainer container) { unknownIndex = container.UnknownIndex; indexes = new Dictionary <string, MemoryIndex>(); CollectionMemoryUtils.AddAll(indexes, container.Indexes); }
/// <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) { writeableTargetContainer.AddIndex(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) { IReadonlyIndexContainer container = source.Item1; Snapshot snapshot = source.Item2; MemoryIndex containerIndex; if (container.TryGetIndex(index.Key, out containerIndex)) { operation.Add(containerIndex, snapshot); } else { operation.Add(container.UnknownIndex, snapshot); } } } }
/// <summary> /// Cotinues traversing using specified segment in given index container. /// </summary> /// <param name="segment">The segment.</param> /// <param name="container">The container.</param> /// <param name="isMust">if set to <c>true</c> [is must].</param> private void processSegment(PathSegment segment, IReadonlyIndexContainer container, bool isMust = true) { if (segment.IsAny) { mayIndexesProcess.Add(container.UnknownIndex); addToMay(container.UnknownIndex); foreach (var index in container.Indexes) { addToMay(index.Value); } } else if (segment.IsUnknown) { addToMay(container.UnknownIndex); } else if (segment.Names.Count == 1) { MemoryIndex processIndex; if (!container.TryGetIndex(segment.Names[0], out processIndex) && !snapshot.Structure.Locked) { creatorVisitor.Name = segment.Names[0]; creatorVisitor.IsMust = isMust; segment.Accept(creatorVisitor); processIndex = creatorVisitor.CreatedIndex; } if (processIndex != null) { if (isMust) { addToMust(processIndex); } else { addToMay(processIndex); } } } else { creatorVisitor.IsMust = false; foreach (String name in segment.Names) { MemoryIndex processIndex; if (!container.TryGetIndex(name, out processIndex) && !snapshot.Structure.Locked) { creatorVisitor.Name = name; segment.Accept(creatorVisitor); processIndex = creatorVisitor.CreatedIndex; } if (processIndex != null) { addToMay(processIndex); } } } }
/// <summary> /// Collects the segment from structure. /// </summary> /// <param name="segment">The segment.</param> /// <param name="node">The node.</param> /// <param name="indexContainer">The index container.</param> /// <param name="isMust">if set to <c>true</c> [is must].</param> public void CollectSegmentFromStructure(PathSegment segment, CollectorNode node, IReadonlyIndexContainer indexContainer, bool isMust) { isMust = isMust && node.IsMust; if (segment.IsAny) { collectMemoryIndexAnyNode(indexContainer.UnknownIndex, node); foreach (var item in indexContainer.Indexes) { collectMemoryIndexExpandedNode(item.Key, item.Value, node); } } else if (segment.IsUnknown) { collectMemoryIndexAnyNode(indexContainer.UnknownIndex, node); } else if (segment.Names.Count == 1) { string name = segment.Names[0]; collectMemoryIndexNode(name, node, indexContainer, isMust); } else { foreach (string name in segment.Names) { collectMemoryIndexNode(name, node, indexContainer, false); } } }
/// <summary> /// Enqueues the merge operation. /// </summary> /// <param name="childName">Name of the child.</param> /// <param name="operation">The operation.</param> /// <param name="targetContainerContext">The target container context.</param> /// <param name="childTreeNode">The child tree node.</param> /// <param name="alwaysDefined">if set to <c>true</c> [always defined].</param> private void enqueueMergeOperation(string childName, MergeOperation operation, ITargetContainerContext targetContainerContext, MemoryIndexTreeNode childTreeNode, bool alwaysDefined) { IReadonlyIndexContainer targetContainer = targetContainerContext.getSourceContainer(); MemoryIndex targetIndex; // Use index from target collection or crete and add it to the target collection if (!targetContainer.TryGetIndex(childName, out targetIndex)) { targetIndex = createNewTargetIndex(targetContainerContext, childName); if (targetIndex == null) { return; } } // Set parameters and add it to collection operation.TreeNode = childTreeNode; operation.SetTargetIndex(targetIndex); if (!alwaysDefined) { operation.SetUndefined(); } operationQueue.AddLast(operation); }
private void createRepresentation(Snapshot snapshot, StringBuilder result, IReadonlyIndexContainer indexContainer) { createIndexRepresentation(snapshot, result, indexContainer.UnknownIndex, indexContainer.UnknownIndex.ToString()); foreach (var item in indexContainer.Indexes) { MemoryIndex index = item.Value; createIndexRepresentation(snapshot, result, index, index.ToString()); } }
private void createRepresentation(IReadonlyIndexContainer indexContainer) { createIndexRepresentation(indexContainer.UnknownIndex, indexContainer.UnknownIndex.ToString()); foreach (var item in indexContainer.Indexes) { MemoryIndex index = item.Value; createIndexRepresentation(index, index.ToString()); } }
/// <summary> /// Gets the or create control stack node. /// </summary> /// <param name="collector">The collector.</param> /// <param name="callLevel">The call level.</param> /// <returns>Node representing stack context on specified level.</returns> public ContainerCollectorNode GetOrCreateControlStackNode(TreeIndexCollector collector, int callLevel) { ContainerCollectorNode controlStackNode; if (!ControlStackNodes.TryGetValue(callLevel, out controlStackNode)) { IReadonlyIndexContainer indexContainer = collector.Structure .GetReadonlyStackContext(callLevel).ReadonlyControllVariables; controlStackNode = new ContainerCollectorNode(indexContainer); ControlStackNodes.Add(callLevel, controlStackNode); } return(controlStackNode); }
/// <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[targetCallLevel + 1]; ContainerOperations[] collectControl = new ContainerOperations[targetCallLevel + 1]; MergeOperation returnOperation = new MergeOperation(); for (int x = 0; x <= targetCallLevel; x++) { IReadonlyIndexContainer variables = Structure.Readonly.GetReadonlyStackContext(x).ReadonlyVariables; collectVariables[x] = new ContainerOperations(this, variables, variables.UnknownIndex, variables.UnknownIndex); IReadonlyIndexContainer control = Structure.Readonly.GetReadonlyStackContext(x).ReadonlyControllVariables; collectControl[x] = new ContainerOperations(this, control, control.UnknownIndex, control.UnknownIndex); } foreach (Snapshot snapshot in sourceSnapshots) { for (int sourceLevel = 0, targetLevel = 0; targetLevel <= targetCallLevel; sourceLevel++, targetLevel++) { if (sourceLevel == snapshot.CallLevel && snapshot.CallLevel != targetCallLevel) { if (isCallMerge) { break; } else { targetLevel = targetCallLevel; } } IReadonlyIndexContainer variables = snapshot.Structure.Readonly.GetReadonlyStackContext(sourceLevel).ReadonlyVariables; collectVariables[targetLevel].AddContainer(variables, snapshot); IReadonlyIndexContainer control = snapshot.Structure.Readonly.GetReadonlyStackContext(sourceLevel).ReadonlyControllVariables; collectControl[targetLevel].AddContainer(control, snapshot); } } mergeObjects(); for (int x = 0; x <= targetCallLevel; x++) { collectVariables[x].MergeContainers(); collectControl[x].MergeContainers(); mergeTemporary(x); } processMerge(); }
/// <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.writeableTargetContainer = targetContainer; this.worker = worker; this.targetIndex = targetIndex; unknownOperation = new MergeOperation(unknownIndex); worker.addOperation(unknownOperation); }
/// <summary> /// Gets the or create variable stack node. /// </summary> /// <param name="collector">The collector.</param> /// <param name="callLevel">The call level.</param> /// <returns></returns> public ContainerCollectorNode GetOrCreateVariableStackNode(TreeIndexCollector collector, int callLevel) { ContainerCollectorNode variableStackNode; if (!VariableStackNodes.TryGetValue(callLevel, out variableStackNode)) { IReadonlyIndexContainer indexContainer = collector.Structure .GetReadonlyStackContext(callLevel).ReadonlyVariables; variableStackNode = new ContainerCollectorNode(indexContainer); VariableStackNodes.Add(callLevel, variableStackNode); } return(variableStackNode); }
/// <summary> /// Enqueues the delete operation. /// </summary> /// <param name="childName">Name of the child.</param> /// <param name="operation">The operation.</param> /// <param name="targetContainerContext">The target container context.</param> /// <param name="childTreeNode">The child tree node.</param> private void enqueueDeleteOperation(string childName, MergeOperation operation, ITargetContainerContext targetContainerContext, MemoryIndexTreeNode childTreeNode) { IReadonlyIndexContainer targetContainer = targetContainerContext.getSourceContainer(); MemoryIndex targetIndex; if (targetContainer.TryGetIndex(childName, out targetIndex)) { // Enque delete operation only if target index exists in paret snapshot operation.TreeNode = childTreeNode; operation.SetTargetIndex(targetIndex); operation.SetDeleteOperation(); operationQueue.AddLast(operation); // Delete child from parent container targetContainerContext.getWriteableSourceContainer().RemoveIndex(childName); } }
/// <summary> /// Enqueues the merge unknown operation. /// </summary> /// <param name="targetContainerContext">The target container context.</param> /// <param name="anyNode">Any node.</param> /// <param name="sourceContainers">The source containers.</param> private void enqueueMergeUnknownOperation(ITargetContainerContext targetContainerContext, MemoryIndexTreeNode anyNode, List <ContainerContext> sourceContainers) { MergeOperation unknownOperation = new MergeOperation(); foreach (ContainerContext containerContext in sourceContainers) { unknownOperation.Add(new MergeOperationContext( containerContext.IndexContainer.UnknownIndex, containerContext.SnapshotContext)); } IReadonlyIndexContainer targetContainer = targetContainerContext.getSourceContainer(); unknownOperation.TreeNode = anyNode; unknownOperation.SetTargetIndex(targetContainer.UnknownIndex); unknownOperation.SetUndefined(); operationQueue.AddLast(unknownOperation); }
private void collectMemoryIndexNode(string name, CollectorNode node, IReadonlyIndexContainer indexContainer, bool isMust) { if (testAndProcessReturnedNode(name, node, isMust)) { LocationCollectorNode nextNode; MemoryIndex memoryIndex; if (indexContainer.TryGetIndex(name, out memoryIndex)) { nextNode = node.CreateMemoryIndexChild(name, memoryIndex); } else { nextNode = node.CreateMemoryIndexChildFromAny(name, indexContainer.UnknownIndex); } nextNode.IsMust = isMust; AddNode(nextNode); } }
/// <summary> /// Cotinues traversing using specified segment in given index container. /// </summary> /// <param name="segment">The segment.</param> /// <param name="container">The container.</param> private void process(PathSegment segment, IReadonlyIndexContainer container) { if (segment.IsAny) { mustIndexesProcess.Add(container.UnknownIndex); foreach (var index in container.Indexes) { mustIndexesProcess.Add(index.Value); } } else if (segment.IsUnknown) { mustIndexesProcess.Add(container.UnknownIndex); } else { bool isUnknown = false; foreach (String name in segment.Names) { MemoryIndex index; if (container.TryGetIndex(name, out index)) { mustIndexesProcess.Add(index); } else { isUnknown = true; } } if (isUnknown) { IsDefined = false; mustIndexesProcess.Add(container.UnknownIndex); } } }
/// <summary> /// Stores given collection as the source of indexes and adds its unknown index into unknown operation. /// Target collection is not modified. /// /// This method is for the second phase of anaysis. /// </summary> /// <param name="sourceContainer">The source container.</param> /// <param name="sourceSnapshot">The source snapshot.</param> public void AddContainer(IReadonlyIndexContainer sourceContainer, Snapshot sourceSnapshot) { sources.Add(new Tuple <IReadonlyIndexContainer, Snapshot>(sourceContainer, sourceSnapshot)); unknownOperation.Add(sourceContainer.UnknownIndex, sourceSnapshot); }
/// <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[targetSnapshotCallLevel + 1]; ContainerOperations[] collectControl = new ContainerOperations[targetSnapshotCallLevel + 1]; MergeOperation returnOperation = new MergeOperation(); // Prepares empty structure for target snapshot for (int x = 0; x <= targetSnapshotCallLevel; x++) { writeableStrucure.AddLocalLevel(); IWriteableIndexContainer variables = writeableStrucure.GetWriteableStackContext(x).WriteableVariables; collectVariables[x] = new ContainerOperations(this, variables, variables.UnknownIndex, variables.UnknownIndex); IWriteableIndexContainer control = writeableStrucure.GetWriteableStackContext(x).WriteableControllVariables; collectControl[x] = new ContainerOperations(this, control, control.UnknownIndex, control.UnknownIndex); } // Collects all objects and root locations from the source objects foreach (Snapshot snapshot in sourceSnapshots) { collectObjects(snapshot); for (int sourceLevel = 0, targetLevel = 0; targetLevel <= targetSnapshotCallLevel; 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 != targetSnapshotCallLevel) { if (isCallMerge) { // When this is the call merge the local level is forgotten break; } else { targetLevel = targetSnapshotCallLevel; } } // Gets all root locations IWriteableIndexContainer targetVariables = writeableStrucure.GetWriteableStackContext(targetLevel).WriteableVariables; IReadonlyIndexContainer sourceVariables = snapshot.Structure.Readonly.GetReadonlyStackContext(sourceLevel).ReadonlyVariables; collectVariables[targetLevel].CollectIndexes(snapshot, targetVariables.UnknownIndex, sourceVariables); IWriteableIndexContainer targetControlls = writeableStrucure.GetWriteableStackContext(targetLevel).WriteableControllVariables; IReadonlyIndexContainer sourceControlls = snapshot.Structure.Readonly.GetReadonlyStackContext(sourceLevel).ReadonlyControllVariables; collectControl[targetLevel].CollectIndexes(snapshot, targetControlls.UnknownIndex, sourceControlls); collectTemporary(snapshot, sourceLevel, targetLevel); } foreach (var name in snapshot.Structure.Readonly.GetFunctions()) { foreach (var decl in snapshot.Structure.Readonly.GetFunction(name)) { writeableStrucure.AddFunctiondeclaration(name, decl); } } foreach (var name in snapshot.Structure.Readonly.GetClasses()) { foreach (var decl in snapshot.Structure.Readonly.GetClass(name)) { writeableStrucure.AddClassDeclaration(name, decl); } } // 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.Readonly.ReadonlyLocalContext.ReadonlyArrays) { writeableStrucure.AddCallArray(array, snapshot); } } } mergeObjects(); // Prepares operations for all root locations for (int x = 0; x <= targetSnapshotCallLevel; x++) { collectVariables[x].MergeContainers(); collectControl[x].MergeContainers(); mergeTemporary(x); } processMerge(); // Build aliases foreach (var alias in memoryAliases) { writeableStrucure.SetAlias(alias.Key, alias.Value.Build(writeableStrucure)); } }
public ContainerCollectorNode(IReadonlyIndexContainer indexContainer) { this.indexContainer = indexContainer; IsMust = true; }
/// <summary> /// Initializes a new instance of the <see cref="ContainerContext"/> class. /// </summary> /// <param name="context">The context.</param> /// <param name="indexContainer">The index container.</param> /// <param name="operationType">Type of the operation.</param> public ContainerContext(SnapshotContext context, IReadonlyIndexContainer indexContainer, MergeOperationType operationType = MergeOperationType.ChangedOnly) { this.SnapshotContext = context; this.IndexContainer = indexContainer; this.OperationType = operationType; }
/// <summary> /// Creates the and enqueue operations. /// </summary> /// <param name="targetContainerContext">The target container context.</param> /// <param name="treeNode">The tree node.</param> /// <param name="sourceContainers">The source containers.</param> /// <param name="alwaysDefined">if set to <c>true</c> [always defined].</param> private void createAndEnqueueOperations( ITargetContainerContext targetContainerContext, MemoryIndexTreeNode treeNode, List <ContainerContext> sourceContainers, bool alwaysDefined) { IReadonlyIndexContainer targetContainer = targetContainerContext.getSourceContainer(); // Creates and enques merge operations for all child nodes of given node foreach (var childNode in treeNode.ChildNodes) { string childName = childNode.Key; MemoryIndexTreeNode childTreeNode = childNode.Value; MergeOperation operation = new MergeOperation(); bool isChildDefined = collectIndexes(childName, sourceContainers, operation); if (isChildDefined) { // Child is defined at least in one collection - enqueue merge operation MemoryIndex targetIndex; // Use index from target collection or crete and add it to the target collection if (!targetContainer.TryGetIndex(childName, out targetIndex)) { targetIndex = createNewTargetIndex(targetContainerContext, childName); if (targetIndex == null) { continue; } } // Set parameters and add it to collection operation.TreeNode = childTreeNode; operation.SetTargetIndex(targetIndex); if (!alwaysDefined) { operation.SetUndefined(); } operationQueue.AddLast(operation); } else { // Child is not defined - enqueue delete operation MemoryIndex targetIndex; if (targetContainer.TryGetIndex(childName, out targetIndex)) { // Enque delete operation only if target index exists in paret snapshot operation.TreeNode = childTreeNode; operation.SetTargetIndex(targetIndex); operation.SetDeleteOperation(); operationQueue.AddLast(operation); deleteChild(targetContainerContext, childName); } } } // Enqueue merge operation for unknown index if is defined if (treeNode.AnyChild != null) { MergeOperation unknownOperation = new MergeOperation(); foreach (ContainerContext containerContext in sourceContainers) { unknownOperation.Add(new MergeOperationContext( containerContext.IndexContainer.UnknownIndex, containerContext.SnapshotContext)); } unknownOperation.TreeNode = treeNode.AnyChild; unknownOperation.SetTargetIndex(targetContainer.UnknownIndex); unknownOperation.SetUndefined(); operationQueue.AddLast(unknownOperation); } }