diff options
Diffstat (limited to 'java/com/google/turbine')
-rw-r--r-- | java/com/google/turbine/binder/ConstBinder.java | 4 | ||||
-rw-r--r-- | java/com/google/turbine/binder/ConstEvaluator.java | 522 | ||||
-rw-r--r-- | java/com/google/turbine/binder/bytecode/BytecodeBinder.java | 13 | ||||
-rw-r--r-- | java/com/google/turbine/bytecode/AnnotationWriter.java | 19 | ||||
-rw-r--r-- | java/com/google/turbine/bytecode/AttributeWriter.java | 18 | ||||
-rw-r--r-- | java/com/google/turbine/bytecode/ClassReader.java | 17 | ||||
-rw-r--r-- | java/com/google/turbine/diag/TurbineError.java | 1 | ||||
-rw-r--r-- | java/com/google/turbine/model/Const.java | 331 |
8 files changed, 442 insertions, 483 deletions
diff --git a/java/com/google/turbine/binder/ConstBinder.java b/java/com/google/turbine/binder/ConstBinder.java index 00b100f..96c03db 100644 --- a/java/com/google/turbine/binder/ConstBinder.java +++ b/java/com/google/turbine/binder/ConstBinder.java @@ -293,7 +293,9 @@ public class ConstBinder { return null; } if (type.tyKind().equals(TyKind.PRIM_TY)) { - value = ConstEvaluator.coerce(value, ((Type.PrimTy) type).primkind()); + value = + constEvaluator.coerce( + base.decl().init().get().position(), value, ((Type.PrimTy) type).primkind()); } return value; } diff --git a/java/com/google/turbine/binder/ConstEvaluator.java b/java/com/google/turbine/binder/ConstEvaluator.java index 486b865..2780028 100644 --- a/java/com/google/turbine/binder/ConstEvaluator.java +++ b/java/com/google/turbine/binder/ConstEvaluator.java @@ -44,7 +44,11 @@ import com.google.turbine.diag.TurbineError.ErrorKind; import com.google.turbine.diag.TurbineLog.TurbineLogWithSource; import com.google.turbine.model.Const; import com.google.turbine.model.Const.ArrayInitValue; +import com.google.turbine.model.Const.CharValue; import com.google.turbine.model.Const.ConstCastError; +import com.google.turbine.model.Const.DoubleValue; +import com.google.turbine.model.Const.FloatValue; +import com.google.turbine.model.Const.StringValue; import com.google.turbine.model.Const.Value; import com.google.turbine.model.TurbineConstantTypeKind; import com.google.turbine.model.TurbineFlag; @@ -323,36 +327,283 @@ public strictfp class ConstEvaluator { if (!value.kind().equals(Const.Kind.PRIMITIVE)) { throw error(position, ErrorKind.EXPRESSION_ERROR); } - return coerce((Value) value, ((Type.PrimTy) ty).primkind()); + return coerce(position, (Value) value, ((Type.PrimTy) ty).primkind()); default: throw new AssertionError(ty.tyKind()); } } /** Casts the constant value to the given type. */ - static Value coerce(Value value, TurbineConstantTypeKind kind) { + Value coerce(int position, Value value, TurbineConstantTypeKind kind) { switch (kind) { + case BYTE: + return asByte(position, value); + case SHORT: + return asShort(position, value); + case INT: + return asInt(position, value); + case LONG: + return asLong(position, value); + case FLOAT: + return asFloat(position, value); + case DOUBLE: + return asDouble(position, value); + case CHAR: + return asChar(position, value); case BOOLEAN: - return value.asBoolean(); case STRING: - return value.asString(); + case NULL: + if (!value.constantTypeKind().equals(kind)) { + throw typeError(position, value, kind); + } + return value; + } + throw new AssertionError(kind); + } + + private Const.BooleanValue asBoolean(int position, Value value) { + if (!value.constantTypeKind().equals(TurbineConstantTypeKind.BOOLEAN)) { + throw typeError(position, value, TurbineConstantTypeKind.BOOLEAN); + } + return (Const.BooleanValue) value; + } + + private Const.StringValue asString(int position, Value value) { + String result; + switch (value.constantTypeKind()) { + case CHAR: + result = String.valueOf(((Const.CharValue) value).value()); + break; + case SHORT: + result = String.valueOf(((Const.ShortValue) value).value()); + break; + case INT: + result = String.valueOf(((Const.IntValue) value).value()); + break; + case LONG: + result = String.valueOf(((Const.LongValue) value).value()); + break; + case FLOAT: + result = String.valueOf(((Const.FloatValue) value).value()); + break; + case DOUBLE: + result = String.valueOf(((Const.DoubleValue) value).value()); + break; + case BOOLEAN: + result = String.valueOf(((Const.BooleanValue) value).value()); + break; + case BYTE: + result = String.valueOf(((Const.ByteValue) value).value()); + break; + case STRING: + return (StringValue) value; + default: + throw typeError(position, value, TurbineConstantTypeKind.STRING); + } + return new Const.StringValue(result); + } + + private Const.CharValue asChar(int position, Value value) { + char result; + switch (value.constantTypeKind()) { + case CHAR: + return (Const.CharValue) value; + case BYTE: + result = (char) ((Const.ByteValue) value).value(); + break; + case SHORT: + result = (char) ((Const.ShortValue) value).value(); + break; + case INT: + result = (char) ((Const.IntValue) value).value(); + break; + case LONG: + result = (char) ((Const.LongValue) value).value(); + break; + case FLOAT: + result = (char) ((Const.FloatValue) value).value(); + break; + case DOUBLE: + result = (char) ((Const.DoubleValue) value).value(); + break; + default: + throw typeError(position, value, TurbineConstantTypeKind.CHAR); + } + return new Const.CharValue(result); + } + + private Const.ByteValue asByte(int position, Value value) { + byte result; + switch (value.constantTypeKind()) { + case CHAR: + result = (byte) ((Const.CharValue) value).value(); + break; + case BYTE: + return (Const.ByteValue) value; + case SHORT: + result = (byte) ((Const.ShortValue) value).value(); + break; + case INT: + result = (byte) ((Const.IntValue) value).value(); + break; + case LONG: + result = (byte) ((Const.LongValue) value).value(); + break; + case FLOAT: + result = (byte) ((Const.FloatValue) value).value(); + break; + case DOUBLE: + result = (byte) ((Const.DoubleValue) value).value(); + break; + default: + throw typeError(position, value, TurbineConstantTypeKind.BYTE); + } + return new Const.ByteValue(result); + } + + private Const.ShortValue asShort(int position, Value value) { + short result; + switch (value.constantTypeKind()) { + case CHAR: + result = (short) ((Const.CharValue) value).value(); + break; + case BYTE: + result = ((Const.ByteValue) value).value(); + break; + case SHORT: + return (Const.ShortValue) value; + case INT: + result = (short) ((Const.IntValue) value).value(); + break; case LONG: - return value.asLong(); + result = (short) ((Const.LongValue) value).value(); + break; + case FLOAT: + result = (short) ((Const.FloatValue) value).value(); + break; + case DOUBLE: + result = (short) ((Const.DoubleValue) value).value(); + break; + default: + throw typeError(position, value, TurbineConstantTypeKind.SHORT); + } + return new Const.ShortValue(result); + } + + private Const.IntValue asInt(int position, Value value) { + int result; + switch (value.constantTypeKind()) { + case CHAR: + result = ((CharValue) value).value(); + break; + case BYTE: + result = ((Const.ByteValue) value).value(); + break; + case SHORT: + result = ((Const.ShortValue) value).value(); + break; case INT: - return value.asInteger(); + return (Const.IntValue) value; + case LONG: + result = (int) ((Const.LongValue) value).value(); + break; + case FLOAT: + result = (int) ((Const.FloatValue) value).value(); + break; + case DOUBLE: + result = (int) ((Const.DoubleValue) value).value(); + break; + default: + throw typeError(position, value, TurbineConstantTypeKind.INT); + } + return new Const.IntValue(result); + } + + private Const.LongValue asLong(int position, Value value) { + long result; + switch (value.constantTypeKind()) { + case CHAR: + result = ((CharValue) value).value(); + break; case BYTE: - return value.asByte(); + result = ((Const.ByteValue) value).value(); + break; + case SHORT: + result = ((Const.ShortValue) value).value(); + break; + case INT: + result = ((Const.IntValue) value).value(); + break; + case LONG: + return (Const.LongValue) value; + case FLOAT: + result = (long) ((Const.FloatValue) value).value(); + break; + case DOUBLE: + result = (long) ((Const.DoubleValue) value).value(); + break; + default: + throw typeError(position, value, TurbineConstantTypeKind.LONG); + } + return new Const.LongValue(result); + } + + private Const.FloatValue asFloat(int position, Value value) { + float result; + switch (value.constantTypeKind()) { case CHAR: - return value.asChar(); + result = ((CharValue) value).value(); + break; + case BYTE: + result = ((Const.ByteValue) value).value(); + break; case SHORT: - return value.asShort(); + result = ((Const.ShortValue) value).value(); + break; + case INT: + result = (float) ((Const.IntValue) value).value(); + break; + case LONG: + result = (float) ((Const.LongValue) value).value(); + break; + case FLOAT: + return (FloatValue) value; case DOUBLE: - return value.asDouble(); + result = (float) ((Const.DoubleValue) value).value(); + break; + default: + throw typeError(position, value, TurbineConstantTypeKind.FLOAT); + } + return new Const.FloatValue(result); + } + + private Const.DoubleValue asDouble(int position, Value value) { + double result; + switch (value.constantTypeKind()) { + case CHAR: + result = ((CharValue) value).value(); + break; + case BYTE: + result = ((Const.ByteValue) value).value(); + break; + case SHORT: + result = ((Const.ShortValue) value).value(); + break; + case INT: + result = ((Const.IntValue) value).value(); + break; + case LONG: + result = (double) ((Const.LongValue) value).value(); + break; case FLOAT: - return value.asFloat(); + result = ((Const.FloatValue) value).value(); + break; + case DOUBLE: + return (DoubleValue) value; default: - throw new AssertionError(kind); + throw typeError(position, value, TurbineConstantTypeKind.DOUBLE); } + return new Const.DoubleValue(result); } private @Nullable Value evalValue(Expression tree) { @@ -367,7 +618,9 @@ public strictfp class ConstEvaluator { if (condition == null) { return null; } - return condition.asBoolean().value() ? evalValue(t.iftrue()) : evalValue(t.iffalse()); + return asBoolean(t.position(), condition).value() + ? evalValue(t.iftrue()) + : evalValue(t.iffalse()); } private @Nullable Value evalUnary(Unary t) { @@ -392,7 +645,7 @@ public strictfp class ConstEvaluator { private @Nullable Value unaryNegate(int position, Value expr) { switch (expr.constantTypeKind()) { case BOOLEAN: - return new Const.BooleanValue(!expr.asBoolean().value()); + return new Const.BooleanValue(!asBoolean(position, expr).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, expr.constantTypeKind()); } @@ -402,9 +655,9 @@ public strictfp class ConstEvaluator { expr = promoteUnary(position, expr); switch (expr.constantTypeKind()) { case INT: - return new Const.IntValue(~expr.asInteger().value()); + return new Const.IntValue(~asInt(position, expr).value()); case LONG: - return new Const.LongValue(~expr.asLong().value()); + return new Const.LongValue(~asLong(position, expr).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, expr.constantTypeKind()); } @@ -414,13 +667,13 @@ public strictfp class ConstEvaluator { expr = promoteUnary(position, expr); switch (expr.constantTypeKind()) { case INT: - return new Const.IntValue(+expr.asInteger().value()); + return new Const.IntValue(+asInt(position, expr).value()); case LONG: - return new Const.LongValue(+expr.asLong().value()); + return new Const.LongValue(+asLong(position, expr).value()); case FLOAT: - return new Const.FloatValue(+expr.asFloat().value()); + return new Const.FloatValue(+asFloat(position, expr).value()); case DOUBLE: - return new Const.DoubleValue(+expr.asDouble().value()); + return new Const.DoubleValue(+asDouble(position, expr).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, expr.constantTypeKind()); } @@ -430,13 +683,13 @@ public strictfp class ConstEvaluator { expr = promoteUnary(position, expr); switch (expr.constantTypeKind()) { case INT: - return new Const.IntValue(-expr.asInteger().value()); + return new Const.IntValue(-asInt(position, expr).value()); case LONG: - return new Const.LongValue(-expr.asLong().value()); + return new Const.LongValue(-asLong(position, expr).value()); case FLOAT: - return new Const.FloatValue(-expr.asFloat().value()); + return new Const.FloatValue(-asFloat(position, expr).value()); case DOUBLE: - return new Const.DoubleValue(-expr.asDouble().value()); + return new Const.DoubleValue(-asDouble(position, expr).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, expr.constantTypeKind()); } @@ -449,7 +702,7 @@ public strictfp class ConstEvaluator { } switch (t.ty().kind()) { case PRIM_TY: - return coerce(expr, ((Tree.PrimTy) t.ty()).tykind()); + return coerce(t.expr().position(), expr, ((Tree.PrimTy) t.ty()).tykind()); case CLASS_TY: { ClassTy classTy = (ClassTy) t.ty(); @@ -458,7 +711,7 @@ public strictfp class ConstEvaluator { // Explicit boxing cases (e.g. `(Boolean) false`) are legal, but not const exprs. return null; } - return expr.asString(); + return asString(t.expr().position(), expr); } default: throw new AssertionError(t.ty().kind()); @@ -468,20 +721,20 @@ public strictfp class ConstEvaluator { private @Nullable Value add(int position, Value a, Value b) { if (a.constantTypeKind() == TurbineConstantTypeKind.STRING || b.constantTypeKind() == TurbineConstantTypeKind.STRING) { - return new Const.StringValue(a.asString().value() + b.asString().value()); + return new Const.StringValue(asString(position, a).value() + asString(position, b).value()); } TurbineConstantTypeKind type = promoteBinary(position, a, b); - a = coerce(a, type); - b = coerce(b, type); + a = coerce(position, a, type); + b = coerce(position, b, type); switch (type) { case INT: - return new Const.IntValue(a.asInteger().value() + b.asInteger().value()); + return new Const.IntValue(asInt(position, a).value() + asInt(position, b).value()); case LONG: - return new Const.LongValue(a.asLong().value() + b.asLong().value()); + return new Const.LongValue(asLong(position, a).value() + asLong(position, b).value()); case FLOAT: - return new Const.FloatValue(a.asFloat().value() + b.asFloat().value()); + return new Const.FloatValue(asFloat(position, a).value() + asFloat(position, b).value()); case DOUBLE: - return new Const.DoubleValue(a.asDouble().value() + b.asDouble().value()); + return new Const.DoubleValue(asDouble(position, a).value() + asDouble(position, b).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, type); } @@ -489,17 +742,17 @@ public strictfp class ConstEvaluator { private @Nullable Value subtract(int position, Value a, Value b) { TurbineConstantTypeKind type = promoteBinary(position, a, b); - a = coerce(a, type); - b = coerce(b, type); + a = coerce(position, a, type); + b = coerce(position, b, type); switch (type) { case INT: - return new Const.IntValue(a.asInteger().value() - b.asInteger().value()); + return new Const.IntValue(asInt(position, a).value() - asInt(position, b).value()); case LONG: - return new Const.LongValue(a.asLong().value() - b.asLong().value()); + return new Const.LongValue(asLong(position, a).value() - asLong(position, b).value()); case FLOAT: - return new Const.FloatValue(a.asFloat().value() - b.asFloat().value()); + return new Const.FloatValue(asFloat(position, a).value() - asFloat(position, b).value()); case DOUBLE: - return new Const.DoubleValue(a.asDouble().value() - b.asDouble().value()); + return new Const.DoubleValue(asDouble(position, a).value() - asDouble(position, b).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, type); } @@ -507,17 +760,17 @@ public strictfp class ConstEvaluator { private @Nullable Value mult(int position, Value a, Value b) { TurbineConstantTypeKind type = promoteBinary(position, a, b); - a = coerce(a, type); - b = coerce(b, type); + a = coerce(position, a, type); + b = coerce(position, b, type); switch (type) { case INT: - return new Const.IntValue(a.asInteger().value() * b.asInteger().value()); + return new Const.IntValue(asInt(position, a).value() * asInt(position, b).value()); case LONG: - return new Const.LongValue(a.asLong().value() * b.asLong().value()); + return new Const.LongValue(asLong(position, a).value() * asLong(position, b).value()); case FLOAT: - return new Const.FloatValue(a.asFloat().value() * b.asFloat().value()); + return new Const.FloatValue(asFloat(position, a).value() * asFloat(position, b).value()); case DOUBLE: - return new Const.DoubleValue(a.asDouble().value() * b.asDouble().value()); + return new Const.DoubleValue(asDouble(position, a).value() * asDouble(position, b).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, type); } @@ -525,17 +778,17 @@ public strictfp class ConstEvaluator { private @Nullable Value divide(int position, Value a, Value b) { TurbineConstantTypeKind type = promoteBinary(position, a, b); - a = coerce(a, type); - b = coerce(b, type); + a = coerce(position, a, type); + b = coerce(position, b, type); switch (type) { case INT: - return new Const.IntValue(a.asInteger().value() / b.asInteger().value()); + return new Const.IntValue(asInt(position, a).value() / asInt(position, b).value()); case LONG: - return new Const.LongValue(a.asLong().value() / b.asLong().value()); + return new Const.LongValue(asLong(position, a).value() / asLong(position, b).value()); case FLOAT: - return new Const.FloatValue(a.asFloat().value() / b.asFloat().value()); + return new Const.FloatValue(asFloat(position, a).value() / asFloat(position, b).value()); case DOUBLE: - return new Const.DoubleValue(a.asDouble().value() / b.asDouble().value()); + return new Const.DoubleValue(asDouble(position, a).value() / asDouble(position, b).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, type); } @@ -543,17 +796,17 @@ public strictfp class ConstEvaluator { private @Nullable Value mod(int position, Value a, Value b) { TurbineConstantTypeKind type = promoteBinary(position, a, b); - a = coerce(a, type); - b = coerce(b, type); + a = coerce(position, a, type); + b = coerce(position, b, type); switch (type) { case INT: - return new Const.IntValue(a.asInteger().value() % b.asInteger().value()); + return new Const.IntValue(asInt(position, a).value() % asInt(position, b).value()); case LONG: - return new Const.LongValue(a.asLong().value() % b.asLong().value()); + return new Const.LongValue(asLong(position, a).value() % asLong(position, b).value()); case FLOAT: - return new Const.FloatValue(a.asFloat().value() % b.asFloat().value()); + return new Const.FloatValue(asFloat(position, a).value() % asFloat(position, b).value()); case DOUBLE: - return new Const.DoubleValue(a.asDouble().value() % b.asDouble().value()); + return new Const.DoubleValue(asDouble(position, a).value() % asDouble(position, b).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, type); } @@ -569,9 +822,10 @@ public strictfp class ConstEvaluator { switch (a.constantTypeKind()) { case INT: return new Const.IntValue( - a.asInteger().value() << (b.asInteger().value() & INT_SHIFT_MASK)); + asInt(position, a).value() << (asInt(position, b).value() & INT_SHIFT_MASK)); case LONG: - return new Const.LongValue(a.asLong().value() << (b.asInteger().value() & LONG_SHIFT_MASK)); + return new Const.LongValue( + asLong(position, a).value() << (asInt(position, b).value() & LONG_SHIFT_MASK)); default: throw error(position, ErrorKind.OPERAND_TYPE, a.constantTypeKind()); } @@ -583,9 +837,10 @@ public strictfp class ConstEvaluator { switch (a.constantTypeKind()) { case INT: return new Const.IntValue( - a.asInteger().value() >> (b.asInteger().value() & INT_SHIFT_MASK)); + asInt(position, a).value() >> (asInt(position, b).value() & INT_SHIFT_MASK)); case LONG: - return new Const.LongValue(a.asLong().value() >> (b.asInteger().value() & LONG_SHIFT_MASK)); + return new Const.LongValue( + asLong(position, a).value() >> (asInt(position, b).value() & LONG_SHIFT_MASK)); default: throw error(position, ErrorKind.OPERAND_TYPE, a.constantTypeKind()); } @@ -597,10 +852,10 @@ public strictfp class ConstEvaluator { switch (a.constantTypeKind()) { case INT: return new Const.IntValue( - a.asInteger().value() >>> (b.asInteger().value() & INT_SHIFT_MASK)); + asInt(position, a).value() >>> (asInt(position, b).value() & INT_SHIFT_MASK)); case LONG: return new Const.LongValue( - a.asLong().value() >>> (b.asInteger().value() & LONG_SHIFT_MASK)); + asLong(position, a).value() >>> (asInt(position, b).value() & LONG_SHIFT_MASK)); default: throw error(position, ErrorKind.OPERAND_TYPE, a.constantTypeKind()); } @@ -608,17 +863,18 @@ public strictfp class ConstEvaluator { private @Nullable Value lessThan(int position, Value a, Value b) { TurbineConstantTypeKind type = promoteBinary(position, a, b); - a = coerce(a, type); - b = coerce(b, type); + a = coerce(position, a, type); + b = coerce(position, b, type); switch (type) { case INT: - return new Const.BooleanValue(a.asInteger().value() < b.asInteger().value()); + return new Const.BooleanValue(asInt(position, a).value() < asInt(position, b).value()); case LONG: - return new Const.BooleanValue(a.asLong().value() < b.asLong().value()); + return new Const.BooleanValue(asLong(position, a).value() < asLong(position, b).value()); case FLOAT: - return new Const.BooleanValue(a.asFloat().value() < b.asFloat().value()); + return new Const.BooleanValue(asFloat(position, a).value() < asFloat(position, b).value()); case DOUBLE: - return new Const.BooleanValue(a.asDouble().value() < b.asDouble().value()); + return new Const.BooleanValue( + asDouble(position, a).value() < asDouble(position, b).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, type); } @@ -626,17 +882,18 @@ public strictfp class ConstEvaluator { private @Nullable Value lessThanEqual(int position, Value a, Value b) { TurbineConstantTypeKind type = promoteBinary(position, a, b); - a = coerce(a, type); - b = coerce(b, type); + a = coerce(position, a, type); + b = coerce(position, b, type); switch (type) { case INT: - return new Const.BooleanValue(a.asInteger().value() <= b.asInteger().value()); + return new Const.BooleanValue(asInt(position, a).value() <= asInt(position, b).value()); case LONG: - return new Const.BooleanValue(a.asLong().value() <= b.asLong().value()); + return new Const.BooleanValue(asLong(position, a).value() <= asLong(position, b).value()); case FLOAT: - return new Const.BooleanValue(a.asFloat().value() <= b.asFloat().value()); + return new Const.BooleanValue(asFloat(position, a).value() <= asFloat(position, b).value()); case DOUBLE: - return new Const.BooleanValue(a.asDouble().value() <= b.asDouble().value()); + return new Const.BooleanValue( + asDouble(position, a).value() <= asDouble(position, b).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, type); } @@ -644,17 +901,18 @@ public strictfp class ConstEvaluator { private @Nullable Value greaterThan(int position, Value a, Value b) { TurbineConstantTypeKind type = promoteBinary(position, a, b); - a = coerce(a, type); - b = coerce(b, type); + a = coerce(position, a, type); + b = coerce(position, b, type); switch (type) { case INT: - return new Const.BooleanValue(a.asInteger().value() > b.asInteger().value()); + return new Const.BooleanValue(asInt(position, a).value() > asInt(position, b).value()); case LONG: - return new Const.BooleanValue(a.asLong().value() > b.asLong().value()); + return new Const.BooleanValue(asLong(position, a).value() > asLong(position, b).value()); case FLOAT: - return new Const.BooleanValue(a.asFloat().value() > b.asFloat().value()); + return new Const.BooleanValue(asFloat(position, a).value() > asFloat(position, b).value()); case DOUBLE: - return new Const.BooleanValue(a.asDouble().value() > b.asDouble().value()); + return new Const.BooleanValue( + asDouble(position, a).value() > asDouble(position, b).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, type); } @@ -662,17 +920,18 @@ public strictfp class ConstEvaluator { private @Nullable Value greaterThanEqual(int position, Value a, Value b) { TurbineConstantTypeKind type = promoteBinary(position, a, b); - a = coerce(a, type); - b = coerce(b, type); + a = coerce(position, a, type); + b = coerce(position, b, type); switch (type) { case INT: - return new Const.BooleanValue(a.asInteger().value() >= b.asInteger().value()); + return new Const.BooleanValue(asInt(position, a).value() >= asInt(position, b).value()); case LONG: - return new Const.BooleanValue(a.asLong().value() >= b.asLong().value()); + return new Const.BooleanValue(asLong(position, a).value() >= asLong(position, b).value()); case FLOAT: - return new Const.BooleanValue(a.asFloat().value() >= b.asFloat().value()); + return new Const.BooleanValue(asFloat(position, a).value() >= asFloat(position, b).value()); case DOUBLE: - return new Const.BooleanValue(a.asDouble().value() >= b.asDouble().value()); + return new Const.BooleanValue( + asDouble(position, a).value() >= asDouble(position, b).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, type); } @@ -681,24 +940,27 @@ public strictfp class ConstEvaluator { private @Nullable Value equal(int position, Value a, Value b) { switch (a.constantTypeKind()) { case STRING: - return new Const.BooleanValue(a.asString().value().equals(b.asString().value())); + return new Const.BooleanValue( + asString(position, a).value().equals(asString(position, b).value())); case BOOLEAN: - return new Const.BooleanValue(a.asBoolean().value() == b.asBoolean().value()); + return new Const.BooleanValue( + asBoolean(position, a).value() == asBoolean(position, b).value()); default: break; } TurbineConstantTypeKind type = promoteBinary(position, a, b); - a = coerce(a, type); - b = coerce(b, type); + a = coerce(position, a, type); + b = coerce(position, b, type); switch (type) { case INT: - return new Const.BooleanValue(a.asInteger().value() == b.asInteger().value()); + return new Const.BooleanValue(asInt(position, a).value() == asInt(position, b).value()); case LONG: - return new Const.BooleanValue(a.asLong().value() == b.asLong().value()); + return new Const.BooleanValue(asLong(position, a).value() == asLong(position, b).value()); case FLOAT: - return new Const.BooleanValue(a.asFloat().value() == b.asFloat().value()); + return new Const.BooleanValue(asFloat(position, a).value() == asFloat(position, b).value()); case DOUBLE: - return new Const.BooleanValue(a.asDouble().value() == b.asDouble().value()); + return new Const.BooleanValue( + asDouble(position, a).value() == asDouble(position, b).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, type); } @@ -707,64 +969,69 @@ public strictfp class ConstEvaluator { private @Nullable Value notEqual(int position, Value a, Value b) { switch (a.constantTypeKind()) { case STRING: - return new Const.BooleanValue(!a.asString().value().equals(b.asString().value())); + return new Const.BooleanValue( + !asString(position, a).value().equals(asString(position, b).value())); case BOOLEAN: - return new Const.BooleanValue(a.asBoolean().value() != b.asBoolean().value()); + return new Const.BooleanValue( + asBoolean(position, a).value() != asBoolean(position, b).value()); default: break; } TurbineConstantTypeKind type = promoteBinary(position, a, b); - a = coerce(a, type); - b = coerce(b, type); + a = coerce(position, a, type); + b = coerce(position, b, type); switch (type) { case INT: - return new Const.BooleanValue(a.asInteger().value() != b.asInteger().value()); + return new Const.BooleanValue(asInt(position, a).value() != asInt(position, b).value()); case LONG: - return new Const.BooleanValue(a.asLong().value() != b.asLong().value()); + return new Const.BooleanValue(asLong(position, a).value() != asLong(position, b).value()); case FLOAT: - return new Const.BooleanValue(a.asFloat().value() != b.asFloat().value()); + return new Const.BooleanValue(asFloat(position, a).value() != asFloat(position, b).value()); case DOUBLE: - return new Const.BooleanValue(a.asDouble().value() != b.asDouble().value()); + return new Const.BooleanValue( + asDouble(position, a).value() != asDouble(position, b).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, type); } } - private @Nullable Value bitwiseAnd(int position, Value a, Value b) { + private Value bitwiseAnd(int position, Value a, Value b) { switch (a.constantTypeKind()) { case BOOLEAN: - return new Const.BooleanValue(a.asBoolean().value() & b.asBoolean().value()); + return new Const.BooleanValue( + asBoolean(position, a).value() & asBoolean(position, b).value()); default: break; } TurbineConstantTypeKind type = promoteBinary(position, a, b); - a = coerce(a, type); - b = coerce(b, type); + a = coerce(position, a, type); + b = coerce(position, b, type); switch (type) { case INT: - return new Const.IntValue(a.asInteger().value() & b.asInteger().value()); + return new Const.IntValue(asInt(position, a).value() & asInt(position, b).value()); case LONG: - return new Const.LongValue(a.asLong().value() & b.asLong().value()); + return new Const.LongValue(asLong(position, a).value() & asLong(position, b).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, type); } } - private @Nullable Value bitwiseOr(int position, Value a, Value b) { + private Value bitwiseOr(int position, Value a, Value b) { switch (a.constantTypeKind()) { case BOOLEAN: - return new Const.BooleanValue(a.asBoolean().value() | b.asBoolean().value()); + return new Const.BooleanValue( + asBoolean(position, a).value() | asBoolean(position, b).value()); default: break; } TurbineConstantTypeKind type = promoteBinary(position, a, b); - a = coerce(a, type); - b = coerce(b, type); + a = coerce(position, a, type); + b = coerce(position, b, type); switch (type) { case INT: - return new Const.IntValue(a.asInteger().value() | b.asInteger().value()); + return new Const.IntValue(asInt(position, a).value() | asInt(position, b).value()); case LONG: - return new Const.LongValue(a.asLong().value() | b.asLong().value()); + return new Const.LongValue(asLong(position, a).value() | asLong(position, b).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, type); } @@ -773,18 +1040,19 @@ public strictfp class ConstEvaluator { private @Nullable Value bitwiseXor(int position, Value a, Value b) { switch (a.constantTypeKind()) { case BOOLEAN: - return new Const.BooleanValue(a.asBoolean().value() ^ b.asBoolean().value()); + return new Const.BooleanValue( + asBoolean(position, a).value() ^ asBoolean(position, b).value()); default: break; } TurbineConstantTypeKind type = promoteBinary(position, a, b); - a = coerce(a, type); - b = coerce(b, type); + a = coerce(position, a, type); + b = coerce(position, b, type); switch (type) { case INT: - return new Const.IntValue(a.asInteger().value() ^ b.asInteger().value()); + return new Const.IntValue(asInt(position, a).value() ^ asInt(position, b).value()); case LONG: - return new Const.LongValue(a.asLong().value() ^ b.asLong().value()); + return new Const.LongValue(asLong(position, a).value() ^ asLong(position, b).value()); default: throw error(position, ErrorKind.OPERAND_TYPE, type); } @@ -826,9 +1094,11 @@ public strictfp class ConstEvaluator { case NOT_EQUAL: return notEqual(t.position(), lhs, rhs); case AND: - return new Const.BooleanValue(lhs.asBoolean().value() && rhs.asBoolean().value()); + return new Const.BooleanValue( + asBoolean(t.position(), lhs).value() && asBoolean(t.position(), rhs).value()); case OR: - return new Const.BooleanValue(lhs.asBoolean().value() || rhs.asBoolean().value()); + return new Const.BooleanValue( + asBoolean(t.position(), lhs).value() || asBoolean(t.position(), rhs).value()); case BITWISE_AND: return bitwiseAnd(t.position(), lhs, rhs); case BITWISE_XOR: @@ -845,7 +1115,7 @@ public strictfp class ConstEvaluator { case CHAR: case SHORT: case BYTE: - return v.asInteger(); + return asInt(position, v); case INT: case LONG: case FLOAT: @@ -1031,7 +1301,7 @@ public strictfp class ConstEvaluator { if (!(value instanceof Value)) { throw error(tree.position(), ErrorKind.EXPRESSION_ERROR); } - return coerce((Value) value, ((Type.PrimTy) ty).primkind()); + return coerce(tree.position(), (Value) value, ((Type.PrimTy) ty).primkind()); case CLASS_TY: case TY_VAR: return value; @@ -1057,6 +1327,10 @@ public strictfp class ConstEvaluator { return TurbineError.format(source, position, kind, args); } + private TurbineError typeError(int position, Value value, TurbineConstantTypeKind kind) { + return error(position, ErrorKind.TYPE_CONVERSION, value, value.constantTypeKind(), kind); + } + public @Nullable Value evalFieldInitializer(Expression expression, Type type) { try { Const value = eval(expression); diff --git a/java/com/google/turbine/binder/bytecode/BytecodeBinder.java b/java/com/google/turbine/binder/bytecode/BytecodeBinder.java index 0f4bac1..d2383b6 100644 --- a/java/com/google/turbine/binder/bytecode/BytecodeBinder.java +++ b/java/com/google/turbine/binder/bytecode/BytecodeBinder.java @@ -40,6 +40,7 @@ import com.google.turbine.bytecode.sig.Sig.WildTySig; import com.google.turbine.bytecode.sig.SigParser; import com.google.turbine.model.Const; import com.google.turbine.model.Const.ArrayInitValue; +import com.google.turbine.model.Const.Value; import com.google.turbine.type.AnnoInfo; import com.google.turbine.type.Type; import java.util.ArrayList; @@ -175,19 +176,23 @@ public final class BytecodeBinder { // TODO(b/32626659): this is not bug-compatible with javac switch (((Type.PrimTy) type).primkind()) { case CHAR: - return new Const.CharValue(value.asChar().value()); + return new Const.CharValue((char) asInt(value)); case SHORT: - return new Const.ShortValue(value.asShort().value()); + return new Const.ShortValue((short) asInt(value)); case BOOLEAN: // boolean constants are encoded as integers - return new Const.BooleanValue(value.asInteger().value() != 0); + return new Const.BooleanValue(asInt(value) != 0); case BYTE: - return new Const.ByteValue(value.asByte().value()); + return new Const.ByteValue((byte) asInt(value)); default: return value; } } + private static int asInt(Value value) { + return ((Const.IntValue) value).value(); + } + private static Const bindEnumValue(EnumConstValue value) { return new EnumConstantValue( new FieldSymbol(asClassSymbol(value.typeName()), value.constName())); diff --git a/java/com/google/turbine/bytecode/AnnotationWriter.java b/java/com/google/turbine/bytecode/AnnotationWriter.java index 34d6262..ccae0f1 100644 --- a/java/com/google/turbine/bytecode/AnnotationWriter.java +++ b/java/com/google/turbine/bytecode/AnnotationWriter.java @@ -33,6 +33,7 @@ import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo.ThrowsTarget; import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo.TypeParameterBoundTarget; import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo.TypeParameterTarget; import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo.TypePath; +import com.google.turbine.model.Const; import com.google.turbine.model.Const.Value; import java.util.Map; @@ -79,31 +80,31 @@ public class AnnotationWriter { private void writeConstElementValue(Value value) { switch (value.constantTypeKind()) { case BYTE: - writeConst('B', pool.integer(value.asInteger().value())); + writeConst('B', pool.integer(((Const.ByteValue) value).value())); break; case CHAR: - writeConst('C', pool.integer(value.asInteger().value())); + writeConst('C', pool.integer(((Const.CharValue) value).value())); break; case SHORT: - writeConst('S', pool.integer(value.asInteger().value())); + writeConst('S', pool.integer(((Const.ShortValue) value).value())); break; case DOUBLE: - writeConst('D', pool.doubleInfo(value.asDouble().value())); + writeConst('D', pool.doubleInfo(((Const.DoubleValue) value).value())); break; case FLOAT: - writeConst('F', pool.floatInfo(value.asFloat().value())); + writeConst('F', pool.floatInfo(((Const.FloatValue) value).value())); break; case INT: - writeConst('I', pool.integer(value.asInteger().value())); + writeConst('I', pool.integer(((Const.IntValue) value).value())); break; case LONG: - writeConst('J', pool.longInfo(value.asLong().value())); + writeConst('J', pool.longInfo(((Const.LongValue) value).value())); break; case STRING: - writeConst('s', pool.utf8(value.asString().value())); + writeConst('s', pool.utf8(((Const.StringValue) value).value())); break; case BOOLEAN: - writeConst('Z', pool.integer(value.asBoolean().value() ? 1 : 0)); + writeConst('Z', pool.integer(((Const.BooleanValue) value).value() ? 1 : 0)); break; default: throw new AssertionError(value.constantTypeKind()); diff --git a/java/com/google/turbine/bytecode/AttributeWriter.java b/java/com/google/turbine/bytecode/AttributeWriter.java index 84ca55f..b92d2e7 100644 --- a/java/com/google/turbine/bytecode/AttributeWriter.java +++ b/java/com/google/turbine/bytecode/AttributeWriter.java @@ -127,25 +127,31 @@ public class AttributeWriter { Const.Value value = attribute.value; switch (value.constantTypeKind()) { case INT: + output.writeShort(pool.integer(((Const.IntValue) value).value())); + break; case CHAR: + output.writeShort(pool.integer(((Const.CharValue) value).value())); + break; case SHORT: + output.writeShort(pool.integer(((Const.ShortValue) value).value())); + break; case BYTE: - output.writeShort(pool.integer(value.asInteger().value())); + output.writeShort(pool.integer(((Const.ByteValue) value).value())); break; case LONG: - output.writeShort(pool.longInfo(value.asLong().value())); + output.writeShort(pool.longInfo(((Const.LongValue) value).value())); break; case DOUBLE: - output.writeShort(pool.doubleInfo(value.asDouble().value())); + output.writeShort(pool.doubleInfo(((Const.DoubleValue) value).value())); break; case FLOAT: - output.writeShort(pool.floatInfo(value.asFloat().value())); + output.writeShort(pool.floatInfo(((Const.FloatValue) value).value())); break; case BOOLEAN: - output.writeShort(pool.integer(value.asBoolean().value() ? 1 : 0)); + output.writeShort(pool.integer(((Const.BooleanValue) value).value() ? 1 : 0)); break; case STRING: - output.writeShort(pool.string(value.asString().value())); + output.writeShort(pool.string(((Const.StringValue) value).value())); break; default: throw new AssertionError(value.constantTypeKind()); diff --git a/java/com/google/turbine/bytecode/ClassReader.java b/java/com/google/turbine/bytecode/ClassReader.java index ac8b1e1..cb72d3e 100644 --- a/java/com/google/turbine/bytecode/ClassReader.java +++ b/java/com/google/turbine/bytecode/ClassReader.java @@ -334,11 +334,11 @@ public class ClassReader { int tag = reader.u1(); switch (tag) { case 'B': - return new ConstValue(readConst(constantPool).asByte()); + return new ConstValue(new Const.ByteValue((byte) readInt(constantPool))); case 'C': - return new ConstValue(readConst(constantPool).asChar()); + return new ConstValue(new Const.CharValue((char) readInt(constantPool))); case 'S': - return new ConstValue(readConst(constantPool).asShort()); + return new ConstValue(new Const.ShortValue((short) readInt(constantPool))); case 'D': case 'F': case 'I': @@ -346,11 +346,8 @@ public class ClassReader { case 's': return new ConstValue(readConst(constantPool)); case 'Z': - { - Const.Value value = readConst(constantPool); - // boolean constants are encoded as integers - return new ConstValue(new Const.BooleanValue(value.asInteger().value() != 0)); - } + // boolean constants are encoded as integers + return new ConstValue(new Const.BooleanValue(readInt(constantPool) != 0)); case 'e': { int typeNameIndex = reader.u2(); @@ -381,6 +378,10 @@ public class ClassReader { throw new AssertionError(String.format("bad tag value %c", tag)); } + private int readInt(ConstantPoolReader constantPool) { + return ((Const.IntValue) readConst(constantPool)).value(); + } + private Const.Value readConst(ConstantPoolReader constantPool) { int constValueIndex = reader.u2(); return constantPool.constant(constValueIndex); diff --git a/java/com/google/turbine/diag/TurbineError.java b/java/com/google/turbine/diag/TurbineError.java index e3f8a0e..f839345 100644 --- a/java/com/google/turbine/diag/TurbineError.java +++ b/java/com/google/turbine/diag/TurbineError.java @@ -48,6 +48,7 @@ public class TurbineError extends Error { CANNOT_RESOLVE("could not resolve %s"), EXPRESSION_ERROR("could not evaluate constant expression"), OPERAND_TYPE("bad operand type %s"), + TYPE_CONVERSION("value %s of type %s cannot be converted to %s"), CYCLIC_HIERARCHY("cycle in class hierarchy: %s"), NOT_AN_ANNOTATION("%s is not an annotation"), ANNOTATION_VALUE_NAME("expected an annotation value of the form name=value"), diff --git a/java/com/google/turbine/model/Const.java b/java/com/google/turbine/model/Const.java index ed4b072..8dbb44d 100644 --- a/java/com/google/turbine/model/Const.java +++ b/java/com/google/turbine/model/Const.java @@ -64,42 +64,6 @@ public abstract class Const { public Kind kind() { return Kind.PRIMITIVE; } - - public IntValue asInteger() { - throw new ConstCastError(constantTypeKind(), TurbineConstantTypeKind.INT); - } - - public FloatValue asFloat() { - throw new ConstCastError(constantTypeKind(), TurbineConstantTypeKind.FLOAT); - } - - public DoubleValue asDouble() { - throw new ConstCastError(constantTypeKind(), TurbineConstantTypeKind.DOUBLE); - } - - public LongValue asLong() { - throw new ConstCastError(constantTypeKind(), TurbineConstantTypeKind.LONG); - } - - public BooleanValue asBoolean() { - throw new ConstCastError(constantTypeKind(), TurbineConstantTypeKind.BOOLEAN); - } - - public StringValue asString() { - throw new ConstCastError(constantTypeKind(), TurbineConstantTypeKind.STRING); - } - - public CharValue asChar() { - throw new ConstCastError(constantTypeKind(), TurbineConstantTypeKind.CHAR); - } - - public ShortValue asShort() { - throw new ConstCastError(constantTypeKind(), TurbineConstantTypeKind.SHORT); - } - - public ByteValue asByte() { - throw new ConstCastError(constantTypeKind(), TurbineConstantTypeKind.BYTE); - } } /** A boolean literal value. */ @@ -135,16 +99,6 @@ public abstract class Const { } @Override - public BooleanValue asBoolean() { - return this; - } - - @Override - public StringValue asString() { - return new StringValue(String.valueOf(value)); - } - - @Override public int hashCode() { return Boolean.hashCode(value); } @@ -189,46 +143,6 @@ public abstract class Const { } @Override - public IntValue asInteger() { - return this; - } - - @Override - public ByteValue asByte() { - return new ByteValue((byte) value); - } - - @Override - public LongValue asLong() { - return new LongValue((long) value); - } - - @Override - public CharValue asChar() { - return new CharValue((char) value); - } - - @Override - public ShortValue asShort() { - return new ShortValue((short) value); - } - - @Override - public DoubleValue asDouble() { - return new DoubleValue((double) value); - } - - @Override - public FloatValue asFloat() { - return new FloatValue((float) value); - } - - @Override - public StringValue asString() { - return new StringValue(String.valueOf(value)); - } - - @Override public int hashCode() { return Integer.hashCode(value); } @@ -272,46 +186,6 @@ public abstract class Const { } @Override - public IntValue asInteger() { - return new IntValue((int) value); - } - - @Override - public ByteValue asByte() { - return new ByteValue((byte) value); - } - - @Override - public LongValue asLong() { - return this; - } - - @Override - public CharValue asChar() { - return new CharValue((char) value); - } - - @Override - public ShortValue asShort() { - return new ShortValue((short) value); - } - - @Override - public DoubleValue asDouble() { - return new DoubleValue((double) value); - } - - @Override - public FloatValue asFloat() { - return new FloatValue((float) value); - } - - @Override - public StringValue asString() { - return new StringValue(String.valueOf(value)); - } - - @Override public int hashCode() { return Long.hashCode(value); } @@ -355,46 +229,6 @@ public abstract class Const { } @Override - public IntValue asInteger() { - return new IntValue((int) value); - } - - @Override - public ByteValue asByte() { - return new ByteValue((byte) value); - } - - @Override - public LongValue asLong() { - return new LongValue((long) value); - } - - @Override - public CharValue asChar() { - return this; - } - - @Override - public ShortValue asShort() { - return new ShortValue((short) value); - } - - @Override - public DoubleValue asDouble() { - return new DoubleValue((double) value); - } - - @Override - public FloatValue asFloat() { - return new FloatValue((float) value); - } - - @Override - public StringValue asString() { - return new StringValue(String.valueOf(value)); - } - - @Override public int hashCode() { return Character.hashCode(value); } @@ -441,46 +275,6 @@ public abstract class Const { } @Override - public IntValue asInteger() { - return new IntValue((int) value); - } - - @Override - public ByteValue asByte() { - return new ByteValue((byte) value); - } - - @Override - public LongValue asLong() { - return new LongValue((long) value); - } - - @Override - public CharValue asChar() { - return new CharValue((char) value); - } - - @Override - public ShortValue asShort() { - return new ShortValue((short) value); - } - - @Override - public DoubleValue asDouble() { - return new DoubleValue((double) value); - } - - @Override - public FloatValue asFloat() { - return this; - } - - @Override - public StringValue asString() { - return new StringValue(String.valueOf(value)); - } - - @Override public int hashCode() { return Float.hashCode(value); } @@ -533,46 +327,6 @@ public abstract class Const { } @Override - public IntValue asInteger() { - return new IntValue((int) value); - } - - @Override - public ByteValue asByte() { - return new ByteValue((byte) value); - } - - @Override - public LongValue asLong() { - return new LongValue((long) value); - } - - @Override - public CharValue asChar() { - return new CharValue((char) value); - } - - @Override - public ShortValue asShort() { - return new ShortValue((short) value); - } - - @Override - public DoubleValue asDouble() { - return this; - } - - @Override - public FloatValue asFloat() { - return new FloatValue((float) value); - } - - @Override - public StringValue asString() { - return new StringValue(String.valueOf(value)); - } - - @Override public int hashCode() { return Double.hashCode(value); } @@ -616,11 +370,6 @@ public abstract class Const { } @Override - public StringValue asString() { - return this; - } - - @Override public int hashCode() { return value.hashCode(); } @@ -664,46 +413,6 @@ public abstract class Const { } @Override - public IntValue asInteger() { - return new IntValue((int) value); - } - - @Override - public ByteValue asByte() { - return new ByteValue((byte) value); - } - - @Override - public LongValue asLong() { - return new LongValue((long) value); - } - - @Override - public CharValue asChar() { - return new CharValue((char) value); - } - - @Override - public ShortValue asShort() { - return this; - } - - @Override - public DoubleValue asDouble() { - return new DoubleValue((double) value); - } - - @Override - public FloatValue asFloat() { - return new FloatValue((float) value); - } - - @Override - public StringValue asString() { - return new StringValue(String.valueOf(value)); - } - - @Override public int hashCode() { return Short.hashCode(value); } @@ -738,46 +447,6 @@ public abstract class Const { } @Override - public IntValue asInteger() { - return new IntValue((int) value); - } - - @Override - public ByteValue asByte() { - return this; - } - - @Override - public LongValue asLong() { - return new LongValue((long) value); - } - - @Override - public CharValue asChar() { - return new CharValue((char) value); - } - - @Override - public ShortValue asShort() { - return new ShortValue((short) value); - } - - @Override - public DoubleValue asDouble() { - return new DoubleValue((double) value); - } - - @Override - public FloatValue asFloat() { - return new FloatValue((float) value); - } - - @Override - public StringValue asString() { - return new StringValue(String.valueOf(value)); - } - - @Override public int hashCode() { return Byte.hashCode(value); } |