*
* @param src the source code representing the member body.
* It must be a single statement or block.
+ * If it is <code>null</code>, the substituted member
+ * body does nothing except returning zero or null.
*/
public void setBody(String src) throws CannotCompileException {
declaringClass.checkModify();
*
* @param src the source code representing the constructor body.
* It must be a single statement or block.
+ * If it is <code>null</code>, the substituted
+ * constructor body does nothing except calling
+ * <code>super()</code>.
*/
public void setBody(String src) throws CannotCompileException {
+ if (src == null)
+ src = "super();";
+
super.setBody(src);
}
*
* @param src the source code representing the method body.
* It must be a single statement or block.
+ * If it is <code>null</code>, the substituted method
+ * body does nothing except returning zero or null.
*/
public void setBody(String src) throws CannotCompileException {
super.setBody(src);
/**
* Creates a public constructor.
*
- * @param returnType the type of the returned value
- * @param mname the method name
- * @param parameters a list of the parameter types
- * @param exceptions a list of the exception types
- * @param src the source text of the method body.
+ * @param returnType the type of the returned value.
+ * @param mname the method name.
+ * @param parameters a list of the parameter types.
+ * @param exceptions a list of the exception types.
+ * @param body the source text of the constructor body.
* It must be a block surrounded by <code>{}</code>.
+ * If it is <code>null</code>, the substituted
+ * constructor body does nothing except calling
+ * <code>super()</code>.
* @param declaring the class to which the created method is added.
*/
public static CtConstructor make(CtClass[] parameters,
/**
* Creates a public method.
*
- * @param returnType the type of the returned value
- * @param mname the method name
- * @param parameters a list of the parameter types
- * @param exceptions a list of the exception types
- * @param src the source text of the method body.
+ * @param returnType the type of the returned value.
+ * @param mname the method name.
+ * @param parameters a list of the parameter types.
+ * @param exceptions a list of the exception types.
+ * @param body the source text of the method body.
* It must be a block surrounded by <code>{}</code>.
+ * If it is <code>null</code>, the created method
+ * does nothing except returning zero or null.
* @param declaring the class to which the created method is added.
*/
public static CtMethod make(CtClass returnType, String mname,
bytecode.addOpcode(POP2);
}
else if (result_type == P_FLOAT) {
- bytecode.addOpcode(SWAP);
+ if (type1_p == P_LONG) {
+ bytecode.addOpcode(DUP_X2);
+ bytecode.addOpcode(POP);
+ }
+ else
+ bytecode.addOpcode(SWAP);
+
bytecode.addOpcode(op);
bytecode.addOpcode(SWAP);
}
package javassist.compiler;
import javassist.CtClass;
+import javassist.CtPrimitiveType;
import javassist.CtMember;
import javassist.CtField;
import javassist.CtBehavior;
import javassist.ClassPool;
import javassist.Modifier;
import javassist.bytecode.Bytecode;
+import javassist.bytecode.Opcode;
import javassist.NotFoundException;
import javassist.compiler.ast.*;
* Compiles a method (or constructor) body.
*
* @src a single statement or a block.
+ * If null, this method produces a body returning zero or null.
*/
public Bytecode compileBody(CtBehavior method, String src)
throws CompileError
recordReturnType(rtype, false);
boolean isVoid = rtype == CtClass.voidType;
- Parser p = new Parser(new Lex(src));
- SymbolTable stb = new SymbolTable(stable);
- Stmnt s = p.parseStatement(stb);
- gen.atMethodBody(s, method instanceof CtConstructor, isVoid);
+ if (src == null)
+ makeDefaultBody(bytecode, rtype);
+ else {
+ Parser p = new Parser(new Lex(src));
+ SymbolTable stb = new SymbolTable(stable);
+ Stmnt s = p.parseStatement(stb);
+ gen.atMethodBody(s, method instanceof CtConstructor, isVoid);
+ }
+
return bytecode;
}
catch (NotFoundException e) {
}
}
+ private static void makeDefaultBody(Bytecode b, CtClass type) {
+ int op;
+ int value;
+ if (type instanceof CtPrimitiveType) {
+ CtPrimitiveType pt = (CtPrimitiveType)type;
+ op = pt.getReturnOp();
+ if (op == Opcode.DRETURN)
+ value = Opcode.DCONST_0;
+ else if (op == Opcode.FRETURN)
+ value = Opcode.FCONST_0;
+ else if (op == Opcode.LRETURN)
+ value = Opcode.LCONST_0;
+ else if (op == Opcode.RETURN)
+ value = Opcode.NOP;
+ else
+ value = Opcode.ICONST_0;
+ }
+ else {
+ op = Opcode.ARETURN;
+ value = Opcode.ACONST_NULL;
+ }
+
+ if (value != Opcode.NOP)
+ b.addOpcode(value);
+
+ b.addOpcode(op);
+ }
+
/**
* Makes variables $0 (this), $1, $2, ..., and $args represent method
* parameters. $args represents an array of all the parameters.
return parseTry(tbl);
else if (t == SWITCH)
return parseSwitch(tbl);
+ else if (t == SYNCHRONIZED)
+ return parseSynchronized(tbl);
else if (t == RETURN)
return parseReturn(tbl);
else if (t == THROW)
throw new CompileError("switch is not supported", lex);
}
+ /* synchronized.statement :
+ * SYNCHRONIZED "(" expression ")" block.statement
+ */
+ private Stmnt parseSynchronized(SymbolTable tbl) throws CompileError {
+ throw new CompileError("synchronized is not supported", lex);
+ }
+
/* try.statement
* : TRY block.statement
* [ CATCH "(" class.type Identifier ")" block.statement ]*
<p><code>CtMethod</code> and <code>CtConstructor</code> provide
<code>setBody()</code> for substituting a whole
method body. They compile the given source text into Java bytecode
-and substitutes it for the original method body.
+and substitutes it for the original method body. If the given source
+text is <code>null</code>, the substituted body includes only a
+<code>return</code> statement, which returns zero or null unless the
+result type is <code>void</code>.
<p>In the source text given to <code>setBody()</code>, the identifiers
-starting with $ have special meaning
+starting with <code>$</code> have special meaning
<ul><table border=0>
<tr>
In this example, <code>x</code> is a <code>int</code> field in
the class <code>Point</code>.
-<p>The source text passed to <code>make()</code> can refer to
+<p>The source text passed to <code>make()</code> can include the
+identifiers starting with <code>$</code> except <code>$_</code>
+as in <code>setBody()</code>.
+It can also include
<code>$proceed</code> if the target object and the target method name
are also given to <code>make()</code>. For example,
<p><li>Inner classes or anonymous classes are not supported.
-<p><li><code>switch</code> statements are not supported yet.
+<p><li><code>switch</code> or <code>synchronized</code>
+statements are not supported yet.
<p><li>Labeled <code>continue</code> and <code>break</code> statements
are not supported.