CastExpr.java revision 628:2bfaf29cc90b
1219019Sgabor/* 2219019Sgabor * reserved comment block 3219019Sgabor * DO NOT REMOVE OR ALTER! 4219019Sgabor */ 5219019Sgabor/* 6219019Sgabor * Copyright 2001-2004 The Apache Software Foundation. 7219019Sgabor * 8219019Sgabor * Licensed under the Apache License, Version 2.0 (the "License"); 9219019Sgabor * you may not use this file except in compliance with the License. 10219019Sgabor * You may obtain a copy of the License at 11219019Sgabor * 12219019Sgabor * http://www.apache.org/licenses/LICENSE-2.0 13219019Sgabor * 14219019Sgabor * Unless required by applicable law or agreed to in writing, software 15219019Sgabor * distributed under the License is distributed on an "AS IS" BASIS, 16219019Sgabor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17219019Sgabor * See the License for the specific language governing permissions and 18219019Sgabor * limitations under the License. 19219019Sgabor */ 20219019Sgabor/* 21219019Sgabor * $Id: CastExpr.java,v 1.2.4.1 2005/09/12 10:06:35 pvedula Exp $ 22219019Sgabor */ 23219019Sgabor 24219019Sgaborpackage com.sun.org.apache.xalan.internal.xsltc.compiler; 25219019Sgabor 26219019Sgaborimport com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 27219019Sgaborimport com.sun.org.apache.bcel.internal.generic.IF_ICMPNE; 28219019Sgaborimport com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; 29219019Sgaborimport com.sun.org.apache.bcel.internal.generic.InstructionList; 30219019Sgaborimport com.sun.org.apache.bcel.internal.generic.SIPUSH; 31219019Sgaborimport com.sun.org.apache.xalan.internal.xsltc.compiler.util.BooleanType; 32219019Sgaborimport com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; 33219019Sgaborimport com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; 34219019Sgaborimport com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; 35219019Sgaborimport com.sun.org.apache.xalan.internal.xsltc.compiler.util.MultiHashtable; 36219019Sgaborimport com.sun.org.apache.xalan.internal.xsltc.compiler.util.NodeType; 37219019Sgaborimport com.sun.org.apache.xalan.internal.xsltc.compiler.util.ResultTreeType; 38219019Sgaborimport com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; 39219019Sgaborimport com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; 40219019Sgaborimport com.sun.org.apache.xml.internal.dtm.Axis; 41219019Sgabor 42219019Sgabor/** 43219019Sgabor * @author Jacek Ambroziak 44219019Sgabor * @author Santiago Pericas-Geertsen 45219019Sgabor * @author Morten Jorgensen 46219019Sgabor * @author Erwin Bolwidt <ejb@klomp.org> 47219019Sgabor */ 48219019Sgaborfinal class CastExpr extends Expression { 49219019Sgabor private final Expression _left; 50219019Sgabor 51219019Sgabor /** 52219019Sgabor * Legal conversions between internal types. 53219019Sgabor */ 54219019Sgabor static private MultiHashtable InternalTypeMap = new MultiHashtable(); 55219019Sgabor 56219019Sgabor static { 57219019Sgabor // Possible type conversions between internal types 58219019Sgabor InternalTypeMap.put(Type.Boolean, Type.Boolean); 59219019Sgabor InternalTypeMap.put(Type.Boolean, Type.Real); 60219019Sgabor InternalTypeMap.put(Type.Boolean, Type.String); 61219019Sgabor InternalTypeMap.put(Type.Boolean, Type.Reference); 62219019Sgabor InternalTypeMap.put(Type.Boolean, Type.Object); 63219019Sgabor 64219019Sgabor InternalTypeMap.put(Type.Real, Type.Real); 65219019Sgabor InternalTypeMap.put(Type.Real, Type.Int); 66219019Sgabor InternalTypeMap.put(Type.Real, Type.Boolean); 67219019Sgabor InternalTypeMap.put(Type.Real, Type.String); 68219019Sgabor InternalTypeMap.put(Type.Real, Type.Reference); 69219019Sgabor InternalTypeMap.put(Type.Real, Type.Object); 70219019Sgabor 71219019Sgabor InternalTypeMap.put(Type.Int, Type.Int); 72219019Sgabor InternalTypeMap.put(Type.Int, Type.Real); 73219019Sgabor InternalTypeMap.put(Type.Int, Type.Boolean); 74219019Sgabor InternalTypeMap.put(Type.Int, Type.String); 75219019Sgabor InternalTypeMap.put(Type.Int, Type.Reference); 76219019Sgabor InternalTypeMap.put(Type.Int, Type.Object); 77219019Sgabor 78219019Sgabor InternalTypeMap.put(Type.String, Type.String); 79219019Sgabor InternalTypeMap.put(Type.String, Type.Boolean); 80219019Sgabor InternalTypeMap.put(Type.String, Type.Real); 81219019Sgabor InternalTypeMap.put(Type.String, Type.Reference); 82219019Sgabor InternalTypeMap.put(Type.String, Type.Object); 83219019Sgabor 84219019Sgabor InternalTypeMap.put(Type.NodeSet, Type.NodeSet); 85219019Sgabor InternalTypeMap.put(Type.NodeSet, Type.Boolean); 86219019Sgabor InternalTypeMap.put(Type.NodeSet, Type.Real); 87219019Sgabor InternalTypeMap.put(Type.NodeSet, Type.String); 88219019Sgabor InternalTypeMap.put(Type.NodeSet, Type.Node); 89219019Sgabor InternalTypeMap.put(Type.NodeSet, Type.Reference); 90219019Sgabor InternalTypeMap.put(Type.NodeSet, Type.Object); 91219019Sgabor 92219019Sgabor InternalTypeMap.put(Type.Node, Type.Node); 93219019Sgabor InternalTypeMap.put(Type.Node, Type.Boolean); 94219019Sgabor InternalTypeMap.put(Type.Node, Type.Real); 95219019Sgabor InternalTypeMap.put(Type.Node, Type.String); 96219019Sgabor InternalTypeMap.put(Type.Node, Type.NodeSet); 97219019Sgabor InternalTypeMap.put(Type.Node, Type.Reference); 98219019Sgabor InternalTypeMap.put(Type.Node, Type.Object); 99219019Sgabor 100219019Sgabor InternalTypeMap.put(Type.ResultTree, Type.ResultTree); 101219019Sgabor InternalTypeMap.put(Type.ResultTree, Type.Boolean); 102219019Sgabor InternalTypeMap.put(Type.ResultTree, Type.Real); 103219019Sgabor InternalTypeMap.put(Type.ResultTree, Type.String); 104219019Sgabor InternalTypeMap.put(Type.ResultTree, Type.NodeSet); 105219019Sgabor InternalTypeMap.put(Type.ResultTree, Type.Reference); 106219019Sgabor InternalTypeMap.put(Type.ResultTree, Type.Object); 107219019Sgabor 108219019Sgabor InternalTypeMap.put(Type.Reference, Type.Reference); 109219019Sgabor InternalTypeMap.put(Type.Reference, Type.Boolean); 110219019Sgabor InternalTypeMap.put(Type.Reference, Type.Int); 111219019Sgabor InternalTypeMap.put(Type.Reference, Type.Real); 112219019Sgabor InternalTypeMap.put(Type.Reference, Type.String); 113219019Sgabor InternalTypeMap.put(Type.Reference, Type.Node); 114219019Sgabor InternalTypeMap.put(Type.Reference, Type.NodeSet); 115219019Sgabor InternalTypeMap.put(Type.Reference, Type.ResultTree); 116219019Sgabor InternalTypeMap.put(Type.Reference, Type.Object); 117219019Sgabor 118219019Sgabor InternalTypeMap.put(Type.Object, Type.String); 119219019Sgabor 120219019Sgabor InternalTypeMap.put(Type.Void, Type.String); 121219019Sgabor } 122263986Stijl 123219019Sgabor private boolean _typeTest = false; 124219019Sgabor 125219019Sgabor /** 126219019Sgabor * Construct a cast expression and check that the conversion is 127219019Sgabor * valid by calling typeCheck(). 128219019Sgabor */ 129219019Sgabor public CastExpr(Expression left, Type type) throws TypeCheckError { 130219019Sgabor _left = left; 131219019Sgabor _type = type; // use inherited field 132219019Sgabor 133219019Sgabor if ((_left instanceof Step) && (_type == Type.Boolean)) { 134219019Sgabor Step step = (Step)_left; 135219019Sgabor if ((step.getAxis() == Axis.SELF) && (step.getNodeType() != -1)) 136219019Sgabor _typeTest = true; 137219019Sgabor } 138219019Sgabor 139260003Sdim // check if conversion is valid 140219019Sgabor setParser(left.getParser()); 141219019Sgabor setParent(left.getParent()); 142219019Sgabor left.setParent(this); 143219019Sgabor typeCheck(left.getParser().getSymbolTable()); 144219019Sgabor } 145219019Sgabor 146219019Sgabor public Expression getExpr() { 147219019Sgabor return _left; 148219019Sgabor } 149219019Sgabor 150219019Sgabor /** 151219019Sgabor * Returns true if this expressions contains a call to position(). This is 152219019Sgabor * needed for context changes in node steps containing multiple predicates. 153219019Sgabor */ 154219019Sgabor public boolean hasPositionCall() { 155219019Sgabor return(_left.hasPositionCall()); 156219019Sgabor } 157260003Sdim 158219019Sgabor public boolean hasLastCall() { 159219019Sgabor return(_left.hasLastCall()); 160219019Sgabor } 161219019Sgabor 162219019Sgabor public String toString() { 163219019Sgabor return "cast(" + _left + ", " + _type + ")"; 164219019Sgabor } 165219019Sgabor 166219019Sgabor /** 167219019Sgabor * Type checking a cast expression amounts to verifying that the 168219019Sgabor * type conversion is legal. Cast expressions are created during 169219019Sgabor * type checking, but typeCheck() is usually not called on them. 170219019Sgabor * As a result, this method is called from the constructor. 171219019Sgabor */ 172219019Sgabor public Type typeCheck(SymbolTable stable) throws TypeCheckError { 173219019Sgabor Type tleft = _left.getType(); 174219019Sgabor if (tleft == null) { 175219019Sgabor tleft = _left.typeCheck(stable); 176219019Sgabor } 177219019Sgabor if (tleft instanceof NodeType) { 178219019Sgabor tleft = Type.Node; // multiple instances 179281550Stijl } 180219019Sgabor else if (tleft instanceof ResultTreeType) { 181219019Sgabor tleft = Type.ResultTree; // multiple instances 182281550Stijl } 183219019Sgabor if (InternalTypeMap.maps(tleft, _type) != null) { 184219019Sgabor return _type; 185219019Sgabor } 186219019Sgabor // throw new TypeCheckError(this); 187219019Sgabor throw new TypeCheckError(new ErrorMsg( 188219019Sgabor ErrorMsg.DATA_CONVERSION_ERR, tleft.toString(), _type.toString())); 189219019Sgabor } 190219019Sgabor 191219019Sgabor public void translateDesynthesized(ClassGenerator classGen, 192219019Sgabor MethodGenerator methodGen) { 193219019Sgabor FlowList fl; 194219019Sgabor final Type ltype = _left.getType(); 195219019Sgabor 196219019Sgabor // This is a special case for the self:: axis. Instead of letting 197219019Sgabor // the Step object create and iterator that we cast back to a single 198219019Sgabor // node, we simply ask the DOM for the node type. 199219019Sgabor if (_typeTest) { 200219019Sgabor final ConstantPoolGen cpg = classGen.getConstantPool(); 201219019Sgabor final InstructionList il = methodGen.getInstructionList(); 202219019Sgabor 203219019Sgabor final int idx = cpg.addInterfaceMethodref(DOM_INTF, 204219019Sgabor "getExpandedTypeID", 205219019Sgabor "(I)I"); 206219019Sgabor il.append(new SIPUSH((short)((Step)_left).getNodeType())); 207219019Sgabor il.append(methodGen.loadDOM()); 208219019Sgabor il.append(methodGen.loadContextNode()); 209219019Sgabor il.append(new INVOKEINTERFACE(idx, 2)); 210219019Sgabor _falseList.add(il.append(new IF_ICMPNE(null))); 211219019Sgabor } 212219019Sgabor else { 213219019Sgabor 214219019Sgabor _left.translate(classGen, methodGen); 215219019Sgabor if (_type != ltype) { 216219019Sgabor _left.startIterator(classGen, methodGen); 217219019Sgabor if (_type instanceof BooleanType) { 218219019Sgabor fl = ltype.translateToDesynthesized(classGen, methodGen, 219219019Sgabor _type); 220219019Sgabor if (fl != null) { 221219019Sgabor _falseList.append(fl); 222219019Sgabor } 223219019Sgabor } 224219019Sgabor else { 225219019Sgabor ltype.translateTo(classGen, methodGen, _type); 226219019Sgabor } 227219019Sgabor } 228219019Sgabor } 229219019Sgabor } 230219019Sgabor 231219019Sgabor public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 232219019Sgabor final Type ltype = _left.getType(); 233219019Sgabor _left.translate(classGen, methodGen); 234219019Sgabor if (_type.identicalTo(ltype) == false) { 235219019Sgabor _left.startIterator(classGen, methodGen); 236219019Sgabor ltype.translateTo(classGen, methodGen, _type); 237219019Sgabor } 238219019Sgabor } 239219019Sgabor} 240219019Sgabor