Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.SqlXml / System / Xml / Xsl / QIL / QilCloneVisitor.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="QilCloneVisitor.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
7
8 using System;
9 using System.Collections.Generic;
10 using System.Diagnostics;
11 using System.Xml;
12 using System.Xml.Xsl;
13
14 namespace System.Xml.Xsl.Qil {
15
16     // Create an exact replica of a QIL graph
17     internal class QilCloneVisitor : QilScopedVisitor {
18         private QilFactory fac;
19         private SubstitutionList subs;
20  
21
22         //-----------------------------------------------
23         // Constructors
24         //-----------------------------------------------
25
26         public QilCloneVisitor(QilFactory fac) : this(fac, new SubstitutionList()) {
27         }
28
29         public QilCloneVisitor(QilFactory fac, SubstitutionList subs) {
30             this.fac = fac;
31             this.subs = subs;
32         }
33
34
35         //-----------------------------------------------
36         // Entry
37         //-----------------------------------------------
38
39         public QilNode Clone(QilNode node) {
40             QilDepthChecker.Check(node);
41             // Assume that iterator nodes at the top-level are references rather than definitions
42             return VisitAssumeReference(node);
43         }
44
45
46         //-----------------------------------------------
47         // QilVisitor overrides
48         //-----------------------------------------------
49
50         /// <summary>
51         /// Visit all children of "parent", replacing each child with a copy of each child.
52         /// </summary>
53         protected override QilNode Visit(QilNode oldNode) {
54             QilNode newNode = null;
55
56             if (oldNode == null)
57                 return null;
58
59             // ShallowClone any nodes which have not yet been cloned
60             if (oldNode is QilReference) {
61                 // Reference nodes may have been cloned previously and put into scope
62                 newNode = FindClonedReference(oldNode);
63             }
64
65             if (newNode == null)
66                 newNode = oldNode.ShallowClone(this.fac);
67
68             return base.Visit(newNode);
69         }
70
71         /// <summary>
72         /// Visit all children of "parent", replacing each child with a copy of each child.
73         /// </summary>
74         protected override QilNode VisitChildren(QilNode parent) {
75             // Visit children
76             for (int i = 0; i < parent.Count; i++) {
77                 QilNode child = parent[i];
78
79                 // If child is a reference,
80                 if (IsReference(parent, i)) {
81                     // Visit the reference and substitute its copy
82                     parent[i] = VisitReference(child);
83
84                     // If no substutition found, then use original child
85                     if (parent[i] == null)
86                         parent[i] = child;
87                 }
88                 else {
89                     // Otherwise, visit the node and substitute its copy
90                     parent[i] = Visit(child);
91                 }
92             }
93
94             return parent;
95         }
96
97         /// <summary>
98         /// If a cloned reference is in scope, replace "oldNode".  Otherwise, return "oldNode".
99         /// </summary>
100         protected override QilNode VisitReference(QilNode oldNode) {
101             QilNode newNode = FindClonedReference(oldNode);
102             return base.VisitReference(newNode == null ? oldNode : newNode);
103         }
104
105
106         //-----------------------------------------------
107         // QilScopedVisitor methods
108         //-----------------------------------------------
109
110         /// <summary>
111         /// Push node and its shallow clone onto the substitution list.
112         /// </summary>
113         protected override void BeginScope(QilNode node) {
114             this.subs.AddSubstitutionPair(node, node.ShallowClone(this.fac));
115         }
116
117         /// <summary>
118         /// Pop entry from substitution list.
119         /// </summary>
120         protected override void EndScope(QilNode node) {
121             this.subs.RemoveLastSubstitutionPair();
122         }
123
124
125         //-----------------------------------------------
126         // QilCloneVisitor methods
127         //-----------------------------------------------
128
129         /// <summary>
130         /// Find the clone of an in-scope reference.
131         /// </summary>
132         protected QilNode FindClonedReference(QilNode node) {
133             return this.subs.FindReplacement(node);
134         }
135     }
136 }