📄 predicate.java
字号:
/* * Copyright 2001-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * $Id: Predicate.java,v 1.2.4.1 2005/09/12 11:02:18 pvedula Exp $ */package com.sun.org.apache.xalan.internal.xsltc.compiler;import java.util.ArrayList;import com.sun.org.apache.bcel.internal.classfile.Field;import com.sun.org.apache.bcel.internal.generic.ASTORE;import com.sun.org.apache.bcel.internal.generic.CHECKCAST;import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;import com.sun.org.apache.bcel.internal.generic.GETFIELD;import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;import com.sun.org.apache.bcel.internal.generic.InstructionList;import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;import com.sun.org.apache.bcel.internal.generic.NEW;import com.sun.org.apache.bcel.internal.generic.PUSH;import com.sun.org.apache.bcel.internal.generic.PUTFIELD;import com.sun.org.apache.xalan.internal.xsltc.compiler.util.BooleanType;import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;import com.sun.org.apache.xalan.internal.xsltc.compiler.util.FilterGenerator;import com.sun.org.apache.xalan.internal.xsltc.compiler.util.IntType;import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NumberType;import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ReferenceType;import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ResultTreeType;import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TestGenerator;import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;import com.sun.org.apache.xalan.internal.xsltc.runtime.Operators;/** * @author Jacek Ambroziak * @author Santiago Pericas-Geertsen * @author Morten Jorgensen */final class Predicate extends Expression implements Closure { /** * The predicate's expression. */ private Expression _exp = null; /** * This flag indicates if optimizations are turned on. The * method <code>dontOptimize()</code> can be called to turn * optimizations off. */ private boolean _canOptimize = true; /** * Flag indicatig if the nth position optimization is on. It * is set in <code>typeCheck()</code>. */ private boolean _nthPositionFilter = false; /** * Flag indicatig if the nth position descendant is on. It * is set in <code>typeCheck()</code>. */ private boolean _nthDescendant = false; /** * Cached node type of the expression that owns this predicate. */ int _ptype = -1; /** * Name of the inner class. */ private String _className = null; /** * List of variables in closure. */ private ArrayList _closureVars = null; /** * Reference to parent closure. */ private Closure _parentClosure = null; /** * Cached value of method <code>getCompareValue()</code>. */ private Expression _value = null; /** * Cached value of method <code>getCompareValue()</code>. */ private Step _step = null; /** * Initializes a predicate. */ public Predicate(Expression exp) { _exp = exp; _exp.setParent(this); } /** * Set the parser for this expression. */ public void setParser(Parser parser) { super.setParser(parser); _exp.setParser(parser); } /** * Returns a boolean value indicating if the nth position optimization * is on. Must be call after type checking! */ public boolean isNthPositionFilter() { return _nthPositionFilter; } /** * Returns a boolean value indicating if the nth descendant optimization * is on. Must be call after type checking! */ public boolean isNthDescendant() { return _nthDescendant; } /** * Turns off all optimizations for this predicate. */ public void dontOptimize() { _canOptimize = false; } /** * Returns true if the expression in this predicate contains a call * to position(). */ public boolean hasPositionCall() { return _exp.hasPositionCall(); } /** * Returns true if the expression in this predicate contains a call * to last(). */ public boolean hasLastCall() { return _exp.hasLastCall(); } // -- Begin Closure interface -------------------- /** * Returns true if this closure is compiled in an inner class (i.e. * if this is a real closure). */ public boolean inInnerClass() { return (_className != null); } /** * 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; } /** * Returns the name of the auxiliary class or null if this predicate * is compiled inside the Translet. */ public String getInnerClassName() { return _className; } /** * Add new variable to the closure. */ public void addVariable(VariableRefBase variableRef) { if (_closureVars == null) { _closureVars = new ArrayList(); } // Only one reference per variable if (!_closureVars.contains(variableRef)) { _closureVars.add(variableRef); // Add variable to parent closure as well Closure parentClosure = getParentClosure(); if (parentClosure != null) { parentClosure.addVariable(variableRef); } } } // -- End Closure interface ---------------------- /** * Returns the node type of the expression owning this predicate. The * return value is cached in <code>_ptype</code>. */ public int getPosType() { if (_ptype == -1) { SyntaxTreeNode parent = getParent(); if (parent instanceof StepPattern) { _ptype = ((StepPattern)parent).getNodeType(); } else if (parent instanceof AbsoluteLocationPath) { AbsoluteLocationPath path = (AbsoluteLocationPath)parent; Expression exp = path.getPath(); if (exp instanceof Step) { _ptype = ((Step)exp).getNodeType(); } } else if (parent instanceof VariableRefBase) { final VariableRefBase ref = (VariableRefBase)parent; final VariableBase var = ref.getVariable(); final Expression exp = var.getExpression(); if (exp instanceof Step) { _ptype = ((Step)exp).getNodeType(); } } else if (parent instanceof Step) { _ptype = ((Step)parent).getNodeType(); } } return _ptype; } public boolean parentIsPattern() { return (getParent() instanceof Pattern); } public Expression getExpr() { return _exp; } public String toString() { return "pred(" + _exp + ')'; } /** * 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. * * 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -