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 }