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: * Instanceof operator.
025: */
026: public class Instanceof extends Expr {
027: /**
028: * Undocumented constructor. Do not use; internal-use only.
029: */
030: protected Instanceof(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 instanceof
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: * instanceof 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
055: * instanceof expression.
056: *
057: * @return null if this information is not available.
058: */
059: public String getFileName() {
060: return super .getFileName();
061: }
062:
063: /**
064: * Returns the <code>CtClass</code> object representing
065: * the type name on the right hand side
066: * of the instanceof operator.
067: */
068: public CtClass getType() throws NotFoundException {
069: ConstPool cp = getConstPool();
070: int pos = currentPos;
071: int index = iterator.u16bitAt(pos + 1);
072: String name = cp.getClassInfo(index);
073: return Descriptor.toCtClass(name, this Class.getClassPool());
074: }
075:
076: /**
077: * Returns the list of exceptions that the expression may throw.
078: * This list includes both the exceptions that the try-catch statements
079: * including the expression can catch and the exceptions that
080: * the throws declaration allows the method to throw.
081: */
082: public CtClass[] mayThrow() {
083: return super .mayThrow();
084: }
085:
086: /**
087: * Replaces the instanceof operator with the bytecode derived from
088: * the given source text.
089: *
090: * <p>$0 is available but the value is <code>null</code>.
091: *
092: * @param statement a Java statement.
093: */
094: public void replace(String statement) throws CannotCompileException {
095: ConstPool constPool = getConstPool();
096: int pos = currentPos;
097: int index = iterator.u16bitAt(pos + 1);
098:
099: Javac jc = new Javac(this Class);
100: ClassPool cp = this Class.getClassPool();
101: CodeAttribute ca = iterator.get();
102:
103: try {
104: CtClass[] params = new CtClass[] { cp.get(javaLangObject) };
105: CtClass retType = CtClass.booleanType;
106:
107: int paramVar = ca.getMaxLocals();
108: jc.recordParams(javaLangObject, params, true, paramVar,
109: withinStatic());
110: int retVar = jc.recordReturnType(retType, true);
111: jc.recordProceed(new ProceedForInstanceof(index));
112:
113: // because $type is not the return type...
114: jc.recordType(getType());
115:
116: /* Is $_ included in the source code?
117: */
118: checkResultValue(retType, statement);
119:
120: Bytecode bytecode = jc.getBytecode();
121: storeStack(params, true, paramVar, bytecode);
122: jc.recordLocalVariables(ca, pos);
123:
124: bytecode.addConstZero(retType);
125: bytecode.addStore(retVar, retType); // initialize $_
126:
127: jc.compileStmnt(statement);
128: bytecode.addLoad(retVar, retType);
129:
130: replace0(pos, bytecode, 3);
131: } catch (CompileError e) {
132: throw new CannotCompileException(e);
133: } catch (NotFoundException e) {
134: throw new CannotCompileException(e);
135: } catch (BadBytecode e) {
136: throw new CannotCompileException("broken method");
137: }
138: }
139:
140: /* boolean $proceed(Object obj)
141: */
142: static class ProceedForInstanceof implements ProceedHandler {
143: int index;
144:
145: ProceedForInstanceof(int i) {
146: index = i;
147: }
148:
149: public void doit(JvstCodeGen gen, Bytecode bytecode,
150: ASTList args) throws CompileError {
151: if (gen.getMethodArgsLength(args) != 1)
152: throw new CompileError(Javac.proceedName
153: + "() cannot take more than one parameter "
154: + "for instanceof");
155:
156: gen.atMethodArgs(args, new int[1], new int[1],
157: new String[1]);
158: bytecode.addOpcode(Opcode.INSTANCEOF);
159: bytecode.addIndex(index);
160: gen.setType(CtClass.booleanType);
161: }
162:
163: public void setReturnType(JvstTypeChecker c, ASTList args)
164: throws CompileError {
165: c.atMethodArgs(args, new int[1], new int[1], new String[1]);
166: c.setType(CtClass.booleanType);
167: }
168: }
169: }
|