001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: ParentPattern.java 468650 2006-10-28 07:03:30Z minchau $
020     */
021    
022    package org.apache.xalan.xsltc.compiler;
023    
024    import org.apache.bcel.generic.ConstantPoolGen;
025    import org.apache.bcel.generic.ILOAD;
026    import org.apache.bcel.generic.INVOKEINTERFACE;
027    import org.apache.bcel.generic.ISTORE;
028    import org.apache.bcel.generic.InstructionHandle;
029    import org.apache.bcel.generic.InstructionList;
030    import org.apache.bcel.generic.LocalVariableGen;
031    import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
032    import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
033    import org.apache.xalan.xsltc.compiler.util.Type;
034    import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
035    import org.apache.xalan.xsltc.compiler.util.Util;
036    
037    /**
038     * @author Jacek Ambroziak
039     * @author Santiago Pericas-Geertsen
040     */
041    final class ParentPattern extends RelativePathPattern {
042        private final Pattern _left;
043        private final RelativePathPattern _right;
044                    
045        public ParentPattern(Pattern left, RelativePathPattern right) {
046            (_left = left).setParent(this);
047            (_right = right).setParent(this);
048        }
049    
050        public void setParser(Parser parser) {
051            super.setParser(parser);
052            _left.setParser(parser);
053            _right.setParser(parser);
054        }
055        
056        public boolean isWildcard() {
057            return false;
058        }
059            
060        public StepPattern getKernelPattern() {
061            return _right.getKernelPattern();
062        }
063            
064        public void reduceKernelPattern() {
065            _right.reduceKernelPattern();
066        }
067    
068        public Type typeCheck(SymbolTable stable) throws TypeCheckError {
069            _left.typeCheck(stable);
070            return _right.typeCheck(stable);
071        }
072    
073        public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
074            final ConstantPoolGen cpg = classGen.getConstantPool();
075            final InstructionList il = methodGen.getInstructionList();
076            final LocalVariableGen local =
077                methodGen.addLocalVariable2("ppt", 
078                                            Util.getJCRefType(NODE_SIG),
079                                            null);
080            
081            final org.apache.bcel.generic.Instruction loadLocal =
082                new ILOAD(local.getIndex());
083            final org.apache.bcel.generic.Instruction storeLocal =
084                new ISTORE(local.getIndex());
085    
086            if (_right.isWildcard()) {
087                il.append(methodGen.loadDOM());
088                il.append(SWAP);
089            }
090            else if (_right instanceof StepPattern) {
091                il.append(DUP);
092                local.setStart(il.append(storeLocal));
093                
094                _right.translate(classGen, methodGen);
095                
096                il.append(methodGen.loadDOM());
097                local.setEnd(il.append(loadLocal));
098            }
099            else {
100                _right.translate(classGen, methodGen);
101    
102                if (_right instanceof AncestorPattern) {
103                    il.append(methodGen.loadDOM());
104                    il.append(SWAP);
105                }
106            }
107    
108            final int getParent = cpg.addInterfaceMethodref(DOM_INTF,
109                                                            GET_PARENT,
110                                                            GET_PARENT_SIG);
111            il.append(new INVOKEINTERFACE(getParent, 2));
112    
113            final SyntaxTreeNode p = getParent();
114            if (p == null || p instanceof Instruction || 
115                p instanceof TopLevelElement) 
116            {
117                _left.translate(classGen, methodGen);
118            }
119            else {
120                il.append(DUP);
121                InstructionHandle storeInst = il.append(storeLocal);
122    
123                if (local.getStart() == null) {
124                    local.setStart(storeInst);
125                }
126                _left.translate(classGen, methodGen);
127    
128                il.append(methodGen.loadDOM());
129                local.setEnd(il.append(loadLocal));
130            }
131    
132            methodGen.removeLocalVariable(local);
133            
134            /*
135             * If _right is an ancestor pattern, backpatch _left false
136             * list to the loop that searches for more ancestors.
137             */
138            if (_right instanceof AncestorPattern) {
139                final AncestorPattern ancestor = (AncestorPattern) _right;
140                _left.backPatchFalseList(ancestor.getLoopHandle());    // clears list
141            }
142    
143            _trueList.append(_right._trueList.append(_left._trueList));
144            _falseList.append(_right._falseList.append(_left._falseList));
145        }
146    
147        public String toString() {
148            return "Parent(" + _left + ", " + _right + ')';
149        }
150    }