diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index fca4a8d2f4f..26ca8a9d624 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -277,7 +277,7 @@ public class ExpressionCodegen extends JetVisitor { PsiField psiField = (PsiField) declaration; if (psiField.hasModifierProperty(PsiModifier.STATIC)) { v.visitFieldInsn(Opcodes.GETSTATIC, - jvmName(psiField.getContainingClass()), + JetTypeMapper.jvmName(psiField.getContainingClass()), psiField.getName(), psiTypeToAsm(psiField.getType()).getDescriptor()); } @@ -342,23 +342,17 @@ public class ExpressionCodegen extends JetVisitor { PsiElement declarationPsiElement = bindingContext.getDeclarationPsiElement(funDescriptor); if (declarationPsiElement instanceof PsiMethod) { PsiMethod method = (PsiMethod) declarationPsiElement; - PsiParameter[] parameters = method.getParameterList().getParameters(); - - List args = expression.getValueArguments(); - for (int i = 0, argsSize = args.size(); i < argsSize; i++) { - JetArgument arg = args.get(i); - gen(arg.getArgumentExpression(), psiTypeToAsm(parameters[i].getType())); - } + pushMethodArguments(expression, method); if (method.hasModifierProperty(PsiModifier.STATIC)) { v.visitMethodInsn(Opcodes.INVOKESTATIC, - jvmName(method.getContainingClass()), + JetTypeMapper.jvmName(method.getContainingClass()), method.getName(), getMethodDescriptor(method)); } else { v.visitMethodInsn(Opcodes.INVOKEVIRTUAL, - jvmName(method.getContainingClass()), + JetTypeMapper.jvmName(method.getContainingClass()), method.getName(), getMethodDescriptor(method)); } @@ -380,8 +374,14 @@ public class ExpressionCodegen extends JetVisitor { } } - private static String jvmName(PsiClass containingClass) { - return containingClass.getQualifiedName().replace(".", "/"); + private void pushMethodArguments(JetCall expression, PsiMethod method) { + PsiParameter[] parameters = method.getParameterList().getParameters(); + + List args = expression.getValueArguments(); + for (int i = 0, argsSize = args.size(); i < argsSize; i++) { + JetArgument arg = args.get(i); + gen(arg.getArgumentExpression(), psiTypeToAsm(parameters[i].getType())); + } } private void unbox(PsiType type) { @@ -396,7 +396,7 @@ public class ExpressionCodegen extends JetVisitor { } private static String getMethodDescriptor(PsiMethod method) { - Type returnType = psiTypeToAsm(method.getReturnType()); + Type returnType = method.isConstructor() ? Type.VOID_TYPE : psiTypeToAsm(method.getReturnType()); PsiParameter[] parameters = method.getParameterList().getParameters(); Type[] parameterTypes = new Type[parameters.length]; for (int i = 0; i < parameters.length; i++) { @@ -449,9 +449,9 @@ public class ExpressionCodegen extends JetVisitor { if (psiClass == null) { throw new UnsupportedOperationException("unresolved PsiClassType: " + type); } - return Type.getType("L" + jvmName(psiClass) + ";"); + return JetTypeMapper.psiClassType(psiClass); } - throw new UnsupportedOperationException("don't know how to map type " + type + " to ASM"); + throw new UnsupportedOperationException("don't know how to map type " + type + " to ASM"); } @Override @@ -726,6 +726,7 @@ public class ExpressionCodegen extends JetVisitor { else { int oldStackSize = myStack.size(); gen(expression.getBaseExpression(), asmType); + generateIncrement(op, asmType, expression.getBaseExpression()); myStack.push(StackValue.onStack(asmType)); assert myStack.size() == oldStackSize+1; } @@ -810,6 +811,26 @@ public class ExpressionCodegen extends JetVisitor { } } + @Override + public void visitNewExpression(JetNewExpression expression) { + final JetUserType constructorType = (JetUserType) expression.getTypeReference().getTypeElement(); + final JetSimpleNameExpression constructorReference = constructorType.getReferenceExpression(); + final PsiElement declaration = bindingContext.getDeclarationPsiElement(bindingContext.resolveReferenceExpression(constructorReference)); + if (declaration instanceof PsiMethod) { + final PsiMethod constructor = (PsiMethod) declaration; + PsiClass javaClass = constructor.getContainingClass(); + Type type = JetTypeMapper.psiClassType(javaClass); + v.anew(type); + v.dup(); + pushMethodArguments(expression, constructor); + v.invokespecial(JetTypeMapper.jvmName(javaClass), "", getMethodDescriptor(constructor)); + myStack.push(StackValue.onStack(type)); + return; + } + + throw new UnsupportedOperationException("don't know how to generate this new expression"); + } + private static class CompilationException extends RuntimeException { } } diff --git a/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 150c6ab40e9..89433abbcb5 100644 --- a/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -24,7 +24,7 @@ public class FunctionCodegen { this.v = v; this.bindingContext = bindingContext; this.standardLibrary = standardLibrary; - typeMapper = new JetTypeMapper(standardLibrary); + typeMapper = new JetTypeMapper(standardLibrary, bindingContext); } public void gen(JetFunction f, JetNamespace owner) { diff --git a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 588d4b85ed8..adebe2cd025 100644 --- a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -1,5 +1,8 @@ package org.jetbrains.jet.codegen; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.types.*; import org.objectweb.asm.Type; @@ -8,9 +11,19 @@ import org.objectweb.asm.Type; */ public class JetTypeMapper { private final JetStandardLibrary standardLibrary; + private final BindingContext bindingContext; - public JetTypeMapper(JetStandardLibrary standardLibrary) { + public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) { this.standardLibrary = standardLibrary; + this.bindingContext = bindingContext; + } + + static String jvmName(PsiClass psiClass) { + return psiClass.getQualifiedName().replace(".", "/"); + } + + static Type psiClassType(PsiClass psiClass) { + return Type.getType("L" + jvmName(psiClass) + ";"); } public Type mapType(final JetType jetType) { @@ -83,6 +96,10 @@ public class JetTypeMapper { } if (descriptor instanceof ClassDescriptor) { + final PsiElement declaration = bindingContext.getDeclarationPsiElement(descriptor); + if (declaration instanceof PsiClass) { + return psiClassType((PsiClass) declaration); + } return Type.getObjectType(CodeGenUtil.getInternalInterfaceName((ClassDescriptor) descriptor)); } diff --git a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java index 97dd45b4ae2..14052438f75 100644 --- a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java @@ -494,6 +494,7 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase { public void testJavaConstructor() throws Exception { loadText("fun foo(): StringBuilder = new StringBuilder()"); + System.out.println(generateToText()); final Method main = generateFunction(); final Object result = main.invoke(null); assertTrue(result instanceof StringBuilder);