multi-index array expressions and related fixes

This commit is contained in:
Alex Tkachman
2011-11-02 23:51:27 +01:00
parent 532af2639f
commit 3ad5e74abb
6 changed files with 221 additions and 102 deletions
@@ -52,7 +52,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
private int myLastLineNumber = -1; private int myLastLineNumber = -1;
private final InstructionAdapter v; private final InstructionAdapter v;
private final FrameMap myMap; private final FrameMap myFrameMap;
private final JetTypeMapper typeMapper; private final JetTypeMapper typeMapper;
private final GenerationState state; private final GenerationState state;
@@ -68,7 +68,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
Type returnType, Type returnType,
ClassContext context, ClassContext context,
GenerationState state) { GenerationState state) {
this.myMap = myMap; this.myFrameMap = myMap;
this.typeMapper = state.getTypeMapper(); this.typeMapper = state.getTypeMapper();
this.returnType = returnType; this.returnType = returnType;
this.state = state; this.state = state;
@@ -264,7 +264,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
JetType paramType = parameterDescriptor.getOutType(); JetType paramType = parameterDescriptor.getOutType();
Type asmParamType = typeMapper.mapType(paramType); Type asmParamType = typeMapper.mapType(paramType);
int iteratorVar = myMap.enterTemp(); int iteratorVar = myFrameMap.enterTemp();
gen(expression.getLoopRange(), loopRangeType); gen(expression.getLoopRange(), loopRangeType);
invokeFunctionNoParams(iteratorDescriptor, asmIterType, v); invokeFunctionNoParams(iteratorDescriptor, asmIterType, v);
v.store(iteratorVar, asmIterType); v.store(iteratorVar, asmIterType);
@@ -289,7 +289,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
v.ifeq(end); v.ifeq(end);
myMap.enter(parameterDescriptor, asmParamType.getSize()); myFrameMap.enter(parameterDescriptor, asmParamType.getSize());
v.load(iteratorVar, asmIterType); v.load(iteratorVar, asmIterType);
invokeFunctionNoParams(nextDescriptor, asmParamType, v); invokeFunctionNoParams(nextDescriptor, asmParamType, v);
@@ -304,10 +304,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.goTo(begin); v.goTo(begin);
v.mark(end); v.mark(end);
int paramIndex = myMap.leave(parameterDescriptor); int paramIndex = myFrameMap.leave(parameterDescriptor);
//noinspection ConstantConditions //noinspection ConstantConditions
v.visitLocalVariable(loopParameter.getName(), asmParamType.getDescriptor(), null, begin, end, paramIndex); v.visitLocalVariable(loopParameter.getName(), asmParamType.getDescriptor(), null, begin, end, paramIndex);
myMap.leaveTemp(); myFrameMap.leaveTemp();
myBreakTargets.pop(); myBreakTargets.pop();
myContinueTargets.pop(); myContinueTargets.pop();
} }
@@ -338,7 +338,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
JetType paramType = parameterDescriptor.getOutType(); JetType paramType = parameterDescriptor.getOutType();
Type asmParamType = typeMapper.mapType(paramType); Type asmParamType = typeMapper.mapType(paramType);
myMap.enter(parameterDescriptor, asmParamType.getSize()); myFrameMap.enter(parameterDescriptor, asmParamType.getSize());
generatePrologue(); generatePrologue();
Label condition = new Label(); Label condition = new Label();
@@ -358,7 +358,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.mark(end); v.mark(end);
cleanupTemp(); cleanupTemp();
final int paramIndex = myMap.leave(parameterDescriptor); final int paramIndex = myFrameMap.leave(parameterDescriptor);
//noinspection ConstantConditions //noinspection ConstantConditions
v.visitLocalVariable(expression.getLoopParameter().getName(), asmParamType.getDescriptor(), null, condition, end, paramIndex); v.visitLocalVariable(expression.getLoopParameter().getName(), asmParamType.getDescriptor(), null, condition, end, paramIndex);
myBreakTargets.pop(); myBreakTargets.pop();
@@ -386,11 +386,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override @Override
protected void generatePrologue() { protected void generatePrologue() {
myLengthVar = myMap.enterTemp(); myLengthVar = myFrameMap.enterTemp();
gen(expression.getLoopRange(), loopRangeType); gen(expression.getLoopRange(), loopRangeType);
v.arraylength(); v.arraylength();
v.store(myLengthVar, Type.INT_TYPE); v.store(myLengthVar, Type.INT_TYPE);
myIndexVar = myMap.enterTemp(); myIndexVar = myFrameMap.enterTemp();
v.iconst(0); v.iconst(0);
v.store(myIndexVar, Type.INT_TYPE); v.store(myIndexVar, Type.INT_TYPE);
} }
@@ -414,7 +414,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
protected void cleanupTemp() { protected void cleanupTemp() {
myMap.leaveTemp(2); myFrameMap.leaveTemp(2);
} }
} }
@@ -427,7 +427,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override @Override
protected void generatePrologue() { protected void generatePrologue() {
myEndVar = myMap.enterTemp(); myEndVar = myFrameMap.enterTemp();
if(isIntRangeExpr(expression.getLoopRange())) { if(isIntRangeExpr(expression.getLoopRange())) {
JetBinaryExpression rangeExpression = (JetBinaryExpression) expression.getLoopRange(); JetBinaryExpression rangeExpression = (JetBinaryExpression) expression.getLoopRange();
//noinspection ConstantConditions //noinspection ConstantConditions
@@ -461,7 +461,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override @Override
protected void cleanupTemp() { protected void cleanupTemp() {
myMap.leaveTemp(1); myFrameMap.leaveTemp(1);
} }
} }
@@ -634,7 +634,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final Type sharedVarType = getSharedVarType(variableDescriptor); final Type sharedVarType = getSharedVarType(variableDescriptor);
final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType()); final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType());
myMap.enter(variableDescriptor, type.getSize()); myFrameMap.enter(variableDescriptor, type.getSize());
} }
} }
@@ -658,7 +658,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, var); VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, var);
assert variableDescriptor != null; assert variableDescriptor != null;
int index = myMap.leave(variableDescriptor); int index = myFrameMap.leave(variableDescriptor);
final Type sharedVarType = getSharedVarType(variableDescriptor); final Type sharedVarType = getSharedVarType(variableDescriptor);
final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType()); final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType());
@@ -859,7 +859,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
public int lookupLocal(DeclarationDescriptor descriptor) { public int lookupLocal(DeclarationDescriptor descriptor) {
return myMap.getIndex(descriptor); return myFrameMap.getIndex(descriptor);
} }
public void invokeFunctionNoParams(FunctionDescriptor functionDescriptor, Type type, InstructionAdapter v) { public void invokeFunctionNoParams(FunctionDescriptor functionDescriptor, Type type, InstructionAdapter v) {
@@ -1122,8 +1122,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (isSubclass((ClassDescriptor) curContextType, calleeContainingClass)) break; if (isSubclass((ClassDescriptor) curContextType, calleeContainingClass)) break;
final StackValue outer; final StackValue outer;
if (!thisDone && myMap instanceof ConstructorFrameMap) { if (!thisDone && myFrameMap instanceof ConstructorFrameMap) {
outer = StackValue.local(((ConstructorFrameMap) myMap).getOuterThisIndex(), JetTypeMapper.TYPE_OBJECT); outer = StackValue.local(((ConstructorFrameMap) myFrameMap).getOuterThisIndex(), JetTypeMapper.TYPE_OBJECT);
} }
else { else {
thisToStack(); thisToStack();
@@ -1631,12 +1631,20 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
final Callable callable = resolveToCallable(op); final Callable callable = resolveToCallable(op);
final JetExpression lhs = expression.getLeft(); final JetExpression lhs = expression.getLeft();
// if(lhs instanceof JetArrayAccessExpression) {
// JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) lhs;
// if(arrayAccessExpression.getIndexExpressions().size() != 1) {
// throw new UnsupportedOperationException("Augmented assignment with multi-index");
// }
// }
Type lhsType = expressionType(lhs); Type lhsType = expressionType(lhs);
//noinspection ConstantConditions //noinspection ConstantConditions
if (bindingContext.get(BindingContext.VARIABLE_REASSIGNMENT, expression)) { if (bindingContext.get(BindingContext.VARIABLE_REASSIGNMENT, expression)) {
if (callable instanceof IntrinsicMethod) { if (callable instanceof IntrinsicMethod) {
StackValue value = gen(lhs); // receiver StackValue value = gen(lhs); // receiver
value.dupReceiver(v, 0); // receiver receiver value.dupReceiver(v); // receiver receiver
value.put(lhsType, v); // receiver lhs value.put(lhsType, v); // receiver lhs
final IntrinsicMethod intrinsic = (IntrinsicMethod) callable; final IntrinsicMethod intrinsic = (IntrinsicMethod) callable;
//noinspection NullableProblems //noinspection NullableProblems
@@ -1659,7 +1667,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
private void callAugAssignMethod(JetBinaryExpression expression, CallableMethod callable, Type lhsType, final boolean keepReturnValue) { private void callAugAssignMethod(JetBinaryExpression expression, CallableMethod callable, Type lhsType, final boolean keepReturnValue) {
StackValue value = gen(expression.getLeft()); StackValue value = gen(expression.getLeft());
if (keepReturnValue) { if (keepReturnValue) {
value.dupReceiver(v, 0); value.dupReceiver(v);
} }
value.put(lhsType, v); value.put(lhsType, v);
genToJVMStack(expression.getRight()); genToJVMStack(expression.getRight());
@@ -1747,7 +1755,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
} }
StackValue value = genQualified(receiver, operand); StackValue value = genQualified(receiver, operand);
value.dupReceiver(v, 0); value.dupReceiver(v);
value.put(asmType, v); value.put(asmType, v);
if (asmType == Type.LONG_TYPE) { if (asmType == Type.LONG_TYPE) {
//noinspection UnnecessaryBoxing //noinspection UnnecessaryBoxing
@@ -1914,7 +1922,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
if(args.size() == 2) { if(args.size() == 2) {
int sizeIndex = myMap.enterTemp(2); int sizeIndex = myFrameMap.enterTemp(2);
int indexIndex = sizeIndex+1; int indexIndex = sizeIndex+1;
v.dup(); v.dup();
@@ -1946,7 +1954,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.visitLabel(end); v.visitLabel(end);
v.pop(); v.pop();
myMap.leaveTemp(2); myFrameMap.leaveTemp(2);
} }
} }
@@ -1956,8 +1964,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, array); JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, array);
final Type arrayType = type == null ? Type.VOID_TYPE : typeMapper.mapType(type); final Type arrayType = type == null ? Type.VOID_TYPE : typeMapper.mapType(type);
gen(array, arrayType); gen(array, arrayType);
generateArrayIndex(expression); final List<JetExpression> indices = expression.getIndexExpressions();
if (arrayType.getSort() == Type.ARRAY) { FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression);
if (arrayType.getSort() == Type.ARRAY && indices.size() == 1 && operationDescriptor.getValueParameters().get(0).getOutType().equals(state.getStandardLibrary().getIntType())) {
for (JetExpression index : indices) {
gen(index, Type.INT_TYPE);
}
if(state.getStandardLibrary().getArray().equals(type.getConstructor().getDeclarationDescriptor())) { if(state.getStandardLibrary().getArray().equals(type.getConstructor().getDeclarationDescriptor())) {
JetType elementType = type.getArguments().get(0).getType(); JetType elementType = type.getArguments().get(0).getType();
Type notBoxed = typeMapper.mapType(elementType); Type notBoxed = typeMapper.mapType(elementType);
@@ -1969,27 +1981,39 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
} }
else { else {
DeclarationDescriptor operationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression); CallableMethod accessor = typeMapper.mapToCallableMethod(operationDescriptor, OwnerKind.IMPLEMENTATION);
CallableMethod accessor = typeMapper.mapToCallableMethod((FunctionDescriptor) operationDescriptor, OwnerKind.IMPLEMENTATION);
boolean isGetter = accessor.getSignature().getName().equals("get"); boolean isGetter = accessor.getSignature().getName().equals("get");
ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression);
FunctionDescriptor setterDescriptor = resolvedSetCall == null ? null : resolvedSetCall.getResultingDescriptor();
CallableMethod setter = resolvedSetCall == null ? null : typeMapper.mapToCallableMethod(setterDescriptor, OwnerKind.IMPLEMENTATION);
ResolvedCall<FunctionDescriptor> resolvedGetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression);
FunctionDescriptor getterDescriptor = resolvedGetCall == null ? null : resolvedGetCall.getResultingDescriptor();
CallableMethod getter = resolvedGetCall == null ? null : typeMapper.mapToCallableMethod(getterDescriptor, OwnerKind.IMPLEMENTATION);
Type asmType;
Type[] argumentTypes = accessor.getSignature().getArgumentTypes();
int index = 0;
if(isGetter) { if(isGetter) {
ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression); if(getterDescriptor.getReceiverParameter().exists()) {
FunctionDescriptor setterDescriptor = resolvedCall == null ? null : resolvedCall.getResultingDescriptor(); index++;
return StackValue.collectionElement( }
accessor.getSignature().getReturnType(), asmType = accessor.getSignature().getReturnType();
accessor,
setterDescriptor != null ? typeMapper.mapToCallableMethod(setterDescriptor, OwnerKind.IMPLEMENTATION) : null);
} }
else { else {
ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression); if(setterDescriptor.getReceiverParameter().exists()) {
FunctionDescriptor getterDescriptor = resolvedCall == null ? null : resolvedCall.getResultingDescriptor(); index++;
return StackValue.collectionElement( }
accessor.getSignature().getArgumentTypes()[1], asmType = argumentTypes[argumentTypes.length-1];
getterDescriptor != null ? typeMapper.mapToCallableMethod(getterDescriptor, OwnerKind.IMPLEMENTATION) : null,
accessor);
} }
for (JetExpression jetExpression : expression.getIndexExpressions()) {
gen(jetExpression, argumentTypes[index]);
index++;
}
return StackValue.collectionElement(asmType, getter, setter, myFrameMap);
} }
} }
@@ -2033,13 +2057,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
} }
private void generateArrayIndex(JetArrayAccessExpression expression) {
final List<JetExpression> indices = expression.getIndexExpressions();
for (JetExpression index : indices) {
gen(index, Type.INT_TYPE);
}
}
@Override @Override
public StackValue visitThrowExpression(JetThrowExpression expression, StackValue receiver) { public StackValue visitThrowExpression(JetThrowExpression expression, StackValue receiver) {
gen(expression.getThrownExpression(), JetTypeMapper.TYPE_OBJECT); gen(expression.getThrownExpression(), JetTypeMapper.TYPE_OBJECT);
@@ -2082,21 +2099,21 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
VariableDescriptor descriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, clause.getCatchParameter()); VariableDescriptor descriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, clause.getCatchParameter());
assert descriptor != null; assert descriptor != null;
Type descriptorType = typeMapper.mapType(descriptor.getOutType()); Type descriptorType = typeMapper.mapType(descriptor.getOutType());
myMap.enter(descriptor, 1); myFrameMap.enter(descriptor, 1);
int index = lookupLocal(descriptor); int index = lookupLocal(descriptor);
v.store(index, descriptorType); v.store(index, descriptorType);
gen(clause.getCatchBody(), Type.VOID_TYPE); gen(clause.getCatchBody(), Type.VOID_TYPE);
v.goTo(end); // TODO don't generate goto if there's no code following try/catch v.goTo(end); // TODO don't generate goto if there's no code following try/catch
myMap.leave(descriptor); myFrameMap.leave(descriptor);
v.visitTryCatchBlock(tryStart, tryEnd, clauseStart, descriptorType.getInternalName()); v.visitTryCatchBlock(tryStart, tryEnd, clauseStart, descriptorType.getInternalName());
} }
if (finallyBlock != null) { if (finallyBlock != null) {
Label finallyStart = new Label(); Label finallyStart = new Label();
v.mark(finallyStart); v.mark(finallyStart);
int index = myMap.enterTemp(); int index = myFrameMap.enterTemp();
v.store(index, THROWABLE_TYPE); v.store(index, THROWABLE_TYPE);
gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE); gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE);
@@ -2104,7 +2121,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.load(index, THROWABLE_TYPE); v.load(index, THROWABLE_TYPE);
v.athrow(); v.athrow();
myMap.leaveTemp(); myFrameMap.leaveTemp();
v.visitTryCatchBlock(tryStart, tryEnd, finallyStart, null); v.visitTryCatchBlock(tryStart, tryEnd, finallyStart, null);
} }
@@ -2159,7 +2176,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (pattern instanceof JetTypePattern) { if (pattern instanceof JetTypePattern) {
JetTypeReference typeReference = ((JetTypePattern) pattern).getTypeReference(); JetTypeReference typeReference = ((JetTypePattern) pattern).getTypeReference();
JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference); JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference);
expressionToMatch.dupReceiver(v, 0); expressionToMatch.dupReceiver(v);
generateInstanceOf(expressionToMatch, jetType, false); generateInstanceOf(expressionToMatch, jetType, false);
StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE); StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE);
return negated ? StackValue.not(value) : value; return negated ? StackValue.not(value) : value;
@@ -2169,7 +2186,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
else if (pattern instanceof JetExpressionPattern) { else if (pattern instanceof JetExpressionPattern) {
final Type subjectType = expressionToMatch.type; final Type subjectType = expressionToMatch.type;
expressionToMatch.dupReceiver(v, 0); expressionToMatch.dupReceiver(v);
expressionToMatch.put(subjectType, v); expressionToMatch.put(subjectType, v);
JetExpression condExpression = ((JetExpressionPattern) pattern).getExpression(); JetExpression condExpression = ((JetExpressionPattern) pattern).getExpression();
Type condType = isNumberPrimitive(subjectType) ? expressionType(condExpression) : OBJECT_TYPE; Type condType = isNumberPrimitive(subjectType) ? expressionType(condExpression) : OBJECT_TYPE;
@@ -2184,10 +2201,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, var); final VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, var);
assert variableDescriptor != null; assert variableDescriptor != null;
final Type varType = typeMapper.mapType(variableDescriptor.getOutType()); final Type varType = typeMapper.mapType(variableDescriptor.getOutType());
myMap.enter(variableDescriptor, varType.getSize()); myFrameMap.enter(variableDescriptor, varType.getSize());
expressionToMatch.dupReceiver(v, 0); expressionToMatch.dupReceiver(v);
expressionToMatch.put(varType, v); expressionToMatch.put(varType, v);
final int varIndex = myMap.getIndex(variableDescriptor); final int varIndex = myFrameMap.getIndex(variableDescriptor);
v.store(varIndex, varType); v.store(varIndex, varType);
return generateWhenCondition(varType, varIndex, ((JetBindingPattern) pattern).getCondition(), null); return generateWhenCondition(varType, varIndex, ((JetBindingPattern) pattern).getCondition(), null);
} }
@@ -2202,7 +2219,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
Label lblFail = new Label(); Label lblFail = new Label();
Label lblDone = new Label(); Label lblDone = new Label();
expressionToMatch.dupReceiver(v, 0); expressionToMatch.dupReceiver(v);
expressionToMatch.put(OBJECT_TYPE, v); expressionToMatch.put(OBJECT_TYPE, v);
v.dup(); v.dup();
final String tupleClassName = "jet/Tuple" + entries.size(); final String tupleClassName = "jet/Tuple" + entries.size();
@@ -2384,7 +2401,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
public StackValue visitWhenExpression(JetWhenExpression expression, StackValue receiver) { public StackValue visitWhenExpression(JetWhenExpression expression, StackValue receiver) {
JetExpression expr = expression.getSubjectExpression(); JetExpression expr = expression.getSubjectExpression();
final Type subjectType = expressionType(expr); final Type subjectType = expressionType(expr);
final int subjectLocal = myMap.enterTemp(subjectType.getSize()); final int subjectLocal = myFrameMap.enterTemp(subjectType.getSize());
gen(expr, subjectType); gen(expr, subjectType);
v.store(subjectLocal, subjectType); v.store(subjectLocal, subjectType);
@@ -2396,7 +2413,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.mark(nextCondition); v.mark(nextCondition);
} }
nextCondition = new Label(); nextCondition = new Label();
FrameMap.Mark mark = myMap.mark(); FrameMap.Mark mark = myFrameMap.mark();
Label thisEntry = new Label(); Label thisEntry = new Label();
if (!whenEntry.isElse()) { if (!whenEntry.isElse()) {
final JetWhenCondition[] conditions = whenEntry.getConditions(); final JetWhenCondition[] conditions = whenEntry.getConditions();
@@ -2424,7 +2441,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
v.mark(end); v.mark(end);
myMap.leaveTemp(subjectType.getSize()); myFrameMap.leaveTemp(subjectType.getSize());
return StackValue.onStack(expressionType(expression)); return StackValue.onStack(expressionType(expression));
} }
@@ -81,9 +81,10 @@ public class FunctionCodegen {
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state);
Type[] argTypes = jvmSignature.getArgumentTypes(); Type[] argTypes = jvmSignature.getArgumentTypes();
int add = functionDescriptor.getReceiverParameter().exists() ? state.getTypeMapper().mapType(functionDescriptor.getReceiverParameter().getType()).getSize() : 0;
for (int i = 0; i < paramDescrs.size(); i++) { for (int i = 0; i < paramDescrs.size(); i++) {
ValueParameterDescriptor parameter = paramDescrs.get(i); ValueParameterDescriptor parameter = paramDescrs.get(i);
frameMap.enter(parameter, argTypes[i].getSize()); frameMap.enter(parameter, argTypes[i+add].getSize());
} }
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) { for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
@@ -547,6 +547,9 @@ public class JetTypeMapper {
} }
public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) { public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) {
if(functionDescriptor == null)
return null;
final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration(); final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration();
final List<Type> valueParameterTypes = new ArrayList<Type>(); final List<Type> valueParameterTypes = new ArrayList<Type>();
Method descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, kind); Method descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, kind);
@@ -38,7 +38,7 @@ public abstract class StackValue {
throw new UnsupportedOperationException("cannot store to value " + this); throw new UnsupportedOperationException("cannot store to value " + this);
} }
public void dupReceiver(InstructionAdapter v, int below) { public void dupReceiver(InstructionAdapter v) {
} }
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) { public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
@@ -84,8 +84,8 @@ public abstract class StackValue {
return new ArrayElement(type, unbox); return new ArrayElement(type, unbox);
} }
public static StackValue collectionElement(Type type, CallableMethod getter, CallableMethod setter) { public static StackValue collectionElement(Type type, CallableMethod getter, CallableMethod setter, FrameMap frame) {
return new CollectionElement(type, getter, setter); return new CollectionElement(type, getter, setter, frame);
} }
public static StackValue field(Type type, String owner, String name, boolean isStatic) { public static StackValue field(Type type, String owner, String name, boolean isStatic) {
@@ -456,24 +456,21 @@ public abstract class StackValue {
} }
@Override @Override
public void dupReceiver(InstructionAdapter v, int below) { public void dupReceiver(InstructionAdapter v) {
if (below == 1) { v.dup2(); // array and index
v.dup2X1();
}
else {
v.dup2(); // array and index
}
} }
} }
private static class CollectionElement extends StackValue { private static class CollectionElement extends StackValue {
private final CallableMethod getter; private final CallableMethod getter;
private final CallableMethod setter; private final CallableMethod setter;
private final FrameMap frame;
public CollectionElement(Type type, CallableMethod getter, CallableMethod setter) { public CollectionElement(Type type, CallableMethod getter, CallableMethod setter, FrameMap frame) {
super(type); super(type);
this.getter = getter; this.getter = getter;
this.setter = setter; this.setter = setter;
this.frame = frame;
} }
@Override @Override
@@ -494,13 +491,70 @@ public abstract class StackValue {
} }
@Override @Override
public void dupReceiver(InstructionAdapter v, int below) { public void dupReceiver(InstructionAdapter v) {
if (below == 1) { int size = calcSize();
v.dup2X1();
} if(size == 2) {
else {
v.dup2(); // collection and index v.dup2(); // collection and index
} }
else {
Method signature = getter.getSignature();
Type[] argumentTypes = signature.getArgumentTypes();
int firstIndex = frame.enterTemp();
int lastIndex = firstIndex;
frame.leaveTemp();
for(int i = argumentTypes.length-1; i >= 0; i--) {
int sz = argumentTypes[i].getSize();
frame.enterTemp(sz);
lastIndex += sz;
v.store(lastIndex-sz, argumentTypes[i]);
}
if(getter.getInvokeOpcode() != Opcodes.INVOKESTATIC) {
frame.enterTemp();
lastIndex++;
v.store(lastIndex-1, JetTypeMapper.TYPE_OBJECT);
}
firstIndex = lastIndex;
int curIndex = lastIndex;
if(getter.getInvokeOpcode() != Opcodes.INVOKESTATIC) {
v.load(curIndex-1, JetTypeMapper.TYPE_OBJECT);
curIndex--;
}
for(int i = 0; i != argumentTypes.length; i++) {
int sz = argumentTypes[i].getSize();
v.load(curIndex-sz, argumentTypes[i]);
curIndex -= sz;
}
curIndex = firstIndex;
if(getter.getInvokeOpcode() != Opcodes.INVOKESTATIC) {
v.load(curIndex-1, JetTypeMapper.TYPE_OBJECT);
curIndex--;
}
for(int i = 0; i != argumentTypes.length; i++) {
int sz = argumentTypes[i].getSize();
v.load(curIndex-sz, argumentTypes[i]);
curIndex -= sz;
}
frame.leaveTemp(size);
}
}
private int calcSize() {
assert getter != null;
int size = getter.getInvokeOpcode() == Opcodes.INVOKESTATIC ? 0 : 1;
Method signature = getter.getSignature();
Type[] argumentTypes = signature.getArgumentTypes();
for(int i = 0; i != argumentTypes.length; ++i)
size += argumentTypes[i].getSize();
return size;
} }
} }
@@ -523,14 +577,9 @@ public abstract class StackValue {
} }
@Override @Override
public void dupReceiver(InstructionAdapter v, int below) { public void dupReceiver(InstructionAdapter v) {
if (!isStatic) { if (!isStatic) {
if (below == 1) { v.dup();
v.dupX1();
}
else {
v.dup();
}
} }
} }
@@ -557,7 +606,7 @@ public abstract class StackValue {
} }
@Override @Override
public void dupReceiver(InstructionAdapter v, int below) { public void dupReceiver(InstructionAdapter v) {
} }
@Override @Override
@@ -607,14 +656,9 @@ public abstract class StackValue {
} }
@Override @Override
public void dupReceiver(InstructionAdapter v, int below) { public void dupReceiver(InstructionAdapter v) {
if (!isStatic) { if (!isStatic) {
if (below == 1) { v.dup();
v.dupX1();
}
else {
v.dup();
}
} }
} }
} }
@@ -716,13 +760,8 @@ public abstract class StackValue {
} }
@Override @Override
public void dupReceiver(InstructionAdapter v, int below) { public void dupReceiver(InstructionAdapter v) {
if (below == 1) { v.dup();
v.dupX1();
}
else {
v.dup();
}
} }
@Override @Override
@@ -32,7 +32,7 @@ public class Increment implements IntrinsicMethod {
} }
} }
StackValue value = codegen.genQualified(receiver, operand); StackValue value = codegen.genQualified(receiver, operand);
value.dupReceiver(v, 0); value. dupReceiver(v);
value.put(expectedType, v); value.put(expectedType, v);
if (expectedType == Type.LONG_TYPE) { if (expectedType == Type.LONG_TYPE) {
v.lconst(myDelta); v.lconst(myDelta);
@@ -107,4 +107,63 @@ public class ArrayGenTest extends CodegenTestCase {
Method foo = generateFunction(); Method foo = generateFunction();
assertTrue((Integer)foo.invoke(null) == 12); assertTrue((Integer)foo.invoke(null) == 12);
} }
public void testCollectionAssignGetMultiIndex () throws Exception {
loadText("import java.util.ArrayList\n" +
"fun box() : String { val s = ArrayList<String>(1); s.add(\"\"); s [1, -1] = \"5\"; s[2, -2] += \"7\"; return s[2,-2] }\n" +
"fun ArrayList<String>.get(index1: Int, index2 : Int) = this[index1+index2]\n" +
"fun ArrayList<String>.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem }\n");
System.out.println(generateToText());
Method foo = generateFunction("box");
assertTrue(foo.invoke(null).equals("57"));
}
public void testArrayGetAssignMultiIndex () throws Exception {
loadText(
"fun box() : String? { val s = Array<String>(1,{ \"\" }); s [1, -1] = \"5\"; s[2, -2] += \"7\"; return s[-3,3] }\n" +
"fun Array<String>.get(index1: Int, index2 : Int) = this[index1+index2]\n" +
"fun Array<String>.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem\n }");
System.out.println(generateToText());
Method foo = generateFunction("box");
assertTrue(foo.invoke(null).equals("57"));
}
public void testCollectionGetMultiIndex () throws Exception {
loadText("import java.util.ArrayList\n" +
"fun box() : String { val s = ArrayList<String>(1); s.add(\"\"); s [1, -1] = \"5\"; return s[2, -2] }\n" +
"fun ArrayList<String>.get(index1: Int, index2 : Int) = this[index1+index2]\n" +
"fun ArrayList<String>.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem }\n");
System.out.println(generateToText());
Method foo = generateFunction("box");
assertTrue(foo.invoke(null).equals("5"));
}
public void testArrayGetMultiIndex () throws Exception {
loadText(
"fun box() : String? { val s = Array<String>(1,{ \"\" }); s [1, -1] = \"5\"; return s[-2, 2] }\n" +
"fun Array<String>.get(index1: Int, index2 : Int) = this[index1+index2]\n" +
"fun Array<String>.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem\n }");
System.out.println(generateToText());
Method foo = generateFunction("box");
assertTrue(foo.invoke(null).equals("5"));
}
public void testMap () throws Exception {
loadText(
"fun box() : Int? { val s = java.util.HashMap<String,Int?>(); s[\"239\"] = 239; return s[\"239\"] }\n" +
"fun java.util.HashMap<String,Int?>.set(index: String, elem: Int?) { this.put(index, elem) }");
System.out.println(generateToText());
Method foo = generateFunction("box");
assertTrue((Integer)foo.invoke(null) == 239);
}
public void testLongDouble () throws Exception {
loadText(
"fun box() : Int { var l = IntArray(1); l[0.lng] = 4; l[0.lng] += 6; return l[0.lng];}\n" +
"fun IntArray.set(index: Long, elem: Int) { this[index.int] = elem }\n" +
"fun IntArray.get(index: Long) = this[index.int]");
System.out.println(generateToText());
Method foo = generateFunction("box");
assertTrue((Integer)foo.invoke(null) == 10);
}
} }