aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main/javassist/CtBehavior.java2
-rw-r--r--src/main/javassist/CtConstructor.java6
-rw-r--r--src/main/javassist/CtMethod.java2
-rw-r--r--src/main/javassist/CtNewConstructor.java13
-rw-r--r--src/main/javassist/CtNewMethod.java12
-rw-r--r--src/main/javassist/compiler/CodeGen.java8
-rw-r--r--src/main/javassist/compiler/Javac.java44
-rw-r--r--src/main/javassist/compiler/Parser.java9
-rw-r--r--tutorial/tutorial2.html15
9 files changed, 92 insertions, 19 deletions
diff --git a/src/main/javassist/CtBehavior.java b/src/main/javassist/CtBehavior.java
index f040b87b..35ea4061 100644
--- a/src/main/javassist/CtBehavior.java
+++ b/src/main/javassist/CtBehavior.java
@@ -147,6 +147,8 @@ public abstract class CtBehavior extends CtMember {
*
* @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();
diff --git a/src/main/javassist/CtConstructor.java b/src/main/javassist/CtConstructor.java
index e44e6db0..403ce95d 100644
--- a/src/main/javassist/CtConstructor.java
+++ b/src/main/javassist/CtConstructor.java
@@ -283,8 +283,14 @@ public final class CtConstructor extends CtBehavior {
*
* @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);
}
diff --git a/src/main/javassist/CtMethod.java b/src/main/javassist/CtMethod.java
index 7e100717..22796467 100644
--- a/src/main/javassist/CtMethod.java
+++ b/src/main/javassist/CtMethod.java
@@ -304,6 +304,8 @@ public final class CtMethod extends CtBehavior {
*
* @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);
diff --git a/src/main/javassist/CtNewConstructor.java b/src/main/javassist/CtNewConstructor.java
index a461bb19..49e7465a 100644
--- a/src/main/javassist/CtNewConstructor.java
+++ b/src/main/javassist/CtNewConstructor.java
@@ -74,12 +74,15 @@ public class CtNewConstructor {
/**
* 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,
diff --git a/src/main/javassist/CtNewMethod.java b/src/main/javassist/CtNewMethod.java
index 525a1216..4853c2fd 100644
--- a/src/main/javassist/CtNewMethod.java
+++ b/src/main/javassist/CtNewMethod.java
@@ -84,12 +84,14 @@ public class CtNewMethod {
/**
* 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,
diff --git a/src/main/javassist/compiler/CodeGen.java b/src/main/javassist/compiler/CodeGen.java
index 35ca2605..d0009429 100644
--- a/src/main/javassist/compiler/CodeGen.java
+++ b/src/main/javassist/compiler/CodeGen.java
@@ -1090,7 +1090,13 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
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);
}
diff --git a/src/main/javassist/compiler/Javac.java b/src/main/javassist/compiler/Javac.java
index de322cdf..491cff45 100644
--- a/src/main/javassist/compiler/Javac.java
+++ b/src/main/javassist/compiler/Javac.java
@@ -16,6 +16,7 @@
package javassist.compiler;
import javassist.CtClass;
+import javassist.CtPrimitiveType;
import javassist.CtMember;
import javassist.CtField;
import javassist.CtBehavior;
@@ -25,6 +26,7 @@ import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.Modifier;
import javassist.bytecode.Bytecode;
+import javassist.bytecode.Opcode;
import javassist.NotFoundException;
import javassist.compiler.ast.*;
@@ -172,6 +174,7 @@ public class Javac {
* 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
@@ -191,10 +194,15 @@ public class Javac {
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) {
@@ -202,6 +210,34 @@ public class Javac {
}
}
+ 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.
diff --git a/src/main/javassist/compiler/Parser.java b/src/main/javassist/compiler/Parser.java
index 3bddb7c8..f1865951 100644
--- a/src/main/javassist/compiler/Parser.java
+++ b/src/main/javassist/compiler/Parser.java
@@ -262,6 +262,8 @@ public final class Parser implements TokenId {
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)
@@ -403,6 +405,13 @@ public final class Parser implements TokenId {
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 ]*
diff --git a/tutorial/tutorial2.html b/tutorial/tutorial2.html
index 5016474a..31d75f0b 100644
--- a/tutorial/tutorial2.html
+++ b/tutorial/tutorial2.html
@@ -489,10 +489,13 @@ catch (java.io.IOException e) {
<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>
@@ -1095,7 +1098,10 @@ point.addMethod(m);
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,
@@ -1207,7 +1213,8 @@ supported.
<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.