From f39d058e65fb1a8b53a965f3ef20b38337ccfd76 Mon Sep 17 00:00:00 2001 From: chiba Date: Mon, 30 Aug 2004 17:10:34 +0000 Subject: [PATCH] implemented CtField#getConstantValue(). git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@128 30ef5769-5b8d-40dd-aea6-55b5d6557bb3 --- src/main/javassist/CtField.java | 36 +++++++ src/main/javassist/bytecode/ConstPool.java | 2 +- src/main/javassist/bytecode/FieldInfo.java | 28 +++++- src/main/javassist/compiler/ast/CastExpr.java | 2 + src/main/javassist/compiler/ast/CondExpr.java | 2 + .../javassist/compiler/ast/DoubleConst.java | 54 ++++++++++ src/main/javassist/compiler/ast/Expr.java | 4 + src/main/javassist/compiler/ast/IntConst.java | 98 +++++++++++++++++++ 8 files changed, 224 insertions(+), 2 deletions(-) diff --git a/src/main/javassist/CtField.java b/src/main/javassist/CtField.java index baf01812..bbf76338 100644 --- a/src/main/javassist/CtField.java +++ b/src/main/javassist/CtField.java @@ -244,6 +244,42 @@ public class CtField extends CtMember { fieldInfo.setDescriptor(Descriptor.of(clazz)); } + /** + * Returns the value of this field if it is a constant field. + * This method works only if the field type is a primitive type + * or String type. Otherwise, it returns null. + * A constant field is static and final. + * + * @return a Integer, Long, Float, + * Double, or String object + * representing the constant value. + * null if it is not a constant field + * or if the field type is not a primitive type + * or String. + */ + public Object getConstantValue() { + int index = fieldInfo.getConstantValue(); + if (index == 0) + return null; + + ConstPool cp = fieldInfo.getConstPool(); + switch (cp.getTag(index)) { + case ConstPool.CONST_Long : + return new Long(cp.getLongInfo(index)); + case ConstPool.CONST_Float : + return new Float(cp.getFloatInfo(index)); + case ConstPool.CONST_Double : + return new Double(cp.getDoubleInfo(index)); + case ConstPool.CONST_Integer : + return new Integer(cp.getIntegerInfo(index)); + case ConstPool.CONST_String : + return cp.getStringInfo(index); + default : + throw new RuntimeException("bad tag: " + cp.getTag(index) + + " at " + index); + } + } + /** * Obtains an attribute with the given name. * If that attribute is not found in the class file, this diff --git a/src/main/javassist/bytecode/ConstPool.java b/src/main/javassist/bytecode/ConstPool.java index 6f0b2bef..920ac703 100644 --- a/src/main/javassist/bytecode/ConstPool.java +++ b/src/main/javassist/bytecode/ConstPool.java @@ -68,7 +68,7 @@ public final class ConstPool { /** * CONSTANT_Float */ - public static final int CONST_Float = IntegerInfo.tag; + public static final int CONST_Float = FloatInfo.tag; /** * CONSTANT_Long diff --git a/src/main/javassist/bytecode/FieldInfo.java b/src/main/javassist/bytecode/FieldInfo.java index 54ae1ba6..ff45f1ba 100644 --- a/src/main/javassist/bytecode/FieldInfo.java +++ b/src/main/javassist/bytecode/FieldInfo.java @@ -60,7 +60,15 @@ public final class FieldInfo { } void prune(ConstPool cp) { - attribute = null; + int index = getConstantValue(); + if (index == 0) + attribute = null; + else { + index = constPool.copy(index, cp, null); + attribute = new LinkedList(); + attribute.add(new ConstantAttribute(cp, index)); + } + name = cp.addUtf8Info(getName()); descriptor = cp.addUtf8Info(getDescriptor()); constPool = cp; @@ -125,6 +133,24 @@ public final class FieldInfo { descriptor = constPool.addUtf8Info(desc); } + /** + * Finds a ConstantValue attribute and returns the index into + * the constant_pool table. + * + * @return 0 if a ConstantValue attribute is not found. + */ + public int getConstantValue() { + if ((accessFlags & AccessFlag.STATIC) == 0) + return 0; + + ConstantAttribute attr + = (ConstantAttribute)getAttribute(ConstantAttribute.tag); + if (attr == null) + return 0; + else + return attr.getConstantValue(); + } + /** * Returns all the attributes. * A new element can be added to the returned list diff --git a/src/main/javassist/compiler/ast/CastExpr.java b/src/main/javassist/compiler/ast/CastExpr.java index f390d943..06565b38 100644 --- a/src/main/javassist/compiler/ast/CastExpr.java +++ b/src/main/javassist/compiler/ast/CastExpr.java @@ -47,6 +47,8 @@ public class CastExpr extends ASTList implements TokenId { public ASTree getOprand() { return getRight().getLeft(); } + public void setOprand(ASTree t) { getRight().setLeft(t); } + public String getTag() { return "cast:" + castType + ":" + arrayDim; } public void accept(Visitor v) throws CompileError { v.atCastExpr(this); } diff --git a/src/main/javassist/compiler/ast/CondExpr.java b/src/main/javassist/compiler/ast/CondExpr.java index 5eb786f3..f20da602 100644 --- a/src/main/javassist/compiler/ast/CondExpr.java +++ b/src/main/javassist/compiler/ast/CondExpr.java @@ -27,6 +27,8 @@ public class CondExpr extends ASTList { public ASTree condExpr() { return head(); } + public void setCond(ASTree t) { setHead(t); } + public ASTree thenExpr() { return tail().head(); } public void setThen(ASTree t) { tail().setHead(t); } diff --git a/src/main/javassist/compiler/ast/DoubleConst.java b/src/main/javassist/compiler/ast/DoubleConst.java index b7063714..27de8878 100644 --- a/src/main/javassist/compiler/ast/DoubleConst.java +++ b/src/main/javassist/compiler/ast/DoubleConst.java @@ -16,6 +16,7 @@ package javassist.compiler.ast; import javassist.compiler.CompileError; +import javassist.compiler.TokenId; /** * Double constant. @@ -28,6 +29,8 @@ public class DoubleConst extends ASTree { public double get() { return value; } + public void set(double v) { value = v; } + /* Returns DoubleConstant or FloatConstant */ public int getType() { return type; } @@ -37,4 +40,55 @@ public class DoubleConst extends ASTree { public void accept(Visitor v) throws CompileError { v.atDoubleConst(this); } + + public ASTree compute(int op, ASTree right) { + if (right instanceof IntConst) + return compute0(op, (IntConst)right); + else if (right instanceof DoubleConst) + return compute0(op, (DoubleConst)right); + else + return null; + } + + private DoubleConst compute0(int op, DoubleConst right) { + int newType; + if (this.type == TokenId.DoubleConstant + || right.type == TokenId.DoubleConstant) + newType = TokenId.DoubleConstant; + else + newType = TokenId.FloatConstant; + + return compute(op, this.value, right.value, newType); + } + + private DoubleConst compute0(int op, IntConst right) { + return compute(op, this.value, (double)right.value, this.type); + } + + private static DoubleConst compute(int op, double value1, double value2, + int newType) + { + double newValue; + switch (op) { + case '+' : + newValue = value1 + value2; + break; + case '-' : + newValue = value1 - value2; + break; + case '*' : + newValue = value1 * value2; + break; + case '/' : + newValue = value1 / value2; + break; + case '%' : + newValue = value1 % value2; + break; + default : + return null; + } + + return new DoubleConst(newValue, newType); + } } diff --git a/src/main/javassist/compiler/ast/Expr.java b/src/main/javassist/compiler/ast/Expr.java index 88fc09e6..aafe8a75 100644 --- a/src/main/javassist/compiler/ast/Expr.java +++ b/src/main/javassist/compiler/ast/Expr.java @@ -52,6 +52,10 @@ public class Expr extends ASTList implements TokenId { public ASTree oprand1() { return getLeft(); } + public void setOprand1(ASTree expr) { + setLeft(expr); + } + public ASTree oprand2() { return getRight().getLeft(); } public void setOprand2(ASTree expr) { diff --git a/src/main/javassist/compiler/ast/IntConst.java b/src/main/javassist/compiler/ast/IntConst.java index d90f1438..b6204e1f 100644 --- a/src/main/javassist/compiler/ast/IntConst.java +++ b/src/main/javassist/compiler/ast/IntConst.java @@ -16,6 +16,7 @@ package javassist.compiler.ast; import javassist.compiler.CompileError; +import javassist.compiler.TokenId; /** * Integer constant. @@ -28,6 +29,8 @@ public class IntConst extends ASTree { public long get() { return value; } + public void set(long v) { value = v; } + /* Returns IntConstant, CharConstant, or LongConstant. */ public int getType() { return type; } @@ -37,4 +40,99 @@ public class IntConst extends ASTree { public void accept(Visitor v) throws CompileError { v.atIntConst(this); } + + public ASTree compute(int op, ASTree right) { + if (right instanceof IntConst) + return compute0(op, (IntConst)right); + else if (right instanceof DoubleConst) + return compute0(op, (DoubleConst)right); + else + return null; + } + + private IntConst compute0(int op, IntConst right) { + int type1 = this.type; + int type2 = right.type; + int newType; + if (type1 == TokenId.LongConstant || type2 == TokenId.LongConstant) + newType = TokenId.LongConstant; + else if (type1 == TokenId.CharConstant + && type2 == TokenId.CharConstant) + newType = TokenId.CharConstant; + else + newType = TokenId.IntConstant; + + long value1 = this.value; + long value2 = right.value; + long newValue; + switch (op) { + case '+' : + newValue = value1 + value2; + break; + case '-' : + newValue = value1 - value2; + break; + case '*' : + newValue = value1 * value2; + break; + case '/' : + newValue = value1 / value2; + break; + case '%' : + newValue = value1 % value2; + break; + case '|' : + newValue = value1 | value2; + break; + case '^' : + newValue = value1 ^ value2; + break; + case '&' : + newValue = value1 & value2; + break; + case TokenId.LSHIFT : + newValue = value << (int)value2; + newType = type1; + break; + case TokenId.RSHIFT : + newValue = value >> (int)value2; + newType = type1; + break; + case TokenId.ARSHIFT : + newValue = value >>> (int)value2; + newType = type1; + break; + default : + return null; + } + + return new IntConst(newValue, newType); + } + + private DoubleConst compute0(int op, DoubleConst right) { + double value1 = (double)this.value; + double value2 = right.value; + double newValue; + switch (op) { + case '+' : + newValue = value1 + value2; + break; + case '-' : + newValue = value1 - value2; + break; + case '*' : + newValue = value1 * value2; + break; + case '/' : + newValue = value1 / value2; + break; + case '%' : + newValue = value1 % value2; + break; + default : + return null; + } + + return new DoubleConst(newValue, right.type); + } } -- 2.39.5