1 package net.sf.saxon.query; 2 3 import net.sf.saxon.event.LocationProvider; 4 import net.sf.saxon.expr.*; 5 import net.sf.saxon.functions.ExecutableFunctionLibrary; 6 import net.sf.saxon.instruct.*; 7 import net.sf.saxon.om.NamePool; 8 import net.sf.saxon.om.NamespaceResolver; 9 import net.sf.saxon.style.StandardNames; 10 import net.sf.saxon.trace.InstructionInfo; 11 import net.sf.saxon.trace.Location; 12 import net.sf.saxon.trans.StaticError; 13 import net.sf.saxon.trans.XPathException; 14 import net.sf.saxon.value.SequenceType; 15 16 import java.util.ArrayList ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 20 public class XQueryFunction implements InstructionInfo, Container, Declaration { 21 private int nameCode; 22 List arguments; SequenceType resultType; 24 Expression body = null; 25 List references = new ArrayList (10); 26 int lineNumber; 27 int columnNumber; 28 String systemId; 29 private Executable executable; 30 private UserFunction compiledFunction = null; 31 NamespaceResolver namespaceResolver; 32 private StaticContext staticContext; 33 34 public XQueryFunction() {} 35 36 public void setNameCode(int nameCode) { 37 this.nameCode = nameCode; 38 } 39 40 public int getNameCode() { 41 return nameCode; 42 } 43 44 public String getFunctionDisplayName(NamePool pool) { 45 return pool.getDisplayName(nameCode); 46 } 47 48 public int getFunctionFingerprint() { 49 return nameCode & 0xfffff; 50 } 51 52 public SequenceType getResultType() { 53 return resultType; 54 } 55 56 public void setExecutable(Executable exec) { 57 executable = exec; 58 } 59 60 public Executable getExecutable() { 61 return executable; 62 } 63 64 67 68 public LocationProvider getLocationProvider() { 69 return executable.getLocationMap(); 70 } 71 72 public StaticContext getStaticContext() { 73 return staticContext; 74 } 75 76 public SequenceType[] getArgumentTypes() { 77 SequenceType[] types = new SequenceType[arguments.size()]; 78 for (int i=0; i<arguments.size(); i++) { 79 types[i] = ((RangeVariableDeclaration)arguments.get(i)).getRequiredType(); 80 } 81 return types; 82 } 83 84 public UserFunctionParameter[] getParameterDefinitions() { 85 UserFunctionParameter[] params = new UserFunctionParameter[arguments.size()]; 86 for (int i=0; i<arguments.size(); i++) { 87 SequenceType type = ((RangeVariableDeclaration)arguments.get(i)).getRequiredType(); 88 UserFunctionParameter param = new UserFunctionParameter(); 89 param.setRequiredType(type); 90 params[i] = param; 91 } 92 return params; 93 } 94 95 public int getNumberOfArguments() { 96 return arguments.size(); 97 } 98 99 public void registerReference(UserFunctionCall ufc) { 100 references.add(ufc); 101 } 102 103 public UserFunction compile(StaticQueryContext env) throws StaticError { 104 staticContext = env; 105 try { 106 112 if (compiledFunction == null) { 113 SlotManager map = env.getConfiguration().makeSlotManager(); 116 UserFunctionParameter[] params = getParameterDefinitions(); 117 Iterator iter = arguments.iterator(); 118 int slot = 0; 119 while (iter.hasNext()) { 120 RangeVariableDeclaration decl = (RangeVariableDeclaration)iter.next(); 121 UserFunctionParameter param = params[slot]; 122 param.setSlotNumber(slot++); 123 param.setRequiredType(decl.getRequiredType()); 124 map.allocateSlotNumber(decl.getNameCode() & 0xfffff); 125 decl.fixupReferences(param); 126 } 127 128 130 body = body.simplify(env).typeCheck(env, null); 131 body = body.optimize(env.getConfiguration().getOptimizer(), env, null); 132 if (body instanceof ComputedExpression) { 133 ((ComputedExpression)body).setParentExpression(this); 134 } 135 RoleLocator role = 136 new RoleLocator(RoleLocator.FUNCTION_RESULT, new Integer (nameCode), 0, env.getNamePool()); 137 role.setSourceLocator(this); 138 body = TypeChecker.staticTypeCheck(body, resultType, false, role, env); 139 if (body instanceof ComputedExpression) { 140 ((ComputedExpression)body).setParentExpression(this); 141 } 142 ExpressionTool.allocateSlots(body, slot, map); 143 144 if (env.getConfiguration().getTraceListener() != null) { 145 namespaceResolver = env.getNamespaceResolver(); 146 TraceExpression trace = new TraceExpression(body); 147 trace.setLineNumber(lineNumber); 148 trace.setColumnNumber(columnNumber); 149 trace.setSystemId(env.getBaseURI()); 150 trace.setConstructType(StandardNames.XSL_FUNCTION); 151 trace.setObjectNameCode(nameCode); 152 trace.setLocationId(env.getLocationMap().allocateLocationId(systemId, lineNumber)); 153 body = trace; 154 } 155 156 compiledFunction = new UserFunction(body); 157 compiledFunction.setFunctionNameCode(nameCode); 158 compiledFunction.setParameterDefinitions(params); 159 compiledFunction.setResultType(getResultType()); 161 compiledFunction.setLineNumber(lineNumber); 162 compiledFunction.setSystemId(systemId); 163 compiledFunction.setExecutable(executable); 164 compiledFunction.setStackFrameMap(map); 165 166 168 boolean tailCalls = ExpressionTool.markTailFunctionCalls(body); 169 compiledFunction.setTailRecursive(tailCalls); 170 171 for (int i=0; i<params.length; i++) { 172 RangeVariableDeclaration decl = (RangeVariableDeclaration)arguments.get(i); 173 UserFunctionParameter param = params[i]; 174 int refs = decl.getReferenceCount(param); 175 param.setReferenceCount(refs); 176 } 177 178 } 179 180 182 fixupReferences(env); 183 184 186 if (executable.getFunctionLibrary() instanceof ExecutableFunctionLibrary) { 187 ExecutableFunctionLibrary lib = (ExecutableFunctionLibrary)executable.getFunctionLibrary(); 188 lib.addFunction(compiledFunction); 189 } else { 190 throw new AssertionError ("executable.getFunctionLibrary() is an instance of " + 191 executable.getFunctionLibrary().getClass().getName()); 192 } 193 194 return compiledFunction; 195 } catch (XPathException e) { 196 if (e.getLocator()==null) { 197 e.setLocator(this); 198 } 199 if (e instanceof StaticError) { 200 throw (StaticError)e; 201 } else { 202 throw new StaticError(e); 203 } 204 } 205 } 206 207 210 211 public void fixupReferences(StaticContext env) throws XPathException { 212 Iterator iter = references.iterator(); 213 while (iter.hasNext()) { 214 UserFunctionCall ufc = (UserFunctionCall)iter.next(); 215 ufc.setFunction(compiledFunction, env); 216 } 217 } 218 219 222 223 public void checkReferences(StaticContext env) throws XPathException { 224 Iterator iter = references.iterator(); 225 while (iter.hasNext()) { 226 UserFunctionCall ufc = (UserFunctionCall)iter.next(); 227 ufc.checkFunctionCall(compiledFunction, env); 228 } 229 230 references = new ArrayList (0); 232 233 } 234 235 239 public void explain(NamePool pool) { 240 System.err.println("declare function " + pool.getDisplayName(nameCode) + " {"); 241 body.display(4, pool, System.err); 242 System.err.println("}"); 243 } 244 245 248 249 public UserFunction getUserFunction() { 250 return compiledFunction; 251 } 252 253 257 258 public int getConstructType() { 259 return StandardNames.XSL_FUNCTION; 260 } 261 262 266 267 271 275 276 public int getObjectNameCode() { 277 return nameCode; 278 } 279 280 287 288 public String getSystemId() { 289 return systemId; 290 } 291 292 297 298 public int getLineNumber() { 299 return lineNumber; 300 } 301 302 308 public String getPublicId() { 309 return null; 310 } 311 312 317 318 public int getColumnNumber() { 319 return -1; 320 } 321 322 public String getSystemId(int locationId) { 323 return getSystemId(); 324 } 325 326 public int getLineNumber(int locationId) { 327 return getLineNumber(); 328 } 329 330 334 335 public NamespaceResolver getNamespaceResolver() { 336 return namespaceResolver; 337 } 338 339 346 347 public Object getProperty(String name) { 348 if ("name".equals(name)) { 349 return staticContext.getNamePool().getDisplayName(nameCode); 350 } else if ("as".equals(name)) { 351 return resultType.toString(); 352 } else { 353 return null; 354 } 355 } 356 357 362 363 public Iterator getProperties() { 364 return new PairIterator("name", "as"); 365 } 366 367 368 } 369 370 371 | Popular Tags |