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;
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<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()));
}
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<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) {
@@ -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), "<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 {
}
}
@@ -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) {
@@ -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));
}
@@ -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);