001: /*
002: * Javassist, a Java-bytecode translator toolkit.
003: * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.
004: *
005: * The contents of this file are subject to the Mozilla Public License Version
006: * 1.1 (the "License"); you may not use this file except in compliance with
007: * the License. Alternatively, the contents of this file may be used under
008: * the terms of the GNU Lesser General Public License Version 2.1 or later.
009: *
010: * Software distributed under the License is distributed on an "AS IS" basis,
011: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
012: * for the specific language governing rights and limitations under the
013: * License.
014: */
015:
016: package javassist.expr;
017:
018: import javassist.*;
019: import javassist.bytecode.*;
020: import javassist.compiler.*;
021: import javassist.compiler.ast.ASTList;
022:
023: /**
024: * Explicit type cast.
025: */
026: public class Cast extends Expr {
027: /**
028: * Undocumented constructor. Do not use; internal-use only.
029: */
030: protected Cast(int pos, CodeIterator i, CtClass declaring,
031: MethodInfo m) {
032: super (pos, i, declaring, m);
033: }
034:
035: /**
036: * Returns the method or constructor containing the type cast
037: * expression represented by this object.
038: */
039: public CtBehavior where() {
040: return super .where();
041: }
042:
043: /**
044: * Returns the line number of the source line containing the
045: * type-cast expression.
046: *
047: * @return -1 if this information is not available.
048: */
049: public int getLineNumber() {
050: return super .getLineNumber();
051: }
052:
053: /**
054: * Returns the source file containing the type-cast expression.
055: *
056: * @return null if this information is not available.
057: */
058: public String getFileName() {
059: return super .getFileName();
060: }
061:
062: /**
063: * Returns the <code>CtClass</code> object representing
064: * the type specified by the cast.
065: */
066: public CtClass getType() throws NotFoundException {
067: ConstPool cp = getConstPool();
068: int pos = currentPos;
069: int index = iterator.u16bitAt(pos + 1);
070: String name = cp.getClassInfo(index);
071: return Descriptor.toCtClass(name, this Class.getClassPool());
072: }
073:
074: /**
075: * Returns the list of exceptions that the expression may throw.
076: * This list includes both the exceptions that the try-catch statements
077: * including the expression can catch and the exceptions that
078: * the throws declaration allows the method to throw.
079: */
080: public CtClass[] mayThrow() {
081: return super .mayThrow();
082: }
083:
084: /**
085: * Replaces the explicit cast operator with the bytecode derived from
086: * the given source text.
087: *
088: * <p>$0 is available but the value is <code>null</code>.
089: *
090: * @param statement a Java statement.
091: */
092: public void replace(String statement) throws CannotCompileException {
093: ConstPool constPool = getConstPool();
094: int pos = currentPos;
095: int index = iterator.u16bitAt(pos + 1);
096:
097: Javac jc = new Javac(this Class);
098: ClassPool cp = this Class.getClassPool();
099: CodeAttribute ca = iterator.get();
100:
101: try {
102: CtClass[] params = new CtClass[] { cp.get(javaLangObject) };
103: CtClass retType = getType();
104:
105: int paramVar = ca.getMaxLocals();
106: jc.recordParams(javaLangObject, params, true, paramVar,
107: withinStatic());
108: int retVar = jc.recordReturnType(retType, true);
109: jc.recordProceed(new ProceedForCast(index, retType));
110:
111: /* Is $_ included in the source code?
112: */
113: checkResultValue(retType, statement);
114:
115: Bytecode bytecode = jc.getBytecode();
116: storeStack(params, true, paramVar, bytecode);
117: jc.recordLocalVariables(ca, pos);
118:
119: bytecode.addConstZero(retType);
120: bytecode.addStore(retVar, retType); // initialize $_
121:
122: jc.compileStmnt(statement);
123: bytecode.addLoad(retVar, retType);
124:
125: replace0(pos, bytecode, 3);
126: } catch (CompileError e) {
127: throw new CannotCompileException(e);
128: } catch (NotFoundException e) {
129: throw new CannotCompileException(e);
130: } catch (BadBytecode e) {
131: throw new CannotCompileException("broken method");
132: }
133: }
134:
135: /* <type> $proceed(Object obj)
136: */
137: static class ProceedForCast implements ProceedHandler {
138: int index;
139: CtClass retType;
140:
141: ProceedForCast(int i, CtClass t) {
142: index = i;
143: retType = t;
144: }
145:
146: public void doit(JvstCodeGen gen, Bytecode bytecode,
147: ASTList args) throws CompileError {
148: if (gen.getMethodArgsLength(args) != 1)
149: throw new CompileError(Javac.proceedName
150: + "() cannot take more than one parameter "
151: + "for cast");
152:
153: gen.atMethodArgs(args, new int[1], new int[1],
154: new String[1]);
155: bytecode.addOpcode(Opcode.CHECKCAST);
156: bytecode.addIndex(index);
157: gen.setType(retType);
158: }
159:
160: public void setReturnType(JvstTypeChecker c, ASTList args)
161: throws CompileError {
162: c.atMethodArgs(args, new int[1], new int[1], new String[1]);
163: c.setType(retType);
164: }
165: }
166: }
|