generate new array creation
This commit is contained in:
@@ -26,6 +26,7 @@ import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
@@ -1153,43 +1154,61 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
|
||||
@Override
|
||||
public void visitNewExpression(JetNewExpression expression) {
|
||||
final JetUserType constructorType = (JetUserType) expression.getTypeReference().getTypeElement();
|
||||
JetTypeReference typeReference = expression.getTypeReference();
|
||||
final JetUserType constructorType = (JetUserType) typeReference.getTypeElement();
|
||||
final JetSimpleNameExpression constructorReference = constructorType.getReferenceExpression();
|
||||
DeclarationDescriptor constructorDescriptor = bindingContext.resolveReferenceExpression(constructorReference);
|
||||
final PsiElement declaration = bindingContext.getDeclarationPsiElement(constructorDescriptor);
|
||||
Type type;
|
||||
if (declaration instanceof PsiMethod) {
|
||||
final PsiMethod constructor = (PsiMethod) declaration;
|
||||
PsiClass javaClass = constructor.getContainingClass();
|
||||
Type type = JetTypeMapper.psiClassType(javaClass);
|
||||
v.anew(type);
|
||||
v.dup();
|
||||
final Method jvmConstructor = getMethodDescriptor(constructor);
|
||||
pushMethodArguments(expression, jvmConstructor);
|
||||
v.invokespecial(JetTypeMapper.jvmName(javaClass), "<init>", jvmConstructor.getDescriptor());
|
||||
myStack.push(StackValue.onStack(type));
|
||||
return;
|
||||
type = generateJavaConstructorCall(expression, (PsiMethod) declaration);
|
||||
}
|
||||
else if (constructorDescriptor instanceof ConstructorDescriptor) {
|
||||
ClassDescriptor classDecl = (ClassDescriptor) constructorDescriptor.getContainingDeclaration();
|
||||
Type type = JetTypeMapper.jetImplementationType(classDecl);
|
||||
v.anew(type);
|
||||
v.dup();
|
||||
|
||||
Method method = typeMapper.mapConstructorSignature((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
pushMethodArguments(expression, method);
|
||||
|
||||
for (JetTypeReference typeArgumentReference : constructorType.getTypeArgumentsAsTypes()) {
|
||||
JetType typeArgument = bindingContext.resolveTypeReference(typeArgumentReference);
|
||||
// TODO is the makeNullable() call correct here?
|
||||
ClassCodegen.newTypeInfo(v, typeMapper.mapType(TypeUtils.makeNullable(typeArgument)));
|
||||
type = typeMapper.mapType(bindingContext.resolveTypeReference(typeReference), OwnerKind.IMPLEMENTATION);
|
||||
if (type.getSort() == Type.ARRAY) {
|
||||
generateNewArray(expression, type);
|
||||
}
|
||||
else {
|
||||
v.anew(type);
|
||||
v.dup();
|
||||
|
||||
v.invokespecial(JetTypeMapper.jvmNameForImplementation(classDecl), "<init>", method.getDescriptor());
|
||||
myStack.push(StackValue.onStack(type));
|
||||
return;
|
||||
Method method = typeMapper.mapConstructorSignature((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
pushMethodArguments(expression, method);
|
||||
|
||||
for (JetTypeReference typeArgumentReference : constructorType.getTypeArgumentsAsTypes()) {
|
||||
JetType typeArgument = bindingContext.resolveTypeReference(typeArgumentReference);
|
||||
// TODO is the makeNullable() call correct here?
|
||||
ClassCodegen.newTypeInfo(v, typeMapper.mapType(TypeUtils.makeNullable(typeArgument)));
|
||||
}
|
||||
|
||||
ClassDescriptor classDecl = (ClassDescriptor) constructorDescriptor.getContainingDeclaration();
|
||||
v.invokespecial(JetTypeMapper.jvmNameForImplementation(classDecl), "<init>", method.getDescriptor());
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("don't know how to generate this new expression");
|
||||
}
|
||||
myStack.push(StackValue.onStack(type));
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("don't know how to generate this new expression");
|
||||
private Type generateJavaConstructorCall(JetNewExpression expression, PsiMethod constructor) {
|
||||
PsiClass javaClass = constructor.getContainingClass();
|
||||
Type type = JetTypeMapper.psiClassType(javaClass);
|
||||
v.anew(type);
|
||||
v.dup();
|
||||
final Method jvmConstructor = getMethodDescriptor(constructor);
|
||||
pushMethodArguments(expression, jvmConstructor);
|
||||
v.invokespecial(JetTypeMapper.jvmName(javaClass), "<init>", jvmConstructor.getDescriptor());
|
||||
return type;
|
||||
}
|
||||
|
||||
private void generateNewArray(JetNewExpression expression, Type type) {
|
||||
List<JetArgument> args = expression.getValueArguments();
|
||||
if (args.size() != 1) {
|
||||
throw new CompilationException("array constructor requires one value argument");
|
||||
}
|
||||
gen(args.get(0).getArgumentExpression(), Type.INT_TYPE);
|
||||
v.newarray(type.getElementType());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1308,7 +1327,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
if (!(descriptor instanceof ClassDescriptor)) {
|
||||
throw new UnsupportedOperationException("don't know how to handle non-class types in as/as?");
|
||||
}
|
||||
Type type = typeMapper.jvmType((ClassDescriptor) descriptor, OwnerKind.INTERFACE);
|
||||
Type type = typeMapper.mapType(jetType, OwnerKind.INTERFACE);
|
||||
gen(expression.getLeft(), OBJECT_TYPE);
|
||||
if (opToken == JetTokens.AS_SAFE) {
|
||||
generateInstanceOf(new Runnable() {
|
||||
@@ -1380,7 +1399,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
if (leaveExpressionOnStack) {
|
||||
v.dup();
|
||||
}
|
||||
Type type = typeMapper.jvmType((ClassDescriptor) descriptor, OwnerKind.INTERFACE);
|
||||
Type type = typeMapper.mapType(jetType, OwnerKind.INTERFACE);
|
||||
v.instanceOf(type);
|
||||
}
|
||||
}
|
||||
@@ -1487,5 +1506,11 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
}
|
||||
|
||||
private static class CompilationException extends RuntimeException {
|
||||
private CompilationException() {
|
||||
}
|
||||
|
||||
private CompilationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.jetbrains.jet.codegen;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import jet.typeinfo.TypeInfo;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -118,6 +119,10 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
public Type mapType(final JetType jetType) {
|
||||
return mapType(jetType, OwnerKind.INTERFACE);
|
||||
}
|
||||
|
||||
public Type mapType(final JetType jetType, OwnerKind kind) {
|
||||
if (jetType.equals(JetStandardClasses.getUnitType()) || jetType.equals(JetStandardClasses.getNothingType())) {
|
||||
return Type.VOID_TYPE;
|
||||
}
|
||||
@@ -191,7 +196,7 @@ public class JetTypeMapper {
|
||||
if (declaration instanceof PsiClass) {
|
||||
return psiClassType((PsiClass) declaration);
|
||||
}
|
||||
return Type.getObjectType(jvmNameForInterface((ClassDescriptor) descriptor));
|
||||
return Type.getObjectType(jetJvmName((ClassDescriptor) descriptor, kind));
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Unknown type " + jetType);
|
||||
|
||||
@@ -360,6 +360,13 @@ public class NamespaceGenTest extends CodegenTestCase {
|
||||
assertEquals(10, data[0]);
|
||||
}
|
||||
|
||||
public void testArrayNew() throws Exception {
|
||||
loadText("fun foo() = new Array<Int>(4)");
|
||||
final Method main = generateFunction();
|
||||
int[] result = (int[]) main.invoke(null);
|
||||
assertEquals(4, result.length);
|
||||
}
|
||||
|
||||
public void testIntRange() throws Exception {
|
||||
loadText("fun foo() = 1..10");
|
||||
final Method main = generateFunction();
|
||||
|
||||
Reference in New Issue
Block a user