001: package net.sf.saxon.query;
002:
003: import net.sf.saxon.expr.*;
004: import net.sf.saxon.instruct.GeneralVariable;
005: import net.sf.saxon.instruct.GlobalParam;
006: import net.sf.saxon.instruct.GlobalVariable;
007: import net.sf.saxon.instruct.SlotManager;
008: import net.sf.saxon.om.NamePool;
009: import net.sf.saxon.trans.XPathException;
010: import net.sf.saxon.type.ItemType;
011: import net.sf.saxon.type.Type;
012: import net.sf.saxon.type.TypeHierarchy;
013: import net.sf.saxon.value.SequenceType;
014:
015: import java.util.ArrayList;
016: import java.util.Iterator;
017: import java.util.List;
018:
019: /**
020: * Class to hold compile-time information about an XQuery global variable
021: * or parameter
022: */
023:
024: public class GlobalVariableDefinition implements VariableDeclaration,
025: Declaration {
026:
027: protected List references = new ArrayList(10);
028: private SequenceType requiredType;
029: private Expression value;
030: private int nameCode;
031: private boolean isParameter;
032: private String variableName;
033: private String systemId; // identifies the module where the variable declaration occurred
034: private int lineNumber; // identifies the line number of the variable declaration
035: private GlobalVariable compiledVar;
036:
037: /**
038: * Set the required type of the variable
039: * @param type the declared type, from the "as" clause if present
040: */
041:
042: public void setRequiredType(SequenceType type) {
043: requiredType = type;
044: }
045:
046: /**
047: * Get the required type of the variable
048: * @return the declared type, from the "as" clause if present
049: */
050:
051: public SequenceType getRequiredType() {
052: return requiredType;
053: }
054:
055: /**
056: * Set the variable name
057: * @param nameCode the variable name, expressed as a NamePool name code
058: */
059: public void setNameCode(int nameCode) {
060: this .nameCode = nameCode;
061: }
062:
063: /**
064: * Get the variable name
065: * @return the variable name, expressed as a NamePool name code
066: */
067: public int getNameCode() {
068: return nameCode;
069: }
070:
071: /**
072: * Set the line number where the variable declaration appears in the source
073: * @param lineNumber the line number
074: */
075: public void setLineNumber(int lineNumber) {
076: this .lineNumber = lineNumber;
077: }
078:
079: /**
080: * Get the line number where the declaration appears
081: */
082:
083: public int getLineNumber() {
084: return lineNumber;
085: }
086:
087: /**
088: * Get column number
089: * @return -1 always
090: */
091:
092: public int getColumnNumber() {
093: return -1;
094: }
095:
096: /**
097: * Get public identifier
098: * @return null always
099: */
100:
101: public String getPublicId() {
102: return null;
103: }
104:
105: /**
106: * Set the system ID of the module where the variable declaration appears
107: */
108: public void setSystemId(String systemId) {
109: this .systemId = systemId;
110: }
111:
112: /**
113: * Get the system ID of the module containing the variable declaration
114: */
115:
116: public String getSystemId() {
117: return systemId;
118: }
119:
120: /**
121: * Get the name of the variable
122: * @return the variable name, as a lexical QName
123: */
124: public String getVariableName() {
125: return variableName;
126: }
127:
128: /**
129: * Set the variable name
130: * @param variableName the variable name, as a lexical QName
131: */
132: public void setVariableName(String variableName) {
133: this .variableName = variableName;
134: }
135:
136: /**
137: * Set the expression used to define the value of the variable
138: * @param val the initializing expression
139: */
140: public void setValueExpression(Expression val) {
141: this .value = val;
142: }
143:
144: /**
145: * Indicate whether this global variable is a "parameter" (an external variable, in XQuery terminology)
146: * @param b true if this variable is external
147: */
148: public void setIsParameter(boolean b) {
149: isParameter = b;
150: }
151:
152: /**
153: * Register a variable reference that refers to this global variable
154: * @param ref the variable reference
155: */
156: public void registerReference(BindingReference ref) {
157: references.add(ref);
158: }
159:
160: /**
161: * Iterate over the references to this variable
162: */
163:
164: public Iterator iterateReferences() {
165: return references.iterator();
166: }
167:
168: /**
169: * Create a compiled representation of this global variable
170: * @param env the static context for the query module
171: * @param slot the slot number allocated to this variable
172: * @return the compiled representation
173: * @throws XPathException if compile-time errors are found.
174: */
175:
176: public GlobalVariable compile(StaticQueryContext env, int slot)
177: throws XPathException {
178:
179: GlobalVariable var;
180: if (isParameter) {
181: var = new GlobalParam();
182: var.setExecutable(env.getExecutable());
183: var.setRequiredParam(value == null);
184: } else {
185: var = new GlobalVariable();
186: var.setExecutable(env.getExecutable());
187: }
188:
189: var.setSelectExpression(value);
190: var.setNameCode(nameCode);
191: var.setRequiredType(requiredType);
192: var.setVariableName(variableName);
193: var.setSlotNumber(slot);
194:
195: int loc = var.getExecutable().getLocationMap()
196: .allocateLocationId(systemId, lineNumber);
197: var.setLocationId(loc);
198:
199: Iterator iter = references.iterator();
200: while (iter.hasNext()) {
201: BindingReference binding = (BindingReference) iter.next();
202: binding.setStaticType(requiredType, null, 0);
203: binding.fixup(var);
204: }
205: env.getExecutable().registerGlobalVariable(var);
206: int referenceCount = RangeVariableDeclaration
207: .getReferenceCount(references, var, env, true);
208: if (referenceCount < 10) {
209: // allow for the fact that the references may be in functions that are executed repeatedly
210: referenceCount = 10;
211: }
212: var.setReferenceCount(referenceCount);
213: compiledVar = var;
214: return var;
215: }
216:
217: /**
218: * Type check the compiled representation of this global variable
219: * @param env the static context for the query module
220: * @throws XPathException if compile-time errors are found.
221: */
222:
223: public static void typeCheck(StaticQueryContext env,
224: GeneralVariable var) throws XPathException {
225:
226: Expression value = var.getSelectExpression();
227: if (value != null) {
228: if (value instanceof ComputedExpression) {
229: ((ComputedExpression) value).setParentExpression(var);
230: }
231: RoleLocator role = new RoleLocator(
232: RoleLocator.VARIABLE,
233: env.getNamePool().getDisplayName(var.getNameCode()),
234: 0, null);
235: Expression value2 = TypeChecker.strictTypeCheck(value
236: .simplify(env).typeCheck(env, Type.ITEM_TYPE), var
237: .getRequiredType(), role, env);
238: value2 = value2.optimize(env.getConfiguration()
239: .getOptimizer(), env, Type.ITEM_TYPE);
240: var.setSelectExpression(value2);
241: if (value2 instanceof ComputedExpression) {
242: ((ComputedExpression) value2).setParentExpression(var);
243: }
244: // the value expression may declare local variables
245: SlotManager map = env.getConfiguration().makeSlotManager();
246: int slots = ExpressionTool.allocateSlots(value2, 0, map);
247: if (slots > 0) {
248: ((GlobalVariable) var).setContainsLocals(map);
249: }
250: }
251:
252: if (var.getRequiredType() == SequenceType.ANY_SEQUENCE
253: && !(var instanceof GlobalParam)) {
254: // no type was declared; try to deduce a type from the value
255: try {
256: final TypeHierarchy th = env.getNamePool()
257: .getTypeHierarchy();
258: final ItemType itemType = value.getItemType(th);
259: final int cardinality = value.getCardinality();
260: var.setRequiredType(SequenceType.makeSequenceType(
261: itemType, cardinality));
262: } catch (Exception err) {
263: // exceptions can happen because references to variables and functions are still unbound
264: }
265: }
266: }
267:
268: /**
269: * Get the compiled variable if the definition has been compiled
270: */
271:
272: public GlobalVariable getCompiledVariable() {
273: return compiledVar;
274: }
275:
276: /**
277: * Produce diagnostic output showing the compiled and optimized expression tree for a function
278: * @param pool the namepool to be used
279: */
280: public void explain(NamePool pool) {
281: System.err.println("declare variable "
282: + pool.getDisplayName(nameCode) + " := ");
283: if (value != null) {
284: value.display(4, pool, System.err);
285: }
286: System.err.println(";");
287: }
288: }
289:
290: //
291: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
292: // you may not use this file except in compliance with the License. You may obtain a copy of the
293: // License at http://www.mozilla.org/MPL/
294: //
295: // Software distributed under the License is distributed on an "AS IS" basis,
296: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
297: // See the License for the specific language governing rights and limitations under the License.
298: //
299: // The Original Code is: all this file.
300: //
301: // The Initial Developer of the Original Code is Michael H. Kay
302: //
303: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
304: //
305: // Contributor(s): none
306: //
|