multi-index array expressions and related fixes
This commit is contained in:
@@ -52,7 +52,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
private int myLastLineNumber = -1;
|
||||
|
||||
private final InstructionAdapter v;
|
||||
private final FrameMap myMap;
|
||||
private final FrameMap myFrameMap;
|
||||
private final JetTypeMapper typeMapper;
|
||||
|
||||
private final GenerationState state;
|
||||
@@ -68,7 +68,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
Type returnType,
|
||||
ClassContext context,
|
||||
GenerationState state) {
|
||||
this.myMap = myMap;
|
||||
this.myFrameMap = myMap;
|
||||
this.typeMapper = state.getTypeMapper();
|
||||
this.returnType = returnType;
|
||||
this.state = state;
|
||||
@@ -264,7 +264,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
JetType paramType = parameterDescriptor.getOutType();
|
||||
Type asmParamType = typeMapper.mapType(paramType);
|
||||
|
||||
int iteratorVar = myMap.enterTemp();
|
||||
int iteratorVar = myFrameMap.enterTemp();
|
||||
gen(expression.getLoopRange(), loopRangeType);
|
||||
invokeFunctionNoParams(iteratorDescriptor, asmIterType, v);
|
||||
v.store(iteratorVar, asmIterType);
|
||||
@@ -289,7 +289,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
v.ifeq(end);
|
||||
|
||||
myMap.enter(parameterDescriptor, asmParamType.getSize());
|
||||
myFrameMap.enter(parameterDescriptor, asmParamType.getSize());
|
||||
v.load(iteratorVar, asmIterType);
|
||||
invokeFunctionNoParams(nextDescriptor, asmParamType, v);
|
||||
|
||||
@@ -304,10 +304,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
v.goTo(begin);
|
||||
v.mark(end);
|
||||
|
||||
int paramIndex = myMap.leave(parameterDescriptor);
|
||||
int paramIndex = myFrameMap.leave(parameterDescriptor);
|
||||
//noinspection ConstantConditions
|
||||
v.visitLocalVariable(loopParameter.getName(), asmParamType.getDescriptor(), null, begin, end, paramIndex);
|
||||
myMap.leaveTemp();
|
||||
myFrameMap.leaveTemp();
|
||||
myBreakTargets.pop();
|
||||
myContinueTargets.pop();
|
||||
}
|
||||
@@ -338,7 +338,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
JetType paramType = parameterDescriptor.getOutType();
|
||||
Type asmParamType = typeMapper.mapType(paramType);
|
||||
|
||||
myMap.enter(parameterDescriptor, asmParamType.getSize());
|
||||
myFrameMap.enter(parameterDescriptor, asmParamType.getSize());
|
||||
generatePrologue();
|
||||
|
||||
Label condition = new Label();
|
||||
@@ -358,7 +358,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
v.mark(end);
|
||||
|
||||
cleanupTemp();
|
||||
final int paramIndex = myMap.leave(parameterDescriptor);
|
||||
final int paramIndex = myFrameMap.leave(parameterDescriptor);
|
||||
//noinspection ConstantConditions
|
||||
v.visitLocalVariable(expression.getLoopParameter().getName(), asmParamType.getDescriptor(), null, condition, end, paramIndex);
|
||||
myBreakTargets.pop();
|
||||
@@ -386,11 +386,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
@Override
|
||||
protected void generatePrologue() {
|
||||
myLengthVar = myMap.enterTemp();
|
||||
myLengthVar = myFrameMap.enterTemp();
|
||||
gen(expression.getLoopRange(), loopRangeType);
|
||||
v.arraylength();
|
||||
v.store(myLengthVar, Type.INT_TYPE);
|
||||
myIndexVar = myMap.enterTemp();
|
||||
myIndexVar = myFrameMap.enterTemp();
|
||||
v.iconst(0);
|
||||
v.store(myIndexVar, Type.INT_TYPE);
|
||||
}
|
||||
@@ -414,7 +414,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
|
||||
protected void cleanupTemp() {
|
||||
myMap.leaveTemp(2);
|
||||
myFrameMap.leaveTemp(2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,7 +427,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
@Override
|
||||
protected void generatePrologue() {
|
||||
myEndVar = myMap.enterTemp();
|
||||
myEndVar = myFrameMap.enterTemp();
|
||||
if(isIntRangeExpr(expression.getLoopRange())) {
|
||||
JetBinaryExpression rangeExpression = (JetBinaryExpression) expression.getLoopRange();
|
||||
//noinspection ConstantConditions
|
||||
@@ -461,7 +461,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
@Override
|
||||
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 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);
|
||||
assert variableDescriptor != null;
|
||||
|
||||
int index = myMap.leave(variableDescriptor);
|
||||
int index = myFrameMap.leave(variableDescriptor);
|
||||
|
||||
final Type sharedVarType = getSharedVarType(variableDescriptor);
|
||||
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) {
|
||||
return myMap.getIndex(descriptor);
|
||||
return myFrameMap.getIndex(descriptor);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
final StackValue outer;
|
||||
if (!thisDone && myMap instanceof ConstructorFrameMap) {
|
||||
outer = StackValue.local(((ConstructorFrameMap) myMap).getOuterThisIndex(), JetTypeMapper.TYPE_OBJECT);
|
||||
if (!thisDone && myFrameMap instanceof ConstructorFrameMap) {
|
||||
outer = StackValue.local(((ConstructorFrameMap) myFrameMap).getOuterThisIndex(), JetTypeMapper.TYPE_OBJECT);
|
||||
}
|
||||
else {
|
||||
thisToStack();
|
||||
@@ -1188,12 +1188,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
else if(resolvedValueArgument instanceof VarargValueArgument) {
|
||||
VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument;
|
||||
JetType outType = valueParameterDescriptor.getOutType();
|
||||
|
||||
|
||||
Type type = typeMapper.mapType(outType);
|
||||
assert type.getSort() == Type.ARRAY;
|
||||
Type elementType = type.getElementType();
|
||||
int size = valueArgument.getArgumentExpressions().size();
|
||||
|
||||
|
||||
v.iconst(valueArgument.getArgumentExpressions().size());
|
||||
v.newarray(elementType);
|
||||
for(int i = 0; i != size; ++i) {
|
||||
@@ -1202,7 +1202,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
gen(valueArgument.getArgumentExpressions().get(i), elementType);
|
||||
StackValue.arrayElement(elementType, false).store(v);
|
||||
}
|
||||
|
||||
|
||||
// throw new UnsupportedOperationException("Varargs are not supported yet");
|
||||
}
|
||||
else {
|
||||
@@ -1631,12 +1631,20 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
|
||||
final Callable callable = resolveToCallable(op);
|
||||
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);
|
||||
//noinspection ConstantConditions
|
||||
if (bindingContext.get(BindingContext.VARIABLE_REASSIGNMENT, expression)) {
|
||||
if (callable instanceof IntrinsicMethod) {
|
||||
StackValue value = gen(lhs); // receiver
|
||||
value.dupReceiver(v, 0); // receiver receiver
|
||||
value.dupReceiver(v); // receiver receiver
|
||||
value.put(lhsType, v); // receiver lhs
|
||||
final IntrinsicMethod intrinsic = (IntrinsicMethod) callable;
|
||||
//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) {
|
||||
StackValue value = gen(expression.getLeft());
|
||||
if (keepReturnValue) {
|
||||
value.dupReceiver(v, 0);
|
||||
value.dupReceiver(v);
|
||||
}
|
||||
value.put(lhsType, v);
|
||||
genToJVMStack(expression.getRight());
|
||||
@@ -1747,7 +1755,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
}
|
||||
StackValue value = genQualified(receiver, operand);
|
||||
value.dupReceiver(v, 0);
|
||||
value.dupReceiver(v);
|
||||
value.put(asmType, v);
|
||||
if (asmType == Type.LONG_TYPE) {
|
||||
//noinspection UnnecessaryBoxing
|
||||
@@ -1914,7 +1922,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
|
||||
if(args.size() == 2) {
|
||||
int sizeIndex = myMap.enterTemp(2);
|
||||
int sizeIndex = myFrameMap.enterTemp(2);
|
||||
int indexIndex = sizeIndex+1;
|
||||
|
||||
v.dup();
|
||||
@@ -1946,7 +1954,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
v.visitLabel(end);
|
||||
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);
|
||||
final Type arrayType = type == null ? Type.VOID_TYPE : typeMapper.mapType(type);
|
||||
gen(array, arrayType);
|
||||
generateArrayIndex(expression);
|
||||
if (arrayType.getSort() == Type.ARRAY) {
|
||||
final List<JetExpression> indices = expression.getIndexExpressions();
|
||||
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())) {
|
||||
JetType elementType = type.getArguments().get(0).getType();
|
||||
Type notBoxed = typeMapper.mapType(elementType);
|
||||
@@ -1969,27 +1981,39 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
}
|
||||
else {
|
||||
DeclarationDescriptor operationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression);
|
||||
CallableMethod accessor = typeMapper.mapToCallableMethod((FunctionDescriptor) operationDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
CallableMethod accessor = typeMapper.mapToCallableMethod(operationDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
|
||||
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) {
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression);
|
||||
FunctionDescriptor setterDescriptor = resolvedCall == null ? null : resolvedCall.getResultingDescriptor();
|
||||
return StackValue.collectionElement(
|
||||
accessor.getSignature().getReturnType(),
|
||||
accessor,
|
||||
setterDescriptor != null ? typeMapper.mapToCallableMethod(setterDescriptor, OwnerKind.IMPLEMENTATION) : null);
|
||||
if(getterDescriptor.getReceiverParameter().exists()) {
|
||||
index++;
|
||||
}
|
||||
asmType = accessor.getSignature().getReturnType();
|
||||
}
|
||||
else {
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression);
|
||||
FunctionDescriptor getterDescriptor = resolvedCall == null ? null : resolvedCall.getResultingDescriptor();
|
||||
return StackValue.collectionElement(
|
||||
accessor.getSignature().getArgumentTypes()[1],
|
||||
getterDescriptor != null ? typeMapper.mapToCallableMethod(getterDescriptor, OwnerKind.IMPLEMENTATION) : null,
|
||||
accessor);
|
||||
if(setterDescriptor.getReceiverParameter().exists()) {
|
||||
index++;
|
||||
}
|
||||
asmType = argumentTypes[argumentTypes.length-1];
|
||||
}
|
||||
|
||||
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
|
||||
public StackValue visitThrowExpression(JetThrowExpression expression, StackValue receiver) {
|
||||
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());
|
||||
assert descriptor != null;
|
||||
Type descriptorType = typeMapper.mapType(descriptor.getOutType());
|
||||
myMap.enter(descriptor, 1);
|
||||
myFrameMap.enter(descriptor, 1);
|
||||
int index = lookupLocal(descriptor);
|
||||
v.store(index, descriptorType);
|
||||
|
||||
gen(clause.getCatchBody(), Type.VOID_TYPE);
|
||||
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());
|
||||
}
|
||||
if (finallyBlock != null) {
|
||||
Label finallyStart = new Label();
|
||||
v.mark(finallyStart);
|
||||
|
||||
int index = myMap.enterTemp();
|
||||
int index = myFrameMap.enterTemp();
|
||||
v.store(index, THROWABLE_TYPE);
|
||||
|
||||
gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE);
|
||||
@@ -2104,7 +2121,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
v.load(index, THROWABLE_TYPE);
|
||||
v.athrow();
|
||||
|
||||
myMap.leaveTemp();
|
||||
myFrameMap.leaveTemp();
|
||||
|
||||
v.visitTryCatchBlock(tryStart, tryEnd, finallyStart, null);
|
||||
}
|
||||
@@ -2159,7 +2176,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
if (pattern instanceof JetTypePattern) {
|
||||
JetTypeReference typeReference = ((JetTypePattern) pattern).getTypeReference();
|
||||
JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference);
|
||||
expressionToMatch.dupReceiver(v, 0);
|
||||
expressionToMatch.dupReceiver(v);
|
||||
generateInstanceOf(expressionToMatch, jetType, false);
|
||||
StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE);
|
||||
return negated ? StackValue.not(value) : value;
|
||||
@@ -2169,7 +2186,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
else if (pattern instanceof JetExpressionPattern) {
|
||||
final Type subjectType = expressionToMatch.type;
|
||||
expressionToMatch.dupReceiver(v, 0);
|
||||
expressionToMatch.dupReceiver(v);
|
||||
expressionToMatch.put(subjectType, v);
|
||||
JetExpression condExpression = ((JetExpressionPattern) pattern).getExpression();
|
||||
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);
|
||||
assert variableDescriptor != null;
|
||||
final Type varType = typeMapper.mapType(variableDescriptor.getOutType());
|
||||
myMap.enter(variableDescriptor, varType.getSize());
|
||||
expressionToMatch.dupReceiver(v, 0);
|
||||
myFrameMap.enter(variableDescriptor, varType.getSize());
|
||||
expressionToMatch.dupReceiver(v);
|
||||
expressionToMatch.put(varType, v);
|
||||
final int varIndex = myMap.getIndex(variableDescriptor);
|
||||
final int varIndex = myFrameMap.getIndex(variableDescriptor);
|
||||
v.store(varIndex, varType);
|
||||
return generateWhenCondition(varType, varIndex, ((JetBindingPattern) pattern).getCondition(), null);
|
||||
}
|
||||
@@ -2202,7 +2219,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
Label lblFail = new Label();
|
||||
Label lblDone = new Label();
|
||||
expressionToMatch.dupReceiver(v, 0);
|
||||
expressionToMatch.dupReceiver(v);
|
||||
expressionToMatch.put(OBJECT_TYPE, v);
|
||||
v.dup();
|
||||
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) {
|
||||
JetExpression expr = expression.getSubjectExpression();
|
||||
final Type subjectType = expressionType(expr);
|
||||
final int subjectLocal = myMap.enterTemp(subjectType.getSize());
|
||||
final int subjectLocal = myFrameMap.enterTemp(subjectType.getSize());
|
||||
gen(expr, subjectType);
|
||||
v.store(subjectLocal, subjectType);
|
||||
|
||||
@@ -2396,7 +2413,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
v.mark(nextCondition);
|
||||
}
|
||||
nextCondition = new Label();
|
||||
FrameMap.Mark mark = myMap.mark();
|
||||
FrameMap.Mark mark = myFrameMap.mark();
|
||||
Label thisEntry = new Label();
|
||||
if (!whenEntry.isElse()) {
|
||||
final JetWhenCondition[] conditions = whenEntry.getConditions();
|
||||
@@ -2424,7 +2441,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
v.mark(end);
|
||||
|
||||
myMap.leaveTemp(subjectType.getSize());
|
||||
myFrameMap.leaveTemp(subjectType.getSize());
|
||||
return StackValue.onStack(expressionType(expression));
|
||||
}
|
||||
|
||||
|
||||
@@ -81,9 +81,10 @@ public class FunctionCodegen {
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state);
|
||||
|
||||
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++) {
|
||||
ValueParameterDescriptor parameter = paramDescrs.get(i);
|
||||
frameMap.enter(parameter, argTypes[i].getSize());
|
||||
frameMap.enter(parameter, argTypes[i+add].getSize());
|
||||
}
|
||||
|
||||
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
||||
|
||||
@@ -547,6 +547,9 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
||||
if(functionDescriptor == null)
|
||||
return null;
|
||||
|
||||
final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration();
|
||||
final List<Type> valueParameterTypes = new ArrayList<Type>();
|
||||
Method descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, kind);
|
||||
|
||||
@@ -38,7 +38,7 @@ public abstract class StackValue {
|
||||
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) {
|
||||
@@ -84,8 +84,8 @@ public abstract class StackValue {
|
||||
return new ArrayElement(type, unbox);
|
||||
}
|
||||
|
||||
public static StackValue collectionElement(Type type, CallableMethod getter, CallableMethod setter) {
|
||||
return new CollectionElement(type, getter, setter);
|
||||
public static StackValue collectionElement(Type type, CallableMethod getter, CallableMethod setter, FrameMap frame) {
|
||||
return new CollectionElement(type, getter, setter, frame);
|
||||
}
|
||||
|
||||
public static StackValue field(Type type, String owner, String name, boolean isStatic) {
|
||||
@@ -456,24 +456,21 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dupReceiver(InstructionAdapter v, int below) {
|
||||
if (below == 1) {
|
||||
v.dup2X1();
|
||||
}
|
||||
else {
|
||||
v.dup2(); // array and index
|
||||
}
|
||||
public void dupReceiver(InstructionAdapter v) {
|
||||
v.dup2(); // array and index
|
||||
}
|
||||
}
|
||||
|
||||
private static class CollectionElement extends StackValue {
|
||||
private final CallableMethod getter;
|
||||
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);
|
||||
this.getter = getter;
|
||||
this.setter = setter;
|
||||
this.frame = frame;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -494,13 +491,70 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dupReceiver(InstructionAdapter v, int below) {
|
||||
if (below == 1) {
|
||||
v.dup2X1();
|
||||
}
|
||||
else {
|
||||
public void dupReceiver(InstructionAdapter v) {
|
||||
int size = calcSize();
|
||||
|
||||
if(size == 2) {
|
||||
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
|
||||
public void dupReceiver(InstructionAdapter v, int below) {
|
||||
public void dupReceiver(InstructionAdapter v) {
|
||||
if (!isStatic) {
|
||||
if (below == 1) {
|
||||
v.dupX1();
|
||||
}
|
||||
else {
|
||||
v.dup();
|
||||
}
|
||||
v.dup();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,7 +606,7 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dupReceiver(InstructionAdapter v, int below) {
|
||||
public void dupReceiver(InstructionAdapter v) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -607,14 +656,9 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dupReceiver(InstructionAdapter v, int below) {
|
||||
public void dupReceiver(InstructionAdapter v) {
|
||||
if (!isStatic) {
|
||||
if (below == 1) {
|
||||
v.dupX1();
|
||||
}
|
||||
else {
|
||||
v.dup();
|
||||
}
|
||||
v.dup();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -716,13 +760,8 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dupReceiver(InstructionAdapter v, int below) {
|
||||
if (below == 1) {
|
||||
v.dupX1();
|
||||
}
|
||||
else {
|
||||
v.dup();
|
||||
}
|
||||
public void dupReceiver(InstructionAdapter v) {
|
||||
v.dup();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -32,7 +32,7 @@ public class Increment implements IntrinsicMethod {
|
||||
}
|
||||
}
|
||||
StackValue value = codegen.genQualified(receiver, operand);
|
||||
value.dupReceiver(v, 0);
|
||||
value. dupReceiver(v);
|
||||
value.put(expectedType, v);
|
||||
if (expectedType == Type.LONG_TYPE) {
|
||||
v.lconst(myDelta);
|
||||
|
||||
@@ -107,4 +107,63 @@ public class ArrayGenTest extends CodegenTestCase {
|
||||
Method foo = generateFunction();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user