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: AbsoluteLocationPath.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 Jacek Ambroziak 041 * @author Santiago Pericas-Geertsen 042 */ 043 final class AbsoluteLocationPath extends Expression { 044 private Expression _path; // may be null 045 046 public AbsoluteLocationPath() { 047 _path = null; 048 } 049 050 public AbsoluteLocationPath(Expression path) { 051 _path = path; 052 if (path != null) { 053 _path.setParent(this); 054 } 055 } 056 057 public void setParser(Parser parser) { 058 super.setParser(parser); 059 if (_path != null) { 060 _path.setParser(parser); 061 } 062 } 063 064 public Expression getPath() { 065 return(_path); 066 } 067 068 public String toString() { 069 return "AbsoluteLocationPath(" + 070 (_path != null ? _path.toString() : "null") + ')'; 071 } 072 073 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 074 if (_path != null) { 075 final Type ptype = _path.typeCheck(stable); 076 if (ptype instanceof NodeType) { // promote to node-set 077 _path = new CastExpr(_path, Type.NodeSet); 078 } 079 } 080 return _type = Type.NodeSet; 081 } 082 083 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 084 final ConstantPoolGen cpg = classGen.getConstantPool(); 085 final InstructionList il = methodGen.getInstructionList(); 086 if (_path != null) { 087 final int initAI = cpg.addMethodref(ABSOLUTE_ITERATOR, 088 "<init>", 089 "(" 090 + NODE_ITERATOR_SIG 091 + ")V"); 092 093 // Compile relative path iterator(s) 094 // 095 // Backwards branches are prohibited if an uninitialized object is 096 // on the stack by section 4.9.4 of the JVM Specification, 2nd Ed. 097 // We don't know whether this code might contain backwards branches, 098 // so we mustn't create the new object until after we've created 099 // this argument to its constructor. Instead we calculate the 100 // value of the argument to the constructor first, store it in 101 // a temporary variable, create the object and reload the argument 102 // from the temporary to avoid the problem. 103 _path.translate(classGen, methodGen); 104 LocalVariableGen relPathIterator 105 = methodGen.addLocalVariable("abs_location_path_tmp", 106 Util.getJCRefType(NODE_ITERATOR_SIG), 107 null, null); 108 relPathIterator.setStart( 109 il.append(new ASTORE(relPathIterator.getIndex()))); 110 111 // Create new AbsoluteIterator 112 il.append(new NEW(cpg.addClass(ABSOLUTE_ITERATOR))); 113 il.append(DUP); 114 relPathIterator.setEnd( 115 il.append(new ALOAD(relPathIterator.getIndex()))); 116 117 // Initialize AbsoluteIterator with iterator from the stack 118 il.append(new INVOKESPECIAL(initAI)); 119 } 120 else { 121 final int gitr = cpg.addInterfaceMethodref(DOM_INTF, 122 "getIterator", 123 "()"+NODE_ITERATOR_SIG); 124 il.append(methodGen.loadDOM()); 125 il.append(new INVOKEINTERFACE(gitr, 1)); 126 } 127 } 128 }