Add test for instanceof
This commit is contained in:
parent
bffc7f9f1c
commit
729e88bc6d
18
resources/bytecode/javFiles/InstanceOf.jav
Normal file
18
resources/bytecode/javFiles/InstanceOf.jav
Normal 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
|
||||
}
|
@ -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());
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -23,8 +23,7 @@ public class BinaryExpr extends Expression {
|
||||
LESSEQUAL, // <=
|
||||
BIGGEREQUAL, // >=
|
||||
EQUAL, // ==
|
||||
NOTEQUAL, // !=
|
||||
INSTOF // instanceof
|
||||
NOTEQUAL // !=
|
||||
}
|
||||
|
||||
public final Operator operation;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -1,4 +0,0 @@
|
||||
package de.dhbwstuttgart.target.tree.expression;
|
||||
|
||||
public record Guard(TargetPattern inner, TargetExpression expression) implements TargetPattern {
|
||||
}
|
@ -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 {
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package de.dhbwstuttgart.target.tree.expression;
|
||||
|
||||
public record TargetGuard(TargetPattern inner, TargetExpression expression) implements TargetPattern {
|
||||
}
|
@ -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() {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
}
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user