169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit. 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License. Alternatively, the contents of this file may be used under 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later. 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis, 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License. 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.expr; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.*; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.*; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.compiler.*; 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.compiler.ast.ASTList; 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Explicit type cast. 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class Cast extends Expr { 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Undocumented constructor. Do not use; internal-use only. 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected Cast(int pos, CodeIterator i, CtClass declaring, MethodInfo m) { 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(pos, i, declaring, m); 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the method or constructor containing the type cast 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * expression represented by this object. 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public CtBehavior where() { return super.where(); } 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the line number of the source line containing the 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * type-cast expression. 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return -1 if this information is not available. 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int getLineNumber() { 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return super.getLineNumber(); 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the source file containing the type-cast expression. 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return null if this information is not available. 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public String getFileName() { 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return super.getFileName(); 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the <code>CtClass</code> object representing 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the type specified by the cast. 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public CtClass getType() throws NotFoundException { 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ConstPool cp = getConstPool(); 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int pos = currentPos; 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int index = iterator.u16bitAt(pos + 1); 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name = cp.getClassInfo(index); 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return thisClass.getClassPool().getCtClass(name); 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the list of exceptions that the expression may throw. 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This list includes both the exceptions that the try-catch statements 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * including the expression can catch and the exceptions that 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the throws declaration allows the method to throw. 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public CtClass[] mayThrow() { 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return super.mayThrow(); 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Replaces the explicit cast operator with the bytecode derived from 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the given source text. 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>$0 is available but the value is <code>null</code>. 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param statement a Java statement except try-catch. 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void replace(String statement) throws CannotCompileException { 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal thisClass.getClassFile(); // to call checkModify(). 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ConstPool constPool = getConstPool(); 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int pos = currentPos; 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int index = iterator.u16bitAt(pos + 1); 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Javac jc = new Javac(thisClass); 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ClassPool cp = thisClass.getClassPool(); 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CodeAttribute ca = iterator.get(); 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass[] params 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = new CtClass[] { cp.get(javaLangObject) }; 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass retType = getType(); 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int paramVar = ca.getMaxLocals(); 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal jc.recordParams(javaLangObject, params, true, paramVar, 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal withinStatic()); 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int retVar = jc.recordReturnType(retType, true); 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal jc.recordProceed(new ProceedForCast(index, retType)); 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* Is $_ included in the source code? 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal checkResultValue(retType, statement); 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Bytecode bytecode = jc.getBytecode(); 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal storeStack(params, true, paramVar, bytecode); 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal jc.recordLocalVariables(ca, pos); 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addConstZero(retType); 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addStore(retVar, retType); // initialize $_ 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal jc.compileStmnt(statement); 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addLoad(retVar, retType); 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal replace0(pos, bytecode, 3); 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (CompileError e) { throw new CannotCompileException(e); } 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (NotFoundException e) { throw new CannotCompileException(e); } 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (BadBytecode e) { 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCompileException("broken method"); 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* <type> $proceed(Object obj) 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static class ProceedForCast implements ProceedHandler { 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int index; 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass retType; 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ProceedForCast(int i, CtClass t) { 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal index = i; 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal retType = t; 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (gen.getMethodArgsLength(args) != 1) 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError(Javac.proceedName 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + "() cannot take more than one parameter " 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + "for cast"); 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal gen.atMethodArgs(args, new int[1], new int[1], new String[1]); 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addOpcode(Opcode.CHECKCAST); 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addIndex(index); 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal gen.setType(retType); 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void setReturnType(JvstTypeChecker c, ASTList args) 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c.atMethodArgs(args, new int[1], new int[1], new String[1]); 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c.setType(retType); 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 166