KT-531 Support nullable iterator in for()
This commit is contained in:
@@ -278,7 +278,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
if(nextDescriptor == null)
|
if(nextDescriptor == null)
|
||||||
throw new IllegalStateException("No next() method " + DiagnosticUtils.atLocation(loopRange));
|
throw new IllegalStateException("No next() method " + DiagnosticUtils.atLocation(loopRange));
|
||||||
if(hasNextDescriptor == null)
|
if(hasNextDescriptor == null)
|
||||||
throw new IllegalStateException("No iterator() method " + DiagnosticUtils.atLocation(loopRange));
|
throw new IllegalStateException("No hasNext method or property" + DiagnosticUtils.atLocation(loopRange));
|
||||||
|
|
||||||
final JetParameter loopParameter = expression.getLoopParameter();
|
final JetParameter loopParameter = expression.getLoopParameter();
|
||||||
final VariableDescriptor parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, loopParameter);
|
final VariableDescriptor parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, loopParameter);
|
||||||
@@ -293,9 +293,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
gen(expression.getLoopRange(), loopRangeType);
|
gen(expression.getLoopRange(), loopRangeType);
|
||||||
invokeFunctionNoParams(iteratorDescriptor, asmIterType, v);
|
invokeFunctionNoParams(iteratorDescriptor, asmIterType, v);
|
||||||
v.store(iteratorVar, asmIterType);
|
v.store(iteratorVar, asmIterType);
|
||||||
|
|
||||||
|
Label end = new Label();
|
||||||
|
if(iteratorType.isNullable()) {
|
||||||
|
v.load(iteratorVar, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
v.ifnull(end);
|
||||||
|
}
|
||||||
|
|
||||||
Label begin = new Label();
|
Label begin = new Label();
|
||||||
Label end = new Label();
|
|
||||||
myContinueTargets.push(begin);
|
myContinueTargets.push(begin);
|
||||||
myBreakTargets.push(end);
|
myBreakTargets.push(end);
|
||||||
|
|
||||||
@@ -346,6 +351,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
protected Type loopRangeType;
|
protected Type loopRangeType;
|
||||||
protected JetType expressionType;
|
protected JetType expressionType;
|
||||||
protected VariableDescriptor parameterDescriptor;
|
protected VariableDescriptor parameterDescriptor;
|
||||||
|
Label end = new Label();
|
||||||
|
|
||||||
public ForLoopGenerator(JetForExpression expression, Type loopRangeType) {
|
public ForLoopGenerator(JetForExpression expression, Type loopRangeType) {
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
@@ -364,7 +370,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
Label condition = new Label();
|
Label condition = new Label();
|
||||||
Label increment = new Label();
|
Label increment = new Label();
|
||||||
Label end = new Label();
|
|
||||||
v.mark(condition);
|
v.mark(condition);
|
||||||
myContinueTargets.push(increment);
|
myContinueTargets.push(increment);
|
||||||
myBreakTargets.push(end);
|
myBreakTargets.push(end);
|
||||||
@@ -398,8 +403,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class ForInArrayLoopGenerator extends ForLoopGenerator {
|
private class ForInArrayLoopGenerator extends ForLoopGenerator {
|
||||||
private int myLengthVar;
|
|
||||||
private int myIndexVar;
|
private int myIndexVar;
|
||||||
|
private int myArrayVar;
|
||||||
|
private boolean localArrayVar;
|
||||||
|
|
||||||
public ForInArrayLoopGenerator(JetForExpression expression, Type loopRangeType) {
|
public ForInArrayLoopGenerator(JetForExpression expression, Type loopRangeType) {
|
||||||
super(expression, loopRangeType);
|
super(expression, loopRangeType);
|
||||||
@@ -407,11 +413,24 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void generatePrologue() {
|
protected void generatePrologue() {
|
||||||
myLengthVar = myFrameMap.enterTemp();
|
|
||||||
gen(expression.getLoopRange(), loopRangeType);
|
|
||||||
v.arraylength();
|
|
||||||
v.store(myLengthVar, Type.INT_TYPE);
|
|
||||||
myIndexVar = myFrameMap.enterTemp();
|
myIndexVar = myFrameMap.enterTemp();
|
||||||
|
|
||||||
|
StackValue value = gen(expression.getLoopRange());
|
||||||
|
if(value instanceof StackValue.Local) {
|
||||||
|
myArrayVar = ((StackValue.Local)value).index;
|
||||||
|
localArrayVar = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
myArrayVar = myFrameMap.enterTemp();
|
||||||
|
value.put(loopRangeType, v);
|
||||||
|
v.store(myArrayVar, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(expressionType.isNullable()) {
|
||||||
|
v.load(myArrayVar, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
v.ifnull(end);
|
||||||
|
}
|
||||||
|
|
||||||
v.iconst(0);
|
v.iconst(0);
|
||||||
v.store(myIndexVar, Type.INT_TYPE);
|
v.store(myIndexVar, Type.INT_TYPE);
|
||||||
}
|
}
|
||||||
@@ -420,10 +439,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
Type arrayElParamType = state.getStandardLibrary().getArray().equals(expressionType.getConstructor().getDeclarationDescriptor()) ? JetTypeMapper.boxType(asmParamType): asmParamType;
|
Type arrayElParamType = state.getStandardLibrary().getArray().equals(expressionType.getConstructor().getDeclarationDescriptor()) ? JetTypeMapper.boxType(asmParamType): asmParamType;
|
||||||
|
|
||||||
v.load(myIndexVar, Type.INT_TYPE);
|
v.load(myIndexVar, Type.INT_TYPE);
|
||||||
v.load(myLengthVar, Type.INT_TYPE);
|
v.load(myArrayVar, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
v.arraylength();
|
||||||
v.ificmpge(end);
|
v.ificmpge(end);
|
||||||
|
|
||||||
gen(expression.getLoopRange(), loopRangeType); // array
|
v.load(myArrayVar, JetTypeMapper.TYPE_OBJECT);
|
||||||
v.load(myIndexVar, Type.INT_TYPE);
|
v.load(myIndexVar, Type.INT_TYPE);
|
||||||
v.aload(arrayElParamType);
|
v.aload(arrayElParamType);
|
||||||
StackValue.onStack(arrayElParamType).put(asmParamType, v);
|
StackValue.onStack(arrayElParamType).put(asmParamType, v);
|
||||||
@@ -435,7 +455,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void cleanupTemp() {
|
protected void cleanupTemp() {
|
||||||
myFrameMap.leaveTemp(2);
|
myFrameMap.leaveTemp(localArrayVar ? 1 : 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ public abstract class StackValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class Local extends StackValue {
|
public static class Local extends StackValue {
|
||||||
private final int index;
|
final int index;
|
||||||
|
|
||||||
public Local(int index, Type type) {
|
public Local(int index, Type type) {
|
||||||
super(type);
|
super(type);
|
||||||
|
|||||||
@@ -12,5 +12,10 @@ fun box() : String {
|
|||||||
System.out?.println(sum)
|
System.out?.println(sum)
|
||||||
if(sum != 10) return "b failed"
|
if(sum != 10) return "b failed"
|
||||||
|
|
||||||
|
val d : Array<Int?>? = null
|
||||||
|
for (el in d) {
|
||||||
|
sum = sum + (el ?: 7)
|
||||||
|
}
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
@@ -10,5 +10,10 @@ fun box() : String {
|
|||||||
}
|
}
|
||||||
if(sum != 10) return "a failed"
|
if(sum != 10) return "a failed"
|
||||||
|
|
||||||
|
val b : IntArray? = null
|
||||||
|
for (el in b) {
|
||||||
|
sum = sum + el
|
||||||
|
}
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
@@ -66,6 +66,14 @@ fun box() : String {
|
|||||||
System.out?.println(sum)
|
System.out?.println(sum)
|
||||||
if(sum != 10) return "b failed"
|
if(sum != 10) return "b failed"
|
||||||
|
|
||||||
|
val c7 = MyCollection5()
|
||||||
|
sum = 0
|
||||||
|
for (el in c7) {
|
||||||
|
sum = sum + el
|
||||||
|
}
|
||||||
|
if(sum != 0) return "c7 failed"
|
||||||
|
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,3 +123,14 @@ class MyCollection4() {
|
|||||||
fun hasNext() = k > 0
|
fun hasNext() = k > 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MyCollection5() {
|
||||||
|
fun iterator() : MyIterator? = null
|
||||||
|
|
||||||
|
class MyIterator() {
|
||||||
|
var k : Int = 5
|
||||||
|
|
||||||
|
fun next() : Int = k--
|
||||||
|
fun hasNext() = k > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user