generate Java constructors
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user