|
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 * Remove a reference to this variable. Called by VariableRef when this |
|
88 * variable goes out of scope. |
|
89 */ |
|
90 public void removeReference(VariableRefBase vref) { |
|
91 _refs.remove(vref); |
|
92 } |
|
93 |
|
94 /** |
|
95 * When a variable is overriden by another, e.g. via xsl:import, |
|
96 * its references need to be copied or otherwise it may be |
|
97 * compiled away as dead code. This method can be used for that |
|
98 * purpose. |
|
99 */ |
|
100 public void copyReferences(VariableBase var) { |
|
101 final int size = _refs.size(); |
|
102 for (int i = 0; i < size; i++) { |
|
103 var.addReference((VariableRefBase) _refs.get(i)); |
|
104 } |
|
105 } |
|
106 |
|
107 /** |
|
108 * Map this variable to a register |
|
109 */ |
|
110 public void mapRegister(MethodGenerator methodGen) { |
|
111 if (_local == null) { |
|
112 final InstructionList il = methodGen.getInstructionList(); |
|
113 final String name = getEscapedName(); // TODO: namespace ? |
|
114 final com.sun.org.apache.bcel.internal.generic.Type varType = _type.toJCType(); |
|
115 _local = methodGen.addLocalVariable2(name, varType, il.getEnd()); |
|
116 } |
|
117 } |
|
118 |
|
119 /** |
|
120 * Remove the mapping of this variable to a register. |
|
121 * Called when we leave the AST scope of the variable's declaration |
|
122 */ |
|
123 public void unmapRegister(MethodGenerator methodGen) { |
|
124 if (_refs.isEmpty() && (_local != null)) { |
|
125 _local.setEnd(methodGen.getInstructionList().getEnd()); |
|
126 methodGen.removeLocalVariable(_local); |
|
127 _refs = null; |
|
128 _local = null; |
|
129 } |
|
130 } |
|
131 |
|
132 /** |
|
133 * Returns an instruction for loading the value of this variable onto |
|
134 * the JVM stack. |
|
135 */ |
|
136 public Instruction loadInstruction() { |
|
137 final Instruction instr = _loadInstruction; |
|
138 if (_loadInstruction == null) { |
|
139 _loadInstruction = _type.LOAD(_local.getIndex()); |
|
140 } |
|
141 return _loadInstruction; |
|
142 } |
|
143 |
|
144 /** |
|
145 * Returns an instruction for storing a value from the JVM stack |
|
146 * into this variable. |
|
147 */ |
|
148 public Instruction storeInstruction() { |
|
149 final Instruction instr = _storeInstruction; |
|
150 if (_storeInstruction == null) { |
|
151 _storeInstruction = _type.STORE(_local.getIndex()); |
|
152 } |
|
153 return _storeInstruction; |
|
154 } |
|
155 |
|
156 /** |
|
157 * Returns the expression from this variable's select attribute (if any) |
|
158 */ |
|
159 public Expression getExpression() { |
|
160 return(_select); |
|
161 } |
|
162 |
|
163 /** |
|
164 * Display variable as single string |
|
165 */ |
|
166 public String toString() { |
|
167 return("variable("+_name+")"); |
|
168 } |
|
169 |
|
170 /** |
|
171 * Display variable in a full AST dump |
|
172 */ |
|
173 public void display(int indent) { |
|
174 indent(indent); |
|
175 System.out.println("Variable " + _name); |
|
176 if (_select != null) { |
|
177 indent(indent + IndentIncrement); |
|
178 System.out.println("select " + _select.toString()); |
|
179 } |
|
180 displayContents(indent + IndentIncrement); |
|
181 } |
|
182 |
|
183 /** |
|
184 * Returns the type of the variable |
|
185 */ |
|
186 public Type getType() { |
|
187 return _type; |
|
188 } |
|
189 |
|
190 /** |
|
191 * Returns the name of the variable or parameter as it will occur in the |
|
192 * compiled translet. |
|
193 */ |
|
194 public QName getName() { |
|
195 return _name; |
|
196 } |
|
197 |
|
198 /** |
|
199 * Returns the escaped qname of the variable or parameter |
|
200 */ |
|
201 public String getEscapedName() { |
|
202 return _escapedName; |
|
203 } |
|
204 |
|
205 /** |
|
206 * Set the name of the variable or paremeter. Escape all special chars. |
|
207 */ |
|
208 public void setName(QName name) { |
|
209 _name = name; |
|
210 _escapedName = Util.escape(name.getStringRep()); |
|
211 } |
|
212 |
|
213 /** |
|
214 * Returns the true if the variable is local |
|
215 */ |
|
216 public boolean isLocal() { |
|
217 return _isLocal; |
|
218 } |
|
219 |
|
220 /** |
|
221 * Parse the contents of the <xsl:decimal-format> element. |
|
222 */ |
|
223 public void parseContents(Parser parser) { |
|
224 // Get the 'name attribute |
|
225 String name = getAttribute("name"); |
|
226 |
|
227 if (name.length() > 0) { |
|
228 if (!XML11Char.isXML11ValidQName(name)) { |
|
229 ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, name, this); |
|
230 parser.reportError(Constants.ERROR, err); |
|
231 } |
|
232 setName(parser.getQNameIgnoreDefaultNs(name)); |
|
233 } |
|
234 else |
|
235 reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "name"); |
|
236 |
|
237 // Check whether variable/param of the same name is already in scope |
|
238 VariableBase other = parser.lookupVariable(_name); |
|
239 if ((other != null) && (other.getParent() == getParent())) { |
|
240 reportError(this, parser, ErrorMsg.VARIABLE_REDEF_ERR, name); |
|
241 } |
|
242 |
|
243 select = getAttribute("select"); |
|
244 if (select.length() > 0) { |
|
245 _select = getParser().parseExpression(this, "select", null); |
|
246 if (_select.isDummy()) { |
|
247 reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "select"); |
|
248 return; |
|
249 } |
|
250 } |
|
251 |
|
252 // Children must be parsed first -> static scoping |
|
253 parseChildren(parser); |
|
254 } |
|
255 |
|
256 /** |
|
257 * Compile the value of the variable, which is either in an expression in |
|
258 * a 'select' attribute, or in the variable elements body |
|
259 */ |
|
260 public void translateValue(ClassGenerator classGen, |
|
261 MethodGenerator methodGen) { |
|
262 // Compile expression is 'select' attribute if present |
|
263 if (_select != null) { |
|
264 _select.translate(classGen, methodGen); |
|
265 // Create a CachedNodeListIterator for select expressions |
|
266 // in a variable or parameter. |
|
267 if (_select.getType() instanceof NodeSetType) { |
|
268 final ConstantPoolGen cpg = classGen.getConstantPool(); |
|
269 final InstructionList il = methodGen.getInstructionList(); |
|
270 |
|
271 final int initCNI = cpg.addMethodref(CACHED_NODE_LIST_ITERATOR_CLASS, |
|
272 "<init>", |
|
273 "(" |
|
274 +NODE_ITERATOR_SIG |
|
275 +")V"); |
|
276 il.append(new NEW(cpg.addClass(CACHED_NODE_LIST_ITERATOR_CLASS))); |
|
277 il.append(DUP_X1); |
|
278 il.append(SWAP); |
|
279 |
|
280 il.append(new INVOKESPECIAL(initCNI)); |
|
281 } |
|
282 _select.startIterator(classGen, methodGen); |
|
283 } |
|
284 // If not, compile result tree from parameter body if present. |
|
285 else if (hasContents()) { |
|
286 compileResultTree(classGen, methodGen); |
|
287 } |
|
288 // If neither are present then store empty string in variable |
|
289 else { |
|
290 final ConstantPoolGen cpg = classGen.getConstantPool(); |
|
291 final InstructionList il = methodGen.getInstructionList(); |
|
292 il.append(new PUSH(cpg, Constants.EMPTYSTRING)); |
|
293 } |
|
294 } |
|
295 |
|
296 } |