From a8a438ffd324e90fe103171a40df7eb5bd20dcbd Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Mon, 5 Sep 2011 13:47:54 +0200 Subject: [PATCH] fix for KT-48 --- .../codegen/ImplementationBodyCodegen.java | 36 +++++++++++++- .../AnnotationArgumentVisitor.java | 2 + .../lang/resolve/constants/FloatValue.java | 38 +++++++++++++++ .../jet/lang/types/JetTypeInferrer.java | 47 +++++++++++++++++-- idea/testData/codegen/regressions/kt48.jet | 29 ++++++++++++ .../jetbrains/jet/codegen/ClassGenTest.java | 5 ++ 6 files changed, 152 insertions(+), 5 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/lang/resolve/constants/FloatValue.java create mode 100644 idea/testData/codegen/regressions/kt48.jet diff --git a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 7ce0246dccd..8a84bdb69a7 100644 --- a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lexer.JetTokens; import org.objectweb.asm.ClassVisitor; @@ -413,8 +414,41 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) { final JetExpression initializer = ((JetProperty) declaration).getInitializer(); if (initializer != null) { + CompileTimeConstant compileTimeValue = state.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, initializer); + if(compileTimeValue != null) { + assert compileTimeValue != null; + Object value = compileTimeValue.getValue(); + Type type = state.getTypeMapper().mapType(propertyDescriptor.getOutType()); + if(JetTypeMapper.isPrimitive(type)) { + if( !propertyDescriptor.getOutType().isNullable() && value instanceof Number) { + if(type == Type.INT_TYPE && ((Number)value).intValue() == 0) + continue; + if(type == Type.BYTE_TYPE && ((Number)value).byteValue() == 0) + continue; + if(type == Type.LONG_TYPE && ((Number)value).longValue() == 0L) + continue; + if(type == Type.SHORT_TYPE && ((Number)value).shortValue() == 0) + continue; + if(type == Type.DOUBLE_TYPE && ((Number)value).doubleValue() == 0d) + continue; + if(type == Type.FLOAT_TYPE && ((Number)value).byteValue() == 0f) + continue; + } + if(type == Type.BOOLEAN_TYPE && value instanceof Boolean && !((Boolean)value)) + continue; + if(type == Type.CHAR_TYPE && value instanceof Character && ((Character)value) == 0) + continue; + } + else { + if(value == null) + continue; + } + } iv.load(0, JetTypeMapper.TYPE_OBJECT); - codegen.genToJVMStack(initializer); + Type type = codegen.expressionType(initializer); + if(propertyDescriptor.getOutType().isNullable()) + type = state.getTypeMapper().boxType(type); + codegen.gen(initializer, type); codegen.intermediateValueForProperty(propertyDescriptor, false, false).store(iv); } diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationArgumentVisitor.java b/idea/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationArgumentVisitor.java index 70057d05f38..6443c23e9cb 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationArgumentVisitor.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationArgumentVisitor.java @@ -19,6 +19,8 @@ public interface AnnotationArgumentVisitor { R visitDoubleValue(DoubleValue value, D data); + R visitFloatValue(FloatValue value, D data); + R visitBooleanValue(BooleanValue value, D data); R visitCharValue(CharValue value, D data); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/constants/FloatValue.java b/idea/src/org/jetbrains/jet/lang/resolve/constants/FloatValue.java new file mode 100644 index 00000000000..5f8442cca26 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/resolve/constants/FloatValue.java @@ -0,0 +1,38 @@ +package org.jetbrains.jet.lang.resolve.constants; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationArgumentVisitor; +import org.jetbrains.jet.lang.types.JetStandardLibrary; +import org.jetbrains.jet.lang.types.JetType; + +/** + * @author alex.tkachman + */ +public class FloatValue implements CompileTimeConstant { + private final float value; + + public FloatValue(float value) { + this.value = value; + } + + @Override + public Float getValue() { + return value; + } + + @NotNull + @Override + public JetType getType(@NotNull JetStandardLibrary standardLibrary) { + return standardLibrary.getFloatType(); + } + + @Override + public R accept(AnnotationArgumentVisitor visitor, D data) { + return visitor.visitFloatValue(this, data); + } + + @Override + public String toString() { + return value + ".flt"; + } +} diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 0e637764a7b..1ae384663f7 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -18,10 +18,7 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.*; -import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; -import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver; -import org.jetbrains.jet.lang.resolve.constants.ErrorValue; -import org.jetbrains.jet.lang.resolve.constants.StringValue; +import org.jetbrains.jet.lang.resolve.constants.*; import org.jetbrains.jet.lang.types.inference.ConstraintSystem; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.resolve.DescriptorRenderer; @@ -35,6 +32,17 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.*; * @author abreslav */ public class JetTypeInferrer { + + private static final Set numberConversions = new HashSet(); + + static { + numberConversions.add("dbl"); + numberConversions.add("flt"); + numberConversions.add("lng"); + numberConversions.add("sht"); + numberConversions.add("byt"); + numberConversions.add("int"); + } private static final JetType FORBIDDEN = new JetType() { @NotNull @@ -2156,7 +2164,38 @@ public class JetTypeInferrer { // TODO : functions as values JetExpression selectorExpression = expression.getSelectorExpression(); JetExpression receiverExpression = expression.getReceiverExpression(); + JetType receiverType = context.services.typeInferrerVisitorWithNamespaces.getType(receiverExpression, new TypeInferenceContext(context.trace, context.scope, false, context.dataFlowInfo, NO_EXPECTED_TYPE, NO_EXPECTED_TYPE)); + + if(selectorExpression instanceof JetSimpleNameExpression) { + CompileTimeConstant compileTimeConstant = context.trace.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, receiverExpression); + CompileTimeConstant expressionCompileTimeConstant = context.trace.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, expression); + if(expressionCompileTimeConstant == null && compileTimeConstant != null && compileTimeConstant.getValue() instanceof Number) { + Number value = (Number) compileTimeConstant.getValue(); + String referencedName = ((JetSimpleNameExpression) selectorExpression).getReferencedName(); + if(numberConversions.contains(referencedName)) { + if("dbl".equals(referencedName)) { + context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new DoubleValue(value.doubleValue())); + } + else if("flt".equals(referencedName)) { + context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new FloatValue(value.floatValue())); + } + else if("lng".equals(referencedName)) { + context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new LongValue(value.longValue())); + } + else if("sht".equals(referencedName)) { + context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new ShortValue(value.shortValue())); + } + else if("byt".equals(referencedName)) { + context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new ByteValue(value.byteValue())); + } + else if("byt".equals(referencedName)) { + context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new IntValue(value.intValue())); + } + } + } + } + if (receiverType == null) return null; // Clean resolution: no autocasts diff --git a/idea/testData/codegen/regressions/kt48.jet b/idea/testData/codegen/regressions/kt48.jet new file mode 100644 index 00000000000..8a0126def52 --- /dev/null +++ b/idea/testData/codegen/regressions/kt48.jet @@ -0,0 +1,29 @@ +class A() { + var xi = 0 + var xin : Int? = 0 + var xinn : Int? = null + + var xl = 0.lng + var xln : Long? = 0.lng + var xlnn : Long? = null + + var xb = 0.byt + var xbn : Long? = 0.byt + var xbnn : Long? = null + + var xf = 0.flt + var xfn : Float? = 0.flt + var xfnn : Float? = null + + var xd = 0.dbl + var xdn : Double? = 0.dbl + var xdnn : Double? = null + + var xs = 0.sht + var xsn : Short? = 0.sht + var xsnn : Short? = null +} + +fun box() : String { + return "OK" +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java index 8a17b3d4887..b215854c0ab 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -172,4 +172,9 @@ public class ClassGenTest extends CodegenTestCase { public void testKt249() throws Exception { blackBoxFile("regressions/kt249.jet"); } + + public void testKt48 () throws Exception { + blackBoxFile("regressions/kt48.jet"); + System.out.println(generateToText()); + } }