View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright 2001-2004 The Apache Software Foundation.
7    *
8    * Licensed under the Apache License, Version 2.0 (the "License");
9    * you may not use this file except in compliance with the License.
10   * You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  /*
21   * $Id: ParentPattern.java,v 1.2.4.1 2005/09/02 11:10:09 pvedula Exp $
22   */
23  
24  package com.sun.org.apache.xalan.internal.xsltc.compiler;
25  
26  import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
27  import com.sun.org.apache.bcel.internal.generic.ILOAD;
28  import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
29  import com.sun.org.apache.bcel.internal.generic.ISTORE;
30  import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
31  import com.sun.org.apache.bcel.internal.generic.InstructionList;
32  import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
33  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
34  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
35  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
36  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
37  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
38  
39  /**
40   * @author Jacek Ambroziak
41   * @author Santiago Pericas-Geertsen
42   */
43  final class ParentPattern extends RelativePathPattern {
44      private final Pattern _left;
45      private final RelativePathPattern _right;
46  
47      public ParentPattern(Pattern left, RelativePathPattern right) {
48          (_left = left).setParent(this);
49          (_right = right).setParent(this);
50      }
51  
52      public void setParser(Parser parser) {
53          super.setParser(parser);
54          _left.setParser(parser);
55          _right.setParser(parser);
56      }
57  
58      public boolean isWildcard() {
59          return false;
60      }
61  
62      public StepPattern getKernelPattern() {
63          return _right.getKernelPattern();
64      }
65  
66      public void reduceKernelPattern() {
67          _right.reduceKernelPattern();
68      }
69  
70      public Type typeCheck(SymbolTable stable) throws TypeCheckError {
71          _left.typeCheck(stable);
72          return _right.typeCheck(stable);
73      }
74  
75      public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
76          final ConstantPoolGen cpg = classGen.getConstantPool();
77          final InstructionList il = methodGen.getInstructionList();
78          final LocalVariableGen local =
79              methodGen.addLocalVariable2("ppt",
80                                          Util.getJCRefType(NODE_SIG),
81                                          null);
82  
83          final com.sun.org.apache.bcel.internal.generic.Instruction loadLocal =
84              new ILOAD(local.getIndex());
85          final com.sun.org.apache.bcel.internal.generic.Instruction storeLocal =
86              new ISTORE(local.getIndex());
87  
88          if (_right.isWildcard()) {
89              il.append(methodGen.loadDOM());
90              il.append(SWAP);
91          }
92          else if (_right instanceof StepPattern) {
93              il.append(DUP);
94              local.setStart(il.append(storeLocal));
95  
96              _right.translate(classGen, methodGen);
97  
98              il.append(methodGen.loadDOM());
99              local.setEnd(il.append(loadLocal));
100         }
101         else {
102             _right.translate(classGen, methodGen);
103 
104             if (_right instanceof AncestorPattern) {
105                 il.append(methodGen.loadDOM());
106                 il.append(SWAP);
107             }
108         }
109 
110         final int getParent = cpg.addInterfaceMethodref(DOM_INTF,
111                                                         GET_PARENT,
112                                                         GET_PARENT_SIG);
113         il.append(new INVOKEINTERFACE(getParent, 2));
114 
115         final SyntaxTreeNode p = getParent();
116         if (p == null || p instanceof Instruction ||
117             p instanceof TopLevelElement)
118         {
119             _left.translate(classGen, methodGen);
120         }
121         else {
122             il.append(DUP);
123             InstructionHandle storeInst = il.append(storeLocal);
124 
125             if (local.getStart() == null) {
126                 local.setStart(storeInst);
127             }
128 
129             _left.translate(classGen, methodGen);
130 
131             il.append(methodGen.loadDOM());
132             local.setEnd(il.append(loadLocal));
133         }
134 
135         methodGen.removeLocalVariable(local);
136 
137         /*
138          * If _right is an ancestor pattern, backpatch _left false
139          * list to the loop that searches for more ancestors.
140          */
141         if (_right instanceof AncestorPattern) {
142             final AncestorPattern ancestor = (AncestorPattern) _right;
143             _left.backPatchFalseList(ancestor.getLoopHandle());    // clears list
144         }
145 
146         _trueList.append(_right._trueList.append(_left._trueList));
147         _falseList.append(_right._falseList.append(_left._falseList));
148     }
149 
150     public String toString() {
151         return "Parent(" + _left + ", " + _right + ')';
152     }
153 }