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 47 public VariableRefBase(VariableBase variable) { 48 _variable = variable; 49 variable.addReference(this); 50 } 51 52 public VariableRefBase() { 53 _variable = null; 54 } 55 56 /** 57 * Returns a reference to the associated variable 58 */ 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 */ 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 102 public boolean equals(Object obj) { 103 return obj == this || (obj instanceof VariableRefBase) 104 && (_variable == ((VariableRefBase) obj)._variable); 105 } 106 107 @Override 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 118 public String toString() { 119 return "variable-ref("+_variable.getName()+'/'+_variable.getType()+')'; 120 } 121 122 @Override 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 }