1 //------------------------------------------------------------------------------
2 // <copyright file="QilCloneVisitor.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
9 using System.Collections.Generic;
10 using System.Diagnostics;
14 namespace System.Xml.Xsl.Qil {
16 // Create an exact replica of a QIL graph
17 internal class QilCloneVisitor : QilScopedVisitor {
18 private QilFactory fac;
19 private SubstitutionList subs;
22 //-----------------------------------------------
24 //-----------------------------------------------
26 public QilCloneVisitor(QilFactory fac) : this(fac, new SubstitutionList()) {
29 public QilCloneVisitor(QilFactory fac, SubstitutionList subs) {
35 //-----------------------------------------------
37 //-----------------------------------------------
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);
46 //-----------------------------------------------
47 // QilVisitor overrides
48 //-----------------------------------------------
51 /// Visit all children of "parent", replacing each child with a copy of each child.
53 protected override QilNode Visit(QilNode oldNode) {
54 QilNode newNode = null;
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);
66 newNode = oldNode.ShallowClone(this.fac);
68 return base.Visit(newNode);
72 /// Visit all children of "parent", replacing each child with a copy of each child.
74 protected override QilNode VisitChildren(QilNode parent) {
76 for (int i = 0; i < parent.Count; i++) {
77 QilNode child = parent[i];
79 // If child is a reference,
80 if (IsReference(parent, i)) {
81 // Visit the reference and substitute its copy
82 parent[i] = VisitReference(child);
84 // If no substutition found, then use original child
85 if (parent[i] == null)
89 // Otherwise, visit the node and substitute its copy
90 parent[i] = Visit(child);
98 /// If a cloned reference is in scope, replace "oldNode". Otherwise, return "oldNode".
100 protected override QilNode VisitReference(QilNode oldNode) {
101 QilNode newNode = FindClonedReference(oldNode);
102 return base.VisitReference(newNode == null ? oldNode : newNode);
106 //-----------------------------------------------
107 // QilScopedVisitor methods
108 //-----------------------------------------------
111 /// Push node and its shallow clone onto the substitution list.
113 protected override void BeginScope(QilNode node) {
114 this.subs.AddSubstitutionPair(node, node.ShallowClone(this.fac));
118 /// Pop entry from substitution list.
120 protected override void EndScope(QilNode node) {
121 this.subs.RemoveLastSubstitutionPair();
125 //-----------------------------------------------
126 // QilCloneVisitor methods
127 //-----------------------------------------------
130 /// Find the clone of an in-scope reference.
132 protected QilNode FindClonedReference(QilNode node) {
133 return this.subs.FindReplacement(node);