提交 20520e99 编写于 作者: D Dmitry Jemerov

generate calls to functions in a Jet namespace

上级 91b613e8
......@@ -7,11 +7,13 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.resolve.DescriptorUtil;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import org.objectweb.asm.commons.Method;
import java.util.List;
import java.util.Stack;
......@@ -324,7 +326,8 @@ public class ExpressionCodegen extends JetVisitor {
if (callee instanceof JetSimpleNameExpression) {
DeclarationDescriptor funDescriptor = bindingContext.resolveReferenceExpression((JetSimpleNameExpression) callee);
if (funDescriptor instanceof FunctionDescriptor) {
if (isNumberPrimitive(funDescriptor.getContainingDeclaration())) {
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);
......@@ -333,23 +336,41 @@ public class ExpressionCodegen extends JetVisitor {
return;
}
}
if (expression.getParent() instanceof JetDotQualifiedExpression) {
final JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent();
if (!resolvesToClassOrPackage(parent.getReceiverExpression())) {
// we have a receiver on stack
myStack.pop().put(Type.getObjectType("java/lang/Object"), v);
}
}
PsiElement declarationPsiElement = bindingContext.getDeclarationPsiElement(funDescriptor);
Method methodDescriptor;
if (declarationPsiElement instanceof PsiMethod) {
PsiMethod method = (PsiMethod) declarationPsiElement;
pushMethodArguments(expression, method);
PsiMethod psiMethod = (PsiMethod) declarationPsiElement;
methodDescriptor = getMethodDescriptor(psiMethod);
pushMethodArguments(expression, methodDescriptor);
final boolean isStatic = method.hasModifierProperty(PsiModifier.STATIC);
final boolean isStatic = psiMethod.hasModifierProperty(PsiModifier.STATIC);
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL,
JetTypeMapper.jvmName(method.getContainingClass()),
method.getName(),
getMethodDescriptor(method));
final Type type = psiTypeToAsm(method.getReturnType());
if (type != Type.VOID_TYPE) {
myStack.push(StackValue.onStack(type));
}
JetTypeMapper.jvmName(psiMethod.getContainingClass()),
methodDescriptor.getName(),
methodDescriptor.getDescriptor());
}
else {
throw new UnsupportedOperationException("don't know how to generate call to " + declarationPsiElement);
if (functionParent instanceof NamespaceDescriptor && declarationPsiElement instanceof JetFunction) {
methodDescriptor = typeMapper.mapSignature((JetFunction) declarationPsiElement);
pushMethodArguments(expression, methodDescriptor);
final String owner = NamespaceCodegen.getJVMClassName(DescriptorUtil.getFQName(functionParent));
v.invokestatic(owner, methodDescriptor.getName(), methodDescriptor.getDescriptor());
}
else {
throw new UnsupportedOperationException("don't know how to generate call to " + declarationPsiElement);
}
}
if (methodDescriptor.getReturnType() != Type.VOID_TYPE) {
myStack.push(StackValue.onStack(methodDescriptor.getReturnType()));
}
}
else {
......@@ -361,24 +382,23 @@ public class ExpressionCodegen extends JetVisitor {
}
}
private void pushMethodArguments(JetCall expression, PsiMethod method) {
PsiParameter[] parameters = method.getParameterList().getParameters();
private void pushMethodArguments(JetCall expression, Method method) {
final Type[] argTypes = method.getArgumentTypes();
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()));
gen(arg.getArgumentExpression(), argTypes[i]);
}
}
private static String getMethodDescriptor(PsiMethod method) {
private static Method getMethodDescriptor(PsiMethod method) {
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++) {
parameterTypes[i] = psiTypeToAsm(parameters [i].getType());
}
return Type.getMethodDescriptor(returnType, parameterTypes);
return new Method(method.getName(), Type.getMethodDescriptor(returnType, parameterTypes));
}
private Type expressionType(JetExpression expr) {
......@@ -798,8 +818,9 @@ public class ExpressionCodegen extends JetVisitor {
Type type = JetTypeMapper.psiClassType(javaClass);
v.anew(type);
v.dup();
pushMethodArguments(expression, constructor);
v.invokespecial(JetTypeMapper.jvmName(javaClass), "<init>", getMethodDescriptor(constructor));
final Method constructorDescriptor = getMethodDescriptor(constructor);
pushMethodArguments(expression, constructorDescriptor);
v.invokespecial(JetTypeMapper.jvmName(javaClass), "<init>", constructorDescriptor.getDescriptor());
myStack.push(StackValue.onStack(type));
return;
}
......
......@@ -36,22 +36,7 @@ public class FunctionCodegen {
}
private void gen(JetFunction f) {
final List<JetParameter> parameters = f.getValueParameters();
Type[] parameterTypes = new Type[parameters.size()];
for (int i = 0; i < parameters.size(); i++) {
parameterTypes[i] = typeMapper.mapType(bindingContext.resolveTypeReference(parameters.get(i).getTypeReference()));
}
final JetTypeReference returnTypeRef = f.getReturnTypeRef();
Type returnType;
if (returnTypeRef == null) {
final FunctionDescriptor functionDescriptor = bindingContext.getFunctionDescriptor(f);
final JetType type = functionDescriptor.getUnsubstitutedReturnType();
returnType = typeMapper.mapType(type);
}
else {
returnType = typeMapper.mapType(bindingContext.resolveTypeReference(returnTypeRef));
}
Method method = new Method(f.getName(), returnType, parameterTypes);
Method method = typeMapper.mapSignature(f);
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
method.getName(), method.getDescriptor(), null, null);
mv.visitCode();
......@@ -60,12 +45,13 @@ public class FunctionCodegen {
List<ValueParameterDescriptor> parameDescrs = bindingContext.getFunctionDescriptor(f).getUnsubstitutedValueParameters();
Type[] argTypes = method.getArgumentTypes();
for (int i = 0; i < parameDescrs.size(); i++) {
ValueParameterDescriptor parameter = parameDescrs.get(i);
frameMap.enter(parameter, parameterTypes[i].getSize());
frameMap.enter(parameter, argTypes[i].getSize());
}
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, returnType);
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, method.getReturnType());
bodyExpression.accept(codegen);
generateReturn(mv, bodyExpression, codegen);
mv.visitMaxs(0, 0);
......
......@@ -2,9 +2,15 @@ package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.psi.JetFunction;
import org.jetbrains.jet.lang.psi.JetParameter;
import org.jetbrains.jet.lang.psi.JetTypeReference;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.*;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method;
import java.util.List;
/**
* @author yole
......@@ -105,4 +111,23 @@ public class JetTypeMapper {
throw new UnsupportedOperationException("Unknown type " + jetType);
}
public Method mapSignature(JetFunction f) {
final List<JetParameter> parameters = f.getValueParameters();
Type[] parameterTypes = new Type[parameters.size()];
for (int i = 0; i < parameters.size(); i++) {
parameterTypes[i] = mapType(bindingContext.resolveTypeReference(parameters.get(i).getTypeReference()));
}
final JetTypeReference returnTypeRef = f.getReturnTypeRef();
Type returnType;
if (returnTypeRef == null) {
final FunctionDescriptor functionDescriptor = bindingContext.getFunctionDescriptor(f);
final JetType type = functionDescriptor.getUnsubstitutedReturnType();
returnType = mapType(type);
}
else {
returnType = mapType(bindingContext.resolveTypeReference(returnTypeRef));
}
return new Method(f.getName(), returnType, parameterTypes);
}
}
......@@ -54,6 +54,9 @@ public class NamespaceCodegen {
}
public static String getJVMClassName(String fqName) {
if (fqName.length() == 0) {
return "namespace";
}
return fqName.replace('.', '/') + "/namespace";
}
......
fun f() {
val x = new StringBuilder();
g(x);
return x.toString();
}
fun g(sb: StringBuilder): Unit {
sb.append("foo");
}
......@@ -530,6 +530,13 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
assertEquals(Boolean.FALSE, main.invoke(null, null, "jet"));
}
public void testFunctionCall() throws Exception {
loadFile("functionCall.jet");
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals("foo", main.invoke(null));
}
private void binOpTest(final String text, final Object arg1, final Object arg2, final Object expected) throws Exception {
loadText(text);
System.out.println(generateToText());
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册