From 729e88bc6d0035e8fc1d7fba17708df81cc1eae2 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Fri, 18 Aug 2023 11:35:01 +0200 Subject: [PATCH] Add test for instanceof --- resources/bytecode/javFiles/InstanceOf.jav | 18 +++++++++++ .../de/dhbwstuttgart/bytecode/Codegen.java | 25 +++++++++++----- .../StatementGenerator.java | 6 ++-- .../syntaxtree/statement/BinaryExpr.java | 3 +- .../syntaxtree/statement/InstanceOf.java | 30 +++++++++---------- .../target/generate/GenerateGenerics.java | 3 +- .../generate/StatementToTargetExpression.java | 10 +++---- .../generate/TracingStatementVisitor.java | 3 +- .../target/tree/expression/Guard.java | 4 --- ...Pattern.java => TargetComplexPattern.java} | 2 +- .../target/tree/expression/TargetGuard.java | 4 +++ .../tree/expression/TargetInstanceOf.java | 2 +- .../target/tree/expression/TargetPattern.java | 2 +- ...plePattern.java => TargetTypePattern.java} | 2 +- .../typeinference/typeAlgo/TYPEStmt.java | 4 +-- src/test/java/TestComplete.java | 7 +++++ src/test/java/targetast/TestCodegen.java | 6 ++-- 17 files changed, 83 insertions(+), 48 deletions(-) create mode 100644 resources/bytecode/javFiles/InstanceOf.jav delete mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/Guard.java rename src/main/java/de/dhbwstuttgart/target/tree/expression/{ComplexPattern.java => TargetComplexPattern.java} (50%) create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetGuard.java rename src/main/java/de/dhbwstuttgart/target/tree/expression/{SimplePattern.java => TargetTypePattern.java} (54%) diff --git a/resources/bytecode/javFiles/InstanceOf.jav b/resources/bytecode/javFiles/InstanceOf.jav new file mode 100644 index 00000000..4cee01f2 --- /dev/null +++ b/resources/bytecode/javFiles/InstanceOf.jav @@ -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 +} \ No newline at end of file diff --git a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java index 5a758899..d75a8236 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java @@ -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(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()); diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index 8cc1d586..5fbda898 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -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(); } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/BinaryExpr.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/BinaryExpr.java index 4fe8f9fb..9902f481 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/BinaryExpr.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/BinaryExpr.java @@ -23,8 +23,7 @@ public class BinaryExpr extends Expression { LESSEQUAL, // <= BIGGEREQUAL, // >= EQUAL, // == - NOTEQUAL, // != - INSTOF // instanceof + NOTEQUAL // != } public final Operator operation; diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/InstanceOf.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/InstanceOf.java index 0c8b0eab..a3a08414 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/InstanceOf.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/InstanceOf.java @@ -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); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java b/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java index cc209487..3e26ff8f 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java @@ -383,7 +383,8 @@ public abstract class GenerateGenerics { superType = new Void(new NullToken()); ifStmt.then_block.accept(this); superType = new Void(new NullToken()); - ifStmt.else_block.accept(this); + if (ifStmt.else_block != null) + ifStmt.else_block.accept(this); } @Override diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index b27672b6..7a59dbcc 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -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())); } } diff --git a/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java index 6301145b..81aa824e 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java @@ -69,7 +69,8 @@ public abstract class TracingStatementVisitor implements StatementVisitor { @Override public void visit(IfStmt ifStmt) { ifStmt.then_block.accept(this); - ifStmt.else_block.accept(this); + if (ifStmt.else_block != null) + ifStmt.else_block.accept(this); } @Override diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/Guard.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/Guard.java deleted file mode 100644 index 46594350..00000000 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/Guard.java +++ /dev/null @@ -1,4 +0,0 @@ -package de.dhbwstuttgart.target.tree.expression; - -public record Guard(TargetPattern inner, TargetExpression expression) implements TargetPattern { -} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/ComplexPattern.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetComplexPattern.java similarity index 50% rename from src/main/java/de/dhbwstuttgart/target/tree/expression/ComplexPattern.java rename to src/main/java/de/dhbwstuttgart/target/tree/expression/TargetComplexPattern.java index 92896ba3..761ddeed 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/ComplexPattern.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetComplexPattern.java @@ -4,5 +4,5 @@ import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.List; -public record ComplexPattern(TargetType type, String name, List subPatterns) implements TargetPattern { +public record TargetComplexPattern(TargetType type, String name, List subPatterns) implements TargetPattern { } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetGuard.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetGuard.java new file mode 100644 index 00000000..11dcf10d --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetGuard.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.target.tree.expression; + +public record TargetGuard(TargetPattern inner, TargetExpression expression) implements TargetPattern { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetInstanceOf.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetInstanceOf.java index c1f104e2..e6b28534 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetInstanceOf.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetInstanceOf.java @@ -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() { diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetPattern.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetPattern.java index 9d9fd5ed..4f5bd943 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetPattern.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetPattern.java @@ -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; } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/SimplePattern.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetTypePattern.java similarity index 54% rename from src/main/java/de/dhbwstuttgart/target/tree/expression/SimplePattern.java rename to src/main/java/de/dhbwstuttgart/target/tree/expression/TargetTypePattern.java index 1ed9bec6..856496f9 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/SimplePattern.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetTypePattern.java @@ -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 { } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index 082b5f7a..52801b18 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -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 diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index 5f3d592e..b8e13e89 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -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(); + } } diff --git a/src/test/java/targetast/TestCodegen.java b/src/test/java/targetast/TestCodegen.java index f7292a4a..a7812172 100644 --- a/src/test/java/targetast/TestCodegen.java +++ b/src/test/java/targetast/TestCodegen.java @@ -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(