1 package net.sf.saxon.instruct; 2 import net.sf.saxon.Configuration; 3 import net.sf.saxon.Controller; 4 import net.sf.saxon.expr.*; 5 import net.sf.saxon.om.AxisIterator; 6 import net.sf.saxon.om.SingletonIterator; 7 import net.sf.saxon.om.ValueRepresentation; 8 import net.sf.saxon.om.NamePool; 9 import net.sf.saxon.style.StandardNames; 10 import net.sf.saxon.trace.InstructionInfo; 11 import net.sf.saxon.trans.DynamicError; 12 import net.sf.saxon.trans.StaticError; 13 import net.sf.saxon.trans.XPathException; 14 15 import java.util.ArrayList ; 16 import java.util.List ; 17 import java.util.Stack ; 18 19 22 23 public class GlobalVariable extends GeneralVariable implements Container { 24 25 private Executable executable; 26 private SlotManager stackFrameMap = null; 27 28 public Executable getExecutable() { 29 return executable; 30 } 31 32 public void setExecutable(Executable executable) { 33 this.executable = executable; 34 } 35 36 public void setContainsLocals(SlotManager map) { 37 this.stackFrameMap = map; 38 } 39 40 public boolean isGlobal() { 41 return true; 42 } 43 44 51 52 public void lookForCycles(Stack referees) throws StaticError { 53 if (referees.contains(this)) { 54 int s = referees.indexOf(this); 55 referees.push(this); 56 String message = "Circular definition of global variable. "; 57 NamePool pool = executable.getConfiguration().getNamePool(); 58 for (int i=s; i<referees.size()-1; i++) { 59 if (referees.get(i+1) instanceof GlobalVariable) { 60 GlobalVariable next = (GlobalVariable)referees.get(i+1); 61 if (i==s) { 62 message += '$' + getVariableName() + " uses $" + next.getVariableName(); 63 } else { 64 message += ", which uses $" + next.getVariableName(); 65 } 66 } else if (referees.get(i+1) instanceof UserFunction) { 67 UserFunction next = (UserFunction)referees.get(i+1); 68 message += ", which calls " + pool.getDisplayName(next.getFunctionNameCode()) + "()"; 69 } 70 } 71 message += '.'; 72 StaticError err = new StaticError(message); 73 err.setErrorCode("XQST0054"); 74 err.setLocator(this); 75 throw err; 76 } 77 if (select != null) { 78 referees.push(this); 79 List list = new ArrayList (10); 80 ExpressionTool.gatherReferencedVariables(select, list); 81 for (int i=0; i<list.size(); i++) { 82 Binding b = (Binding)list.get(i); 83 if (b instanceof GlobalVariable) { 84 ((GlobalVariable)b).lookForCycles(referees); 85 } 86 } 87 list.clear(); 88 ExpressionTool.gatherCalledFunctions(select, list); 89 for (int i=0; i<list.size(); i++) { 90 UserFunction f = (UserFunction)list.get(i); 91 if (!referees.contains(f)) { 92 lookForFunctionCycles(f, referees); 94 } 95 } 96 referees.pop(); 97 } 98 } 99 100 103 104 private static void lookForFunctionCycles(UserFunction f, Stack referees) throws StaticError { 105 Expression body = f.getBody(); 106 referees.push(f); 107 List list = new ArrayList (10); 108 ExpressionTool.gatherReferencedVariables(body, list); 109 for (int i=0; i<list.size(); i++) { 110 Binding b = (Binding)list.get(i); 111 if (b instanceof GlobalVariable) { 112 ((GlobalVariable)b).lookForCycles(referees); 113 } 114 } 115 list.clear(); 116 ExpressionTool.gatherCalledFunctions(body, list); 117 for (int i=0; i<list.size(); i++) { 118 UserFunction fn = (UserFunction)list.get(i); 119 if (!referees.contains(fn)) { 120 lookForFunctionCycles(fn, referees); 122 } 123 } 124 referees.pop(); 125 } 126 127 128 131 132 public TailCall processLeavingTail(XPathContext context) throws XPathException { 133 134 return null; 137 } 138 139 144 145 public ValueRepresentation getSelectValue(XPathContext context) throws XPathException { 146 if (select==null) { 147 throw new AssertionError ("*** No select expression for global variable!!"); 148 } else { 149 XPathContextMajor c2 = context.newCleanContext(); 150 c2.setOrigin(this); 151 AxisIterator initialNode = SingletonIterator.makeIterator(c2.getController().getPrincipalSourceDocument()); 152 initialNode.next(); 153 c2.setCurrentIterator(initialNode); 154 if (stackFrameMap != null) { 155 c2.openStackFrame(stackFrameMap); 156 } 157 return ExpressionTool.lazyEvaluate(select, c2, 10); 158 } 159 } 160 161 164 165 public ValueRepresentation evaluateVariable(XPathContext context) throws XPathException { 166 Controller controller = context.getController(); 167 Bindery b = controller.getBindery(); 168 169 ValueRepresentation v = b.getGlobalVariableValue(this); 170 171 if (v != null) { 172 return v; 173 } else { 174 175 179 try { 180 b.setExecuting(this, true); 181 ValueRepresentation value = getSelectValue(context); 182 b.defineGlobalVariable(this, value); 183 b.setExecuting(this, false); 184 return value; 185 186 } catch (XPathException err) { 187 b.setExecuting(this, false); 188 if (err instanceof XPathException.Circularity) { 189 DynamicError e = new DynamicError("Circular definition of variable " + getVariableName()); 190 int lang = context.getController().getExecutable().getHostLanguage(); 191 e.setErrorCode(lang == Configuration.XQUERY ? "XQST0054" : "XTDE0640"); 192 e.setXPathContext(context); 193 select = new ErrorExpression(e); 195 throw e; 196 } else { 197 throw err; 198 } 199 } 200 } 201 } 202 203 206 207 public InstructionInfo getInstructionInfo() { 208 InstructionDetails details = new InstructionDetails(); 209 details.setConstructType(StandardNames.XSL_VARIABLE); 210 details.setObjectNameCode(getVariableFingerprint()); 211 details.setProperty("expression", this); 212 details.setSystemId(getSystemId()); 213 details.setLineNumber(getLineNumber()); 214 details.setColumnNumber(getColumnNumber()); 215 return details; 216 } 217 218 219 } 220 221 | Popular Tags |