diff --git a/idea/src/org/jetbrains/jet/codegen/CallableMethod.java b/idea/src/org/jetbrains/jet/codegen/CallableMethod.java new file mode 100644 index 00000000000..a0381403c49 --- /dev/null +++ b/idea/src/org/jetbrains/jet/codegen/CallableMethod.java @@ -0,0 +1,30 @@ +package org.jetbrains.jet.codegen; + +import org.objectweb.asm.commons.Method; + +/** + * @author yole + */ +public class CallableMethod { + private final String owner; + private final Method descriptor; + private final int invokeOpcode; + + public CallableMethod(String owner, Method descriptor, int invokeOpcode) { + this.owner = owner; + this.descriptor = descriptor; + this.invokeOpcode = invokeOpcode; + } + + public String getOwner() { + return owner; + } + + public Method getDescriptor() { + return descriptor; + } + + public int getInvokeOpcode() { + return invokeOpcode; + } +} diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 10de4a52cce..0c4d9a4ee1a 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -17,7 +17,6 @@ import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.lexer.JetTokens; -import org.jetbrains.jet.resolve.DescriptorRenderer; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; @@ -785,30 +784,21 @@ public class ExpressionCodegen extends JetVisitor { } else if (declarationPsiElement instanceof JetNamedFunction) { final JetNamedFunction jetFunction = (JetNamedFunction) declarationPsiElement; - methodDescriptor = typeMapper.mapSignature(jetFunction); + CallableMethod callableMethod = typeMapper.mapToCallableMethod(jetFunction); + if (functionParent instanceof NamespaceDescriptorImpl) { if (jetFunction.getReceiverTypeRef() != null) { ensureReceiverOnStack(expression, null); } - pushMethodArguments(expression, methodDescriptor); - pushTypeArguments(expression); - final String owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(functionParent)); - v.invokestatic(owner, methodDescriptor.getName(), methodDescriptor.getDescriptor()); } else if (functionParent instanceof ClassDescriptor) { - ClassDescriptor containingClass = (ClassDescriptor) functionParent; - ensureReceiverOnStack(expression, containingClass); - pushMethodArguments(expression, methodDescriptor); - pushTypeArguments(expression); - final String owner = typeMapper.jvmName(containingClass, OwnerKind.INTERFACE); - int opcode = typeMapper.isInterface(containingClass, OwnerKind.INTERFACE) - ? Opcodes.INVOKEINTERFACE - : Opcodes.INVOKEVIRTUAL; - v.visitMethodInsn(opcode,owner, methodDescriptor.getName(), methodDescriptor.getDescriptor()); - } - else { - throw new UnsupportedOperationException("don't know how to generate call to " + declarationPsiElement); + ensureReceiverOnStack(expression, (ClassDescriptor) functionParent); } + + pushMethodArguments(expression, callableMethod.getDescriptor()); + pushTypeArguments(expression); + invokeCallableMethod(callableMethod); + methodDescriptor = callableMethod.getDescriptor(); } else { gen(callee, Type.getObjectType(ClosureCodegen.getInternalClassName(fd))); @@ -840,6 +830,11 @@ public class ExpressionCodegen extends JetVisitor { } } + private void invokeCallableMethod(CallableMethod callableMethod) { + v.visitMethodInsn(callableMethod.getInvokeOpcode(), callableMethod.getOwner(), + callableMethod.getDescriptor().getName(), callableMethod.getDescriptor().getDescriptor()); + } + private Method generateJavaMethodCall(JetCallExpression expression, PsiMethod psiMethod) { final PsiClass containingClass = psiMethod.getContainingClass(); String owner = JetTypeMapper.jvmName(containingClass); diff --git a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 6af99e1fcd9..c62c780460a 100644 --- a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -298,6 +298,30 @@ public class JetTypeMapper { return new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()])); } + public CallableMethod mapToCallableMethod(JetNamedFunction f) { + final FunctionDescriptor functionDescriptor = bindingContext.getFunctionDescriptor(f); + final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration(); + Method descriptor = mapSignature(f); + String owner; + int invokeOpcode; + if (functionParent instanceof NamespaceDescriptor) { + owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(functionParent)); + invokeOpcode = Opcodes.INVOKESTATIC; + } + else if (functionParent instanceof ClassDescriptor) { + ClassDescriptor containingClass = (ClassDescriptor) functionParent; + owner = jvmName(containingClass, OwnerKind.INTERFACE); + invokeOpcode = isInterface(containingClass, OwnerKind.INTERFACE) + ? Opcodes.INVOKEINTERFACE + : Opcodes.INVOKEVIRTUAL; + } + else { + throw new UnsupportedOperationException("unknown function parent"); + } + + return new CallableMethod(owner, descriptor, invokeOpcode); + } + public Method mapSignature(String name, FunctionDescriptor f) { final JetType receiverType = f.getReceiverType(); final List parameters = f.getValueParameters();