diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 7a928630a67..605cd5a7923 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -4,6 +4,7 @@ import gnu.trove.TObjectIntHashMap; import org.jetbrains.jet.lang.psi.*; 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; @@ -230,6 +231,18 @@ public class ExpressionCodegen extends JetVisitor { } + @Override + public void visitReturnExpression(JetReturnExpression expression) { + final JetExpression returnedExpression = expression.getReturnedExpression(); + if (returnedExpression != null) { + returnedExpression.accept(this); + v.visitInsn(Opcodes.ARETURN); + } + else { + v.visitInsn(Opcodes.RETURN); + } + } + private Type getType(JetProperty var) { return InstructionAdapter.OBJECT_TYPE; // TODO: } diff --git a/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 2877de3c99c..4950496bd3c 100644 --- a/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -25,14 +25,33 @@ public class FunctionCodegen { for (int i = 0; i < parameters.size(); i++) { parameterTypes[i] = mapTypeReference(parameters.get(i).getTypeReference()); } - Method method = new Method(f.getName(), Type.VOID_TYPE, parameterTypes); + final JetTypeReference returnTypeRef = f.getReturnTypeRef(); + Type returnType = returnTypeRef == null ? Type.VOID_TYPE : mapTypeReference(returnTypeRef); + Method method = new Method(f.getName(), returnType, parameterTypes); final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, method.getName(), method.getDescriptor(), null, null); mv.visitCode(); - mv.visitInsn(Opcodes.RETURN); + final JetExpression bodyExpression = f.getBodyExpression(); + bodyExpression.accept(new ExpressionCodegen(mv)); + if (needReturn(bodyExpression)) { + mv.visitInsn(Opcodes.RETURN); + } + mv.visitMaxs(0, 0); mv.visitEnd(); } + private boolean needReturn(JetExpression bodyExpression) { + if (bodyExpression instanceof JetBlockExpression) { + final List statements = ((JetBlockExpression) bodyExpression).getStatements(); + if (statements.size() == 0) { + return true; + } + final JetElement jetElement = statements.get(statements.size() - 1); + return !(jetElement instanceof JetReturnExpression); + } + return false; + } + private Type mapTypeReference(JetTypeReference typeRef) { if (typeRef == null) { throw new UnsupportedOperationException("Cannot evaluate type for parameter with no type ref"); @@ -53,6 +72,9 @@ public class FunctionCodegen { if ("String".equals(referencedName)) { return Type.getType(String.class); } + if ("Int".equals(referencedName)) { + return Type.getType(Integer.class); + } } throw new UnsupportedOperationException("Unknown type " + typeRef); diff --git a/idea/testData/codegen/returnOne.jet b/idea/testData/codegen/returnOne.jet new file mode 100644 index 00000000000..b53ad32899f --- /dev/null +++ b/idea/testData/codegen/returnOne.jet @@ -0,0 +1 @@ +fun f() : Int { return 42; } diff --git a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java index 52ec8e0378d..5f6e5c1606b 100644 --- a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java @@ -25,12 +25,25 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase { System.out.println(text); final Class aClass = generateToClass(namespace, codegen); - final Method[] methods = aClass.getMethods(); - final Method main = methods[0]; + final Method main = firstMethod(aClass); Object[] args = new Object[] { new String[0] }; main.invoke(null, args); } + public void testReturnOne() throws Exception { + myFixture.configureByFile(JetParsingTest.getTestDataDir() + "/codegen/returnOne.jet"); + JetFile jetFile = (JetFile) myFixture.getFile(); + JetNamespace namespace = jetFile.getRootNamespace(); + NamespaceCodegen codegen = new NamespaceCodegen(); + final String text = generateToText(namespace, codegen); + System.out.println(text); + + final Class aClass = generateToClass(namespace, codegen); + final Method main = firstMethod(aClass); + final Object returnValue = main.invoke(null, new Object[0]); + assertEquals(new Integer(42), returnValue); + } + private static String generateToText(JetNamespace namespace, NamespaceCodegen codegen) { StringWriter writer = new StringWriter(); codegen.generate(namespace, new TraceClassVisitor(new PrintWriter(writer))); @@ -46,6 +59,10 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase { return aClass; } + private static Method firstMethod(Class aClass) { + return aClass.getMethods()[0]; + } + private static class MyClassLoader extends ClassLoader { public MyClassLoader(ClassLoader parent) { super(parent);