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: FilteredAbsoluteLocationPath.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.ALOAD; 025 import org.apache.bcel.generic.ASTORE; 026 import org.apache.bcel.generic.ConstantPoolGen; 027 import org.apache.bcel.generic.INVOKEINTERFACE; 028 import org.apache.bcel.generic.INVOKESPECIAL; 029 import org.apache.bcel.generic.InstructionList; 030 import org.apache.bcel.generic.LocalVariableGen; 031 import org.apache.bcel.generic.NEW; 032 import org.apache.xalan.xsltc.compiler.util.ClassGenerator; 033 import org.apache.xalan.xsltc.compiler.util.MethodGenerator; 034 import org.apache.xalan.xsltc.compiler.util.NodeType; 035 import org.apache.xalan.xsltc.compiler.util.Type; 036 import org.apache.xalan.xsltc.compiler.util.TypeCheckError; 037 import org.apache.xalan.xsltc.compiler.util.Util; 038 039 /** 040 * @author G. Todd Miller 041 */ 042 final class FilteredAbsoluteLocationPath extends Expression { 043 private Expression _path; // may be null 044 045 public FilteredAbsoluteLocationPath() { 046 _path = null; 047 } 048 049 public FilteredAbsoluteLocationPath(Expression path) { 050 _path = path; 051 if (path != null) { 052 _path.setParent(this); 053 } 054 } 055 056 public void setParser(Parser parser) { 057 super.setParser(parser); 058 if (_path != null) { 059 _path.setParser(parser); 060 } 061 } 062 063 public Expression getPath() { 064 return(_path); 065 } 066 067 public String toString() { 068 return "FilteredAbsoluteLocationPath(" + 069 (_path != null ? _path.toString() : "null") + ')'; 070 } 071 072 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 073 if (_path != null) { 074 final Type ptype = _path.typeCheck(stable); 075 if (ptype instanceof NodeType) { // promote to node-set 076 _path = new CastExpr(_path, Type.NodeSet); 077 } 078 } 079 return _type = Type.NodeSet; 080 } 081 082 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 083 final ConstantPoolGen cpg = classGen.getConstantPool(); 084 final InstructionList il = methodGen.getInstructionList(); 085 if (_path != null) { 086 final int initDFI = cpg.addMethodref(DUP_FILTERED_ITERATOR, 087 "<init>", 088 "(" 089 + NODE_ITERATOR_SIG 090 + ")V"); 091 092 // Backwards branches are prohibited if an uninitialized object is 093 // on the stack by section 4.9.4 of the JVM Specification, 2nd Ed. 094 // We don't know whether this code might contain backwards branches, 095 // so we mustn't create the new object until after we've created 096 // the suspect arguments to its constructor. Instead we calculate 097 // the values of the arguments to the constructor first, store them 098 // in temporary variables, create the object and reload the 099 // arguments from the temporaries to avoid the problem. 100 101 // Compile relative path iterator(s) 102 LocalVariableGen pathTemp = 103 methodGen.addLocalVariable("filtered_absolute_location_path_tmp", 104 Util.getJCRefType(NODE_ITERATOR_SIG), 105 null, null); 106 _path.translate(classGen, methodGen); 107 pathTemp.setStart(il.append(new ASTORE(pathTemp.getIndex()))); 108 109 // Create new Dup Filter Iterator 110 il.append(new NEW(cpg.addClass(DUP_FILTERED_ITERATOR))); 111 il.append(DUP); 112 pathTemp.setEnd(il.append(new ALOAD(pathTemp.getIndex()))); 113 114 // Initialize Dup Filter Iterator with iterator from the stack 115 il.append(new INVOKESPECIAL(initDFI)); 116 } 117 else { 118 final int git = cpg.addInterfaceMethodref(DOM_INTF, 119 "getIterator", 120 "()"+NODE_ITERATOR_SIG); 121 il.append(methodGen.loadDOM()); 122 il.append(new INVOKEINTERFACE(git, 1)); 123 } 124 } 125 }