public override bool Equals(object obj) { SubTreeId other = obj as SubTreeId; return ((other != null) && (m_hashCode == other.m_hashCode) && ((other.m_subTreeRoot == this.m_subTreeRoot) || ((other.m_parent == this.m_parent) && (other.m_childIndex == this.m_childIndex)))); }
/// <summary> /// Apply rules to the current subtree in a bottom-up fashion. /// </summary> /// <param name="context">Current rule processing context</param> /// <param name="rules">The look-up table with the rules to be applied</param> /// <param name="subTreeRoot">Current subtree</param> /// <param name="parent">Parent node</param> /// <param name="childIndexInParent">Index of this child within the parent</param> /// <returns>the result of the transformation</returns> private Node ApplyRulesToSubtree(RuleProcessingContext context, ReadOnlyCollection<ReadOnlyCollection<InternalTrees.Rule>> rules, Node subTreeRoot, Node parent, int childIndexInParent) { int loopCount = 0; Dictionary<SubTreeId, SubTreeId> localProcessedMap = new Dictionary<SubTreeId, SubTreeId>(); SubTreeId subTreeId; while (true) { // Am I looping forever Debug.Assert(loopCount < 12, "endless loops?"); loopCount++; // // We may need to update state regardless of whether this subTree has // changed after it has been processed last. For example, it may be // affected by transformation in its siblings due to external references. // context.PreProcessSubTree(subTreeRoot); subTreeId = new SubTreeId(context, subTreeRoot, parent, childIndexInParent); // Have I seen this subtree already? Just return, if so if (m_processedNodeMap.ContainsKey(subTreeId)) { break; } // Avoid endless loops here - avoid cycles of 2 or more if (localProcessedMap.ContainsKey(subTreeId)) { // mark this subtree as processed m_processedNodeMap[subTreeId] = subTreeId; break; } // Keep track of this one localProcessedMap[subTreeId] = subTreeId; // Walk my children for (int i = 0; i < subTreeRoot.Children.Count; i++) { subTreeRoot.Children[i] = ApplyRulesToSubtree(context, rules, subTreeRoot.Children[i], subTreeRoot, i); } // Apply rules to myself. If no transformations were performed, // then mark this subtree as processed, and break out Node newSubTreeRoot; if (!ApplyRulesToNode(context, rules, subTreeRoot, out newSubTreeRoot)) { Debug.Assert(subTreeRoot == newSubTreeRoot); // mark this subtree as processed m_processedNodeMap[subTreeId] = subTreeId; break; } context.PostProcessSubTree(subTreeRoot); subTreeRoot = newSubTreeRoot; } context.PostProcessSubTree(subTreeRoot); return subTreeRoot; }
/// <summary> /// Apply rules to the current subtree in a bottom-up fashion. /// </summary> /// <param name="context">Current rule processing context</param> /// <param name="rules">The look-up table with the rules to be applied</param> /// <param name="subTreeRoot">Current subtree</param> /// <param name="parent">Parent node</param> /// <param name="childIndexInParent">Index of this child within the parent</param> /// <returns>the result of the transformation</returns> private Node ApplyRulesToSubtree(RuleProcessingContext context, ReadOnlyCollection <ReadOnlyCollection <InternalTrees.Rule> > rules, Node subTreeRoot, Node parent, int childIndexInParent) { int loopCount = 0; Dictionary <SubTreeId, SubTreeId> localProcessedMap = new Dictionary <SubTreeId, SubTreeId>(); SubTreeId subTreeId; while (true) { // Am I looping forever Debug.Assert(loopCount < 12, "endless loops?"); loopCount++; // // We may need to update state regardless of whether this subTree has // changed after it has been processed last. For example, it may be // affected by transformation in its siblings due to external references. // context.PreProcessSubTree(subTreeRoot); subTreeId = new SubTreeId(context, subTreeRoot, parent, childIndexInParent); // Have I seen this subtree already? Just return, if so if (m_processedNodeMap.ContainsKey(subTreeId)) { break; } // Avoid endless loops here - avoid cycles of 2 or more if (localProcessedMap.ContainsKey(subTreeId)) { // mark this subtree as processed m_processedNodeMap[subTreeId] = subTreeId; break; } // Keep track of this one localProcessedMap[subTreeId] = subTreeId; // Walk my children for (int i = 0; i < subTreeRoot.Children.Count; i++) { subTreeRoot.Children[i] = ApplyRulesToSubtree(context, rules, subTreeRoot.Children[i], subTreeRoot, i); } // Apply rules to myself. If no transformations were performed, // then mark this subtree as processed, and break out Node newSubTreeRoot; if (!ApplyRulesToNode(context, rules, subTreeRoot, out newSubTreeRoot)) { Debug.Assert(subTreeRoot == newSubTreeRoot); // mark this subtree as processed m_processedNodeMap[subTreeId] = subTreeId; break; } context.PostProcessSubTree(subTreeRoot); subTreeRoot = newSubTreeRoot; } context.PostProcessSubTree(subTreeRoot); return(subTreeRoot); }