diff --git a/doc/PluginBau.pdf b/doc/PluginBau.pdf index f6bab5cc..9489a7a9 100644 Binary files a/doc/PluginBau.pdf and b/doc/PluginBau.pdf differ diff --git a/doc/parser.md b/doc/parser.md new file mode 100644 index 00000000..b8263623 --- /dev/null +++ b/doc/parser.md @@ -0,0 +1,24 @@ +# Dateien +* sämtliche Datein im Ordner de.dhbwstuttgart.parser gehören zum Parser +* Auch zu beachten: pom.xml + * Ein Teil der pom.xml instruiert maven zur Kompilierung der Java8.g4 Datei + * VORSICHT! Wird nicht zwangsläufig von der IDE ausgeführt + * siehe Kapitel "Grammatik -> Parser" + + +## Unterordner antlr +* Java8.g4 + * die eigentliche Java Grammatik + * hier wurden Anpassungen vorgenommen, damit sie auch typloses Java annimmt +* alle anderen Dateien in diesem Ordner sind vom ANTLR-Parsergenerator autogeneriert + +## Unterordner SyntaxTreeGenerator +* SyntaxTreeGenerator +* TODO + +# Grammatik -> Parser +* Die Antlr-Grammatik (Java8.g4) wandelt +* Folgende Stellen sind relevant + * TODO + + diff --git a/src/de/dhbwstuttgart/bytecode/ArgumentVisitor.java b/src/de/dhbwstuttgart/bytecode/ArgumentVisitor.java index be0e1bc7..87c730ad 100644 --- a/src/de/dhbwstuttgart/bytecode/ArgumentVisitor.java +++ b/src/de/dhbwstuttgart/bytecode/ArgumentVisitor.java @@ -69,8 +69,11 @@ public class ArgumentVisitor implements StatementVisitor { public void visit(BinaryExpr binary) { binary.accept(bytecodeGenMethod); - if(argListMethCall.get(0)) + if(argListMethCall.get(0)) { bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(binary.getType())); + } else { + bytecodeGenMethod.doBoxing(bytecodeGenMethod.getResolvedType(binary.getType())); + } argListMethCall.remove(0); } diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java index 165c888c..cbd5a7c5 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -2,7 +2,9 @@ package de.dhbwstuttgart.bytecode; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import de.dhbwstuttgart.exceptions.NotImplementedException; @@ -13,6 +15,9 @@ import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; +import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; import de.dhbwstuttgart.bytecode.signature.Signature; @@ -21,6 +26,7 @@ import de.dhbwstuttgart.bytecode.signature.TypeToString; import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; import de.dhbwstuttgart.bytecode.utilities.NormalConstructor; import de.dhbwstuttgart.bytecode.utilities.NormalMethod; +import de.dhbwstuttgart.bytecode.utilities.Simplify; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.statement.Literal; @@ -56,8 +62,7 @@ public class BytecodeGen implements ASTVisitor { HashMap paramsAndLocals = new HashMap<>(); // stores generics and their bounds of class HashMap genericsAndBounds = new HashMap<>(); - // stores generics and their bounds of method - HashMap genericsAndBoundsMethod = new HashMap<>(); + private final TPHExtractor tphExtractor = new TPHExtractor(); private final ArrayList commonPairs = new ArrayList<>(); @@ -175,8 +180,32 @@ public class BytecodeGen implements ASTVisitor { @Override public void visit(Constructor field) { + System.out.println("ResultSet: "); + resultSet.results.forEach(a->{ + System.out.println(a.getLeft().toString() + " = " + a.getRight().toString()); + }); + System.out.println("---------------"); + + // stores generics and their bounds of method + HashMap genericsAndBoundsMethod = new HashMap<>(); + field.getParameterList().accept(this); + String methParamTypes = field.name+"%%"; + + Iterator itr = field.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+";"; +// methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToSignature())+";"; + } + + if(methodNameAndParamsT.contains(methParamTypes)) { + return; + } + methodNameAndParamsT.add(methParamTypes); + System.out.println("Method: "+field.name +" , paramsType: "+methParamTypes); + String desc = null; boolean hasGen = false; @@ -190,8 +219,8 @@ public class BytecodeGen implements ASTVisitor { } String sig = null; if(hasGen) { - ArrayList pairs = simplifyPairs(field.name,tphExtractor.allPairs); - Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes,resultSet,pairs); + HashMap> constraints = Simplify.simplifyConstraints(field.name, tphExtractor); + Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes,resultSet,constraints); sig = signature.toString(); } NormalConstructor constructor = new NormalConstructor(field,genericsAndBounds,hasGen); @@ -212,6 +241,7 @@ public class BytecodeGen implements ASTVisitor { // TODO: check if the method is static => if static then the first param will be stored in pos 0 // else it will be stored in pos 1 and this will be stored in pos 0 String retType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); +// String retType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); String methParamTypes = retType+method.name+"%%"; method.getParameterList().accept(this); @@ -219,6 +249,7 @@ public class BytecodeGen implements ASTVisitor { while(itr.hasNext()) { FormalParameter fp = itr.next(); methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+";"; +// methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToSignature())+";"; } if(methodNameAndParamsT.contains(methParamTypes)) { @@ -226,6 +257,8 @@ public class BytecodeGen implements ASTVisitor { } methodNameAndParamsT.add(methParamTypes); System.out.println("Method: "+method.name +" , paramsType: "+methParamTypes); + // stores generics and their bounds of method + HashMap genericsAndBoundsMethod = new HashMap<>(); String methDesc = null; // Method getModifiers() ? @@ -257,10 +290,12 @@ public class BytecodeGen implements ASTVisitor { /* if method has generics or return type is TPH, create signature */ // zwite operand muss weggelassen werden if(hasGen||resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToString()).equals("TPH")) { - ArrayList pairs = simplifyPairs(method.name,tphExtractor.allPairs); - System.out.println(method.name + " => Simplified Pairs: "); - pairs.forEach(p->System.out.println(p.TA1.getName() + " -> "+p.TA2.getName())); - Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds,methodParamsAndTypes,resultSet, pairs); + System.out.println("ALL CONST: " + tphExtractor.allCons.size()); + tphExtractor.allCons.forEach(c->System.out.println(c.toString())); + System.out.println("----------------"); + HashMap> constraints = Simplify.simplifyConstraints(method.name, tphExtractor); +// ArrayList pairs = simplifyPairs(method.name,tphExtractor.allPairs,tphExtractor.allCons); + Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds,methodParamsAndTypes,resultSet,constraints); sig = signature.toString(); } System.out.println(method.getName()+" ==> "+sig); @@ -278,145 +313,6 @@ public class BytecodeGen implements ASTVisitor { mv.visitEnd(); } - private ArrayList simplifyPairs(String methodName, ArrayList allPairs) { - allPairs.forEach(p->System.out.print(p.TA1 + " < "+ p.TA2+ " ; ")); - - if(allPairs.size() < 2) - return allPairs; - - ArrayList simplifiedPairs = new ArrayList<>(); - - ArrayList> beforeSimplify = new ArrayList<>(); - - MethodAndTPH method; - ArrayList methodTphs = new ArrayList<>(); - ArrayList methodPairs = new ArrayList<>(); - for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) { - if(m.getName().equals(methodName)) { - methodTphs = m.getTphs(); - methodPairs = m.getPairs(); - break; - } - } - - HashMap subAndSuperTph = new HashMap<>(); - for(GenericInsertPair p : allPairs) { - // Tph2.jav - if(subAndSuperTph.containsKey(p.TA1)) { - if(methodTphs.contains(subAndSuperTph.get(p.TA1))) - continue; - } - subAndSuperTph.put(p.TA1, p.TA2); - } - int numOfVisitedPairs = 0; - for(TypePlaceholder subTph: subAndSuperTph.keySet()) { - - if(numOfVisitedPairs>=subAndSuperTph.size()) - break; - - if(!methodTphs.contains(subTph)) - continue; - - HashMap tphsInRel= new HashMap<>(); - - tphsInRel.put(tphsInRel.size(), subTph); - TypePlaceholder superTph = subAndSuperTph.get(subTph); - tphsInRel.put(tphsInRel.size(), superTph); - - numOfVisitedPairs++; - boolean isCycle = false; - while(subAndSuperTph.containsKey(superTph)) { - superTph = subAndSuperTph.get(superTph); - if(tphsInRel.containsValue(superTph)) { - isCycle = true; - break; - } - tphsInRel.put(tphsInRel.size(), superTph); - numOfVisitedPairs++; - } - - // Subtype - TypePlaceholder subTphRes = tphsInRel.get(0); - // Die größte Supertype - TypePlaceholder superTphRes = tphsInRel.get(tphsInRel.size()-1); - - while(subAndSuperTph.containsValue(subTphRes)) { - for(TypePlaceholder tph : subAndSuperTph.keySet()) { - if(methodTphs.contains(tph) && subAndSuperTph.get(tph).equals(subTphRes)) { - subTphRes = tph; - break; - } - } - if(subTphRes.equals(tphsInRel.get(0))) { - break; - } - tphsInRel.put(0, subTphRes); - numOfVisitedPairs++; - } - - subTphRes = tphsInRel.get(0); - - int i = 2; - while(!methodTphs.contains(superTphRes) && (tphsInRel.size()-i) >0) { - superTphRes = tphsInRel.get(tphsInRel.size()-i); - i++; - } - - if((methodTphs.contains(superTphRes) || !tphExtractor.allTPHS.containsKey(superTphRes)) - && !subTphRes.equals(superTphRes)) { - - beforeSimplify.add(tphsInRel); - } - - // teste noch den Fall X < Y und Y nicht in TPHS der Methode - // Dann hat man nach der While-Schleife X < Y - // Y muss durch Object ersetzt. - - // Zweite Operand für die Fälle wie in Lambda.jav (Paramtrisierte Typen) - if((methodTphs.contains(superTphRes) || !tphExtractor.allTPHS.containsKey(superTphRes)) - && !subTphRes.equals(superTphRes)) { - GenericInsertPair sPair = new GenericInsertPair(subTphRes, superTphRes); - simplifiedPairs.add(sPair); - } - } - beforeSimplify.forEach(e->{ - System.out.println("=> "); - e.forEach((v,k) -> { - System.out.print(v + "->" + k + ", "); - }); - System.out.println(); - System.out.println("----------------------"); - }); - - if(beforeSimplify.size()>1) { - int i = 0; - while(i e: beforeSimplify) { - if(!e.equals(beforeSimplify.get(i)) && e.containsValue(sub)) { - GenericInsertPair sPair = new GenericInsertPair(e.get(0), sub); - System.out.println("To remove = " + e.get(0)+ " " +e.get(e.size()-1)); - removePair(simplifiedPairs,e.get(0), e.get(e.size()-1)); - simplifiedPairs.add(sPair); - } - } - i++; - } - } - - return simplifiedPairs; - } - - private void removePair(ArrayList simplifiedPairs, TypePlaceholder typePlaceholder, TypePlaceholder typePlaceholder2) { - for(GenericInsertPair p : simplifiedPairs) { - if(p.TA1.equals(typePlaceholder) && p.TA2.equals(typePlaceholder2)) { - simplifiedPairs.remove(p); - return; - } - } - } - @Override public void visit(ParameterList formalParameters) { paramsAndLocals = new HashMap<>(); @@ -469,16 +365,19 @@ public class BytecodeGen implements ASTVisitor { // ?? @Override public void visit(FieldVar fieldVar) { + System.out.println("In FieldVar ---"); // cw.newField(fieldVar.receiver.toString(), fieldVar.fieldVarName.toString(), fieldVar.getType().toString()); FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, fieldVar.fieldVarName, "L"+fieldVar.getType()+";", null, null); fv.visitEnd(); } - // access flages?? modifiers @Override public void visit(Field field) { - FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, field.getName(), "L"+field.getType().toString().replace(".", "/")+";", null, null); - fv.visitEnd(); + System.out.println("In Field ---"); + cw.visitField(field.modifier, field.getName(), + "L"+resultSet.resolveType(field.getType()).resolvedType.acceptTV(new TypeToDescriptor())+";", + resultSet.resolveType(field.getType()).resolvedType.acceptTV(new TypeToSignature()), + null); } @Override @@ -659,14 +558,15 @@ public class BytecodeGen implements ASTVisitor { throw new NotImplementedException(); } - private class TPHExtractor extends AbstractASTWalker{ + public class TPHExtractor extends AbstractASTWalker{ // Alle TPHs der Felder werden iKopf der Klasse definiert // alle TPHs der Klasse: (TPH, is in Method?) final HashMap allTPHS = new HashMap<>(); MethodAndTPH methodAndTph; Boolean inMethod = false; - final ArrayList ListOfMethodsAndTph = new ArrayList<>(); + public final ArrayList ListOfMethodsAndTph = new ArrayList<>(); final ArrayList allPairs = new ArrayList<>(); + public final ArrayList allCons = new ArrayList<>(); @Override public void visit(TypePlaceholder tph) { @@ -681,6 +581,8 @@ public class BytecodeGen implements ASTVisitor { if(inMethod) methodAndTph.getPairs().add(ag); allPairs.add(ag); + TPHConstraint con = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); + allCons.add(con); } }); } diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index 643e98d5..3da49bca 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -9,6 +9,8 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.Parameter; +import java.net.URL; +import java.net.URLClassLoader; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -68,6 +70,8 @@ public class BytecodeGenMethod implements StatementVisitor { private String path; private SourceFile sf; private IStatement statement = null; + private boolean isReturnStmt = false; + private boolean isParentBinary = false; private boolean needDUP = false; @@ -106,14 +110,14 @@ public class BytecodeGenMethod implements StatementVisitor { } public BytecodeGenMethod(LambdaExpression lambdaExpression, ResultSet resultSet, MethodVisitor mv, - int indexOfFirstParamLam, boolean isInterface, HashMap classFiles, String path) { + int indexOfFirstParamLam, boolean isInterface, HashMap classFiles, String path, int lamCounter) { this.resultSet = resultSet; this.mv = mv; this.isInterface = isInterface; this.classFiles = classFiles; this.path = path; - + this.lamCounter = lamCounter; Iterator itr = lambdaExpression.params.iterator(); int i = indexOfFirstParamLam; while (itr.hasNext()) { @@ -208,7 +212,7 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(BinaryExpr binary) { - + isParentBinary = true; String lexpType = getResolvedType(binary.lexpr.getType()); String rexpType = getResolvedType(binary.rexpr.getType()); @@ -223,7 +227,7 @@ public class BytecodeGenMethod implements StatementVisitor { } Label endLabel = new Label(); - // this case for while loops + // this case for while loops and If statements if (statement instanceof LoopStmt) mv.visitLabel(endLabel); @@ -239,12 +243,14 @@ public class BytecodeGenMethod implements StatementVisitor { needDUP = true; binary.rexpr.accept(this); - + + isParentBinary = false; + if (!lexpType.equals(rexpType) && !rexpType.equals(largerType)) doCast(rexpType, largerType); Operator op = binary.operation; - + switch (op) { case ADD: doVisitAddOpInsn(largerType); @@ -270,6 +276,8 @@ public class BytecodeGenMethod implements StatementVisitor { case LESSEQUAL: case BIGGERTHAN: case BIGGEREQUAL: + case EQUAL: + case NOTEQUAL: Label branchLabel = new Label(); doVisitRelOpInsn(op, largerType, branchLabel, endLabel); break; @@ -277,7 +285,6 @@ public class BytecodeGenMethod implements StatementVisitor { default: break; } - } private String getLargerType(String lexpType, String rexpType) { @@ -501,6 +508,18 @@ public class BytecodeGenMethod implements StatementVisitor { public void visit(LambdaExpression lambdaExpression) { this.lamCounter++; + String typeErasure = "("; + Iterator itr = lambdaExpression.params.iterator(); + while (itr.hasNext()) { + itr.next(); + typeErasure += "L" + Type.getInternalName(Object.class) + ";"; + } + + typeErasure += ")L" + Type.getInternalName(Object.class) + ";"; + + generateBCForFunN(lambdaExpression, typeErasure); + + Lambda lam = new Lambda(lambdaExpression); String lamDesc = lam.accept(new DescriptorToString(resultSet)); // Call site, which, when invoked, returns an instance of the functional @@ -516,20 +535,12 @@ public class BytecodeGenMethod implements StatementVisitor { // Für die Parameter-Typen und Return-Typ braucht man die Bounds (für die // Typlöschung) - String typeErasure = "("; - Iterator itr = lambdaExpression.params.iterator(); - while (itr.hasNext()) { - itr.next(); - typeErasure += "L" + Type.getInternalName(Object.class) + ";"; - } - - typeErasure += ")L" + Type.getInternalName(Object.class) + ";"; // Type erasure Type arg1 = Type.getMethodType(typeErasure); // Type arg1 = Type.getMethodType(lamDesc); // real Type Type arg3 = Type.getMethodType(lamDesc); - + int staticOrSpecial = 0; int staticOrInstance = 0; int indexOfFirstParamLam = 0; @@ -556,14 +567,14 @@ public class BytecodeGenMethod implements StatementVisitor { methodName, arg3.toString(), null, null); new BytecodeGenMethod(lambdaExpression, this.resultSet, mvLambdaBody, indexOfFirstParamLam, isInterface, - classFiles,this.path); + classFiles,this.path, lamCounter); mvLambdaBody.visitMaxs(0, 0); mvLambdaBody.visitEnd(); cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup", "java/lang/invoke/MethodHandles", "Lookup", Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL); - generateBCForFunN(lambdaExpression, typeErasure); +// generateBCForFunN(lambdaExpression, typeErasure); } private void generateBCForFunN(LambdaExpression lambdaExpression, String methDesc) { @@ -644,7 +655,10 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(IfStmt ifStmt) { - System.out.println("If"); + statement = new IfStatement(ifStmt.expr, ifStmt.then_block, ifStmt.else_block); + isBinaryExp = statement.isExprBinary(); + ifStmt.expr.accept(this); + statement = null; } @Override @@ -654,77 +668,106 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(MethodCall methodCall) { + boolean parentBinary = isParentBinary; System.out.println("In MethodCall = " + methodCall.name); String receiverName = getResolvedType(methodCall.receiver.getType()); System.out.println("Methods of " + receiverName + " "); ClassLoader cLoader = ClassLoader.getSystemClassLoader(); + // This will be used if the class is not standard class (not in API) + ClassLoader cLoader2; java.lang.reflect.Method methodRefl = null; String clazz = receiverName.replace("/", "."); + String methCallType = resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + String[] typesOfParams = getTypes(methodCall.arglist.getArguments()); try { if(receiverName.contains("<")) { clazz = clazz.substring(0, receiverName.indexOf("<")); } + java.lang.reflect.Method[] methods = cLoader.loadClass(clazz).getMethods(); System.out.println("Methods of " + receiverName + " "); - for(java.lang.reflect.Method m : methods) { - if(methodCall.name.equals(m.getName())) { - methodRefl = m; - break; - } - } + methodRefl = getMethod(methodCall.name,methodCall.arglist.getArguments().size(),methods); + } catch (Exception e) { - String superClass = ""; - // TODO: Test SubMatrix.jav - while(true) { - for(ClassOrInterface cl : sf.getClasses()) { - if(receiverName.equals(cl.getClassName().toString())) { - superClass = cl.getSuperClass().getName().toString(); - break; - } - } - System.out.println(superClass); - - if(superClass.equals("")) - break; - - try { - String superClazz = superClass.replace("/", "."); - if(superClass.contains("<")) { - superClazz = superClazz.substring(0, superClass.indexOf("<")); - } - java.lang.reflect.Method[] methods = cLoader.loadClass(superClazz).getMethods(); - System.out.println("Methods of " + superClass + " "); - - for(java.lang.reflect.Method m : methods) { - if(methodCall.name.equals(m.getName())) { - methodRefl = m; +// try { +// cLoader2 = new URLClassLoader(new URL[] {new URL("file://"+path)}); +// java.lang.reflect.Method[] methods = cLoader2.loadClass(clazz).getMethods(); +// System.out.println("Methods of " + receiverName + " "); +// for(int i = 0; i argListMethCall = new LinkedList<>(); + String receiverRefl=""; if(methodRefl == null) { MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), receiverName, genericsAndBoundsMethod, genericsAndBounds); mDesc = method.accept(new DescriptorToString(resultSet)); methodCall.arglist.accept(this); } else { + receiverRefl = methodRefl.getAnnotatedReceiverType().getType().toString(); for(Parameter p:methodRefl.getParameters()) { System.out.println(p.getName() + " und is Primitive = " + p.getType().isPrimitive()); argListMethCall.add(p.getType().isPrimitive()); } + System.out.println("Receiver = " + methodRefl.getAnnotatedReceiverType().getType().toString()); mDesc = getMethodDesc(methodRefl); for (Expression al : methodCall.arglist.getArguments()) { statement = new ArgumentExpr(al); @@ -740,7 +783,7 @@ public class BytecodeGenMethod implements StatementVisitor { // methodCall.arglist.accept(this); // is methodCall.receiver functional Interface)? - if (varsFunInterface.contains(methodCall.receiver.getType())) { + if (varsFunInterface.contains(methodCall.receiver.getType()) || (methodRefl!= null && receiverRefl.contains("interface"))) { mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, clazz.replace(".", "/"), methodCall.name, mDesc, true); } else { @@ -759,8 +802,70 @@ public class BytecodeGenMethod implements StatementVisitor { if(isBinaryExp) doUnboxing(getResolvedType(methodCall.getType())); } + System.out.println("ISParent Binary = "+isParentBinary +" -> " + parentBinary); + if(methodRefl == null && (parentBinary || !isReturnStmt)) { + if(isBinaryExp) + doUnboxing(getResolvedType(methodCall.getType())); + } } + + private String[] getTypes(List arguments) { + String[] types = new String[arguments.size()]; + for(int i = 0; i[] pTypes = m.getParameterTypes(); + for(int j = 0; j RefType - private void doBoxing(String type) { + public void doBoxing(String type) { switch (type) { case "java/lang/String": mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", @@ -1191,7 +1305,6 @@ public class BytecodeGenMethod implements StatementVisitor { BinaryExpr binary = (BinaryExpr) al; String binaryType = getResolvedType(binary.getType()); doBoxing(binaryType); - isBinaryExp = false; } statement = null; } @@ -1207,8 +1320,9 @@ public class BytecodeGenMethod implements StatementVisitor { // array slot onto the top of the operand stack. assignLeftSide.field.receiver.accept(this); this.rightSideTemp.accept(this); + System.out.println("Receiver = " + getResolvedType(assignLeftSide.field.receiver.getType())); mv.visitFieldInsn(Opcodes.PUTFIELD, getResolvedType(assignLeftSide.field.receiver.getType()), - assignLeftSide.field.fieldVarName, getResolvedType(assignLeftSide.field.getType())); + assignLeftSide.field.fieldVarName, "L"+getResolvedType(assignLeftSide.field.getType())+";"); } @Override diff --git a/src/de/dhbwstuttgart/bytecode/IfStatement.java b/src/de/dhbwstuttgart/bytecode/IfStatement.java new file mode 100644 index 00000000..dc548f01 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/IfStatement.java @@ -0,0 +1,29 @@ +package de.dhbwstuttgart.bytecode; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.syntaxtree.statement.Statement; + +public class IfStatement extends AStatement{ + + private Statement then_block; + private Statement else_block; + + public IfStatement(Expression expr, Statement then_block, Statement else_block) { + super(expr); + this.then_block = then_block; + this.else_block = else_block; + } + + @Override + public void genBCForRelOp(MethodVisitor mv,Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod) { + bytecodeGenMethod.isBinary(false); + this.then_block.accept(bytecodeGenMethod); + + mv.visitLabel(branchLabel); + this.else_block.accept(bytecodeGenMethod); + } +} diff --git a/src/de/dhbwstuttgart/bytecode/constraint/EqualConstraint.java b/src/de/dhbwstuttgart/bytecode/constraint/EqualConstraint.java new file mode 100644 index 00000000..fb6cae20 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/constraint/EqualConstraint.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.bytecode.constraint; + +public class EqualConstraint extends TPHConstraint { + + public EqualConstraint(String left, String right, Relation rel) { + super(left, right, rel); + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/constraint/ExtendsConstraint.java b/src/de/dhbwstuttgart/bytecode/constraint/ExtendsConstraint.java new file mode 100644 index 00000000..6f28e24f --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/constraint/ExtendsConstraint.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.bytecode.constraint; + +public class ExtendsConstraint extends TPHConstraint { + + public ExtendsConstraint(String left, String right, Relation rel) { + super(left, right, rel); + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/constraint/TPHConstraint.java b/src/de/dhbwstuttgart/bytecode/constraint/TPHConstraint.java new file mode 100644 index 00000000..e0f3b4c0 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/constraint/TPHConstraint.java @@ -0,0 +1,55 @@ +package de.dhbwstuttgart.bytecode.constraint; + +public class TPHConstraint { + protected String left; + protected String right; + protected Relation rel; + public enum Relation{ + EXTENDS, EQUAL + } + + public TPHConstraint(String left, String right, Relation rel) { + this.left = left; + this.right = right; + this.rel = rel; + } + + public String getLeft() { + return left; + } + + + public String getRight() { + return right; + } + + + public Relation getRel() { + return rel; + } + + public void setLeft(String left) { + this.left = left; + } + + public void setRight(String right) { + this.right = right; + } + + public void setRel(Relation rel) { + this.rel = rel; + } + + public boolean containTPH(String tph) { + return left.equals(tph)||right.equals(tph); + } + + @Override + public String toString() { + if(rel == Relation.EXTENDS) { + return left + " < " + right; + }else { + return left + " = " + right; + } + } +} diff --git a/src/de/dhbwstuttgart/bytecode/signature/Signature.java b/src/de/dhbwstuttgart/bytecode/signature/Signature.java index 4daf3ded..8626cbf9 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/Signature.java +++ b/src/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -2,15 +2,18 @@ package de.dhbwstuttgart.bytecode.signature; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import org.objectweb.asm.Type; import org.objectweb.asm.signature.SignatureVisitor; import org.objectweb.asm.signature.SignatureWriter; +import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; -import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; -import de.dhbwstuttgart.syntaxtree.AbstractASTWalker; +import de.dhbwstuttgart.bytecode.utilities.Simplify; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.Constructor; import de.dhbwstuttgart.syntaxtree.GenericTypeVar; @@ -36,7 +39,7 @@ public class Signature { private HashMap methodParamsAndTypes; private ResultSet resultSet; private ArrayList commonPairs; - private ArrayList methodPairs; + private HashMap> methodConstraints; public Signature(ClassOrInterface classOrInterface, HashMap genericsAndBounds,ArrayList commonPairs) { this.classOrInterface = classOrInterface; @@ -47,24 +50,26 @@ public class Signature { } public Signature(Constructor constructor, HashMap genericsAndBounds, - HashMap methodParamsAndTypes,ResultSet resultSet,ArrayList methodPairs) { + HashMap methodParamsAndTypes,ResultSet resultSet, + HashMap> methodConstraints) { this.constructor = constructor; this.genericsAndBounds = genericsAndBounds; this.methodParamsAndTypes = methodParamsAndTypes; this.resultSet = resultSet; - this.methodPairs = methodPairs; + this.methodConstraints = methodConstraints; sw = new SignatureWriter(); createSignatureForConsOrMethod(this.constructor,true); } public Signature(Method method, HashMap genericsAndBoundsMethod,HashMap genericsAndBounds, - HashMap methodParamsAndTypes, ResultSet resultSet, ArrayList methodPairs) { + HashMap methodParamsAndTypes, ResultSet resultSet, + HashMap> methodConstraints) { this.method = method; this.genericsAndBoundsMethod = genericsAndBoundsMethod; this.genericsAndBounds = genericsAndBounds; this.methodParamsAndTypes = methodParamsAndTypes; this.resultSet = resultSet; - this.methodPairs = methodPairs; + this.methodConstraints = methodConstraints; sw = new SignatureWriter(); createSignatureForConsOrMethod(this.method,false); } @@ -111,104 +116,39 @@ public class Signature { getBoundsOfTypeVar(g,genericsAndBoundsMethod); } - //TODO: paramtrisierte Typen mit Generics, Type Variablen müssen definiert werden. - // Wenn die RückgabeType eine TPH ist, wird als generic behandelt // z.B: Type = TPH K => wird eine Formal Type Parameter K$ erzeugt und Bound = Object if(!isConstructor) { String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); + ArrayList allConsBeforeSimplify = new ArrayList<>(); + + HashMap> allConstraints = new HashMap<>(); + + if(ret.contains("<")) { + allConsBeforeSimplify = getAllConstraints((RefType) resultSet.resolveType(method.getReturnType()).resolvedType); + } + + for(String paramName : methodParamsAndTypes.keySet()) { + RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName); + String pT = t.acceptTV(new TypeToSignature()); + + if(pT.contains("<")) + allConsBeforeSimplify = getAllConstraints((RefType) t); + } + boolean doSimplify = false; + if(!allConsBeforeSimplify.isEmpty()) { + addConstraintsToMap(allConstraints,allConsBeforeSimplify); + doSimplify = true; + } + createTypeVars(allConstraints, doSimplify); + if(!ret.equals("V")) { - // TODO TypeToSignature nochmal kontrollieren und schauen ob man dort wirklich - // T... braucht und L ... if(ret.contains("$") && !ret.contains("$$") && !ret.contains("<")) { if(genericsAndBounds.containsKey(ret)) { genericsAndBoundsMethod.put(ret.substring(1), genericsAndBounds.get(ret.substring(1))); - }else { - sw.visitFormalTypeParameter(ret.substring(1)); - sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); - genericsAndBoundsMethod.put(ret.substring(1), Type.getInternalName(Object.class)); - sw.visitClassBound().visitEnd(); } } - if(ret.contains("<")) { - RefType ref = (RefType) resultSet.resolveType(method.getReturnType()).resolvedType; - if(hasTPHs(ref)) { - createSignatureForParameterizedType(ref); - } - System.out.println("HAS WC = " + hasWC(ref)); - if(hasWC(ref)) - createSigForParamTypeWithWC(ref); - } - } - } - - // Parameters - for(String paramName : methodParamsAndTypes.keySet()) { - RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName); - String pT = t.acceptTV(new TypeToSignature()); - // S.o - if(t instanceof TypePlaceholder) { - String gP = t.acceptTV(new TypeToSignature()); - if(!genericsAndBounds.containsKey(gP.substring(1)) && !genericsAndBoundsMethod.containsKey(gP.substring(1))) { - sw.visitFormalTypeParameter(gP.substring(1)); - String bound = Type.getInternalName(Object.class); - boolean isTypeVar = false; - for(GenericInsertPair pair : methodPairs) { - if(pT.substring(1,pT.length()-1).equals(pair.TA1.getName())) { - bound = pair.TA2.getName()+"$"; - isTypeVar = true; - break; - } - } - - if(isTypeVar) { - sw.visitClassBound().visitTypeVariable(bound); - }else { - sw.visitClassBound().visitClassType(bound); - sw.visitClassBound().visitEnd(); - } - - genericsAndBoundsMethod.put(gP.substring(1), bound); - } - } - - if(pT.contains("<")) { - RefType ref = (RefType) methodParamsAndTypes.get(paramName); - if(hasTPHs(ref)) - createSignatureForParameterizedType(ref); - - System.out.println("HAS WC = " + hasWC(ref)); - if(hasWC(ref)) - createSigForParamTypeWithWC(ref); - } - - for(GenericInsertPair p:methodPairs) { - String name = p.TA1.getName()+"$"; - if(!genericsAndBoundsMethod.containsKey(name)) { - sw.visitFormalTypeParameter(name); - sw.visitClassBound().visitTypeVariable(p.TA2.getName()+"$"); - genericsAndBoundsMethod.put(name, p.TA2.getName()+"$"); - } - } - - ArrayList types = new ArrayList<>(); - ArrayList superTypes = new ArrayList<>(); - - for(GenericInsertPair p : methodPairs) { - types.add(p.TA1); - superTypes.add(p.TA2); - } - - for(GenericInsertPair p : methodPairs) { - String name = p.TA2.getName()+"$"; - if(!types.contains(p.TA2) && !genericsAndBoundsMethod.containsKey(name)) { - String bound = Type.getInternalName(Object.class); - sw.visitFormalTypeParameter(name); - sw.visitClassBound().visitClassType(bound); - genericsAndBoundsMethod.put(name, bound); - sw.visitClassBound().visitEnd(); - } } } @@ -229,169 +169,94 @@ public class Signature { // sw.visitEnd(); } - private void createSigForParamTypeWithWC(RefType ref) { - for(RefTypeOrTPHOrWildcardOrGeneric p : ref.getParaList()) { - if(p instanceof WildcardType) { - if(((WildcardType) p).getInnerType() instanceof GenericRefType) { - String name = new TypeToSignature().visit((GenericRefType)((WildcardType) p).getInnerType()); - System.out.println("NAME WC = " + name); - if(!genericsAndBoundsMethod.containsKey(name) && !genericsAndBounds.containsKey(name)) { - sw.visitFormalTypeParameter(name); - sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); - sw.visitClassBound().visitEnd(); - genericsAndBoundsMethod.put(name, Type.getInternalName(Object.class)); - } + private void addConstraintsToMap(HashMap> allConstraints, + ArrayList allConsBeforeSimplify) { + for(TPHConstraint tphCons : allConsBeforeSimplify) { + allConstraints.put(tphCons, null); + } + } + + private String getEqualTPH(HashMap> methodConstraints, String tph) { + for(TPHConstraint cons : methodConstraints.keySet()) { + if(methodConstraints.get(cons) != null) { + if(methodConstraints.get(cons).contains(tph)) { + return cons.getLeft(); } } } - + return tph; } - private boolean hasWC(RefType ref) { - for(RefTypeOrTPHOrWildcardOrGeneric p : ref.getParaList()) { - System.out.println("HAS WCs: " + p.acceptTV(new TypeToString())); - System.out.println("HAS WCs: " + p.getClass()); - if(p.acceptTV(new TypeToString()).contains("WC")) - return true; - - } - return false; - } - - private void createSignatureForParameterizedType(RefType ref) { - ArrayList allPairs = getAllPairs(ref); - allPairs.addAll(methodPairs); - ArrayList simplifiedPairs = simplifyPairs(allPairs); + private void createTypeVars(HashMap> allConstraints, boolean doSimplify) { + allConstraints.putAll(methodConstraints); - HashMap names = new HashMap<>(); - - for(GenericInsertPair pair : simplifiedPairs) { - if(ref.getParaList().contains(pair.TA1)) { - String sub = pair.TA1.getName()+"$"; - String superT = pair.TA2.getName()+"$"; - names.put(sub, superT); - } + HashMap> simplifiedConstraints; + if(doSimplify) { + simplifiedConstraints = Simplify.simplifyContraints(allConstraints); + }else { + simplifiedConstraints = allConstraints; } - for(String sub : names.keySet()) { + for(TPHConstraint cons : simplifiedConstraints.keySet()) { + // need subst. + String sub = cons.getLeft()+"$"; if(!genericsAndBoundsMethod.containsKey(sub) && !genericsAndBounds.containsKey(sub)) { sw.visitFormalTypeParameter(sub); - String bound = names.get(sub); - sw.visitClassBound().visitTypeVariable(bound); - genericsAndBoundsMethod.put(sub, bound); - } - } - - for(String superT : names.values()) { - if(!names.containsKey(superT)) { - if(!genericsAndBoundsMethod.containsKey(superT) && !genericsAndBounds.containsKey(superT)) { - sw.visitFormalTypeParameter(superT); + String bound = cons.getRight(); + if(bound.equals(Type.getInternalName(Object.class))) { sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); sw.visitClassBound().visitEnd(); - genericsAndBoundsMethod.put(superT, Type.getInternalName(Object.class)); - } - } - } - - for(RefTypeOrTPHOrWildcardOrGeneric p: ref.getParaList()) { - if(p instanceof TypePlaceholder) { - String name = ((TypePlaceholder) p).getName() + "$"; - if(!genericsAndBoundsMethod.containsKey(name) && !genericsAndBounds.containsKey(name)) { - sw.visitFormalTypeParameter(name); - sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); - sw.visitClassBound().visitEnd(); - genericsAndBoundsMethod.put(name, Type.getInternalName(Object.class)); + genericsAndBoundsMethod.put(sub, bound); + } else { + String boundName = bound+"$"; + sw.visitClassBound().visitTypeVariable(boundName); + genericsAndBoundsMethod.put(sub, boundName); } } + } } - - private ArrayList getAllPairs(RefType ref) { - final ArrayList res = new ArrayList<>(); + + private ArrayList getAllConstraints(RefType ref) { + final ArrayList res = new ArrayList<>(); for(RefTypeOrTPHOrWildcardOrGeneric p : ref.getParaList()) { - RefTypeOrTPHOrWildcardOrGeneric resolved = resultSet.resolveType(p).resolvedType; + ResolvedType resType; + if(p instanceof WildcardType) { + resType = resultSet.resolveType(((WildcardType) p).getInnerType()); + }else { + resType = resultSet.resolveType(p); + } + + RefTypeOrTPHOrWildcardOrGeneric resolved = resType.resolvedType; if(resolved instanceof TypePlaceholder) { - resultSet.resolveType(p).additionalGenerics.forEach(ag ->{ - if(!contains(res,ag)) { - res.add(ag); + resType.additionalGenerics.forEach(ag ->{ + TPHConstraint constr = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); + if(!contains(res,constr)) { + res.add(constr); } }); } + if(resolved instanceof WildcardType) { + WildcardType resWC = (WildcardType) resolved; + ResolvedType resType2 = resultSet.resolveType(resWC.getInnerType()); + if(resType2.resolvedType instanceof TypePlaceholder) { + resType2.additionalGenerics.forEach(ag ->{ + TPHConstraint constr = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); + if(!contains(res,constr)) { + res.add(constr); + } + }); + } + } } + System.out.println("RES GIP === " + res.size()); return res; } - - private boolean contains(ArrayList pairs, GenericInsertPair genPair) { - for(int i=0; i simplifyPairs(ArrayList allPairs) { - ArrayList simplifiedPairs = new ArrayList<>(); - - HashMap subAndSuperTph = new HashMap<>(); - for(GenericInsertPair p : allPairs) { - subAndSuperTph.put(p.TA1, p.TA2); - } - - subAndSuperTph.forEach((k,v)->System.out.println(k.getName() + " || " + v.getName())); - - int numOfVisitedPairs = 0; - for(TypePlaceholder subTph: subAndSuperTph.keySet()) { - - if(numOfVisitedPairs>=subAndSuperTph.size()) - break; - - HashMap tphsInRel= new HashMap<>(); - - tphsInRel.put(tphsInRel.size(), subTph); - TypePlaceholder superTph = subAndSuperTph.get(subTph); - tphsInRel.put(tphsInRel.size(), superTph); - - numOfVisitedPairs++; - - while(subAndSuperTph.containsKey(superTph)) { - superTph = subAndSuperTph.get(superTph); - tphsInRel.put(tphsInRel.size(), superTph); - numOfVisitedPairs++; - } - - // Subtype - TypePlaceholder subTphRes = tphsInRel.get(0); - // Die größte Supertype - TypePlaceholder superTphRes = tphsInRel.get(tphsInRel.size()-1); - - - while(subAndSuperTph.containsValue(subTphRes)) { - for(TypePlaceholder tph : subAndSuperTph.keySet()) { - if(subAndSuperTph.get(tph).equals(subTphRes)) { - subTphRes = tph; - break; - } - } - tphsInRel.put(0, subTphRes); - numOfVisitedPairs++; - } - - subTphRes = tphsInRel.get(0); - GenericInsertPair sPair = new GenericInsertPair(subTphRes, superTphRes); - simplifiedPairs.add(sPair); - } - return simplifiedPairs; - } - - private boolean hasTPHs(RefType ref) { - for(RefTypeOrTPHOrWildcardOrGeneric p : ref.getParaList()) { - System.out.println("HAS TPHs: " + p.acceptTV(new TypeToString())); - if(p.acceptTV(new TypeToString()).contains("WC")){ - continue; - } - if(resultSet.resolveType(p).resolvedType instanceof TypePlaceholder) + private boolean contains(ArrayList constraints, TPHConstraint constr) { + for(int i=0; i { // params += "L"+param.toString().replace(".", "/"); // } params += param.acceptTV(new TypeToSignature()); - if(!(param instanceof RefType)) + + if(param instanceof TypePlaceholder) params += ";"; -// if(it.hasNext())params += ";"; } params += ">"; } @@ -48,7 +48,10 @@ public class TypeToSignature implements TypeVisitor { @Override public String visit(SuperWildcardType superWildcardType) { // throw new NotImplementedException(); - return "-" + superWildcardType.getInnerType().acceptTV(new TypeToSignature()); + String sig = "-" + superWildcardType.getInnerType().acceptTV(new TypeToSignature()); + if(superWildcardType.getInnerType() instanceof TypePlaceholder) + sig += ";"; + return sig; } @Override @@ -60,7 +63,10 @@ public class TypeToSignature implements TypeVisitor { @Override public String visit(ExtendsWildcardType extendsWildcardType) { // throw new NotImplementedException(); - return "+" + extendsWildcardType.getInnerType().acceptTV(new TypeToSignature()); + String sig = "+" + extendsWildcardType.getInnerType().acceptTV(new TypeToSignature()); + if(extendsWildcardType.getInnerType() instanceof TypePlaceholder) + sig += ";"; + return sig; } @Override diff --git a/src/de/dhbwstuttgart/bytecode/utilities/KindOfLambda.java b/src/de/dhbwstuttgart/bytecode/utilities/KindOfLambda.java index d2f7ee5b..53994d1e 100644 --- a/src/de/dhbwstuttgart/bytecode/utilities/KindOfLambda.java +++ b/src/de/dhbwstuttgart/bytecode/utilities/KindOfLambda.java @@ -46,8 +46,8 @@ public class KindOfLambda implements StatementVisitor{ @Override public void visit(BinaryExpr binary) { - // TODO Auto-generated method stub - + binary.lexpr.accept(this); + binary.rexpr.accept(this); } @Override @@ -82,8 +82,9 @@ public class KindOfLambda implements StatementVisitor{ @Override public void visit(IfStmt ifStmt) { - // TODO Auto-generated method stub - + ifStmt.expr.accept(this); + ifStmt.then_block.accept(this); + ifStmt.else_block.accept(this); } @Override @@ -156,8 +157,10 @@ public class KindOfLambda implements StatementVisitor{ @Override public void visit(This aThis) { - this.isInstanceCapturingLambda = true; - this.argumentList.add(aThis.getType()); + if(!isInstanceCapturingLambda) { + this.isInstanceCapturingLambda = true; + this.argumentList.add(aThis.getType()); + } } @Override diff --git a/src/de/dhbwstuttgart/bytecode/utilities/Simplify.java b/src/de/dhbwstuttgart/bytecode/utilities/Simplify.java new file mode 100644 index 00000000..566eca81 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/utilities/Simplify.java @@ -0,0 +1,432 @@ +package de.dhbwstuttgart.bytecode.utilities; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; + +import org.objectweb.asm.Type; + +import de.dhbwstuttgart.bytecode.BytecodeGen.TPHExtractor; +import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +public class Simplify { + + public static HashMap> simplifyConstraints(String name, TPHExtractor tphExtractor) { + // 1. check if there are any cycles like L set L=R and: + // * remove both constraints + // * substitute L with R in all constraint + // b)no => go to next step + // 2. check the result of step 1 if there are any equal-constraints like L=R, M=R .. + // a) yes => put all such TPhs in a map and define "key-Cons" + // -- key-Cons = TPH < Object -- + // put this Constraint and the + // b) no + // 3. is + + ArrayList allCons = tphExtractor.allCons; + ArrayList consToRemove = new ArrayList<>(); + // step 1: + for(TPHConstraint c : allCons) { + + String left = c.getLeft(); + String right = c.getRight(); + if(c.getRel() == Relation.EXTENDS) { + TPHConstraint revCon = getReverseConstraint(allCons,left,right); + if(revCon != null) { + revCon.setRel(Relation.EQUAL); + consToRemove.add(revCon); + c.setRel(Relation.EQUAL); + substituteTPH(allCons,left, right); + } + } + } + System.out.println(); + System.out.println("NEW ALL CONST: " + allCons.size()); + allCons.forEach(c->System.out.println(c.toString())); + System.out.println("----------------"); + allCons.removeAll(consToRemove); + consToRemove = new ArrayList<>(); + + int size = allCons.size(); + + System.out.println("AFTER DELETE ALL CONST: " + allCons.size()); + allCons.forEach(c->System.out.println(c.toString())); + System.out.println("----------------"); + HashMap> result = new HashMap<>(); + + for(TPHConstraint c : allCons) { + if(c.getRel()==Relation.EQUAL) { + HashSet equalTPHs = getEqualsTPHs(result, c); + TPHConstraint constraint = getKeyConstraint(result,c); + equalTPHs.add(c.getLeft()); + equalTPHs.add(c.getRight()); + result.put(constraint, equalTPHs); + consToRemove.add(c); + size--; + } + } + System.out.println("Step 2 Result: "); + result.forEach((c,hs)->{ + System.out.print(c.toString() + " -> "); + hs.forEach(s->{ + System.out.print(s + ", "); + }); + System.out.println(); + }); + System.out.println("----------------"); + allCons.removeAll(consToRemove); + allCons.addAll(result.keySet()); + + if(!allCons.isEmpty() && allCons.size()<2) { + + if(!result.containsKey(allCons.get(0))) + result.put(allCons.get(0), null); + + return result; + } + + size += result.keySet().size(); + + for(TPHConstraint c : allCons) { + if(c.getRight().equals(Type.getInternalName(Object.class))) + size--; + } + ArrayList methodTphs = new ArrayList<>(); + for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) { + if(m.getName().equals(name)) { + methodTphs = m.getTphs(); + break; + } + } + + HashMap subAndSuper = new HashMap<>(); + for(TPHConstraint c : allCons) { + if(subAndSuper.containsKey(c.getLeft())) { + LinkedList all = new LinkedList<>(); + all.add(c.getLeft()); + String sup =c.getRight(); + all.add(sup); + HashMap ss = new HashMap<>(); + for(TPHConstraint constr : allCons) { + ss.put(constr.getLeft(), constr.getRight()); + } + while(ss.containsKey(sup)) { + sup = ss.get(sup); + all.add(sup); + } + if(!containTPH(methodTphs, all.getLast())) + continue; + } + subAndSuper.put(c.getLeft(), c.getRight()); + } + + int numOfVisitedPairs = 0; + for(String sub : subAndSuper.keySet()) { + if(isTPHInConstraint(result,sub)) + continue; + + if(!containTPH(methodTphs,sub)) + continue; + + if(numOfVisitedPairs>=size) + break; + LinkedList tphInRel = new LinkedList<>(); + tphInRel.add(sub); + String superT = subAndSuper.get(sub); + tphInRel.add(superT); + + numOfVisitedPairs++; + while(subAndSuper.containsKey(superT)) { + superT = subAndSuper.get(superT); + if(tphInRel.contains(superT)) { + break; + } + tphInRel.add(superT); + numOfVisitedPairs++; + } + + // Subtype + String subTphRes = tphInRel.getFirst(); + // Die größte Supertype + String superTphRes = tphInRel.getLast(); + + while(subAndSuper.containsValue(subTphRes)) { + for(String tph : subAndSuper.keySet()) { + if(containTPH(methodTphs,tph) && subAndSuper.get(tph).equals(subTphRes)) { + subTphRes = tph; + break; + } + } + if(subTphRes.equals(tphInRel.getFirst())) { + break; + } + tphInRel.addFirst(subTphRes); + numOfVisitedPairs++; + } + + subTphRes = tphInRel.getFirst(); + + int i = 2; + while(!containTPH(methodTphs,superTphRes) && (tphInRel.size()-i) >0) { + superTphRes = tphInRel.get(tphInRel.size()-i); + i++; + } + + if(!containTPH(methodTphs, superTphRes)) { + result.put(new ExtendsConstraint(subTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null); + } else { + result.put(new ExtendsConstraint(subTphRes, superTphRes, Relation.EXTENDS), null); + result.put(new ExtendsConstraint(superTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null); + } + } + + for(TypePlaceholder tph : methodTphs) { + if(!isTPHInConstraint(result, tph.getName())) { + result.put(new ExtendsConstraint(tph.getName(), Type.getInternalName(Object.class), Relation.EXTENDS), null); + } + } + + System.out.println("EndResult: "); + result.forEach((c,hs)->{ + if(c!=null) { + System.out.print(c.toString() + " -> "); + if(hs == null) { + System.out.print(" [] "); + }else { + hs.forEach(s->{ + System.out.print(s + ", "); + }); + } + } + + + System.out.println(); + }); + System.out.println("----------------"); + return result; + } + + public static HashMap> simplifyContraints(HashMap> allConstraints) { + // 1. check if there are any cycles like L set L=R and: + // * remove both constraints + // * substitute L with R in all constraint + // b)no => go to next step + // 2. check the result of step 1 if there are any equal-constraints like L=R, M=R .. + // a) yes => put all such TPhs in a map and define "key-Cons" + // -- key-Cons = TPH < Object -- + // put this Constraint and the + // b) no + // 3. is + ArrayList allCons = new ArrayList<>(); + for(TPHConstraint tphCons : allConstraints.keySet()) { + allCons.add(tphCons); + } + ArrayList consToRemove = new ArrayList<>(); + // step 1: + for(TPHConstraint c : allCons) { + + String left = c.getLeft(); + String right = c.getRight(); + if(c.getRel() == Relation.EXTENDS) { + TPHConstraint revCon = getReverseConstraint(allCons,left,right); + if(revCon != null) { + revCon.setRel(Relation.EQUAL); + consToRemove.add(revCon); + c.setRel(Relation.EQUAL); + substituteTPH(allCons,left, right); + } + } + } + System.out.println(); + System.out.println("NEW ALL CONST: " + allCons.size()); + allCons.forEach(c->System.out.println(c.toString())); + System.out.println("----------------"); + allCons.removeAll(consToRemove); + consToRemove = new ArrayList<>(); + +// int size = allCons.size(); + + System.out.println("AFTER DELETE ALL CONST: " + allCons.size()); + allCons.forEach(c->System.out.println(c.toString())); + System.out.println("----------------"); + HashMap> result = new HashMap<>(); + + for(TPHConstraint c : allCons) { + if(c.getRel()==Relation.EQUAL) { + HashSet equalTPHs = getEqualsTPHs(result, c); + TPHConstraint constraint = getKeyConstraint(result,c); + equalTPHs.add(c.getLeft()); + equalTPHs.add(c.getRight()); + result.put(constraint, equalTPHs); + consToRemove.add(c); +// size--; + } + } + System.out.println("Step 2 Result: "); + result.forEach((c,hs)->{ + System.out.print(c.toString() + " -> "); + hs.forEach(s->{ + System.out.print(s + ", "); + }); + System.out.println(); + }); + System.out.println("----------------"); + allCons.removeAll(consToRemove); + allCons.addAll(result.keySet()); + + if(!allCons.isEmpty() && allCons.size()<2) { + + if(!result.containsKey(allCons.get(0))) + result.put(allCons.get(0), null); + + return result; + } + +// size += result.keySet().size(); + +// for(TPHConstraint c : allCons) { +// if(c.getRight().equals(Type.getInternalName(Object.class))) +// size--; +// } + + HashMap subAndSuper = new HashMap<>(); + + for(TPHConstraint c : allCons) { + subAndSuper.put(c.getLeft(), c.getRight()); + } + +// int numOfVisitedPairs = 0; + for(String sub : subAndSuper.keySet()) { + if(isTPHInConstraint(result,sub)) + continue; + +// if(numOfVisitedPairs>=size) +// break; + + LinkedList tphInRel = new LinkedList<>(); + tphInRel.add(sub); + String superT = subAndSuper.get(sub); + tphInRel.add(superT); + +// numOfVisitedPairs++; + while(subAndSuper.containsKey(superT)) { + superT = subAndSuper.get(superT); + if(tphInRel.contains(superT)) { + break; + } + tphInRel.add(superT); +// numOfVisitedPairs++; + } + + // Subtype + String subTphRes = tphInRel.getFirst(); + // Die größte Supertype + String superTphRes = tphInRel.getLast(); + + while(subAndSuper.containsValue(subTphRes)) { + for(String tph : subAndSuper.keySet()) { + if(subAndSuper.get(tph).equals(subTphRes)) { + subTphRes = tph; + break; + } + } + if(subTphRes.equals(tphInRel.getFirst())) { + break; + } + tphInRel.addFirst(subTphRes); +// numOfVisitedPairs++; + } + + subTphRes = tphInRel.getFirst(); + + int i = 2; + while(superTphRes.equals(Type.getInternalName(Object.class)) && (tphInRel.size()-i) >0) { + superTphRes = tphInRel.get(tphInRel.size()-i); + i++; + } + if(superTphRes.equals(Type.getInternalName(Object.class))) { + result.put(new ExtendsConstraint(subTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null); + } else { + result.put(new ExtendsConstraint(subTphRes, superTphRes, Relation.EXTENDS), null); + result.put(new ExtendsConstraint(superTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null); + } + + } + System.out.println("EndResult: "); + result.forEach((c,hs)->{ + if(c!=null) { + System.out.print(c.toString() + " -> "); + if(hs == null) { + System.out.print(" [] "); + }else { + hs.forEach(s->{ + System.out.print(s + ", "); + }); + } + } + + + System.out.println(); + }); + System.out.println("----------------"); + return result; + } + + private static void substituteTPH(ArrayList allCons,String left ,String right) { + allCons.forEach(c->{ + if(c.getRel() == Relation.EXTENDS) { + if(c.getLeft().equals(left)) + c.setLeft(right); + if(c.getRight().equals(left)) + c.setRight(right); + } + }); + } + + private static TPHConstraint getReverseConstraint(ArrayList allCons, String left, String right) { + for(TPHConstraint c : allCons) { + if(c.getLeft().equals(right) && c.getRight().equals(left)){ + return c; + } + } + return null; + } + + private static boolean isTPHInConstraint(HashMap> result, String sub) { + for(TPHConstraint c : result.keySet()) { + if(c.getLeft().equals(sub)) + return true; + } + return false; + } + + private static boolean containTPH(ArrayList methodTphs, String sub) { + for(TypePlaceholder tph : methodTphs) { + if(tph.getName().equals(sub)) + return true; + } + return false; + } + + private static TPHConstraint getKeyConstraint(HashMap> result, TPHConstraint toFind) { + for(TPHConstraint c : result.keySet()) { + if(c.containTPH(toFind.getLeft()) || c.containTPH(toFind.getRight())) + return c; + } + return new ExtendsConstraint(toFind.getRight(), Type.getInternalName(Object.class), Relation.EXTENDS); + } + + private static HashSet getEqualsTPHs(HashMap> result, TPHConstraint toFind) { + for(TPHConstraint c : result.keySet()) { + if(c.containTPH(toFind.getLeft()) || c.containTPH(toFind.getRight())) + return result.get(c); + } + return new HashSet<>(); + } +} diff --git a/src/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/de/dhbwstuttgart/core/JavaTXCompiler.java index 5b113b7a..9049051c 100644 --- a/src/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -26,14 +26,17 @@ import de.dhbwstuttgart.typeinference.unify.RuleSet; import de.dhbwstuttgart.typeinference.unify.TypeUnify; import de.dhbwstuttgart.typeinference.unify.distributeVariance; import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -79,10 +82,16 @@ public class JavaTXCompiler { } public List getAvailableClasses(SourceFile forSourceFile) throws ClassNotFoundException { - List allClasses = new ArrayList<>();//environment.getAllAvailableClasses(); + //PL 2018-09-18: List durch Set ersetzt, damit die Klassen nur einmal hinzugefuegt werden + //List allClasses = new ArrayList<>();//environment.getAllAvailableClasses(); + Set allClasses = new HashSet<>(); + + /* PL 2018-09-19 geloescht werden bereits in typeInference hinzugefuegt for (SourceFile sf : sourceFiles.values()) { allClasses.addAll(sf.getClasses()); } + */ + List importedClasses = new ArrayList<>(); for (JavaClassName name : forSourceFile.getImports()) { //TODO: Hier werden imports von eigenen (.jav) Klassen nicht beachtet @@ -91,7 +100,7 @@ public class JavaTXCompiler { importedClasses.add(importedClass); allClasses.addAll(importedClasses); } - return allClasses; + return new ArrayList<>(allClasses); } public List typeInference() throws ClassNotFoundException { @@ -127,6 +136,10 @@ public class JavaTXCompiler { Set returnTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) .map(z -> ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get(); + Set fieldTypeVarNames = allClasses.stream().map(x -> x.getFieldDecl().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get(); + + returnTypeVarNames.addAll(fieldTypeVarNames); xConsSet = xConsSet.stream().map(x -> { //Hier muss ueberlegt werden, ob @@ -154,9 +167,11 @@ public class JavaTXCompiler { ((PlaceholderType)x.getRhsType()).setVariance((byte)-1); ((PlaceholderType)x.getRhsType()).disableWildcardtable(); } - } - return x;//HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE JEWEILS ANDERE SEITE - }).map( y -> { + } + return x;//HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE JEWEILS ANDERE SEITE + }) + /* PL 2018-11-07 wird in varianceInheritance erledigt + .map( y -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { if (((PlaceholderType)y.getLhsType()).getVariance() != 0 && ((PlaceholderType)y.getRhsType()).getVariance() == 0) { ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType()).getVariance()); @@ -166,15 +181,25 @@ public class JavaTXCompiler { } } return y; } ) + */ .collect(Collectors.toCollection(HashSet::new)); varianceInheritance(xConsSet); Set> result = unify.unifySequential(xConsSet, finiteClosure); //Set> result = unify.unify(xConsSet, finiteClosure); System.out.println("RESULT: " + result); results.addAll(result); - } - - + } + results = results.stream().map(x -> { + Optional> res = new RuleSet().subst(x.stream().map(y -> { + if (y.getPairOp() == PairOperator.SMALLERDOTWC) y.setPairOp(PairOperator.EQUALSDOT); + return y; //alle Paare a <.? b erden durch a =. b ersetzt + }).collect(Collectors.toCollection(HashSet::new))); + if (res.isPresent()) {//wenn subst ein Erg liefert wurde was veraendert + return new TypeUnifyTask().applyTypeUnificationRules(res.get(), finiteClosure); + } + else return x; //wenn nichts veraendert wurde wird x zurueckgegeben + }).collect(Collectors.toCollection(HashSet::new)); + System.out.println("RESULT Final: " + results); return results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, generateTPHMap(cons))))).collect(Collectors.toList()); } @@ -183,7 +208,7 @@ public class JavaTXCompiler { * Vererbt alle Variancen * @param eq The set of constraints */ - private void varianceInheritance(Set eq) { + private void varianceInheritance(Set eq) { Set usedTPH = new HashSet<>(); Set phSet = eq.stream().map(x -> { Set pair = new HashSet<>(); diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java index c4fc5b58..29c53981 100644 --- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java +++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java @@ -13,6 +13,8 @@ import de.dhbwstuttgart.typeinference.unify.model.*; import java.util.*; import java.util.stream.Collectors; +import org.antlr.v4.runtime.Token; + public class FCGenerator { /** * Baut die FiniteClosure aus availableClasses. @@ -26,11 +28,18 @@ public class FCGenerator { public static Set toFC(Collection availableClasses) throws ClassNotFoundException { HashSet pairs = new HashSet<>(); + //PL 2018-09-18: gtvs vor die for-Schleife gezogen, damit immer die gleichen Typeplaceholder eingesetzt werden. + HashMap gtvs = new HashMap<>(); for(ClassOrInterface cly : availableClasses){ - pairs.addAll(getSuperTypes(cly, availableClasses)); + pairs.addAll(getSuperTypes(cly, availableClasses, gtvs)); } return pairs; } + + + + + /** * Bildet eine Kette vom übergebenen Typ bis hin zum höchsten bekannten Typ diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index 36cba603..067430e2 100644 --- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -21,12 +21,14 @@ import java.util.*; public class StatementGenerator { private JavaClassRegistry reg; + private Map fields; //PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH bekommen private Map localVars; private GenericsRegistry generics; - public StatementGenerator(JavaClassRegistry reg, GenericsRegistry generics, Map localVars){ + public StatementGenerator(JavaClassRegistry reg, GenericsRegistry generics, Map fields, Map localVars){ this.reg = reg; this.generics = generics; + this.fields = fields; this.localVars = localVars; } @@ -238,9 +240,14 @@ public class StatementGenerator { if(localVars.get(expression) != null){ return new LocalVar(expression, localVars.get(expression), offset); }else{ + if(fields.get(expression) != null){//PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH bekommen + return new FieldVar(new This(offset), expression, fields.get(expression), offset); + + } else { + //kann eigentlich nicht vorkommen //Dann Muss es ein Feld sein! return new FieldVar(new This(offset), expression, TypePlaceholder.fresh(offset), offset); - } + }} } return generateFieldVarOrClassname(expression, offset); } @@ -818,8 +825,12 @@ public class StatementGenerator { } private Expression convert(Java8Parser.LiteralContext literal) { - if(literal.IntegerLiteral() != null || literal.FloatingPointLiteral()!= null){ - Number value = Double.parseDouble(literal.IntegerLiteral().getText()); + if(literal.IntegerLiteral() != null){ + Number value = Integer.parseInt(literal.IntegerLiteral().getText()); + return new Literal(TypePlaceholder.fresh(literal.getStart()), + value, literal.getStart()); + } else if(literal.FloatingPointLiteral()!= null){ + Number value = Double.parseDouble(literal.FloatingPointLiteral().getText()); return new Literal(TypePlaceholder.fresh(literal.getStart()), value, literal.getStart()); }else if(literal.BooleanLiteral() != null){ @@ -892,7 +903,7 @@ public class StatementGenerator { for(FormalParameter param : params.getFormalparalist()){ lambdaLocals.put(param.getName(), param.getType()); } - StatementGenerator lambdaGenerator = new StatementGenerator(reg, generics, lambdaLocals); + StatementGenerator lambdaGenerator = new StatementGenerator(reg, generics, fields, lambdaLocals); Block block; if(expression.lambdaBody().expression() != null){ diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java index 73b0e55f..b0331a00 100644 --- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java +++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java @@ -33,6 +33,7 @@ public class SyntaxTreeGenerator{ private final GenericsRegistry globalGenerics; private String pkgName = ""; Set imports = new HashSet(); + private Map fields = new HashMap<>(); //PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH bekommen List fieldInitializations = new ArrayList<>(); @@ -122,7 +123,7 @@ public class SyntaxTreeGenerator{ private Method convert(int modifiers, Java8Parser.MethodHeaderContext header, Java8Parser.MethodBodyContext body, JavaClassName parentClass, RefType superClass, GenericsRegistry localGenerics) { - StatementGenerator stmtGen = new StatementGenerator(reg, localGenerics, new HashMap<>()); + StatementGenerator stmtGen = new StatementGenerator(reg, localGenerics, fields, new HashMap<>()); String name = header.methodDeclarator().Identifier().getText(); GenericDeclarationList gtvDeclarations = new GenericDeclarationList(new ArrayList<>(), header.getStart()); @@ -346,6 +347,7 @@ public class SyntaxTreeGenerator{ } for(Java8Parser.VariableDeclaratorContext varCtx : fieldDeclarationContext.variableDeclaratorList().variableDeclarator()){ String fieldName = convert(varCtx.variableDeclaratorId()); + fields.put(fieldName, fieldType); if(varCtx.variableInitializer() != null){ initializeField(varCtx, fieldType, generics); } @@ -360,7 +362,7 @@ public class SyntaxTreeGenerator{ // Initialize a field by creating implicit constructor. private void initializeField(Java8Parser.VariableDeclaratorContext ctx, RefTypeOrTPHOrWildcardOrGeneric typeOfField, GenericsRegistry generics){ - StatementGenerator statementGenerator = new StatementGenerator(reg, generics, new HashMap<>()); + StatementGenerator statementGenerator = new StatementGenerator(reg, generics, fields, new HashMap<>()); fieldInitializations.add(statementGenerator.generateFieldAssignment(ctx, typeOfField)); } diff --git a/src/de/dhbwstuttgart/syntaxtree/type/RefType.java b/src/de/dhbwstuttgart/syntaxtree/type/RefType.java index 3c9a5907..3e86275a 100644 --- a/src/de/dhbwstuttgart/syntaxtree/type/RefType.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/RefType.java @@ -105,7 +105,7 @@ public class RefType extends RefTypeOrTPHOrWildcardOrGeneric return false; } } - + @Override public void accept(ASTVisitor visitor) { diff --git a/src/de/dhbwstuttgart/syntaxtree/type/RefTypeOrTPHOrWildcardOrGeneric.java b/src/de/dhbwstuttgart/syntaxtree/type/RefTypeOrTPHOrWildcardOrGeneric.java index 8a573d16..d20d451d 100644 --- a/src/de/dhbwstuttgart/syntaxtree/type/RefTypeOrTPHOrWildcardOrGeneric.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/RefTypeOrTPHOrWildcardOrGeneric.java @@ -15,4 +15,5 @@ public abstract class RefTypeOrTPHOrWildcardOrGeneric extends SyntaxTreeNode{ public abstract A acceptTV(TypeVisitor visitor); public abstract void accept(ResultSetVisitor visitor); + } diff --git a/src/de/dhbwstuttgart/syntaxtree/type/TypePlaceholder.java b/src/de/dhbwstuttgart/syntaxtree/type/TypePlaceholder.java index ab4414fd..6f0fa3ff 100644 --- a/src/de/dhbwstuttgart/syntaxtree/type/TypePlaceholder.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/TypePlaceholder.java @@ -59,6 +59,7 @@ public class TypePlaceholder extends RefTypeOrTPHOrWildcardOrGeneric } } + public String toString() { return "TPH " + this.name; diff --git a/src/de/dhbwstuttgart/typeinference/result/ResultPair.java b/src/de/dhbwstuttgart/typeinference/result/ResultPair.java index 19bd65f9..749f9c1c 100644 --- a/src/de/dhbwstuttgart/typeinference/result/ResultPair.java +++ b/src/de/dhbwstuttgart/typeinference/result/ResultPair.java @@ -23,4 +23,8 @@ public abstract class ResultPair 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + oderConstraints.add(constraint); + } + constraintsSet.addOderConstraint(oderConstraints); + // */ + return; + } + if (literal.value instanceof Short) { + constraintsSet.addUndConstraint(new Pair(literal.getType(),shortt, PairOperator.EQUALSDOT)); + return; + } + if (literal.value instanceof Byte) { + constraintsSet.addUndConstraint(new Pair(literal.getType(),bytee, PairOperator.EQUALSDOT)); + return; + } + if (literal.value instanceof Float) { + constraintsSet.addUndConstraint(new Pair(literal.getType(),floatt, PairOperator.EQUALSDOT)); + return; + } + if (literal.value instanceof String) { + constraintsSet.addUndConstraint(new Pair(literal.getType(),string, PairOperator.EQUALSDOT)); + return; + } + if (literal.value instanceof Boolean) { + constraintsSet.addUndConstraint(new Pair(literal.getType(),bool, PairOperator.EQUALSDOT)); + return; + } + else { + throw new NotImplementedException(); + } } @Override @@ -445,6 +521,8 @@ public class TYPEStmt implements StatementVisitor{ @Override public void visit(AssignToField assignLeftSide) { //Hier ist kein Code nötig. Es werden keine extra Constraints generiert + //HIER muss Code rein PL 2018-10-24 + assignLeftSide.field.accept(this); } @Override @@ -474,8 +552,10 @@ public class TYPEStmt implements StatementVisitor{ RefTypeOrTPHOrWildcardOrGeneric receiverType = new RefType(assumption.getReceiver().getClassName(), params, forMethod.getOffset()); */ - methodConstraint.add(new Pair(forMethod.receiver.getType(), assumption.getReceiverType(resolver), - PairOperator.SMALLERDOT)); + + RefTypeOrTPHOrWildcardOrGeneric retType = assumption.getReceiverType(resolver); + methodConstraint.add(new Pair(forMethod.receiver.getType(), retType, + PairOperator.SMALLERDOT)); methodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT)); methodConstraint.addAll(generateParameterConstraints(forMethod, assumption, info, resolver)); diff --git a/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java b/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java index 690ee4ca..e2edbb97 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java +++ b/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java @@ -36,7 +36,7 @@ import java.io.IOException; */ public class RuleSet implements IRuleSet{ - RuleSet() { + public RuleSet() { super(); } @@ -776,10 +776,17 @@ public class RuleSet implements IRuleSet{ return Optional.empty(); Set result = new HashSet(); - - result.add(new UnifyPair(funNLhsType.getTypeParams().get(funNLhsType.getTypeParams().size()-1), funNRhsType.getTypeParams().get(funNRhsType.getTypeParams().size()-1), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); - for(int i = 0; i < funNLhsType.getTypeParams().size()-1; i++) { - result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + if (pair.getPairOp() == PairOperator.SMALLERDOT) { + result.add(new UnifyPair(funNLhsType.getTypeParams().get(funNLhsType.getTypeParams().size()-1), funNRhsType.getTypeParams().get(funNRhsType.getTypeParams().size()-1), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + for(int i = 0; i < funNLhsType.getTypeParams().size()-1; i++) { + result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + } + else {// pair.getPairOp() == PairOperator.EQUALDOT + result.add(new UnifyPair(funNLhsType.getTypeParams().get(funNLhsType.getTypeParams().size()-1), funNRhsType.getTypeParams().get(funNRhsType.getTypeParams().size()-1), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + for(int i = 0; i < funNLhsType.getTypeParams().size()-1; i++) { + result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), funNLhsType.getTypeParams().get(i), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + } } result.stream().forEach(x -> { UnifyType l = x.getLhsType(); if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); } diff --git a/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java b/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java index c217bda2..106f0688 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java +++ b/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java @@ -23,14 +23,17 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet; import de.dhbwstuttgart.typeinference.unify.interfaces.ISetOperations; import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.FunNType; import de.dhbwstuttgart.typeinference.unify.model.PairOperator; 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.TypeParams; import de.dhbwstuttgart.typeinference.unify.model.Unifier; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; import de.dhbwstuttgart.typeinference.unify.model.UnifyType; import de.dhbwstuttgart.typeinference.unify.model.OrderingUnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.Pair; import java.io.File; import java.io.FileWriter; @@ -79,7 +82,7 @@ public class TypeUnifyTask extends RecursiveTask>> { Integer noAllErasedElements = 0; - Integer noBacktracking = 0; + static int noBacktracking; public TypeUnifyTask() { rules = new RuleSet(); @@ -500,7 +503,7 @@ public class TypeUnifyTask extends RecursiveTask>> { /* auskommentiert um alle Max und min Betrachtung auszuschalten ANFANG */ if (!result.isEmpty() && !isUndefinedPairSetSet(res)) { - if (nextSetasList.iterator().hasNext() && nextSetasList.iterator().next().stream().filter(x -> x.getLhsType().getName().equals("D")).findFirst().isPresent() && nextSetasList.size()>1) + if (nextSetasList.iterator().hasNext() && nextSetasList.iterator().next().stream().filter(x -> x.getLhsType().getName().equals("B")).findFirst().isPresent() && nextSetasList.size()>1) System.out.print(""); Iterator> nextSetasListIt = new ArrayList>(nextSetasList).iterator(); if (variance == 1) { @@ -511,6 +514,9 @@ public class TypeUnifyTask extends RecursiveTask>> { (oup.compare(a, a_next) == 1)) { nextSetasList.remove(a_next); } + else { + System.out.println(""); + } } } else { if (variance == -1) { @@ -521,6 +527,9 @@ public class TypeUnifyTask extends RecursiveTask>> { (oup.compare(a, a_next) == -1)) { nextSetasList.remove(0); } + else { + System.out.println(""); + } } } else if (variance == 0) { @@ -529,8 +538,9 @@ public class TypeUnifyTask extends RecursiveTask>> { } } /* auskommentiert um alle Max und min Betrachtung auszuschalten ENDE */ - + if (isUndefinedPairSetSet(res)) { + int nofstred= 0; Set abhSubst = res.stream() .map(b -> b.stream() @@ -542,8 +552,18 @@ public class TypeUnifyTask extends RecursiveTask>> { .filter(x -> b.contains(x)) //.filter(y -> abhSubst.contains(y)) .collect(Collectors.toCollection(HashSet::new)); - Set vars = durchschnitt.stream().map(x -> (PlaceholderType)x.getLhsType()).collect(Collectors.toCollection(HashSet::new)); + //Set vars = durchschnitt.stream().map(x -> (PlaceholderType)x.getLhsType()).collect(Collectors.toCollection(HashSet::new)); int len = nextSetasList.size(); + Set undefRes = res.stream().reduce((y,z) -> { y.addAll(z); return y;}).get(); //flatten aller undef results + Set, UnifyPair>> reducedUndefResSubstGroundedBasePair = undefRes.stream() + .map(x -> { Set su = x.getAllSubstitutions(); //alle benutzten Substitutionen + su.add(x.getGroundBasePair()); // urspruengliches Paar + su.removeAll(durchschnitt); //alle aktuell genänderten Paare entfernen + return new Pair<>(su, x.getGroundBasePair());}) + .collect(Collectors.toCollection(HashSet::new)); + if (res.size() > 1) { + System.out.println(); + } nextSetasList = nextSetasList.stream().filter(x -> { //Boolean ret = false; //for (PlaceholderType var : vars) { @@ -553,7 +573,6 @@ public class TypeUnifyTask extends RecursiveTask>> { }).collect(Collectors.toCollection(ArrayList::new)); noAllErasedElements = noAllErasedElements + (len - nextSetasList.size()); - noBacktracking++; System.out.println(""); @@ -569,7 +588,94 @@ public class TypeUnifyTask extends RecursiveTask>> { return result; } + protected boolean couldBecorrect(Set, UnifyPair>> reducedUndefResSubstGroundedBasePair, Set nextElem) { + return reducedUndefResSubstGroundedBasePair.stream() + .map(pair -> { + Set reducedAbhSubst = pair.getKey(); + reducedAbhSubst.addAll(nextElem); + Optional> substRes = rules.subst(reducedAbhSubst); + if (!substRes.isPresent()) { + return true; + } + //PL 2018-10-12 + //Evtl. zurest applyTypeUnification aufrufen + //evtl auch unify aufrufen + else { + UnifyPair checkPair = substRes.get().stream() + .filter(x -> x.getGroundBasePair().equals(pair.getValue().get())).findFirst().get(); + if (((checkPair.getLhsType() instanceof PlaceholderType) || (checkPair.getRhsType() instanceof PlaceholderType)) + && (checkPair.getPairOp() == PairOperator.SMALLERDOT || checkPair.getPairOp() == PairOperator.SMALLERDOTWC)) + { + /* + Set setCheckPair = new HashSet<>(); + setCheckPair.add(checkPair); + Set setReturnCheckPair = applyTypeUnificationRules(setCheckPair, fc); + UnifyPair checkPair1 = setReturnCheckPair.iterator().next(); + Set up = new HashSet<>(); + up.add(checkPair1); + Set undef = new HashSet<>(); + */ + PairOperator pairOp = checkPair.getPairOp(); + UnifyType lhsType = checkPair.getLhsType(); + UnifyType rhsType = checkPair.getRhsType(); + ///* Case 1: (a <. Theta') + if ((((pairOp == PairOperator.SMALLERDOT) || (pairOp == PairOperator.SMALLERNEQDOT)) && lhsType instanceof PlaceholderType) + // Case 2: (a <.? ? ext Theta') + || (pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof ExtendsType) + // Case 3: (a <.? ? sup Theta') + || (pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof SuperType) + // Case 4 was replaced by an inference rule + // Case 4: (a <.? Theta') + || (pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType) + // Case 5: (Theta <. a) + || ((pairOp == PairOperator.SMALLERDOT) && rhsType instanceof PlaceholderType) + // Case 6 was replaced by an inference rule. + // Case 6: (? ext Theta <.? a) + || (pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof ExtendsType && rhsType instanceof PlaceholderType) + // Case 7 was replaced by an inference rule + // Case 7: (? sup Theta <.? a) + || (pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof SuperType && rhsType instanceof PlaceholderType) + // Case 8: (Theta <.? a) + || (pairOp == PairOperator.SMALLERDOTWC && rhsType instanceof PlaceholderType) + //reduceWildcardLow + || (pairOp == PairOperator.SMALLERDOTWC && (lhsType instanceof ExtendsType) && (rhsType instanceof ExtendsType)) + //reduceWildcardLowRight + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof ReferenceType) && (rhsType instanceof ExtendsType)) + //reduceWildcardUp + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof SuperType) && (rhsType instanceof SuperType)) + //reduceWildcardUpRight + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof ReferenceType) && (rhsType instanceof SuperType)) + //reduceFunN + || (((pairOp == PairOperator.SMALLERDOT) || (pairOp == PairOperator.EQUALSDOT)) + //PL 2017-10-03 hinzugefuegt + //da Regel auch fuer EQUALSDOT anwendbar + && (lhsType instanceof FunNType) && (rhsType instanceof FunNType)) + //greaterFunN + || ((pairOp== PairOperator.SMALLERDOT) && (lhsType instanceof FunNType) && (rhsType instanceof PlaceholderType)) + //smallerFunN + || ((pairOp == PairOperator.SMALLERDOT) && (lhsType instanceof PlaceholderType && rhsType instanceof FunNType)) + //reduceTph + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof PlaceholderType && rhsType instanceof ReferenceType)) + //reduceTphExt + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof ExtendsType) && rhsType instanceof PlaceholderType) + //reduceTphSup + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof SuperType) && rhsType instanceof PlaceholderType)) { + return true; + } + // Case unknown: If a pair fits no other case, then the type unification has failed. + // Through application of the rules, every pair should have one of the above forms. + // Pairs that do not have one of the aboves form are contradictory. + else { + return false; + } + //*/ + } else { + //Pair type <. ? extends ? extends type betrachten TODO PL 2018-10-09 + }} + return true;}).reduce((xx, yy) -> xx || yy).get(); + } + protected boolean isUndefinedPairSet(Set s) { if (s.size() >= 1 ) { Boolean ret = s.stream().map(x -> x.isUndefinedPair()).reduce(true, (x,y)-> (x && y)); diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/Pair.java b/src/de/dhbwstuttgart/typeinference/unify/model/Pair.java index 08c4aa1c..de05c97d 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/Pair.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/Pair.java @@ -18,4 +18,8 @@ public class Pair { public T getKey() { return key; } + + public String toString() { + return "(" + key.toString() + "," + "," + value.toString() + ")\n"; + } } diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java b/src/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java index 848e7fdd..d69138a7 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; @@ -116,6 +117,10 @@ public class UnifyPair { return pairOp; } + public void setPairOp(PairOperator po) { + pairOp = po; + } + public byte getVariance() { return variance; } @@ -147,6 +152,18 @@ public class UnifyPair { return ret; } + public UnifyPair getGroundBasePair () { + if (basePair == null) { + return this; + } + if (basePair.getBasePair() == null) { + return basePair; + } + else { + return basePair.getGroundBasePair(); + } + } + public Boolean wrongWildcard() { return lhs.wrongWildcard() || rhs.wrongWildcard(); } diff --git a/test/bytecode/FacultyTest.java b/test/bytecode/FacultyTest.java new file mode 100644 index 00000000..fb8f4fad --- /dev/null +++ b/test/bytecode/FacultyTest.java @@ -0,0 +1,54 @@ +package bytecode; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class FacultyTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Faculty.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Faculty"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + +// Method m = classToTest.getDeclaredMethod("m", Integer.class); + Field fact = classToTest.getDeclaredField("fact"); +// Class lambda = m.invoke(instanceOfClass).getClass(); + Class lambda = fact.getType(); + Method apply = lambda.getMethod("apply", Object.class); +// +// // Damit man auf die Methode zugreifen kann + apply.setAccessible(true); + + Integer i = 3; + + Integer result = (Integer) apply.invoke(instanceOfClass, i); +// Integer result = (Integer) m.invoke(instanceOfClass,i); + + assertEquals(6, result); + } + + +} diff --git a/test/bytecode/FieldTest.java b/test/bytecode/FieldTest.java new file mode 100644 index 00000000..a5528b00 --- /dev/null +++ b/test/bytecode/FieldTest.java @@ -0,0 +1,43 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Field; + +import org.junit.BeforeClass; +import org.junit.Test; +import java.net.URL; +import java.net.URLClassLoader; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class FieldTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Field.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Field"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() { + Field[] fields = classToTest.getFields(); + assertEquals(1, fields.length); + } + +} diff --git a/test/bytecode/FunOLTest.java b/test/bytecode/FunOLTest.java new file mode 100644 index 00000000..55aba31c --- /dev/null +++ b/test/bytecode/FunOLTest.java @@ -0,0 +1,52 @@ +package bytecode; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class FunOLTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/FunOL.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("FunOL"); + /* + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + Method m = classToTest.getDeclaredMethod("m"); + Class lambda = m.invoke(instanceOfClass).getClass(); + Method apply = lambda.getMethod("apply", Object.class); + + // Damit man auf die Methode zugreifen kann + apply.setAccessible(true); + + Integer i = 77; + + Integer result = (Integer) apply.invoke(m.invoke(instanceOfClass), i); + + assertEquals(77, result); + */ + } + + +} diff --git a/test/bytecode/MatrixOpTest.java b/test/bytecode/MatrixOpTest.java new file mode 100644 index 00000000..8fe538aa --- /dev/null +++ b/test/bytecode/MatrixOpTest.java @@ -0,0 +1,91 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class MatrixOpTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass_m1; + private static Object instanceOfClass_m2; + private static Object instanceOfClass_m3; + + @Test + public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, IOException, InstantiationException { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/MatrixOP.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; +// compiler.generateBytecode(pathToClassFile); +// loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); +// classToTest = loader.loadClass("MatrixOP"); +/* + Vector> vv = new Vector>(); + Vector v1 = new Vector (); + v1.addElement(2); + v1.addElement(2); + Vector v2 = new Vector (); + v2.addElement(3); + v2.addElement(3); + //Matrix m1 = new Matrix(); + //m1.addElement(v1); + //m1.addElement(v2); + vv.addElement(v1); + vv.addElement(v2); + instanceOfClass_m1 = classToTest.getDeclaredConstructor(Vector.class).newInstance(vv); //Matrix m1 = new Matrix(vv); + + Vector> vv1 = new Vector>(); + Vector v3 = new Vector (); + v3.addElement(2); + v3.addElement(2); + Vector v4 = new Vector (); + v4.addElement(3); + v4.addElement(3); + //Matrix m2 = new Matrix(); + //m2.addElement(v3); + //m2.addElement(v4); + vv1.addElement(v3); + vv1.addElement(v4); + instanceOfClass_m2 = classToTest.getDeclaredConstructor(Vector.class).newInstance(vv1);//Matrix m2 = new Matrix(vv1); + + + + //Matrix m3 = m1.mul(vv1); + Method mul = classToTest.getDeclaredMethod("mul", Vector.class); + Object result = mul.invoke(instanceOfClass_m1, instanceOfClass_m2); + System.out.println(instanceOfClass_m1.toString() + " * " + instanceOfClass_m2.toString() + " = " + result.toString()); + + Vector> res = new Vector>(); + Vector v5 = new Vector (); + v5.addElement(10); + v5.addElement(10); + Vector v6 = new Vector (); + v6.addElement(15); + v6.addElement(15); + //Matrix m2 = new Matrix(); + //m2.addElement(v3); + //m2.addElement(v4); + res.addElement(v5); + res.addElement(v6); + instanceOfClass_m3 = classToTest.getDeclaredConstructor(Vector.class).newInstance(res); + assertEquals(result, instanceOfClass_m3); +*/ + } + +} diff --git a/test/bytecode/OverloadingSortingTest.java b/test/bytecode/OverloadingSortingTest.java index a781280f..c6df11cd 100644 --- a/test/bytecode/OverloadingSortingTest.java +++ b/test/bytecode/OverloadingSortingTest.java @@ -24,28 +24,28 @@ public class OverloadingSortingTest { private static Class classOL2; private static Object instanceOfClassOL2; - @BeforeClass - public static void setUpBeforeClass() throws Exception { + @Test + public void generateBC() throws Exception { path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Sorting.jav"; fileToTest = new File(path); compiler = new JavaTXCompiler(fileToTest); pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; compiler.generateBytecode(pathToClassFile); - loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); - classToTest = loader.loadClass("Sorting"); - instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); +// loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); +// classToTest = loader.loadClass("Sorting"); +// instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); } - @Test - public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { - Method meth = classToTest.getDeclaredMethod("merge", classToTest); - } - - @Test - public void test2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { - Method meth = classToTest.getDeclaredMethod("test", classOL2); - String res = (String) meth.invoke(instanceOfClass, instanceOfClassOL2); - assertEquals("Overloading2", res); - } +// @Test +// public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { +// Method meth = classToTest.getDeclaredMethod("merge", classToTest); +// } +// +// @Test +// public void test2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { +// Method meth = classToTest.getDeclaredMethod("test", classOL2); +// String res = (String) meth.invoke(instanceOfClass, instanceOfClassOL2); +// assertEquals("Overloading2", res); +// } } diff --git a/test/bytecode/SortingTest.java b/test/bytecode/SortingTest.java new file mode 100644 index 00000000..2704fc68 --- /dev/null +++ b/test/bytecode/SortingTest.java @@ -0,0 +1,52 @@ +package bytecode; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class SortingTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Sorting.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Sorting"); + /* + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + Method m = classToTest.getDeclaredMethod("m"); + Class lambda = m.invoke(instanceOfClass).getClass(); + Method apply = lambda.getMethod("apply", Object.class); + + // Damit man auf die Methode zugreifen kann + apply.setAccessible(true); + + Integer i = 77; + + Integer result = (Integer) apply.invoke(m.invoke(instanceOfClass), i); + + assertEquals(77, result); + */ + } + + +} diff --git a/test/bytecode/Tph5Test.java b/test/bytecode/Tph5Test.java index 7d44e5e5..4107cca2 100644 --- a/test/bytecode/Tph5Test.java +++ b/test/bytecode/Tph5Test.java @@ -36,8 +36,9 @@ public class Tph5Test { @Test public void test() throws Exception { - Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class, Object.class); - Object result = m.invoke(instanceOfClass, "xx",2,3); +// Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class, Object.class); + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); +// Object result = m.invoke(instanceOfClass, "xx",2,3); //assertEquals(2,result); } diff --git a/test/bytecode/YTest.java b/test/bytecode/YTest.java new file mode 100644 index 00000000..80d37c6a --- /dev/null +++ b/test/bytecode/YTest.java @@ -0,0 +1,52 @@ +package bytecode; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class YTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Y.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Y"); + /* + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + Method m = classToTest.getDeclaredMethod("m"); + Class lambda = m.invoke(instanceOfClass).getClass(); + Method apply = lambda.getMethod("apply", Object.class); + + // Damit man auf die Methode zugreifen kann + apply.setAccessible(true); + + Integer i = 77; + + Integer result = (Integer) apply.invoke(m.invoke(instanceOfClass), i); + + assertEquals(77, result); + */ + } + + +} diff --git a/test/bytecode/javFiles/Faculty.jav b/test/bytecode/javFiles/Faculty.jav index d2bdcf91..a6171e5f 100644 --- a/test/bytecode/javFiles/Faculty.jav +++ b/test/bytecode/javFiles/Faculty.jav @@ -1,17 +1,46 @@ import java.lang.Integer; -class Faculty { - - m () { - - var fact = (x) -> { - if (x == 1) { - return x; - } - else { - return x * (fact.apply(x-1)); - } - }; - return fact; - } +public class Faculty { + public fact; + Faculty() { + fact = (x) -> { + if(x<0) { + return 0; + }else if (x < 1) { + return x; + } + else { + return x * (fact.apply(x-1)); + } + }; + } + +// m (x) { +// +//// var fact = (x) -> { +//// if (x == 1) { +//// return x; +//// } +//// else { +//// return x * (fact.apply(x-1)); +//// } +//// }; +//// return fact; +//// var x = 13; +//// if(x>22) { +//// return 0; +//// }else if(x <1){ +//// return x; +//// }else { +//// return 1; +//// } +// +// if (x < 0) { +// return 0; +// }else if(x<2) { +// return x; +// } else { +// return x * m(x-1); +// } +// } } diff --git a/test/bytecode/javFiles/Field.jav b/test/bytecode/javFiles/Field.jav new file mode 100644 index 00000000..b19b2308 --- /dev/null +++ b/test/bytecode/javFiles/Field.jav @@ -0,0 +1,9 @@ +import java.lang.Integer; + +public class Field { + public Integer x = 5; + + m(){ + return x; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/FunOL.jav b/test/bytecode/javFiles/FunOL.jav new file mode 100644 index 00000000..60736e1f --- /dev/null +++ b/test/bytecode/javFiles/FunOL.jav @@ -0,0 +1,12 @@ +import java.util.Vector; +import java.lang.Integer; +import java.lang.String; +//import java.lang.Byte; +//import java.lang.Boolean; + +public class FunOL { + + add(f, y) { + return f.apply() + y; + } +} diff --git a/test/bytecode/javFiles/Matrix.jav b/test/bytecode/javFiles/Matrix.jav index 2ba7f307..48f6eda2 100644 --- a/test/bytecode/javFiles/Matrix.jav +++ b/test/bytecode/javFiles/Matrix.jav @@ -1,9 +1,10 @@ import java.util.Vector; import java.lang.Integer; +//import java.lang.Float; //import java.lang.Byte; import java.lang.Boolean; -public class Matrix extends Vector> { +public class Matrix extends Vector> { Matrix () { } diff --git a/test/bytecode/javFiles/MatrixOP.jav b/test/bytecode/javFiles/MatrixOP.jav new file mode 100644 index 00000000..828a270b --- /dev/null +++ b/test/bytecode/javFiles/MatrixOP.jav @@ -0,0 +1,43 @@ +import java.util.Vector; +import java.lang.Integer; +//import java.lang.Byte; +import java.lang.Boolean; + +public class MatrixOP extends Vector> { + + MatrixOP () { + } + + MatrixOP(vv) { + Integer i; + i = 0; + while(i < vv.size()) { +// Boolean a = this.add(vv.elementAt(i)); + this.add(vv.elementAt(i)); + i=i+1; + } + } + + mul = (m1, m2) -> { + var ret = new MatrixOP(); + var i = 0; + while(i < size()) { + var v1 = m1.elementAt(i); + var v2 = new Vector(); + var j = 0; + while(j < v1.size()) { + var erg = 0; + var k = 0; + while(k < v1.size()) { + erg = erg + v1.elementAt(k) + * m2.elementAt(k).elementAt(j); + k++; } +// v2.addElement(new Integer(erg)); + v2.addElement(erg); + j++; } + ret.addElement(v2); + i++; + } + return ret; + }; +} diff --git a/test/bytecode/javFiles/Sorting.jav b/test/bytecode/javFiles/Sorting.jav index e6febcdd..341a1a6b 100644 --- a/test/bytecode/javFiles/Sorting.jav +++ b/test/bytecode/javFiles/Sorting.jav @@ -1,9 +1,23 @@ import java.util.List; -import java.util.Collection; +import java.util.ArrayList; +import java.lang.String; -class Sorting{ +public class Sorting{ merge(a, b){ a.addAll(b); return a; } -} \ No newline at end of file +/* +sort(in){ + var firstHalf = in; + var secondHalf = in; + return merge(sort(firstHalf), sort(secondHalf)); +} +*/ +/* + + void sort(ArrayList a){ + a = merge(a,a); + } +*/ +} diff --git a/test/bytecode/javFiles/Tph.jav b/test/bytecode/javFiles/Tph.jav index 1160e1a5..9faa570c 100644 --- a/test/bytecode/javFiles/Tph.jav +++ b/test/bytecode/javFiles/Tph.jav @@ -2,7 +2,7 @@ public class Tph { m(a,b){ var c = m2(b); - return c; + return a; // return m2(b); } diff --git a/test/bytecode/javFiles/Tph5.jav b/test/bytecode/javFiles/Tph5.jav index 1772b7ce..e73cfa2c 100644 --- a/test/bytecode/javFiles/Tph5.jav +++ b/test/bytecode/javFiles/Tph5.jav @@ -1,7 +1,13 @@ public class Tph5 { - m(a,b,c){ - a = c; - b = c; - return a; +// m(a,b,c){ +// a = c; +// b = c; +// return a; +// } + + m(x,y){ + x = m2(y); } + + m2(y) { return y; } } diff --git a/test/bytecode/javFiles/VectorAdd.jav b/test/bytecode/javFiles/VectorAdd.jav new file mode 100644 index 00000000..814f46c2 --- /dev/null +++ b/test/bytecode/javFiles/VectorAdd.jav @@ -0,0 +1,19 @@ +import java.util.Vector; +import java.lang.Integer; +import java.lang.String; +//import java.lang.Byte; +//import java.lang.Boolean; + +public class VectorAdd { + + add(v1, v2) { + var ret = new Vector(); + var i = 0; + var erg; + while(i < v1.size()) { + erg = v1.elementAt(i) + v2.elementAt(i); + ret.addElement(erg); + } + return ret; + } +} diff --git a/test/bytecode/javFiles/Y.jav b/test/bytecode/javFiles/Y.jav new file mode 100644 index 00000000..3c3e204d --- /dev/null +++ b/test/bytecode/javFiles/Y.jav @@ -0,0 +1,28 @@ +import java.lang.Integer; + +class Y { + y; + //factorial; + + Y() { + y = f -> t -> f.apply(y.apply(f)).apply(t); + //factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); }); + } +} + +/* +ergibt Parse-Error +class fac1 { + factorial; + + fac1() { + var y; + y = new Y<>().y; + factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); }); + } + public static void main(String args[]) { + System.out.println(new fac1().factorial.apply(3)); + } + +} +*/ \ No newline at end of file diff --git a/test/javFiles/ListenerOverload.jav b/test/javFiles/ListenerOverload.jav new file mode 100644 index 00000000..e1a8d65d --- /dev/null +++ b/test/javFiles/ListenerOverload.jav @@ -0,0 +1,20 @@ +import java.lang.Integer; +import java.lang.String; + +class ListenerOverload{ + +call(p){ + call(p.left); + call(p.right); +} + +call(Integer i){} + +call(String s){} + +} + +class Pair{ + A left; + B right; +} \ No newline at end of file diff --git a/test/typeinference/JavaTXCompilerTest.java b/test/typeinference/JavaTXCompilerTest.java index 30b6feae..233e8b24 100644 --- a/test/typeinference/JavaTXCompilerTest.java +++ b/test/typeinference/JavaTXCompilerTest.java @@ -104,6 +104,10 @@ public class JavaTXCompilerTest { public void multipleSolutions() throws IOException, ClassNotFoundException { execute(new File(rootDirectory+"Sorting.jav")); } + @Test + public void listenerTest() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"ListenerOverload.jav")); + } private static class TestResultSet{