generate Java constructors

This commit is contained in:
Dmitry Jemerov
2011-04-14 19:02:15 +02:00
parent e9f9236303
commit dbbde029ad
4 changed files with 56 additions and 17 deletions
@@ -277,7 +277,7 @@ public class ExpressionCodegen extends JetVisitor {
PsiField psiField = (PsiField) declaration; PsiField psiField = (PsiField) declaration;
if (psiField.hasModifierProperty(PsiModifier.STATIC)) { if (psiField.hasModifierProperty(PsiModifier.STATIC)) {
v.visitFieldInsn(Opcodes.GETSTATIC, v.visitFieldInsn(Opcodes.GETSTATIC,
jvmName(psiField.getContainingClass()), JetTypeMapper.jvmName(psiField.getContainingClass()),
psiField.getName(), psiField.getName(),
psiTypeToAsm(psiField.getType()).getDescriptor()); psiTypeToAsm(psiField.getType()).getDescriptor());
} }
@@ -342,23 +342,17 @@ public class ExpressionCodegen extends JetVisitor {
PsiElement declarationPsiElement = bindingContext.getDeclarationPsiElement(funDescriptor); PsiElement declarationPsiElement = bindingContext.getDeclarationPsiElement(funDescriptor);
if (declarationPsiElement instanceof PsiMethod) { if (declarationPsiElement instanceof PsiMethod) {
PsiMethod method = (PsiMethod) declarationPsiElement; PsiMethod method = (PsiMethod) declarationPsiElement;
PsiParameter[] parameters = method.getParameterList().getParameters(); pushMethodArguments(expression, method);
List<JetArgument> 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()));
}
if (method.hasModifierProperty(PsiModifier.STATIC)) { if (method.hasModifierProperty(PsiModifier.STATIC)) {
v.visitMethodInsn(Opcodes.INVOKESTATIC, v.visitMethodInsn(Opcodes.INVOKESTATIC,
jvmName(method.getContainingClass()), JetTypeMapper.jvmName(method.getContainingClass()),
method.getName(), method.getName(),
getMethodDescriptor(method)); getMethodDescriptor(method));
} }
else { else {
v.visitMethodInsn(Opcodes.INVOKEVIRTUAL, v.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
jvmName(method.getContainingClass()), JetTypeMapper.jvmName(method.getContainingClass()),
method.getName(), method.getName(),
getMethodDescriptor(method)); getMethodDescriptor(method));
} }
@@ -380,8 +374,14 @@ public class ExpressionCodegen extends JetVisitor {
} }
} }
private static String jvmName(PsiClass containingClass) { private void pushMethodArguments(JetCall expression, PsiMethod method) {
return containingClass.getQualifiedName().replace(".", "/"); PsiParameter[] parameters = method.getParameterList().getParameters();
List<JetArgument> 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) { private void unbox(PsiType type) {
@@ -396,7 +396,7 @@ public class ExpressionCodegen extends JetVisitor {
} }
private static String getMethodDescriptor(PsiMethod method) { 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(); PsiParameter[] parameters = method.getParameterList().getParameters();
Type[] parameterTypes = new Type[parameters.length]; Type[] parameterTypes = new Type[parameters.length];
for (int i = 0; i < parameters.length; i++) { for (int i = 0; i < parameters.length; i++) {
@@ -449,9 +449,9 @@ public class ExpressionCodegen extends JetVisitor {
if (psiClass == null) { if (psiClass == null) {
throw new UnsupportedOperationException("unresolved PsiClassType: " + type); 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 @Override
@@ -726,6 +726,7 @@ public class ExpressionCodegen extends JetVisitor {
else { else {
int oldStackSize = myStack.size(); int oldStackSize = myStack.size();
gen(expression.getBaseExpression(), asmType); gen(expression.getBaseExpression(), asmType);
generateIncrement(op, asmType, expression.getBaseExpression());
myStack.push(StackValue.onStack(asmType)); myStack.push(StackValue.onStack(asmType));
assert myStack.size() == oldStackSize+1; 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), "<init>", 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 { private static class CompilationException extends RuntimeException {
} }
} }
@@ -24,7 +24,7 @@ public class FunctionCodegen {
this.v = v; this.v = v;
this.bindingContext = bindingContext; this.bindingContext = bindingContext;
this.standardLibrary = standardLibrary; this.standardLibrary = standardLibrary;
typeMapper = new JetTypeMapper(standardLibrary); typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
} }
public void gen(JetFunction f, JetNamespace owner) { public void gen(JetFunction f, JetNamespace owner) {
@@ -1,5 +1,8 @@
package org.jetbrains.jet.codegen; 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.jetbrains.jet.lang.types.*;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
@@ -8,9 +11,19 @@ import org.objectweb.asm.Type;
*/ */
public class JetTypeMapper { public class JetTypeMapper {
private final JetStandardLibrary standardLibrary; private final JetStandardLibrary standardLibrary;
private final BindingContext bindingContext;
public JetTypeMapper(JetStandardLibrary standardLibrary) { public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) {
this.standardLibrary = standardLibrary; 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) { public Type mapType(final JetType jetType) {
@@ -83,6 +96,10 @@ public class JetTypeMapper {
} }
if (descriptor instanceof ClassDescriptor) { 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)); return Type.getObjectType(CodeGenUtil.getInternalInterfaceName((ClassDescriptor) descriptor));
} }
@@ -494,6 +494,7 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
public void testJavaConstructor() throws Exception { public void testJavaConstructor() throws Exception {
loadText("fun foo(): StringBuilder = new StringBuilder()"); loadText("fun foo(): StringBuilder = new StringBuilder()");
System.out.println(generateToText());
final Method main = generateFunction(); final Method main = generateFunction();
final Object result = main.invoke(null); final Object result = main.invoke(null);
assertTrue(result instanceof StringBuilder); assertTrue(result instanceof StringBuilder);