try / finally

This commit is contained in:
Dmitry Jemerov
2011-05-19 18:40:42 +02:00
parent 5bbb99e247
commit d7a2cb07f3
4 changed files with 66 additions and 16 deletions
@@ -52,6 +52,8 @@ public class ExpressionCodegen extends JetVisitor {
private static final Type OBJECT_TYPE = Type.getType(Object.class);
private static final Type ITERATOR_TYPE = Type.getType(Iterator.class);
private static final Type THROWABLE_TYPE = Type.getType(Throwable.class);
private static final Type RANGE_TYPE = Type.getType(Range.class);
private static final Type INT_RANGE_TYPE = Type.getType(IntRange.class);
private static final Type JET_OBJECT_TYPE = Type.getType(JetObject.class);
@@ -1246,14 +1248,15 @@ public class ExpressionCodegen extends JetVisitor {
@Override
public void visitTryExpression(JetTryExpression expression) {
if (expression.getFinallyBlock() != null) {
throw new UnsupportedOperationException("finally block in try/catch not yet supported");
}
Label tryStart = new Label();
v.mark(tryStart);
gen(expression.getTryBlock(), Type.VOID_TYPE);
Label tryEnd = new Label();
v.mark(tryEnd);
JetFinallySection finallyBlock = expression.getFinallyBlock();
if (finallyBlock != null) {
gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE);
}
Label end = new Label();
v.goTo(end); // TODO don't generate goto if there's no code following try/catch
for (JetCatchClause clause : expression.getCatchClauses()) {
@@ -1272,6 +1275,22 @@ public class ExpressionCodegen extends JetVisitor {
myMap.leave(descriptor);
v.visitTryCatchBlock(tryStart, tryEnd, clauseStart, descriptorType.getInternalName());
}
if (finallyBlock != null) {
Label finallyStart = new Label();
v.mark(finallyStart);
int index = myMap.enterTemp();
v.store(index, THROWABLE_TYPE);
gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE);
v.load(index, THROWABLE_TYPE);
v.athrow();
myMap.leaveTemp();
v.visitTryCatchBlock(tryStart, tryEnd, finallyStart, null);
}
v.mark(end);
}
@@ -1,11 +1,10 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@@ -81,17 +80,16 @@ public class FunctionCodegen {
}
else {
bodyExpression.accept(codegen);
generateReturn(mv, bodyExpression, codegen);
generateReturn(mv, bodyExpression, codegen, jvmSignature);
}
mv.visitMaxs(0, 0);
mv.visitEnd();
}
}
private void generateReturn(MethodVisitor mv, JetExpression bodyExpression, ExpressionCodegen codegen) {
private void generateReturn(MethodVisitor mv, JetExpression bodyExpression, ExpressionCodegen codegen, Method jvmSignature) {
if (!endsWithReturn(bodyExpression)) {
final JetType expressionType = bindingContext.getExpressionType(bodyExpression);
if (expressionType == null || expressionType.equals(JetStandardClasses.getUnitType())) {
if (jvmSignature.getReturnType() == Type.VOID_TYPE) {
mv.visitInsn(Opcodes.RETURN);
}
else {
@@ -0,0 +1,9 @@
fun f(sb: StringBuilder, s: String): Unit {
try {
sb.append("foo");
sb.append(Integer.parseInt(s));
}
finally {
sb.append("bar");
}
}
@@ -9,8 +9,13 @@ import java.util.List;
* @author yole
*/
public class ControlStructuresTest extends CodegenTestCase {
@Override
protected String getPrefix() {
return "controlStructures";
}
public void testIf() throws Exception {
loadFile("controlStructures/if.jet");
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
@@ -19,7 +24,7 @@ public class ControlStructuresTest extends CodegenTestCase {
}
public void testSingleBranchIf() throws Exception {
loadFile("controlStructures/singleBranchIf.jet");
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
@@ -49,7 +54,7 @@ public class ControlStructuresTest extends CodegenTestCase {
}
public void testContinue() throws Exception {
loadFile("controlStructures/continue.jet");
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(3, main.invoke(null, 4));
@@ -57,7 +62,7 @@ public class ControlStructuresTest extends CodegenTestCase {
}
public void testIfNoElse() throws Exception {
loadFile("controlStructures/ifNoElse.jet");
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(5, main.invoke(null, 5, true));
@@ -72,7 +77,7 @@ public class ControlStructuresTest extends CodegenTestCase {
}
public void testFor() throws Exception {
loadFile("controlStructures/for.jet");
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
List<String> args = Arrays.asList("IntelliJ", " ", "IDEA");
@@ -80,7 +85,7 @@ public class ControlStructuresTest extends CodegenTestCase {
}
public void testForInArray() throws Exception {
loadFile("controlStructures/forInArray.jet");
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
String[] args = new String[] { "IntelliJ", " ", "IDEA" };
@@ -102,10 +107,29 @@ public class ControlStructuresTest extends CodegenTestCase {
}
public void testTryCatch() throws Exception {
loadFile("controlStructures/tryCatch.jet");
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals("no message", main.invoke(null, "0"));
assertEquals("For input string: \"a\"", main.invoke(null, "a"));
}
public void testTryFinally() throws Exception {
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
StringBuilder sb = new StringBuilder();
main.invoke(null, sb, "9");
assertEquals("foo9bar", sb.toString());
sb = new StringBuilder();
boolean caught = false;
try {
main.invoke(null, sb, "x");
}
catch(InvocationTargetException e) {
caught = e.getTargetException() instanceof NumberFormatException;
}
assertTrue(caught);
assertEquals("foobar", sb.toString());
}
}