Implement throw

This commit is contained in:
Daniel Holle 2024-02-01 11:58:08 +01:00
parent 9da763b361
commit a035589647
13 changed files with 83 additions and 5 deletions

View File

@ -1,3 +1,8 @@
import java.lang.String;
import java.lang.RuntimeException;
public class Exceptions { public class Exceptions {
// m(Integer i) throws m() {
throw new RuntimeException("Some Exception");
}
} }

View File

@ -1040,6 +1040,11 @@ public class Codegen {
mv.visitMethodInsn(INVOKESPECIAL, _new.type().getInternalName(), "<init>", _new.getDescriptor(), false); mv.visitMethodInsn(INVOKESPECIAL, _new.type().getInternalName(), "<init>", _new.getDescriptor(), false);
break; break;
} }
case TargetThrow _throw: {
generate(state, _throw.expr());
mv.visitInsn(ATHROW);
break;
}
default: default:
throw new CodeGenException("Unexpected value: " + expr); throw new CodeGenException("Unexpected value: " + expr);
} }

View File

@ -611,8 +611,7 @@ public class StatementGenerator {
} }
private Statement convert(Java17Parser.ThrowstmtContext stmt) { private Statement convert(Java17Parser.ThrowstmtContext stmt) {
// TODO return new Throw(convert(stmt.expression()), stmt.getStart());
throw new NotImplementedException();
} }
private Statement convert(Java17Parser.SynchronizedstmtContext stmt) { private Statement convert(Java17Parser.SynchronizedstmtContext stmt) {

View File

@ -266,6 +266,11 @@ public abstract class AbstractASTWalker implements ASTVisitor {
} }
@Override
public void visit(Throw aThrow) {
}
@Override @Override
public void visit(AssignToField assignLeftSide) { public void visit(AssignToField assignLeftSide) {
assignLeftSide.field.accept(this); assignLeftSide.field.accept(this);

View File

@ -76,4 +76,6 @@ public interface StatementVisitor {
void visit(UnaryExpr unaryExpr); void visit(UnaryExpr unaryExpr);
void visit(Literal literal); void visit(Literal literal);
void visit(Throw aThrow);
} }

View File

@ -0,0 +1,21 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.Void;
import org.antlr.v4.runtime.Token;
public class Throw extends Statement {
public final Expression expr;
public Throw(Expression expr, Token offset) {
super(new Void(offset), offset);
this.expr = expr;
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@ -407,6 +407,11 @@ public class OutputGenerator implements ASTVisitor {
out.append(literal.value); out.append(literal.value);
} }
@Override
public void visit(Throw aThrow) {
// TODO implement
}
@Override @Override
public void visit(Switch switchStmt) { public void visit(Switch switchStmt) {
out.append("switch("); out.append("switch(");

View File

@ -323,6 +323,11 @@ public class StatementToTargetExpression implements ASTVisitor {
} }
} }
@Override
public void visit(Throw aThrow) {
result = new TargetThrow(converter.convert(aThrow.expr));
}
@Override @Override
public void visit(Switch switchStmt) { public void visit(Switch switchStmt) {
var cases = switchStmt.getBlocks().stream().filter(s -> !s.isDefault()).map(converter::convert).toList(); var cases = switchStmt.getBlocks().stream().filter(s -> !s.isDefault()).map(converter::convert).toList();

View File

@ -173,6 +173,11 @@ public abstract class TracingStatementVisitor implements StatementVisitor {
} }
@Override
public void visit(Throw aThrow) {
}
@Override @Override
public void visit(Switch switchStmt) { public void visit(Switch switchStmt) {

View File

@ -3,7 +3,7 @@ package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.*; import de.dhbwstuttgart.target.tree.type.*;
public sealed interface TargetExpression public sealed interface TargetExpression
permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetPattern, TargetTernary, TargetThis, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield { permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetPattern, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetThrow, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield {
default TargetType type() { default TargetType type() {
return null; return null;

View File

@ -0,0 +1,4 @@
package de.dhbwstuttgart.target.tree.expression;
public record TargetThrow(TargetExpression expr) implements TargetExpression {
}

View File

@ -456,6 +456,11 @@ public class TYPEStmt implements StatementVisitor {
} }
} }
@Override
public void visit(Throw aThrow) {
aThrow.expr.accept(this);
}
@Override @Override
public void visit(Return returnExpr) { public void visit(Return returnExpr) {
returnExpr.retexpr.accept(this); returnExpr.retexpr.accept(this);

View File

@ -1,9 +1,9 @@
import de.dhbwstuttgart.environment.ByteArrayClassLoader; import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.util.Arrays; import java.util.Arrays;
@ -799,4 +799,21 @@ public class TestComplete {
assertTrue((Boolean) clazz.getDeclaredMethod("test2").invoke(instance)); assertTrue((Boolean) clazz.getDeclaredMethod("test2").invoke(instance));
assertFalse((Boolean) clazz.getDeclaredMethod("test3").invoke(instance)); assertFalse((Boolean) clazz.getDeclaredMethod("test3").invoke(instance));
} }
@Test
public void testExceptions() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Exceptions.jav");
var clazz = classFiles.get("Exceptions");
var instance = clazz.getDeclaredConstructor().newInstance();
try {
clazz.getDeclaredMethod("m").invoke(instance);
fail("No exception thrown!");
} catch (InvocationTargetException exception) {
var exc = exception.getTargetException();
if (!(exc instanceof RuntimeException rexp) || !rexp.getMessage().equals("Some Exception")) {
fail("Wrong exception thrown!");
}
}
}
} }