Add test for instanceof

This commit is contained in:
Daniel Holle 2023-08-18 11:35:01 +02:00
parent bffc7f9f1c
commit 729e88bc6d
17 changed files with 83 additions and 48 deletions

View File

@ -0,0 +1,18 @@
import java.lang.Number;
import java.lang.Integer;
import java.lang.Double;
import java.lang.String;
public class InstanceOf {
main(n) {
if (n instanceof Integer i) {
takes(i);
return "Integer";
} else if (n instanceof Double d) {
takes(d);
return "Double";
}
}
takes(i) {} // Should be overloaded
}

View File

@ -782,7 +782,7 @@ public class Codegen {
convertTo(state, cast.expr().type(), cast.type());
break;
case TargetInstanceOf instanceOf:
mv.visitTypeInsn(INSTANCEOF, instanceOf.right().getInternalName());
generateInstanceOf(state, instanceOf);
break;
case TargetLiteral literal:
switch (literal) {
@ -1009,6 +1009,17 @@ public class Codegen {
}
}
private void generateInstanceOf(State state, TargetInstanceOf instanceOf) {
var mv = state.mv;
if (instanceOf.right() instanceof TargetTypePattern right && right.name() == null) {
mv.visitTypeInsn(INSTANCEOF, right.type().getInternalName());
return;
}
}
private void yieldValue(State state, TargetType type) {
boxPrimitive(state, type);
state.mv.visitVarInsn(ASTORE, state.switchResultValue.peek());
@ -1113,11 +1124,11 @@ public class Codegen {
var types = new ArrayList<Object>(aSwitch.cases().size());
for (var cse : aSwitch.cases()) for (var label : cse.labels()) {
if (label instanceof SimplePattern || label instanceof ComplexPattern)
if (label instanceof TargetTypePattern || label instanceof TargetComplexPattern)
types.add(Type.getObjectType(label.type().getInternalName()));
else if (label instanceof TargetLiteral lit)
types.add(lit.value());
else if (label instanceof Guard guard)
else if (label instanceof TargetGuard guard)
types.add(Type.getObjectType(guard.inner().type().getInternalName()));
// TODO Same here we need to evaluate constant;
else throw new NotImplementedException();
@ -1151,7 +1162,7 @@ public class Codegen {
if (cse.labels().size() == 1) {
var label = cse.labels().get(0);
if (label instanceof Guard gd) {
if (label instanceof TargetGuard gd) {
state.mv.visitVarInsn(ALOAD, tmp);
bindPattern(state, aSwitch.expr().type(), gd.inner(), start, i, 1);
} else if (label instanceof TargetPattern pat) {
@ -1159,7 +1170,7 @@ public class Codegen {
bindPattern(state, aSwitch.expr().type(), pat, start, i, 1);
}
if (label instanceof Guard gd) {
if (label instanceof TargetGuard gd) {
generate(state, gd.expression());
var next = new Label();
mv.visitJumpInsn(IFNE, next);
@ -1216,10 +1227,10 @@ public class Codegen {
state.mv.visitTypeInsn(CHECKCAST, pat.type().getInternalName());
if (pat instanceof SimplePattern sp) {
if (pat instanceof TargetTypePattern sp) {
var local = state.createVariable(sp.name(), sp.type());
state.mv.visitVarInsn(ASTORE, local.index);
} else if (pat instanceof ComplexPattern cp) {
} else if (pat instanceof TargetComplexPattern cp) {
if (cp.name() != null) {
state.mv.visitInsn(DUP);
var local = state.createVariable(cp.name(), cp.type());

View File

@ -875,8 +875,8 @@ public class StatementGenerator {
private Expression convert(Java17Parser.InstanceofexpressionContext expression) {
Expression left = convert(expression.expression());
Token offset = expression.getStart();
if (Objects.isNull(expression.pattern())) {
return new InstanceOf(left, TypeGenerator.convert(expression.typeType(), reg, generics), offset);
if (Objects.isNull(expression.pattern())) {;
return new InstanceOf(left, new RefType(reg.getName("java.lang.Boolean"), expression.getStart()), TypeGenerator.convert(expression.typeType(), reg, generics), offset);
} else {
switch (expression.pattern()) {
case PPatternContext primaryPattern:
@ -886,7 +886,7 @@ public class StatementGenerator {
String localVarName = typePatternCtx.identifier().getText();
RefTypeOrTPHOrWildcardOrGeneric localVarType = TypeGenerator.convert(typePatternCtx.typeType(), reg, generics);
localVars.put(localVarName, localVarType);
return new InstanceOf(left, new FormalParameter(localVarName, localVarType, typePatternCtx.getStart()), offset);
return new InstanceOf(left, new RefType(reg.getName("java.lang.Boolean"), expression.getStart()), new FormalParameter(localVarName, localVarType, typePatternCtx.getStart()), offset);
default:
throw new NotImplementedException();
}

View File

@ -23,8 +23,7 @@ public class BinaryExpr extends Expression {
LESSEQUAL, // <=
BIGGEREQUAL, // >=
EQUAL, // ==
NOTEQUAL, // !=
INSTOF // instanceof
NOTEQUAL // !=
}
public final Operator operation;

View File

@ -6,33 +6,31 @@ import org.antlr.v4.runtime.Token;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
public class InstanceOf extends BinaryExpr {
private FormalParameter pattern;
public class InstanceOf extends Expression {
private final Pattern pattern;
private final Expression expr;
public InstanceOf(Expression expr, RefTypeOrTPHOrWildcardOrGeneric reftype, Token offset) {
super(BinaryExpr.Operator.INSTOF, TypePlaceholder.fresh(offset), expr, new LocalVar("", reftype, reftype.getOffset()), offset);
public InstanceOf(Expression expr, RefTypeOrTPHOrWildcardOrGeneric type, RefTypeOrTPHOrWildcardOrGeneric reftype, Token offset) {
super(type, offset);
this.pattern = new FormalParameter(null, reftype, offset);
this.expr = expr;
}
public InstanceOf(Expression expr, FormalParameter pattern, Token offset) {
super(BinaryExpr.Operator.INSTOF, TypePlaceholder.fresh(offset), expr, new LocalVar(pattern.getName(), pattern.getType(), pattern.getOffset()), offset);
public InstanceOf(Expression expr, RefTypeOrTPHOrWildcardOrGeneric type, Pattern pattern, Token offset) {
super(type, offset);
this.pattern = pattern;
this.expr = expr;
}
public RefTypeOrTPHOrWildcardOrGeneric getReftype() {
return pattern.getType();
}
public String getName() {
return pattern.getName();
}
public FormalParameter gPattern() {
public Pattern getPattern() {
return pattern;
}
public Expression getExpression() {
return expr;
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);

View File

@ -383,6 +383,7 @@ public abstract class GenerateGenerics {
superType = new Void(new NullToken());
ifStmt.then_block.accept(this);
superType = new Void(new NullToken());
if (ifStmt.else_block != null)
ifStmt.else_block.accept(this);
}

View File

@ -143,12 +143,12 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(IfStmt ifStmt) {
result = new TargetIf(converter.convert(ifStmt.expr), converter.convert(ifStmt.then_block), converter.convert(ifStmt.else_block));
result = new TargetIf(converter.convert(ifStmt.expr), converter.convert(ifStmt.then_block), ifStmt.else_block != null ? converter.convert(ifStmt.else_block) : null);
}
@Override
public void visit(InstanceOf instanceOf) {
result = new TargetInstanceOf(converter.convert(instanceOf.lexpr), converter.convert(instanceOf.rexpr.getType()));
result = new TargetInstanceOf(converter.convert(instanceOf.getExpression()), converter.convert(instanceOf.getPattern()));
}
@Override
@ -433,7 +433,7 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(FormalParameter aPattern) {
result = new SimplePattern(converter.convert(aPattern.getType()), aPattern.getName());
result = new TargetTypePattern(converter.convert(aPattern.getType()), aPattern.getName());
}
@Override
@ -443,7 +443,7 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(RecordPattern aRecordPattern) {
result = new ComplexPattern(
result = new TargetComplexPattern(
converter.convert(aRecordPattern.getType()),
aRecordPattern.getName(),
aRecordPattern.getSubPattern().stream().map(x -> (TargetPattern) converter.convert(x)).toList()
@ -452,6 +452,6 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(GuardedPattern aGuardedPattern) {
result = new Guard((TargetPattern) converter.convert(aGuardedPattern.getNestedPattern()), converter.convert(aGuardedPattern.getCondition()));
result = new TargetGuard((TargetPattern) converter.convert(aGuardedPattern.getNestedPattern()), converter.convert(aGuardedPattern.getCondition()));
}
}

View File

@ -69,6 +69,7 @@ public abstract class TracingStatementVisitor implements StatementVisitor {
@Override
public void visit(IfStmt ifStmt) {
ifStmt.then_block.accept(this);
if (ifStmt.else_block != null)
ifStmt.else_block.accept(this);
}

View File

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

View File

@ -4,5 +4,5 @@ import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
public record ComplexPattern(TargetType type, String name, List<TargetPattern> subPatterns) implements TargetPattern {
public record TargetComplexPattern(TargetType type, String name, List<TargetPattern> subPatterns) implements TargetPattern {
}

View File

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

View File

@ -3,7 +3,7 @@ package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetInstanceOf(TargetExpression left, TargetType right) implements TargetExpression {
public record TargetInstanceOf(TargetExpression left, TargetExpression right) implements TargetExpression {
@Override
public TargetType type() {

View File

@ -1,6 +1,6 @@
package de.dhbwstuttgart.target.tree.expression;
public sealed interface TargetPattern extends TargetExpression permits ComplexPattern, Guard, SimplePattern {
public sealed interface TargetPattern extends TargetExpression permits TargetComplexPattern, TargetGuard, TargetTypePattern {
default String name() {
return null;
}

View File

@ -2,5 +2,5 @@ package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record SimplePattern(TargetType type, String name) implements TargetPattern {
public record TargetTypePattern(TargetType type, String name) implements TargetPattern {
}

View File

@ -175,7 +175,7 @@ public class TYPEStmt implements StatementVisitor {
// Blöcke inferieren:
ifStmt.then_block.accept(this);
// Beide Blöcke müssen den gleichen Supertyp haben, welcher den Rückgabetyp des If-Stmts darstellt
constraintsSet.addUndConstraint(new Pair(ifStmt.else_block.getType(), ifStmt.getType(), PairOperator.SMALLERDOT));
//constraintsSet.addUndConstraint(new Pair(ifStmt.else_block.getType(), ifStmt.getType(), PairOperator.SMALLERDOT));
if (ifStmt.else_block != null) {
ifStmt.else_block.accept(this);
constraintsSet.addUndConstraint(new Pair(ifStmt.else_block.getType(), ifStmt.getType(), PairOperator.SMALLERDOT));
@ -185,7 +185,7 @@ public class TYPEStmt implements StatementVisitor {
@Override
public void visit(InstanceOf instanceOf) {
throw new NotImplementedException();
//throw new NotImplementedException();
}
@Override

View File

@ -684,4 +684,11 @@ public class TestComplete {
assertEquals(main.invoke(instance, "TEST"), 3);
assertEquals(main.invoke(instance, "awawa"), 4);
}
@Test
public void testInstanceOfPattern() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "InstanceOf.jav");
var clazz = classFiles.get("InstanceOf");
var instance = clazz.getDeclaredConstructor().newInstance();
}
}

View File

@ -237,15 +237,15 @@ public class TestCodegen {
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "SwitchEnhanced");
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 SimplePattern(TargetType.String, "aString")), new TargetBlock(
new TargetSwitch.Case(List.of(new TargetTypePattern(TargetType.String, "aString")), new TargetBlock(
List.of(new TargetYield(new TargetLiteral.IntLiteral(0)))
), false),
new TargetSwitch.Case(List.of(
new Guard(new SimplePattern(TargetType.Integer, "i"), new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(10)))
new TargetGuard(new TargetTypePattern(TargetType.Integer, "i"), new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(10)))
), new TargetBlock(
List.of(new TargetLiteral.IntLiteral(3))
), true),
new TargetSwitch.Case(List.of(new SimplePattern(TargetType.Integer, "anInteger")), new TargetBlock(
new TargetSwitch.Case(List.of(new TargetTypePattern(TargetType.Integer, "anInteger")), new TargetBlock(
List.of(new TargetLiteral.IntLiteral(1))
), true)
), new TargetSwitch.Case(new TargetBlock(