diff --git a/resources/bytecode/javFiles/SuperCall.jav b/resources/bytecode/javFiles/SuperCall.jav new file mode 100644 index 00000000..08b8a046 --- /dev/null +++ b/resources/bytecode/javFiles/SuperCall.jav @@ -0,0 +1,11 @@ +import java.lang.Integer; + +class Parent { + public Parent(Integer x) {} +} + +public class SuperCall extends Parent { + public SuperCall() { + super(20); + } +} \ No newline at end of file diff --git a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java index 6cd9a3bc..dffcebeb 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java @@ -1382,8 +1382,8 @@ public class Codegen { generate(state, stmts.get(0)); if (constructor.fieldInitializer() != null) { var stmts2 = constructor.fieldInitializer().statements(); - for (var i = 1; i < stmts2.size(); i++) { - generate(state, stmts2.get(i)); + for (TargetExpression expression : stmts2) { + generate(state, expression); } } for (var i = 1; i < stmts.size(); i++) diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index 4514a0f5..39914f0d 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -707,13 +707,19 @@ public class StatementGenerator { } else if (!Objects.isNull(expr.SUPER())) { // if(methodInvocationContext.Identifier() != null){ name = expr.SUPER().getText(); - receiver = new Super(offset); } ArgumentList argumentList = convertArguments(expr.expressionList()); ArrayList signature = argumentList.getArguments().stream().map(x -> (RefTypeOrTPHOrWildcardOrGeneric) TypePlaceholder.fresh(offset)).collect(Collectors.toCollection(ArrayList::new)); signature.add(TypePlaceholder.fresh(offset)); // return type - MethodCall ret = new MethodCall(TypePlaceholder.fresh(offset), getReceiver(receiver), name, argumentList, TypePlaceholder.fresh(offset), signature, offset); + + MethodCall ret; + if (expr.SUPER() != null) { + ret = new SuperCall(argumentList, TypePlaceholder.fresh(offset), signature, offset); + } else { + ret = new MethodCall(TypePlaceholder.fresh(offset), getReceiver(receiver), name, argumentList, TypePlaceholder.fresh(offset), signature, offset); + } + ret.setStatement(); return ret; } @@ -796,7 +802,7 @@ public class StatementGenerator { receiver = new This(offset); isStatic = Modifier.isStatic(fields.get(fieldName).modifiers()); } else if (parts[0].contentEquals("super")) { - receiver = new Super(offset); + receiver = new Super(TypePlaceholder.fresh(offset), offset); isStatic = Modifier.isStatic(compiler.getClass(new JavaClassName(superClass.getName().toString())).getField(fieldName).orElseThrow().modifier); } else if (receiver == null) { // Handelt es sich um keinen Statischen Klassennamen: String part = expression.substring(0, expression.length() - (1 + parts[parts.length - 1].length())); diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java index 895c4ecd..dafc1eca 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java @@ -16,6 +16,7 @@ import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.Record; +import de.dhbwstuttgart.syntaxtree.statement.*; import org.antlr.v4.runtime.CommonToken; import org.antlr.v4.runtime.Token; @@ -66,15 +67,6 @@ import de.dhbwstuttgart.parser.scope.GenericsRegistry; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.parser.scope.JavaClassRegistry; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; -import de.dhbwstuttgart.syntaxtree.statement.Assign; -import de.dhbwstuttgart.syntaxtree.statement.AssignLeftSide; -import de.dhbwstuttgart.syntaxtree.statement.AssignToField; -import de.dhbwstuttgart.syntaxtree.statement.Block; -import de.dhbwstuttgart.syntaxtree.statement.FieldVar; -import de.dhbwstuttgart.syntaxtree.statement.LocalVar; -import de.dhbwstuttgart.syntaxtree.statement.Return; -import de.dhbwstuttgart.syntaxtree.statement.Statement; -import de.dhbwstuttgart.syntaxtree.statement.This; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; @@ -280,8 +272,8 @@ public class SyntaxTreeGenerator { methods.add(new Method(allmodifiers.get("public"), fieldname, fieldtype, new ParameterList(new ArrayList<>(), offset), new Block(Arrays.asList(returnStatement), offset), new GenericDeclarationList(new ArrayList<>(), offset), offset)); } RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), genericClassParameters, offset); - Constructor implicitConstructor = new Constructor(allmodifiers.get("public"), identifier, classType, new ParameterList(constructorParameters, offset), new Block(constructorStatements, offset), genericClassParameters, offset); - Optional initializations = Optional.of(implicitConstructor); + Constructor implicitConstructor = new Constructor(allmodifiers.get("public"), identifier, classType, new ParameterList(constructorParameters, offset), prepareBlock(new Block(constructorStatements, offset), superClass), genericClassParameters, offset); + //Optional initializations = Optional.of(implicitConstructor); constructors.add(implicitConstructor); for (ClassBodyDeclarationContext bodyDeclaration : recordDeclaration.recordBody().classBodyDeclaration()) { convert(bodyDeclaration, fielddecl, constructors, methods, name, superClass, generics); @@ -290,7 +282,7 @@ public class SyntaxTreeGenerator { implementedInterfaces.addAll(convert(recordDeclaration.typeList(), generics)); } var staticCtor = Optional.of(this.generateStaticConstructor(recordDeclaration.identifier().getText(), staticFieldInitializations, genericClassParameters, offset)); - return new Record(modifiers, name, fielddecl, initializations, staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset); + return new Record(modifiers, name, fielddecl, Optional.empty(), staticCtor, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset); } private void convert(ClassBodyDeclarationContext classBody, List fields, List constructors, List methods, JavaClassName name, RefType superClass, GenericsRegistry generics) { @@ -451,18 +443,24 @@ public class SyntaxTreeGenerator { return new Method(modifiers, name, retType, paramlist, block, gtvDeclarations, bodydeclaration.getStart()); } + protected static Block prepareBlock(Block constructorBlock, RefType superClass) { + List statements = constructorBlock.getStatements(); + if (statements.isEmpty() || !(statements.get(0) instanceof SuperCall)) { + var signature = new ArrayList(); + signature.add(new Void(new NullToken())); + statements.add(0, new SuperCall(superClass, signature, constructorBlock.getOffset())); + } + /* statements.addAll(fieldInitializations); geloescht PL 2018-11-24 */ + return new Block(statements, constructorBlock.getOffset()); + } + /** * http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.9 */ private Constructor generateStandardConstructor(String className, JavaClassName parentClass, RefType superClass, GenericDeclarationList classGenerics, Token offset) { RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset); ParameterList params = new ParameterList(new ArrayList<>(), offset); - Block block = new Block(new ArrayList<>(), offset); - // - // - return new Constructor(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset); // fieldInitializations - // geloescht PL - // 2018-11-24 + return new Constructor(Modifier.PUBLIC, className, classType, params, prepareBlock(new Block(new ArrayList<>(), offset), superClass), classGenerics, offset); // fieldInitializations // 2018-11-24 } /* @@ -471,10 +469,7 @@ public class SyntaxTreeGenerator { private Constructor generatePseudoConstructor(String className, List initializations, GenericDeclarationList classGenerics, Token offset) { RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset); ParameterList params = new ParameterList(new ArrayList<>(), offset); - Block block = new Block(new ArrayList<>(initializations), offset); - return new Constructor(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset /* - * fieldInitializations geloescht PL 2018-11-24 - */); + return new Constructor(Modifier.PUBLIC, className, classType, params, new Block(new ArrayList<>(initializations), offset), classGenerics, offset); } private Method generateStaticConstructor(String className, List initializations, GenericDeclarationList classGenerics, Token offset) { @@ -553,7 +548,7 @@ public class SyntaxTreeGenerator { block = stmtgen.convert(methodblock.block(), true); } if (name.equals(parentClass.getClassName())) { - return new Constructor(modifiers, name, retType, paramlist, block, gtvDeclarations, methoddeclaration.getStart()); + return new Constructor(modifiers, name, retType, paramlist, prepareBlock(block, superClass), gtvDeclarations, methoddeclaration.getStart()); } else { return new Method(modifiers, name, retType, paramlist, block, gtvDeclarations, methoddeclaration.getStart()); } @@ -582,7 +577,7 @@ public class SyntaxTreeGenerator { RefTypeOrTPHOrWildcardOrGeneric retType = TypeGenerator.convertTypeName(name, constructordeclaration.getStart(), reg, localgenerics); StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fields, new HashMap<>()); ParameterList paramlist = stmtgen.convert(constructordeclaration.formalParameters().formalParameterList()); - Block block = stmtgen.convert(constructordeclaration.constructorBody, true); + Block block = prepareBlock(stmtgen.convert(constructordeclaration.constructorBody, true), superClass); return new Constructor(modifiers, name, retType, paramlist, block, gtvDeclarations, constructordeclaration.getStart()); } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/Constructor.java b/src/main/java/de/dhbwstuttgart/syntaxtree/Constructor.java index 1c955c81..1cf3454a 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/Constructor.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/Constructor.java @@ -1,31 +1,25 @@ package de.dhbwstuttgart.syntaxtree; +import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.statement.Statement; +import de.dhbwstuttgart.syntaxtree.statement.Super; import de.dhbwstuttgart.syntaxtree.statement.SuperCall; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.Void; import org.antlr.v4.runtime.Token; import de.dhbwstuttgart.syntaxtree.statement.Block; +import java.sql.Ref; +import java.util.ArrayList; import java.util.List; public class Constructor extends Method { // TODO: Constructor braucht ein super-Statement - public Constructor(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block codeInsideConstructor, GenericDeclarationList gtvDeclarations, Token offset /* , List fieldInitializations geloescht PL 2018-11-24 */) { - super(modifier, name, returnType, parameterList, /* codeInsideConstructor, */ prepareBlock(codeInsideConstructor) /* ,fieldInitializations )geloescht PL 2018-11-24 ) */, gtvDeclarations, offset); - - } - - /** - * @param fieldInitializations - Das sind die Statements, welche die Felder der zugehörigen Klasse dieses Konstruktor initialisieren - */ - protected static Block prepareBlock(Block constructorBlock /* , List fieldInitializations new ArrayList<>() geloescht PL 2018-11-24 */) { - List statements = constructorBlock.getStatements(); - statements.add(0, new SuperCall(null, null, constructorBlock.getOffset())); - /* statements.addAll(fieldInitializations); geloescht PL 2018-11-24 */ - return new Block(statements, constructorBlock.getOffset()); + public Constructor(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block codeInsideConstructor, GenericDeclarationList gtvDeclarations, Token offset) { + super(modifier, name, returnType, parameterList, codeInsideConstructor, gtvDeclarations, offset); } @Override diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java index fdb672fb..e1deca0f 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java @@ -37,6 +37,7 @@ public class MethodCall extends Statement this.receiver = receiver; this.receiverType = receiverType; this.signature = signature; + if (signature == null) throw new NullPointerException(); } public List signatureArguments() { diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Super.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Super.java index fbeba99b..e56e2fe4 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Super.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Super.java @@ -1,6 +1,9 @@ package de.dhbwstuttgart.syntaxtree.statement; +import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation; @@ -9,9 +12,9 @@ import de.dhbwstuttgart.exceptions.NotImplementedException; public class Super extends Expression { - public Super(Token offset) + public Super(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) { - super(null,null); + super(type, offset); } @Override diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java index 3b7eebbf..e4a7ea01 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.syntaxtree.statement; +import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; @@ -9,6 +10,7 @@ import org.antlr.v4.runtime.Token; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; import java.util.ArrayList; +import java.util.List; public class SuperCall extends MethodCall @@ -20,7 +22,7 @@ public class SuperCall extends MethodCall public SuperCall(ArgumentList argumentList, RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList argTypes, Token offset){ - super(new Void(offset), new ExpressionReceiver(new This(offset)), "", argumentList, receiverType, argTypes, offset); + super(new Void(offset), new ExpressionReceiver(new Super(receiverType, offset)), "", argumentList, receiverType, argTypes, offset); } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java b/src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java index 23f08039..7125d3cd 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java @@ -8,6 +8,7 @@ import de.dhbwstuttgart.syntaxtree.TypeScope; import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.typeinference.constraints.GenericsResolver; import java.util.ArrayList; @@ -66,6 +67,7 @@ public class MethodAssumption extends Assumption{ * @return */ public RefTypeOrTPHOrWildcardOrGeneric getReceiverType(GenericsResolver resolver) { + if (receiver == null) return null; List params = new ArrayList<>(); for(GenericTypeVar gtv : receiver.getGenerics()){ //Die Generics werden alle zu TPHs umgewandelt. diff --git a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index ac023831..6920dab2 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -538,7 +538,23 @@ public class TYPEStmt implements StatementVisitor { @Override public void visit(SuperCall superCall) { - // TODO: Für einen super-Call werden keine Constraints erzeugt bisher + Set> methodConstraints = new HashSet<>(); + for (var clazz : info.getAvailableClasses()) { + if (clazz.getClassName().equals(info.getCurrentClass().getSuperClass().getName())) { + for (var ctor : clazz.getConstructors()) { + var assumption = new MethodAssumption(null, new Void(new NullToken()), convertParams(ctor.getParameterList(), info), createTypeScope(clazz, ctor), ctor.isInherited); + + GenericsResolver resolver = getResolverInstance(); + Set> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver); + System.out.println(">>>"); + System.out.println(oneMethodConstraints); + System.out.println("<<<"); + methodConstraints.addAll(oneMethodConstraints); + } + break; + } + } + constraintsSet.addOderConstraint(methodConstraints); } /* @@ -558,10 +574,12 @@ public class TYPEStmt implements StatementVisitor { */ RefTypeOrTPHOrWildcardOrGeneric receiverType = assumption.getReceiverType(resolver); - methodConstraint.add(new Pair(forMethod.receiver.getType(), receiverType, PairOperator.EQUALSDOT));// PL 2020-03-17 SMALLERDOT in EQUALSDOT umgewandelt, weil alle geerbten Methoden in den jeweilen Klassen enthalten sind. + if (receiverType != null) { + methodConstraint.add(new Pair(forMethod.receiver.getType(), receiverType, PairOperator.EQUALSDOT));// PL 2020-03-17 SMALLERDOT in EQUALSDOT umgewandelt, weil alle geerbten Methoden in den jeweilen Klassen enthalten sind. - // PL 2023-01-24: dafuer ? extends receiverType noch ergaenzt - extendsMethodConstraint.add(new Pair(forMethod.receiver.getType(), new ExtendsWildcardType(receiverType, receiverType.getOffset()), PairOperator.EQUALSDOT)); + // PL 2023-01-24: dafuer ? extends receiverType noch ergaenzt + extendsMethodConstraint.add(new Pair(forMethod.receiver.getType(), new ExtendsWildcardType(receiverType, receiverType.getOffset()), PairOperator.EQUALSDOT)); + } // gegenseite Verschraenkung der beiden Mengen von Typannahmen methodConstraint.setExtendConstraint(extendsMethodConstraint); @@ -578,7 +596,8 @@ public class TYPEStmt implements StatementVisitor { // methodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT)); // extendsMethodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT)); - ((TypePlaceholder) forMethod.getType()).setOrCons((byte) -1);// fuer Maximums-Bestimmung + if (forMethod.getType() instanceof TypePlaceholder tph) + tph.setOrCons((byte) -1);// fuer Maximums-Bestimmung Set parameterContraints = generateParameterConstraints(forMethod, assumption, info, resolver); @@ -625,7 +644,6 @@ public class TYPEStmt implements StatementVisitor { } // Zuordnung von MethodCall.signature(ReturnType) zu dem ReturnType der ausgewaehlten Methode (assumption.returnType) - System.out.println(foMethod.name); ret.add(new Pair(foMethod.signature.get(foMethod.signature.size() - 1), assumption.getReturnType(), PairOperator.EQUALSDOT)); return ret; } diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index 1f50d362..34571c82 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -234,7 +234,7 @@ public class TestComplete { } @Test - //@Ignore("This is to complex") + //@Ignore("This is too complex") public void matrixTest() throws Exception { var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Matrix.jav"); var matrix = classFiles.get("Matrix"); @@ -781,4 +781,11 @@ public class TestComplete { var hello = clazz.getDeclaredMethod("hello"); hello.invoke(null); } + + @Test + public void testSuperCall() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "SuperCall.jav"); + var clazz = classFiles.get("SuperCall"); + var instance = clazz.getDeclaredConstructor().newInstance(); + } }