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