try / finally
This commit is contained in:
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user