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/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/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/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/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/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/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/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/resources/bytecode/javFiles/Literal.jav b/resources/bytecode/javFiles/Literal.jav new file mode 100644 index 00000000..52e1c8c9 --- /dev/null +++ b/resources/bytecode/javFiles/Literal.jav @@ -0,0 +1,6 @@ +import java.lang.Character; + +public class Literal { + m() { return null; } + m2() { return 'C'; } +} \ No newline at end of file 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/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/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 5ef179d3..7445e772 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; @@ -135,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); } } @@ -156,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); } } @@ -805,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); @@ -884,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(); @@ -918,6 +924,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(); @@ -1036,15 +1045,50 @@ 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); } } + 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; if (instanceOf.right() instanceof TargetTypePattern right && right.name() == null) { + generate(state, instanceOf.left()); mv.visitTypeInsn(INSTANCEOF, right.type().getInternalName()); return; } @@ -1349,8 +1393,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/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/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/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index 3611f003..000526b3 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -490,15 +490,33 @@ 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 + 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()) ); } } @@ -594,8 +612,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) { @@ -616,7 +633,6 @@ public class StatementGenerator { /* *************** + Expression Conversions: */ - private Expression convert(Java17Parser.ExpressionContext expression) { switch (expression) { case PrimaryExpression2Context primary: @@ -690,13 +706,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; } @@ -779,7 +801,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..40d2a323 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; @@ -100,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 @@ -125,6 +119,7 @@ public class SyntaxTreeGenerator { this.allmodifiers.put("strictfp", 32768); this.compiler = compiler; + this.fileName = fileName; } public JavaClassRegistry getReg() { @@ -234,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); } @@ -280,8 +275,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 +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, 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, fileName); } private void convert(ClassBodyDeclarationContext classBody, List fields, List constructors, List methods, JavaClassName name, RefType superClass, GenericsRegistry generics) { @@ -409,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) { @@ -451,18 +446,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 +472,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 +551,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 +580,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/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/syntaxtree/AbstractASTWalker.java b/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java index 9b8d5286..fde26cb7 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); @@ -261,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/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/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/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/StatementVisitor.java b/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java index 737e984e..c7a6c2a7 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); @@ -74,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/factory/ASTFactory.java b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java index 48c4830d..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; } @@ -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/syntaxtree/factory/UnifyTypeFactory.java b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java index 92b72ec4..4037d2f4 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; @@ -9,13 +8,13 @@ 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; 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 +23,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 +43,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, SourceLoc 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, SourceLoc 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, SourceLoc 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, SourceLoc location){ + return new UnifyPair(tl, tr, PairOperator.EQUALSDOT, location); } /** @@ -164,19 +164,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/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/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/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 1afcfdea..e68adda6 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("); @@ -402,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/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 1e5d77d5..22554417 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -141,12 +141,22 @@ 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.convertWrapInBlock(forStmt.block) + ); + } + + @Override + public void visit(ForEachStmt forEachStmt) { + 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 @@ -315,9 +325,16 @@ 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(); } } + @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 f7feb9f4..7967f0c4 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); @@ -168,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/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/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/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/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/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/constraints/Pair.java b/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java index 78513531..a485ba5e 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java @@ -3,9 +3,12 @@ import java.io.Serializable; 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; +import org.antlr.v4.runtime.Token; public class Pair implements Serializable @@ -13,11 +16,13 @@ public class Pair implements Serializable public final RefTypeOrTPHOrWildcardOrGeneric TA1; public final RefTypeOrTPHOrWildcardOrGeneric TA2; + private SourceLoc 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 +37,11 @@ public class Pair implements Serializable this(TA1,TA2); this.eOperator = eOp; } - + + public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator e0p, SourceLoc location) { + this(TA1, TA2, e0p); + this.location = location; + } public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator eOp, Boolean noUnification) { @@ -41,6 +50,10 @@ public class Pair implements Serializable this.eOperator = eOp; this.noUnification = noUnification; } + + public SourceLoc 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 154beca8..41ded156 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)); - constraintsSet.addUndConstraint(new Pair(lambdaExpression.getReturnType(), tphRetType, PairOperator.EQUALSDOT)); + 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)); + 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)); // 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, 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) @@ -123,32 +129,42 @@ 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); } + @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, loc(forEachStmt.getOffset()))); + 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()); // 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, 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)); + constraintsSet.addUndConstraint(new Pair(ifStmt.else_block.getType(), ifStmt.getType(), PairOperator.SMALLERDOT, loc(ifStmt.getOffset()))); } } @Override public void visit(InstanceOf instanceOf) { - //throw new NotImplementedException(); + instanceOf.getExpression().accept(this); } @Override @@ -217,15 +233,17 @@ 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) { 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, 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)); + constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), unaryExpr.getType(), PairOperator.EQUALSDOT, loc(unaryExpr.getOffset()))); } else { throw new NotImplementedException(); } @@ -252,49 +270,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, 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)); - 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, 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)); - 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, 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)); - 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, 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)); - 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, 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)); - 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, 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); } /* @@ -307,9 +325,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, 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); } } @@ -328,10 +346,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, 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)); + 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)); @@ -343,7 +361,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, loc(binary.getOffset()))); } else { throw new NotImplementedException(); } @@ -352,9 +370,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, 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; @@ -367,23 +385,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, loc(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, loc(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, loc(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, loc(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, loc(literal.getOffset()))); return; } if (literal.value instanceof Integer) { @@ -392,31 +410,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, 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)); + 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)); + 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)); + 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)); + 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)); + constraint.add(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT, loc(literal.getOffset()))); oderConstraints.add(constraint); } constraintsSet.addOderConstraint(oderConstraints); @@ -424,33 +442,43 @@ 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, loc(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, loc(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, loc(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, loc(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, loc(literal.getOffset()))); return; - } else { + } + if (literal.value instanceof Character) { + constraintsSet.addUndConstraint(new Pair(literal.getType(), charr, PairOperator.EQUALSDOT, loc(literal.getOffset()))); + return; + } + if (literal.value != null) { throw new NotImplementedException(); } } + @Override + public void visit(Throw aThrow) { + aThrow.expr.accept(this); + } + @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, loc(returnExpr.getOffset()))); } @Override @@ -482,7 +510,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, loc(aThis.getOffset()))); } private static TypeScope createNullTypeScope() { @@ -505,7 +533,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, loc(whileStmt.expr.getOffset()))); // LoopBlock inferieren: whileStmt.loopBlock.accept(this); } @@ -529,7 +557,22 @@ 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 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); + methodConstraints.addAll(oneMethodConstraints); + } + break; + } + } + constraintsSet.addOderConstraint(methodConstraints); } /* @@ -549,10 +592,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, 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)); + // PL 2023-01-24: dafuer ? extends receiverType noch ergaenzt + extendsMethodConstraint.add(new Pair(forMethod.receiver.getType(), new ExtendsWildcardType(receiverType, receiverType.getOffset()), PairOperator.EQUALSDOT, loc(forMethod.getOffset()))); + } // gegenseite Verschraenkung der beiden Mengen von Typannahmen methodConstraint.setExtendConstraint(extendsMethodConstraint); @@ -563,13 +608,14 @@ 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, 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)); - ((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); @@ -596,7 +642,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, 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)); @@ -616,7 +662,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; } @@ -691,7 +736,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, loc(forConstructor.getOffset()))); // WELCHEN SINN MACHT DIESER CONSTRAINT??? methodConstraint.addAll(generateParameterConstraints(forConstructor, assumption, info, resolver)); return methodConstraint; @@ -715,17 +760,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, loc(label.getOffset()))); } } } } else { - constraintsSet.addUndConstraint(new Pair(caseExpressionType, switchStmt.getSwitch().getType(), PairOperator.EQUALSDOT)); + 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)); + constraintsSet.addUndConstraint(new Pair(child.getType(), switchStmt.getType(), PairOperator.SMALLERDOT, loc(switchStmt.getOffset()))); } switchStack.pop(); @@ -746,7 +791,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, loc(aYield.getOffset()))); // TODO Auto-generated method stub } } 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..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; @@ -10,6 +11,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 +24,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, SourceLoc 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..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; @@ -27,6 +28,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 +147,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 +262,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, SourceLoc location) { Set ret; if ((ret = greaterHash.get(new hashKeyType(type))) != null) { //System.out.println(greaterHash); @@ -302,7 +303,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 +345,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(); - + // Caching hashcode hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode(); - } + } + + public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, SourceLoc location) { + this(lhs, rhs, op); + this.location = location; + } public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, Set 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, SourceLoc location) { this.lhs = lhs; this.rhs = rhs; pairOp = op; substitution = uni; basePair = base; - - + this.location = location; + //this.fBounded = fBounded; // what? + // 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 SourceLoc getLocation() { + if (location != null) return location; + else if (basePair != null) return basePair.getLocation(); + return null; } /** @@ -231,7 +252,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.line() + " in " + location.file(); + } + + return res; } /* diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index 4e885284..307f04cd 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; @@ -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"); @@ -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 { @@ -772,4 +781,99 @@ 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(); + } + + @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)); + } + + @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!"); + } + } + } + + @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)); + assertEquals(clazz.getDeclaredMethod("m2").invoke(instance), 'C'); + } + + @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); + } + + @Test + public void testStringConcat() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Op2.jav"); + var clazz = classFiles.get("Op2"); + 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"); + 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(); + } + + @Test + public void testBug125() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug125.jav"); + 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(); + } } 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");