1 /*
2  * reserved comment block
3  * DO NOT REMOVE OR ALTER!
4  */
5 /*
6  * Copyright 2001-2004 The Apache Software Foundation.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 /*
21  * $Id: VariableRefBase.java,v 1.5 2005/09/28 13:48:18 pvedula Exp $
22  */
23 
24 package com.sun.org.apache.xalan.internal.xsltc.compiler;
25 
26 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
27 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
28 import java.util.Objects;
29 
30 /**
31  * @author Morten Jorgensen
32  * @author Santiago Pericas-Geertsen
33  */
34 class VariableRefBase extends Expression {
35 
36     /**
37      * A reference to the associated variable.
38      */
39     protected VariableBase _variable;
40 
41     /**
42      * A reference to the enclosing expression/instruction for which a
43      * closure is needed (Predicate, Number or Sort).
44      */
45     protected Closure _closure = null;
46 
VariableRefBase(VariableBase variable)47     public VariableRefBase(VariableBase variable) {
48         _variable = variable;
49         variable.addReference(this);
50     }
51 
VariableRefBase()52     public VariableRefBase() {
53         _variable = null;
54     }
55 
56     /**
57      * Returns a reference to the associated variable
58      */
getVariable()59     public VariableBase getVariable() {
60         return _variable;
61     }
62 
63     /**
64      * If this variable reference is in a top-level element like
65      * another variable, param or key, add a dependency between
66      * that top-level element and the referenced variable. For
67      * example,
68      *
69      *   <xsl:variable name="x" .../>
70      *   <xsl:variable name="y" select="$x + 1"/>
71      *
72      * and assuming this class represents "$x", add a reference
73      * between variable y and variable x.
74      */
addParentDependency()75     public void addParentDependency() {
76         SyntaxTreeNode node = this;
77         while (node != null && node instanceof TopLevelElement == false) {
78             node = node.getParent();
79         }
80 
81         TopLevelElement parent = (TopLevelElement) node;
82         if (parent != null) {
83             VariableBase var = _variable;
84             if (_variable._ignore) {
85                 if (_variable instanceof Variable) {
86                     var = parent.getSymbolTable()
87                                 .lookupVariable(_variable._name);
88                 } else if (_variable instanceof Param) {
89                     var = parent.getSymbolTable().lookupParam(_variable._name);
90                 }
91             }
92 
93             parent.addDependency(var);
94         }
95     }
96 
97     /**
98      * Two variable references are deemed equal if they refer to the
99      * same variable.
100      */
101     @Override
equals(Object obj)102     public boolean equals(Object obj) {
103         return obj == this || (obj instanceof VariableRefBase)
104             && (_variable == ((VariableRefBase) obj)._variable);
105     }
106 
107     @Override
hashCode()108     public int hashCode() {
109         return Objects.hashCode(this._variable);
110     }
111 
112     /**
113      * Returns a string representation of this variable reference on the
114      * format 'variable-ref(<var-name>)'.
115      * @return Variable reference description
116      */
117     @Override
toString()118     public String toString() {
119         return "variable-ref("+_variable.getName()+'/'+_variable.getType()+')';
120     }
121 
122     @Override
typeCheck(SymbolTable stable)123     public Type typeCheck(SymbolTable stable)
124         throws TypeCheckError
125     {
126         // Returned cached type if available
127         if (_type != null) return _type;
128 
129         // Find nearest closure to add a variable reference
130         if (_variable.isLocal()) {
131             SyntaxTreeNode node = getParent();
132             do {
133                 if (node instanceof Closure) {
134                     _closure = (Closure) node;
135                     break;
136                 }
137                 if (node instanceof TopLevelElement) {
138                     break;      // way up in the tree
139                 }
140                 node = node.getParent();
141             } while (node != null);
142 
143             if (_closure != null) {
144                 _closure.addVariable(this);
145             }
146         }
147 
148         // Attempt to get the cached variable type
149         _type = _variable.getType();
150 
151         // If that does not work we must force a type-check (this is normally
152         // only needed for globals in included/imported stylesheets
153         if (_type == null) {
154             _variable.typeCheck(stable);
155             _type = _variable.getType();
156         }
157 
158         // If in a top-level element, create dependency to the referenced var
159         addParentDependency();
160 
161         // Return the type of the referenced variable
162         return _type;
163     }
164 
165 }
166