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: VariableBase.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 java.util.Vector; 27 28 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 29 import com.sun.org.apache.bcel.internal.generic.Instruction; 30 import com.sun.org.apache.bcel.internal.generic.InstructionList; 31 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; 32 import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; 33 import com.sun.org.apache.bcel.internal.generic.NEW; 34 import com.sun.org.apache.bcel.internal.generic.PUSH; 35 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; 36 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; 37 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; 38 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NodeSetType; 39 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; 40 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util; 41 import com.sun.org.apache.xml.internal.utils.XML11Char; 42 43 /** 44 * @author Jacek Ambroziak 45 * @author Santiago Pericas-Geertsen 46 * @author Morten Jorgensen 47 * @author Erwin Bolwidt <ejb@klomp.org> 48 * @author John Howard <JohnH@schemasoft.com> 49 */ 50 class VariableBase extends TopLevelElement { 51 52 protected QName _name; // The name of the variable. 53 protected String _escapedName; // The escaped qname of the variable. 54 protected Type _type; // The type of this variable. 55 protected boolean _isLocal; // True if the variable is local. 56 protected LocalVariableGen _local; // Reference to JVM variable 57 protected Instruction _loadInstruction; // Instruction to load JVM variable 58 protected Instruction _storeInstruction; // Instruction to load JVM variable 59 protected Expression _select; // Reference to variable expression 60 protected String select; // Textual repr. of variable expr. 61 62 // References to this variable (when local) 63 protected Vector _refs = new Vector(2); 64 65 // Dependencies to other variables/parameters (for globals only) 66 protected Vector _dependencies = null; 67 68 // Used to make sure parameter field is not added twice 69 protected boolean _ignore = false; 70 71 /** 72 * Disable this variable/parameter 73 */ 74 public void disable() { 75 _ignore = true; 76 } 77 78 /** 79 * Add a reference to this variable. Called by VariableRef when an 80 * expression contains a reference to this variable. 81 */ 82 public void addReference(VariableRefBase vref) { 83 _refs.addElement(vref); 84 } 85 86 /** 87 * When a variable is overriden by another, e.g. via xsl:import, 88 * its references need to be copied or otherwise it may be 89 * compiled away as dead code. This method can be used for that 90 * purpose. 91 */ 92 public void copyReferences(VariableBase var) { 93 final int size = _refs.size(); 94 for (int i = 0; i < size; i++) { 95 var.addReference((VariableRefBase) _refs.get(i)); 96 } 97 } 98 99 /** 100 * Map this variable to a register 101 */ 102 public void mapRegister(MethodGenerator methodGen) { 103 if (_local == null) { 104 final InstructionList il = methodGen.getInstructionList(); 105 final String name = getEscapedName(); // TODO: namespace ? 106 final com.sun.org.apache.bcel.internal.generic.Type varType = _type.toJCType(); 107 _local = methodGen.addLocalVariable2(name, varType, il.getEnd()); 108 } 109 } 110 111 /** 112 * Remove the mapping of this variable to a register. 113 * Called when we leave the AST scope of the variable's declaration 114 */ 115 public void unmapRegister(MethodGenerator methodGen) { 116 if (_local != null) { 117 _local.setEnd(methodGen.getInstructionList().getEnd()); 118 methodGen.removeLocalVariable(_local); 119 _refs = null; 120 _local = null; 121 } 122 } 123 124 /** 125 * Returns an instruction for loading the value of this variable onto 126 * the JVM stack. 127 */ 128 public Instruction loadInstruction() { 129 final Instruction instr = _loadInstruction; 130 if (_loadInstruction == null) { 131 _loadInstruction = _type.LOAD(_local.getIndex()); 132 } 133 return _loadInstruction; 134 } 135 136 /** 137 * Returns an instruction for storing a value from the JVM stack 138 * into this variable. 139 */ 140 public Instruction storeInstruction() { 141 final Instruction instr = _storeInstruction; 142 if (_storeInstruction == null) { 143 _storeInstruction = _type.STORE(_local.getIndex()); 144 } 145 return _storeInstruction; 146 } 147 148 /** 149 * Returns the expression from this variable's select attribute (if any) 150 */ 151 public Expression getExpression() { 152 return(_select); 153 } 154 155 /** 156 * Display variable as single string 157 */ 158 public String toString() { 159 return("variable("+_name+")"); 160 } 161 162 /** 163 * Display variable in a full AST dump 164 */ 165 public void display(int indent) { 166 indent(indent); 167 System.out.println("Variable " + _name); 168 if (_select != null) { 169 indent(indent + IndentIncrement); 170 System.out.println("select " + _select.toString()); 171 } 172 displayContents(indent + IndentIncrement); 173 } 174 175 /** 176 * Returns the type of the variable 177 */ 178 public Type getType() { 179 return _type; 180 } 181 182 /** 183 * Returns the name of the variable or parameter as it will occur in the 184 * compiled translet. 185 */ 186 public QName getName() { 187 return _name; 188 } 189 190 /** 191 * Returns the escaped qname of the variable or parameter 192 */ 193 public String getEscapedName() { 194 return _escapedName; 195 } 196 197 /** 198 * Set the name of the variable or paremeter. Escape all special chars. 199 */ 200 public void setName(QName name) { 201 _name = name; 202 _escapedName = Util.escape(name.getStringRep()); 203 } 204 205 /** 206 * Returns the true if the variable is local 207 */ 208 public boolean isLocal() { 209 return _isLocal; 210 } 211 212 /** 213 * Parse the contents of the <xsl:decimal-format> element. 214 */ 215 public void parseContents(Parser parser) { 216 // Get the 'name attribute 217 String name = getAttribute("name"); 218 219 if (name.length() > 0) { 220 if (!XML11Char.isXML11ValidQName(name)) { 221 ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, name, this); 222 parser.reportError(Constants.ERROR, err); 223 } 224 setName(parser.getQNameIgnoreDefaultNs(name)); 225 } 226 else 227 reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "name"); 228 229 // Check whether variable/param of the same name is already in scope 230 VariableBase other = parser.lookupVariable(_name); 231 if ((other != null) && (other.getParent() == getParent())) { 232 reportError(this, parser, ErrorMsg.VARIABLE_REDEF_ERR, name); 233 } 234 235 select = getAttribute("select"); 236 if (select.length() > 0) { 237 _select = getParser().parseExpression(this, "select", null); 238 if (_select.isDummy()) { 239 reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "select"); 240 return; 241 } 242 } 243 244 // Children must be parsed first -> static scoping 245 parseChildren(parser); 246 } 247 248 /** 249 * Compile the value of the variable, which is either in an expression in 250 * a 'select' attribute, or in the variable elements body 251 */ 252 public void translateValue(ClassGenerator classGen, 253 MethodGenerator methodGen) { 254 // Compile expression is 'select' attribute if present 255 if (_select != null) { 256 _select.translate(classGen, methodGen); 257 // Create a CachedNodeListIterator for select expressions 258 // in a variable or parameter. 259 if (_select.getType() instanceof NodeSetType) { 260 final ConstantPoolGen cpg = classGen.getConstantPool(); 261 final InstructionList il = methodGen.getInstructionList(); 262 263 final int initCNI = cpg.addMethodref(CACHED_NODE_LIST_ITERATOR_CLASS, 264 "<init>", 265 "(" 266 +NODE_ITERATOR_SIG 267 +")V"); 268 il.append(new NEW(cpg.addClass(CACHED_NODE_LIST_ITERATOR_CLASS))); 269 il.append(DUP_X1); 270 il.append(SWAP); 271 272 il.append(new INVOKESPECIAL(initCNI)); 273 } 274 _select.startIterator(classGen, methodGen); 275 } 276 // If not, compile result tree from parameter body if present. 277 else if (hasContents()) { 278 compileResultTree(classGen, methodGen); 279 } 280 // If neither are present then store empty string in variable 281 else { 282 final ConstantPoolGen cpg = classGen.getConstantPool(); 283 final InstructionList il = methodGen.getInstructionList(); 284 il.append(new PUSH(cpg, Constants.EMPTYSTRING)); 285 } 286 } 287 288 }