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 }