refactor visitCallExpression() in preparation for supporting calls in pattern matching

This commit is contained in:
Dmitry Jemerov
2011-07-06 16:02:25 +02:00
parent 7adb2d1381
commit d824997dcf
@@ -742,99 +742,106 @@ public class ExpressionCodegen extends JetVisitor {
@Override @Override
public void visitCallExpression(JetCallExpression expression) { public void visitCallExpression(JetCallExpression expression) {
JetExpression callee = expression.getCalleeExpression(); final JetExpression callee = expression.getCalleeExpression();
DeclarationDescriptor funDescriptor = resolveCalleeDescriptor(expression);
if (callee instanceof JetSimpleNameExpression) { if (funDescriptor instanceof ConstructorDescriptor) {
DeclarationDescriptor funDescriptor = bindingContext.resolveReferenceExpression((JetSimpleNameExpression) callee); generateConstructorCall(expression, (JetSimpleNameExpression) callee);
if (funDescriptor == null) { }
throw new CompilationException("Cannot resolve: " + callee.getText()); else if (funDescriptor instanceof FunctionDescriptor) {
final DeclarationDescriptor functionParent = funDescriptor.getContainingDeclaration();
if (isNumberPrimitive(functionParent)) {
if (funDescriptor.getName().equals("inv")) {
final StackValue value = myStack.pop(); // HACK we rely on the dot reference handler to put it on the stack
final Type asmType = expressionType(expression);
value.put(asmType, v);
generateInv(asmType);
return;
}
} }
if (funDescriptor instanceof ConstructorDescriptor) { final FunctionDescriptor fd = (FunctionDescriptor) funDescriptor;
generateConstructorCall(expression, (JetSimpleNameExpression) callee); PsiElement declarationPsiElement = resolveCalleeToDeclaration(funDescriptor);
CallableMethod callableMethod;
if (declarationPsiElement instanceof PsiMethod) {
final PsiMethod psiMethod = (PsiMethod) declarationPsiElement;
callableMethod = JetTypeMapper.mapToCallableMethod(psiMethod);
if (!psiMethod.hasModifierProperty(PsiModifier.STATIC)) {
ensureReceiverOnStack(expression, null);
setOwnerFromCall(callableMethod, expression);
}
} }
else if (funDescriptor instanceof FunctionDescriptor) { else if (declarationPsiElement instanceof JetNamedFunction) {
final DeclarationDescriptor functionParent = funDescriptor.getContainingDeclaration(); final JetNamedFunction jetFunction = (JetNamedFunction) declarationPsiElement;
if (isNumberPrimitive(functionParent)) { callableMethod = typeMapper.mapToCallableMethod(jetFunction);
if (funDescriptor.getName().equals("inv")) {
final StackValue value = myStack.pop(); // HACK we rely on the dot reference handler to put it on the stack
final Type asmType = expressionType(expression);
value.put(asmType, v);
generateInv(asmType);
return;
}
}
if (functionParent instanceof NamespaceDescriptorImpl) {
PsiElement declarationPsiElement = bindingContext.getDeclarationPsiElement(funDescriptor); if (jetFunction.getReceiverTypeRef() != null) {
final FunctionDescriptor fd = (FunctionDescriptor) funDescriptor;
if (declarationPsiElement == null && isClass(functionParent, "String")) {
final Project project = expression.getProject();
PsiClass jlString = JavaPsiFacade.getInstance(project).findClass("java.lang.String",
ProjectScope.getAllScope(project));
// TODO better overload mapping
final PsiMethod[] methods = jlString.findMethodsByName(funDescriptor.getName(), false);
final int arity = fd.getValueParameters().size();
for (PsiMethod method : methods) {
if (method.getParameterList().getParametersCount() == arity) {
declarationPsiElement = method;
}
}
}
if (declarationPsiElement == null) {
throw new UnsupportedOperationException("couldn't find declaration for " + funDescriptor);
}
CallableMethod callableMethod;
if (declarationPsiElement instanceof PsiMethod) {
final PsiMethod psiMethod = (PsiMethod) declarationPsiElement;
callableMethod = JetTypeMapper.mapToCallableMethod(psiMethod);
if (!psiMethod.hasModifierProperty(PsiModifier.STATIC)) {
ensureReceiverOnStack(expression, null);
setOwnerFromCall(callableMethod, expression);
}
}
else if (declarationPsiElement instanceof JetNamedFunction) {
final JetNamedFunction jetFunction = (JetNamedFunction) declarationPsiElement;
callableMethod = typeMapper.mapToCallableMethod(jetFunction);
if (functionParent instanceof NamespaceDescriptorImpl) {
if (jetFunction.getReceiverTypeRef() != null) {
ensureReceiverOnStack(expression, null);
}
}
else if (functionParent instanceof ClassDescriptor) {
ensureReceiverOnStack(expression, (ClassDescriptor) functionParent);
}
}
else {
gen(callee, Type.getObjectType(ClosureCodegen.getInternalClassName(fd)));
boolean isExtensionFunction = fd.getReceiverType() != null;
if (isExtensionFunction) {
ensureReceiverOnStack(expression, null); ensureReceiverOnStack(expression, null);
} }
callableMethod = ClosureCodegen.asCallableMethod(fd);
} }
else if (functionParent instanceof ClassDescriptor) {
invokeMethodWithArguments(callableMethod, expression); ensureReceiverOnStack(expression, (ClassDescriptor) functionParent);
final Type callReturnType = callableMethod.getSignature().getReturnType();
if (callReturnType != Type.VOID_TYPE) {
final Type retType = typeMapper.mapType(fd.getReturnType());
StackValue.onStack(callReturnType).upcast(retType, v);
myStack.push(StackValue.onStack(retType));
} }
} }
else { else {
throw new CompilationException(); gen(callee, Type.getObjectType(ClosureCodegen.getInternalClassName(fd)));
boolean isExtensionFunction = fd.getReceiverType() != null;
if (isExtensionFunction) {
ensureReceiverOnStack(expression, null);
}
callableMethod = ClosureCodegen.asCallableMethod(fd);
}
invokeMethodWithArguments(callableMethod, expression);
final Type callReturnType = callableMethod.getSignature().getReturnType();
if (callReturnType != Type.VOID_TYPE) {
final Type retType = typeMapper.mapType(fd.getReturnType());
StackValue.onStack(callReturnType).upcast(retType, v);
myStack.push(StackValue.onStack(retType));
} }
} }
else { else {
throw new UnsupportedOperationException("Don't know how to generate a call"); throw new UnsupportedOperationException("unknown type of callee descriptor: " + funDescriptor);
} }
} }
private PsiElement resolveCalleeToDeclaration(DeclarationDescriptor funDescriptor) {
PsiElement declarationPsiElement = bindingContext.getDeclarationPsiElement(funDescriptor);
if (declarationPsiElement == null && isClass(funDescriptor.getContainingDeclaration(), "String")) {
final Project project = state.getProject();
PsiClass jlString = JavaPsiFacade.getInstance(project).findClass("java.lang.String",
ProjectScope.getAllScope(project));
// TODO better overload mapping
final PsiMethod[] methods = jlString.findMethodsByName(funDescriptor.getName(), false);
final int arity = ((FunctionDescriptor) funDescriptor).getValueParameters().size();
for (PsiMethod method : methods) {
if (method.getParameterList().getParametersCount() == arity) {
declarationPsiElement = method;
}
}
}
if (declarationPsiElement == null) {
throw new UnsupportedOperationException("couldn't find declaration for " + funDescriptor);
}
return declarationPsiElement;
}
private DeclarationDescriptor resolveCalleeDescriptor(JetCallExpression call) {
JetExpression callee = call.getCalleeExpression();
if (!(callee instanceof JetSimpleNameExpression)) {
throw new UnsupportedOperationException("Don't know how to generate a call to " + callee);
}
DeclarationDescriptor funDescriptor = bindingContext.resolveReferenceExpression((JetSimpleNameExpression) callee);
if (funDescriptor == null) {
throw new CompilationException("Cannot resolve: " + callee.getText());
}
return funDescriptor;
}
private void invokeMethodWithArguments(CallableMethod callableMethod, JetCallExpression expression) { private void invokeMethodWithArguments(CallableMethod callableMethod, JetCallExpression expression) {
pushMethodArguments(expression, callableMethod.getValueParameterTypes()); pushMethodArguments(expression, callableMethod.getValueParameterTypes());
if (callableMethod.acceptsTypeArguments()) { if (callableMethod.acceptsTypeArguments()) {