git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@16 30ef5769-5b8d-40dd-aea6-55b5d6557bb3tags/rel_3_17_1_ga
@@ -192,6 +192,30 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
return sbuf.toString(); | |||
} | |||
protected static int jvmTypeNameToExprType(char type) { | |||
switch(type) { | |||
case 'Z' : | |||
return BOOLEAN; | |||
case 'B' : | |||
return BYTE; | |||
case 'C' : | |||
return CHAR; | |||
case 'S' : | |||
return SHORT; | |||
case 'I' : | |||
return INT; | |||
case 'J' : | |||
return LONG; | |||
case 'F' : | |||
return FLOAT; | |||
case 'D' : | |||
return DOUBLE; | |||
case 'V' : | |||
return VOID; | |||
default : | |||
return CLASS; | |||
} | |||
} | |||
public void atASTList(ASTList n) throws CompileError { fatal(); } | |||
@@ -184,10 +184,18 @@ public class JvstCodeGen extends MemberCodeGen { | |||
*/ | |||
protected void atCastToRtype(CastExpr expr) throws CompileError { | |||
expr.getOprand().accept(this); | |||
if (!isRefType(exprType) || arrayDim > 0) | |||
throw new CompileError("invalid type for " + returnCastName); | |||
compileUnwrapValue(returnType, bytecode); | |||
if (exprType == VOID || isRefType(exprType) || arrayDim > 0) | |||
compileUnwrapValue(returnType, bytecode); | |||
else if (returnType instanceof CtPrimitiveType) { | |||
CtPrimitiveType pt = (CtPrimitiveType)returnType; | |||
int destType = jvmTypeNameToExprType(pt.getDescriptor()); | |||
atNumCastExpr(exprType, destType); | |||
exprType = destType; | |||
arrayDim = 0; | |||
className = null; | |||
} | |||
else | |||
throw new CompileError("invalid cast"); | |||
} | |||
protected void atCastToWrapper(CastExpr expr) throws CompileError { | |||
@@ -583,15 +591,22 @@ public class JvstCodeGen extends MemberCodeGen { | |||
protected void compileUnwrapValue(CtClass type, Bytecode code) | |||
throws CompileError | |||
{ | |||
if (type == CtClass.voidType) { | |||
addNullIfVoid(); | |||
return; | |||
} | |||
if (exprType == VOID) | |||
throw new CompileError("invalid type for " + returnCastName); | |||
if (type instanceof CtPrimitiveType) { | |||
CtPrimitiveType pt = (CtPrimitiveType)type; | |||
if (pt != CtClass.voidType) { | |||
String wrapper = pt.getWrapperName(); | |||
code.addCheckcast(wrapper); | |||
code.addInvokevirtual(wrapper, pt.getGetMethodName(), | |||
pt.getGetMethodDescriptor()); | |||
setType(type); | |||
} | |||
// pt is not voidType. | |||
String wrapper = pt.getWrapperName(); | |||
code.addCheckcast(wrapper); | |||
code.addInvokevirtual(wrapper, pt.getGetMethodName(), | |||
pt.getGetMethodDescriptor()); | |||
setType(type); | |||
} | |||
else { | |||
code.addCheckcast(type); |
@@ -350,15 +350,28 @@ For example, this is a typical use: | |||
$_ = ($r)result;</pre></ul> | |||
<p>If the result type is a primitive type, then <code>($r)</code> | |||
converts from the wrapper type to the primitive type. | |||
follows special semantics. First, if the operand type of the cast | |||
expression is a primitive type, <code>($r)</code> works as a normal | |||
cast operator to the result type. | |||
On the other hand, if the operand type is a wrapper type, | |||
<code>($r)</code> converts from the wrapper type to the result type. | |||
For example, if the result type is <code>int</code>, then | |||
<code>($r)</code> converts from <code>java.lang.Integer</code> to | |||
<code>int</code>. | |||
<p>If the result type is <code>void</code>, then | |||
<code>($r)</code> does not convert a type; it does nothing. | |||
Moreover, the soruce text can include a <code>return</code> | |||
statement with a resulting value: | |||
However, if the operand is a call to a <code>void</code> method, | |||
then <code>($r)</code> results in <code>null</code>. For example, | |||
<ul><pre>$_ = ($r)foo();</pre></ul> | |||
<p>is a valid statement if the result type is <code>void</code>. | |||
Here, <code>foo()</code> is a <code>void</code> method. | |||
<p>The cast operator <code>($r)</code> is also useful in a | |||
<code>return</code> statement. Even if the result type is | |||
<code>void</code>, the following <code>return</code> statement is valid: | |||
<ul><pre>return ($r)result;</pre></ul> | |||