aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/javassist/expr
diff options
context:
space:
mode:
authorpatriot1burke <patriot1burke@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2003-04-22 13:47:06 +0000
committerpatriot1burke <patriot1burke@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2003-04-22 13:47:06 +0000
commit069bceaf72fd0d6ffad14ce4e3e00ca91a280bde (patch)
treeb8230a15d3061c64d5a64bf9efa654d0d6311ff2 /src/main/javassist/expr
parentf610083ba0adbcb3fe92a504015fb26fb5a42530 (diff)
downloadjavassist-069bceaf72fd0d6ffad14ce4e3e00ca91a280bde.tar.gz
javassist-069bceaf72fd0d6ffad14ce4e3e00ca91a280bde.zip
This commit was generated by cvs2svn to compensate for changes in r2, which
included commits to RCS files with non-trunk default branches. git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@6 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main/javassist/expr')
-rw-r--r--src/main/javassist/expr/Cast.java162
-rw-r--r--src/main/javassist/expr/Expr.java223
-rw-r--r--src/main/javassist/expr/ExprEditor.java211
-rw-r--r--src/main/javassist/expr/FieldAccess.java300
-rw-r--r--src/main/javassist/expr/Instanceof.java165
-rw-r--r--src/main/javassist/expr/MethodCall.java220
-rw-r--r--src/main/javassist/expr/NewExpr.java224
7 files changed, 1505 insertions, 0 deletions
diff --git a/src/main/javassist/expr/Cast.java b/src/main/javassist/expr/Cast.java
new file mode 100644
index 00000000..44648e78
--- /dev/null
+++ b/src/main/javassist/expr/Cast.java
@@ -0,0 +1,162 @@
+/*
+ * This file is part of the Javassist toolkit.
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * either http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is Javassist.
+ *
+ * The Initial Developer of the Original Code is Shigeru Chiba. Portions
+ * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba.
+ * All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * The development of this software is supported in part by the PRESTO
+ * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation.
+ */
+
+package javassist.expr;
+
+import javassist.*;
+import javassist.bytecode.*;
+import javassist.compiler.*;
+import javassist.compiler.ast.ASTList;
+
+/**
+ * Explicit type cast.
+ */
+public class Cast extends Expr {
+ /**
+ * Undocumented constructor. Do not use; internal-use only.
+ */
+ Cast(int pos, CodeIterator i, CtClass declaring, MethodInfo m) {
+ super(pos, i, declaring, m);
+ }
+
+ /**
+ * Returns the method or constructor containing the type cast
+ * expression represented by this object.
+ */
+ public CtBehavior where() { return super.where(); }
+
+ /**
+ * Returns the line number of the source line containing the
+ * type-cast expression.
+ *
+ * @return -1 if this information is not available.
+ */
+ public int getLineNumber() {
+ return super.getLineNumber();
+ }
+
+ /**
+ * Returns the source file containing the type-cast expression.
+ *
+ * @return null if this information is not available.
+ */
+ public String getFileName() {
+ return super.getFileName();
+ }
+
+ /**
+ * Returns the <code>CtClass</code> object representing
+ * the type specified by the cast.
+ */
+ public CtClass getType() throws NotFoundException {
+ ConstPool cp = getConstPool();
+ int pos = currentPos;
+ int index = iterator.u16bitAt(pos + 1);
+ String name = cp.getClassInfo(index);
+ return Descriptor.toCtClass(name, thisClass.getClassPool());
+ }
+
+ /**
+ * Returns the list of exceptions that the expression may throw.
+ * This list includes both the exceptions that the try-catch statements
+ * including the expression can catch and the exceptions that
+ * the throws declaration allows the method to throw.
+ */
+ public CtClass[] mayThrow() {
+ return super.mayThrow();
+ }
+
+ /**
+ * Replaces the explicit cast operator with the bytecode derived from
+ * the given source text.
+ *
+ * <p>$0 is available but the value is <code>null</code>.
+ *
+ * @param statement a Java statement.
+ */
+ public void replace(String statement) throws CannotCompileException {
+ ConstPool constPool = getConstPool();
+ int pos = currentPos;
+ int index = iterator.u16bitAt(pos + 1);
+
+ Javac jc = new Javac(thisClass);
+ ClassPool cp = thisClass.getClassPool();
+ CodeAttribute ca = iterator.get();
+
+ try {
+ CtClass[] params
+ = new CtClass[] { cp.get(javaLangObject) };
+ CtClass retType = getType();
+
+ int paramVar = ca.getMaxLocals();
+ jc.recordParams(javaLangObject, params, true, paramVar,
+ withinStatic());
+ int retVar = jc.recordReturnType(retType, true);
+ jc.recordProceed(new ProceedForCast(index, retType));
+
+ /* Is $_ included in the source code?
+ */
+ checkResultValue(retType, statement);
+
+ Bytecode bytecode = jc.getBytecode();
+ storeStack(params, true, paramVar, bytecode);
+ jc.compileStmnt(statement);
+ bytecode.addLoad(retVar, retType);
+
+ replace0(pos, bytecode, 3);
+ }
+ catch (CompileError e) { throw new CannotCompileException(e); }
+ catch (NotFoundException e) { throw new CannotCompileException(e); }
+ catch (BadBytecode e) {
+ throw new CannotCompileException("broken method");
+ }
+ }
+
+ /* <type> $proceed(Object obj)
+ */
+ static class ProceedForCast implements ProceedHandler {
+ int index;
+ CtClass retType;
+
+ ProceedForCast(int i, CtClass t) {
+ index = i;
+ retType = t;
+ }
+
+ public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
+ throws CompileError
+ {
+ if (gen.atMethodArgsLength(args) != 1)
+ throw new CompileError(Javac.proceedName
+ + "() cannot take more than one parameter "
+ + "for cast");
+
+ gen.atMethodArgs(args, new int[1], new int[1], new String[1]);
+ bytecode.addOpcode(Opcode.CHECKCAST);
+ bytecode.addIndex(index);
+ gen.setType(retType);
+ }
+ }
+}
diff --git a/src/main/javassist/expr/Expr.java b/src/main/javassist/expr/Expr.java
new file mode 100644
index 00000000..d88d7939
--- /dev/null
+++ b/src/main/javassist/expr/Expr.java
@@ -0,0 +1,223 @@
+/*
+ * This file is part of the Javassist toolkit.
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * either http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is Javassist.
+ *
+ * The Initial Developer of the Original Code is Shigeru Chiba. Portions
+ * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba.
+ * All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * The development of this software is supported in part by the PRESTO
+ * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation.
+ */
+
+package javassist.expr;
+
+import javassist.*;
+import javassist.bytecode.*;
+import javassist.compiler.*;
+import java.util.LinkedList;
+import java.util.Iterator;
+
+/**
+ * Caller-side expression.
+ */
+abstract class Expr implements Opcode {
+ int currentPos;
+ CodeIterator iterator;
+ CtClass thisClass;
+ MethodInfo thisMethod;
+
+ boolean edited;
+ int maxLocals, maxStack;
+
+ static final String javaLangObject = "java.lang.Object";
+
+ Expr(int pos, CodeIterator i, CtClass declaring, MethodInfo m) {
+ currentPos = pos;
+ iterator = i;
+ thisClass = declaring;
+ thisMethod = m;
+ }
+
+ final ConstPool getConstPool() {
+ return thisMethod.getConstPool();
+ }
+
+ final boolean edited() { return edited; }
+
+ final int locals() { return maxLocals; }
+
+ final int stack() { return maxStack; }
+
+ /**
+ * Returns true if this method is static.
+ */
+ final boolean withinStatic() {
+ return (thisMethod.getAccessFlags() & AccessFlag.STATIC) != 0;
+ }
+
+ /**
+ * Returns the constructor or method containing the expression.
+ */
+ public CtBehavior where() {
+ MethodInfo mi = thisMethod;
+ CtBehavior[] cb = thisClass.getDeclaredBehaviors();
+ for (int i = cb.length - 1; i >= 0; --i)
+ if (cb[i].getMethodInfo() == mi)
+ return cb[i];
+
+ throw new RuntimeException("fatal: not found");
+ }
+
+ /**
+ * Returns the list of exceptions that the expression may throw.
+ * This list includes both the exceptions that the try-catch statements
+ * including the expression can catch and the exceptions that
+ * the throws declaration allows the method to throw.
+ */
+ public CtClass[] mayThrow() {
+ ClassPool pool = thisClass.getClassPool();
+ ConstPool cp = thisMethod.getConstPool();
+ LinkedList list = new LinkedList();
+ try {
+ CodeAttribute ca = thisMethod.getCodeAttribute();
+ ExceptionTable et = ca.getExceptionTable();
+ int pos = currentPos;
+ int n = et.size();
+ for (int i = 0; i < n; ++i)
+ if (et.startPc(i) <= pos && pos < et.endPc(i)) {
+ int t = et.catchType(i);
+ if (t > 0)
+ try {
+ addClass(list, pool.get(cp.getClassInfo(t)));
+ }
+ catch (NotFoundException e) {}
+ }
+ }
+ catch (NullPointerException e) {}
+
+ ExceptionsAttribute ea = thisMethod.getExceptionsAttribute();
+ if (ea != null) {
+ String[] exceptions = ea.getExceptions();
+ if (exceptions != null) {
+ int n = exceptions.length;
+ for (int i = 0; i < n; ++i)
+ try {
+ addClass(list, pool.get(exceptions[i]));
+ }
+ catch (NotFoundException e) {}
+ }
+ }
+
+ return (CtClass[])list.toArray(new CtClass[list.size()]);
+ }
+
+ private static void addClass(LinkedList list, CtClass c) {
+ Iterator it = list.iterator();
+ while (it.hasNext())
+ if (it.next() == c)
+ return;
+
+ list.add(c);
+ }
+
+ /**
+ * Returns the line number of the source line containing the
+ * expression.
+ *
+ * @return -1 if this information is not available.
+ */
+ public int getLineNumber() {
+ return thisMethod.getLineNumber(currentPos);
+ }
+
+ /**
+ * Returns the source file containing the expression.
+ *
+ * @return null if this information is not available.
+ */
+ public String getFileName() {
+ ClassFile cf = thisClass.getClassFile2();
+ if (cf == null)
+ return null;
+ else
+ return cf.getSourceFile();
+ }
+
+ static final boolean checkResultValue(CtClass retType, String prog)
+ throws CannotCompileException
+ {
+ /* Is $_ included in the source code?
+ */
+ boolean hasIt = (prog.indexOf(Javac.resultVarName) >= 0);
+ if (!hasIt && retType != CtClass.voidType)
+ throw new CannotCompileException(
+ "the resulting value is not stored in "
+ + Javac.resultVarName);
+
+ return hasIt;
+ }
+
+ /* If isStaticCall is true, null is assigned to $0. So $0 must
+ * be declared by calling Javac.recordParams().
+ *
+ * After executing this method, the current stack depth might
+ * be less than 0.
+ */
+ static final void storeStack(CtClass[] params, boolean isStaticCall,
+ int regno, Bytecode bytecode) {
+ storeStack0(0, params.length, params, regno + 1, bytecode);
+ if (isStaticCall)
+ bytecode.addOpcode(ACONST_NULL);
+
+ bytecode.addAstore(regno);
+ }
+
+ private static void storeStack0(int i, int n, CtClass[] params,
+ int regno, Bytecode bytecode) {
+ if (i >= n)
+ return;
+ else {
+ CtClass c = params[i];
+ int size;
+ if (c instanceof CtPrimitiveType)
+ size = ((CtPrimitiveType)c).getDataSize();
+ else
+ size = 1;
+
+ storeStack0(i + 1, n, params, regno + size, bytecode);
+ bytecode.addStore(regno, c);
+ }
+ }
+
+ protected void replace0(int pos, Bytecode bytecode, int size)
+ throws BadBytecode
+ {
+ byte[] code = bytecode.get();
+ edited = true;
+ int gap = code.length - size;
+ if (gap > 0)
+ iterator.insertGap(pos, gap);
+ else
+ for (int i = 0; i < size; ++i)
+ iterator.writeByte(NOP, pos + i);
+
+ iterator.write(code, pos);
+ iterator.insert(bytecode.getExceptionTable(), pos);
+ maxLocals = bytecode.getMaxLocals();
+ maxStack = bytecode.getMaxStack();
+ }
+}
diff --git a/src/main/javassist/expr/ExprEditor.java b/src/main/javassist/expr/ExprEditor.java
new file mode 100644
index 00000000..c6814ef5
--- /dev/null
+++ b/src/main/javassist/expr/ExprEditor.java
@@ -0,0 +1,211 @@
+/*
+ * This file is part of the Javassist toolkit.
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * either http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is Javassist.
+ *
+ * The Initial Developer of the Original Code is Shigeru Chiba. Portions
+ * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba.
+ * All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * The development of this software is supported in part by the PRESTO
+ * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation.
+ */
+
+package javassist.expr;
+
+import javassist.bytecode.*;
+import javassist.CtClass;
+import javassist.CannotCompileException;
+
+/**
+ * A translator of method bodies.
+ *
+ * <p>The users can define a subclass of this class to customize how to
+ * modify a method body. The overall architecture is similar to the
+ * strategy pattern.
+ *
+ * <p>If <code>instrument()</code> is called in
+ * <code>CtMethod</code>, the method body is scanned from the beginning
+ * to the end.
+ * Whenever an expression, such as a method call and a <tt>new</tt>
+ * expression (object creation),
+ * is found, <code>edit()</code> is called in <code>ExprEdit</code>.
+ * <code>edit()</code> can inspect and modify the given expression.
+ * The modification is reflected on the original method body. If
+ * <code>edit()</code> does nothing, the original method body is not
+ * changed.
+ *
+ * <p>The following code is an example:
+ *
+ * <ul><pre>
+ * CtMethod cm = ...;
+ * cm.instrument(new ExprEditor() {
+ * public void edit(MethodCall m) throws CannotCompileException {
+ * if (m.getClassName().equals("Point")) {
+ * System.out.println(m.getMethodName() + " line: "
+ * + m.getLineNumber());
+ * }
+ * });
+ * </pre></ul>
+ *
+ * <p>This code inspects all method calls appearing in the method represented
+ * by <code>cm</code> and it prints the names and the line numbers of the
+ * methods declared in class <code>Point</code>. This code does not modify
+ * the body of the method represented by <code>cm</code>. If the method
+ * body must be modified, call <code>replace()</code>
+ * in <code>MethodCall</code>.
+ *
+ * @see javassist.CtClass#instrument(ExprEditor)
+ * @see javassist.CtMethod#instrument(ExprEditor)
+ * @see javassist.CtConstructor#instrument(ExprEditor)
+ * @see MethodCall
+ * @see NewExpr
+ * @see FieldAccess
+ *
+ * @see javassist.CodeConverter
+ */
+public class ExprEditor {
+ /**
+ * Default constructor. It does nothing.
+ */
+ public ExprEditor() {}
+
+ static class NewOp {
+ NewOp next;
+ int pos;
+ String type;
+
+ NewOp(NewOp n, int p, String t) {
+ next = n;
+ pos = p;
+ type = t;
+ }
+ }
+
+ /**
+ * Undocumented method. Do not use; internal-use only.
+ */
+ public boolean doit(CtClass clazz, MethodInfo minfo)
+ throws CannotCompileException
+ {
+ CodeAttribute codeAttr = minfo.getCodeAttribute();
+ if (codeAttr == null)
+ return false;
+
+ CodeIterator iterator = codeAttr.iterator();
+ boolean edited = false;
+ int maxLocals = codeAttr.getMaxLocals();
+ int maxStack = 0;
+
+ NewOp newList = null;
+ ConstPool cp = minfo.getConstPool();
+
+ while (iterator.hasNext())
+ try {
+ Expr expr = null;
+ int pos = iterator.next();
+ int c = iterator.byteAt(pos);
+
+ if (c == Opcode.INVOKESTATIC || c == Opcode.INVOKEINTERFACE
+ || c == Opcode.INVOKEVIRTUAL) {
+ expr = new MethodCall(pos, iterator, clazz, minfo);
+ edit((MethodCall)expr);
+ }
+ else if (c == Opcode.GETFIELD || c == Opcode.GETSTATIC
+ || c == Opcode.PUTFIELD || c == Opcode.PUTSTATIC) {
+ expr = new FieldAccess(pos, iterator, clazz, minfo, c);
+ edit((FieldAccess)expr);
+ }
+ else if (c == Opcode.NEW) {
+ int index = iterator.u16bitAt(pos + 1);
+ newList = new NewOp(newList, pos,
+ cp.getClassInfo(index));
+ }
+ else if (c == Opcode.INVOKESPECIAL) {
+ if (newList != null && cp.isConstructor(newList.type,
+ iterator.u16bitAt(pos + 1)) > 0) {
+ expr = new NewExpr(pos, iterator, clazz, minfo,
+ newList.type, newList.pos);
+ edit((NewExpr)expr);
+ newList = newList.next;
+ }
+ else {
+ expr = new MethodCall(pos, iterator, clazz, minfo);
+ MethodCall mcall = (MethodCall)expr;
+ if (!mcall.getMethodName().equals(
+ MethodInfo.nameInit))
+ edit(mcall);
+ }
+ }
+ else if (c == Opcode.INSTANCEOF) {
+ expr = new Instanceof(pos, iterator, clazz, minfo);
+ edit((Instanceof)expr);
+ }
+ else if (c == Opcode.CHECKCAST) {
+ expr = new Cast(pos, iterator, clazz, minfo);
+ edit((Cast)expr);
+ }
+
+ if (expr != null && expr.edited()) {
+ edited = true;
+ if (maxLocals < expr.locals())
+ maxLocals = expr.locals();
+
+ if (maxStack < expr.stack())
+ maxStack = expr.stack();
+ }
+ }
+ catch (BadBytecode e) {
+ throw new CannotCompileException(e);
+ }
+
+ codeAttr.setMaxLocals(maxLocals);
+ codeAttr.setMaxStack(codeAttr.getMaxStack() + maxStack);
+ return edited;
+ }
+
+ /**
+ * Edits a <tt>new</tt> expression (overridable).
+ * The default implementation performs nothing.
+ *
+ * @param e the <tt>new</tt> expression creating an object.
+ */
+ public void edit(NewExpr e) throws CannotCompileException {}
+
+ /**
+ * Edits a method call (overridable).
+ * The default implementation performs nothing.
+ */
+ public void edit(MethodCall m) throws CannotCompileException {}
+
+ /**
+ * Edits a field-access expression (overridable).
+ * Field access means both read and write.
+ * The default implementation performs nothing.
+ */
+ public void edit(FieldAccess f) throws CannotCompileException {}
+
+ /**
+ * Edits an instanceof expression (overridable).
+ * The default implementation performs nothing.
+ */
+ public void edit(Instanceof i) throws CannotCompileException {}
+
+ /**
+ * Edits an expression for explicit type casting (overridable).
+ * The default implementation performs nothing.
+ */
+ public void edit(Cast c) throws CannotCompileException {}
+}
diff --git a/src/main/javassist/expr/FieldAccess.java b/src/main/javassist/expr/FieldAccess.java
new file mode 100644
index 00000000..a524b07d
--- /dev/null
+++ b/src/main/javassist/expr/FieldAccess.java
@@ -0,0 +1,300 @@
+/*
+ * This file is part of the Javassist toolkit.
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * either http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is Javassist.
+ *
+ * The Initial Developer of the Original Code is Shigeru Chiba. Portions
+ * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba.
+ * All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * The development of this software is supported in part by the PRESTO
+ * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation.
+ */
+
+package javassist.expr;
+
+import javassist.*;
+import javassist.bytecode.*;
+import javassist.compiler.*;
+import javassist.compiler.ast.ASTList;
+
+/**
+ * Expression for accessing a field.
+ */
+public class FieldAccess extends Expr {
+ int opcode;
+
+ FieldAccess(int pos, CodeIterator i, CtClass declaring, MethodInfo m,
+ int op) {
+ super(pos, i, declaring, m);
+ opcode = op;
+ }
+
+ /**
+ * Returns the method or constructor containing the field-access
+ * expression represented by this object.
+ */
+ public CtBehavior where() { return super.where(); }
+
+ /**
+ * Returns the line number of the source line containing the
+ * field access.
+ *
+ * @return -1 if this information is not available.
+ */
+ public int getLineNumber() {
+ return super.getLineNumber();
+ }
+
+ /**
+ * Returns the source file containing the field access.
+ *
+ * @return null if this information is not available.
+ */
+ public String getFileName() {
+ return super.getFileName();
+ }
+
+ /**
+ * Returns true if the field is static.
+ */
+ public boolean isStatic() {
+ return isStatic(opcode);
+ }
+
+ static boolean isStatic(int c) {
+ return c == Opcode.GETSTATIC || c == Opcode.PUTSTATIC;
+ }
+
+ /**
+ * Returns true if the field is read.
+ */
+ public boolean isReader() {
+ return opcode == Opcode.GETFIELD || opcode == Opcode.GETSTATIC;
+ }
+
+ /**
+ * Returns true if the field is written in.
+ */
+ public boolean isWriter() {
+ return opcode == Opcode.PUTFIELD || opcode == Opcode.PUTSTATIC;
+ }
+
+ /**
+ * Returns the class in which the field is declared.
+ */
+ private CtClass getCtClass() throws NotFoundException {
+ return thisClass.getClassPool().get(getClassName());
+ }
+
+ /**
+ * Returns the name of the class in which the field is declared.
+ */
+ public String getClassName() {
+ int index = iterator.u16bitAt(currentPos + 1);
+ return getConstPool().getFieldrefClassName(index);
+ }
+
+ /**
+ * Returns the name of the field.
+ */
+ public String getFieldName() {
+ int index = iterator.u16bitAt(currentPos + 1);
+ return getConstPool().getFieldrefName(index);
+ }
+
+ /**
+ * Returns the field accessed by this expression.
+ */
+ public CtField getField() throws NotFoundException {
+ CtClass cc = getCtClass();
+ return cc.getField(getFieldName());
+ }
+
+ /**
+ * Returns the list of exceptions that the expression may throw.
+ * This list includes both the exceptions that the try-catch statements
+ * including the expression can catch and the exceptions that
+ * the throws declaration allows the method to throw.
+ */
+ public CtClass[] mayThrow() {
+ return super.mayThrow();
+ }
+
+ /*
+ * Returns the type of the field.
+
+ public CtClass getFieldType() throws NotFoundException {
+ int index = iterator.u16bitAt(currentPos + 1);
+ String type = getConstPool().getFieldrefType(index);
+ return Descriptor.toCtClass(type, thisClass.getClassPool());
+ }
+ */
+
+ /**
+ * Replaces the method call with the bytecode derived from
+ * the given source text.
+ *
+ * <p>$0 is available even if the called method is static.
+ * If the field access is writing, $_ is available but the value
+ * of $_ is ignored.
+ *
+ * @param statement a Java statement.
+ */
+ public void replace(String statement) throws CannotCompileException {
+ ConstPool constPool = getConstPool();
+ int pos = currentPos;
+ int index = iterator.u16bitAt(pos + 1);
+
+ Javac jc = new Javac(thisClass);
+ CodeAttribute ca = iterator.get();
+ try {
+ CtClass[] params;
+ CtClass retType;
+ CtClass fieldType
+ = Descriptor.toCtClass(constPool.getFieldrefType(index),
+ thisClass.getClassPool());
+ boolean read = isReader();
+ if (read) {
+ params = new CtClass[0];
+ retType = fieldType;
+ }
+ else {
+ params = new CtClass[1];
+ params[0] = fieldType;
+ retType = CtClass.voidType;
+ }
+
+ int paramVar = ca.getMaxLocals();
+ jc.recordParams(constPool.getFieldrefClassName(index), params,
+ true, paramVar, withinStatic());
+
+ /* Is $_ included in the source code?
+ */
+ boolean included = checkResultValue(retType, statement);
+
+ int retVar = jc.recordReturnType(retType, included);
+ if (read)
+ jc.recordProceed(new ProceedForRead(retType, opcode,
+ index, paramVar));
+ else {
+ // because $type is not the return type...
+ jc.recordType(fieldType);
+ jc.recordProceed(new ProceedForWrite(params[0], opcode,
+ index, paramVar));
+ }
+
+ Bytecode bytecode = jc.getBytecode();
+ storeStack(params, isStatic(), paramVar, bytecode);
+ jc.compileStmnt(statement);
+ if (read)
+ bytecode.addLoad(retVar, retType);
+
+ replace0(pos, bytecode, 3);
+ }
+ catch (CompileError e) { throw new CannotCompileException(e); }
+ catch (NotFoundException e) { throw new CannotCompileException(e); }
+ catch (BadBytecode e) {
+ throw new CannotCompileException("broken method");
+ }
+ }
+
+ /* <field type> $proceed()
+ */
+ static class ProceedForRead implements ProceedHandler {
+ CtClass fieldType;
+ int opcode;
+ int targetVar, index;
+
+ ProceedForRead(CtClass type, int op, int i, int var) {
+ fieldType = type;
+ targetVar = var;
+ opcode = op;
+ index = i;
+ }
+
+ public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
+ throws CompileError
+ {
+ if (args != null && !gen.isParamListName(args))
+ throw new CompileError(Javac.proceedName
+ + "() cannot take a parameter for field reading");
+
+ int stack;
+ if (isStatic(opcode))
+ stack = 0;
+ else {
+ stack = -1;
+ bytecode.addAload(targetVar);
+ }
+
+ if (fieldType instanceof CtPrimitiveType)
+ stack += ((CtPrimitiveType)fieldType).getDataSize();
+ else
+ ++stack;
+
+ bytecode.add(opcode);
+ bytecode.addIndex(index);
+ bytecode.growStack(stack);
+ gen.setType(fieldType);
+ }
+ }
+
+ /* void $proceed(<field type>)
+ * the return type is not the field type but void.
+ */
+ static class ProceedForWrite implements ProceedHandler {
+ CtClass fieldType;
+ int opcode;
+ int targetVar, index;
+
+ ProceedForWrite(CtClass type, int op, int i, int var) {
+ fieldType = type;
+ targetVar = var;
+ opcode = op;
+ index = i;
+ }
+
+ public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
+ throws CompileError
+ {
+ if (gen.atMethodArgsLength(args) != 1)
+ throw new CompileError(Javac.proceedName
+ + "() cannot take more than one parameter "
+ + "for field writing");
+
+ int stack;
+ if (isStatic(opcode))
+ stack = 0;
+ else {
+ stack = -1;
+ bytecode.addAload(targetVar);
+ }
+
+ gen.atMethodArgs(args, new int[1], new int[1], new String[1]);
+ gen.doNumCast(fieldType);
+ if (fieldType instanceof CtPrimitiveType)
+ stack -= ((CtPrimitiveType)fieldType).getDataSize();
+ else
+ --stack;
+
+ bytecode.add(opcode);
+ bytecode.addIndex(index);
+ bytecode.growStack(stack);
+ gen.setType(CtClass.voidType);
+ gen.addNullIfVoid();
+ }
+ }
+}
diff --git a/src/main/javassist/expr/Instanceof.java b/src/main/javassist/expr/Instanceof.java
new file mode 100644
index 00000000..5b980f8e
--- /dev/null
+++ b/src/main/javassist/expr/Instanceof.java
@@ -0,0 +1,165 @@
+/*
+ * This file is part of the Javassist toolkit.
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * either http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is Javassist.
+ *
+ * The Initial Developer of the Original Code is Shigeru Chiba. Portions
+ * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba.
+ * All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * The development of this software is supported in part by the PRESTO
+ * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation.
+ */
+
+package javassist.expr;
+
+import javassist.*;
+import javassist.bytecode.*;
+import javassist.compiler.*;
+import javassist.compiler.ast.ASTList;
+
+/**
+ * Instanceof operator.
+ */
+public class Instanceof extends Expr {
+ /**
+ * Undocumented constructor. Do not use; internal-use only.
+ */
+ Instanceof(int pos, CodeIterator i, CtClass declaring, MethodInfo m) {
+ super(pos, i, declaring, m);
+ }
+
+ /**
+ * Returns the method or constructor containing the instanceof
+ * expression represented by this object.
+ */
+ public CtBehavior where() { return super.where(); }
+
+ /**
+ * Returns the line number of the source line containing the
+ * instanceof expression.
+ *
+ * @return -1 if this information is not available.
+ */
+ public int getLineNumber() {
+ return super.getLineNumber();
+ }
+
+ /**
+ * Returns the source file containing the
+ * instanceof expression.
+ *
+ * @return null if this information is not available.
+ */
+ public String getFileName() {
+ return super.getFileName();
+ }
+
+ /**
+ * Returns the <code>CtClass</code> object representing
+ * the type name on the right hand side
+ * of the instanceof operator.
+ */
+ public CtClass getType() throws NotFoundException {
+ ConstPool cp = getConstPool();
+ int pos = currentPos;
+ int index = iterator.u16bitAt(pos + 1);
+ String name = cp.getClassInfo(index);
+ return Descriptor.toCtClass(name, thisClass.getClassPool());
+ }
+
+ /**
+ * Returns the list of exceptions that the expression may throw.
+ * This list includes both the exceptions that the try-catch statements
+ * including the expression can catch and the exceptions that
+ * the throws declaration allows the method to throw.
+ */
+ public CtClass[] mayThrow() {
+ return super.mayThrow();
+ }
+
+ /**
+ * Replaces the instanceof operator with the bytecode derived from
+ * the given source text.
+ *
+ * <p>$0 is available but the value is <code>null</code>.
+ *
+ * @param statement a Java statement.
+ */
+ public void replace(String statement) throws CannotCompileException {
+ ConstPool constPool = getConstPool();
+ int pos = currentPos;
+ int index = iterator.u16bitAt(pos + 1);
+
+ Javac jc = new Javac(thisClass);
+ ClassPool cp = thisClass.getClassPool();
+ CodeAttribute ca = iterator.get();
+
+ try {
+ CtClass[] params
+ = new CtClass[] { cp.get(javaLangObject) };
+ CtClass retType = CtClass.booleanType;
+
+ int paramVar = ca.getMaxLocals();
+ jc.recordParams(javaLangObject, params, true, paramVar,
+ withinStatic());
+ int retVar = jc.recordReturnType(retType, true);
+ jc.recordProceed(new ProceedForInstanceof(index));
+
+ // because $type is not the return type...
+ jc.recordType(getType());
+
+ /* Is $_ included in the source code?
+ */
+ checkResultValue(retType, statement);
+
+ Bytecode bytecode = jc.getBytecode();
+ storeStack(params, true, paramVar, bytecode);
+ jc.compileStmnt(statement);
+ bytecode.addLoad(retVar, retType);
+
+ replace0(pos, bytecode, 3);
+ }
+ catch (CompileError e) { throw new CannotCompileException(e); }
+ catch (NotFoundException e) { throw new CannotCompileException(e); }
+ catch (BadBytecode e) {
+ throw new CannotCompileException("broken method");
+ }
+ }
+
+ /* boolean $proceed(Object obj)
+ */
+ static class ProceedForInstanceof implements ProceedHandler {
+ int index;
+
+ ProceedForInstanceof(int i) {
+ index = i;
+ }
+
+ public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
+ throws CompileError
+ {
+ if (gen.atMethodArgsLength(args) != 1)
+ throw new CompileError(Javac.proceedName
+ + "() cannot take more than one parameter "
+ + "for instanceof");
+
+ gen.atMethodArgs(args, new int[1], new int[1], new String[1]);
+ bytecode.addOpcode(Opcode.INSTANCEOF);
+ bytecode.addIndex(index);
+ gen.setType(CtClass.booleanType);
+ }
+ }
+}
diff --git a/src/main/javassist/expr/MethodCall.java b/src/main/javassist/expr/MethodCall.java
new file mode 100644
index 00000000..747380b4
--- /dev/null
+++ b/src/main/javassist/expr/MethodCall.java
@@ -0,0 +1,220 @@
+/*
+ * This file is part of the Javassist toolkit.
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * either http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is Javassist.
+ *
+ * The Initial Developer of the Original Code is Shigeru Chiba. Portions
+ * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba.
+ * All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * The development of this software is supported in part by the PRESTO
+ * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation.
+ */
+
+package javassist.expr;
+
+import javassist.*;
+import javassist.bytecode.*;
+import javassist.compiler.*;
+
+/**
+ * Method invocation (caller-side expression).
+ */
+public class MethodCall extends Expr {
+ /**
+ * Undocumented constructor. Do not use; internal-use only.
+ */
+ MethodCall(int pos, CodeIterator i, CtClass declaring, MethodInfo m) {
+ super(pos, i, declaring, m);
+ }
+
+ private int getNameAndType(ConstPool cp) {
+ String cname;
+ int pos = currentPos;
+ int c = iterator.byteAt(pos);
+ int index = iterator.u16bitAt(pos + 1);
+
+ if (c == INVOKEINTERFACE)
+ return cp.getInterfaceMethodrefNameAndType(index);
+ else
+ return cp.getMethodrefNameAndType(index);
+ }
+
+ /**
+ * Returns the method or constructor containing the method-call
+ * expression represented by this object.
+ */
+ public CtBehavior where() { return super.where(); }
+
+ /**
+ * Returns the line number of the source line containing the
+ * method call.
+ *
+ * @return -1 if this information is not available.
+ */
+ public int getLineNumber() {
+ return super.getLineNumber();
+ }
+
+ /**
+ * Returns the source file containing the method call.
+ *
+ * @return null if this information is not available.
+ */
+ public String getFileName() {
+ return super.getFileName();
+ }
+
+ /**
+ * Returns the class of the target object,
+ * which the method is called on.
+ */
+ private CtClass getCtClass() throws NotFoundException {
+ return thisClass.getClassPool().get(getClassName());
+ }
+
+ /**
+ * Returns the class name of the target object,
+ * which the method is called on.
+ */
+ public String getClassName() {
+ String cname;
+
+ ConstPool cp = getConstPool();
+ int pos = currentPos;
+ int c = iterator.byteAt(pos);
+ int index = iterator.u16bitAt(pos + 1);
+
+ if (c == INVOKEINTERFACE)
+ cname = cp.getInterfaceMethodrefClassName(index);
+ else
+ cname = cp.getMethodrefClassName(index);
+
+ return cname;
+ }
+
+ /**
+ * Returns the name of the called method.
+ */
+ public String getMethodName() {
+ ConstPool cp = getConstPool();
+ int nt = getNameAndType(cp);
+ return cp.getUtf8Info(cp.getNameAndTypeName(nt));
+ }
+
+ /**
+ * Returns the called method.
+ */
+ public CtMethod getMethod() throws NotFoundException {
+ return getCtClass().getMethod(getMethodName(), getMethodDesc());
+ }
+
+ private String getMethodDesc() {
+ ConstPool cp = getConstPool();
+ int nt = getNameAndType(cp);
+ return cp.getUtf8Info(cp.getNameAndTypeDescriptor(nt));
+ }
+
+ /**
+ * Returns the list of exceptions that the expression may throw.
+ * This list includes both the exceptions that the try-catch statements
+ * including the expression can catch and the exceptions that
+ * the throws declaration allows the method to throw.
+ */
+ public CtClass[] mayThrow() {
+ return super.mayThrow();
+ }
+
+ /*
+ * Returns the parameter types of the called method.
+
+ public CtClass[] getParameterTypes() throws NotFoundException {
+ return Descriptor.getParameterTypes(getMethodDesc(),
+ thisClass.getClassPool());
+ }
+ */
+
+ /*
+ * Returns the return type of the called method.
+
+ public CtClass getReturnType() throws NotFoundException {
+ return Descriptor.getReturnType(getMethodDesc(),
+ thisClass.getClassPool());
+ }
+ */
+
+ /**
+ * Replaces the method call with the bytecode derived from
+ * the given source text.
+ *
+ * <p>$0 is available even if the called method is static.
+ *
+ * @param statement a Java statement.
+ */
+ public void replace(String statement) throws CannotCompileException {
+ ConstPool constPool = getConstPool();
+ int pos = currentPos;
+ int index = iterator.u16bitAt(pos + 1);
+
+ String classname, methodname, signature;
+ int opcodeSize;
+ int c = iterator.byteAt(pos);
+ if (c == INVOKEINTERFACE) {
+ opcodeSize = 5;
+ classname = constPool.getInterfaceMethodrefClassName(index);
+ methodname = constPool.getInterfaceMethodrefName(index);
+ signature = constPool.getInterfaceMethodrefType(index);
+ }
+ else if (c == INVOKESTATIC
+ || c == INVOKESPECIAL || c == INVOKEVIRTUAL) {
+ opcodeSize = 3;
+ classname = constPool.getMethodrefClassName(index);
+ methodname = constPool.getMethodrefName(index);
+ signature = constPool.getMethodrefType(index);
+ }
+ else
+ throw new CannotCompileException("not method invocation");
+
+ Javac jc = new Javac(thisClass);
+ ClassPool cp = thisClass.getClassPool();
+ CodeAttribute ca = iterator.get();
+ try {
+ CtClass[] params = Descriptor.getParameterTypes(signature, cp);
+ CtClass retType = Descriptor.getReturnType(signature, cp);
+ int paramVar = ca.getMaxLocals();
+ jc.recordParams(classname, params,
+ true, paramVar, withinStatic());
+ int retVar = jc.recordReturnType(retType, true);
+ jc.recordProceed(Javac.param0Name, methodname);
+
+ /* Is $_ included in the source code?
+ */
+ checkResultValue(retType, statement);
+
+ Bytecode bytecode = jc.getBytecode();
+ storeStack(params, c == INVOKESTATIC, paramVar, bytecode);
+ jc.compileStmnt(statement);
+ if (retType != CtClass.voidType)
+ bytecode.addLoad(retVar, retType);
+
+ replace0(pos, bytecode, opcodeSize);
+ }
+ catch (CompileError e) { throw new CannotCompileException(e); }
+ catch (NotFoundException e) { throw new CannotCompileException(e); }
+ catch (BadBytecode e) {
+ throw new CannotCompileException("broken method");
+ }
+ }
+}
diff --git a/src/main/javassist/expr/NewExpr.java b/src/main/javassist/expr/NewExpr.java
new file mode 100644
index 00000000..73546238
--- /dev/null
+++ b/src/main/javassist/expr/NewExpr.java
@@ -0,0 +1,224 @@
+/*
+ * This file is part of the Javassist toolkit.
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * either http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is Javassist.
+ *
+ * The Initial Developer of the Original Code is Shigeru Chiba. Portions
+ * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba.
+ * All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * The development of this software is supported in part by the PRESTO
+ * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation.
+ */
+
+package javassist.expr;
+
+import javassist.*;
+import javassist.bytecode.*;
+import javassist.compiler.*;
+import javassist.compiler.ast.ASTree;
+import javassist.compiler.ast.ASTList;
+
+/**
+ * Object creation (<tt>new</tt> expression).
+ */
+public class NewExpr extends Expr {
+ String newTypeName;
+ int newPos;
+
+ /**
+ * Undocumented constructor. Do not use; internal-use only.
+ */
+ NewExpr(int pos, CodeIterator i, CtClass declaring, MethodInfo m,
+ String type, int np)
+ {
+ super(pos, i, declaring, m);
+ newTypeName = type;
+ newPos = np;
+ }
+
+ private int getNameAndType(ConstPool cp) {
+ String cname;
+ int pos = currentPos;
+ int c = iterator.byteAt(pos);
+ int index = iterator.u16bitAt(pos + 1);
+
+ if (c == INVOKEINTERFACE)
+ return cp.getInterfaceMethodrefNameAndType(index);
+ else
+ return cp.getMethodrefNameAndType(index);
+ }
+
+ /**
+ * Returns the method or constructor containing the <tt>new</tt>
+ * expression represented by this object.
+ */
+ public CtBehavior where() { return super.where(); }
+
+ /**
+ * Returns the line number of the source line containing the
+ * <tt>new</tt> expression.
+ *
+ * @return -1 if this information is not available.
+ */
+ public int getLineNumber() {
+ return super.getLineNumber();
+ }
+
+ /**
+ * Returns the source file containing the <tt>new</tt> expression.
+ *
+ * @return null if this information is not available.
+ */
+ public String getFileName() {
+ return super.getFileName();
+ }
+
+ /**
+ * Returns the class of the created object.
+ */
+ private CtClass getCtClass() throws NotFoundException {
+ return thisClass.getClassPool().get(newTypeName);
+ }
+
+ /**
+ * Returns the class name of the created object.
+ */
+ public String getClassName() {
+ return newTypeName;
+ }
+
+ /**
+ * Returns the constructor called for creating the object.
+ */
+ public CtConstructor getConstructor() throws NotFoundException {
+ ConstPool cp = getConstPool();
+ int index = iterator.u16bitAt(currentPos + 1);
+ String desc = cp.getMethodrefType(index);
+ return getCtClass().getConstructor(desc);
+ }
+
+ /**
+ * Returns the list of exceptions that the expression may throw.
+ * This list includes both the exceptions that the try-catch statements
+ * including the expression can catch and the exceptions that
+ * the throws declaration allows the method to throw.
+ */
+ public CtClass[] mayThrow() {
+ return super.mayThrow();
+ }
+
+ /*
+ * Returns the parameter types of the constructor.
+
+ public CtClass[] getParameterTypes() throws NotFoundException {
+ ConstPool cp = getConstPool();
+ int index = iterator.u16bitAt(currentPos + 1);
+ String desc = cp.getMethodrefType(index);
+ return Descriptor.getParameterTypes(desc, thisClass.getClassPool());
+ }
+ */
+
+ private int canReplace() throws CannotCompileException {
+ int op = iterator.byteAt(newPos + 3);
+ if (op == Opcode.DUP)
+ return 4;
+ else if (op == Opcode.DUP_X1
+ && iterator.byteAt(newPos + 4) == Opcode.SWAP)
+ return 5;
+ else
+ throw new CannotCompileException(
+ "sorry, cannot edit NEW followed by no DUP");
+ }
+
+ /**
+ * Replaces the <tt>new</tt> expression with the bytecode derived from
+ * the given source text.
+ *
+ * <p>$0 is available but the value is null.
+ *
+ * @param statement a Java statement.
+ */
+ public void replace(String statement) throws CannotCompileException {
+ final int bytecodeSize = 3;
+ int pos = newPos;
+
+ int newIndex = iterator.u16bitAt(pos + 1);
+
+ /* delete the preceding NEW and DUP (or DUP_X1, SWAP) instructions.
+ */
+ int end = pos + canReplace();
+ for (int i = pos; i < end; ++i)
+ iterator.writeByte(NOP, i);
+
+ ConstPool constPool = getConstPool();
+ pos = currentPos;
+ int methodIndex = iterator.u16bitAt(pos + 1); // constructor
+
+ String signature = constPool.getMethodrefType(methodIndex);
+
+ Javac jc = new Javac(thisClass);
+ ClassPool cp = thisClass.getClassPool();
+ CodeAttribute ca = iterator.get();
+ try {
+ CtClass[] params = Descriptor.getParameterTypes(signature, cp);
+ CtClass newType = cp.get(newTypeName);
+ int paramVar = ca.getMaxLocals();
+ jc.recordParams(newTypeName, params,
+ true, paramVar, withinStatic());
+ int retVar = jc.recordReturnType(newType, true);
+ jc.recordProceed(new ProceedForNew(newType, newIndex,
+ methodIndex));
+
+ /* Is $_ included in the source code?
+ */
+ checkResultValue(newType, statement);
+
+ Bytecode bytecode = jc.getBytecode();
+ storeStack(params, true, paramVar, bytecode);
+ jc.compileStmnt(statement);
+ bytecode.addAload(retVar);
+
+ replace0(pos, bytecode, bytecodeSize);
+ }
+ catch (CompileError e) { throw new CannotCompileException(e); }
+ catch (NotFoundException e) { throw new CannotCompileException(e); }
+ catch (BadBytecode e) {
+ throw new CannotCompileException("broken method");
+ }
+ }
+
+ static class ProceedForNew implements ProceedHandler {
+ CtClass newType;
+ int newIndex, methodIndex;
+
+ ProceedForNew(CtClass nt, int ni, int mi) {
+ newType = nt;
+ newIndex = ni;
+ methodIndex = mi;
+ }
+
+ public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
+ throws CompileError
+ {
+ bytecode.addOpcode(NEW);
+ bytecode.addIndex(newIndex);
+ bytecode.addOpcode(DUP);
+ gen.atMethodCall2(newType, MethodInfo.nameInit,
+ args, false, true);
+ gen.setType(newType);
+ }
+ }
+}