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 29 /** 30 * @author Morten Jorgensen 31 * @author Santiago Pericas-Geertsen 32 */ 33 class VariableRefBase extends Expression { 34 35 /** 36 * A reference to the associated variable. 37 */ 38 protected VariableBase _variable; 39 40 /** 41 * A reference to the enclosing expression/instruction for which a 42 * closure is needed (Predicate, Number or Sort). 43 */ 44 protected Closure _closure = null; 45 46 public VariableRefBase(VariableBase variable) { 47 _variable = variable; 48 variable.addReference(this); 49 } 50 51 public VariableRefBase() { 52 _variable = null; 53 } 54 55 /** 56 * Returns a reference to the associated variable 57 */ 58 public VariableBase getVariable() { 59 return _variable; 60 } 61 62 /** 63 * If this variable reference is in a top-level element like 64 * another variable, param or key, add a dependency between 65 * that top-level element and the referenced variable. For 66 * example, 67 * 68 * <xsl:variable name="x" .../> 69 * <xsl:variable name="y" select="$x + 1"/> 70 * 71 * and assuming this class represents "$x", add a reference 72 * between variable y and variable x. 73 */ 74 public void addParentDependency() { 75 SyntaxTreeNode node = this; 76 while (node != null && node instanceof TopLevelElement == false) { 77 node = node.getParent(); 78 } 79 80 TopLevelElement parent = (TopLevelElement) node; 81 if (parent != null) { 82 VariableBase var = _variable; 83 if (_variable._ignore) { 84 if (_variable instanceof Variable) { 85 var = parent.getSymbolTable() 86 .lookupVariable(_variable._name); 87 } else if (_variable instanceof Param) { 88 var = parent.getSymbolTable().lookupParam(_variable._name); 89 } 90 } 91 92 parent.addDependency(var); 93 } 94 } 95 96 /** 97 * Two variable references are deemed equal if they refer to the 98 * same variable. 99 */ 100 public boolean equals(Object obj) { 101 try { 102 return (_variable == ((VariableRefBase) obj)._variable); 103 } 104 catch (ClassCastException e) { 105 return false; 106 } 107 } 108 109 /** 110 * Returns a string representation of this variable reference on the 111 * format 'variable-ref(<var-name>)'. 112 * @return Variable reference description 113 */ 114 public String toString() { 115 return "variable-ref("+_variable.getName()+'/'+_variable.getType()+')'; 116 } 117 118 public Type typeCheck(SymbolTable stable) 119 throws TypeCheckError 120 { 121 // Returned cached type if available 122 if (_type != null) return _type; 123 124 // Find nearest closure to add a variable reference 125 if (_variable.isLocal()) { 126 SyntaxTreeNode node = getParent(); 127 do { 128 if (node instanceof Closure) { 129 _closure = (Closure) node; 130 break; 131 } 132 if (node instanceof TopLevelElement) { 133 break; // way up in the tree 134 } 135 node = node.getParent(); 136 } while (node != null); 137 138 if (_closure != null) { 139 _closure.addVariable(this); 140 } 141 } 142 143 // Attempt to get the cached variable type 144 _type = _variable.getType(); 145 146 // If that does not work we must force a type-check (this is normally 147 // only needed for globals in included/imported stylesheets 148 if (_type == null) { 149 _variable.typeCheck(stable); 150 _type = _variable.getType(); 151 } 152 153 // If in a top-level element, create dependency to the referenced var 154 addParentDependency(); 155 156 // Return the type of the referenced variable 157 return _type; 158 } 159 160 }