Add new target ast nodes and test cases for switch
This commit is contained in:
parent
a0582e918b
commit
3de9fde672
@ -11,20 +11,20 @@ public class SwitchBlock extends Block {
|
||||
|
||||
private List<SwitchLabel> labels = new ArrayList<>();
|
||||
|
||||
private Boolean defaultBlock = false;
|
||||
private boolean defaultBlock = false;
|
||||
|
||||
public SwitchBlock(List<SwitchLabel> labels, Block statements, Token offset) {
|
||||
super(statements.getStatements(), offset);
|
||||
this.labels = labels;
|
||||
}
|
||||
|
||||
public SwitchBlock(List<SwitchLabel> labels, Block statements, Boolean isDefault, Token offset) {
|
||||
public SwitchBlock(List<SwitchLabel> labels, Block statements, boolean isDefault, Token offset) {
|
||||
super(statements.getStatements(), offset);
|
||||
this.labels = labels;
|
||||
this.defaultBlock = isDefault;
|
||||
}
|
||||
|
||||
public Boolean isDefault() {
|
||||
public boolean isDefault() {
|
||||
return defaultBlock;
|
||||
}
|
||||
|
||||
|
@ -10,9 +10,11 @@ import de.dhbwstuttgart.syntaxtree.type.*;
|
||||
import de.dhbwstuttgart.target.tree.*;
|
||||
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
||||
import de.dhbwstuttgart.target.tree.expression.TargetExpression;
|
||||
import de.dhbwstuttgart.target.tree.expression.TargetSwitch;
|
||||
import de.dhbwstuttgart.target.tree.type.*;
|
||||
import de.dhbwstuttgart.typeinference.result.*;
|
||||
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@ -205,6 +207,10 @@ public class ASTToTargetAST {
|
||||
return result;
|
||||
}
|
||||
|
||||
protected TargetSwitch.Case convert(SwitchBlock block) {
|
||||
return new TargetSwitch.Case(block.getLabels().stream().map(this::convert).toList(), convert((Block) block));
|
||||
}
|
||||
|
||||
protected TargetBlock convert(Block block) {
|
||||
return new TargetBlock(block.statements.stream().map(this::convert).toList());
|
||||
}
|
||||
|
@ -74,41 +74,6 @@ public class StatementToTargetExpression implements StatementVisitor {
|
||||
@Override
|
||||
public void visit(LambdaExpression lambda) {
|
||||
} // Don't look at lambda expressions
|
||||
|
||||
@Override
|
||||
public void visit(Switch switchStmt) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SwitchBlock switchBlock) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SwitchLabel switchLabel) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Yield aYield) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Pattern aPattern) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RecordPattern aRecordPattern) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(GuardedPattern aGuardedPattern) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
});
|
||||
|
||||
result = new TargetLambdaExpression(converter.convert(lambdaExpression.getType()), captures, parameters, converter.convert(lambdaExpression.getReturnType()), converter.convert(lambdaExpression.methodBody));
|
||||
@ -378,18 +343,16 @@ public class StatementToTargetExpression implements StatementVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(Switch switchStmt) {
|
||||
// TODO Auto-generated method stub
|
||||
var cases = switchStmt.getBlocks().stream().filter(s -> !s.isDefault()).map(converter::convert).toList();
|
||||
var default_ = switchStmt.getBlocks().stream().filter(SwitchBlock::isDefault).map(s -> converter.convert((Block) s)).findFirst().orElse(null);
|
||||
result = new TargetSwitch(converter.convert(switchStmt.getSwitch()), cases, default_, converter.convert(switchStmt.getType()), !switchStmt.getStatement());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SwitchBlock switchBlock) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
public void visit(SwitchBlock switchBlock) {}
|
||||
|
||||
@Override
|
||||
public void visit(SwitchLabel switchLabel) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
public void visit(SwitchLabel switchLabel) {}
|
||||
|
||||
@Override
|
||||
public void visit(Yield aYield) {
|
||||
@ -398,16 +361,21 @@ public class StatementToTargetExpression implements StatementVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(Pattern aPattern) {
|
||||
// TODO Auto-generated method stub
|
||||
result = new TargetSwitch.Pattern(converter.convert(aPattern.getType()), aPattern.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RecordPattern aRecordPattern) {
|
||||
// TODO Auto-generated method stub
|
||||
result = new TargetSwitch.ComplexPattern(
|
||||
converter.convert(aRecordPattern.getType()),
|
||||
aRecordPattern.getSubPattern().stream().map(x -> (TargetSwitch.Pattern) converter.convert(x)).toList()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(GuardedPattern aGuardedPattern) {
|
||||
// TODO Auto-generated method stub
|
||||
//FIXME This isn't done properly inside the parser, really you should only have one guard (Chaining them together with && just yields another expression)
|
||||
//And then it also needs to be able to accept complex patterns. Because of this we only accept one condition for now.
|
||||
result = new TargetSwitch.Guard(new TargetSwitch.Pattern(converter.convert(aGuardedPattern.getType()), aGuardedPattern.getName()), converter.convert(aGuardedPattern.getConditions().get(0)));
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,4 @@ import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
import java.util.List;
|
||||
|
||||
public record TargetBlock(List<TargetExpression> statements) implements TargetExpression {
|
||||
@Override
|
||||
public TargetType type() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,4 @@ package de.dhbwstuttgart.target.tree.expression;
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
|
||||
public record TargetBreak() implements TargetExpression {
|
||||
|
||||
@Override
|
||||
public TargetType type() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,4 @@ package de.dhbwstuttgart.target.tree.expression;
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
|
||||
public record TargetContinue() implements TargetExpression {
|
||||
|
||||
@Override
|
||||
public TargetType type() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,9 @@ package de.dhbwstuttgart.target.tree.expression;
|
||||
import de.dhbwstuttgart.target.tree.type.*;
|
||||
|
||||
public sealed interface TargetExpression
|
||||
permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetUnaryOp, TargetVarDecl, TargetWhile {
|
||||
permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetSwitch.ComplexPattern, TargetSwitch.Guard, TargetSwitch.Pattern, TargetTernary, TargetThis, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield {
|
||||
|
||||
TargetType type();
|
||||
default TargetType type() {
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
@ -3,9 +3,4 @@ package de.dhbwstuttgart.target.tree.expression;
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
|
||||
public record TargetFor(TargetExpression init, TargetExpression termination, TargetExpression increment, TargetExpression body) implements TargetExpression {
|
||||
|
||||
@Override
|
||||
public TargetType type() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,4 @@ package de.dhbwstuttgart.target.tree.expression;
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
|
||||
public record TargetForEach(TargetExpression vardecl, TargetExpression list) implements TargetExpression {
|
||||
|
||||
@Override
|
||||
public TargetType type() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,4 @@ package de.dhbwstuttgart.target.tree.expression;
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
|
||||
public record TargetIf(TargetExpression cond, TargetExpression if_body, TargetExpression else_body) implements TargetExpression {
|
||||
@Override
|
||||
public TargetType type() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,4 @@ package de.dhbwstuttgart.target.tree.expression;
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
|
||||
public record TargetReturn(TargetExpression expression) implements TargetExpression {
|
||||
@Override
|
||||
public TargetType type() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,27 @@
|
||||
package de.dhbwstuttgart.target.tree.expression;
|
||||
|
||||
import de.dhbwstuttgart.syntaxtree.statement.Expression;
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record TargetSwitch(Expression expr, List<Case> cases, Expression default_) implements TargetExpression {
|
||||
public record TargetSwitch(TargetExpression expr, List<Case> cases, TargetBlock default_, TargetType type, boolean isExpression) implements TargetExpression {
|
||||
|
||||
@Override
|
||||
public TargetType type() {
|
||||
return null;
|
||||
public TargetSwitch(TargetExpression expr, List<Case> cases, TargetBlock default_) {
|
||||
this(expr, cases, default_, null, false);
|
||||
}
|
||||
|
||||
record Case(Expression value, Expression body) {}
|
||||
public TargetSwitch(TargetExpression expr, List<Case> cases, TargetBlock default_, TargetType type) {
|
||||
this(expr, cases, default_, type, true);
|
||||
}
|
||||
|
||||
public TargetSwitch(TargetExpression expr, List<Case> cases, TargetBlock default_, boolean isExpression) {
|
||||
this(expr, cases, default_, null, isExpression);
|
||||
}
|
||||
|
||||
public record Case(List<TargetExpression> labels, TargetBlock body) {}
|
||||
|
||||
public record Pattern(TargetType type, String name) implements TargetExpression {}
|
||||
public record ComplexPattern(TargetType type, List<Pattern> subPatterns) implements TargetExpression {}
|
||||
|
||||
public record Guard(TargetExpression inner, TargetExpression expression) implements TargetExpression {}
|
||||
}
|
||||
|
@ -3,9 +3,4 @@ package de.dhbwstuttgart.target.tree.expression;
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
|
||||
public record TargetWhile(TargetExpression cond, TargetExpression body) implements TargetExpression {
|
||||
|
||||
@Override
|
||||
public TargetType type() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,4 @@
|
||||
package de.dhbwstuttgart.target.tree.expression;
|
||||
|
||||
public record TargetYield(TargetExpression expression) implements TargetExpression {
|
||||
}
|
@ -13,7 +13,9 @@ import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -196,6 +198,47 @@ public class TestCodegen {
|
||||
assertEquals(clazz.getDeclaredMethod("whileLoop").invoke(null), 10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassicSwitch() throws Exception {
|
||||
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC , "Switch");
|
||||
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "switchClassic", List.of(new MethodParameter(TargetType.Integer, "i")), TargetType.Integer, new TargetBlock(List.of(
|
||||
new TargetVarDecl(TargetType.Integer, "res", null),
|
||||
new TargetSwitch(new TargetLocalVar(TargetType.Integer, "i"), List.of(
|
||||
new TargetSwitch.Case(List.of(new TargetLiteral.IntLiteral(10)), new TargetBlock(
|
||||
List.of(new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "res"), new TargetLiteral.IntLiteral(0)), new TargetBreak())
|
||||
)),
|
||||
new TargetSwitch.Case(List.of(new TargetLiteral.IntLiteral(20)), new TargetBlock(List.of())),
|
||||
new TargetSwitch.Case(List.of(new TargetLiteral.IntLiteral(30)), new TargetBlock(
|
||||
List.of(new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "res"), new TargetLiteral.IntLiteral(1)), new TargetBreak())
|
||||
))
|
||||
), new TargetBlock(
|
||||
List.of(new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "res"), new TargetLiteral.IntLiteral(2)), new TargetBreak())
|
||||
))
|
||||
)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTypeSwitch() throws Exception {
|
||||
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Switch");
|
||||
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "switchType", List.of(new MethodParameter(TargetType.Object, "obj")), TargetType.Integer, new TargetBlock(List.of(
|
||||
new TargetReturn(new TargetSwitch(new TargetLocalVar(TargetType.Object, "obj"), List.of(
|
||||
new TargetSwitch.Case(List.of(new TargetSwitch.Pattern(TargetType.String, "aString")), new TargetBlock(
|
||||
List.of(new TargetLiteral.IntLiteral(0))
|
||||
)),
|
||||
new TargetSwitch.Case(List.of(new TargetSwitch.Pattern(TargetType.Integer, "anInteger")), new TargetBlock(
|
||||
List.of(new TargetLiteral.IntLiteral(1))
|
||||
))
|
||||
), new TargetBlock(
|
||||
List.of(new TargetLiteral.IntLiteral(2))
|
||||
), TargetType.Integer)
|
||||
))));
|
||||
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
|
||||
var m = clazz.getDeclaredMethod("switchType", Object.class);
|
||||
assertEquals(m.invoke(null, "String"), 0);
|
||||
assertEquals(m.invoke(null, 10), 1);
|
||||
assertEquals(m.invoke(null, 'A'), 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("The lambda class is not generated because we don't call ASTToTargetAST")
|
||||
public void testLambda() throws Exception {
|
||||
|
Loading…
Reference in New Issue
Block a user