including nothing but a return statement. git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@20 30ef5769-5b8d-40dd-aea6-55b5d6557bb3tags/rel_3_17_1_ga
* | * | ||||
* @param src the source code representing the member body. | * @param src the source code representing the member body. | ||||
* It must be a single statement or block. | * 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 { | public void setBody(String src) throws CannotCompileException { | ||||
declaringClass.checkModify(); | declaringClass.checkModify(); |
* | * | ||||
* @param src the source code representing the constructor body. | * @param src the source code representing the constructor body. | ||||
* It must be a single statement or block. | * 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 { | public void setBody(String src) throws CannotCompileException { | ||||
if (src == null) | |||||
src = "super();"; | |||||
super.setBody(src); | super.setBody(src); | ||||
} | } | ||||
* | * | ||||
* @param src the source code representing the method body. | * @param src the source code representing the method body. | ||||
* It must be a single statement or block. | * 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 { | public void setBody(String src) throws CannotCompileException { | ||||
super.setBody(src); | super.setBody(src); |
/** | /** | ||||
* Creates a public constructor. | * 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>. | * 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. | * @param declaring the class to which the created method is added. | ||||
*/ | */ | ||||
public static CtConstructor make(CtClass[] parameters, | public static CtConstructor make(CtClass[] parameters, |
/** | /** | ||||
* Creates a public method. | * 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>. | * 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. | * @param declaring the class to which the created method is added. | ||||
*/ | */ | ||||
public static CtMethod make(CtClass returnType, String mname, | public static CtMethod make(CtClass returnType, String mname, |
bytecode.addOpcode(POP2); | bytecode.addOpcode(POP2); | ||||
} | } | ||||
else if (result_type == P_FLOAT) { | 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(op); | ||||
bytecode.addOpcode(SWAP); | bytecode.addOpcode(SWAP); | ||||
} | } |
package javassist.compiler; | package javassist.compiler; | ||||
import javassist.CtClass; | import javassist.CtClass; | ||||
import javassist.CtPrimitiveType; | |||||
import javassist.CtMember; | import javassist.CtMember; | ||||
import javassist.CtField; | import javassist.CtField; | ||||
import javassist.CtBehavior; | import javassist.CtBehavior; | ||||
import javassist.ClassPool; | import javassist.ClassPool; | ||||
import javassist.Modifier; | import javassist.Modifier; | ||||
import javassist.bytecode.Bytecode; | import javassist.bytecode.Bytecode; | ||||
import javassist.bytecode.Opcode; | |||||
import javassist.NotFoundException; | import javassist.NotFoundException; | ||||
import javassist.compiler.ast.*; | import javassist.compiler.ast.*; | ||||
* Compiles a method (or constructor) body. | * Compiles a method (or constructor) body. | ||||
* | * | ||||
* @src a single statement or a block. | * @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) | public Bytecode compileBody(CtBehavior method, String src) | ||||
throws CompileError | throws CompileError | ||||
recordReturnType(rtype, false); | recordReturnType(rtype, false); | ||||
boolean isVoid = rtype == CtClass.voidType; | 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; | return bytecode; | ||||
} | } | ||||
catch (NotFoundException e) { | 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 | * Makes variables $0 (this), $1, $2, ..., and $args represent method | ||||
* parameters. $args represents an array of all the parameters. | * parameters. $args represents an array of all the parameters. |
return parseTry(tbl); | return parseTry(tbl); | ||||
else if (t == SWITCH) | else if (t == SWITCH) | ||||
return parseSwitch(tbl); | return parseSwitch(tbl); | ||||
else if (t == SYNCHRONIZED) | |||||
return parseSynchronized(tbl); | |||||
else if (t == RETURN) | else if (t == RETURN) | ||||
return parseReturn(tbl); | return parseReturn(tbl); | ||||
else if (t == THROW) | else if (t == THROW) | ||||
throw new CompileError("switch is not supported", lex); | 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.statement | ||||
* : TRY block.statement | * : TRY block.statement | ||||
* [ CATCH "(" class.type Identifier ")" block.statement ]* | * [ CATCH "(" class.type Identifier ")" block.statement ]* |
<p><code>CtMethod</code> and <code>CtConstructor</code> provide | <p><code>CtMethod</code> and <code>CtConstructor</code> provide | ||||
<code>setBody()</code> for substituting a whole | <code>setBody()</code> for substituting a whole | ||||
method body. They compile the given source text into Java bytecode | 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 | <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> | <ul><table border=0> | ||||
<tr> | <tr> | ||||
In this example, <code>x</code> is a <code>int</code> field in | In this example, <code>x</code> is a <code>int</code> field in | ||||
the class <code>Point</code>. | 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 | <code>$proceed</code> if the target object and the target method name | ||||
are also given to <code>make()</code>. For example, | are also given to <code>make()</code>. For example, | ||||
<p><li>Inner classes or anonymous classes are not 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 | <p><li>Labeled <code>continue</code> and <code>break</code> statements | ||||
are not supported. | are not supported. |