From 71899ac673de6e47b06e46c5d57a900bf2cead19 Mon Sep 17 00:00:00 2001 From: "pl@gohorb.ba-horb.de" Date: Fri, 15 Dec 2023 13:47:25 +0100 Subject: [PATCH 01/18] Please enter the commit message for your changes. Lines starting with '#' will be ignored, and an empty message aborts the commit. --- .../de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java index 01834a75..76e6a438 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java @@ -2024,9 +2024,6 @@ public class TypeUnifyTask extends RecursiveTask>> { if (((pairOp == PairOperator.SMALLERDOT) || (pairOp == PairOperator.SMALLERNEQDOT)) && lhsType instanceof PlaceholderType) { //System.out.println(pair); if (first) { //writeLog(pair.toString()+"\n"); - if (((PlaceholderType)(pair.getLhsType())).getName().equals("AR")) { - System.out.println("AR"); - } Set> x1 = unifyCase1(pair, fc); if (pairOp == PairOperator.SMALLERNEQDOT) { Set remElem = new HashSet<>(); From b80cc726c86a15cf6588f04c978844d94bb5f0bc Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Fri, 19 Jan 2024 16:29:59 +0100 Subject: [PATCH 02/18] Add ForEach loop --- resources/bytecode/javFiles/ForEach.jav | 15 +++++++++ .../de/dhbwstuttgart/bytecode/Codegen.java | 33 +++++++++++++++++++ .../StatementGenerator.java | 27 ++++++++++++--- .../syntaxtree/AbstractASTWalker.java | 5 +++ .../syntaxtree/StatementVisitor.java | 2 ++ .../syntaxtree/statement/ForEachStmt.java | 26 +++++++++++++++ .../syntaxtree/visual/OutputGenerator.java | 5 +++ .../generate/StatementToTargetExpression.java | 5 +++ .../generate/TracingStatementVisitor.java | 5 +++ .../target/tree/expression/TargetForEach.java | 2 +- .../typeinference/typeAlgo/TYPEStmt.java | 9 +++++ src/test/java/TestComplete.java | 9 +++++ 12 files changed, 137 insertions(+), 6 deletions(-) create mode 100644 resources/bytecode/javFiles/ForEach.jav create mode 100644 src/main/java/de/dhbwstuttgart/syntaxtree/statement/ForEachStmt.java diff --git a/resources/bytecode/javFiles/ForEach.jav b/resources/bytecode/javFiles/ForEach.jav new file mode 100644 index 00000000..32b1eb8d --- /dev/null +++ b/resources/bytecode/javFiles/ForEach.jav @@ -0,0 +1,15 @@ +import java.util.ArrayList; +import java.lang.Integer; + +public class ForEach { + m() { + var list = new ArrayList<>(); + list.add(1); list.add(2); list.add(3); + + var sum = 0; + for (var i : list) { + sum = sum + i; + } + return sum; + } +} \ 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 5ef179d3..6cd9a3bc 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java @@ -2,6 +2,7 @@ package de.dhbwstuttgart.bytecode; import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.type.RefType; @@ -918,6 +919,9 @@ public class Codegen { state.localCounter = localCounter; break; } + case TargetForEach forEach: + generateForEach(forEach, state); + break; case TargetWhile _while: { Label start = new Label(); Label end = new Label(); @@ -1041,6 +1045,35 @@ public class Codegen { } } + private void generateForEach(TargetForEach forEach, State state) { + state.enterScope(); + TargetVarDecl vd = (TargetVarDecl) forEach.vardecl(); + var localVar = state.createVariable(vd.name(), vd.varType()); + + var expr = forEach.expression(); + // TODO Check for arrays + var mv = state.mv; + generate(state, expr); + mv.visitMethodInsn(INVOKEINTERFACE, "java/lang/Iterable", "iterator", "()Ljava/util/Iterator;", true); + var start = new Label(); + var end = new Label(); + mv.visitLabel(start); + mv.visitInsn(DUP); + mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z", true); + mv.visitJumpInsn(IFEQ, end); + mv.visitInsn(DUP); + mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;", true); + mv.visitVarInsn(ASTORE, localVar.index); + + generate(state, forEach.body()); + + mv.visitJumpInsn(GOTO, start); + mv.visitLabel(end); + mv.visitInsn(POP); + + state.exitScope(); + } + private void generateInstanceOf(State state, TargetInstanceOf instanceOf) { var mv = state.mv; diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index 3611f003..4514a0f5 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -490,15 +490,32 @@ public class StatementGenerator { private Statement convert(Java17Parser.ForloopContext stmt) { var control = stmt.forControl(); - var block = convert(stmt.statement()); - if (control.enhancedForControl() != null) - throw new NotImplementedException(); - else { + if (control.enhancedForControl() != null) { + var forCtrl = control.enhancedForControl(); + var name = forCtrl.variableDeclaratorId().identifier(); + + RefTypeOrTPHOrWildcardOrGeneric type; + if (Objects.isNull(forCtrl.typeType()) || !Objects.isNull(forCtrl.VAR())) { + type = TypePlaceholder.fresh(forCtrl.getStart()); + } else { + type = TypeGenerator.convert(forCtrl.typeType(), reg, generics); + } + + var vardecl = new LocalVarDecl(name.getText(), type, name.getStart()); + this.localVars.put(name.getText(), type); + + return new ForEachStmt( + stmt.getStart(), + vardecl, + convert(forCtrl.expression()), + convert(stmt.statement()) + ); + } else { return new ForStmt( stmt.getStart(), convert(control.forInit().localVariableDeclaration()), convert(control.expression()), control.forUpdate.expression().stream().map(this::convert).toList(), - block + convert(stmt.statement()) ); } } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java b/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java index 9b8d5286..f8bf0502 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java @@ -166,6 +166,11 @@ public abstract class AbstractASTWalker implements ASTVisitor { forStmt.block.accept(this); } + @Override + public void visit(ForEachStmt forEachStmt) { + forEachStmt.block.accept(this); + } + @Override public void visit(IfStmt ifStmt) { ifStmt.then_block.accept(this); diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java b/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java index 737e984e..3cc4e128 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java @@ -25,6 +25,8 @@ public interface StatementVisitor { void visit(ForStmt forStmt); + void visit(ForEachStmt forEachStmt); + void visit(IfStmt ifStmt); void visit(InstanceOf instanceOf); diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ForEachStmt.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ForEachStmt.java new file mode 100644 index 00000000..3686ea27 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ForEachStmt.java @@ -0,0 +1,26 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.parser.NullToken; +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 ForEachStmt extends Statement { + + public final Statement statement; + public final Expression expression; + public final Statement block; + + public ForEachStmt(Token offset, Statement stmt, Expression expression, Statement block) { + super(new Void(new NullToken()), offset); + this.statement = stmt; + this.expression = expression; + this.block = block; + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java b/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java index 1afcfdea..0e0b7081 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java @@ -244,6 +244,11 @@ public class OutputGenerator implements ASTVisitor { } + @Override + public void visit(ForEachStmt forEachStmt) { + + } + @Override public void visit(IfStmt ifStmt) { out.append("if("); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 1e5d77d5..6eeb784b 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -144,6 +144,11 @@ public class StatementToTargetExpression implements ASTVisitor { result = new TargetFor(forStmt.initializer.stream().map(converter::convert).toList(), converter.convert(forStmt.condition), forStmt.loopExpr.stream().map(converter::convert).toList(), converter.convert(forStmt.block)); } + @Override + public void visit(ForEachStmt forEachStmt) { + result = new TargetForEach(converter.convert(forEachStmt.statement), converter.convert(forEachStmt.expression), converter.convert(forEachStmt.block)); + } + @Override public void visit(IfStmt ifStmt) { result = new TargetIf(converter.convert(ifStmt.expr), converter.convert(ifStmt.then_block), ifStmt.else_block != null ? converter.convert(ifStmt.else_block) : null); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java index f7feb9f4..a84d6322 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java @@ -66,6 +66,11 @@ public abstract class TracingStatementVisitor implements StatementVisitor { forStmt.block.accept(this); } + @Override + public void visit(ForEachStmt forEachStmt) { + forEachStmt.block.accept(this); + } + @Override public void visit(IfStmt ifStmt) { ifStmt.then_block.accept(this); diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetForEach.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetForEach.java index ce4fa10b..e7928afc 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetForEach.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetForEach.java @@ -1,4 +1,4 @@ package de.dhbwstuttgart.target.tree.expression; -public record TargetForEach(TargetExpression vardecl, TargetExpression list) implements TargetExpression { +public record TargetForEach(TargetExpression vardecl, TargetExpression expression, TargetExpression body) implements TargetExpression { } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index 154beca8..ac023831 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -128,6 +128,15 @@ public class TYPEStmt implements StatementVisitor { forStmt.block.accept(this); } + @Override + public void visit(ForEachStmt forEachStmt) { + var iterableType = new RefType(ASTFactory.createClass(java.lang.Iterable.class).getClassName(), Arrays.asList(forEachStmt.statement.getType()), new NullToken()); + constraintsSet.addUndConstraint(new Pair(forEachStmt.expression.getType(), iterableType, PairOperator.SMALLERDOT)); + forEachStmt.statement.accept(this); + forEachStmt.expression.accept(this); + forEachStmt.block.accept(this); + } + @Override public void visit(IfStmt ifStmt) { RefType booleanType = new RefType(ASTFactory.createClass(java.lang.Boolean.class).getClassName(), new NullToken()); diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index 4e885284..1f50d362 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -737,6 +737,15 @@ public class TestComplete { var m = clazz.getDeclaredMethod("m", Integer.class); assertEquals(m.invoke(instance, 10), 60); } + + @Test + public void testForEach() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "ForEach.jav"); + var clazz = classFiles.get("ForEach"); + var instance = clazz.getDeclaredConstructor().newInstance(); + var m = clazz.getDeclaredMethod("m"); + assertEquals(m.invoke(instance), 6); + } @Test public void testLambdaRunnable() throws Exception { From f18903834ebe45011d8104458d8a692da6135dce Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Tue, 23 Jan 2024 14:00:42 +0100 Subject: [PATCH 03/18] Fix super calls --- resources/bytecode/javFiles/SuperCall.jav | 11 +++++ .../de/dhbwstuttgart/bytecode/Codegen.java | 4 +- .../StatementGenerator.java | 12 ++++-- .../SyntaxTreeGenerator.java | 43 ++++++++----------- .../dhbwstuttgart/syntaxtree/Constructor.java | 20 +++------ .../syntaxtree/statement/MethodCall.java | 1 + .../syntaxtree/statement/Super.java | 7 ++- .../syntaxtree/statement/SuperCall.java | 4 +- .../assumptions/MethodAssumption.java | 2 + .../typeinference/typeAlgo/TYPEStmt.java | 30 ++++++++++--- src/test/java/TestComplete.java | 9 +++- 11 files changed, 91 insertions(+), 52 deletions(-) create mode 100644 resources/bytecode/javFiles/SuperCall.jav diff --git a/resources/bytecode/javFiles/SuperCall.jav b/resources/bytecode/javFiles/SuperCall.jav new file mode 100644 index 00000000..08b8a046 --- /dev/null +++ b/resources/bytecode/javFiles/SuperCall.jav @@ -0,0 +1,11 @@ +import java.lang.Integer; + +class Parent { + public Parent(Integer x) {} +} + +public class SuperCall extends Parent { + public SuperCall() { + super(20); + } +} \ 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 6cd9a3bc..dffcebeb 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java @@ -1382,8 +1382,8 @@ public class Codegen { generate(state, stmts.get(0)); if (constructor.fieldInitializer() != null) { var stmts2 = constructor.fieldInitializer().statements(); - for (var i = 1; i < stmts2.size(); i++) { - generate(state, stmts2.get(i)); + for (TargetExpression expression : stmts2) { + generate(state, expression); } } for (var i = 1; i < stmts.size(); i++) diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index 4514a0f5..39914f0d 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -707,13 +707,19 @@ public class StatementGenerator { } else if (!Objects.isNull(expr.SUPER())) { // if(methodInvocationContext.Identifier() != null){ name = expr.SUPER().getText(); - receiver = new Super(offset); } ArgumentList argumentList = convertArguments(expr.expressionList()); ArrayList signature = argumentList.getArguments().stream().map(x -> (RefTypeOrTPHOrWildcardOrGeneric) TypePlaceholder.fresh(offset)).collect(Collectors.toCollection(ArrayList::new)); signature.add(TypePlaceholder.fresh(offset)); // return type - MethodCall ret = new MethodCall(TypePlaceholder.fresh(offset), getReceiver(receiver), name, argumentList, TypePlaceholder.fresh(offset), signature, offset); + + MethodCall ret; + if (expr.SUPER() != null) { + ret = new SuperCall(argumentList, TypePlaceholder.fresh(offset), signature, offset); + } else { + ret = new MethodCall(TypePlaceholder.fresh(offset), getReceiver(receiver), name, argumentList, TypePlaceholder.fresh(offset), signature, offset); + } + ret.setStatement(); return ret; } @@ -796,7 +802,7 @@ public class StatementGenerator { receiver = new This(offset); isStatic = Modifier.isStatic(fields.get(fieldName).modifiers()); } else if (parts[0].contentEquals("super")) { - receiver = new Super(offset); + receiver = new Super(TypePlaceholder.fresh(offset), offset); isStatic = Modifier.isStatic(compiler.getClass(new JavaClassName(superClass.getName().toString())).getField(fieldName).orElseThrow().modifier); } else if (receiver == null) { // Handelt es sich um keinen Statischen Klassennamen: String part = expression.substring(0, expression.length() - (1 + parts[parts.length - 1].length())); diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java index 895c4ecd..dafc1eca 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java @@ -16,6 +16,7 @@ import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.Record; +import de.dhbwstuttgart.syntaxtree.statement.*; import org.antlr.v4.runtime.CommonToken; import org.antlr.v4.runtime.Token; @@ -66,15 +67,6 @@ import de.dhbwstuttgart.parser.scope.GenericsRegistry; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.parser.scope.JavaClassRegistry; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; -import de.dhbwstuttgart.syntaxtree.statement.Assign; -import de.dhbwstuttgart.syntaxtree.statement.AssignLeftSide; -import de.dhbwstuttgart.syntaxtree.statement.AssignToField; -import de.dhbwstuttgart.syntaxtree.statement.Block; -import de.dhbwstuttgart.syntaxtree.statement.FieldVar; -import de.dhbwstuttgart.syntaxtree.statement.LocalVar; -import de.dhbwstuttgart.syntaxtree.statement.Return; -import de.dhbwstuttgart.syntaxtree.statement.Statement; -import de.dhbwstuttgart.syntaxtree.statement.This; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; @@ -280,8 +272,8 @@ public class SyntaxTreeGenerator { methods.add(new Method(allmodifiers.get("public"), fieldname, fieldtype, new ParameterList(new ArrayList<>(), offset), new Block(Arrays.asList(returnStatement), offset), new GenericDeclarationList(new ArrayList<>(), offset), offset)); } RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), genericClassParameters, offset); - Constructor implicitConstructor = new Constructor(allmodifiers.get("public"), identifier, classType, new ParameterList(constructorParameters, offset), new Block(constructorStatements, offset), genericClassParameters, offset); - Optional initializations = Optional.of(implicitConstructor); + Constructor implicitConstructor = new Constructor(allmodifiers.get("public"), identifier, classType, new ParameterList(constructorParameters, offset), prepareBlock(new Block(constructorStatements, offset), superClass), genericClassParameters, offset); + //Optional initializations = Optional.of(implicitConstructor); constructors.add(implicitConstructor); for (ClassBodyDeclarationContext bodyDeclaration : recordDeclaration.recordBody().classBodyDeclaration()) { convert(bodyDeclaration, fielddecl, constructors, methods, name, superClass, generics); @@ -290,7 +282,7 @@ public class SyntaxTreeGenerator { implementedInterfaces.addAll(convert(recordDeclaration.typeList(), generics)); } var staticCtor = Optional.of(this.generateStaticConstructor(recordDeclaration.identifier().getText(), staticFieldInitializations, genericClassParameters, offset)); - return new Record(modifiers, name, fielddecl, initializations, staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset); + return new Record(modifiers, name, fielddecl, Optional.empty(), staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset); } private void convert(ClassBodyDeclarationContext classBody, List fields, List constructors, List methods, JavaClassName name, RefType superClass, GenericsRegistry generics) { @@ -451,18 +443,24 @@ public class SyntaxTreeGenerator { return new Method(modifiers, name, retType, paramlist, block, gtvDeclarations, bodydeclaration.getStart()); } + protected static Block prepareBlock(Block constructorBlock, RefType superClass) { + List statements = constructorBlock.getStatements(); + if (statements.isEmpty() || !(statements.get(0) instanceof SuperCall)) { + var signature = new ArrayList(); + signature.add(new Void(new NullToken())); + statements.add(0, new SuperCall(superClass, signature, constructorBlock.getOffset())); + } + /* statements.addAll(fieldInitializations); geloescht PL 2018-11-24 */ + return new Block(statements, constructorBlock.getOffset()); + } + /** * http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.9 */ private Constructor generateStandardConstructor(String className, JavaClassName parentClass, RefType superClass, GenericDeclarationList classGenerics, Token offset) { RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset); ParameterList params = new ParameterList(new ArrayList<>(), offset); - Block block = new Block(new ArrayList<>(), offset); - // - // - return new Constructor(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset); // fieldInitializations - // geloescht PL - // 2018-11-24 + return new Constructor(Modifier.PUBLIC, className, classType, params, prepareBlock(new Block(new ArrayList<>(), offset), superClass), classGenerics, offset); // fieldInitializations // 2018-11-24 } /* @@ -471,10 +469,7 @@ public class SyntaxTreeGenerator { private Constructor generatePseudoConstructor(String className, List initializations, GenericDeclarationList classGenerics, Token offset) { RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset); ParameterList params = new ParameterList(new ArrayList<>(), offset); - Block block = new Block(new ArrayList<>(initializations), offset); - return new Constructor(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset /* - * fieldInitializations geloescht PL 2018-11-24 - */); + return new Constructor(Modifier.PUBLIC, className, classType, params, new Block(new ArrayList<>(initializations), offset), classGenerics, offset); } private Method generateStaticConstructor(String className, List initializations, GenericDeclarationList classGenerics, Token offset) { @@ -553,7 +548,7 @@ public class SyntaxTreeGenerator { block = stmtgen.convert(methodblock.block(), true); } if (name.equals(parentClass.getClassName())) { - return new Constructor(modifiers, name, retType, paramlist, block, gtvDeclarations, methoddeclaration.getStart()); + return new Constructor(modifiers, name, retType, paramlist, prepareBlock(block, superClass), gtvDeclarations, methoddeclaration.getStart()); } else { return new Method(modifiers, name, retType, paramlist, block, gtvDeclarations, methoddeclaration.getStart()); } @@ -582,7 +577,7 @@ public class SyntaxTreeGenerator { RefTypeOrTPHOrWildcardOrGeneric retType = TypeGenerator.convertTypeName(name, constructordeclaration.getStart(), reg, localgenerics); StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fields, new HashMap<>()); ParameterList paramlist = stmtgen.convert(constructordeclaration.formalParameters().formalParameterList()); - Block block = stmtgen.convert(constructordeclaration.constructorBody, true); + Block block = prepareBlock(stmtgen.convert(constructordeclaration.constructorBody, true), superClass); return new Constructor(modifiers, name, retType, paramlist, block, gtvDeclarations, constructordeclaration.getStart()); } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/Constructor.java b/src/main/java/de/dhbwstuttgart/syntaxtree/Constructor.java index 1c955c81..1cf3454a 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/Constructor.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/Constructor.java @@ -1,31 +1,25 @@ package de.dhbwstuttgart.syntaxtree; +import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.statement.Statement; +import de.dhbwstuttgart.syntaxtree.statement.Super; import de.dhbwstuttgart.syntaxtree.statement.SuperCall; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.Void; import org.antlr.v4.runtime.Token; import de.dhbwstuttgart.syntaxtree.statement.Block; +import java.sql.Ref; +import java.util.ArrayList; import java.util.List; public class Constructor extends Method { // TODO: Constructor braucht ein super-Statement - public Constructor(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block codeInsideConstructor, GenericDeclarationList gtvDeclarations, Token offset /* , List fieldInitializations geloescht PL 2018-11-24 */) { - super(modifier, name, returnType, parameterList, /* codeInsideConstructor, */ prepareBlock(codeInsideConstructor) /* ,fieldInitializations )geloescht PL 2018-11-24 ) */, gtvDeclarations, offset); - - } - - /** - * @param fieldInitializations - Das sind die Statements, welche die Felder der zugehörigen Klasse dieses Konstruktor initialisieren - */ - protected static Block prepareBlock(Block constructorBlock /* , List fieldInitializations new ArrayList<>() geloescht PL 2018-11-24 */) { - List statements = constructorBlock.getStatements(); - statements.add(0, new SuperCall(null, null, constructorBlock.getOffset())); - /* statements.addAll(fieldInitializations); geloescht PL 2018-11-24 */ - return new Block(statements, constructorBlock.getOffset()); + public Constructor(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block codeInsideConstructor, GenericDeclarationList gtvDeclarations, Token offset) { + super(modifier, name, returnType, parameterList, codeInsideConstructor, gtvDeclarations, offset); } @Override diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java index fdb672fb..e1deca0f 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java @@ -37,6 +37,7 @@ public class MethodCall extends Statement this.receiver = receiver; this.receiverType = receiverType; this.signature = signature; + if (signature == null) throw new NullPointerException(); } public List signatureArguments() { diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Super.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Super.java index fbeba99b..e56e2fe4 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Super.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Super.java @@ -1,6 +1,9 @@ package de.dhbwstuttgart.syntaxtree.statement; +import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation; @@ -9,9 +12,9 @@ import de.dhbwstuttgart.exceptions.NotImplementedException; public class Super extends Expression { - public Super(Token offset) + public Super(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) { - super(null,null); + super(type, offset); } @Override diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java index 3b7eebbf..e4a7ea01 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.syntaxtree.statement; +import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; @@ -9,6 +10,7 @@ import org.antlr.v4.runtime.Token; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; import java.util.ArrayList; +import java.util.List; public class SuperCall extends MethodCall @@ -20,7 +22,7 @@ public class SuperCall extends MethodCall public SuperCall(ArgumentList argumentList, RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList argTypes, Token offset){ - super(new Void(offset), new ExpressionReceiver(new This(offset)), "", argumentList, receiverType, argTypes, offset); + super(new Void(offset), new ExpressionReceiver(new Super(receiverType, offset)), "", argumentList, receiverType, argTypes, offset); } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java b/src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java index 23f08039..7125d3cd 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java @@ -8,6 +8,7 @@ import de.dhbwstuttgart.syntaxtree.TypeScope; import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.typeinference.constraints.GenericsResolver; import java.util.ArrayList; @@ -66,6 +67,7 @@ public class MethodAssumption extends Assumption{ * @return */ public RefTypeOrTPHOrWildcardOrGeneric getReceiverType(GenericsResolver resolver) { + if (receiver == null) return null; List params = new ArrayList<>(); for(GenericTypeVar gtv : receiver.getGenerics()){ //Die Generics werden alle zu TPHs umgewandelt. diff --git a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index ac023831..6920dab2 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -538,7 +538,23 @@ public class TYPEStmt implements StatementVisitor { @Override public void visit(SuperCall superCall) { - // TODO: Für einen super-Call werden keine Constraints erzeugt bisher + Set> methodConstraints = new HashSet<>(); + for (var clazz : info.getAvailableClasses()) { + if (clazz.getClassName().equals(info.getCurrentClass().getSuperClass().getName())) { + for (var ctor : clazz.getConstructors()) { + var assumption = new MethodAssumption(null, new Void(new NullToken()), convertParams(ctor.getParameterList(), info), createTypeScope(clazz, ctor), ctor.isInherited); + + GenericsResolver resolver = getResolverInstance(); + Set> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver); + System.out.println(">>>"); + System.out.println(oneMethodConstraints); + System.out.println("<<<"); + methodConstraints.addAll(oneMethodConstraints); + } + break; + } + } + constraintsSet.addOderConstraint(methodConstraints); } /* @@ -558,10 +574,12 @@ public class TYPEStmt implements StatementVisitor { */ RefTypeOrTPHOrWildcardOrGeneric receiverType = assumption.getReceiverType(resolver); - methodConstraint.add(new Pair(forMethod.receiver.getType(), receiverType, PairOperator.EQUALSDOT));// PL 2020-03-17 SMALLERDOT in EQUALSDOT umgewandelt, weil alle geerbten Methoden in den jeweilen Klassen enthalten sind. + if (receiverType != null) { + methodConstraint.add(new Pair(forMethod.receiver.getType(), receiverType, PairOperator.EQUALSDOT));// PL 2020-03-17 SMALLERDOT in EQUALSDOT umgewandelt, weil alle geerbten Methoden in den jeweilen Klassen enthalten sind. - // PL 2023-01-24: dafuer ? extends receiverType noch ergaenzt - extendsMethodConstraint.add(new Pair(forMethod.receiver.getType(), new ExtendsWildcardType(receiverType, receiverType.getOffset()), PairOperator.EQUALSDOT)); + // PL 2023-01-24: dafuer ? extends receiverType noch ergaenzt + extendsMethodConstraint.add(new Pair(forMethod.receiver.getType(), new ExtendsWildcardType(receiverType, receiverType.getOffset()), PairOperator.EQUALSDOT)); + } // gegenseite Verschraenkung der beiden Mengen von Typannahmen methodConstraint.setExtendConstraint(extendsMethodConstraint); @@ -578,7 +596,8 @@ public class TYPEStmt implements StatementVisitor { // methodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT)); // extendsMethodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT)); - ((TypePlaceholder) forMethod.getType()).setOrCons((byte) -1);// fuer Maximums-Bestimmung + if (forMethod.getType() instanceof TypePlaceholder tph) + tph.setOrCons((byte) -1);// fuer Maximums-Bestimmung Set parameterContraints = generateParameterConstraints(forMethod, assumption, info, resolver); @@ -625,7 +644,6 @@ public class TYPEStmt implements StatementVisitor { } // Zuordnung von MethodCall.signature(ReturnType) zu dem ReturnType der ausgewaehlten Methode (assumption.returnType) - System.out.println(foMethod.name); ret.add(new Pair(foMethod.signature.get(foMethod.signature.size() - 1), assumption.getReturnType(), PairOperator.EQUALSDOT)); return ret; } diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index 1f50d362..34571c82 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -234,7 +234,7 @@ public class TestComplete { } @Test - //@Ignore("This is to complex") + //@Ignore("This is too complex") public void matrixTest() throws Exception { var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Matrix.jav"); var matrix = classFiles.get("Matrix"); @@ -781,4 +781,11 @@ public class TestComplete { var hello = clazz.getDeclaredMethod("hello"); hello.invoke(null); } + + @Test + public void testSuperCall() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "SuperCall.jav"); + var clazz = classFiles.get("SuperCall"); + var instance = clazz.getDeclaredConstructor().newInstance(); + } } From 700ea125fc0dd8c0350805c3a4e7cf9353dec235 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Tue, 30 Jan 2024 15:46:02 +0100 Subject: [PATCH 04/18] Throw different exception --- .../java/de/dhbwstuttgart/parser/scope/JavaClassRegistry.java | 2 +- .../java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/parser/scope/JavaClassRegistry.java b/src/main/java/de/dhbwstuttgart/parser/scope/JavaClassRegistry.java index 670a21db..1ab04244 100644 --- a/src/main/java/de/dhbwstuttgart/parser/scope/JavaClassRegistry.java +++ b/src/main/java/de/dhbwstuttgart/parser/scope/JavaClassRegistry.java @@ -31,7 +31,7 @@ public class JavaClassRegistry { if (name.equals(new JavaClassName(className))) return name; } - throw new NotImplementedException(); + throw new RuntimeException("Class " + className + " not found!"); } @Override diff --git a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index 6920dab2..e1c82e94 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -546,9 +546,6 @@ public class TYPEStmt implements StatementVisitor { GenericsResolver resolver = getResolverInstance(); Set> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver); - System.out.println(">>>"); - System.out.println(oneMethodConstraints); - System.out.println("<<<"); methodConstraints.addAll(oneMethodConstraints); } break; From 9da763b361cb43a71a88e7729614e13b35a199c5 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Wed, 31 Jan 2024 17:27:18 +0100 Subject: [PATCH 05/18] Add instanceof --- resources/bytecode/javFiles/InstanceOf.jav | 26 +++++++++---------- .../de/dhbwstuttgart/bytecode/Codegen.java | 1 + .../typeinference/typeAlgo/TYPEStmt.java | 2 +- src/test/java/TestComplete.java | 11 ++++++++ 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/resources/bytecode/javFiles/InstanceOf.jav b/resources/bytecode/javFiles/InstanceOf.jav index 4cee01f2..e7b1cbd8 100644 --- a/resources/bytecode/javFiles/InstanceOf.jav +++ b/resources/bytecode/javFiles/InstanceOf.jav @@ -1,18 +1,18 @@ -import java.lang.Number; +import java.lang.Object; import java.lang.Integer; -import java.lang.Double; -import java.lang.String; +import java.lang.Boolean; + +interface Interface {} + +class Test implements Interface { +} +class Test2 { +} public class InstanceOf { - main(n) { - if (n instanceof Integer i) { - takes(i); - return "Integer"; - } else if (n instanceof Double d) { - takes(d); - return "Double"; - } - } + a = new Test(); - takes(i) {} // Should be overloaded + test1() { return this.a instanceof Test; } + test2() { return this.a instanceof Interface; } + test3() { return this.a instanceof Integer; } } \ 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 dffcebeb..d7ced3bf 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java @@ -1078,6 +1078,7 @@ public class Codegen { var mv = state.mv; if (instanceOf.right() instanceof TargetTypePattern right && right.name() == null) { + generate(state, instanceOf.left()); mv.visitTypeInsn(INSTANCEOF, right.type().getInternalName()); return; } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index e1c82e94..a776f81c 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -157,7 +157,7 @@ public class TYPEStmt implements StatementVisitor { @Override public void visit(InstanceOf instanceOf) { - //throw new NotImplementedException(); + instanceOf.getExpression().accept(this); } @Override diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index 34571c82..0ab8a7ec 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -788,4 +788,15 @@ public class TestComplete { var clazz = classFiles.get("SuperCall"); var instance = clazz.getDeclaredConstructor().newInstance(); } + + @Test + public void testInstanceOf() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "InstanceOf.jav"); + var clazz = classFiles.get("InstanceOf"); + var instance = clazz.getDeclaredConstructor().newInstance(); + + assertTrue((Boolean) clazz.getDeclaredMethod("test1").invoke(instance)); + assertTrue((Boolean) clazz.getDeclaredMethod("test2").invoke(instance)); + assertFalse((Boolean) clazz.getDeclaredMethod("test3").invoke(instance)); + } } From a0355896475d83615de2ecce6691be6900339418 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Thu, 1 Feb 2024 11:58:08 +0100 Subject: [PATCH 06/18] Implement throw --- resources/bytecode/javFiles/Exceptions.jav | 7 ++++++- .../de/dhbwstuttgart/bytecode/Codegen.java | 5 +++++ .../StatementGenerator.java | 3 +-- .../syntaxtree/AbstractASTWalker.java | 5 +++++ .../syntaxtree/StatementVisitor.java | 2 ++ .../syntaxtree/statement/Throw.java | 21 +++++++++++++++++++ .../syntaxtree/visual/OutputGenerator.java | 5 +++++ .../generate/StatementToTargetExpression.java | 5 +++++ .../generate/TracingStatementVisitor.java | 5 +++++ .../tree/expression/TargetExpression.java | 2 +- .../target/tree/expression/TargetThrow.java | 4 ++++ .../typeinference/typeAlgo/TYPEStmt.java | 5 +++++ src/test/java/TestComplete.java | 19 ++++++++++++++++- 13 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/syntaxtree/statement/Throw.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetThrow.java diff --git a/resources/bytecode/javFiles/Exceptions.jav b/resources/bytecode/javFiles/Exceptions.jav index 9903511c..7b804a6a 100644 --- a/resources/bytecode/javFiles/Exceptions.jav +++ b/resources/bytecode/javFiles/Exceptions.jav @@ -1,3 +1,8 @@ +import java.lang.String; +import java.lang.RuntimeException; + public class Exceptions { -// m(Integer i) throws + m() { + throw new RuntimeException("Some Exception"); + } } \ 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 d7ced3bf..630982b2 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java @@ -1040,6 +1040,11 @@ public class Codegen { mv.visitMethodInsn(INVOKESPECIAL, _new.type().getInternalName(), "", _new.getDescriptor(), false); break; } + case TargetThrow _throw: { + generate(state, _throw.expr()); + mv.visitInsn(ATHROW); + break; + } default: throw new CodeGenException("Unexpected value: " + expr); } diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index 39914f0d..64dad545 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -611,8 +611,7 @@ public class StatementGenerator { } private Statement convert(Java17Parser.ThrowstmtContext stmt) { - // TODO - throw new NotImplementedException(); + return new Throw(convert(stmt.expression()), stmt.getStart()); } private Statement convert(Java17Parser.SynchronizedstmtContext stmt) { diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java b/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java index f8bf0502..fde26cb7 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java @@ -266,6 +266,11 @@ public abstract class AbstractASTWalker implements ASTVisitor { } + @Override + public void visit(Throw aThrow) { + + } + @Override public void visit(AssignToField assignLeftSide) { assignLeftSide.field.accept(this); diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java b/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java index 3cc4e128..c7a6c2a7 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java @@ -76,4 +76,6 @@ public interface StatementVisitor { void visit(UnaryExpr unaryExpr); void visit(Literal literal); + + void visit(Throw aThrow); } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Throw.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Throw.java new file mode 100644 index 00000000..6d91389a --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Throw.java @@ -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); + } +} diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java b/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java index 0e0b7081..e68adda6 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java @@ -407,6 +407,11 @@ public class OutputGenerator implements ASTVisitor { out.append(literal.value); } + @Override + public void visit(Throw aThrow) { + // TODO implement + } + @Override public void visit(Switch switchStmt) { out.append("switch("); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 6eeb784b..c79dd3bb 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -323,6 +323,11 @@ public class StatementToTargetExpression implements ASTVisitor { } } + @Override + public void visit(Throw aThrow) { + result = new TargetThrow(converter.convert(aThrow.expr)); + } + @Override public void visit(Switch switchStmt) { var cases = switchStmt.getBlocks().stream().filter(s -> !s.isDefault()).map(converter::convert).toList(); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java index a84d6322..7967f0c4 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java @@ -173,6 +173,11 @@ public abstract class TracingStatementVisitor implements StatementVisitor { } + @Override + public void visit(Throw aThrow) { + + } + @Override public void visit(Switch switchStmt) { diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java index 76d3976a..e0bbc523 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java @@ -3,7 +3,7 @@ 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, 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() { return null; diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetThrow.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetThrow.java new file mode 100644 index 00000000..080d06a8 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetThrow.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.target.tree.expression; + +public record TargetThrow(TargetExpression expr) implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index a776f81c..5d6ce725 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -456,6 +456,11 @@ public class TYPEStmt implements StatementVisitor { } } + @Override + public void visit(Throw aThrow) { + aThrow.expr.accept(this); + } + @Override public void visit(Return returnExpr) { returnExpr.retexpr.accept(this); diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index 0ab8a7ec..784df1fc 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -1,9 +1,9 @@ import de.dhbwstuttgart.environment.ByteArrayClassLoader; -import de.dhbwstuttgart.syntaxtree.statement.Expression; import org.junit.Ignore; import org.junit.Test; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.util.Arrays; @@ -799,4 +799,21 @@ public class TestComplete { assertTrue((Boolean) clazz.getDeclaredMethod("test2").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!"); + } + } + } } From dcfafe59956e493f4bcd41adb2bddc02b735afc2 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Mon, 5 Feb 2024 14:46:00 +0100 Subject: [PATCH 07/18] Fix null literal --- resources/bytecode/javFiles/Literal.jav | 3 +++ src/main/java/de/dhbwstuttgart/bytecode/Codegen.java | 1 + .../target/generate/StatementToTargetExpression.java | 2 ++ .../target/tree/expression/TargetLiteral.java | 12 ++++++++++++ .../typeinference/typeAlgo/TYPEStmt.java | 3 ++- src/test/java/TestComplete.java | 9 +++++++++ 6 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 resources/bytecode/javFiles/Literal.jav diff --git a/resources/bytecode/javFiles/Literal.jav b/resources/bytecode/javFiles/Literal.jav new file mode 100644 index 00000000..1d081e27 --- /dev/null +++ b/resources/bytecode/javFiles/Literal.jav @@ -0,0 +1,3 @@ +public class Literal { + m() { return null; } +} \ 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 630982b2..aef180d3 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java @@ -806,6 +806,7 @@ public class Codegen { case StringLiteral stringLiteral -> mv.visitLdcInsn(stringLiteral.value()); case CharLiteral charLiteral -> mv.visitIntInsn(BIPUSH, charLiteral.value()); case DoubleLiteral doubleLiteral -> mv.visitLdcInsn(doubleLiteral.value()); + case Null ignored -> mv.visitInsn(ACONST_NULL); case BooleanLiteral booleanLiteral -> { if (booleanLiteral.value()) { mv.visitInsn(ICONST_1); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index c79dd3bb..702432a0 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -320,6 +320,8 @@ public class StatementToTargetExpression implements ASTVisitor { result = new TargetLiteral.StringLiteral((String) literal.value); } else if (literal.value instanceof Boolean) { result = new TargetLiteral.BooleanLiteral((boolean) literal.value); + } else if (literal.value == null) { + result = new TargetLiteral.Null(); } } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLiteral.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLiteral.java index c4673682..c120f966 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLiteral.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLiteral.java @@ -53,4 +53,16 @@ public sealed interface TargetLiteral extends TargetExpression { return TargetType.String; } } + + record Null() implements TargetLiteral { + @Override + public TargetType type() { + return TargetType.Object; + } + + @Override + public Object value() { + return null; + } + } } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index 5d6ce725..440bee30 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -451,7 +451,8 @@ public class TYPEStmt implements StatementVisitor { if (literal.value instanceof Boolean) { constraintsSet.addUndConstraint(new Pair(literal.getType(), bool, PairOperator.EQUALSDOT)); return; - } else { + } + if (literal.value != null) { throw new NotImplementedException(); } } diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index 784df1fc..56dc7aa5 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -816,4 +816,13 @@ public class TestComplete { } } } + + @Test + public void testLiteral() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Literal.jav"); + var clazz = classFiles.get("Literal"); + var instance = clazz.getDeclaredConstructor().newInstance(); + + assertNull(clazz.getDeclaredMethod("m").invoke(instance)); + } } From e88d4428c59491d18074529775c8ce87071cacfb Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Mon, 5 Feb 2024 15:24:06 +0100 Subject: [PATCH 08/18] Fix constructor overloads getting picked with the wrong arity --- resources/bytecode/javFiles/OLConstructor.jav | 17 +++++++++++++++++ .../typeinference/typeAlgo/TYPEStmt.java | 4 +++- src/test/java/TestComplete.java | 8 ++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 resources/bytecode/javFiles/OLConstructor.jav diff --git a/resources/bytecode/javFiles/OLConstructor.jav b/resources/bytecode/javFiles/OLConstructor.jav new file mode 100644 index 00000000..815c80be --- /dev/null +++ b/resources/bytecode/javFiles/OLConstructor.jav @@ -0,0 +1,17 @@ +import java.lang.Integer; + +public class Parent { + public Integer x; + + public Parent(Integer a) { + this.x = a; + } + + public Parent() {} +} + +class Child extends Parent { + Child() { + super(3); + } +} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index 440bee30..c49eceaf 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -548,7 +548,9 @@ public class TYPEStmt implements StatementVisitor { for (var clazz : info.getAvailableClasses()) { if (clazz.getClassName().equals(info.getCurrentClass().getSuperClass().getName())) { for (var ctor : clazz.getConstructors()) { - var assumption = new MethodAssumption(null, new Void(new NullToken()), convertParams(ctor.getParameterList(), info), createTypeScope(clazz, ctor), ctor.isInherited); + var params = convertParams(ctor.getParameterList(), info); + if (params.size() != superCall.arglist.getArguments().size()) continue; + var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(clazz, ctor), ctor.isInherited); GenericsResolver resolver = getResolverInstance(); Set> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver); diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index 56dc7aa5..cd396155 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -825,4 +825,12 @@ public class TestComplete { assertNull(clazz.getDeclaredMethod("m").invoke(instance)); } + + @Test + public void testOLConstructor() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "OLConstructor.jav"); + var clazz = classFiles.get("Child"); + var instance = clazz.getDeclaredConstructor().newInstance(); + assertEquals(clazz.getSuperclass().getDeclaredField("x").get(instance), 3); + } } From 75b9020cf93ad9c97d6890b42acb02511262cc11 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Mon, 26 Feb 2024 15:02:15 +0100 Subject: [PATCH 09/18] Fix up Character --- resources/bytecode/javFiles/Literal.jav | 3 +++ src/main/java/de/dhbwstuttgart/bytecode/Codegen.java | 4 ++-- .../de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java | 2 +- .../de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java | 6 ++++++ src/test/java/TestComplete.java | 1 + 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/resources/bytecode/javFiles/Literal.jav b/resources/bytecode/javFiles/Literal.jav index 1d081e27..52e1c8c9 100644 --- a/resources/bytecode/javFiles/Literal.jav +++ b/resources/bytecode/javFiles/Literal.jav @@ -1,3 +1,6 @@ +import java.lang.Character; + public class Literal { m() { return null; } + m2() { return 'C'; } } \ 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 aef180d3..7c06ee8d 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java @@ -136,7 +136,7 @@ public class Codegen { } else if (type.equals(TargetType.Short) || type.equals(TargetType.short_)) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false); } else if (type.equals(TargetType.Char) || type.equals(TargetType.char_)) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Char", "valueOf", "(C)Ljava/lang/Char;", false); + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false); } } @@ -157,7 +157,7 @@ public class Codegen { } else if (type.equals(TargetType.Short)) { mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false); } else if (type.equals(TargetType.Char)) { - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Char", "charValue", "()C", false); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false); } } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java index 48c4830d..308cf9a2 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java @@ -361,7 +361,7 @@ public class ASTFactory { } else if (type.getTypeName().equals("boolean")) { return new RefType(new JavaClassName("java.lang.Boolean"), new ArrayList<>(), new NullToken(), true); } else if (type.getTypeName().equals("char")) { - return new RefType(new JavaClassName("java.lang.Char"), new ArrayList<>(), new NullToken(), true); + return new RefType(new JavaClassName("java.lang.Character"), new ArrayList<>(), new NullToken(), true); } else if (type.getTypeName().equals("short")) { return new RefType(new JavaClassName("java.lang.Short"), new ArrayList<>(), new NullToken(), true); } else if (type.getTypeName().equals("double")) { diff --git a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index c49eceaf..3e0012f1 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -226,6 +226,8 @@ public class TYPEStmt implements StatementVisitor { private final RefType doublee = new RefType(ASTFactory.createClass(Double.class).getClassName(), new NullToken()); private final RefType string = new RefType(ASTFactory.createClass(String.class).getClassName(), new NullToken()); private final RefType bool = new RefType(ASTFactory.createClass(Boolean.class).getClassName(), new NullToken()); + + private final RefType charr = new RefType(ASTFactory.createClass(Character.class).getClassName(), new NullToken()); @Override public void visit(UnaryExpr unaryExpr) { @@ -452,6 +454,10 @@ public class TYPEStmt implements StatementVisitor { constraintsSet.addUndConstraint(new Pair(literal.getType(), bool, PairOperator.EQUALSDOT)); return; } + if (literal.value instanceof Character) { + constraintsSet.addUndConstraint(new Pair(literal.getType(), charr, PairOperator.EQUALSDOT)); + return; + } if (literal.value != null) { throw new NotImplementedException(); } diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index cd396155..ff857464 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -824,6 +824,7 @@ public class TestComplete { var instance = clazz.getDeclaredConstructor().newInstance(); assertNull(clazz.getDeclaredMethod("m").invoke(instance)); + assertEquals(clazz.getDeclaredMethod("m2").invoke(instance), 'C'); } @Test From a60282414cf3a00c069976b3a58dba2969697293 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Tue, 27 Feb 2024 16:25:47 +0100 Subject: [PATCH 10/18] Add location information to constraints --- .../SyntaxTreeGenerator/FCGenerator.java | 2 +- .../syntaxtree/factory/UnifyTypeFactory.java | 27 ++-- .../typeinference/constraints/Pair.java | 16 ++- .../typeinference/typeAlgo/TYPEStmt.java | 136 +++++++++--------- .../typeinference/unify/model/UnifyPair.java | 28 +++- 5 files changed, 121 insertions(+), 88 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java index f219c196..e864200f 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java @@ -60,7 +60,7 @@ public class FCGenerator { .collect(Collectors.toList())); tl.add(m.getReturnType().acceptTV(new TypeExchanger(gtvs))); return new Pair(new RefType(new JavaClassName("Fun" + (tl.size()-1) + "$$"), tl, new NullToken()), - fIType); + fIType, PairOperator.SMALLER); } return null; //kann nicht passieren, da die Methode nur aufgerufen wird wenn cl Functional Interface ist } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java index 92b72ec4..785ef52a 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java @@ -1,6 +1,5 @@ package de.dhbwstuttgart.syntaxtree.factory; -import java.io.FileWriter; import java.io.Writer; import java.util.*; import java.util.regex.Matcher; @@ -15,7 +14,6 @@ import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.syntaxtree.type.WildcardType; -import de.dhbwstuttgart.typeinference.constraints.Constraint; import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; import de.dhbwstuttgart.typeinference.constraints.Pair; import de.dhbwstuttgart.typeinference.result.PairNoResult; @@ -24,6 +22,7 @@ import de.dhbwstuttgart.typeinference.result.PairTPHequalRefTypeOrWildcardType; import de.dhbwstuttgart.typeinference.result.PairTPHsmallerTPH; import de.dhbwstuttgart.typeinference.result.ResultPair; import de.dhbwstuttgart.typeinference.unify.model.*; +import org.antlr.v4.runtime.Token; public class UnifyTypeFactory { @@ -43,20 +42,20 @@ public class UnifyTypeFactory { return new FiniteClosure(FCGenerator.toUnifyFC(fromClasses, classLoader), logFile); } - public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr){ - return new UnifyPair(tl, tr, PairOperator.SMALLER); + public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr, Token location){ + return new UnifyPair(tl, tr, PairOperator.SMALLER, location); } - public static UnifyPair generateSmallerDotPair(UnifyType tl, UnifyType tr){ - return new UnifyPair(tl, tr, PairOperator.SMALLERDOT); + public static UnifyPair generateSmallerDotPair(UnifyType tl, UnifyType tr, Token location){ + return new UnifyPair(tl, tr, PairOperator.SMALLERDOT, location); } - public static UnifyPair generateSmallNotEqualDotPair(UnifyType tl, UnifyType tr){ - return new UnifyPair(tl, tr, PairOperator.SMALLERNEQDOT); + public static UnifyPair generateSmallNotEqualDotPair(UnifyType tl, UnifyType tr, Token location){ + return new UnifyPair(tl, tr, PairOperator.SMALLERNEQDOT, location); } - public static UnifyPair generateEqualDotPair(UnifyType tl, UnifyType tr){ - return new UnifyPair(tl, tr, PairOperator.EQUALSDOT); + public static UnifyPair generateEqualDotPair(UnifyType tl, UnifyType tr, Token location){ + return new UnifyPair(tl, tr, PairOperator.EQUALSDOT, location); } /** @@ -164,19 +163,19 @@ public class UnifyTypeFactory { UnifyPair ret = null; if(p.GetOperator().equals(PairOperator.SMALLERDOT)) { ret = generateSmallerDotPair(UnifyTypeFactory.convert(p.TA1, false) - , UnifyTypeFactory.convert(p.TA2, false)); + , UnifyTypeFactory.convert(p.TA2, false), p.getLocation()); //return ret; }else if(p.GetOperator().equals(PairOperator.SMALLERNEQDOT)) { ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(p.TA1, false) - , UnifyTypeFactory.convert(p.TA2, false)); + , UnifyTypeFactory.convert(p.TA2, false), p.getLocation()); //return ret; }else if(p.GetOperator().equals(PairOperator.EQUALSDOT)) { ret = generateEqualDotPair(UnifyTypeFactory.convert(p.TA1, false) - , UnifyTypeFactory.convert(p.TA2, false)); + , UnifyTypeFactory.convert(p.TA2, false), p.getLocation()); //return ret; }else if(p.GetOperator().equals(PairOperator.SMALLER)){ ret = generateSmallerPair(UnifyTypeFactory.convert(p.TA1, false), - UnifyTypeFactory.convert(p.TA2, false)); + UnifyTypeFactory.convert(p.TA2, false), p.getLocation()); }else throw new NotImplementedException(); UnifyType lhs, rhs; if (((lhs = ret.getLhsType()) instanceof PlaceholderType) diff --git a/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java b/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java index 78513531..2a4fac90 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java @@ -3,9 +3,11 @@ import java.io.Serializable; import java.util.HashMap; import java.util.Map; +import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import org.antlr.v4.runtime.Token; public class Pair implements Serializable @@ -13,11 +15,13 @@ public class Pair implements Serializable public final RefTypeOrTPHOrWildcardOrGeneric TA1; public final RefTypeOrTPHOrWildcardOrGeneric TA2; + private Token location; + private PairOperator eOperator = PairOperator.SMALLER; private Boolean noUnification = false; - public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2 ) + private Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2 ) { this.TA1 = TA1; this.TA2 = TA2; @@ -32,7 +36,11 @@ public class Pair implements Serializable this(TA1,TA2); this.eOperator = eOp; } - + + public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator e0p, Token location) { + this(TA1, TA2, e0p); + this.location = location; + } public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator eOp, Boolean noUnification) { @@ -41,6 +49,10 @@ public class Pair implements Serializable this.eOperator = eOp; this.noUnification = noUnification; } + + public Token getLocation() { + return this.location; + } public String toString() { diff --git a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index 3e0012f1..a21aba1d 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -71,8 +71,8 @@ public class TYPEStmt implements StatementVisitor { // lambdaParams.add(0,tphRetType); constraintsSet.addUndConstraint(new Pair(lambdaExpression.getType(), new RefType(new JavaClassName("Fun" + (lambdaParams.size() - 1) + "$$"), lambdaParams, new NullToken()), // new FunN(lambdaParams), - PairOperator.EQUALSDOT)); - constraintsSet.addUndConstraint(new Pair(lambdaExpression.getReturnType(), tphRetType, PairOperator.EQUALSDOT)); + PairOperator.EQUALSDOT, lambdaExpression.getOffset())); + constraintsSet.addUndConstraint(new Pair(lambdaExpression.getReturnType(), tphRetType, PairOperator.EQUALSDOT, lambdaExpression.getOffset())); // Constraints des Bodys generieren: TYPEStmt lambdaScope = new TYPEStmt(new TypeInferenceBlockInformation(info, lambdaExpression)); @@ -84,7 +84,7 @@ public class TYPEStmt implements StatementVisitor { public void visit(Assign assign) { assign.lefSide.accept(this); assign.rightSide.accept(this); - constraintsSet.addUndConstraint(new Pair(assign.rightSide.getType(), assign.lefSide.getType(), PairOperator.SMALLERDOT)); + constraintsSet.addUndConstraint(new Pair(assign.rightSide.getType(), assign.lefSide.getType(), PairOperator.SMALLERDOT, assign.getOffset())); } @Override @@ -111,8 +111,8 @@ public class TYPEStmt implements StatementVisitor { for (FieldAssumption fieldAssumption : info.getFields(fieldVar.fieldVarName)) { Constraint constraint = new Constraint(); GenericsResolver resolver = getResolverInstance(); - constraint.add(new Pair(fieldVar.receiver.getType(), fieldAssumption.getReceiverType(resolver), PairOperator.SMALLERDOT)); // PL 2019-12-09: SMALLERDOT eingefuegt, EQUALSDOT entfernt, wenn ds Field privat ist muesste es EQUALSDOT lauten - constraint.add(new Pair(fieldVar.getType(), fieldAssumption.getType(resolver), PairOperator.EQUALSDOT)); + constraint.add(new Pair(fieldVar.receiver.getType(), fieldAssumption.getReceiverType(resolver), PairOperator.SMALLERDOT, fieldVar.getOffset())); // PL 2019-12-09: SMALLERDOT eingefuegt, EQUALSDOT entfernt, wenn ds Field privat ist muesste es EQUALSDOT lauten + constraint.add(new Pair(fieldVar.getType(), fieldAssumption.getType(resolver), PairOperator.EQUALSDOT, fieldVar.getOffset())); oderConstraints.add(constraint); } if (oderConstraints.size() == 0) @@ -131,7 +131,7 @@ public class TYPEStmt implements StatementVisitor { @Override public void visit(ForEachStmt forEachStmt) { var iterableType = new RefType(ASTFactory.createClass(java.lang.Iterable.class).getClassName(), Arrays.asList(forEachStmt.statement.getType()), new NullToken()); - constraintsSet.addUndConstraint(new Pair(forEachStmt.expression.getType(), iterableType, PairOperator.SMALLERDOT)); + constraintsSet.addUndConstraint(new Pair(forEachStmt.expression.getType(), iterableType, PairOperator.SMALLERDOT, forEachStmt.getOffset())); forEachStmt.statement.accept(this); forEachStmt.expression.accept(this); forEachStmt.block.accept(this); @@ -143,14 +143,14 @@ public class TYPEStmt implements StatementVisitor { // Expression inferieren: ifStmt.expr.accept(this); // Expression muss boolean sein: - constraintsSet.addUndConstraint(new Pair(ifStmt.expr.getType(), booleanType, PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(ifStmt.expr.getType(), booleanType, PairOperator.EQUALSDOT, ifStmt.getOffset())); // 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)); if (ifStmt.else_block != null) { ifStmt.else_block.accept(this); - constraintsSet.addUndConstraint(new Pair(ifStmt.else_block.getType(), ifStmt.getType(), PairOperator.SMALLERDOT)); + constraintsSet.addUndConstraint(new Pair(ifStmt.else_block.getType(), ifStmt.getType(), PairOperator.SMALLERDOT, ifStmt.getOffset())); } } @@ -234,9 +234,9 @@ public class TYPEStmt implements StatementVisitor { if (unaryExpr.operation == UnaryExpr.Operation.POSTDECREMENT || unaryExpr.operation == UnaryExpr.Operation.POSTINCREMENT || unaryExpr.operation == UnaryExpr.Operation.PREDECREMENT || unaryExpr.operation == UnaryExpr.Operation.PREINCREMENT) { // @see: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.14.2 // Expression muss zu Numeric Convertierbar sein. also von Numeric erben - constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), number, PairOperator.SMALLERNEQDOT)); + constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), number, PairOperator.SMALLERNEQDOT, unaryExpr.getOffset())); // The type of the postfix increment expression is the type of the variable - constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), unaryExpr.getType(), PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), unaryExpr.getType(), PairOperator.EQUALSDOT, unaryExpr.getOffset())); } else { throw new NotImplementedException(); } @@ -263,49 +263,49 @@ public class TYPEStmt implements StatementVisitor { // PL eingefuegt 2018-07-17 if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(bytee.getName())) { numeric = new Constraint<>(); - numeric.add(new Pair(binary.lexpr.getType(), bytee, PairOperator.SMALLERDOT)); - numeric.add(new Pair(binary.rexpr.getType(), bytee, PairOperator.SMALLERDOT)); - numeric.add(new Pair(binary.getType(), integer, PairOperator.EQUALSDOT)); + numeric.add(new Pair(binary.lexpr.getType(), bytee, PairOperator.SMALLERDOT, binary.getOffset())); + numeric.add(new Pair(binary.rexpr.getType(), bytee, PairOperator.SMALLERDOT, binary.getOffset())); + numeric.add(new Pair(binary.getType(), integer, PairOperator.EQUALSDOT, binary.getOffset())); numericAdditionOrStringConcatenation.add(numeric); } // PL eingefuegt 2018-07-17 if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(shortt.getName())) { numeric = new Constraint<>(); - numeric.add(new Pair(binary.lexpr.getType(), shortt, PairOperator.SMALLERDOT)); - numeric.add(new Pair(binary.rexpr.getType(), shortt, PairOperator.SMALLERDOT)); - numeric.add(new Pair(binary.getType(), integer, PairOperator.EQUALSDOT)); + numeric.add(new Pair(binary.lexpr.getType(), shortt, PairOperator.SMALLERDOT, binary.getOffset())); + numeric.add(new Pair(binary.rexpr.getType(), shortt, PairOperator.SMALLERDOT, binary.getOffset())); + numeric.add(new Pair(binary.getType(), integer, PairOperator.EQUALSDOT, binary.getOffset())); numericAdditionOrStringConcatenation.add(numeric); } // PL eingefuegt 2018-07-17 if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(integer.getName())) { numeric = new Constraint<>(); - numeric.add(new Pair(binary.lexpr.getType(), integer, PairOperator.SMALLERDOT)); - numeric.add(new Pair(binary.rexpr.getType(), integer, PairOperator.SMALLERDOT)); - numeric.add(new Pair(integer, binary.getType(), PairOperator.EQUALSDOT)); + numeric.add(new Pair(binary.lexpr.getType(), integer, PairOperator.SMALLERDOT, binary.getOffset())); + numeric.add(new Pair(binary.rexpr.getType(), integer, PairOperator.SMALLERDOT, binary.getOffset())); + numeric.add(new Pair(integer, binary.getType(), PairOperator.EQUALSDOT, binary.getOffset())); numericAdditionOrStringConcatenation.add(numeric); } // PL eingefuegt 2018-07-17 if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(longg.getName())) { numeric = new Constraint<>(); - numeric.add(new Pair(binary.lexpr.getType(), longg, PairOperator.SMALLERDOT)); - numeric.add(new Pair(binary.rexpr.getType(), longg, PairOperator.SMALLERDOT)); - numeric.add(new Pair(longg, binary.getType(), PairOperator.EQUALSDOT)); + numeric.add(new Pair(binary.lexpr.getType(), longg, PairOperator.SMALLERDOT, binary.getOffset())); + numeric.add(new Pair(binary.rexpr.getType(), longg, PairOperator.SMALLERDOT, binary.getOffset())); + numeric.add(new Pair(longg, binary.getType(), PairOperator.EQUALSDOT, binary.getOffset())); numericAdditionOrStringConcatenation.add(numeric); } // PL eingefuegt 2018-07-17 if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(floatt.getName())) { numeric = new Constraint<>(); - numeric.add(new Pair(binary.lexpr.getType(), floatt, PairOperator.SMALLERDOT)); - numeric.add(new Pair(binary.rexpr.getType(), floatt, PairOperator.SMALLERDOT)); - numeric.add(new Pair(floatt, binary.getType(), PairOperator.EQUALSDOT)); + numeric.add(new Pair(binary.lexpr.getType(), floatt, PairOperator.SMALLERDOT, binary.getOffset())); + numeric.add(new Pair(binary.rexpr.getType(), floatt, PairOperator.SMALLERDOT, binary.getOffset())); + numeric.add(new Pair(floatt, binary.getType(), PairOperator.EQUALSDOT, binary.getOffset())); numericAdditionOrStringConcatenation.add(numeric); } // PL eingefuegt 2018-07-17 if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(doublee.getName())) { numeric = new Constraint<>(); - numeric.add(new Pair(binary.lexpr.getType(), doublee, PairOperator.SMALLERDOT)); - numeric.add(new Pair(binary.rexpr.getType(), doublee, PairOperator.SMALLERDOT)); - numeric.add(new Pair(doublee, binary.getType(), PairOperator.EQUALSDOT)); + numeric.add(new Pair(binary.lexpr.getType(), doublee, PairOperator.SMALLERDOT, binary.getOffset())); + numeric.add(new Pair(binary.rexpr.getType(), doublee, PairOperator.SMALLERDOT, binary.getOffset())); + numeric.add(new Pair(doublee, binary.getType(), PairOperator.EQUALSDOT, binary.getOffset())); numericAdditionOrStringConcatenation.add(numeric); } /* @@ -318,9 +318,9 @@ public class TYPEStmt implements StatementVisitor { // Dann kann der Ausdruck auch das aneinanderfügen zweier Strings sein: ("a" + "b") oder (1 + 2) if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(string.getName())) { Constraint stringConcat = new Constraint<>(); - stringConcat.add(new Pair(binary.lexpr.getType(), string, PairOperator.EQUALSDOT)); - stringConcat.add(new Pair(binary.rexpr.getType(), string, PairOperator.EQUALSDOT)); - stringConcat.add(new Pair(string, binary.getType(), PairOperator.EQUALSDOT)); + stringConcat.add(new Pair(binary.lexpr.getType(), string, PairOperator.EQUALSDOT, binary.getOffset())); + stringConcat.add(new Pair(binary.rexpr.getType(), string, PairOperator.EQUALSDOT, binary.getOffset())); + stringConcat.add(new Pair(string, binary.getType(), PairOperator.EQUALSDOT, binary.getOffset())); numericAdditionOrStringConcatenation.add(stringConcat); } } @@ -339,10 +339,10 @@ public class TYPEStmt implements StatementVisitor { */ // Testeise eingefuegt PL 2018-05-24 // Hier sollte evtl. noch importe angefragt werden PL 2019-05-07 - constraintsSet.addUndConstraint(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERNEQDOT)); - constraintsSet.addUndConstraint(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERNEQDOT)); + constraintsSet.addUndConstraint(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERNEQDOT, binary.getOffset())); + constraintsSet.addUndConstraint(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERNEQDOT, binary.getOffset())); // Rückgabetyp ist Boolean - constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT, binary.getOffset())); // auskommentiert PL 2018-05-24 // constraintsSet.addUndConstraint(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERDOT)); @@ -354,7 +354,7 @@ public class TYPEStmt implements StatementVisitor { * Auszug aus https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.21 The equality operators may be used to compare two operands that are convertible (§5.1.8) to numeric type, or two operands of type boolean or Boolean, or two operands that are each of either reference type or the null type. All other cases result in a compile-time error. */ // Der Equals Operator geht mit fast allen Typen, daher werden hier keine Constraints gesetzt - constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT, binary.getOffset())); } else { throw new NotImplementedException(); } @@ -363,9 +363,9 @@ public class TYPEStmt implements StatementVisitor { @Override public void visit(BoolExpression expr) { - constraintsSet.addUndConstraint(new Pair(bool, expr.getType(), PairOperator.EQUALSDOT)); - constraintsSet.addUndConstraint(new Pair(bool, expr.lexpr.getType(), PairOperator.EQUALSDOT)); - constraintsSet.addUndConstraint(new Pair(bool, expr.rexpr.getType(), PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(bool, expr.getType(), PairOperator.EQUALSDOT, expr.getOffset())); + constraintsSet.addUndConstraint(new Pair(bool, expr.lexpr.getType(), PairOperator.EQUALSDOT, expr.getOffset())); + constraintsSet.addUndConstraint(new Pair(bool, expr.rexpr.getType(), PairOperator.EQUALSDOT, expr.getOffset())); // TODO return; @@ -378,23 +378,23 @@ public class TYPEStmt implements StatementVisitor { // wie hier fuer double gezeigt. Im Momment auskommentiert, weil zu wenige Literaltypen // funktionieren if (literal.value instanceof Short) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), shortt, PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(literal.getType(), shortt, PairOperator.EQUALSDOT, literal.getOffset())); return; } if (literal.value instanceof Byte) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT, literal.getOffset())); return; } if (literal.value instanceof Float) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), floatt, PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(literal.getType(), floatt, PairOperator.EQUALSDOT, literal.getOffset())); return; } if (literal.value instanceof Double) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), doublee, PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(literal.getType(), doublee, PairOperator.EQUALSDOT, literal.getOffset())); return; } if (literal.value instanceof Long) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), longg, PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(literal.getType(), longg, PairOperator.EQUALSDOT, literal.getOffset())); return; } if (literal.value instanceof Integer) { @@ -403,31 +403,31 @@ public class TYPEStmt implements StatementVisitor { HashSet clNames = info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)); Set oderConstraints = new HashSet<>(); Constraint constraint = new Constraint(); - constraint.add(new Pair(literal.getType(), integer, PairOperator.EQUALSDOT)); + constraint.add(new Pair(literal.getType(), integer, PairOperator.EQUALSDOT, literal.getOffset())); oderConstraints.add(constraint); if (clNames.stream().filter(x -> x.toString().equals("java.lang.Double")).findAny().isPresent()) { constraint = new Constraint(); - constraint.add(new Pair(literal.getType(), doublee, PairOperator.EQUALSDOT)); + constraint.add(new Pair(literal.getType(), doublee, PairOperator.EQUALSDOT, literal.getOffset())); oderConstraints.add(constraint); } if (clNames.stream().filter(x -> x.toString().equals("java.lang.Long")).findAny().isPresent()) { constraint = new Constraint(); - constraint.add(new Pair(literal.getType(), longg, PairOperator.EQUALSDOT)); + constraint.add(new Pair(literal.getType(), longg, PairOperator.EQUALSDOT, literal.getOffset())); oderConstraints.add(constraint); } if (clNames.stream().filter(x -> x.toString().equals("java.lang.Float")).findAny().isPresent()) { constraint = new Constraint(); - constraint.add(new Pair(literal.getType(), floatt, PairOperator.EQUALSDOT)); + constraint.add(new Pair(literal.getType(), floatt, PairOperator.EQUALSDOT, literal.getOffset())); oderConstraints.add(constraint); } if (clNames.stream().filter(x -> x.toString().equals("java.lang.Short")).findAny().isPresent()) { constraint = new Constraint(); - constraint.add(new Pair(literal.getType(), shortt, PairOperator.EQUALSDOT)); + constraint.add(new Pair(literal.getType(), shortt, PairOperator.EQUALSDOT, literal.getOffset())); oderConstraints.add(constraint); } if (clNames.stream().filter(x -> x.toString().equals("java.lang.Byte")).findAny().isPresent()) { constraint = new Constraint(); - constraint.add(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT)); + constraint.add(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT, literal.getOffset())); oderConstraints.add(constraint); } constraintsSet.addOderConstraint(oderConstraints); @@ -435,27 +435,27 @@ public class TYPEStmt implements StatementVisitor { return; } if (literal.value instanceof Short) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), shortt, PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(literal.getType(), shortt, PairOperator.EQUALSDOT, literal.getOffset())); return; } if (literal.value instanceof Byte) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT, literal.getOffset())); return; } if (literal.value instanceof Float) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), floatt, PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(literal.getType(), floatt, PairOperator.EQUALSDOT, literal.getOffset())); return; } if (literal.value instanceof String) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), string, PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(literal.getType(), string, PairOperator.EQUALSDOT, literal.getOffset())); return; } if (literal.value instanceof Boolean) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), bool, PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(literal.getType(), bool, PairOperator.EQUALSDOT, literal.getOffset())); return; } if (literal.value instanceof Character) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), charr, PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(literal.getType(), charr, PairOperator.EQUALSDOT, literal.getOffset())); return; } if (literal.value != null) { @@ -471,7 +471,7 @@ public class TYPEStmt implements StatementVisitor { @Override public void visit(Return returnExpr) { returnExpr.retexpr.accept(this); - constraintsSet.addUndConstraint(new Pair(returnExpr.getType(), info.getCurrentTypeScope().getReturnType(), PairOperator.SMALLERDOT)); + constraintsSet.addUndConstraint(new Pair(returnExpr.getType(), info.getCurrentTypeScope().getReturnType(), PairOperator.SMALLERDOT, returnExpr.getOffset())); } @Override @@ -503,7 +503,7 @@ public class TYPEStmt implements StatementVisitor { params.add(new GenericRefType(gtv.getName(), aThis.getOffset())); } RefType thisType = new RefType(currentClass.getClassName(), params, aThis.getOffset()); - constraintsSet.addUndConstraint(new Pair(aThis.getType(), thisType, PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(aThis.getType(), thisType, PairOperator.EQUALSDOT, aThis.getOffset())); } private static TypeScope createNullTypeScope() { @@ -526,7 +526,7 @@ public class TYPEStmt implements StatementVisitor { // Expression inferieren: whileStmt.expr.accept(this); // Expression muss boolean sein: - constraintsSet.addUndConstraint(new Pair(whileStmt.expr.getType(), booleanType, PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(whileStmt.expr.getType(), booleanType, PairOperator.EQUALSDOT, whileStmt.expr.getOffset())); // LoopBlock inferieren: whileStmt.loopBlock.accept(this); } @@ -586,10 +586,10 @@ public class TYPEStmt implements StatementVisitor { RefTypeOrTPHOrWildcardOrGeneric receiverType = assumption.getReceiverType(resolver); if (receiverType != null) { - methodConstraint.add(new Pair(forMethod.receiver.getType(), receiverType, PairOperator.EQUALSDOT));// PL 2020-03-17 SMALLERDOT in EQUALSDOT umgewandelt, weil alle geerbten Methoden in den jeweilen Klassen enthalten sind. + methodConstraint.add(new Pair(forMethod.receiver.getType(), receiverType, PairOperator.EQUALSDOT, forMethod.getOffset()));// PL 2020-03-17 SMALLERDOT in EQUALSDOT umgewandelt, weil alle geerbten Methoden in den jeweilen Klassen enthalten sind. // PL 2023-01-24: dafuer ? extends receiverType noch ergaenzt - extendsMethodConstraint.add(new Pair(forMethod.receiver.getType(), new ExtendsWildcardType(receiverType, receiverType.getOffset()), PairOperator.EQUALSDOT)); + extendsMethodConstraint.add(new Pair(forMethod.receiver.getType(), new ExtendsWildcardType(receiverType, receiverType.getOffset()), PairOperator.EQUALSDOT, forMethod.getOffset())); } // gegenseite Verschraenkung der beiden Mengen von Typannahmen @@ -601,8 +601,8 @@ public class TYPEStmt implements StatementVisitor { // PairOperator.EQUALSDOT)); // Fuer Bytecodegenerierung PL 2020-03-09 wird derzeit nicht benutzt ENDE - methodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.SMALLERDOT)); - extendsMethodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.SMALLERDOT)); + methodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.SMALLERDOT, forMethod.getOffset())); + extendsMethodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.SMALLERDOT, forMethod.getOffset())); // methodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT)); // extendsMethodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT)); @@ -635,7 +635,7 @@ public class TYPEStmt implements StatementVisitor { RefTypeOrTPHOrWildcardOrGeneric argType = foMethod.arglist.getArguments().get(i).getType(); RefTypeOrTPHOrWildcardOrGeneric assType = assumption.getArgTypes(resolver).get(i); - ret.add(new Pair(argType, assType, PairOperator.SMALLERDOT)); + ret.add(new Pair(argType, assType, PairOperator.SMALLERDOT, foMethod.getOffset())); // Fuer Bytecodegenerierung PL 2020-03-09 wird derzeit nicht benutzt ANFANG // ret.add(new Pair(foMethod.argTypes.get(i), assType, PairOperator.EQUALSDOT)); @@ -729,7 +729,7 @@ public class TYPEStmt implements StatementVisitor { Constraint methodConstraint = new Constraint(); // WELCHEN SINN MACHT DIESER CONSTRAINT??? // Ist er nicht immer classname <. classname und damit redundant? - methodConstraint.add(new Pair(assumption.getReturnType(resolver), forConstructor.getType(), PairOperator.SMALLERDOT)); + methodConstraint.add(new Pair(assumption.getReturnType(resolver), forConstructor.getType(), PairOperator.SMALLERDOT, forConstructor.getOffset())); // WELCHEN SINN MACHT DIESER CONSTRAINT??? methodConstraint.addAll(generateParameterConstraints(forConstructor, assumption, info, resolver)); return methodConstraint; @@ -753,17 +753,17 @@ public class TYPEStmt implements StatementVisitor { for (var child : switchStmt.getBlocks()) { for (var label : child.getLabels()) { if (label.getPattern() instanceof FormalParameter) { - constraintsSet.addUndConstraint(new Pair(label.getPattern().getType(), switchStmt.getSwitch().getType(), PairOperator.SMALLERDOT)); + constraintsSet.addUndConstraint(new Pair(label.getPattern().getType(), switchStmt.getSwitch().getType(), PairOperator.SMALLERDOT, label.getOffset())); } } } } else { - constraintsSet.addUndConstraint(new Pair(caseExpressionType, switchStmt.getSwitch().getType(), PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(caseExpressionType, switchStmt.getSwitch().getType(), PairOperator.EQUALSDOT, switchStmt.getSwitch().getOffset())); } for (var child : switchStmt.getBlocks()) { child.accept(this); - constraintsSet.addUndConstraint(new Pair(child.getType(), switchStmt.getType(), PairOperator.SMALLERDOT)); + constraintsSet.addUndConstraint(new Pair(child.getType(), switchStmt.getType(), PairOperator.SMALLERDOT, switchStmt.getOffset())); } switchStack.pop(); @@ -784,7 +784,7 @@ public class TYPEStmt implements StatementVisitor { @Override public void visit(Yield aYield) { aYield.retexpr.accept(this); - constraintsSet.addUndConstraint(new Pair(aYield.getType(), switchStack.peek().getType(), PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(aYield.getType(), switchStack.peek().getType(), PairOperator.EQUALSDOT, aYield.getOffset())); // TODO Auto-generated method stub } } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java index 497fd811..ab2be5ec 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java @@ -1,5 +1,8 @@ package de.dhbwstuttgart.typeinference.unify.model; +import com.google.common.collect.ObjectArrays; +import org.antlr.v4.runtime.Token; + import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; @@ -13,6 +16,8 @@ import java.util.Set; * @author Florian Steurer */ public class UnifyPair { + + private Token location; /** * The type on the left hand side of the pair. @@ -63,10 +68,15 @@ public class UnifyPair { this.rhs = rhs; pairOp = op; substitution = new HashSet<>(); - + // Caching hashcode hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode(); - } + } + + public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, Token location) { + this(lhs, rhs, op); + this.location = location; + } public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, Set uni, UnifyPair base) { this.lhs = lhs; @@ -85,6 +95,12 @@ public class UnifyPair { this.fBounded = fBounded; } + + public Token getLocation() { + if (location != null) return location; + else if (basePair != null) return basePair.getLocation();; + return null; + } /** * Returns the type on the left hand side of the pair. @@ -231,7 +247,13 @@ public class UnifyPair { + "WC: " + ((PlaceholderType)rhs).isWildcardable() + ", IT: " + ((PlaceholderType)rhs).isInnerType(); } - return "(" + lhs + " " + pairOp + " " + rhs + ", " + ret + ")"; //+ ", [" + getfBounded().toString()+ "])"; + var res = "(" + lhs + " " + pairOp + " " + rhs + ", " + ret + ")"; //+ ", [" + getfBounded().toString()+ "])"; + var location = this.getLocation(); + if (location != null) { + res += "@" + location.getLine(); + } + + return res; } /* From 688358aa331a451f161358710dcfd682d82458e6 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Wed, 28 Feb 2024 13:16:32 +0100 Subject: [PATCH 11/18] Add more debug help --- .../typeinference/unify/RuleSet.java | 2 +- .../unify/interfaces/IFiniteClosure.java | 11 ++++++++-- .../unify/model/FiniteClosure.java | 10 ++++----- .../typeinference/unify/model/Unifier.java | 2 +- .../typeinference/unify/model/UnifyPair.java | 21 +++++++++++-------- 5 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java index 39b0de33..1669b760 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java @@ -439,7 +439,7 @@ public class RuleSet implements IRuleSet{ if(!(rhsType instanceof ReferenceType) && !(rhsType instanceof PlaceholderType)) return false; - return fc.greater(lhsType, new HashSet<>()).contains(rhsType); + return fc.greater(lhsType, new HashSet<>(), pair.getLocation()).contains(rhsType); } @Override diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java index 557b664a..5868f0ea 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java @@ -10,6 +10,7 @@ import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; import de.dhbwstuttgart.typeinference.unify.model.SuperType; import de.dhbwstuttgart.typeinference.unify.model.UnifyType; +import org.antlr.v4.runtime.Token; /** * @@ -22,13 +23,19 @@ public interface IFiniteClosure { * Returns all types of the finite closure that are subtypes of the argument. * @return The set of subtypes of the argument. */ - public Set smaller(UnifyType type, Set fBounded); + public Set smaller(UnifyType type, Set fBounded, Token position); + public default Set smaller(UnifyType type, Set fBounded) { + return this.smaller(type, fBounded, null); + } /** * Returns all types of the finite closure that are supertypes of the argument. * @return The set of supertypes of the argument. */ - public Set greater(UnifyType type, Set fBounded); + public Set greater(UnifyType type, Set fBounded, Token position); + public default Set greater(UnifyType type, Set fBounded) { + return this.greater(type, fBounded, null); + } /** * Wo passt Type rein? diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java index 55340fdc..f5671686 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java @@ -27,6 +27,7 @@ import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; import de.dhbwstuttgart.util.Pair; +import org.antlr.v4.runtime.Token; /** * The finite closure for the type unification @@ -145,7 +146,7 @@ implements IFiniteClosure { * @return The set of subtypes of the argument. */ @Override - public Set smaller(UnifyType type, Set fBounded) { + public Set smaller(UnifyType type, Set fBounded, Token position) { Set ret; if ((ret = smallerHash.get(new hashKeyType(type))) != null) { @@ -260,8 +261,7 @@ implements IFiniteClosure { */ @Override //Eingefuegt PL 2018-05-24 F-Bounded Problematik - public Set greater(UnifyType type, Set fBounded) { - + public Set greater(UnifyType type, Set fBounded, Token location) { Set ret; if ((ret = greaterHash.get(new hashKeyType(type))) != null) { //System.out.println(greaterHash); @@ -302,7 +302,7 @@ implements IFiniteClosure { //PL 18-04-05 Unifier durch Matcher ersetzt ANFANG ArrayList termList= new ArrayList(); - termList.add(new UnifyPair(theta1,type, PairOperator.EQUALSDOT)); + termList.add(new UnifyPair(theta1,type, PairOperator.EQUALSDOT, location)); Optional optSigma = match.match(termList); //PL 18-04-05 Unifier durch Matcher ersetzt ENDE if(!optSigma.isPresent()) { @@ -344,7 +344,7 @@ implements IFiniteClosure { BiFunction f = (x,y) -> { ArrayList termList = new ArrayList(); - termList.add(new UnifyPair(y,t.getTypeParams().get(i_ef), PairOperator.EQUALSDOT)); + termList.add(new UnifyPair(y,t.getTypeParams().get(i_ef), PairOperator.EQUALSDOT, location)); return ((match.match(termList).isPresent()) || x); }; //if (parai.getName().equals("java.lang.Integer")) { diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/Unifier.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/Unifier.java index 8cfac643..db050c03 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/Unifier.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/Unifier.java @@ -102,7 +102,7 @@ public class Unifier implements Function, Iterable uni, UnifyPair base) { + this(lhs, rhs, op, uni, base, null); + } + + public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, Set uni, UnifyPair base, Set fBounded) { + this(lhs, rhs, op, uni, base, fBounded, null); + } + + public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, Set uni, UnifyPair base, Set fBounded, Token location) { this.lhs = lhs; this.rhs = rhs; pairOp = op; substitution = uni; basePair = base; - - + this.location = location; + // Caching hashcode hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode(); - } - - public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, Set uni, UnifyPair base, Set fBounded) { - this(lhs, rhs, op, uni, base); - - this.fBounded = fBounded; } public Token getLocation() { if (location != null) return location; - else if (basePair != null) return basePair.getLocation();; + else if (basePair != null) return basePair.getLocation(); return null; } From 9c6372c3ba5cee354ead5f546c85b990901e603c Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Wed, 28 Feb 2024 13:22:13 +0100 Subject: [PATCH 12/18] Thats probably important --- .../de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java index 34069374..5df521cb 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java @@ -94,6 +94,7 @@ public class UnifyPair { substitution = uni; basePair = base; this.location = location; + this.fBounded = fBounded; // Caching hashcode hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode(); From 584690596e138b7e39151d53499328c1f8afac8d Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Fri, 1 Mar 2024 17:34:40 +0100 Subject: [PATCH 13/18] Add filename to debug output, closes #126 --- resources/bytecode/javFiles/Op2.jav | 12 +- .../de/dhbwstuttgart/core/JavaTXCompiler.java | 4 +- .../de/dhbwstuttgart/parser/SourceLoc.java | 4 + .../SyntaxTreeGenerator.java | 11 +- .../syntaxtree/ClassOrInterface.java | 10 +- .../de/dhbwstuttgart/syntaxtree/Record.java | 4 +- .../syntaxtree/factory/ASTFactory.java | 2 +- .../syntaxtree/factory/UnifyTypeFactory.java | 9 +- .../typeinference/assumptions/FunNClass.java | 2 +- .../typeinference/constraints/Pair.java | 7 +- .../typeinference/typeAlgo/TYPEStmt.java | 142 +++++++++--------- .../unify/interfaces/IFiniteClosure.java | 3 +- .../unify/model/FiniteClosure.java | 3 +- .../typeinference/unify/model/UnifyPair.java | 15 +- src/test/java/TestComplete.java | 7 + .../java/targetast/ASTToTypedTargetAST.java | 2 +- 16 files changed, 138 insertions(+), 99 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/parser/SourceLoc.java diff --git a/resources/bytecode/javFiles/Op2.jav b/resources/bytecode/javFiles/Op2.jav index 9d446eb2..4bf3b77e 100644 --- a/resources/bytecode/javFiles/Op2.jav +++ b/resources/bytecode/javFiles/Op2.jav @@ -1,11 +1,17 @@ import java.lang.Integer; +import java.lang.Double; import java.lang.String; public class Op2 { m(){ - var x = ""; - var a = 5+x; - + //var x = ""; + //var a = 5+x; + + Integer x = 10; + Double y = 10.5; + + var a = x - y; + return a; } } \ No newline at end of file diff --git a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java index 8ea08a23..fae04d71 100644 --- a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -651,7 +651,7 @@ public class JavaTXCompiler { private SourceFile parse(File sourceFile) throws IOException, java.lang.ClassNotFoundException { SourceFileContext tree = JavaTXParser.parse(sourceFile); environment.addClassesToRegistry(classRegistry, tree, sourceFile, this); - SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null)); + SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), sourceFile.getName()); var classes = new ArrayList(); var sf = new SourceFile(generator.pkgName, classes, generator.imports); addSourceFile(sourceFile, sf); @@ -672,7 +672,7 @@ public class JavaTXCompiler { var tree = JavaTXParser.parse(file); classRegistry.addName(name.toString(), 0); // TODO This gets overwritten later, is it bad if we don't know this right away? environment.addClassesToRegistry(classRegistry, tree, file, this); - SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null)); + SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), file.getName()); var classes = new ArrayList(); var sf = new SourceFile(generator.pkgName, classes, generator.imports); addSourceFile(file, sf); diff --git a/src/main/java/de/dhbwstuttgart/parser/SourceLoc.java b/src/main/java/de/dhbwstuttgart/parser/SourceLoc.java new file mode 100644 index 00000000..4cdd698c --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/parser/SourceLoc.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.parser; + +public record SourceLoc(String file, int line) { +} diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java index dafc1eca..40d2a323 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java @@ -92,7 +92,9 @@ public class SyntaxTreeGenerator { private final JavaTXCompiler compiler; private RefType superClass; - public SyntaxTreeGenerator(JavaTXCompiler compiler, JavaClassRegistry reg, GenericsRegistry globalGenerics) { + public final String fileName; + + public SyntaxTreeGenerator(JavaTXCompiler compiler, JavaClassRegistry reg, GenericsRegistry globalGenerics, String fileName) { // Die Generics müssen während des Bauens des AST erstellt werden, // da diese mit der Methode oder Klasse, in welcher sie deklariert werden // verknüpft sein müssen. Dennoch werden die Namen aller Generics in einer @@ -117,6 +119,7 @@ public class SyntaxTreeGenerator { this.allmodifiers.put("strictfp", 32768); this.compiler = compiler; + this.fileName = fileName; } public JavaClassRegistry getReg() { @@ -226,7 +229,7 @@ public class SyntaxTreeGenerator { } var ctor = Optional.of(this.generatePseudoConstructor(ctx.identifier().getText(), fieldInitializations, genericClassParameters, offset)); var staticCtor = Optional.of(this.generateStaticConstructor(ctx.identifier().getText(), staticFieldInitializations, genericClassParameters, offset)); - return new ClassOrInterface(modifiers, name, fielddecl, ctor, staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, isFunctionalInterface, implementedInterfaces, permittedSubtypes, offset); + return new ClassOrInterface(modifiers, name, fielddecl, ctor, staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, isFunctionalInterface, implementedInterfaces, permittedSubtypes, offset, fileName); } @@ -282,7 +285,7 @@ public class SyntaxTreeGenerator { implementedInterfaces.addAll(convert(recordDeclaration.typeList(), generics)); } var staticCtor = Optional.of(this.generateStaticConstructor(recordDeclaration.identifier().getText(), staticFieldInitializations, genericClassParameters, offset)); - return new Record(modifiers, name, fielddecl, Optional.empty(), staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset); + return new Record(modifiers, name, fielddecl, Optional.empty(), staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset, fileName); } private void convert(ClassBodyDeclarationContext classBody, List fields, List constructors, List methods, JavaClassName name, RefType superClass, GenericsRegistry generics) { @@ -401,7 +404,7 @@ public class SyntaxTreeGenerator { } var staticCtor = Optional.of(this.generateStaticConstructor(ctx.identifier().getText(), staticFieldInitializations, genericParams, ctx.getStart())); - return new ClassOrInterface(modifiers, name, fields, Optional.empty(), staticCtor, methods, new ArrayList<>(), genericParams, superClass, true, methods.size() == 1 ? true : false, extendedInterfaces, permittedSubtypes, ctx.getStart()); + return new ClassOrInterface(modifiers, name, fields, Optional.empty(), staticCtor, methods, new ArrayList<>(), genericParams, superClass, true, methods.size() == 1 ? true : false, extendedInterfaces, permittedSubtypes, ctx.getStart(), fileName); } private GenericDeclarationList createEmptyGenericDeclarationList(Token classNameIdentifier) { diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java b/src/main/java/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java index a4c527a0..a8777386 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java @@ -21,6 +21,8 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope { private Boolean methodAdded = false; // wird benoetigt bei in JavaTXCompiler.getConstraints() protected int modifiers; protected JavaClassName name; + private final String fileName; + private List fields = new ArrayList<>(); private Optional fieldInitializations; // PL 2018-11-24: Noetig, um Bytecode fuer initializators nur einmal zu erzeugen private Optional staticInitializer; @@ -33,7 +35,7 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope { private List permittedSubtypes; private List constructors; - public ClassOrInterface(int modifiers, JavaClassName name, List fielddecl, Optional fieldInitializations, Optional staticInitializer, List methods, List constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, Boolean isFunctionalInterface, List implementedInterfaces, List permittedSubtypes, Token offset) { + public ClassOrInterface(int modifiers, JavaClassName name, List fielddecl, Optional fieldInitializations, Optional staticInitializer, List methods, List constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, Boolean isFunctionalInterface, List implementedInterfaces, List permittedSubtypes, Token offset, String fileName) { super(offset); if (isInterface) { modifiers |= Modifier.INTERFACE | Modifier.ABSTRACT; @@ -51,6 +53,7 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope { this.permittedSubtypes = permittedSubtypes; this.methods = methods; this.constructors = constructors; + this.fileName = fileName; } /* @@ -70,6 +73,11 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope { this.implementedInterfaces = cl.implementedInterfaces; this.methods = new ArrayList<>(cl.methods); this.constructors = new ArrayList<>(cl.constructors); + this.fileName = cl.fileName; + } + + public String getFileName() { + return fileName; } public Optional getField(String name) { diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/Record.java b/src/main/java/de/dhbwstuttgart/syntaxtree/Record.java index ee93f32e..8fe6258d 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/Record.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/Record.java @@ -13,7 +13,7 @@ import javax.swing.text.html.Option; public class Record extends ClassOrInterface { - public Record(int modifiers, JavaClassName name, List fielddecl, Optional fieldInitializations, Optional staticInitializer, List methods, List constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List implementedInterfaces, Token offset) { - super(modifiers, name, fielddecl, fieldInitializations, staticInitializer, methods, constructors, genericClassParameters, superClass, isInterface, methods.size() == 1 ? true : false, implementedInterfaces, new ArrayList<>(), offset); + public Record(int modifiers, JavaClassName name, List fielddecl, Optional fieldInitializations, Optional staticInitializer, List methods, List constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List implementedInterfaces, Token offset, String fileName) { + super(modifiers, name, fielddecl, fieldInitializations, staticInitializer, methods, constructors, genericClassParameters, superClass, isInterface, methods.size() == 1 ? true : false, implementedInterfaces, new ArrayList<>(), offset, fileName); } } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java index 308cf9a2..27ac8dbb 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java @@ -148,7 +148,7 @@ public class ASTFactory { Token offset = new NullToken(); // Braucht keinen Offset, da diese Klasse nicht aus einem Quellcode geparst wurde - var cinf = new ClassOrInterface(modifier, name, felder, Optional.empty() /* eingefuegt PL 2018-11-24 */, Optional.empty(), methoden, konstruktoren, genericDeclarationList, superClass, isInterface, isFunctionalInterface, implementedInterfaces, permittedSubtypes, offset); + var cinf = new ClassOrInterface(modifier, name, felder, Optional.empty() /* eingefuegt PL 2018-11-24 */, Optional.empty(), methoden, konstruktoren, genericDeclarationList, superClass, isInterface, isFunctionalInterface, implementedInterfaces, permittedSubtypes, offset, null); cache.put(jreClass, cinf); return cinf; } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java index 785ef52a..4037d2f4 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java @@ -8,6 +8,7 @@ import java.util.stream.Collectors; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.SourceLoc; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.FCGenerator; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; @@ -42,19 +43,19 @@ public class UnifyTypeFactory { return new FiniteClosure(FCGenerator.toUnifyFC(fromClasses, classLoader), logFile); } - public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr, Token location){ + public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr, SourceLoc location){ return new UnifyPair(tl, tr, PairOperator.SMALLER, location); } - public static UnifyPair generateSmallerDotPair(UnifyType tl, UnifyType tr, Token location){ + public static UnifyPair generateSmallerDotPair(UnifyType tl, UnifyType tr, SourceLoc location){ return new UnifyPair(tl, tr, PairOperator.SMALLERDOT, location); } - public static UnifyPair generateSmallNotEqualDotPair(UnifyType tl, UnifyType tr, Token location){ + public static UnifyPair generateSmallNotEqualDotPair(UnifyType tl, UnifyType tr, SourceLoc location){ return new UnifyPair(tl, tr, PairOperator.SMALLERNEQDOT, location); } - public static UnifyPair generateEqualDotPair(UnifyType tl, UnifyType tr, Token location){ + public static UnifyPair generateEqualDotPair(UnifyType tl, UnifyType tr, SourceLoc location){ return new UnifyPair(tl, tr, PairOperator.EQUALSDOT, location); } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/assumptions/FunNClass.java b/src/main/java/de/dhbwstuttgart/typeinference/assumptions/FunNClass.java index 8cfb2e8e..e58aa96b 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/assumptions/FunNClass.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/assumptions/FunNClass.java @@ -22,7 +22,7 @@ import java.util.Optional; public class FunNClass extends ClassOrInterface { public FunNClass(List funNParams) { - super(0, new JavaClassName("Fun" + (funNParams.size() - 1)), new ArrayList<>(), Optional.empty(), Optional.empty() /* eingefuegt PL 2018-11-24 */, createMethods(funNParams), new ArrayList<>(), createGenerics(funNParams), ASTFactory.createObjectType(), true, false, new ArrayList<>(), new ArrayList<>(), new NullToken()); + super(0, new JavaClassName("Fun" + (funNParams.size() - 1)), new ArrayList<>(), Optional.empty(), Optional.empty() /* eingefuegt PL 2018-11-24 */, createMethods(funNParams), new ArrayList<>(), createGenerics(funNParams), ASTFactory.createObjectType(), true, false, new ArrayList<>(), new ArrayList<>(), new NullToken(), null); } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java b/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java index 2a4fac90..a485ba5e 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Map; import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.SourceLoc; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.unify.model.PairOperator; @@ -15,7 +16,7 @@ public class Pair implements Serializable public final RefTypeOrTPHOrWildcardOrGeneric TA1; public final RefTypeOrTPHOrWildcardOrGeneric TA2; - private Token location; + private SourceLoc location; private PairOperator eOperator = PairOperator.SMALLER; private Boolean noUnification = false; @@ -37,7 +38,7 @@ public class Pair implements Serializable this.eOperator = eOp; } - public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator e0p, Token location) { + public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator e0p, SourceLoc location) { this(TA1, TA2, e0p); this.location = location; } @@ -50,7 +51,7 @@ public class Pair implements Serializable this.noUnification = noUnification; } - public Token getLocation() { + public SourceLoc getLocation() { return this.location; } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index a21aba1d..b65664e1 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -7,6 +7,7 @@ import java.util.stream.Collectors; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.exceptions.TypeinferenceException; import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.SourceLoc; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.*; @@ -28,6 +29,7 @@ import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; import de.dhbwstuttgart.typeinference.constraints.GenericsResolver; import de.dhbwstuttgart.typeinference.constraints.Pair; import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import org.antlr.v4.runtime.Token; public class TYPEStmt implements StatementVisitor { @@ -43,6 +45,10 @@ public class TYPEStmt implements StatementVisitor { return constraintsSet; } + private SourceLoc loc(Token token) { + return new SourceLoc(info.getCurrentClass().getFileName(), token.getLine()); + }; + /** * Erstellt einen neuen GenericResolver Die Idee dieser Datenstruktur ist es, GTVs einen eindeutigen TPH zuzuweisen. Bei Methodenaufrufen oder anderen Zugriffen, bei denen alle benutzten GTVs jeweils einen einheitlichen TPH bekommen müssen kann diese Klasse eingesetzt werden. Wichtig ist, dass hierfür jeweils eine frische Instanz benutzt wird. * @@ -71,8 +77,8 @@ public class TYPEStmt implements StatementVisitor { // lambdaParams.add(0,tphRetType); constraintsSet.addUndConstraint(new Pair(lambdaExpression.getType(), new RefType(new JavaClassName("Fun" + (lambdaParams.size() - 1) + "$$"), lambdaParams, new NullToken()), // new FunN(lambdaParams), - PairOperator.EQUALSDOT, lambdaExpression.getOffset())); - constraintsSet.addUndConstraint(new Pair(lambdaExpression.getReturnType(), tphRetType, PairOperator.EQUALSDOT, lambdaExpression.getOffset())); + PairOperator.EQUALSDOT, loc(lambdaExpression.getOffset()))); + constraintsSet.addUndConstraint(new Pair(lambdaExpression.getReturnType(), tphRetType, PairOperator.EQUALSDOT, loc(lambdaExpression.getOffset()))); // Constraints des Bodys generieren: TYPEStmt lambdaScope = new TYPEStmt(new TypeInferenceBlockInformation(info, lambdaExpression)); @@ -84,7 +90,7 @@ public class TYPEStmt implements StatementVisitor { public void visit(Assign assign) { assign.lefSide.accept(this); assign.rightSide.accept(this); - constraintsSet.addUndConstraint(new Pair(assign.rightSide.getType(), assign.lefSide.getType(), PairOperator.SMALLERDOT, assign.getOffset())); + constraintsSet.addUndConstraint(new Pair(assign.rightSide.getType(), assign.lefSide.getType(), PairOperator.SMALLERDOT, loc(assign.getOffset()))); } @Override @@ -111,8 +117,8 @@ public class TYPEStmt implements StatementVisitor { for (FieldAssumption fieldAssumption : info.getFields(fieldVar.fieldVarName)) { Constraint constraint = new Constraint(); GenericsResolver resolver = getResolverInstance(); - constraint.add(new Pair(fieldVar.receiver.getType(), fieldAssumption.getReceiverType(resolver), PairOperator.SMALLERDOT, fieldVar.getOffset())); // PL 2019-12-09: SMALLERDOT eingefuegt, EQUALSDOT entfernt, wenn ds Field privat ist muesste es EQUALSDOT lauten - constraint.add(new Pair(fieldVar.getType(), fieldAssumption.getType(resolver), PairOperator.EQUALSDOT, fieldVar.getOffset())); + constraint.add(new Pair(fieldVar.receiver.getType(), fieldAssumption.getReceiverType(resolver), PairOperator.SMALLERDOT, loc(fieldVar.getOffset()))); // PL 2019-12-09: SMALLERDOT eingefuegt, EQUALSDOT entfernt, wenn ds Field privat ist muesste es EQUALSDOT lauten + constraint.add(new Pair(fieldVar.getType(), fieldAssumption.getType(resolver), PairOperator.EQUALSDOT, loc(fieldVar.getOffset()))); oderConstraints.add(constraint); } if (oderConstraints.size() == 0) @@ -131,7 +137,7 @@ public class TYPEStmt implements StatementVisitor { @Override public void visit(ForEachStmt forEachStmt) { var iterableType = new RefType(ASTFactory.createClass(java.lang.Iterable.class).getClassName(), Arrays.asList(forEachStmt.statement.getType()), new NullToken()); - constraintsSet.addUndConstraint(new Pair(forEachStmt.expression.getType(), iterableType, PairOperator.SMALLERDOT, forEachStmt.getOffset())); + constraintsSet.addUndConstraint(new Pair(forEachStmt.expression.getType(), iterableType, PairOperator.SMALLERDOT, loc(forEachStmt.getOffset()))); forEachStmt.statement.accept(this); forEachStmt.expression.accept(this); forEachStmt.block.accept(this); @@ -143,14 +149,14 @@ public class TYPEStmt implements StatementVisitor { // Expression inferieren: ifStmt.expr.accept(this); // Expression muss boolean sein: - constraintsSet.addUndConstraint(new Pair(ifStmt.expr.getType(), booleanType, PairOperator.EQUALSDOT, ifStmt.getOffset())); + constraintsSet.addUndConstraint(new Pair(ifStmt.expr.getType(), booleanType, PairOperator.EQUALSDOT, loc(ifStmt.getOffset()))); // 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)); if (ifStmt.else_block != null) { ifStmt.else_block.accept(this); - constraintsSet.addUndConstraint(new Pair(ifStmt.else_block.getType(), ifStmt.getType(), PairOperator.SMALLERDOT, ifStmt.getOffset())); + constraintsSet.addUndConstraint(new Pair(ifStmt.else_block.getType(), ifStmt.getType(), PairOperator.SMALLERDOT, loc(ifStmt.getOffset()))); } } @@ -234,9 +240,9 @@ public class TYPEStmt implements StatementVisitor { if (unaryExpr.operation == UnaryExpr.Operation.POSTDECREMENT || unaryExpr.operation == UnaryExpr.Operation.POSTINCREMENT || unaryExpr.operation == UnaryExpr.Operation.PREDECREMENT || unaryExpr.operation == UnaryExpr.Operation.PREINCREMENT) { // @see: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.14.2 // Expression muss zu Numeric Convertierbar sein. also von Numeric erben - constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), number, PairOperator.SMALLERNEQDOT, unaryExpr.getOffset())); + constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), number, PairOperator.SMALLERNEQDOT, loc(unaryExpr.getOffset()))); // The type of the postfix increment expression is the type of the variable - constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), unaryExpr.getType(), PairOperator.EQUALSDOT, unaryExpr.getOffset())); + constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), unaryExpr.getType(), PairOperator.EQUALSDOT, loc(unaryExpr.getOffset()))); } else { throw new NotImplementedException(); } @@ -263,49 +269,49 @@ public class TYPEStmt implements StatementVisitor { // PL eingefuegt 2018-07-17 if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(bytee.getName())) { numeric = new Constraint<>(); - numeric.add(new Pair(binary.lexpr.getType(), bytee, PairOperator.SMALLERDOT, binary.getOffset())); - numeric.add(new Pair(binary.rexpr.getType(), bytee, PairOperator.SMALLERDOT, binary.getOffset())); - numeric.add(new Pair(binary.getType(), integer, PairOperator.EQUALSDOT, binary.getOffset())); + numeric.add(new Pair(binary.lexpr.getType(), bytee, PairOperator.SMALLERDOT, loc(binary.getOffset()))); + numeric.add(new Pair(binary.rexpr.getType(), bytee, PairOperator.SMALLERDOT, loc(binary.getOffset()))); + numeric.add(new Pair(binary.getType(), integer, PairOperator.EQUALSDOT, loc(binary.getOffset()))); numericAdditionOrStringConcatenation.add(numeric); } // PL eingefuegt 2018-07-17 if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(shortt.getName())) { numeric = new Constraint<>(); - numeric.add(new Pair(binary.lexpr.getType(), shortt, PairOperator.SMALLERDOT, binary.getOffset())); - numeric.add(new Pair(binary.rexpr.getType(), shortt, PairOperator.SMALLERDOT, binary.getOffset())); - numeric.add(new Pair(binary.getType(), integer, PairOperator.EQUALSDOT, binary.getOffset())); + numeric.add(new Pair(binary.lexpr.getType(), shortt, PairOperator.SMALLERDOT, loc(binary.getOffset()))); + numeric.add(new Pair(binary.rexpr.getType(), shortt, PairOperator.SMALLERDOT, loc(binary.getOffset()))); + numeric.add(new Pair(binary.getType(), integer, PairOperator.EQUALSDOT, loc(binary.getOffset()))); numericAdditionOrStringConcatenation.add(numeric); } // PL eingefuegt 2018-07-17 if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(integer.getName())) { numeric = new Constraint<>(); - numeric.add(new Pair(binary.lexpr.getType(), integer, PairOperator.SMALLERDOT, binary.getOffset())); - numeric.add(new Pair(binary.rexpr.getType(), integer, PairOperator.SMALLERDOT, binary.getOffset())); - numeric.add(new Pair(integer, binary.getType(), PairOperator.EQUALSDOT, binary.getOffset())); + numeric.add(new Pair(binary.lexpr.getType(), integer, PairOperator.SMALLERDOT, loc(binary.getOffset()))); + numeric.add(new Pair(binary.rexpr.getType(), integer, PairOperator.SMALLERDOT, loc(binary.getOffset()))); + numeric.add(new Pair(integer, binary.getType(), PairOperator.EQUALSDOT, loc(binary.getOffset()))); numericAdditionOrStringConcatenation.add(numeric); } // PL eingefuegt 2018-07-17 if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(longg.getName())) { numeric = new Constraint<>(); - numeric.add(new Pair(binary.lexpr.getType(), longg, PairOperator.SMALLERDOT, binary.getOffset())); - numeric.add(new Pair(binary.rexpr.getType(), longg, PairOperator.SMALLERDOT, binary.getOffset())); - numeric.add(new Pair(longg, binary.getType(), PairOperator.EQUALSDOT, binary.getOffset())); + numeric.add(new Pair(binary.lexpr.getType(), longg, PairOperator.SMALLERDOT, loc(binary.getOffset()))); + numeric.add(new Pair(binary.rexpr.getType(), longg, PairOperator.SMALLERDOT, loc(binary.getOffset()))); + numeric.add(new Pair(longg, binary.getType(), PairOperator.EQUALSDOT, loc(binary.getOffset()))); numericAdditionOrStringConcatenation.add(numeric); } // PL eingefuegt 2018-07-17 if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(floatt.getName())) { numeric = new Constraint<>(); - numeric.add(new Pair(binary.lexpr.getType(), floatt, PairOperator.SMALLERDOT, binary.getOffset())); - numeric.add(new Pair(binary.rexpr.getType(), floatt, PairOperator.SMALLERDOT, binary.getOffset())); - numeric.add(new Pair(floatt, binary.getType(), PairOperator.EQUALSDOT, binary.getOffset())); + numeric.add(new Pair(binary.lexpr.getType(), floatt, PairOperator.SMALLERDOT, loc(binary.getOffset()))); + numeric.add(new Pair(binary.rexpr.getType(), floatt, PairOperator.SMALLERDOT, loc(binary.getOffset()))); + numeric.add(new Pair(floatt, binary.getType(), PairOperator.EQUALSDOT, loc(binary.getOffset()))); numericAdditionOrStringConcatenation.add(numeric); } // PL eingefuegt 2018-07-17 if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(doublee.getName())) { numeric = new Constraint<>(); - numeric.add(new Pair(binary.lexpr.getType(), doublee, PairOperator.SMALLERDOT, binary.getOffset())); - numeric.add(new Pair(binary.rexpr.getType(), doublee, PairOperator.SMALLERDOT, binary.getOffset())); - numeric.add(new Pair(doublee, binary.getType(), PairOperator.EQUALSDOT, binary.getOffset())); + numeric.add(new Pair(binary.lexpr.getType(), doublee, PairOperator.SMALLERDOT, loc(binary.getOffset()))); + numeric.add(new Pair(binary.rexpr.getType(), doublee, PairOperator.SMALLERDOT, loc(binary.getOffset()))); + numeric.add(new Pair(doublee, binary.getType(), PairOperator.EQUALSDOT, loc(binary.getOffset()))); numericAdditionOrStringConcatenation.add(numeric); } /* @@ -318,9 +324,9 @@ public class TYPEStmt implements StatementVisitor { // Dann kann der Ausdruck auch das aneinanderfügen zweier Strings sein: ("a" + "b") oder (1 + 2) if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(string.getName())) { Constraint stringConcat = new Constraint<>(); - stringConcat.add(new Pair(binary.lexpr.getType(), string, PairOperator.EQUALSDOT, binary.getOffset())); - stringConcat.add(new Pair(binary.rexpr.getType(), string, PairOperator.EQUALSDOT, binary.getOffset())); - stringConcat.add(new Pair(string, binary.getType(), PairOperator.EQUALSDOT, binary.getOffset())); + stringConcat.add(new Pair(binary.lexpr.getType(), string, PairOperator.EQUALSDOT, loc(binary.getOffset()))); + stringConcat.add(new Pair(binary.rexpr.getType(), string, PairOperator.EQUALSDOT, loc(binary.getOffset()))); + stringConcat.add(new Pair(string, binary.getType(), PairOperator.EQUALSDOT, loc(binary.getOffset()))); numericAdditionOrStringConcatenation.add(stringConcat); } } @@ -339,10 +345,10 @@ public class TYPEStmt implements StatementVisitor { */ // Testeise eingefuegt PL 2018-05-24 // Hier sollte evtl. noch importe angefragt werden PL 2019-05-07 - constraintsSet.addUndConstraint(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERNEQDOT, binary.getOffset())); - constraintsSet.addUndConstraint(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERNEQDOT, binary.getOffset())); + constraintsSet.addUndConstraint(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERNEQDOT, loc(binary.getOffset()))); + constraintsSet.addUndConstraint(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERNEQDOT, loc(binary.getOffset()))); // Rückgabetyp ist Boolean - constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT, binary.getOffset())); + constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT, loc(binary.getOffset()))); // auskommentiert PL 2018-05-24 // constraintsSet.addUndConstraint(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERDOT)); @@ -354,7 +360,7 @@ public class TYPEStmt implements StatementVisitor { * Auszug aus https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.21 The equality operators may be used to compare two operands that are convertible (§5.1.8) to numeric type, or two operands of type boolean or Boolean, or two operands that are each of either reference type or the null type. All other cases result in a compile-time error. */ // Der Equals Operator geht mit fast allen Typen, daher werden hier keine Constraints gesetzt - constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT, binary.getOffset())); + constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT, loc(binary.getOffset()))); } else { throw new NotImplementedException(); } @@ -363,9 +369,9 @@ public class TYPEStmt implements StatementVisitor { @Override public void visit(BoolExpression expr) { - constraintsSet.addUndConstraint(new Pair(bool, expr.getType(), PairOperator.EQUALSDOT, expr.getOffset())); - constraintsSet.addUndConstraint(new Pair(bool, expr.lexpr.getType(), PairOperator.EQUALSDOT, expr.getOffset())); - constraintsSet.addUndConstraint(new Pair(bool, expr.rexpr.getType(), PairOperator.EQUALSDOT, expr.getOffset())); + constraintsSet.addUndConstraint(new Pair(bool, expr.getType(), PairOperator.EQUALSDOT, loc(expr.getOffset()))); + constraintsSet.addUndConstraint(new Pair(bool, expr.lexpr.getType(), PairOperator.EQUALSDOT, loc(expr.getOffset()))); + constraintsSet.addUndConstraint(new Pair(bool, expr.rexpr.getType(), PairOperator.EQUALSDOT, loc(expr.getOffset()))); // TODO return; @@ -378,23 +384,23 @@ public class TYPEStmt implements StatementVisitor { // wie hier fuer double gezeigt. Im Momment auskommentiert, weil zu wenige Literaltypen // funktionieren if (literal.value instanceof Short) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), shortt, PairOperator.EQUALSDOT, literal.getOffset())); + constraintsSet.addUndConstraint(new Pair(literal.getType(), shortt, PairOperator.EQUALSDOT, loc(literal.getOffset()))); return; } if (literal.value instanceof Byte) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT, literal.getOffset())); + constraintsSet.addUndConstraint(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT, loc(literal.getOffset()))); return; } if (literal.value instanceof Float) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), floatt, PairOperator.EQUALSDOT, literal.getOffset())); + constraintsSet.addUndConstraint(new Pair(literal.getType(), floatt, PairOperator.EQUALSDOT, loc(literal.getOffset()))); return; } if (literal.value instanceof Double) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), doublee, PairOperator.EQUALSDOT, literal.getOffset())); + constraintsSet.addUndConstraint(new Pair(literal.getType(), doublee, PairOperator.EQUALSDOT, loc(literal.getOffset()))); return; } if (literal.value instanceof Long) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), longg, PairOperator.EQUALSDOT, literal.getOffset())); + constraintsSet.addUndConstraint(new Pair(literal.getType(), longg, PairOperator.EQUALSDOT, loc(literal.getOffset()))); return; } if (literal.value instanceof Integer) { @@ -403,31 +409,31 @@ public class TYPEStmt implements StatementVisitor { HashSet clNames = info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)); Set oderConstraints = new HashSet<>(); Constraint constraint = new Constraint(); - constraint.add(new Pair(literal.getType(), integer, PairOperator.EQUALSDOT, literal.getOffset())); + constraint.add(new Pair(literal.getType(), integer, PairOperator.EQUALSDOT, loc(literal.getOffset()))); oderConstraints.add(constraint); if (clNames.stream().filter(x -> x.toString().equals("java.lang.Double")).findAny().isPresent()) { constraint = new Constraint(); - constraint.add(new Pair(literal.getType(), doublee, PairOperator.EQUALSDOT, literal.getOffset())); + constraint.add(new Pair(literal.getType(), doublee, PairOperator.EQUALSDOT, loc(literal.getOffset()))); oderConstraints.add(constraint); } if (clNames.stream().filter(x -> x.toString().equals("java.lang.Long")).findAny().isPresent()) { constraint = new Constraint(); - constraint.add(new Pair(literal.getType(), longg, PairOperator.EQUALSDOT, literal.getOffset())); + constraint.add(new Pair(literal.getType(), longg, PairOperator.EQUALSDOT, loc(literal.getOffset()))); oderConstraints.add(constraint); } if (clNames.stream().filter(x -> x.toString().equals("java.lang.Float")).findAny().isPresent()) { constraint = new Constraint(); - constraint.add(new Pair(literal.getType(), floatt, PairOperator.EQUALSDOT, literal.getOffset())); + constraint.add(new Pair(literal.getType(), floatt, PairOperator.EQUALSDOT, loc(literal.getOffset()))); oderConstraints.add(constraint); } if (clNames.stream().filter(x -> x.toString().equals("java.lang.Short")).findAny().isPresent()) { constraint = new Constraint(); - constraint.add(new Pair(literal.getType(), shortt, PairOperator.EQUALSDOT, literal.getOffset())); + constraint.add(new Pair(literal.getType(), shortt, PairOperator.EQUALSDOT, loc(literal.getOffset()))); oderConstraints.add(constraint); } if (clNames.stream().filter(x -> x.toString().equals("java.lang.Byte")).findAny().isPresent()) { constraint = new Constraint(); - constraint.add(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT, literal.getOffset())); + constraint.add(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT, loc(literal.getOffset()))); oderConstraints.add(constraint); } constraintsSet.addOderConstraint(oderConstraints); @@ -435,27 +441,27 @@ public class TYPEStmt implements StatementVisitor { return; } if (literal.value instanceof Short) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), shortt, PairOperator.EQUALSDOT, literal.getOffset())); + constraintsSet.addUndConstraint(new Pair(literal.getType(), shortt, PairOperator.EQUALSDOT, loc(literal.getOffset()))); return; } if (literal.value instanceof Byte) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT, literal.getOffset())); + constraintsSet.addUndConstraint(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT, loc(literal.getOffset()))); return; } if (literal.value instanceof Float) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), floatt, PairOperator.EQUALSDOT, literal.getOffset())); + constraintsSet.addUndConstraint(new Pair(literal.getType(), floatt, PairOperator.EQUALSDOT, loc(literal.getOffset()))); return; } if (literal.value instanceof String) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), string, PairOperator.EQUALSDOT, literal.getOffset())); + constraintsSet.addUndConstraint(new Pair(literal.getType(), string, PairOperator.EQUALSDOT, loc(literal.getOffset()))); return; } if (literal.value instanceof Boolean) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), bool, PairOperator.EQUALSDOT, literal.getOffset())); + constraintsSet.addUndConstraint(new Pair(literal.getType(), bool, PairOperator.EQUALSDOT, loc(literal.getOffset()))); return; } if (literal.value instanceof Character) { - constraintsSet.addUndConstraint(new Pair(literal.getType(), charr, PairOperator.EQUALSDOT, literal.getOffset())); + constraintsSet.addUndConstraint(new Pair(literal.getType(), charr, PairOperator.EQUALSDOT, loc(literal.getOffset()))); return; } if (literal.value != null) { @@ -471,7 +477,7 @@ public class TYPEStmt implements StatementVisitor { @Override public void visit(Return returnExpr) { returnExpr.retexpr.accept(this); - constraintsSet.addUndConstraint(new Pair(returnExpr.getType(), info.getCurrentTypeScope().getReturnType(), PairOperator.SMALLERDOT, returnExpr.getOffset())); + constraintsSet.addUndConstraint(new Pair(returnExpr.getType(), info.getCurrentTypeScope().getReturnType(), PairOperator.SMALLERDOT, loc(returnExpr.getOffset()))); } @Override @@ -503,7 +509,7 @@ public class TYPEStmt implements StatementVisitor { params.add(new GenericRefType(gtv.getName(), aThis.getOffset())); } RefType thisType = new RefType(currentClass.getClassName(), params, aThis.getOffset()); - constraintsSet.addUndConstraint(new Pair(aThis.getType(), thisType, PairOperator.EQUALSDOT, aThis.getOffset())); + constraintsSet.addUndConstraint(new Pair(aThis.getType(), thisType, PairOperator.EQUALSDOT, loc(aThis.getOffset()))); } private static TypeScope createNullTypeScope() { @@ -526,7 +532,7 @@ public class TYPEStmt implements StatementVisitor { // Expression inferieren: whileStmt.expr.accept(this); // Expression muss boolean sein: - constraintsSet.addUndConstraint(new Pair(whileStmt.expr.getType(), booleanType, PairOperator.EQUALSDOT, whileStmt.expr.getOffset())); + constraintsSet.addUndConstraint(new Pair(whileStmt.expr.getType(), booleanType, PairOperator.EQUALSDOT, loc(whileStmt.expr.getOffset()))); // LoopBlock inferieren: whileStmt.loopBlock.accept(this); } @@ -586,10 +592,10 @@ public class TYPEStmt implements StatementVisitor { RefTypeOrTPHOrWildcardOrGeneric receiverType = assumption.getReceiverType(resolver); if (receiverType != null) { - methodConstraint.add(new Pair(forMethod.receiver.getType(), receiverType, PairOperator.EQUALSDOT, forMethod.getOffset()));// PL 2020-03-17 SMALLERDOT in EQUALSDOT umgewandelt, weil alle geerbten Methoden in den jeweilen Klassen enthalten sind. + methodConstraint.add(new Pair(forMethod.receiver.getType(), receiverType, PairOperator.EQUALSDOT, loc(forMethod.getOffset())));// PL 2020-03-17 SMALLERDOT in EQUALSDOT umgewandelt, weil alle geerbten Methoden in den jeweilen Klassen enthalten sind. // PL 2023-01-24: dafuer ? extends receiverType noch ergaenzt - extendsMethodConstraint.add(new Pair(forMethod.receiver.getType(), new ExtendsWildcardType(receiverType, receiverType.getOffset()), PairOperator.EQUALSDOT, forMethod.getOffset())); + extendsMethodConstraint.add(new Pair(forMethod.receiver.getType(), new ExtendsWildcardType(receiverType, receiverType.getOffset()), PairOperator.EQUALSDOT, loc(forMethod.getOffset()))); } // gegenseite Verschraenkung der beiden Mengen von Typannahmen @@ -601,8 +607,8 @@ public class TYPEStmt implements StatementVisitor { // PairOperator.EQUALSDOT)); // Fuer Bytecodegenerierung PL 2020-03-09 wird derzeit nicht benutzt ENDE - methodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.SMALLERDOT, forMethod.getOffset())); - extendsMethodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.SMALLERDOT, forMethod.getOffset())); + methodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.SMALLERDOT, loc(forMethod.getOffset()))); + extendsMethodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.SMALLERDOT, loc(forMethod.getOffset()))); // methodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT)); // extendsMethodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT)); @@ -635,7 +641,7 @@ public class TYPEStmt implements StatementVisitor { RefTypeOrTPHOrWildcardOrGeneric argType = foMethod.arglist.getArguments().get(i).getType(); RefTypeOrTPHOrWildcardOrGeneric assType = assumption.getArgTypes(resolver).get(i); - ret.add(new Pair(argType, assType, PairOperator.SMALLERDOT, foMethod.getOffset())); + ret.add(new Pair(argType, assType, PairOperator.SMALLERDOT, loc(foMethod.getOffset()))); // Fuer Bytecodegenerierung PL 2020-03-09 wird derzeit nicht benutzt ANFANG // ret.add(new Pair(foMethod.argTypes.get(i), assType, PairOperator.EQUALSDOT)); @@ -729,7 +735,7 @@ public class TYPEStmt implements StatementVisitor { Constraint methodConstraint = new Constraint(); // WELCHEN SINN MACHT DIESER CONSTRAINT??? // Ist er nicht immer classname <. classname und damit redundant? - methodConstraint.add(new Pair(assumption.getReturnType(resolver), forConstructor.getType(), PairOperator.SMALLERDOT, forConstructor.getOffset())); + methodConstraint.add(new Pair(assumption.getReturnType(resolver), forConstructor.getType(), PairOperator.SMALLERDOT, loc(forConstructor.getOffset()))); // WELCHEN SINN MACHT DIESER CONSTRAINT??? methodConstraint.addAll(generateParameterConstraints(forConstructor, assumption, info, resolver)); return methodConstraint; @@ -753,17 +759,17 @@ public class TYPEStmt implements StatementVisitor { for (var child : switchStmt.getBlocks()) { for (var label : child.getLabels()) { if (label.getPattern() instanceof FormalParameter) { - constraintsSet.addUndConstraint(new Pair(label.getPattern().getType(), switchStmt.getSwitch().getType(), PairOperator.SMALLERDOT, label.getOffset())); + constraintsSet.addUndConstraint(new Pair(label.getPattern().getType(), switchStmt.getSwitch().getType(), PairOperator.SMALLERDOT, loc(label.getOffset()))); } } } } else { - constraintsSet.addUndConstraint(new Pair(caseExpressionType, switchStmt.getSwitch().getType(), PairOperator.EQUALSDOT, switchStmt.getSwitch().getOffset())); + constraintsSet.addUndConstraint(new Pair(caseExpressionType, switchStmt.getSwitch().getType(), PairOperator.EQUALSDOT, loc(switchStmt.getSwitch().getOffset()))); } for (var child : switchStmt.getBlocks()) { child.accept(this); - constraintsSet.addUndConstraint(new Pair(child.getType(), switchStmt.getType(), PairOperator.SMALLERDOT, switchStmt.getOffset())); + constraintsSet.addUndConstraint(new Pair(child.getType(), switchStmt.getType(), PairOperator.SMALLERDOT, loc(switchStmt.getOffset()))); } switchStack.pop(); @@ -784,7 +790,7 @@ public class TYPEStmt implements StatementVisitor { @Override public void visit(Yield aYield) { aYield.retexpr.accept(this); - constraintsSet.addUndConstraint(new Pair(aYield.getType(), switchStack.peek().getType(), PairOperator.EQUALSDOT, aYield.getOffset())); + constraintsSet.addUndConstraint(new Pair(aYield.getType(), switchStack.peek().getType(), PairOperator.EQUALSDOT, loc(aYield.getOffset()))); // TODO Auto-generated method stub } } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java index 5868f0ea..dea9e53a 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java @@ -3,6 +3,7 @@ package de.dhbwstuttgart.typeinference.unify.interfaces; import java.util.Optional; import java.util.Set; +import de.dhbwstuttgart.parser.SourceLoc; import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; import de.dhbwstuttgart.typeinference.unify.model.FunNType; import de.dhbwstuttgart.typeinference.unify.model.PairOperator; @@ -32,7 +33,7 @@ public interface IFiniteClosure { * Returns all types of the finite closure that are supertypes of the argument. * @return The set of supertypes of the argument. */ - public Set greater(UnifyType type, Set fBounded, Token position); + public Set greater(UnifyType type, Set fBounded, SourceLoc position); public default Set greater(UnifyType type, Set fBounded) { return this.greater(type, fBounded, null); } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java index f5671686..f4c8ab24 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java @@ -20,6 +20,7 @@ import com.google.common.collect.Ordering; //PL 18-02-05/18-04-05 Unifier durch Matcher ersetzt //muss greater noch ersetzt werden ja erledigt 18--04-05 +import de.dhbwstuttgart.parser.SourceLoc; import de.dhbwstuttgart.typeinference.unify.MartelliMontanariUnify; import de.dhbwstuttgart.typeinference.unify.Match; @@ -261,7 +262,7 @@ implements IFiniteClosure { */ @Override //Eingefuegt PL 2018-05-24 F-Bounded Problematik - public Set greater(UnifyType type, Set fBounded, Token location) { + public Set greater(UnifyType type, Set fBounded, SourceLoc location) { Set ret; if ((ret = greaterHash.get(new hashKeyType(type))) != null) { //System.out.println(greaterHash); diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java index 5df521cb..4c5a4f8c 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java @@ -1,6 +1,7 @@ package de.dhbwstuttgart.typeinference.unify.model; import com.google.common.collect.ObjectArrays; +import de.dhbwstuttgart.parser.SourceLoc; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import org.antlr.v4.runtime.Token; @@ -18,8 +19,8 @@ import java.util.Set; */ public class UnifyPair { - private Token location; - + private SourceLoc location; + /** * The type on the left hand side of the pair. */ @@ -74,7 +75,7 @@ public class UnifyPair { hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode(); } - public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, Token location) { + public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, SourceLoc location) { this(lhs, rhs, op); this.location = location; } @@ -87,20 +88,20 @@ public class UnifyPair { this(lhs, rhs, op, uni, base, fBounded, null); } - public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, Set uni, UnifyPair base, Set fBounded, Token location) { + public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, Set uni, UnifyPair base, Set fBounded, SourceLoc location) { this.lhs = lhs; this.rhs = rhs; pairOp = op; substitution = uni; basePair = base; this.location = location; - this.fBounded = fBounded; + //this.fBounded = fBounded; // what? // Caching hashcode hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode(); } - public Token getLocation() { + public SourceLoc getLocation() { if (location != null) return location; else if (basePair != null) return basePair.getLocation(); return null; @@ -254,7 +255,7 @@ public class UnifyPair { var res = "(" + lhs + " " + pairOp + " " + rhs + ", " + ret + ")"; //+ ", [" + getfBounded().toString()+ "])"; var location = this.getLocation(); if (location != null) { - res += "@" + location.getLine(); + res += "@" + location.line() + " in " + location.file(); } return res; diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index ff857464..dc15ec80 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -834,4 +834,11 @@ public class TestComplete { var instance = clazz.getDeclaredConstructor().newInstance(); assertEquals(clazz.getSuperclass().getDeclaredField("x").get(instance), 3); } + + @Test + public void testStringConcat() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Op2.jav"); + var clazz = classFiles.get("Op2"); + var instance = clazz.getDeclaredConstructor().newInstance(); + } } diff --git a/src/test/java/targetast/ASTToTypedTargetAST.java b/src/test/java/targetast/ASTToTypedTargetAST.java index b1389f0f..ae67c9cd 100644 --- a/src/test/java/targetast/ASTToTypedTargetAST.java +++ b/src/test/java/targetast/ASTToTypedTargetAST.java @@ -22,7 +22,7 @@ public class ASTToTypedTargetAST { @Test public void emptyClass() { - ClassOrInterface emptyClass = new ClassOrInterface(0, new JavaClassName("EmptyClass"), new ArrayList<>(), Optional.empty(), Optional.empty(), new ArrayList<>(), new ArrayList<>(), new GenericDeclarationList(new ArrayList<>(), new NullToken()), new RefType(new JavaClassName("Object"), new NullToken()), false, false, new ArrayList<>(), new ArrayList<>(), new NullToken()); + ClassOrInterface emptyClass = new ClassOrInterface(0, new JavaClassName("EmptyClass"), new ArrayList<>(), Optional.empty(), Optional.empty(), new ArrayList<>(), new ArrayList<>(), new GenericDeclarationList(new ArrayList<>(), new NullToken()), new RefType(new JavaClassName("Object"), new NullToken()), false, false, new ArrayList<>(), new ArrayList<>(), new NullToken(), null); ResultSet emptyResultSet = new ResultSet(new HashSet<>()); TargetStructure emptyTargetClass = new ASTToTargetAST(List.of(emptyResultSet)).convert(emptyClass); assert emptyTargetClass.getName().equals("EmptyClass"); From f11d4b0716b00a598c96851c8a787176ba193077 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Mon, 4 Mar 2024 10:58:26 +0100 Subject: [PATCH 14/18] Fix for loop overflowing the stack. Fixes #122 --- resources/bytecode/javFiles/Bug122.jav | 12 ++++++++++++ src/main/java/de/dhbwstuttgart/bytecode/Codegen.java | 8 ++++++-- .../SyntaxTreeGenerator/StatementGenerator.java | 5 +++-- .../target/generate/StatementToTargetExpression.java | 7 ++++++- .../typeinference/typeAlgo/TYPEStmt.java | 3 ++- src/test/java/TestComplete.java | 7 +++++++ 6 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 resources/bytecode/javFiles/Bug122.jav diff --git a/resources/bytecode/javFiles/Bug122.jav b/resources/bytecode/javFiles/Bug122.jav new file mode 100644 index 00000000..78a1c019 --- /dev/null +++ b/resources/bytecode/javFiles/Bug122.jav @@ -0,0 +1,12 @@ +import java.lang.Integer; +import java.lang.Boolean; + +class Bug122 { + void main() { + if (true) { + for (Integer i = 0; i < 10; i++) { + + } + } + } +} \ 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 7c06ee8d..7445e772 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java @@ -886,8 +886,12 @@ public class Codegen { case TargetFor _for: { state.enterScope(); var localCounter = state.localCounter; - if (_for.init() != null) - _for.init().forEach(e -> generate(state, e)); + if (_for.init() != null) { + for (var e : _for.init()) { + generate(state, e); + if (e instanceof TargetAssign) mv.visitInsn(POP); + } + } Label start = new Label(); Label end = new Label(); diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index 64dad545..27f0bf6b 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -513,8 +513,9 @@ public class StatementGenerator { } else { return new ForStmt( stmt.getStart(), - convert(control.forInit().localVariableDeclaration()), - convert(control.expression()), control.forUpdate.expression().stream().map(this::convert).toList(), + control.forInit() != null ? convert(control.forInit().localVariableDeclaration()) : List.of(), + control.expression() != null ? convert(control.expression()) : null, + control.forUpdate != null ? control.forUpdate.expression().stream().map(this::convert).toList() : List.of(), convert(stmt.statement()) ); } diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 702432a0..9117a8d6 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -141,7 +141,12 @@ public class StatementToTargetExpression implements ASTVisitor { @Override public void visit(ForStmt forStmt) { - result = new TargetFor(forStmt.initializer.stream().map(converter::convert).toList(), converter.convert(forStmt.condition), forStmt.loopExpr.stream().map(converter::convert).toList(), converter.convert(forStmt.block)); + result = new TargetFor( + forStmt.initializer.stream().map(converter::convert).toList(), + forStmt.condition != null ? converter.convert(forStmt.condition) : null, + forStmt.loopExpr.stream().map(converter::convert).toList(), + converter.convert(forStmt.block) + ); } @Override diff --git a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index b65664e1..41ded156 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -129,7 +129,8 @@ public class TYPEStmt implements StatementVisitor { @Override public void visit(ForStmt forStmt) { forStmt.initializer.forEach(s -> s.accept(this)); - forStmt.condition.accept(this); + if (forStmt.condition != null) + forStmt.condition.accept(this); forStmt.loopExpr.forEach(e -> e.accept(this)); forStmt.block.accept(this); } diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index dc15ec80..4de13307 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -841,4 +841,11 @@ public class TestComplete { var clazz = classFiles.get("Op2"); var instance = clazz.getDeclaredConstructor().newInstance(); } + + @Test + public void testBug122() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug122.jav"); + var clazz = classFiles.get("Bug122"); + var instance = clazz.getDeclaredConstructor().newInstance(); + } } From 59585296b03b0957efdf8304d57c6547148e8d0a Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Mon, 4 Mar 2024 11:30:36 +0100 Subject: [PATCH 15/18] Fix single expressions not converting to blocks. Fixes #123 --- resources/bytecode/javFiles/Bug123.jav | 13 +++++++++++++ .../SyntaxTreeGenerator/StatementGenerator.java | 1 - .../target/generate/ASTToTargetAST.java | 7 +++++++ .../generate/StatementToTargetExpression.java | 6 +++--- src/test/java/TestComplete.java | 7 +++++++ 5 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 resources/bytecode/javFiles/Bug123.jav diff --git a/resources/bytecode/javFiles/Bug123.jav b/resources/bytecode/javFiles/Bug123.jav new file mode 100644 index 00000000..24cca90e --- /dev/null +++ b/resources/bytecode/javFiles/Bug123.jav @@ -0,0 +1,13 @@ +import java.lang.Boolean; +import java.lang.Integer; + +class Bug123 { + Boolean works(){ + if(true) return true; + else return false; + } + void fails(){ + Boolean a = true; + if(true) a = false; + } +} diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index 27f0bf6b..000526b3 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -633,7 +633,6 @@ public class StatementGenerator { /* *************** + Expression Conversions: */ - private Expression convert(Java17Parser.ExpressionContext expression) { switch (expression) { case PrimaryExpression2Context primary: diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index a7e82f51..86b227b4 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -380,6 +380,13 @@ public class ASTToTargetAST { return new TargetBlock(block.statements.stream().map(this::convert).toList()); } + protected TargetBlock convertWrapInBlock(Expression expression) { + var res = convert(expression); + if (!(res instanceof TargetBlock)) + return new TargetBlock(List.of(res)); + return (TargetBlock) res; + } + protected TargetExpression convert(Expression expr) { var converter = new StatementToTargetExpression(this); expr.accept(converter); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 9117a8d6..22554417 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -145,18 +145,18 @@ public class StatementToTargetExpression implements ASTVisitor { forStmt.initializer.stream().map(converter::convert).toList(), forStmt.condition != null ? converter.convert(forStmt.condition) : null, forStmt.loopExpr.stream().map(converter::convert).toList(), - converter.convert(forStmt.block) + converter.convertWrapInBlock(forStmt.block) ); } @Override public void visit(ForEachStmt forEachStmt) { - result = new TargetForEach(converter.convert(forEachStmt.statement), converter.convert(forEachStmt.expression), converter.convert(forEachStmt.block)); + result = new TargetForEach(converter.convert(forEachStmt.statement), converter.convert(forEachStmt.expression), converter.convertWrapInBlock(forEachStmt.block)); } @Override public void visit(IfStmt ifStmt) { - result = new TargetIf(converter.convert(ifStmt.expr), converter.convert(ifStmt.then_block), ifStmt.else_block != null ? converter.convert(ifStmt.else_block) : null); + result = new TargetIf(converter.convert(ifStmt.expr), converter.convertWrapInBlock(ifStmt.then_block), ifStmt.else_block != null ? converter.convertWrapInBlock(ifStmt.else_block) : null); } @Override diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index 4de13307..e188ee37 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -848,4 +848,11 @@ public class TestComplete { var clazz = classFiles.get("Bug122"); var instance = clazz.getDeclaredConstructor().newInstance(); } + + @Test + public void testBug123() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug123.jav"); + var clazz = classFiles.get("Bug123"); + var instance = clazz.getDeclaredConstructor().newInstance(); + } } From f2e43f180c33e618fc52f7224807cdb8bb72b36a Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Mon, 4 Mar 2024 11:51:28 +0100 Subject: [PATCH 16/18] Add test for issue #125 --- resources/bytecode/javFiles/Bug125.jav | 16 ++++++++++++++++ src/test/java/TestComplete.java | 7 +++++++ 2 files changed, 23 insertions(+) create mode 100644 resources/bytecode/javFiles/Bug125.jav diff --git a/resources/bytecode/javFiles/Bug125.jav b/resources/bytecode/javFiles/Bug125.jav new file mode 100644 index 00000000..26474ae2 --- /dev/null +++ b/resources/bytecode/javFiles/Bug125.jav @@ -0,0 +1,16 @@ +import java.lang.Boolean; +import java.lang.Integer; +import java.lang.String; +import java.util.List; +import java.util.LinkedList; +import java.util.ArrayList; + +class Bug125 { + static ArrayList works = new ArrayList<>(); + static List fails = new ArrayList<>(); + + void main() { + works.toString(); + fails.toString(); + } +} diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index e188ee37..572b6a67 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -855,4 +855,11 @@ public class TestComplete { var clazz = classFiles.get("Bug123"); var instance = clazz.getDeclaredConstructor().newInstance(); } + + @Test + public void testBug125() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug125.jav"); + var clazz = classFiles.get("Bug125"); + var instance = clazz.getDeclaredConstructor().newInstance(); + } } From 388614b220e75757dea0819866d5863a32fa1143 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Mon, 4 Mar 2024 12:00:29 +0100 Subject: [PATCH 17/18] Add testcase for LamRunnable --- resources/bytecode/javFiles/LamRunnable.jav | 15 +++++++++++---- src/test/java/TestComplete.java | 7 +++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/resources/bytecode/javFiles/LamRunnable.jav b/resources/bytecode/javFiles/LamRunnable.jav index 451858f2..d0da84cc 100644 --- a/resources/bytecode/javFiles/LamRunnable.jav +++ b/resources/bytecode/javFiles/LamRunnable.jav @@ -1,8 +1,15 @@ -public class LamRunnable{ +import java.lang.Runnable; +import java.lang.System; +import java.lang.String; +import java.io.PrintStream; + +public class LamRunnable { + + public LamRunnable() { + Runnable lam = () -> { + System.out.println("lambda"); + }; - public LamRunnable(){ - - Runnable lam = () -> {System.out.println("lambda");}; lam.run(); } } diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index 572b6a67..e671b5dc 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -842,6 +842,13 @@ public class TestComplete { var instance = clazz.getDeclaredConstructor().newInstance(); } + @Test + public void testLamRunnable() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "LamRunnable.jav"); + var clazz = classFiles.get("LamRunnable"); + var instance = clazz.getDeclaredConstructor().newInstance(); + } + @Test public void testBug122() throws Exception { var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug122.jav"); From 1877d7f170b97c75f312e547303016b201498607 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Mon, 4 Mar 2024 12:19:56 +0100 Subject: [PATCH 18/18] Add test for #112 --- resources/bytecode/javFiles/Bug112.jav | 7 +++++++ src/test/java/TestComplete.java | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 resources/bytecode/javFiles/Bug112.jav diff --git a/resources/bytecode/javFiles/Bug112.jav b/resources/bytecode/javFiles/Bug112.jav new file mode 100644 index 00000000..34567f03 --- /dev/null +++ b/resources/bytecode/javFiles/Bug112.jav @@ -0,0 +1,7 @@ +public class Bug112 { + m(x) { + var y; + x = y; + return y; + } +} \ No newline at end of file diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index e671b5dc..307f04cd 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -869,4 +869,11 @@ public class TestComplete { var clazz = classFiles.get("Bug125"); var instance = clazz.getDeclaredConstructor().newInstance(); } + + @Test + public void testBug112() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug112.jav"); + var clazz = classFiles.get("Bug112"); + var instance = clazz.getDeclaredConstructor().newInstance(); + } }