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 OBJECT_TYPE = Type.getType(Object.class);
|
||||||
private static final Type ITERATOR_TYPE = Type.getType(Iterator.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 RANGE_TYPE = Type.getType(Range.class);
|
||||||
private static final Type INT_RANGE_TYPE = Type.getType(IntRange.class);
|
private static final Type INT_RANGE_TYPE = Type.getType(IntRange.class);
|
||||||
private static final Type JET_OBJECT_TYPE = Type.getType(JetObject.class);
|
private static final Type JET_OBJECT_TYPE = Type.getType(JetObject.class);
|
||||||
@@ -1246,14 +1248,15 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitTryExpression(JetTryExpression expression) {
|
public void visitTryExpression(JetTryExpression expression) {
|
||||||
if (expression.getFinallyBlock() != null) {
|
|
||||||
throw new UnsupportedOperationException("finally block in try/catch not yet supported");
|
|
||||||
}
|
|
||||||
Label tryStart = new Label();
|
Label tryStart = new Label();
|
||||||
v.mark(tryStart);
|
v.mark(tryStart);
|
||||||
gen(expression.getTryBlock(), Type.VOID_TYPE);
|
gen(expression.getTryBlock(), Type.VOID_TYPE);
|
||||||
Label tryEnd = new Label();
|
Label tryEnd = new Label();
|
||||||
v.mark(tryEnd);
|
v.mark(tryEnd);
|
||||||
|
JetFinallySection finallyBlock = expression.getFinallyBlock();
|
||||||
|
if (finallyBlock != null) {
|
||||||
|
gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE);
|
||||||
|
}
|
||||||
Label end = new Label();
|
Label end = new Label();
|
||||||
v.goTo(end); // TODO don't generate goto if there's no code following try/catch
|
v.goTo(end); // TODO don't generate goto if there's no code following try/catch
|
||||||
for (JetCatchClause clause : expression.getCatchClauses()) {
|
for (JetCatchClause clause : expression.getCatchClauses()) {
|
||||||
@@ -1272,6 +1275,22 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
myMap.leave(descriptor);
|
myMap.leave(descriptor);
|
||||||
v.visitTryCatchBlock(tryStart, tryEnd, clauseStart, descriptorType.getInternalName());
|
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);
|
v.mark(end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
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.DeclarationDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
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.ClassVisitor;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
@@ -81,17 +80,16 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bodyExpression.accept(codegen);
|
bodyExpression.accept(codegen);
|
||||||
generateReturn(mv, bodyExpression, codegen);
|
generateReturn(mv, bodyExpression, codegen, jvmSignature);
|
||||||
}
|
}
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
mv.visitEnd();
|
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)) {
|
if (!endsWithReturn(bodyExpression)) {
|
||||||
final JetType expressionType = bindingContext.getExpressionType(bodyExpression);
|
if (jvmSignature.getReturnType() == Type.VOID_TYPE) {
|
||||||
if (expressionType == null || expressionType.equals(JetStandardClasses.getUnitType())) {
|
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
}
|
}
|
||||||
else {
|
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
|
* @author yole
|
||||||
*/
|
*/
|
||||||
public class ControlStructuresTest extends CodegenTestCase {
|
public class ControlStructuresTest extends CodegenTestCase {
|
||||||
|
@Override
|
||||||
|
protected String getPrefix() {
|
||||||
|
return "controlStructures";
|
||||||
|
}
|
||||||
|
|
||||||
public void testIf() throws Exception {
|
public void testIf() throws Exception {
|
||||||
loadFile("controlStructures/if.jet");
|
loadFile();
|
||||||
|
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
final Method main = generateFunction();
|
final Method main = generateFunction();
|
||||||
@@ -19,7 +24,7 @@ public class ControlStructuresTest extends CodegenTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testSingleBranchIf() throws Exception {
|
public void testSingleBranchIf() throws Exception {
|
||||||
loadFile("controlStructures/singleBranchIf.jet");
|
loadFile();
|
||||||
|
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
final Method main = generateFunction();
|
final Method main = generateFunction();
|
||||||
@@ -49,7 +54,7 @@ public class ControlStructuresTest extends CodegenTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testContinue() throws Exception {
|
public void testContinue() throws Exception {
|
||||||
loadFile("controlStructures/continue.jet");
|
loadFile();
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
final Method main = generateFunction();
|
final Method main = generateFunction();
|
||||||
assertEquals(3, main.invoke(null, 4));
|
assertEquals(3, main.invoke(null, 4));
|
||||||
@@ -57,7 +62,7 @@ public class ControlStructuresTest extends CodegenTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testIfNoElse() throws Exception {
|
public void testIfNoElse() throws Exception {
|
||||||
loadFile("controlStructures/ifNoElse.jet");
|
loadFile();
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
final Method main = generateFunction();
|
final Method main = generateFunction();
|
||||||
assertEquals(5, main.invoke(null, 5, true));
|
assertEquals(5, main.invoke(null, 5, true));
|
||||||
@@ -72,7 +77,7 @@ public class ControlStructuresTest extends CodegenTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testFor() throws Exception {
|
public void testFor() throws Exception {
|
||||||
loadFile("controlStructures/for.jet");
|
loadFile();
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
final Method main = generateFunction();
|
final Method main = generateFunction();
|
||||||
List<String> args = Arrays.asList("IntelliJ", " ", "IDEA");
|
List<String> args = Arrays.asList("IntelliJ", " ", "IDEA");
|
||||||
@@ -80,7 +85,7 @@ public class ControlStructuresTest extends CodegenTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testForInArray() throws Exception {
|
public void testForInArray() throws Exception {
|
||||||
loadFile("controlStructures/forInArray.jet");
|
loadFile();
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
final Method main = generateFunction();
|
final Method main = generateFunction();
|
||||||
String[] args = new String[] { "IntelliJ", " ", "IDEA" };
|
String[] args = new String[] { "IntelliJ", " ", "IDEA" };
|
||||||
@@ -102,10 +107,29 @@ public class ControlStructuresTest extends CodegenTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testTryCatch() throws Exception {
|
public void testTryCatch() throws Exception {
|
||||||
loadFile("controlStructures/tryCatch.jet");
|
loadFile();
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
final Method main = generateFunction();
|
final Method main = generateFunction();
|
||||||
assertEquals("no message", main.invoke(null, "0"));
|
assertEquals("no message", main.invoke(null, "0"));
|
||||||
assertEquals("For input string: \"a\"", main.invoke(null, "a"));
|
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