/* 63: */ /* 64: */ public Type typeCheck(SymbolTable stable) /* 65: */ throws TypeCheckError /* 66: */ { /* 67:120 */ if (this._type != null) { /* 68:120 */ return this._type; /* 69: */ } /* 70:123 */ if (this._variable.isLocal()) /* 71: */ { /* 72:124 */ SyntaxTreeNode node = getParent(); /* 73: */ do /* 74: */ { /* 75:126 */ if ((node instanceof Closure)) /* 76: */ { /* 77:127 */ this._closure = ((Closure) node); /* 78:128 */ break; /* 79: */ } /* 80:130 */ if ((node instanceof TopLevelElement)) { /* 81: */ break; /* 82: */ } /* 83:133 */ node = node.getParent(); /* 84:134 */ } while (node != null); /* 85:136 */ if (this._closure != null) { /* 86:137 */ this._closure.addVariable(this); /* 87: */ } /* 88: */ } /* 89:142 */ this._type = this._variable.getType(); /* 90:146 */ if (this._type == null) /* 91: */ { /* 92:147 */ this._variable.typeCheck(stable); /* 93:148 */ this._type = this._variable.getType(); /* 94: */ } /* 95:152 */ addParentDependency(); /* 96: */ /* 97: */ /* 98:155 */ return this._type; /* 99: */ }
/** * Type check a predicate expression. If the type of the expression is number convert it to * boolean by adding a comparison with position(). Note that if the expression is a parameter, we * cannot distinguish at compile time if its type is number or not. Hence, expressions of * reference type are always converted to booleans. * * <p>This method may be called twice, before and after calling <code>dontOptimize()</code>. If * so, the second time it should honor the new value of <code>_canOptimize</code>. */ public Type typeCheck(SymbolTable stable) throws TypeCheckError { Type texp = _exp.typeCheck(stable); // We need explicit type information for reference types - no good! if (texp instanceof ReferenceType) { _exp = new CastExpr(_exp, texp = Type.Real); } // A result tree fragment should not be cast directly to a number type, // but rather to a boolean value, and then to a numer (0 or 1). // Ref. section 11.2 of the XSLT 1.0 spec if (texp instanceof ResultTreeType) { _exp = new CastExpr(_exp, Type.Boolean); _exp = new CastExpr(_exp, Type.Real); texp = _exp.typeCheck(stable); } // Numerical types will be converted to a position filter if (texp instanceof NumberType) { // Cast any numerical types to an integer if (texp instanceof IntType == false) { _exp = new CastExpr(_exp, Type.Int); } if (_canOptimize) { // Nth position optimization. Expression must not depend on context _nthPositionFilter = !_exp.hasLastCall() && !_exp.hasPositionCall(); // _nthDescendant optimization - only if _nthPositionFilter is on if (_nthPositionFilter) { SyntaxTreeNode parent = getParent(); _nthDescendant = (parent instanceof Step) && (parent.getParent() instanceof AbsoluteLocationPath); return _type = Type.NodeSet; } } // Reset optimization flags _nthPositionFilter = _nthDescendant = false; // Otherwise, expand [e] to [position() = e] final QName position = getParser().getQNameIgnoreDefaultNs("position"); final PositionCall positionCall = new PositionCall(position); positionCall.setParser(getParser()); positionCall.setParent(this); _exp = new EqualityExpr(Operators.EQ, positionCall, _exp); if (_exp.typeCheck(stable) != Type.Boolean) { _exp = new CastExpr(_exp, Type.Boolean); } return _type = Type.Boolean; } else { // All other types will be handled as boolean values if (texp instanceof BooleanType == false) { _exp = new CastExpr(_exp, Type.Boolean); } return _type = Type.Boolean; } }
/** Returns a reference to its parent closure or null if outermost. */ public Closure getParentClosure() { if (_parentClosure == null) { SyntaxTreeNode node = getParent(); do { if (node instanceof Closure) { _parentClosure = (Closure) node; break; } if (node instanceof TopLevelElement) { break; // way up in the tree } node = node.getParent(); } while (node != null); } return _parentClosure; }
/* 27: */ /* 28: */ public void addParentDependency() /* 29: */ { /* 30: 73 */ SyntaxTreeNode node = this; /* 31: 74 */ while ((node != null) && (!(node instanceof TopLevelElement))) { /* 32: 75 */ node = node.getParent(); /* 33: */ } /* 34: 78 */ TopLevelElement parent = (TopLevelElement) node; /* 35: 79 */ if (parent != null) /* 36: */ { /* 37: 80 */ VariableBase var = this._variable; /* 38: 81 */ if (this._variable._ignore) { /* 39: 82 */ if ((this._variable instanceof Variable)) { /* 40: 83 */ var = parent.getSymbolTable().lookupVariable(this._variable._name); /* 41: 85 */ } else if ((this._variable instanceof Param)) { /* 42: 86 */ var = parent.getSymbolTable().lookupParam(this._variable._name); /* 43: */ } /* 44: */ } /* 45: 90 */ parent.addDependency(var); /* 46: */ } /* 47: */ }