diff --git a/.gitignore b/.gitignore index edec9626..a897efd8 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,6 @@ bin .project .settings/ /target/ + +# +manually/ diff --git a/pom.xml b/pom.xml index 5858aaee..5e4159bb 100644 --- a/pom.xml +++ b/pom.xml @@ -148,8 +148,8 @@ org.apache.maven.plugins maven-compiler-plugin - 8 - 8 + 9 + 9 diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java index f24bb3fd..52feb6e5 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -1,7 +1,9 @@ package de.dhbwstuttgart.bytecode; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.syntaxtree.statement.*; @@ -9,6 +11,7 @@ import org.objectweb.asm.ClassWriter; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; @@ -23,6 +26,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.result.ResultPair; import de.dhbwstuttgart.typeinference.result.ResultSet; public class BytecodeGen implements ASTVisitor { @@ -30,9 +34,10 @@ public class BytecodeGen implements ASTVisitor { ClassWriter cw =new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS); String type; - + String className; private boolean isInterface; + private List listOfResultSets; private ResultSet resultSet; private int indexOfFirstParam = 0; @@ -47,16 +52,18 @@ public class BytecodeGen implements ASTVisitor { byte[] bytecode; HashMap classFiles; - public BytecodeGen(HashMap classFiles, ResultSet resultSet) { + ArrayList methodNameAndParamsT = new ArrayList<>(); + + public BytecodeGen(HashMap classFiles, List listOfResultSets) { this.classFiles = classFiles; - this.resultSet = resultSet; + this.listOfResultSets = listOfResultSets; } @Override public void visit(SourceFile sourceFile) { for(ClassOrInterface cl : sourceFile.getClasses()) { System.out.println("in Class: " + cl.getClassName().toString()); - BytecodeGen classGen = new BytecodeGen(classFiles, resultSet); + BytecodeGen classGen = new BytecodeGen(classFiles, listOfResultSets); cl.accept(classGen); classGen.writeClass(cl.getClassName().toString()); } @@ -101,18 +108,27 @@ public class BytecodeGen implements ASTVisitor { cw.visit(Opcodes.V1_8, acc, classOrInterface.getClassName().toString() , sig, classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()), null); - // for each field in the class for(Field f : classOrInterface.getFieldDecl()) { f.accept(this); } +// resultSet = listOfResultSets.get(0); + boolean isConsWithNoParamsVisited = false; + for(ResultSet rs : listOfResultSets) { + resultSet = rs; + + for(Constructor c : classOrInterface.getConstructors()) { + if(!isConsWithNoParamsVisited) + c.accept(this); + if(!c.getParameterList().iterator().hasNext()) + isConsWithNoParamsVisited = true; + } + + for(Method m : classOrInterface.getMethods()) { + m.accept(this); + } - for(Constructor c : classOrInterface.getConstructors()) { - c.accept(this); } - for(Method m : classOrInterface.getMethods()) { - m.accept(this); - } } @Override @@ -146,19 +162,36 @@ public class BytecodeGen implements ASTVisitor { mv.visitMaxs(0, 0); mv.visitEnd(); } - + @Override public void visit(Method method) { // 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 methParamTypes = retType+method.name+"%%"; method.getParameterList().accept(this); + Iterator itr = method.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+";"; + } + + if(methodNameAndParamsT.contains(methParamTypes)) { + return; + } + methodNameAndParamsT.add(methParamTypes); + System.out.println("Method: "+method.name +" , paramsType: "+methParamTypes); String methDesc = null; // Method getModifiers() ? int acc = isInterface?Opcodes.ACC_ABSTRACT:method.modifier; + System.out.println(acc); + /*Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist*/ boolean hasGenInParameterList = genericsAndBounds.containsKey(resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())); + /*Wenn die Rückgabe-Type eine Typ-variable ist, erzeuge direkt die Signature, wenn nicht, + * prüfe, ob einer der Parameter Typ-Variable als Typ hat*/ if(!hasGenInParameterList) { for(String paramName : methodParamsAndTypes.keySet()) { String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToDescriptor()); @@ -170,9 +203,11 @@ public class BytecodeGen implements ASTVisitor { } //TODO: Test if the return-type or any of the parameter is a parameterized type. (VP) - //than create the descriptor with the new syntax. + //then create the descriptor with the new syntax. String sig = null; + /* method.getGenerics: <....> RT method(..) + * */ boolean hasGen = method.getGenerics().iterator().hasNext() || hasGenInParameterList; /* if method has generics or return type is TPH, create signature */ @@ -181,16 +216,17 @@ public class BytecodeGen implements ASTVisitor { Signature signature = new Signature(method, genericsAndBoundsMethod, methodParamsAndTypes,resultSet); sig = signature.toString(); } - System.out.println(sig); +// System.out.println(sig); NormalMethod meth = new NormalMethod(method,genericsAndBounds,genericsAndBoundsMethod,hasGen); methDesc = meth.accept(new DescriptorToString(resultSet)); - System.out.println(methDesc); + +// System.out.println(methDesc); MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC+acc, method.getName(), methDesc, sig, null); mv.visitCode(); - BytecodeGenMethod gen = new BytecodeGenMethod(className,resultSet,method, mv,paramsAndLocals,cw, - genericsAndBounds,genericsAndBounds,isInterface,classFiles); + genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles); + mv.visitMaxs(0, 0); mv.visitEnd(); } diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index df714015..ce5d3def 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -14,8 +14,12 @@ import java.util.Iterator; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.syntaxtree.statement.*; +import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr.Operator; +import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr.Operation; + import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Handle; +import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; @@ -31,40 +35,41 @@ import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.syntaxtree.FormalParameter; import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.StatementVisitor; - -import de.dhbwstuttgart.syntaxtree.statement.Literal; - import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.typeinference.result.ResultSet; -public class BytecodeGenMethod implements StatementVisitor{ - +public class BytecodeGenMethod implements StatementVisitor { + private Method m; private MethodVisitor mv; - private HashMap paramsAndLocals = new HashMap<>(); + private HashMap paramsAndLocals = new HashMap<>(); private String className; private int lamCounter = -1; private ClassWriter cw; private ResultSet resultSet; private boolean isInterface; HashMap genericsAndBoundsMethod; - private HashMap genericsAndBounds; + private HashMap genericsAndBounds; private boolean isBinaryExp = false; - - //for tests ** + + // for tests ** private String fieldName; private String fieldDesc; private Expression rightSideTemp; + private boolean isRightSideALambda = false; private KindOfLambda kindOfLambda; private HashMap classFiles; + private boolean isAssignStmt = false; + private Statement loopBlock; + private ArrayList varsFunInterface = new ArrayList<>();; - - public BytecodeGenMethod(String className,ResultSet resultSet, Method m, MethodVisitor mv, - HashMap paramsAndLocals, ClassWriter cw, HashMap genericsAndBoundsMethod, - HashMap genericsAndBounds, boolean isInterface, HashMap classFiles) { - + + public BytecodeGenMethod(String className, ResultSet resultSet, Method m, MethodVisitor mv, + HashMap paramsAndLocals, ClassWriter cw, HashMap genericsAndBoundsMethod, + HashMap genericsAndBounds, boolean isInterface, HashMap classFiles) { + this.className = className; this.resultSet = resultSet; this.m = m; @@ -75,15 +80,15 @@ public class BytecodeGenMethod implements StatementVisitor{ this.genericsAndBounds = genericsAndBounds; this.isInterface = isInterface; this.classFiles = classFiles; - - if(!isInterface) + + if (!isInterface) this.m.block.accept(this); - + } - - public BytecodeGenMethod(LambdaExpression lambdaExpression,ResultSet resultSet ,MethodVisitor mv, - int indexOfFirstParamLam, boolean isInterface, HashMap classFiles) { - + + public BytecodeGenMethod(LambdaExpression lambdaExpression, ResultSet resultSet, MethodVisitor mv, + int indexOfFirstParamLam, boolean isInterface, HashMap classFiles) { + this.resultSet = resultSet; this.mv = mv; this.isInterface = isInterface; @@ -91,42 +96,46 @@ public class BytecodeGenMethod implements StatementVisitor{ Iterator itr = lambdaExpression.params.iterator(); int i = indexOfFirstParamLam; - while(itr.hasNext()) { + while (itr.hasNext()) { FormalParameter fp = itr.next(); this.paramsAndLocals.put(fp.getName(), i); i++; } lambdaExpression.methodBody.accept(this); } - + private String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor()); } - @Override public void visit(Block block) { - for(Statement stmt : block.getStatements()) { -// System.out.println(where); + for (Statement stmt : block.getStatements()) { stmt.accept(this); } } - + @Override public void visit(SuperCall superCall) { superCall.receiver.accept(this); superCall.arglist.accept(this); - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), superCall.name, "()V",isInterface); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), superCall.name, "()V", + isInterface); } - + // ?? @Override public void visit(LocalVar localVar) { + // wenn String + String zuerst wird ein StringBuilder initialisiert dann + // wird die lokale Var geladen. Sonst wird zuerst die lokale Var geladen. + mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name)); - if(isBinaryExp) { - getVlaue(getResolvedType(localVar.getType())); + + if (isBinaryExp) { + getVlaueIns(getResolvedType(localVar.getType())); } } + // ?? @Override public void visit(LocalVarDecl localVarDecl) { @@ -135,188 +144,487 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(Assign assign) { + isAssignStmt = true; + // if the right side is a lambda => the left side must be a functional interface - if(assign.rightSide instanceof LambdaExpression) { + if (assign.rightSide instanceof LambdaExpression) { isRightSideALambda = true; - }else { + } else { isRightSideALambda = false; } - - if(assign.rightSide instanceof BinaryExpr) + + if (assign.rightSide instanceof BinaryExpr) isBinaryExp = true; - - if(assign.lefSide instanceof AssignToField) { + + + if (assign.lefSide instanceof AssignToField) { // load_0, ldc or .. then putfield this.rightSideTemp = assign.rightSide; - }else { + } else { assign.rightSide.accept(this); } - if(isBinaryExp) { - doAssign(getResolvedType(assign.lefSide.getType())); + if (isBinaryExp) { + BinaryExpr binary = (BinaryExpr) assign.rightSide; + String lexpType = getResolvedType(binary.lexpr.getType()); + String rexpType = getResolvedType(binary.rexpr.getType()); + getValueOfIns(getLargerType(lexpType, rexpType)); isBinaryExp = false; } assign.lefSide.accept(this); + + isAssignStmt =false; } - + + @Override public void visit(BinaryExpr binary) { + + String lexpType = getResolvedType(binary.lexpr.getType()); + String rexpType = getResolvedType(binary.rexpr.getType()); + + String largerType = getLargerType(lexpType,rexpType); + String typeOfBinary = getResolvedType(binary.getType()); + + if (typeOfBinary.equals(Type.getInternalName(String.class))) { + mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(StringBuilder.class)); + mv.visitInsn(Opcodes.DUP); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(StringBuilder.class), "", "()V", + false); + } + + Label endLabel = new Label(); + // this case for while loops + if(!isAssignStmt) + mv.visitLabel(endLabel); + binary.lexpr.accept(this); + + if(!lexpType.equals(rexpType) && + !lexpType.equals(largerType)) + doCast(lexpType, largerType); + binary.rexpr.accept(this); - switch (binary.operation.toString()) { - case "ADD": - mv.visitInsn(Opcodes.IADD); + + if(!lexpType.equals(rexpType) && + !rexpType.equals(largerType)) + doCast(rexpType, largerType); + + Operator op = binary.operation; + + switch (op) { + case ADD: + doVisitAddOpInsn(largerType); break; + case SUB: + doVisitSubOpInsn(typeOfBinary); + break; + + case MUL: + doVisitMulOpInsn(typeOfBinary); + break; + + case DIV: + doVisitDivOpInsn(typeOfBinary); + break; + + case MOD: + doVisitModOpInsn(typeOfBinary); + break; + + case LESSTHAN: + case LESSEQUAL: + case BIGGERTHAN: + case BIGGEREQUAL: + Label branchLabel = new Label(); + doVisitRelOpInsn(op,largerType, branchLabel, endLabel); + break; + default: break; } + + } + + private String getLargerType(String lexpType, String rexpType) { + if(lexpType.equals(Type.getInternalName(String.class)) || + rexpType.equals(Type.getInternalName(String.class))) { + return Type.getInternalName(String.class); + } else + if(lexpType.equals(Type.getInternalName(Double.class)) || + rexpType.equals(Type.getInternalName(Double.class))) { + return Type.getInternalName(Double.class); + } else if(lexpType.equals(Type.getInternalName(Float.class)) || + rexpType.equals(Type.getInternalName(Float.class))) { + return Type.getInternalName(Float.class); + } else if(lexpType.equals(Type.getInternalName(Long.class)) || + rexpType.equals(Type.getInternalName(Long.class))) { + return Type.getInternalName(Long.class); + } else { + return Type.getInternalName(Integer.class); + } + } + + private void doCast(String sourceType, String dest) { + switch (dest) { + case "java/lang/Long": + mv.visitInsn(Opcodes.I2L); + break; + + case "java/lang/Double": + if(sourceType.equals(Type.getInternalName(Long.class))) { + mv.visitInsn(Opcodes.L2D); + } else if(sourceType.equals(Type.getInternalName(Float.class))) { + mv.visitInsn(Opcodes.F2D); + } else { + mv.visitInsn(Opcodes.I2D); + } + break; + + case "java/lang/Float": + if(sourceType.equals(Type.getInternalName(Long.class))) { + mv.visitInsn(Opcodes.L2F); + } else { + mv.visitInsn(Opcodes.I2F); + } + break; + // braucht man eigentlic nicht, muss getestet werden + case "java/lang/String": + if(sourceType.equals(Type.getInternalName(Double.class))) { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(D)Ljava/lang/String;", false); + } else if(sourceType.equals(Type.getInternalName(Long.class))) { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(J)Ljava/lang/String;", false); + } else if(sourceType.equals(Type.getInternalName(Float.class))) { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(F)Ljava/lang/String;", false); + } else { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(I)Ljava/lang/String;", false); + } + break; + default: + break; + } + } + + private void doVisitRelOpInsn(Operator op, String typeOfBinary, Label branchLabel, Label endLabel) { + + switch (typeOfBinary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LCMP); + doVisitIfInRelOp(op, branchLabel, endLabel); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DCMPG); + doVisitIfInRelOp(op, branchLabel, endLabel); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FCMPG); + doVisitIfInRelOp(op, branchLabel, endLabel); + break; + default: + switch (op) { + case LESSTHAN: + mv.visitJumpInsn(Opcodes.IF_ICMPGE, branchLabel); + break; + case LESSEQUAL: + mv.visitJumpInsn(Opcodes.IF_ICMPGT, branchLabel); + break; + case BIGGERTHAN: + mv.visitJumpInsn(Opcodes.IF_ICMPLE, branchLabel); + break; + case BIGGEREQUAL: + mv.visitJumpInsn(Opcodes.IF_ICMPLT, branchLabel); + break; + default: + break; + } + if(isAssignStmt) { + mv.visitInsn(Opcodes.ICONST_1); + mv.visitJumpInsn(Opcodes.GOTO, endLabel); + mv.visitLabel(branchLabel); + mv.visitInsn(Opcodes.ICONST_0); + mv.visitLabel(endLabel); + } else { + loopBlock.accept(this); + mv.visitJumpInsn(Opcodes.GOTO, endLabel); + + mv.visitLabel(branchLabel); + } + break; + } + } + + private void doVisitIfInRelOp(Operator op, Label branchLabel, Label endLabel) { + + switch (op) { + case LESSTHAN: + mv.visitJumpInsn(Opcodes.IFGE, branchLabel); + break; + case LESSEQUAL: + mv.visitJumpInsn(Opcodes.IFGT, branchLabel); + break; + case BIGGERTHAN: + mv.visitJumpInsn(Opcodes.IFLE, branchLabel); + break; + case BIGGEREQUAL: + mv.visitJumpInsn(Opcodes.IFLT, branchLabel); + break; + default: + break; + } + if(isAssignStmt) { + mv.visitInsn(Opcodes.ICONST_1); + mv.visitJumpInsn(Opcodes.GOTO, endLabel); + mv.visitLabel(branchLabel); + mv.visitInsn(Opcodes.ICONST_0); + mv.visitLabel(endLabel); + } else { + loopBlock.accept(this); + mv.visitJumpInsn(Opcodes.GOTO, endLabel); + + mv.visitLabel(branchLabel); + } } - + + private void doVisitModOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LREM); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DREM); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FREM); + break; + default: + mv.visitInsn(Opcodes.IREM); + break; + } + } + + private void doVisitDivOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LDIV); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DDIV); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FDIV); + break; + default: + mv.visitInsn(Opcodes.IDIV); + break; + } + } + + private void doVisitMulOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LMUL); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DMUL); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FMUL); + break; + default: + mv.visitInsn(Opcodes.IMUL); + break; + } + } + + private void doVisitSubOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LSUB); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DSUB); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FSUB); + break; + default: + mv.visitInsn(Opcodes.ISUB); + break; + } + + } + + private void doVisitAddOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case "java/lang/Byte": + mv.visitInsn(Opcodes.IADD); + break; + case "java/lang/Short": + mv.visitInsn(Opcodes.IADD); + break; + case "java/lang/Integer": + mv.visitInsn(Opcodes.IADD); + break; + case "java/lang/Long": + mv.visitInsn(Opcodes.LADD); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DADD); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FADD); + break; + default: + break; + } + } + @Override public void visit(LambdaExpression lambdaExpression) { this.lamCounter++; - + Lambda lam = new Lambda(lambdaExpression); String lamDesc = lam.accept(new DescriptorToString(resultSet)); - //Call site, which, when invoked, returns an instance of the functional interface to which - //the lambda is being converted + // Call site, which, when invoked, returns an instance of the functional + // interface to which + // the lambda is being converted MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, - MethodType.class, MethodType.class, MethodHandle.class, MethodType.class); - + MethodType.class, MethodType.class, MethodHandle.class, MethodType.class); - Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", - "metafactory", mt.toMethodDescriptorString(), false); + Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", + mt.toMethodDescriptorString(), false); String methodName = "lambda$new$" + this.lamCounter; - - // Für die Parameter-Typen und Return-Typ braucht man die Bounds (für die Typlöschung) - + + // 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()) { + while (itr.hasNext()) { itr.next(); - typeErasure += "L"+Type.getInternalName(Object.class) + ";"; + typeErasure += "L" + Type.getInternalName(Object.class) + ";"; } - - typeErasure += ")L"+Type.getInternalName(Object.class) + ";"; + + typeErasure += ")L" + Type.getInternalName(Object.class) + ";"; // Type erasure Type arg1 = Type.getMethodType(typeErasure); -// Type arg1 = Type.getMethodType(lamDesc); + // Type arg1 = Type.getMethodType(lamDesc); // real Type Type arg3 = Type.getMethodType(lamDesc); - - int staticOrSpecial=0; - int staticOrInstance=0; + + int staticOrSpecial = 0; + int staticOrInstance = 0; int indexOfFirstParamLam = 0; this.kindOfLambda = new KindOfLambda(lambdaExpression); - if(kindOfLambda.isInstanceCapturingLambda()) { + if (kindOfLambda.isInstanceCapturingLambda()) { mv.visitVarInsn(Opcodes.ALOAD, 0); staticOrSpecial = Opcodes.H_INVOKESPECIAL; indexOfFirstParamLam = 1; - }else { + } else { staticOrSpecial = Opcodes.H_INVOKESTATIC; staticOrInstance = Opcodes.ACC_STATIC; } - + // first check if capturing lambda then invokestatic or invokespecial - Handle arg2 = new Handle(staticOrSpecial, this.className, methodName, - arg3.toString(),false); + Handle arg2 = new Handle(staticOrSpecial, this.className, methodName, arg3.toString(), false); // Descriptor of functional interface methode SamMethod samMethod = new SamMethod(kindOfLambda.getArgumentList(), lambdaExpression.getType()); // Desc: (this/nothing)TargetType String fiMethodDesc = samMethod.accept(new DescriptorToString(resultSet)); - mv.visitInvokeDynamicInsn("apply", fiMethodDesc, bootstrap, arg1, arg2,arg3); - - MethodVisitor mvLambdaBody = cw.visitMethod(Opcodes.ACC_PRIVATE+ staticOrInstance + Opcodes.ACC_SYNTHETIC, + mv.visitInvokeDynamicInsn("apply", fiMethodDesc, bootstrap, arg1, arg2, arg3); + + MethodVisitor mvLambdaBody = cw.visitMethod(Opcodes.ACC_PRIVATE + staticOrInstance + Opcodes.ACC_SYNTHETIC, methodName, arg3.toString(), null, null); - new BytecodeGenMethod(lambdaExpression,this.resultSet,mvLambdaBody,indexOfFirstParamLam,isInterface, + new BytecodeGenMethod(lambdaExpression, this.resultSet, mvLambdaBody, indexOfFirstParamLam, isInterface, classFiles); - + 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) { - ClassWriter classWriter =new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS); - + ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + SignatureWriter methSig = new SignatureWriter(); - + int numberOfParams = 0; SignatureVisitor paramVisitor = methSig.visitParameterType(); Iterator itr = lambdaExpression.params.iterator(); - while(itr.hasNext()) { + while (itr.hasNext()) { numberOfParams++; // getBounds - paramVisitor.visitTypeVariable("T"+numberOfParams); + paramVisitor.visitTypeVariable("T" + numberOfParams); itr.next(); } methSig.visitReturnType().visitTypeVariable("R"); // ")"+lam.getReturn.getBounds - Signature sig = new Signature(lambdaExpression,numberOfParams); - String name = "Fun"+numberOfParams; - classWriter.visit(Opcodes.V1_8, Opcodes.ACC_INTERFACE+Opcodes.ACC_ABSTRACT, name, - sig.toString(), Type.getInternalName(Object.class), null); - MethodVisitor mvApply = classWriter.visitMethod(Opcodes.ACC_PUBLIC+Opcodes.ACC_ABSTRACT, "apply", - methDesc, methSig.toString(), null); + Signature sig = new Signature(lambdaExpression, numberOfParams); + String name = "Fun" + numberOfParams; + classWriter.visit(Opcodes.V1_8, Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(), + Type.getInternalName(Object.class), null); + MethodVisitor mvApply = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "apply", methDesc, + methSig.toString(), null); mvApply.visitEnd(); - writeClassFile(classWriter.toByteArray(),name); + writeClassFile(classWriter.toByteArray(), name); } - + public void writeClassFile(byte[] bytecode, String name) { FileOutputStream output; try { - System.out.println("generating "+name+ ".class file..."); - output = new FileOutputStream(new File(System.getProperty("user.dir") + "/testBytecode/generatedBC/examples/" +name+".class")); + System.out.println("generating " + name + ".class file..."); + output = new FileOutputStream( + new File(System.getProperty("user.dir") + "/testBytecode/generatedBC/" + name + ".class")); output.write(bytecode); output.close(); - System.out.println(name+".class file generated"); + System.out.println(name + ".class file generated"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } - -} + + } @Override public void visit(CastExpr castExpr) { // TODO Auto-generated method stub - + } @Override public void visit(EmptyStmt emptyStmt) { // TODO Auto-generated method stub - + } @Override public void visit(FieldVar fieldVar) { - + fieldName = fieldVar.fieldVarName; - fieldDesc = "L"+getResolvedType(fieldVar.getType())+";"; - + fieldDesc = "L" + getResolvedType(fieldVar.getType()) + ";"; + fieldVar.receiver.accept(this); // test (if) - if(!fieldVar.receiver.getClass().equals(StaticClassName.class)) { - mv.visitFieldInsn(Opcodes.GETFIELD,getResolvedType(fieldVar.receiver.getType()), - fieldName ,fieldDesc); + if (!fieldVar.receiver.getClass().equals(StaticClassName.class)) { + mv.visitFieldInsn(Opcodes.GETFIELD, getResolvedType(fieldVar.receiver.getType()), fieldName, fieldDesc); } - -// mv.visitFieldInsn(Opcodes.GETSTATIC, fieldVar.receiver.getType().toString().replace(".", "/"), -// fieldVar.fieldVarName, fieldVar.getType().toString()); + + // mv.visitFieldInsn(Opcodes.GETSTATIC, + // fieldVar.receiver.getType().toString().replace(".", "/"), + // fieldVar.fieldVarName, fieldVar.getType().toString()); } @Override public void visit(ForStmt forStmt) { // TODO Auto-generated method stub - + } @Override @@ -327,52 +635,52 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(InstanceOf instanceOf) { // TODO Auto-generated method stub - + } @Override public void visit(MethodCall methodCall) { methodCall.receiver.accept(this); methodCall.arglist.accept(this); - + MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), - genericsAndBoundsMethod,genericsAndBounds); + genericsAndBoundsMethod, genericsAndBounds); String mDesc = method.accept(new DescriptorToString(resultSet)); - - // is methodCall.receiver functional Interface)? - if(varsFunInterface.contains(methodCall.receiver.getType())) { - mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()), - methodCall.name, mDesc, false); - }else { - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, getResolvedType(methodCall.receiver.getType()), - methodCall.name, mDesc, isInterface); + + // is methodCall.receiver functional Interface)? + if (varsFunInterface.contains(methodCall.receiver.getType())) { + mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()), methodCall.name, + mDesc, false); + } else { + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, getResolvedType(methodCall.receiver.getType()), methodCall.name, + mDesc, isInterface); } // test -// if(!methodCall.getType().toString().equals("V")) { -// mv.visitInsn(Opcodes.POP); -// } + // if(!methodCall.getType().toString().equals("V")) { + // mv.visitInsn(Opcodes.POP); + // } } @Override public void visit(NewClass methodCall) { - + mv.visitTypeInsn(Opcodes.NEW, methodCall.name.replace(".", "/")); mv.visitInsn(Opcodes.DUP); // creates Descriptor methodCall.arglist.accept(this); String d = "("; - for(Expression e : methodCall.arglist.getArguments()) { - d = d + "L"+getResolvedType(e.getType()) + ";"; + for (Expression e : methodCall.arglist.getArguments()) { + d = d + "L" + getResolvedType(e.getType()) + ";"; } d += ")V"; - + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, methodCall.name.replace(".", "/"), "", d, isInterface); } @Override public void visit(NewArray newArray) { // TODO Auto-generated method stub - + } @Override @@ -382,12 +690,101 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(UnaryExpr unaryExpr) { - System.out.println(unaryExpr.operation.toString()); + unaryExpr.expr.accept(this); + Operation op = unaryExpr.operation; + + String typeOfUnary = getResolvedType(unaryExpr.getType()); + + boolean isIncOrDec = false; + + switch (op) { + case POSTDECREMENT: + case POSTINCREMENT: + if(isAssignStmt) + mv.visitInsn(Opcodes.DUP); + genBCForIncAndDec(op, typeOfUnary); + getValueOfIns(typeOfUnary); + isIncOrDec = true; + break; + case PREDECREMENT: + case PREINCREMENT: + genBCForIncAndDec(op, typeOfUnary); + getValueOfIns(typeOfUnary); + if(isAssignStmt) + mv.visitInsn(Opcodes.DUP); + isIncOrDec = true; + break; + + case MINUS: + doVisitNegIns(typeOfUnary); + break; + default: + break; + } + + // Für Byte und Short muss noch einen Cast geben i2b, i2s + // das wird später gemacht, da bytecode für cast noch nicht erzeugt wird + + if(isIncOrDec && (unaryExpr.expr instanceof LocalVar)) { + LocalVar local = (LocalVar) unaryExpr.expr; + mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.get(local.name)); + } + } + + private void doVisitNegIns(String typeOfUnary) { + switch (typeOfUnary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LNEG); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DNEG); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FNEG); + break; + default: + mv.visitInsn(Opcodes.INEG); + break; + } + + } + + private void genBCForIncAndDec(Operation op, String typeOfUnary) { + + getVlaueIns(typeOfUnary); + doAssign(typeOfUnary, 1.0, true); + + switch (op) { + case POSTDECREMENT: + case PREDECREMENT: + doVisitSubOpInsn(typeOfUnary); + break; + + case POSTINCREMENT: + case PREINCREMENT: + doVisitAddOpInsn(typeOfUnary); + break; + + default: + break; + } } @Override public void visit(Return aReturn) { + if(aReturn.retexpr instanceof BinaryExpr) + isBinaryExp = true; + aReturn.retexpr.accept(this); + + if (isBinaryExp) { + BinaryExpr binary = (BinaryExpr) aReturn.retexpr; + String lexpType = getResolvedType(binary.lexpr.getType()); + String rexpType = getResolvedType(binary.rexpr.getType()); + getValueOfIns(getLargerType(lexpType, rexpType)); + isBinaryExp = false; + } + mv.visitInsn(Opcodes.ARETURN); } @@ -398,10 +795,11 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(StaticClassName staticClassName) { -// mv.visitMethodInsn(Opcodes.INVOKESTATIC, staticClassName.getType().toString().replace(".", "/"), -// staticClassName.toString(), staticClassName.getType().toString(), false); - mv.visitFieldInsn(Opcodes.GETSTATIC, getResolvedType(staticClassName.getType()), - fieldName, fieldDesc); + // mv.visitMethodInsn(Opcodes.INVOKESTATIC, + // staticClassName.getType().toString().replace(".", "/"), + // staticClassName.toString(), staticClassName.getType().toString(), false); + //mv.visitFieldInsn(Opcodes.GETSTATIC, getResolvedType(staticClassName.getType()), fieldName, fieldDesc); + throw new NotImplementedException("Static noch nicht implementiert!"); } @Override @@ -416,54 +814,57 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(WhileStmt whileStmt) { + this.loopBlock = whileStmt.loopBlock; + + if(whileStmt.expr instanceof BinaryExpr) + isBinaryExp = true; + whileStmt.expr.accept(this); - whileStmt.loopBlock.accept(this); + + isBinaryExp = false; } @Override public void visit(DoStmt whileStmt) { - // TODO Auto-generated method stub - + whileStmt.expr.accept(this); + // TODO: } @Override public void visit(Literal literal) { Object value = literal.value; - String typeOfLiteral = resultSet.resolveType(literal.getType()).resolvedType.acceptTV(new TypeToDescriptor()); - if(this.isBinaryExp) { - getVlaue(typeOfLiteral); - }else { - doAssign(typeOfLiteral, value); - } - - + String typeOfLiteral = getResolvedType(literal.getType()); + // Name der Methode muss geändert werden + doAssign(typeOfLiteral, value, false); + } - - private void getVlaue(String typeOfLiteral) { - switch (typeOfLiteral) { + + private void getVlaueIns(String type) { + switch (type) { case "java/lang/String": + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(StringBuilder.class), "append", + "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); + break; case "java/lang/Boolean": break; case "java/lang/Byte": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", - "(B)Ljava/lang/Byte;", false); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false); break; case "java/lang/Short": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", - "(S)Ljava/lang/Short;", false); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false); break; case "java/lang/Integer": - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", - "()I", false); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false); break; case "java/lang/Long": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", - "(J)Ljava/lang/Long;", false); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false); break; case "java/lang/Float": + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false); break; case "java/lang/Double": + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false); break; case "java/lang/Character": break; @@ -472,7 +873,7 @@ public class BytecodeGenMethod implements StatementVisitor{ } } - private void doAssign(String type, Object value) { + private void doAssign(String type, Object value, boolean isOperator) { switch (type) { case "java/lang/String": mv.visitLdcInsn(String.valueOf(value)); @@ -481,25 +882,17 @@ public class BytecodeGenMethod implements StatementVisitor{ visitBooleanLiteral((Boolean) value); break; case "java/lang/Byte": - visitByteLiteral(((Double) value).byteValue(),false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", - "(B)Ljava/lang/Byte;", false); + visitByteLiteral(((Double) value).byteValue(), false); break; case "java/lang/Short": - visitShortLiteral(((Double) value).shortValue(),false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", - "(S)Ljava/lang/Short;", false); + visitShortLiteral(((Double) value).shortValue(), false); break; case "java/lang/Integer": - //zweite Argument isLong + // zweite Argument isLong visitIntegerLiteral(((Double) value).intValue(), false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", - "(I)Ljava/lang/Integer;", false); break; case "java/lang/Long": visitLongLiteral(((Double) value).longValue(), true); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", - "(J)Ljava/lang/Long;", false); break; case "java/lang/Float": visitFloatLiteral(((Double) value).floatValue()); @@ -513,35 +906,44 @@ public class BytecodeGenMethod implements StatementVisitor{ default: break; } + + if(!type.equals("java/lang/String")&&!type.equals("java/lang/Boolean")) { + if (!this.isBinaryExp && !isOperator) + getValueOfIns(type); + } + } - - private void doAssign(String type) { + + private void getValueOfIns(String type) { switch (type) { case "java/lang/String": + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", + false); break; case "java/lang/Boolean": + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); break; case "java/lang/Byte": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", - "(B)Ljava/lang/Byte;", false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false); break; case "java/lang/Short": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", - "(S)Ljava/lang/Short;", false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false); break; case "java/lang/Integer": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", - "(I)Ljava/lang/Integer;", false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); break; case "java/lang/Long": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", - "(J)Ljava/lang/Long;", false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); break; case "java/lang/Float": + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); break; case "java/lang/Double": + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); break; case "java/lang/Character": + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", + false); break; default: break; @@ -550,111 +952,113 @@ public class BytecodeGenMethod implements StatementVisitor{ private void visitCharLiteral(Character value) { mv.visitIntInsn(Opcodes.BIPUSH, (int) value); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", - "(C)Ljava/lang/Character;", false); + } private void visitDoubleLiteral(Double value) { - if(value == 0) { + if (value == 0) { mv.visitInsn(Opcodes.DCONST_0); - }else if(value == 1) { + } else if (value == 1) { mv.visitInsn(Opcodes.DCONST_1); - }else { + } else { mv.visitLdcInsn(value); } - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", - "(D)Ljava/lang/Double;", false); } private void visitFloatLiteral(Float value) { - if(value.intValue()>-1 && value.intValue() < 3) { - //Opcodes.FCONST_0 = 11, Opcodes.FCONST_1 = 12, usw - mv.visitInsn(value.intValue()+11); - }else { + if (value.intValue() > -1 && value.intValue() < 3) { + // Opcodes.FCONST_0 = 11, Opcodes.FCONST_1 = 12, usw + mv.visitInsn(value.intValue() + 11); + } else { mv.visitLdcInsn(value); } - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", - "(F)Ljava/lang/Float;", false); } private void visitLongLiteral(Long value, boolean isLong) { - if(value=-Math.pow(2, 15))&&value<-128) { - visitShortLiteral(value.shortValue(),isLong); - }else { + if (value < Math.pow(2, 15) || (value >= -Math.pow(2, 15)) && value < -128) { + visitShortLiteral(value.shortValue(), isLong); + } else { mv.visitLdcInsn(value); } } - private void visitShortLiteral(Short value,boolean isLong) { - if(value< 128 || (value>-129 && value<-1)) { + private void visitShortLiteral(Short value, boolean isLong) { + if (value < 128 || (value > -129 && value < -1)) { visitByteLiteral(value.byteValue(), isLong); - }else if(value=-Math.pow(2, 15))&&value<-128) { + } else if (value < Math.pow(2, 15) || (value >= -Math.pow(2, 15)) && value < -128) { mv.visitIntInsn(Opcodes.SIPUSH, value); } } private void visitByteLiteral(Byte value, boolean isLong) { - - if(!isLong && value<6 && value>-1) { - //Opcodes.ICONST_0 = 3, Opcodes.ICONST_1 = 4, usw - mv.visitInsn(value+3); - }else if(isLong && value>-1 && value<2){ - //Opcodes.LCONST_0 = 9, Opcodes.LCONST_1 = 10 - mv.visitInsn(value+9); - }else { + + if (!isLong && value < 6 && value > -1) { + // Opcodes.ICONST_0 = 3, Opcodes.ICONST_1 = 4, usw + mv.visitInsn(value + 3); + } else if (isLong && value > -1 && value < 2) { + // Opcodes.LCONST_0 = 9, Opcodes.LCONST_1 = 10 + mv.visitInsn(value + 9); + } else { mv.visitIntInsn(Opcodes.BIPUSH, value); } - + } private void visitIntegerLiteral(Integer value, boolean isLong) { - - if(value=-Math.pow(2, 15))&&value<-128) { - visitShortLiteral(value.shortValue(),isLong); - }else { + + if (value < Math.pow(2, 15) || (value >= -Math.pow(2, 15)) && value < -128) { + visitShortLiteral(value.shortValue(), isLong); + } else { mv.visitLdcInsn(value); } } private void visitBooleanLiteral(Boolean b) { - if(b) { + if (b) { mv.visitInsn(Opcodes.ICONST_1); - }else { + } else { mv.visitInsn(Opcodes.ICONST_0); } - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", - "(Z)Ljava/lang/Boolean;", false); + // muss noch getestet werden. + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); } @Override public void visit(ArgumentList argumentList) { - for(Expression al : argumentList.getArguments()) { + for (Expression al : argumentList.getArguments()) { al.accept(this); } } @Override public void visit(AssignToField assignLeftSide) { -// temporäre Lösung für testen, bis ich weiss wie man funktionale -// interfaces erkennt - if(isRightSideALambda) + // temporäre Lösung für testen, bis ich weiss wie man funktionale + // interfaces erkennt + if (isRightSideALambda) varsFunInterface.add(assignLeftSide.field.getType()); - // Loads the an object reference from the local variable - // array slot onto the top of the operand stack. + // Loads the an object reference from the local variable + // array slot onto the top of the operand stack. assignLeftSide.field.receiver.accept(this); this.rightSideTemp.accept(this); - mv.visitFieldInsn(Opcodes.PUTFIELD, getResolvedType(assignLeftSide.field.receiver.getType()), + mv.visitFieldInsn(Opcodes.PUTFIELD, getResolvedType(assignLeftSide.field.receiver.getType()), assignLeftSide.field.fieldVarName, getResolvedType(assignLeftSide.field.getType())); } @Override public void visit(AssignToLocal assignLeftSide) { - if(isRightSideALambda) + if (isRightSideALambda) varsFunInterface.add(assignLeftSide.localVar.getType()); - paramsAndLocals.put(assignLeftSide.localVar.name, paramsAndLocals.size()+1); + int index = paramsAndLocals.size(); + String var = assignLeftSide.localVar.name; + if(!paramsAndLocals.containsKey(var)) { + paramsAndLocals.put(var, index + 1); + }else { + paramsAndLocals.put(var, index); + } + mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.size()); // Debug::: - + } } diff --git a/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java b/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java index c9725a82..65f48f71 100644 --- a/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java +++ b/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java @@ -49,9 +49,10 @@ public class DescriptorToString implements DescriptorVisitor{ desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; } } -// else if(((RefType) fp.getType()).getParaList().size() > 0){ -// desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "%").replace("<", "%%").replace(">", "%%")+ ";"; -// } + //TODO: generate a class java%% ... %% + else if(resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()).contains("<")){ + desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "%").replace("<", "%%").replace(">", "%%")+ ";"; + } else { desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; } diff --git a/src/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/de/dhbwstuttgart/core/JavaTXCompiler.java index 9a66543a..68bb2585 100644 --- a/src/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -1,31 +1,41 @@ package de.dhbwstuttgart.core; +import de.dhbwstuttgart.bytecode.BytecodeGen; import de.dhbwstuttgart.environment.CompilationEnvironment; import de.dhbwstuttgart.parser.JavaTXParser; +import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.scope.GenericsRegistry; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.SyntaxTreeGenerator; import de.dhbwstuttgart.parser.antlr.Java8Parser.CompilationUnitContext; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.parser.scope.JavaClassRegistry; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.ParameterList; import de.dhbwstuttgart.syntaxtree.SourceFile; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; import de.dhbwstuttgart.typeinference.constraints.Constraint; import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; import de.dhbwstuttgart.typeinference.constraints.Pair; import de.dhbwstuttgart.typeinference.result.ResultSet; import de.dhbwstuttgart.typeinference.typeAlgo.TYPE; +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.PlaceholderType; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; import java.io.IOException; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; public class JavaTXCompiler { @@ -94,20 +104,114 @@ public class JavaTXCompiler { TypeUnify unify = new TypeUnify(); Set> results = new HashSet<>(); - for (List> xCons : unifyCons.cartesianProduct()) { - Set xConsSet = new HashSet<>(); - for (Constraint constraint : xCons) { - xConsSet.addAll(constraint); - } - - System.out.println(xConsSet); - Set> result = unify.unify(xConsSet, finiteClosure); - System.out.println("RESULT: " + result.size()); - results.addAll(result); + try { + FileWriter logFile = new FileWriter(new File(System.getProperty("user.dir")+"/test/logFiles/"+"log")); + logFile.write("FC:\\" + finiteClosure.toString()+"\n"); + for(SourceFile sf : this.sourceFiles.values()) { + logFile.write(ASTTypePrinter.print(sf)); + } + logFile.flush(); + Set>> cardProd = unifyCons.cartesianProduct(); + for (List> xCons : cardProd ){ + Set xConsSet = new HashSet<>(); + for (Constraint constraint : xCons) { + xConsSet.addAll(constraint); + } + //.collect(Collectors.toCollection(ArrayList::new)))) + System.out.println(xConsSet); + Set paraTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist() + .stream().filter(z -> z.getType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder)z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get()) + .reduce((a,b) -> { a.addAll(b); return a;} ).get(); + + 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(); + + + xConsSet = xConsSet.stream().map(x -> { + //Hier muss ueberlegt werden, ob + //1. alle Argument- und Retuntyp-Variablen in allen UnifyPairs + // mit disableWildcardtable() werden. + //2. alle Typvariablen mit Argument- oder Retuntyp-Variablen + //in Beziehung auch auf disableWildcardtable() gesetzt werden muessen + //PL 2018-04-23 + if ((x.getLhsType() instanceof PlaceholderType)) { + if (paraTypeVarNames.contains(x.getLhsType().getName())) { + ((PlaceholderType)x.getLhsType()).setVariance((byte)1); + ((PlaceholderType)x.getLhsType()).disableWildcardtable(); + } + if (returnTypeVarNames.contains(x.getLhsType().getName())) { + ((PlaceholderType)x.getLhsType()).setVariance((byte)-1); + ((PlaceholderType)x.getLhsType()).disableWildcardtable(); + } + } + if ((x.getRhsType() instanceof PlaceholderType)) { + if (paraTypeVarNames.contains(x.getRhsType().getName())) { + ((PlaceholderType)x.getRhsType()).setVariance((byte)1); + ((PlaceholderType)x.getRhsType()).disableWildcardtable(); + } + if (returnTypeVarNames.contains(x.getRhsType().getName())) { + ((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 -> { + 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()); + } + if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { + ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType()).getVariance()); + } + } + return y; } ) + .collect(Collectors.toCollection(HashSet::new)); + varianceInheritance(xConsSet); + Set> result = unify.unifySequential(xConsSet, finiteClosure, logFile); + //Set> result = unify.unify(xConsSet, finiteClosure); + System.out.println("RESULT: " + result); + logFile.write("RES: " + result.toString()+"\n"); + logFile.flush(); + results.addAll(result); + } + } + catch (IOException e) { } + + return results.stream().map((unifyPairs -> + new ResultSet(UnifyTypeFactory.convert(unifyPairs, generateTPHMap(cons))))).collect(Collectors.toList()); } - return results.stream().map((unifyPairs -> - new ResultSet(UnifyTypeFactory.convert(unifyPairs, generateTPHMap(cons))))).collect(Collectors.toList()); - } + + /** + * Vererbt alle Variancen + * @param eq The set of constraints + */ + private void varianceInheritance(Set eq) { + Set usedTPH = new HashSet<>(); + Set phSet = eq.stream().map(x -> { + Set pair = new HashSet<>(); + if (x.getLhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getLhsType()); + if (x.getRhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getRhsType()); + return pair; + }).reduce(new HashSet<>(), (a,b) -> { a.addAll(b); return a;} , (c,d) -> { c.addAll(d); return c;}); + + ArrayList phSetVariance = new ArrayList<>(phSet); + phSetVariance.removeIf(x -> (x.getVariance() == 0)); + while(!phSetVariance.isEmpty()) { + PlaceholderType a = phSetVariance.remove(0); + usedTPH.add(a); + //HashMap ht = new HashMap<>(); + //ht.put(a, a.getVariance()); + Set eq1 = new HashSet<>(eq); + eq1.removeIf(x -> !(x.getLhsType() instanceof PlaceholderType && ((PlaceholderType)x.getLhsType()).equals(a))); + eq1.stream().forEach(x -> { x.getRhsType().accept(new distributeVariance(), a.getVariance());}); + eq1 = new HashSet<>(eq); + eq1.removeIf(x -> !(x.getRhsType() instanceof PlaceholderType && ((PlaceholderType)x.getRhsType()).equals(a))); + eq1.stream().forEach(x -> { x.getLhsType().accept(new distributeVariance(), a.getVariance());}); + phSetVariance = new ArrayList<>(phSet); + phSetVariance.removeIf(x -> (x.getVariance() == 0 || usedTPH.contains(x))); + } +} private Map generateTPHMap(ConstraintSet constraints) { HashMap ret = new HashMap<>(); @@ -129,5 +233,28 @@ public class JavaTXCompiler { SourceFile ret = generator.convert(tree, environment.packageCrawler); return ret; } + + public void generateBytecode() throws ClassNotFoundException, IOException { + for(File f : sourceFiles.keySet()) { + HashMap classFiles = new HashMap<>(); + SourceFile sf = sourceFiles.get(f); + List typeinferenceResult = this.typeInference(); + BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult); +// BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult.get(0)); + bytecodeGen.visit(sf); + this.writeClassFile(bytecodeGen.getClassFiles()); + } + } -} \ No newline at end of file + private void writeClassFile(HashMap classFiles) throws IOException { + FileOutputStream output; + for(String name : classFiles.keySet()) { + byte[] bytecode = classFiles.get(name); + System.out.println("generating "+name+ ".class file ..."); + output = new FileOutputStream(new File(System.getProperty("user.dir") + "/testBytecode/generatedBC/" +name+".class")); + output.write(bytecode); + output.close(); + System.out.println(name+".class file generated"); + } + } +} diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index 5310d13b..aaa31f74 100644 --- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -832,7 +832,7 @@ public class StatementGenerator { }else if(literal.StringLiteral()!=null){ RefType type = new RefType(reg.getName("java.lang.String"),literal.getStart()); return new Literal(type, - literal.StringLiteral().getText(), + literal.StringLiteral().getText().substring(1, literal.StringLiteral().getText().length()-1), literal.getStart()); }else if(literal.NullLiteral() != null){ return new Literal(TypePlaceholder.fresh(literal.getStart()), null, diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java index 38399bf0..b4923039 100644 --- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java +++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java @@ -113,9 +113,7 @@ public class TypeGenerator { if(referenceTypeContext.classOrInterfaceType() != null){ if(referenceTypeContext.classOrInterfaceType().classType_lfno_classOrInterfaceType()!= null){ Java8Parser.ClassType_lfno_classOrInterfaceTypeContext ctx = referenceTypeContext.classOrInterfaceType().classType_lfno_classOrInterfaceType(); - //return convertTypeName(ctx.Identifier().toString(), ctx.typeArguments(),referenceTypeContext.getStart(), reg, generics); - if(ctx.typeArguments() != null)throw new NotImplementedException(); - return convertTypeName(referenceTypeContext.getText(), null,referenceTypeContext.getStart(), reg, generics); + return convertTypeName(ctx.Identifier().toString(), ctx.typeArguments(),referenceTypeContext.getStart(), reg, generics); }else{ throw new NotImplementedException(); } diff --git a/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java b/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java index 72097fc0..e0c09e92 100644 --- a/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java +++ b/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java @@ -106,4 +106,8 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{ public Collection getSuperInterfaces() { return implementedInterfaces; } + + public String toString() { + return this.name.toString() + this.genericClassParameters.toString(); + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java b/src/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java index e316aa6b..6a264684 100644 --- a/src/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java +++ b/src/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java @@ -31,4 +31,8 @@ public class GenericDeclarationList extends SyntaxTreeNode implements Iterable PLACEHOLDERS = new ArrayList<>(); public static FiniteClosure generateFC(List fromClasses) throws ClassNotFoundException { /* @@ -113,7 +115,15 @@ public class UnifyTypeFactory { } public static UnifyType convert(TypePlaceholder tph){ - return new PlaceholderType(tph.getName()); + PlaceholderType ntph = new PlaceholderType(tph.getName()); + int in = PLACEHOLDERS.indexOf(ntph); + if (in == -1) { + PLACEHOLDERS.add(ntph); + return ntph; + } + else { + return PLACEHOLDERS.get(in); + } } public static UnifyType convert(GenericRefType t){ diff --git a/src/de/dhbwstuttgart/typeinference/constraints/Pair.java b/src/de/dhbwstuttgart/typeinference/constraints/Pair.java index ab0cb3ea..eb322274 100644 --- a/src/de/dhbwstuttgart/typeinference/constraints/Pair.java +++ b/src/de/dhbwstuttgart/typeinference/constraints/Pair.java @@ -11,6 +11,7 @@ public class Pair implements Serializable public final RefTypeOrTPHOrWildcardOrGeneric TA2; private PairOperator eOperator = PairOperator.SMALLER; + public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2 ) { diff --git a/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index 19f212bf..4cf58121 100644 --- a/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -57,8 +57,8 @@ public class TYPEStmt implements StatementVisitor{ public void visit(LambdaExpression lambdaExpression) { TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken()); List lambdaParams = lambdaExpression.params.getFormalparalist().stream().map((formalParameter -> formalParameter.getType())).collect(Collectors.toList()); - //lambdaParams.add(tphRetType); - lambdaParams.add(0,tphRetType); + lambdaParams.add(tphRetType); + //lambdaParams.add(0,tphRetType); constraintsSet.addUndConstraint( new Pair(lambdaExpression.getType(), new FunN(lambdaParams),PairOperator.EQUALSDOT)); @@ -185,6 +185,12 @@ public class TYPEStmt implements StatementVisitor{ } private final RefType number = new RefType(ASTFactory.createClass(Number.class).getClassName(), new NullToken()); + private final RefType longg = new RefType(ASTFactory.createClass(Long.class).getClassName(), new NullToken()); + private final RefType integer = new RefType(ASTFactory.createClass(Integer.class).getClassName(), new NullToken()); + private final RefType shortt = new RefType(ASTFactory.createClass(Short.class).getClassName(), new NullToken()); + private final RefType bytee = new RefType(ASTFactory.createClass(Byte.class).getClassName(), new NullToken()); + private final RefType floatt = new RefType(ASTFactory.createClass(Float.class).getClassName(), new NullToken()); + private final RefType doublee = new RefType(ASTFactory.createClass(Double.class).getClassName(), new NullToken()); private final RefType string = new RefType(ASTFactory.createClass(String.class).getClassName(), new NullToken()); private final RefType bool = new RefType(ASTFactory.createClass(Boolean.class).getClassName(), new NullToken()); @Override @@ -205,18 +211,47 @@ public class TYPEStmt implements StatementVisitor{ @Override public void visit(BinaryExpr binary) { - + binary.lexpr.accept(this); + binary.rexpr.accept(this); if(binary.operation.equals(BinaryExpr.Operator.DIV) || binary.operation.equals(BinaryExpr.Operator.MUL)|| binary.operation.equals(BinaryExpr.Operator.MOD)|| binary.operation.equals(BinaryExpr.Operator.ADD)){ Set numericAdditionOrStringConcatenation = new HashSet<>(); - Constraint numeric = new Constraint<>(); + //Zuerst der Fall für Numerische AusdrücPairOpnumericeratorke, das sind Mul, Mod und Div immer: //see: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17 //Expression muss zu Numeric Convertierbar sein. also von Numeric erben - numeric.add(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERDOT)); - numeric.add(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERDOT)); + Constraint numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), bytee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), bytee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), integer, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), shortt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), shortt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), integer, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), integer, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), integer, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), integer, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), longg, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), longg, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), longg, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), floatt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), floatt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), floatt, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), doublee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), doublee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), doublee, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); /* In Java passiert bei den binären Operatoren eine sogenannte Type Promotion: https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2 diff --git a/src/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java b/src/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java index 1c75ea99..087b8943 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java +++ b/src/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java @@ -94,7 +94,8 @@ public class MartelliMontanariUnify implements IUnify { // SUBST - Rule if(lhsType instanceof PlaceholderType) { mgu.add((PlaceholderType) lhsType, rhsType); - termsList = termsList.stream().map(mgu::apply).collect(Collectors.toCollection(ArrayList::new)); + //PL 2018-04-01 nach checken, ob es richtig ist, dass keine Substitutionen uebergeben werden muessen. + termsList = termsList.stream().map(x -> mgu.apply(x)).collect(Collectors.toCollection(ArrayList::new)); idx = idx+1 == termsList.size() ? 0 : idx+1; continue; } diff --git a/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java b/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java index 8c41660b..5631724b 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java +++ b/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java @@ -24,13 +24,27 @@ 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.WildcardType; +import de.dhbwstuttgart.typeinference.unify.distributeVariance; + +import java.io.FileWriter; +import java.io.IOException; /** * Implementation of the type inference rules. * @author Florian Steurer * */ -public class RuleSet implements IRuleSet{ +public class RuleSet implements IRuleSet{ + + FileWriter logFile; + + RuleSet() { + super(); + } + + RuleSet(FileWriter logFile) { + this.logFile = logFile; + } @Override public Optional reduceUp(UnifyPair pair) { @@ -47,7 +61,7 @@ public class RuleSet implements IRuleSet{ return Optional.empty(); // Rule is applicable, unpack the SuperType - return Optional.of(new UnifyPair(lhsType, ((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT)); + return Optional.of(new UnifyPair(lhsType, ((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -65,7 +79,7 @@ public class RuleSet implements IRuleSet{ return Optional.empty(); // Rule is applicable, unpack the ExtendsType - return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), rhsType, PairOperator.SMALLERDOT)); + return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), rhsType, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -83,7 +97,7 @@ public class RuleSet implements IRuleSet{ return Optional.empty(); // Rule is applicable, unpack both sides - return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(),((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT)); + return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(),((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -133,7 +147,7 @@ public class RuleSet implements IRuleSet{ Set result = new HashSet<>(); for(int rhsIdx = 0; rhsIdx < extYParams.size(); rhsIdx++) - result.add(new UnifyPair(xParams.get(pi[rhsIdx]), extYParams.get(rhsIdx), PairOperator.SMALLERDOTWC)); + result.add(new UnifyPair(xParams.get(pi[rhsIdx]), extYParams.get(rhsIdx), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); return Optional.of(result); } @@ -184,7 +198,7 @@ public class RuleSet implements IRuleSet{ return Optional.empty(); for(int rhsIdx = 0; rhsIdx < supYParams.size(); rhsIdx++) - result.add(new UnifyPair(supYParams.get(rhsIdx), xParams.get(pi[rhsIdx]), PairOperator.SMALLERDOTWC)); + result.add(new UnifyPair(supYParams.get(rhsIdx), xParams.get(pi[rhsIdx]), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); return Optional.of(result); } @@ -215,7 +229,7 @@ public class RuleSet implements IRuleSet{ TypeParams rhsTypeParams = rhsType.getTypeParams(); for(int i = 0; i < lhsTypeParams.size(); i++) - result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT)); + result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); return Optional.of(result); } @@ -236,19 +250,53 @@ public class RuleSet implements IRuleSet{ ReferenceType lhsSType = (ReferenceType) c; ReferenceType rhsSType = (ReferenceType) d; + //try { + // logFile.write("PAIR Rules: " + pair + "\n"); + // logFile.flush(); + //} + //catch (IOException e) { } + if(lhsSType.getTypeParams().empty() || lhsSType.getTypeParams().size() != rhsSType.getTypeParams().size()) return Optional.empty(); UnifyType cFromFc = fc.getLeftHandedType(c.getName()).orElse(null); + //2018-02-23: liefert Vector>: Das kann nicht sein. + + //NOCHMAL UEBERPRUEFEN + //PL 18-02-09 Eingfuegt Anfang + //C und D koennen auch gleich sein. + if (c.getName().equals(d.getName())) { + Set result = new HashSet<>(); + TypeParams rhsTypeParams = d.getTypeParams(); + TypeParams lhsTypeParams = c.getTypeParams(); + for(int rhsIdx = 0; rhsIdx < c.getTypeParams().size(); rhsIdx++) + result.add(new UnifyPair(lhsTypeParams.get(rhsIdx), rhsTypeParams.get(rhsIdx), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); + + return Optional.of(result); + } + //PL 18-02-09 Eingfuegt ENDE + + //try { + // logFile.write("cFromFc: " + cFromFc); + // logFile.flush(); + //} + //catch (IOException e) { } if(cFromFc == null || !cFromFc.getTypeParams().arePlaceholders()) return Optional.empty(); UnifyType dFromFc = fc.getAncestors(cFromFc).stream().filter(x -> x.getName().equals(d.getName())).findAny().orElse(null); + //try { + // logFile.write("cFromFc: " + cFromFc); + // logFile.flush(); + //} + //catch (IOException e) { } + if(dFromFc == null || !dFromFc.getTypeParams().arePlaceholders() || dFromFc.getTypeParams().size() != cFromFc.getTypeParams().size()) return Optional.empty(); - + //System.out.println("cFromFc: " + cFromFc); + //System.out.println("dFromFc: " + dFromFc); int[] pi = pi(cFromFc.getTypeParams(), dFromFc.getTypeParams()); if(pi.length == 0) @@ -259,7 +307,7 @@ public class RuleSet implements IRuleSet{ Set result = new HashSet<>(); for(int rhsIdx = 0; rhsIdx < rhsTypeParams.size(); rhsIdx++) - result.add(new UnifyPair(lhsTypeParams.get(pi[rhsIdx]), rhsTypeParams.get(rhsIdx), PairOperator.SMALLERDOTWC)); + result.add(new UnifyPair(lhsTypeParams.get(pi[rhsIdx]), rhsTypeParams.get(rhsIdx), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); return Optional.of(result); } @@ -314,7 +362,7 @@ public class RuleSet implements IRuleSet{ TypeParams rhsTypeParams = rhsSType.getTypeParams(); TypeParams lhsTypeParams = lhsSType.getTypeParams(); for(int i = 0; i < rhsTypeParams.size(); i++) - result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT)); + result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); return Optional.of(result); } @@ -365,7 +413,7 @@ public class RuleSet implements IRuleSet{ if(!(pair.getRhsType() instanceof PlaceholderType)) return Optional.empty(); - return Optional.of(new UnifyPair(pair.getRhsType(), pair.getLhsType(), PairOperator.EQUALSDOT)); + return Optional.of(new UnifyPair(pair.getRhsType(), pair.getLhsType(), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -407,11 +455,19 @@ public class RuleSet implements IRuleSet{ TypeParams typeDParams = typeD.getTypeParams(); TypeParams typeDgenParams = typeDgen.getTypeParams(); + //System.out.println("Pair: " +pair); + //System.out.println("typeD: " +typeD); + //System.out.println("typeDParams: " +typeDParams); + //System.out.println("typeDgen: " +typeD); + //System.out.println("typeDgenParams: " +typeDgenParams); Unifier unif = Unifier.identity(); - for(int i = 0; i < typeDParams.size(); i++) + for(int i = 0; i < typeDParams.size(); i++) { + //System.out.println("ADAPT" +typeDgenParams); + if (typeDgenParams.get(i) instanceof PlaceholderType) unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i)); - - return Optional.of(new UnifyPair(unif.apply(newLhs), typeDs, PairOperator.SMALLERDOT)); + else System.out.println("ERROR"); + } + return Optional.of(new UnifyPair(unif.apply(newLhs), typeDs, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -457,7 +513,7 @@ public class RuleSet implements IRuleSet{ for(int i = 1; i < typeDParams.size(); i++) unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i)); - return Optional.of(new UnifyPair(unif.apply(newLhs), typeExtDs, PairOperator.SMALLERDOTWC)); + return Optional.of(new UnifyPair(unif.apply(newLhs), typeExtDs, PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -509,7 +565,7 @@ public class RuleSet implements IRuleSet{ for(int i = 1; i < typeDParams.size(); i++) unif.add((PlaceholderType) typeSupDsgenParams.get(i), typeDParams.get(i)); - return Optional.of(new UnifyPair(unif.apply(newLhs), newRhs, PairOperator.SMALLERDOTWC)); + return Optional.of(new UnifyPair(unif.apply(newLhs), newRhs, PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); } /** @@ -581,8 +637,8 @@ public class RuleSet implements IRuleSet{ && typeMap.get(lhsType) > 1 // The type occurs in more pairs in the set than just the recent pair. && !rhsType.getTypeParams().occurs(lhsType)) { Unifier uni = new Unifier(lhsType, rhsType); - result = result.stream().map(uni::apply).collect(Collectors.toCollection(ArrayList::new)); - result1 = result1.stream().map(uni::apply).collect(Collectors.toCollection(LinkedList::new)); + result = result.stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(ArrayList::new)); + result1 = result1.stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(LinkedList::new)); applied = true; } @@ -602,7 +658,7 @@ public class RuleSet implements IRuleSet{ if(!(lhsType instanceof ExtendsType) || !(rhsType instanceof ExtendsType)) return Optional.empty(); - return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT)); + return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -615,7 +671,7 @@ public class RuleSet implements IRuleSet{ if(!(lhsType instanceof ReferenceType) || !(rhsType instanceof ExtendsType)) return Optional.empty(); - return Optional.of(new UnifyPair(lhsType, ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT)); + return Optional.of(new UnifyPair(lhsType, ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -628,7 +684,7 @@ public class RuleSet implements IRuleSet{ if(!(lhsType instanceof SuperType) || !(rhsType instanceof SuperType)) return Optional.empty(); - return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), ((SuperType) lhsType).getSuperedType(), PairOperator.SMALLERDOT)); + return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), ((SuperType) lhsType).getSuperedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -641,9 +697,11 @@ public class RuleSet implements IRuleSet{ if(!(lhsType instanceof ReferenceType) || !(rhsType instanceof SuperType)) return Optional.empty(); - return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), lhsType, PairOperator.SMALLERDOTWC)); + return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), lhsType, PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); } + /* PL 2018-03-06 auskommentiert sind mutmaßlich falsch + * vgl. JAVA_BSP/Wildcard6.java @Override public Optional reduceWildcardLowUp(UnifyPair pair) { if(pair.getPairOp() != PairOperator.SMALLERDOTWC) @@ -670,6 +728,7 @@ public class RuleSet implements IRuleSet{ return Optional.of(new UnifyPair(((SuperType) lhsType).getSuperedType(), ((ExtendsType) rhsType).getExtendedType(), PairOperator.EQUALSDOT)); } + @Override public Optional reduceWildcardLeft(UnifyPair pair) { if(pair.getPairOp() != PairOperator.SMALLERDOTWC) @@ -686,7 +745,7 @@ public class RuleSet implements IRuleSet{ return Optional.empty(); } - + */ @Override public Optional> reduceFunN(UnifyPair pair) { if((pair.getPairOp() != PairOperator.SMALLERDOT) @@ -709,13 +768,19 @@ public class RuleSet implements IRuleSet{ Set result = new HashSet(); - result.add(new UnifyPair(funNLhsType.getTypeParams().get(0), funNRhsType.getTypeParams().get(0), PairOperator.SMALLERDOT)); - for(int i = 1; i < funNLhsType.getTypeParams().size(); i++) - result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), funNLhsType.getTypeParams().get(i), 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())); + } + result.stream().forEach(x -> { UnifyType l = x.getLhsType(); + if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); } + UnifyType r = x.getRhsType(); + if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); } + } ); return Optional.of(result); } - + + @Override public Optional> greaterFunN(UnifyPair pair) { if(pair.getPairOp() != PairOperator.SMALLERDOT) @@ -731,15 +796,29 @@ public class RuleSet implements IRuleSet{ Set result = new HashSet(); + Integer variance = ((PlaceholderType)rhsType).getVariance(); + Integer inversVariance = distributeVariance.inverseVariance(variance); + UnifyType[] freshPlaceholders = new UnifyType[funNLhsType.getTypeParams().size()]; - for(int i = 0; i < freshPlaceholders.length; i++) + for(int i = 0; i < freshPlaceholders.length-1; i++) { freshPlaceholders[i] = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)freshPlaceholders[i]).setVariance(inversVariance); + } + freshPlaceholders[freshPlaceholders.length-1] = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)freshPlaceholders[freshPlaceholders.length-1]).setVariance(variance); + result.add(new UnifyPair(funNLhsType.getTypeParams().get(funNLhsType.getTypeParams().size()-1), freshPlaceholders[funNLhsType.getTypeParams().size()-1], PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); - result.add(new UnifyPair(funNLhsType.getTypeParams().get(0), freshPlaceholders[0], PairOperator.SMALLERDOT)); - for(int i = 1; i < funNLhsType.getTypeParams().size(); i++) - result.add(new UnifyPair(freshPlaceholders[i], funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT)); - result.add(new UnifyPair(rhsType, funNLhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT)); + for(int i = 0; i < funNLhsType.getTypeParams().size()-1; i++) { + result.add(new UnifyPair(freshPlaceholders[i], funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + result.add(new UnifyPair(rhsType, funNLhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + + result.stream().forEach(x -> { UnifyType l = x.getLhsType(); + if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); } + UnifyType r = x.getRhsType(); + if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); } + } ); return Optional.of(result); } @@ -758,15 +837,30 @@ public class RuleSet implements IRuleSet{ Set result = new HashSet(); + Integer variance = ((PlaceholderType)lhsType).getVariance(); + Integer inversVariance = distributeVariance.inverseVariance(variance); + UnifyType[] freshPlaceholders = new UnifyType[funNRhsType.getTypeParams().size()]; - for(int i = 0; i < freshPlaceholders.length; i++) + for(int i = 0; i < freshPlaceholders.length-1; i++) { freshPlaceholders[i] = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)freshPlaceholders[i]).setVariance(inversVariance); + } + freshPlaceholders[freshPlaceholders.length-1] = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)freshPlaceholders[freshPlaceholders.length-1]).setVariance(variance); - result.add(new UnifyPair(freshPlaceholders[0], funNRhsType.getTypeParams().get(0), PairOperator.SMALLERDOT)); - for(int i = 1; i < funNRhsType.getTypeParams().size(); i++) - result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), freshPlaceholders[i], PairOperator.SMALLERDOT)); - result.add(new UnifyPair(lhsType, funNRhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT)); + result.add(new UnifyPair(freshPlaceholders[funNRhsType.getTypeParams().size()-1], funNRhsType.getTypeParams().get(funNRhsType.getTypeParams().size()-1), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + for(int i = 0; i < funNRhsType.getTypeParams().size()-1; i++) { + result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), freshPlaceholders[i], PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + + result.add(new UnifyPair(lhsType, funNRhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + + result.stream().forEach(x -> { UnifyType l = x.getLhsType(); + if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); } + UnifyType r = x.getRhsType(); + if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); } + } ); return Optional.of(result); } @@ -780,7 +874,7 @@ public class RuleSet implements IRuleSet{ if(!(lhsType instanceof PlaceholderType) || !(rhsType instanceof ReferenceType)) return Optional.empty(); - return Optional.of(new UnifyPair(lhsType, rhsType, PairOperator.EQUALSDOT)); + return Optional.of(new UnifyPair(lhsType, rhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -799,11 +893,11 @@ public class RuleSet implements IRuleSet{ Set result = new HashSet<>(); if(isGen) - result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT)); + result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); else { UnifyType freshTph = PlaceholderType.freshPlaceholder(); - result.add(new UnifyPair(rhsType, new ExtendsType(freshTph), PairOperator.EQUALSDOT)); - result.add(new UnifyPair(extendedType, freshTph, PairOperator.SMALLERDOT)); + result.add(new UnifyPair(rhsType, new ExtendsType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + result.add(new UnifyPair(extendedType, freshTph, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } return Optional.of(result); @@ -825,11 +919,11 @@ public class RuleSet implements IRuleSet{ Set result = new HashSet<>(); if(isGen) - result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT)); + result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); else { UnifyType freshTph = PlaceholderType.freshPlaceholder(); - result.add(new UnifyPair(rhsType, new SuperType(freshTph), PairOperator.EQUALSDOT)); - result.add(new UnifyPair(freshTph, superedType, PairOperator.SMALLERDOT)); + result.add(new UnifyPair(rhsType, new SuperType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + result.add(new UnifyPair(freshTph, superedType, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } return Optional.of(result); diff --git a/src/de/dhbwstuttgart/typeinference/unify/TypeUnify.java b/src/de/dhbwstuttgart/typeinference/unify/TypeUnify.java index f457fbb8..69ed93b2 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/TypeUnify.java +++ b/src/de/dhbwstuttgart/typeinference/unify/TypeUnify.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.typeinference.unify; +import java.io.FileWriter; import java.util.Set; import java.util.concurrent.ForkJoinPool; @@ -7,16 +8,16 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; public class TypeUnify { - public Set> unify(Set eq, IFiniteClosure fc) { - TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, true); + public Set> unify(Set eq, IFiniteClosure fc, FileWriter logFile) { + TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, true, logFile); ForkJoinPool pool = new ForkJoinPool(); pool.invoke(unifyTask); Set> res = unifyTask.join(); return res; } - public Set> unifySequential(Set eq, IFiniteClosure fc) { - TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, false); + public Set> unifySequential(Set eq, IFiniteClosure fc, FileWriter logFile) { + TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, false, logFile); Set> res = unifyTask.compute(); return res; } diff --git a/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java b/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java index e51679e2..1d5ca564 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java +++ b/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java @@ -3,7 +3,9 @@ package de.dhbwstuttgart.typeinference.unify; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; @@ -11,7 +13,9 @@ import java.util.Map.Entry; import java.util.Optional; import java.util.Set; import java.util.concurrent.RecursiveTask; +import java.util.function.BinaryOperator; import java.util.stream.Collectors; +import java.util.stream.Stream; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet; @@ -25,16 +29,27 @@ 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 java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import com.google.common.collect.Ordering; /** * Implementation of the type unification algorithm * @author Florian Steurer */ -public class TypeUnifyTask extends RecursiveTask>> { +public class TypeUnifyTask extends RecursiveTask>> { private static final long serialVersionUID = 1L; private static int i = 0; + private boolean printtag = false; + + public static final String rootDirectory = System.getProperty("user.dir")+"/test/logFiles/"; + FileWriter logFile; /** * The implementation of setOps that will be used during the unification @@ -49,23 +64,75 @@ public class TypeUnifyTask extends RecursiveTask>> { /** * The implementation of the rules that will be used during the unification. */ - protected IRuleSet rules = new RuleSet(); + protected IRuleSet rules; protected Set eq; protected IFiniteClosure fc; + protected Ordering> oup; + protected boolean parallel; - public TypeUnifyTask(Set eq, IFiniteClosure fc, boolean parallel) { + Integer nOfUnify = 0; + + Integer noUndefPair = 0; + + Integer noAllErasedElements = 0; + + Integer noBacktracking = 0; + + public TypeUnifyTask() { + rules = new RuleSet(); + } + + public TypeUnifyTask(Set eq, IFiniteClosure fc, boolean parallel, FileWriter logFile) { this.eq = eq; this.fc = fc; + this.oup = new OrderingUnifyPair(fc); this.parallel = parallel; + this.logFile = logFile; + rules = new RuleSet(logFile); } - + + + /** + * Vererbt alle Variancen + * @param eq The set of constraints + */ + /* PL 2018-05- 17 verschoben nach JavaTXCompiler + private void varianceInheritance(Set eq) { + Set usedTPH = new HashSet<>(); + Set phSet = eq.stream().map(x -> { + Set pair = new HashSet<>(); + if (x.getLhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getLhsType()); + if (x.getRhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getRhsType()); + return pair; + }).reduce(new HashSet<>(), (a,b) -> { a.addAll(b); return a;} , (c,d) -> { c.addAll(d); return c;}); + + ArrayList phSetVariance = new ArrayList<>(phSet); + phSetVariance.removeIf(x -> (x.getVariance() == 0)); + while(!phSetVariance.isEmpty()) { + PlaceholderType a = phSetVariance.remove(0); + usedTPH.add(a); + //HashMap ht = new HashMap<>(); + //ht.put(a, a.getVariance()); + Set eq1 = new HashSet<>(eq); + eq1.removeIf(x -> !(x.getLhsType() instanceof PlaceholderType && ((PlaceholderType)x.getLhsType()).equals(a))); + eq1.stream().forEach(x -> { x.getRhsType().accept(new distributeVariance(), a.getVariance());}); + eq1 = new HashSet<>(eq); + eq1.removeIf(x -> !(x.getRhsType() instanceof PlaceholderType && ((PlaceholderType)x.getRhsType()).equals(a))); + eq1.stream().forEach(x -> { x.getLhsType().accept(new distributeVariance(), a.getVariance());}); + phSetVariance = new ArrayList<>(phSet); + phSetVariance.removeIf(x -> (x.getVariance() == 0 || usedTPH.contains(x))); + } +} +*/ @Override protected Set> compute() { - return unify(eq, fc, parallel); + Set> res = unify(eq, fc, parallel); + if (isUndefinedPairSetSet(res)) { return new HashSet<>(); } + else return res; } /** @@ -74,11 +141,38 @@ public class TypeUnifyTask extends RecursiveTask>> { * @param fc The finite closure * @return The set of all principal type unifiers */ - protected Set> unify(Set eq, IFiniteClosure fc, boolean parallel) { + protected Set> unify(Set eq, IFiniteClosure fc, boolean parallel) { + Set aas = eq.stream().filter(x -> x.getLhsType().getName().equals("AA") //&& x.getPairOp().equals(PairOperator.SMALLERDOT) + ).collect(Collectors.toCollection(HashSet::new)); + writeLog(nOfUnify.toString() + " AA: " + aas.toString()); + if (aas.isEmpty()) { + System.out.println(""); + } /* * Step 1: Repeated application of reduce, adapt, erase, swap */ - //System.out.println("Unifikation: " + eq); + nOfUnify++; + writeLog(nOfUnify.toString() + " Unifikation: " + eq.toString()); + //eq = eq.stream().map(x -> {x.setVariance((byte)-1); return x;}).collect(Collectors.toCollection(HashSet::new)); + + /* + * Variancen auf alle Gleichungen vererben + */ + //PL 2018-05-17 nach JavaTXCompiler verschoben + //varianceInheritance(eq); + + /* + * ? extends ? extends Theta rausfiltern + */ + Set doubleExt = eq.stream().filter(x -> (x.wrongWildcard())).map(x -> { x.setUndefinedPair(); return x;}) + .collect(Collectors.toCollection(HashSet::new)); + if (doubleExt.size() > 0) { + Set> ret = new HashSet<>(); + ret.add(doubleExt); + return ret; + } + + Set eq0 = applyTypeUnificationRules(eq, fc); /* @@ -99,7 +193,7 @@ public class TypeUnifyTask extends RecursiveTask>> { // cartesian product of the sets created by pattern matching. List>> topLevelSets = new ArrayList<>(); - System.out.println(eq2s); + //System.out.println(eq2s); if(eq1s.size() != 0) { // Do not add empty sets or the cartesian product will always be empty. Set> wrap = new HashSet<>(); @@ -122,22 +216,34 @@ public class TypeUnifyTask extends RecursiveTask>> { // Sets that originate from pair pattern matching // Sets of the "second level" Set undefinedPairs = new HashSet<>(); + if (printtag) System.out.println("eq2s " + eq2s); + //writeLog("BufferSet: " + bufferSet.toString()+"\n"); Set>>> secondLevelSets = calculatePairSets(eq2s, fc, undefinedPairs); //PL 2017-09-20: Im calculatePairSets wird möglicherweise O .< java.lang.Integer //nicht ausgewertet Faculty Beispiel im 1. Schritt //PL 2017-10-03 geloest, muesste noch mit FCs mit kleineren //Typen getestet werden. + if (printtag) System.out.println("secondLevelSets:" +secondLevelSets); // If pairs occured that did not match one of the cartesian product cases, // those pairs are contradictory and the unification is impossible. - if(!undefinedPairs.isEmpty()) - return new HashSet<>(); + if(!undefinedPairs.isEmpty()) { + noUndefPair++; + for (UnifyPair up : undefinedPairs) { + writeLog(noUndefPair.toString() + " UndefinedPairs; " + up); + writeLog("BasePair; " + up.getBasePair()); + } + Set> error = new HashSet<>(); + undefinedPairs = undefinedPairs.stream().map(x -> { x.setUndefinedPair(); return x;}).collect(Collectors.toCollection(HashSet::new)); + error.add(undefinedPairs); + return error; + } /* Up to here, no cartesian products are calculated. * filters for pairs and sets can be applied here */ - // Sub cartesian products of the second level (pattern matched) sets + // Alternative: Sub cartesian products of the second level (pattern matched) sets // "the big (x)" - for(Set>> secondLevelSet : secondLevelSets) { + /* for(Set>> secondLevelSet : secondLevelSets) { //System.out.println("secondLevelSet "+secondLevelSet.size()); List>> secondLevelSetList = new ArrayList<>(secondLevelSet); Set>> cartResult = setOps.cartesianProduct(secondLevelSetList); @@ -153,62 +259,108 @@ public class TypeUnifyTask extends RecursiveTask>> { flat1.addAll(s1); flat.add(flat1); } - topLevelSets.add(flat); + //topLevelSets.add(flat); } + */ + //Alternative KEIN KARTESISCHES PRODUKT der secondlevel Ebene bilden + for(Set>> secondLevelSet : secondLevelSets) { + for (Set> secondlevelelem : secondLevelSet) { + topLevelSets.add(secondlevelelem); + } + } + //System.out.println(topLevelSets); + //System.out.println(); + + + //Aufruf von computeCartesianRecursive ANFANG + return computeCartesianRecursive(new HashSet<>(), new ArrayList<>(topLevelSets), eq, fc, parallel); + + } + + + Set> unify2(Set> setToFlatten, Set eq, IFiniteClosure fc, boolean parallel) { + //Aufruf von computeCartesianRecursive ENDE + + //keine Ahnung woher das kommt + //Set> setToFlatten = topLevelSets.stream().map(x -> x.iterator().next()).collect(Collectors.toCollection(HashSet::new)); + + //Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG // Cartesian product over all (up to 10) top level sets - Set>> eqPrimeSet = setOps.cartesianProduct(topLevelSets) - .stream().map(x -> new HashSet<>(x)) - .collect(Collectors.toCollection(HashSet::new)); + //Set>> eqPrimeSet = setOps.cartesianProduct(topLevelSets) + // .stream().map(x -> new HashSet<>(x)) + // .collect(Collectors.toCollection(HashSet::new)); + //Muss auskommentiert werden, wenn computeCartesianRecursive ENDE Set> eqPrimePrimeSet = new HashSet<>(); Set forks = new HashSet<>(); - for(Set> setToFlatten : eqPrimeSet) { + + //Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG + //for(Set> setToFlatten : eqPrimeSet) { // Flatten the cartesian product + //Muss auskommentiert werden, wenn computeCartesianRecursive ENDE Set eqPrime = new HashSet<>(); setToFlatten.stream().forEach(x -> eqPrime.addAll(x)); /* * Step 5: Substitution */ - System.out.println("vor Subst: " + eqPrime); + //System.out.println("vor Subst: " + eqPrime); Optional> eqPrimePrime = rules.subst(eqPrime); /* * Step 6 a) Restart (fork) for pairs where subst was applied */ if(parallel) { - if //(eqPrime.equals(eq)) //PL 2017-09-29 auskommentiert und durch - (!eqPrimePrime.isPresent()) //PL 2071-09-29 dies ersetzt - //Begruendung: Wenn in der Substitution keine Veraenderung - //(!eqPrimePrime.isPresent()) erfolgt ist, ist das Ergebnis erzielt. + if (eqPrime.equals(eq) && !eqPrimePrime.isPresent()) //PL 2017-09-29 //(!eqPrimePrime.isPresent()) auskommentiert und durch + //PL 2017-09-29 dies ersetzt //(!eqPrimePrime.isPresent()) + //PL 2018-05-18 beide Bedingungen muessen gelten, da eqPrime Veränderungen in allem ausser subst + //eqPrimePrime Veraenderungen in subst repraesentieren. eqPrimePrimeSet.add(eqPrime); else if(eqPrimePrime.isPresent()) { - System.out.println("nextStep: " + eqPrimePrime.get()); - TypeUnifyTask fork = new TypeUnifyTask(eqPrimePrime.get(), fc, true); + //System.out.println("nextStep: " + eqPrimePrime.get()); + TypeUnifyTask fork = new TypeUnifyTask(eqPrimePrime.get(), fc, true, logFile); forks.add(fork); fork.fork(); } else { - System.out.println("nextStep: " + eqPrime); - TypeUnifyTask fork = new TypeUnifyTask(eqPrime, fc, true); + //System.out.println("nextStep: " + eqPrime); + TypeUnifyTask fork = new TypeUnifyTask(eqPrime, fc, true, logFile); forks.add(fork); fork.fork(); } } else { // sequentiell (Step 6b is included) - if //(eqPrime.equals(eq)) //PL 2017-09-29 auskommentiert und durch - (!eqPrimePrime.isPresent()) //PL 2071-09-29 dies ersetzt - //Begruendung: Wenn in der Substitution keine Veraenderung - //(!eqPrimePrime.isPresent()) erfolgt ist, ist das Ergebnis erzielt. + if (printtag) System.out.println("nextStep: " + eqPrimePrime); + if (eqPrime.equals(eq) && !eqPrimePrime.isPresent()) { //PL 2017-09-29 //(!eqPrimePrime.isPresent()) auskommentiert und durch + //PL 2017-09-29 dies ersetzt //(!eqPrimePrime.isPresent()) + //PL 2018-05-18 beide Bedingungen muessen gelten, da eqPrime Veränderungen in allem ausser subst + //eqPrimePrime Veraenderungen in subst repraesentieren. + try { + if (isSolvedForm(eqPrime)) { + logFile.write(eqPrime.toString()+"\n"); + logFile.flush(); + } + } + catch (IOException e) { } eqPrimePrimeSet.add(eqPrime); - else if(eqPrimePrime.isPresent()) - eqPrimePrimeSet.addAll(unify(eqPrimePrime.get(), fc, false)); - else - eqPrimePrimeSet.addAll(unify(eqPrime, fc, false)); + } + else if(eqPrimePrime.isPresent()) { + Set> unifyres = unify(eqPrimePrime.get(), fc, false); + + eqPrimePrimeSet.addAll(unifyres); + } + else { + Set> unifyres = unify(eqPrime, fc, false); + + + eqPrimePrimeSet.addAll(unifyres); + } } - } + //Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG + //} + //Muss auskommentiert werden, wenn computeCartesianRecursive ENDE /* * Step 6 b) Build the union over everything. @@ -221,10 +373,231 @@ public class TypeUnifyTask extends RecursiveTask>> { /* * Step 7: Filter empty sets; */ - return eqPrimePrimeSet.stream().filter(x -> isSolvedForm(x)).collect(Collectors.toCollection(HashSet::new)); - + eqPrimePrimeSet = eqPrimePrimeSet.stream().filter(x -> isSolvedForm(x) || this.isUndefinedPairSet(x)).collect(Collectors.toCollection(HashSet::new)); + if (!eqPrimePrimeSet.isEmpty() && !isUndefinedPairSetSet(eqPrimePrimeSet)) + writeLog("Result1 " + eqPrimePrimeSet.toString()); + return eqPrimePrimeSet; } + + + Set> computeCartesianRecursive(Set> fstElems, ArrayList>> topLevelSets, Set eq, IFiniteClosure fc, boolean parallel) { + //ArrayList>> remainingSets = new ArrayList<>(topLevelSets); + fstElems.addAll(topLevelSets.stream() + .filter(x -> x.size()==1) + .map(y -> y.stream().findFirst().get()) + .collect(Collectors.toCollection(HashSet::new))); + ArrayList>> remainingSets = topLevelSets.stream() + .filter(x -> x.size()>1) + .collect(Collectors.toCollection(ArrayList::new)); + if (remainingSets.isEmpty()) {//Alle Elemente sind 1-elementig + Set> result = unify2(fstElems, eq, fc, parallel); + return result; + } + Set> nextSet = remainingSets.remove(0); + writeLog("nextSet: " + nextSet.toString()); + List> nextSetasList =new ArrayList<>(nextSet); + try { + //List> + //nextSetasList = oup.sortedCopy(nextSet);//new ArrayList<>(nextSet); + } + catch (java.lang.IllegalArgumentException e) { + System.out.print(""); + } + Set> result = new HashSet<>(); + int variance = 0; + Optional xi = nextSetasList.stream().map(x -> x.stream().filter(y -> y.getLhsType() instanceof PlaceholderType) + .filter(z -> ((PlaceholderType)z.getLhsType()).getVariance() != 0) + .map(c -> ((PlaceholderType)c.getLhsType()).getVariance()) + .reduce((a,b)-> {if (a==b) return a; else return 0; })) + .filter(d -> d.isPresent()) + .map(e -> e.get()) + .findAny(); + if (xi.isPresent()) { + variance = xi.get(); + } + //if (variance == 1 && nextSetasList.size() > 1) { + // List> al = new ArrayList<>(nextSetasList.size()); + // for (int ii = 0; ii < nextSetasList.size();ii++) { + // al.add(0,nextSetasList.get(ii)); + // } + // nextSetasList = al; + //} + //Set a = nextSetasListIt.next(); + /*if (nextSetasList.size()>1) {zu loeschen + if (nextSetasList.iterator().next().iterator().next().getLhsType().getName().equals("D")) + System.out.print(""); + if (variance == 1) { + a_next = oup.max(nextSetasList.iterator()); + } + else if (variance == -1) { + a_next = oup.min(nextSetasList.iterator()); + } + else if (variance == 0) { + a_next = nextSetasList.iterator().next(); + } + } + else { + a_next = nextSetasList.iterator().next(); + } + */ + if (!nextSetasList.iterator().hasNext()) + System.out.print(""); + if (nextSetasList.iterator().next().stream().filter(x -> x.getLhsType().getName().equals("D")).findFirst().isPresent() && nextSetasList.size()>1) + System.out.print(""); + while (nextSetasList.size() > 0) { //(nextSetasList.size() != 0) { + Set a = null; + if (variance == 1) { + a = oup.max(nextSetasList.iterator()); + nextSetasList.remove(a); + } + else if (variance == -1) { + a = oup.min(nextSetasList.iterator()); + nextSetasList.remove(a); + } + else if (variance == 0) { + a = nextSetasList.remove(0); + } + //writeLog("nextSet: " + nextSetasList.toString()+ "\n"); + //nextSetasList.remove(a); + /* zu loeschen + if (nextSetasList.size() > 0) { + if (nextSetasList.size()>1) { + if (variance == 1) { + a_next = oup.max(nextSetasList.iterator()); + } + else if (variance == -1) { + a_next = oup.min(nextSetasList.iterator()); + } + else { + a_next = nextSetasList.iterator().next(); + } + } + else { + a_next = nextSetasList.iterator().next(); + } + } + */ + //PL 2018-03-01 + //TODO: 1. Maximum und Minimum unterscheiden + //TODO: 2. compare noch für alle Elmemente die nicht X =. ty sind erweitern + //for(Set a : newSet) { + i++; + Set> elems = new HashSet>(fstElems); + elems.add(a); + //if (remainingSets.isEmpty()) {//muss immer gegeben sein, weil nur 1 Element der topLevelSets mehr als ein Elemet enthaelt + Set> res = unify2(elems, eq, fc, parallel); + if (!isUndefinedPairSetSet(res) && isUndefinedPairSetSet(result)) { + //wenn korrektes Ergebnis gefunden alle Fehlerfaelle loeschen + result = res; + } + else { + if ((isUndefinedPairSetSet(res) && isUndefinedPairSetSet(result)) + || (!isUndefinedPairSetSet(res) && !isUndefinedPairSetSet(result)) + || result.isEmpty()) { + //alle Fehlerfaelle und alle korrekten Ergebnis jeweils adden + result.addAll(res); + } + //else { + //wenn Korrekte Ergebnisse da und Feherfälle dazukommen Fehlerfälle ignorieren + // if (isUndefinedPairSetSet(res) && !isUndefinedPairSetSet(result)) { + // result = result; + // } + //} + } + + //} + //else {//duerfte gar nicht mehr vorkommen PL 2018-04-03 + //result.addAll(computeCartesianRecursive(elems, remainingSets, eq, fc, parallel)); + //} + + 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) + System.out.print(""); + Iterator> nextSetasListIt = new ArrayList>(nextSetasList).iterator(); + if (variance == 1) { + System.out.println(""); + while (nextSetasListIt.hasNext()) { + Set a_next = nextSetasListIt.next(); + if (a.equals(a_next) || + (oup.compare(a, a_next) == 1)) { + nextSetasList.remove(a_next); + } + } + } + else { if (variance == -1) { + System.out.println(""); + while (nextSetasListIt.hasNext()) { + Set a_next = nextSetasListIt.next(); + if (a.equals(a_next) || + (oup.compare(a, a_next) == -1)) { + nextSetasList.remove(0); + } + } + } + else if (variance == 0) { + break; + } + } + } + if (isUndefinedPairSetSet(res)) { + Set abhSubst = res.stream() + .map(b -> + b.stream() + .map(x -> x.getAllSubstitutions()) + .reduce((y,z) -> { y.addAll(z); return y;}).get()) + .reduce((y,z) -> { y.addAll(z); return y;}).get(); + Set b = a;//effective final a + Set durchschnitt = abhSubst.stream() + .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)); + int len = nextSetasList.size(); + nextSetasList = nextSetasList.stream().filter(x -> { + //Boolean ret = false; + //for (PlaceholderType var : vars) { + // ret = ret || x.stream().map(b -> b.getLhsType().equals(var)).reduce((c,d) -> c || d).get(); + //} + return (!x.containsAll(durchschnitt)); + }).collect(Collectors.toCollection(ArrayList::new)); + writeLog("abhSubst: " + abhSubst.toString()); + writeLog("a: " + a.toString()); + writeLog("Durchschnitt: " + durchschnitt.toString()); + writeLog("nextSet: " + nextSet.toString()); + writeLog("nextSetasList: " + nextSetasList.toString()); + writeLog("Number erased Elements (undef): " + (len - nextSetasList.size())); + noAllErasedElements = noAllErasedElements + (len - nextSetasList.size()); + writeLog("Number erased Elements (undef): " + noAllErasedElements.toString()); + noBacktracking++; + writeLog("Number of Backtracking: " + noBacktracking); + System.out.println(""); + } + //if (nextSetasList.size() == 0 && isUndefinedPairSetSet(result) && nextSet.size() > 1) { + // return result; + //} + //else { + // result.removeIf(y -> isUndefinedPairSet(y)); + //} + //else result.stream().filter(y -> !isUndefinedPairSet(y)); + } + return result; + } + + + protected boolean isUndefinedPairSet(Set s) { + Boolean ret = s.stream().map(x -> x.isUndefinedPair()).reduce(true, (x,y)-> (x && y)); + return ret; + } + + protected boolean isUndefinedPairSetSet(Set> s) { + if (s.size() >= 1) { + Boolean ret = s.stream(). map(x -> isUndefinedPairSet(x)).reduce(true, (x,y)-> (x && y)); + return ret; + } + return false; + + } /** * Checks whether a set of pairs is in solved form. * @param eqPrimePrime The set of pair @@ -250,7 +623,7 @@ public class TypeUnifyTask extends RecursiveTask>> { * This is step one of the unification algorithm. * @return The set of pairs that results from repeated application of the inference rules. */ - protected Set applyTypeUnificationRules(Set eq, IFiniteClosure fc) { + public Set applyTypeUnificationRules(Set eq, IFiniteClosure fc) { /* * Rule Application Strategy: @@ -287,9 +660,10 @@ public class TypeUnifyTask extends RecursiveTask>> { opt = opt.isPresent() ? opt : rules.reduceWildcardLowRight(pair); opt = opt.isPresent() ? opt : rules.reduceWildcardUp(pair); opt = opt.isPresent() ? opt : rules.reduceWildcardUpRight(pair); - opt = opt.isPresent() ? opt : rules.reduceWildcardLowUp(pair); - opt = opt.isPresent() ? opt : rules.reduceWildcardUpLow(pair); - opt = opt.isPresent() ? opt : rules.reduceWildcardLeft(pair); + //PL 2018-03-06 auskommentiert muesste falsch sein vgl. JAVA_BSP/Wildcard6.java + //opt = opt.isPresent() ? opt : rules.reduceWildcardLowUp(pair); + //opt = opt.isPresent() ? opt : rules.reduceWildcardUpLow(pair); + //opt = opt.isPresent() ? opt : rules.reduceWildcardLeft(pair); // Reduce TPH opt = opt.isPresent() ? opt : rules.reduceTph(pair); @@ -301,6 +675,12 @@ public class TypeUnifyTask extends RecursiveTask>> { } // Reduce1, Reduce2, ReduceExt, ReduceSup, ReduceEq + //try { + // logFile.write("PAIR1 " + pair + "\n"); + // logFile.flush(); + //} + //catch (IOException e) { } + Optional> optSet = rules.reduce1(pair, fc); optSet = optSet.isPresent() ? optSet : rules.reduce2(pair); optSet = optSet.isPresent() ? optSet : rules.reduceExt(pair, fc); @@ -324,6 +704,11 @@ public class TypeUnifyTask extends RecursiveTask>> { } // Adapt, AdaptExt, AdaptSup + //try { + // logFile.write("PAIR2 " + pair + "\n"); + // logFile.flush(); + //} + //catch (IOException e) { } opt = rules.adapt(pair, fc); opt = opt.isPresent() ? opt : rules.adaptExt(pair, fc); opt = opt.isPresent() ? opt : rules.adaptSup(pair, fc); @@ -385,26 +770,77 @@ public class TypeUnifyTask extends RecursiveTask>> { // Init all 8 cases for(int i = 0; i < 8; i++) result.add(new HashSet<>()); - - for(UnifyPair pair : eq2s) { + ArrayList eq2sprime = new ArrayList<>(eq2s); + Iterator eq2sprimeit = eq2sprime.iterator(); + ArrayList eq2sAsList = new ArrayList<>(); + while(eq2sprimeit.hasNext()) {// alle mit Variance != 0 nach vorne schieben + UnifyPair up = eq2sprimeit.next(); + if ((up.getLhsType() instanceof PlaceholderType && ((PlaceholderType)up.getLhsType()).getVariance() != 0) + || (up.getRhsType() instanceof PlaceholderType && ((PlaceholderType)up.getRhsType()).getVariance() != 0)) { + eq2sAsList.add(up); + eq2s.remove(up); + } + } + eq2sAsList.addAll(eq2s); + Boolean first = true; + for(UnifyPair pair : eq2sAsList) { PairOperator pairOp = pair.getPairOp(); UnifyType lhsType = pair.getLhsType(); UnifyType rhsType = pair.getRhsType(); // Case 1: (a <. Theta') if(pairOp == PairOperator.SMALLERDOT && lhsType instanceof PlaceholderType) { - System.out.println(pair); - Set> x1 = unifyCase1((PlaceholderType) pair.getLhsType(), pair.getRhsType(), fc); - System.out.println(x1); - result.get(0).add(x1); + //System.out.println(pair); + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase1(pair, fc); + //System.out.println(x1); + result.get(0).add(x1); + if (x1.isEmpty()) { + undefined.add(pair); //Theta ist nicht im FC => Abbruch + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(0).add(s2); + } + } // Case 2: (a <.? ? ext Theta') else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof ExtendsType) - result.get(1).add(unifyCase2((PlaceholderType) pair.getLhsType(), (ExtendsType) pair.getRhsType(), fc)); + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase2(pair, fc); + result.get(1).add(x1); + if (x1.isEmpty()) { + undefined.add(pair); //Theta ist nicht im FC + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(1).add(s2); + } // Case 3: (a <.? ? sup Theta') else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof SuperType) - result.get(2).add(unifyCase3((PlaceholderType) lhsType, (SuperType) rhsType, fc)); + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase3(pair, fc); + result.get(2).add(x1); + if (x1.isEmpty()) { + undefined.add(pair); //Theta ist nicht im FC + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(2).add(s2); + } // Case 4 was replaced by an inference rule // Case 4: (a <.? Theta') @@ -413,7 +849,20 @@ public class TypeUnifyTask extends RecursiveTask>> { // Case 5: (Theta <. a) else if(pairOp == PairOperator.SMALLERDOT && rhsType instanceof PlaceholderType) - result.get(4).add(unifyCase5(lhsType, (PlaceholderType) rhsType, fc)); + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase5(pair, fc); + result.get(4).add(x1); + if (x1.isEmpty()) { + undefined.add(pair); //Theta ist nicht im FC + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(4).add(s2); + } // Case 6 was replaced by an inference rule. // Case 6: (? ext Theta <.? a) @@ -427,7 +876,20 @@ public class TypeUnifyTask extends RecursiveTask>> { // Case 8: (Theta <.? a) else if(pairOp == PairOperator.SMALLERDOTWC && rhsType instanceof PlaceholderType) - result.get(7).add(unifyCase8(lhsType, (PlaceholderType) rhsType, fc)); + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase8(pair, fc); + result.get(7).add(x1); + if (x1.isEmpty()) { + undefined.add(pair); //Theta ist nicht im FC + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(7).add(s2); + } // 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. @@ -436,6 +898,7 @@ public class TypeUnifyTask extends RecursiveTask>> { undefined.add(pair); break; } + first = false; } // Filter empty sets or sets that only contain an empty set. @@ -443,10 +906,15 @@ public class TypeUnifyTask extends RecursiveTask>> { .filter(x -> x.size() > 0).collect(Collectors.toCollection(HashSet::new)); } + //TODO: Wenn Theta' nicht im FC muss ein Fehler produziert werden PL 18-04-20 /** * Cartesian product Case 1: (a <. Theta') */ - protected Set> unifyCase1(PlaceholderType a, UnifyType thetaPrime, IFiniteClosure fc) { + protected Set> unifyCase1(UnifyPair pair, IFiniteClosure fc) { + PlaceholderType a = (PlaceholderType)pair.getLhsType(); + UnifyType thetaPrime = pair.getRhsType(); + byte variance = pair.getVariance(); + Set> result = new HashSet<>(); boolean allGen = thetaPrime.getTypeParams().size() > 0; @@ -458,11 +926,23 @@ public class TypeUnifyTask extends RecursiveTask>> { Set cs = fc.getAllTypesByName(thetaPrime.getName());//cs= [java.util.Vector, java.util.Vector>, ????java.util.Vector???] + + //PL 18-02-06 entfernt, kommt durch unify wieder rein //cs.add(thetaPrime); //PL 18-02-06 entfernt - for(UnifyType c : cs) { + //cs muessen fresh Typvars gesetzt werden PL 2018-03-18 + Set csPHRenamed = cs.stream().map(x -> { + BinaryOperator> combiner = (aa,b) -> { aa.putAll(b); return aa;}; + HashMap hm = x.getInvolvedPlaceholderTypes().stream() + .reduce(new HashMap(), + (aa, b)-> { aa.put(b,PlaceholderType.freshPlaceholder()); return aa; }, combiner); + return x.accept(new freshPlaceholder(), hm); + }).collect(Collectors.toCollection(HashSet::new)); + + + for(UnifyType c : csPHRenamed) { //PL 18-02-05 getChildren durch smaller ersetzt in getChildren werden die Varianlen nicht ersetzt. Set thetaQs = fc.smaller(c).stream().collect(Collectors.toCollection(HashSet::new)); //Set thetaQs = fc.getChildren(c).stream().collect(Collectors.toCollection(HashSet::new)); @@ -489,24 +969,36 @@ public class TypeUnifyTask extends RecursiveTask>> { } for(UnifyType tqp : thetaQPrimes) { - //System.out.println(tqp.toString()); - //i++; - //System.out.println(i); - //if (i == 62) - // System.out.println(tqp.toString()); Optional opt = stdUnify.unify(tqp, thetaPrime); - if (!opt.isPresent()) + if (!opt.isPresent()) { continue; - + } + Unifier unifier = opt.get(); unifier.swapPlaceholderSubstitutions(thetaPrime.getTypeParams()); Set substitutionSet = new HashSet<>(); - for (Entry sigma : unifier) - substitutionSet.add(new UnifyPair(sigma.getKey(), sigma.getValue(), PairOperator.EQUALSDOT)); - + for (Entry sigma : unifier) { + substitutionSet.add(new UnifyPair(sigma.getKey(), sigma.getValue(), PairOperator.EQUALSDOT, + //TODO: nochmals ueberlegen ob hier pair.getSubstitution() korrekt ist, oder ob leere Menge hin müsste + //alle folgenden New UnifyPair ebenfalls ueberpruefen PL 2018-04-19 + pair.getSubstitution(), pair)); + } //List freshTphs = new ArrayList<>(); PL 18-02-06 in die For-Schleife verschoben for (UnifyType tq : thetaQs) { Set smaller = fc.smaller(unifier.apply(tq)); + //eingefuegt PL 2018-03-29 Anfang ? ext. theta hinzufuegen + if (a.isWildcardable()) { + Set smaller_ext = smaller.stream().filter(x -> !(x instanceof ExtendsType) && !(x instanceof SuperType)) + .map(x -> { + //BinaryOperator> combiner = (aa,b) -> { aa.putAll(b); return aa;}; //Variablenumbenennung rausgenommen + //HashMap hm = x.getInvolvedPlaceholderTypes().stream() //Variablen muessen wahrscheinlich erhalten bleiben + // .reduce(new HashMap(), + // (aa, b)-> { aa.put(b,PlaceholderType.freshPlaceholder()); return aa; }, combiner); + return new ExtendsType (x);})//.accept(new freshPlaceholder(), hm));} + .collect(Collectors.toCollection(HashSet::new)); + smaller.addAll(smaller_ext); + } + //eingefuegt PL 2018-03-29 Ende ? ext. theta hinzufuegen for(UnifyType theta : smaller) { List freshTphs = new ArrayList<>(); Set resultPrime = new HashSet<>(); @@ -514,15 +1006,27 @@ public class TypeUnifyTask extends RecursiveTask>> { for(int i = 0; !allGen && i < theta.getTypeParams().size(); i++) { if(freshTphs.size()-1 < i) freshTphs.add(PlaceholderType.freshPlaceholder()); - resultPrime.add(new UnifyPair(freshTphs.get(i), theta.getTypeParams().get(i), PairOperator.SMALLERDOTWC)); + resultPrime.add(new UnifyPair(freshTphs.get(i), theta.getTypeParams().get(i), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair)); } - if(allGen) - resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT)); - else - resultPrime.add(new UnifyPair(a, theta.setTypeParams(new TypeParams(freshTphs.toArray(new UnifyType[0]))), PairOperator.EQUALSDOT)); + if(allGen) { + UnifyPair up = new UnifyPair(a, theta, PairOperator.EQUALSDOT, pair.getSubstitution(), pair); + Iterator upit = up.getRhsType().getTypeParams().iterator(); + while (upit.hasNext()) ((PlaceholderType)upit.next()).setVariance(a.getVariance()); + resultPrime.add(up); + } + else { + UnifyPair up = new UnifyPair(a, theta.setTypeParams(new TypeParams(freshTphs.toArray(new UnifyType[0]))), PairOperator.EQUALSDOT, pair.getSubstitution(), pair); + Iterator upit = up.getRhsType().getTypeParams().iterator(); + while (upit.hasNext()) ((PlaceholderType)upit.next()).setVariance(a.getVariance()); + resultPrime.add(up); + } resultPrime.addAll(substitutionSet); + //writeLog("Substitution: " + substitutionSet.toString()); + resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new)); result.add(resultPrime); + //writeLog("Result: " + resultPrime.toString()); + //writeLog("MAX: " + oup.max(resultPrime.iterator()).toString()); } } @@ -535,40 +1039,53 @@ public class TypeUnifyTask extends RecursiveTask>> { /** * Cartesian Product Case 2: (a <.? ? ext Theta') */ - private Set> unifyCase2(PlaceholderType a, ExtendsType extThetaPrime, IFiniteClosure fc) { + private Set> unifyCase2(UnifyPair pair, IFiniteClosure fc) { + PlaceholderType a = (PlaceholderType) pair.getLhsType(); + ExtendsType extThetaPrime = (ExtendsType) pair.getRhsType(); + byte variance = pair.getVariance(); Set> result = new HashSet<>(); UnifyType aPrime = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)aPrime).setVariance(((PlaceholderType)a).getVariance()); UnifyType extAPrime = new ExtendsType(aPrime); UnifyType thetaPrime = extThetaPrime.getExtendedType(); Set resultPrime = new HashSet<>(); - resultPrime.add(new UnifyPair(a, thetaPrime, PairOperator.SMALLERDOT)); + resultPrime.add(new UnifyPair(a, thetaPrime, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); result.add(resultPrime); resultPrime = new HashSet<>(); - resultPrime.add(new UnifyPair(a, extAPrime, PairOperator.EQUALSDOT)); - resultPrime.add(new UnifyPair(aPrime, thetaPrime, PairOperator.SMALLERDOT)); + resultPrime.add(new UnifyPair(a, extAPrime, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(aPrime, thetaPrime, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); + resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new)); result.add(resultPrime); + //writeLog("Result: " + resultPrime.toString()); return result; } /** * Cartesian Product Case 3: (a <.? ? sup Theta') */ - private Set> unifyCase3(PlaceholderType a, SuperType subThetaPrime, IFiniteClosure fc) { + private Set> unifyCase3(UnifyPair pair, IFiniteClosure fc) { + PlaceholderType a = (PlaceholderType) pair.getLhsType(); + SuperType subThetaPrime = (SuperType) pair.getRhsType(); + byte variance = pair.getVariance(); Set> result = new HashSet<>(); UnifyType aPrime = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)aPrime).setVariance(((PlaceholderType)a).getVariance()); UnifyType supAPrime = new SuperType(aPrime); UnifyType thetaPrime = subThetaPrime.getSuperedType(); Set resultPrime = new HashSet<>(); - resultPrime.add(new UnifyPair(thetaPrime, a, PairOperator.SMALLERDOT)); + resultPrime.add(new UnifyPair(thetaPrime, a, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); result.add(resultPrime); + //writeLog(resultPrime.toString()); resultPrime = new HashSet<>(); - resultPrime.add(new UnifyPair(a, supAPrime, PairOperator.EQUALSDOT)); - resultPrime.add(new UnifyPair(thetaPrime, aPrime, PairOperator.SMALLERDOT)); + resultPrime.add(new UnifyPair(a, supAPrime, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(thetaPrime, aPrime, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); + resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new)); result.add(resultPrime); + //writeLog(resultPrime.toString()); return result; } @@ -576,7 +1093,10 @@ public class TypeUnifyTask extends RecursiveTask>> { /** * Cartesian Product Case 5: (Theta <. a) */ - private Set> unifyCase5(UnifyType theta, PlaceholderType a, IFiniteClosure fc) { + private Set> unifyCase5(UnifyPair pair, IFiniteClosure fc) { + UnifyType theta = pair.getLhsType(); + PlaceholderType a = (PlaceholderType) pair.getRhsType(); + byte variance = pair.getVariance(); Set> result = new HashSet<>(); boolean allGen = theta.getTypeParams().size() > 0; @@ -592,14 +1112,17 @@ public class TypeUnifyTask extends RecursiveTask>> { UnifyType[] freshTphs = new UnifyType[thetaS.getTypeParams().size()]; for(int i = 0; !allGen && i < freshTphs.length; i++) { freshTphs[i] = PlaceholderType.freshPlaceholder(); - resultPrime.add(new UnifyPair(thetaS.getTypeParams().get(i), freshTphs[i], PairOperator.SMALLERDOTWC)); + ((PlaceholderType)freshTphs[i]).setVariance(((PlaceholderType)a).getVariance()); + resultPrime.add(new UnifyPair(thetaS.getTypeParams().get(i), freshTphs[i], PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair)); } if(allGen) - resultPrime.add(new UnifyPair(a, thetaS, PairOperator.EQUALSDOT)); + resultPrime.add(new UnifyPair(a, thetaS, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); else - resultPrime.add(new UnifyPair(a, thetaS.setTypeParams(new TypeParams(freshTphs)), PairOperator.EQUALSDOT)); + resultPrime.add(new UnifyPair(a, thetaS.setTypeParams(new TypeParams(freshTphs)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new)); result.add(resultPrime); + //writeLog(resultPrime.toString()); } return result; @@ -608,23 +1131,32 @@ public class TypeUnifyTask extends RecursiveTask>> { /** * Cartesian Product Case 8: (Theta <.? a) */ - private Set> unifyCase8(UnifyType theta, PlaceholderType a, IFiniteClosure fc) { + private Set> unifyCase8(UnifyPair pair, IFiniteClosure fc) { + UnifyType theta = pair.getLhsType(); + PlaceholderType a = (PlaceholderType) pair.getRhsType(); + byte variance = pair.getVariance(); Set> result = new HashSet<>(); //for(UnifyType thetaS : fc.grArg(theta)) { Set resultPrime = new HashSet<>(); - resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT)); + resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); result.add(resultPrime); + //writeLog(resultPrime.toString()); UnifyType freshTph = PlaceholderType.freshPlaceholder(); + + ((PlaceholderType)freshTph).setVariance(a.getVariance()); resultPrime = new HashSet<>(); - resultPrime.add(new UnifyPair(a, new ExtendsType(freshTph), PairOperator.EQUALSDOT)); - resultPrime.add(new UnifyPair(theta, freshTph, PairOperator.SMALLERDOT)); + resultPrime.add(new UnifyPair(a, new ExtendsType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(theta, freshTph, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); result.add(resultPrime); + //writeLog(resultPrime.toString()); resultPrime = new HashSet<>(); - resultPrime.add(new UnifyPair(a, new SuperType(freshTph), PairOperator.EQUALSDOT)); - resultPrime.add(new UnifyPair(freshTph, theta, PairOperator.SMALLERDOT)); + resultPrime.add(new UnifyPair(a, new SuperType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(freshTph, theta, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); + resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new)); result.add(resultPrime); + //writeLog(resultPrime.toString()); //} return result; @@ -662,4 +1194,13 @@ public class TypeUnifyTask extends RecursiveTask>> { permuteParams(candidates, idx+1, result, current); } } + + void writeLog(String str) { + try { + logFile.write(str+"\n"); + logFile.flush(); + + } + catch (IOException e) { } + } } diff --git a/src/de/dhbwstuttgart/typeinference/unify/distributeVariance.java b/src/de/dhbwstuttgart/typeinference/unify/distributeVariance.java new file mode 100644 index 00000000..1779c941 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/distributeVariance.java @@ -0,0 +1,54 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.TypeParams; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; + +public class distributeVariance extends visitUnifyTypeVisitor { + + public static int inverseVariance(int variance) { + Integer ret = 0; + if (variance == 1) { + ret = -1; + } + if (variance == -1) { + ret = 1; + } + return ret; + } + + + @Override + public PlaceholderType visit(PlaceholderType phty, Integer ht) { + if (ht != 0) { + if (phty.getVariance() == 0) { + phty.setVariance(ht); + } + //PL 2018-05-17 urspruengliche Variance nicht veraendern + //else if (phty.getVariance() != ht) { + // phty.setVariance(0); + //} + } + return phty; + } + + public FunNType visit(FunNType funnty, Integer ht) { + List param = new ArrayList<>(funnty.getTypeParams().get().length); + param.addAll(Arrays.asList(funnty.getTypeParams().get())); + UnifyType resultType = param.remove(param.size()-1); + Integer htInverse = inverseVariance(ht); + param = param.stream() + .map(x -> x.accept(this, htInverse)) + .collect(Collectors.toCollection(ArrayList::new)); + param.add(resultType.accept(this, ht)); + return FunNType.getFunNType(new TypeParams(param)); + } + + +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/freshPlaceholder.java b/src/de/dhbwstuttgart/typeinference/unify/freshPlaceholder.java new file mode 100644 index 00000000..69870bd5 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/freshPlaceholder.java @@ -0,0 +1,15 @@ +package de.dhbwstuttgart.typeinference.unify; + + +import java.util.HashMap; + +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; + + +public class freshPlaceholder extends visitUnifyTypeVisitor> { + + @Override + public PlaceholderType visit(PlaceholderType phty, HashMap ht) { + return ht.get(phty); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java index dcb6c4d1..e97a40e8 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java +++ b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java @@ -5,6 +5,7 @@ import java.util.Set; 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; @@ -60,5 +61,7 @@ public interface IFiniteClosure { public Optional getLeftHandedType(String typeName); public Set getAncestors(UnifyType t); public Set getChildren(UnifyType t); - public Set getAllTypesByName(String typeName); + public Set getAllTypesByName(String typeName); + + public int compare(UnifyType rhsType, UnifyType rhsType2, PairOperator pairop); } diff --git a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IMatch.java b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IMatch.java index 5e201dd7..ab88f33b 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IMatch.java +++ b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IMatch.java @@ -13,23 +13,17 @@ import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; /** * Match * @author Martin Pluemicke + * abgeleitet aus IUnify.java */ public interface IMatch { /** - * Finds the most general unifier sigma of the set {t1,...,tn} so that - * sigma(t1) = sigma(t2) = ... = sigma(tn). - * @param terms The set of terms to be unified - * @return An optional of the most general unifier if it exists or an empty optional if there is no unifier. + * Finds the most general matcher sigma of the set {t1 =. t1',...,tn =. tn'} so that + * sigma(t1) = t1' , ... sigma(tn) = tn'. + * @param terms The set of terms to be matched + * @return An optional of the most general matcher if it exists or an empty optional if there is no matcher. */ public Optional match(ArrayList termsList); - - /** - * Finds the most general unifier sigma of the set {t1,...,tn} so that - * sigma(t1) = sigma(t2) = ... = sigma(tn). - * @param terms The set of terms to be unified - * @return An optional of the most general unifier if it exists or an empty optional if there is no unifier. - */ } diff --git a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java index 62c9649f..a2b647c6 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java +++ b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java @@ -27,9 +27,13 @@ public interface IRuleSet { public Optional reduceWildcardLowRight(UnifyPair pair); public Optional reduceWildcardUp(UnifyPair pair); public Optional reduceWildcardUpRight(UnifyPair pair); + + /* + * vgl. JAVA_BSP/Wildcard6.java public Optional reduceWildcardLowUp(UnifyPair pair); public Optional reduceWildcardUpLow(UnifyPair pair); public Optional reduceWildcardLeft(UnifyPair pair); + */ /* * Additional Rules which replace cases of the cartesian product diff --git a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IUnify.java b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IUnify.java index 524608f5..57b41736 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IUnify.java +++ b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IUnify.java @@ -15,16 +15,16 @@ import de.dhbwstuttgart.typeinference.unify.model.Unifier; public interface IUnify { /** - * Finds the most general unifier sigma of the set {t1,...,tn} so that - * sigma(t1) = sigma(t2) = ... = sigma(tn). + * Finds the most general unifier sigma of the set {t1 =. t1',...,tn =. tn'} so that + * sigma(t1) = sigma(t1') , ... sigma(tn) = sigma(tn'). * @param terms The set of terms to be unified * @return An optional of the most general unifier if it exists or an empty optional if there is no unifier. */ public Optional unify(Set terms); /** - * Finds the most general unifier sigma of the set {t1,...,tn} so that - * sigma(t1) = sigma(t2) = ... = sigma(tn). + * Finds the most general unifier sigma of the set {t1 =. t1',...,tn =. tn'} so that + * sigma(t1) = sigma(t1') , ... sigma(tn) = sigma(tn'). * @param terms The set of terms to be unified * @return An optional of the most general unifier if it exists or an empty optional if there is no unifier. */ diff --git a/src/de/dhbwstuttgart/typeinference/unify/interfaces/UnifyTypeVisitor.java b/src/de/dhbwstuttgart/typeinference/unify/interfaces/UnifyTypeVisitor.java new file mode 100644 index 00000000..8d06b3e1 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/interfaces/UnifyTypeVisitor.java @@ -0,0 +1,23 @@ +package de.dhbwstuttgart.typeinference.unify.interfaces; + +import java.util.HashMap; + +import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; +import de.dhbwstuttgart.typeinference.unify.model.SuperType; + +public interface UnifyTypeVisitor { + + public ReferenceType visit(ReferenceType refty, T ht); + + public PlaceholderType visit(PlaceholderType phty, T ht); + + public FunNType visit(FunNType funnty, T ht); + + public SuperType visit(SuperType suty, T ht); + + public ExtendsType visit(ExtendsType extty, T ht); + +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/ExtendsType.java b/src/de/dhbwstuttgart/typeinference/unify/model/ExtendsType.java index 33f32e07..6c44d2ec 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/ExtendsType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/ExtendsType.java @@ -2,21 +2,30 @@ package de.dhbwstuttgart.typeinference.unify.model; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.Set; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; /** * An extends wildcard type "? extends T". */ public final class ExtendsType extends WildcardType { + public UnifyType accept(UnifyTypeVisitor visitor, T ht) { + return visitor.visit(this, ht); + } + /** * Creates a new extends wildcard type. * @param extendedType The extended type e.g. Integer in "? extends Integer" */ public ExtendsType(UnifyType extendedType) { - super("? extends " + extendedType.getName(), extendedType); + super("? extends " + extendedType.getName(), extendedType); + if (extendedType instanceof ExtendsType) { + System.out.print(""); + } } /** diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java b/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java index dcffbee6..b45309b8 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java @@ -8,11 +8,14 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; -//PL 18-02-05 Unifier durch Matcher ersetzt -//mus greater noch erstezt werden +import com.google.common.collect.Ordering; + +//PL 18-02-05/18-04-05 Unifier durch Matcher ersetzt +//muss greater noch ersetzt werden ja erledigt 18--04-05 import de.dhbwstuttgart.typeinference.unify.MartelliMontanariUnify; import de.dhbwstuttgart.typeinference.unify.Match; +import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; @@ -20,7 +23,7 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; * The finite closure for the type unification * @author Florian Steurer */ -public class FiniteClosure implements IFiniteClosure { +public class FiniteClosure extends Ordering implements IFiniteClosure { /** * A map that maps every type to the node in the inheritance graph that contains that type. @@ -193,7 +196,9 @@ public class FiniteClosure implements IFiniteClosure { protected Set computeGreater(Set types) { HashSet result = new HashSet<>(); - IUnify unify = new MartelliMontanariUnify(); + //PL 18-04-05 Unifier durch Matcher ersetzt + //IUnify unify = new MartelliMontanariUnify(); + Match match = new Match(); for(UnifyType t : types) { @@ -215,7 +220,11 @@ public class FiniteClosure implements IFiniteClosure { Set> candidates = strInheritanceGraph.get(t.getName()); for(Node candidate : candidates) { UnifyType theta1 = candidate.getContent(); - Optional optSigma = unify.unify(theta1, t); + //PL 18-04-05 Unifier durch Matcher ersetzt ANFANG + ArrayList termList= new ArrayList(); + termList.add(new UnifyPair(theta1,t, PairOperator.EQUALSDOT)); + Optional optSigma = match.match(termList); + //PL 18-04-05 Unifier durch Matcher ersetzt ENDE if(!optSigma.isPresent()) continue; @@ -369,7 +378,7 @@ public class FiniteClosure implements IFiniteClosure { return Optional.empty(); for(UnifyPair pair : pairs) - if(pair.getLhsType().getName().equals(typeName)) + if(pair.getLhsType().getName().equals(typeName) && pair.getLhsType().typeParams.arePlaceholders()) return Optional.of(pair.getLhsType()); return Optional.empty(); @@ -430,4 +439,33 @@ public class FiniteClosure implements IFiniteClosure { public String toString(){ return this.inheritanceGraph.toString(); } + + public int compare (UnifyType left, UnifyType right) { + return compare(left, right, PairOperator.SMALLERDOT); + } + + public int compare (UnifyType left, UnifyType right, PairOperator pairop) { + if ((left instanceof ExtendsType && right instanceof ReferenceType) + || (right instanceof ExtendsType && left instanceof ReferenceType)) + System.out.println(""); + UnifyPair up = new UnifyPair(left, right, pairop); + TypeUnifyTask unifyTask = new TypeUnifyTask(); + HashSet hs = new HashSet<>(); + hs.add(up); + Set smallerRes = unifyTask.applyTypeUnificationRules(hs, this); + //Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok. + long smallerLen = smallerRes.stream().filter(x -> !(x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType)).count(); + if (smallerLen == 0) return -1; + else { + up = new UnifyPair(right, left, pairop); + //TypeUnifyTask unifyTask = new TypeUnifyTask(); + hs = new HashSet<>(); + hs.add(up); + Set greaterRes = unifyTask.applyTypeUnificationRules(hs, this); + //Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok. + long greaterLen = greaterRes.stream().filter(x -> !(x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType)).count(); + if (greaterLen == 0) return 1; + else return 0; + } + } } diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/FunNType.java b/src/de/dhbwstuttgart/typeinference/unify/model/FunNType.java index cf2c86ae..95275a12 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/FunNType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/FunNType.java @@ -1,8 +1,12 @@ package de.dhbwstuttgart.typeinference.unify.model; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import java.util.Set; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; /** * A real function type in java. @@ -10,6 +14,10 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; */ public class FunNType extends UnifyType { + public UnifyType accept(UnifyTypeVisitor visitor, T ht) { + return visitor.visit(this, ht); + } + /** * Creates a FunN-Type with the specified TypeParameters. */ @@ -67,11 +75,18 @@ public class FunNType extends UnifyType { return new FunNType(newParams); } + @Override + public Boolean wrongWildcard() { + return (new ArrayList(Arrays.asList(getTypeParams() + .get())).stream().filter(x -> (x instanceof WildcardType)).findFirst().isPresent()); + } + @Override public int hashCode() { return 181 + typeParams.hashCode(); } + @Override public boolean equals(Object obj) { if(!(obj instanceof FunNType)) diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/OrderingUnifyPair.java b/src/de/dhbwstuttgart/typeinference/unify/model/OrderingUnifyPair.java new file mode 100644 index 00000000..8cebdd8a --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/OrderingUnifyPair.java @@ -0,0 +1,228 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Optional; +import java.util.Set; +import java.util.function.BinaryOperator; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.google.common.collect.Ordering; + +import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; + + + +public class OrderingUnifyPair extends Ordering> { + + protected IFiniteClosure fc; + + public OrderingUnifyPair(IFiniteClosure fc) { + this.fc = fc; + } + + /* + * vergleicht Paare (a =. Theta) und (a =. Theta') + * in dem compare(Theta, Theta') aufgerufen wird. + */ + public int compareEq (UnifyPair left, UnifyPair right) { + if (left.getRhsType() instanceof WildcardType || right.getRhsType() instanceof WildcardType) { + return fc.compare(left.getRhsType(), right.getRhsType(), PairOperator.SMALLERDOTWC); + } + else { + return fc.compare(left.getRhsType(), right.getRhsType(), PairOperator.SMALLERDOT); + } + } + /* + public int compareEq (UnifyPair left, UnifyPair right) { + if (left == null || right == null) + System.out.println("Fehler"); + if (left.getLhsType() instanceof PlaceholderType) { + return fc.compare(left.getRhsType(), right.getRhsType(), left.getPairOp()); + } + else { + return fc.compare(left.getLhsType(), right.getLhsType(), left.getPairOp()); + } + } + */ + + public Pair> compare (UnifyType left, UnifyType right) { + UnifyPair up; + if (left instanceof WildcardType || right instanceof WildcardType) { + up = new UnifyPair(left, right, PairOperator.SMALLERDOTWC); + } + else { + up = new UnifyPair(left, right, PairOperator.SMALLERDOT); + } + TypeUnifyTask unifyTask = new TypeUnifyTask(); + HashSet hs = new HashSet<>(); + hs.add(up); + Set smallerRes = unifyTask.applyTypeUnificationRules(hs, fc); + long smallerLen = smallerRes.stream().filter(x -> !(x.getLhsType() instanceof PlaceholderType && x.getRhsType() instanceof PlaceholderType)).count(); + if (smallerLen == 0) return new Pair<>(-1, smallerRes); + else { + if (left instanceof WildcardType || right instanceof WildcardType) { + up = new UnifyPair(right, left, PairOperator.SMALLERDOTWC); + } + else { + up = new UnifyPair(right, left, PairOperator.SMALLERDOT); + } + //TypeUnifyTask unifyTask = new TypeUnifyTask(); + hs = new HashSet<>(); + hs.add(up); + Set greaterRes = unifyTask.applyTypeUnificationRules(hs, fc); + long greaterLen = greaterRes.stream().filter(x -> !(x.getLhsType() instanceof PlaceholderType && x.getRhsType() instanceof PlaceholderType)).count(); + if (greaterLen == 0) return new Pair<>(1, greaterRes); + else return new Pair<>(0, new HashSet<>()); + } + } + + /* TODO muss noch verifiziert werden PL 2018-03-21 + * (non-Javadoc) + * fuehrt zu Fehlern bei Arrays.sort (contract nicht erfuellt) + * @see com.google.common.collect.Ordering#compare(java.lang.Object, java.lang.Object) + */ + public int compare (Set left, Set right) { + Set lefteq = left.stream() + .filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT)) + .collect(Collectors.toCollection(HashSet::new)); + Set righteq = right.stream() + .filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT)) + .collect(Collectors.toCollection(HashSet::new)); + Set leftle = left.stream() + .filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType) + && x.getPairOp() == PairOperator.SMALLERDOT)) + .collect(Collectors.toCollection(HashSet::new)); + Set rightle = right.stream() + .filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType) + && x.getPairOp() == PairOperator.SMALLERDOT)) + .collect(Collectors.toCollection(HashSet::new)); + Set leftlewc = left.stream() + .filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType) + && x.getPairOp() == PairOperator.SMALLERDOTWC)) + .collect(Collectors.toCollection(HashSet::new)); + Set rightlewc = right.stream() + .filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType) + && x.getPairOp() == PairOperator.SMALLERDOTWC)) + .collect(Collectors.toCollection(HashSet::new)); + //System.out.println(left.toString()); + //Fall 2 und 3 + //if (lefteq.iterator().next().getLhsType().getName().equals("AJO")) { + // System.out.print(""); + //} + if (lefteq.size() == 1 && leftle.size() == 1 && righteq.size() == 0 && rightle.size() == 1) { + return 1; + } + //Fall 2 und 3 + if (lefteq.size() == 0 && leftle.size() == 1 && righteq.size() == 1 && rightle.size() == 1) { + return -1; + } + //Fall 5 + if (lefteq.size() == 1 && leftle.size() == 0 && righteq.size() == 1 && rightle.size() == 1) { + return -1; + } + //Fall 5 + if (lefteq.size() == 1 && leftle.size() == 1 && righteq.size() == 1 && rightle.size() == 0) { + return 1; + } + //Fall 5 + if (lefteq.size() == 1 && leftle.size() == 1 && righteq.size() == 1 && rightle.size() == 1) { + return 0; + } + // Nur Paare a =. Theta + if (leftle.size() == 0 && rightle.size() == 0 && leftlewc.size() == 0 && rightlewc.size() ==0) { + Stream lseq = lefteq.stream(); //left.filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT)); + Stream rseq = righteq.stream(); //right.filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT)); + BinaryOperator> combiner = (x,y) -> { x.putAll(y); return x;}; + HashMap hm = rseq.reduce(new HashMap(), (x, y)-> { x.put(y.getLhsType(),y); return x; }, combiner); + lseq = lseq.filter(x -> !(hm.get(x.getLhsType()) == null));//NOCHMALS UEBERPRUEFEN!!!! + lseq = lseq.filter(x -> !x.equals(hm.get(x.getLhsType()))); //Elemente die gleich sind muessen nicht verglichen werden + Optional si = lseq.map(x -> compareEq(x, hm.get(x.getLhsType()))).reduce((x,y)-> { if (x == y) return x; else return 0; } ); + if (!si.isPresent()) return 0; + else return si.get(); + } + //Fall 1 und 4 + if (lefteq.size() >= 1 && righteq.size() >= 1 && (leftlewc.size() > 0 || rightlewc.size() > 0)) { + if (lefteq.iterator().next().getLhsType().getName().equals("D")) + System.out.print(""); + //Set varsleft = lefteq.stream().map(x -> (PlaceholderType)x.getLhsType()).collect(Collectors.toCollection(HashSet::new)); + //Set varsright = righteq.stream().map(x -> (PlaceholderType)x.getLhsType()).collect(Collectors.toCollection(HashSet::new)); + //filtern des Paares a = Theta, das durch a <. Thata' generiert wurde (nur im Fall 1 relevant) + lefteq.removeIf(x -> !(x.getLhsType().getName().equals(x.getBasePair().getLhsType().getName()) + ||x.getLhsType().getName().equals(x.getBasePair().getRhsType().getName())));//removeIf(x -> !varsright.contains(x.getLhsType())); + righteq.removeIf(x -> !(x.getLhsType().getName().equals(x.getBasePair().getLhsType().getName()) + ||x.getLhsType().getName().equals(x.getBasePair().getRhsType().getName())));//.removeIf(x -> !varsleft.contains(x.getLhsType())); + UnifyPair lseq = lefteq.iterator().next(); + UnifyPair rseq = righteq.iterator().next(); + if (lseq.getRhsType().getName().equals("Object")) { + if (rseq.getRhsType().getName().equals("Object")) return 0; + else return 1; + } + else { + if (rseq.getRhsType().getName().equals("Object")) return -1; + } + if (leftlewc.size() == rightlewc.size()) { + //TODO: Hier wird bei Wildcards nicht das richtige compare aufgerufen PL 18-04-20 + Pair> int_Unifier = compare(lseq.getRhsType(), rseq.getRhsType()); + Unifier uni = new Unifier(); + int_Unifier.getValue().get().forEach(x -> uni.add((PlaceholderType) x.getLhsType(), x.getRhsType())); + if (!lseq.getRhsType().getName().equals(rseq.getRhsType().getName()) + || leftlewc.size() == 0 || rightlewc.size() == 0) return int_Unifier.getKey(); + else { + Set lsleuni = leftlewc.stream().map(x -> uni.apply(x)).collect(Collectors.toCollection(HashSet::new)); + Set rsleuni = rightlewc.stream().map(x -> uni.apply(x)).collect(Collectors.toCollection(HashSet::new)); + BinaryOperator> combiner = (x,y) -> { x.putAll(y); return x;}; + + HashMap hm; + Optional si; + //1. Fall + if (leftlewc.iterator().next().getLhsType() instanceof PlaceholderType) { + hm = rsleuni.stream().reduce(new HashMap(), (x, y)-> { x.put(y.getLhsType(),y); return x; }, combiner); + Stream lslewcstr = lsleuni.stream().filter(x -> !(hm.get(x.getLhsType()) == null)); + si = lslewcstr.map(x -> fc.compare(x.getRhsType(), hm.get(x.getLhsType()).getRhsType(), PairOperator.SMALLERDOTWC)).reduce((x,y)-> { if (x == y) return x; else return 0; } ); + } + //4. Fall + else { + hm = rsleuni.stream().reduce(new HashMap(), (x, y)-> { x.put(y.getRhsType(),y); return x; }, combiner); + Stream lslewcstr = lsleuni.stream().filter(x -> !(hm.get(x.getRhsType()) == null)); + si = lslewcstr.map(x -> fc.compare(x.getLhsType(), hm.get(x.getRhsType()).getLhsType(), PairOperator.SMALLERDOTWC)).reduce((x,y)-> { if (x == y) return x; else return 0; } ); + } + if (!si.isPresent()) return 0; + else return si.get(); + } + } else { + if (leftlewc.size() > 0) { + Set subst; + if (leftlewc.iterator().next().getLhsType() instanceof PlaceholderType) { + subst = leftlewc.stream().map(x -> new UnifyPair(x.getLhsType(), x.getRhsType(), PairOperator.EQUALSDOT)).collect(Collectors.toCollection(HashSet::new)); + } + else { + subst = leftlewc.stream().map(x -> new UnifyPair(x.getRhsType(), x.getLhsType(), PairOperator.EQUALSDOT)).collect(Collectors.toCollection(HashSet::new)); + } + Unifier uni = new Unifier(); + subst.stream().forEach(x -> uni.add((PlaceholderType) x.getLhsType(), x.getRhsType())); + lseq = uni.apply(lseq); + } + else { + Set subst; + if (rightlewc.iterator().next().getLhsType() instanceof PlaceholderType) { + subst = rightlewc.stream().map(x -> new UnifyPair(x.getLhsType(), x.getRhsType(), PairOperator.EQUALSDOT)).collect(Collectors.toCollection(HashSet::new)); + } + else { + subst = rightlewc.stream().map(x -> new UnifyPair(x.getRhsType(), x.getLhsType(), PairOperator.EQUALSDOT)).collect(Collectors.toCollection(HashSet::new)); + } + Unifier uni = new Unifier(); + subst.stream().forEach(x -> uni.add((PlaceholderType) x.getLhsType(), x.getRhsType())); + rseq = uni.apply(rseq); + } + return compareEq(lseq, rseq); + } + } + return 0; + } +} + diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/Pair.java b/src/de/dhbwstuttgart/typeinference/unify/model/Pair.java new file mode 100644 index 00000000..08c4aa1c --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/Pair.java @@ -0,0 +1,21 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.Optional; + +public class Pair { + private final T key; + private final T1 value; + + public Pair(T a, T1 b) { + this.value = b; + this.key = a; + } + + public Optional getValue() { + return Optional.of(value); + } + + public T getKey() { + return key; + } +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/PlaceholderType.java b/src/de/dhbwstuttgart/typeinference/unify/model/PlaceholderType.java index e9268d0d..bbd3b3e1 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/PlaceholderType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/PlaceholderType.java @@ -2,11 +2,14 @@ package de.dhbwstuttgart.typeinference.unify.model; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.Random; import java.util.Set; +import de.dhbwstuttgart.typeinference.unify.distributeVariance; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; /** * An unbounded placeholder type. @@ -35,6 +38,21 @@ public final class PlaceholderType extends UnifyType{ */ private final boolean IsGenerated; + + /** + * isWildcardable gibt an, ob ein Wildcardtyp dem PlaceholderType zugeordnet werden darf + */ + private boolean wildcardable = true; + + /** + * variance shows the variance of the pair + * -1: contravariant + * 1 covariant + * 0 invariant + * PL 2018-03-21 + */ + private int variance = 0; + /** * Creates a new placeholder type with the specified name. */ @@ -54,6 +72,10 @@ public final class PlaceholderType extends UnifyType{ IsGenerated = isGenerated; } + public UnifyType accept(UnifyTypeVisitor visitor, T ht) { + return visitor.visit(this, ht); + } + /** * Creates a fresh placeholder type with a name that does so far not exist. * A user could later instantiate a type using the same name that is equivalent to this type. @@ -67,6 +89,7 @@ public final class PlaceholderType extends UnifyType{ return new PlaceholderType(name, true); } + /** * True if this placeholder is auto-generated, false if it is user-generated. */ @@ -74,6 +97,21 @@ public final class PlaceholderType extends UnifyType{ return IsGenerated; } + public void setVariance(int v) { + variance = v; + } + + public int getVariance() { + return variance; + } + + public Boolean isWildcardable() { + return wildcardable; + } + public void disableWildcardtable() { + wildcardable = false; + } + @Override Set smArg(IFiniteClosure fc) { return fc.smArg(this); @@ -96,8 +134,13 @@ public final class PlaceholderType extends UnifyType{ @Override UnifyType apply(Unifier unif) { - if(unif.hasSubstitute(this)) - return unif.getSubstitute(this); + if(unif.hasSubstitute(this)) { + UnifyType ret = unif.getSubstitute(this); + //PL 2018-05-17 Auskommentierung muesste korrekt sein, + //bereits in JavaTXComplier Variancen gesetzt werden. + //ret.accept(new distributeVariance(), this.getVariance()); + return ret; + } return this; } diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java b/src/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java index 02ab38a0..81f6c3b3 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java @@ -1,8 +1,10 @@ package de.dhbwstuttgart.typeinference.unify.model; +import java.util.HashMap; import java.util.Set; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; /** * A reference type e.q. Integer or List. @@ -16,6 +18,11 @@ public final class ReferenceType extends UnifyType { */ private final int hashCode; + + public UnifyType accept(UnifyTypeVisitor visitor, T ht) { + return visitor.visit(this, ht); + } + public ReferenceType(String name, UnifyType... params) { super(name, new TypeParams(params)); hashCode = 31 + 17 * typeName.hashCode() + 17 * typeParams.hashCode(); diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/SuperType.java b/src/de/dhbwstuttgart/typeinference/unify/model/SuperType.java index 4f78602f..53762f86 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/SuperType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/SuperType.java @@ -1,8 +1,10 @@ package de.dhbwstuttgart.typeinference.unify.model; +import java.util.HashMap; import java.util.Set; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; /** * A super wildcard type e.g. ? super Integer. @@ -10,6 +12,10 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; */ public final class SuperType extends WildcardType { + public UnifyType accept(UnifyTypeVisitor visitor, T ht) { + return visitor.visit(this, ht); + } + /** * Creates a new instance "? extends superedType" * @param superedType The type that is supered e.g. Integer in "? super Integer" diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java b/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java index 3d5fc278..973a2785 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java @@ -115,6 +115,14 @@ public final class TypeParams implements Iterable{ return typeParams[i]; } + /** + * Returns the parameters of this object. + * PL 2018-03-17 + */ + public UnifyType[] get() { + return typeParams; + } + /** * Sets the the type t as the i-th parameter and returns a new object * that equals this object, except for the i-th type. diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java b/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java index 061ba588..8f594844 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java @@ -1,8 +1,10 @@ package de.dhbwstuttgart.typeinference.unify.model; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.Map.Entry; +import java.util.Set; import java.util.function.Function; /** @@ -63,7 +65,44 @@ public class Unifier implements Function, Iterable suniUnifyPair = new HashSet<>(); + suniUnifyPair.addAll(thisAsPair.getAllSubstitutions()); + suniUnifyPair.add(thisAsPair); + if (p.getLhsType() instanceof PlaceholderType //&& newLhs instanceof PlaceholderType entfernt PL 2018-04-13 + && p.getPairOp() == PairOperator.EQUALSDOT) { + suniUnifyPair.add(p); //p koennte auch subsitution sein + } + return new UnifyPair(newLhs, newRhs, p.getPairOp(), suniUnifyPair, p); + } + return new UnifyPair(newLhs, newRhs, p.getPairOp(), p.getSubstitution(), p.getBasePair()); } /** diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java b/src/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java index 0909690a..b631e5ec 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java @@ -2,7 +2,10 @@ package de.dhbwstuttgart.typeinference.unify.model; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; + /** * A pair which contains two types and an operator, e.q. (Integer <. a). @@ -25,6 +28,29 @@ public class UnifyPair { */ private PairOperator pairOp; + /** wieder loesecn wird nicht mehr benoetigt PL 2018-03-31 + * variance shows the variance of the pair + * -1: contravariant + * 1 covariant + * 0 invariant + * PL 2018-03-21 + */ + private byte variance = 0; + + private boolean undefinedPair = false; + + /** + * Unifier/substitute that generated this pair + * PL 2018-03-15 + */ + private Set substitution; + + /** + * Base on which the the unifier is applied + * PL 2018-03-15 + */ + private UnifyPair basePair; + private final int hashCode; /** @@ -37,6 +63,20 @@ public class UnifyPair { this.lhs = lhs; this.rhs = rhs; pairOp = op; + substitution = new HashSet<>(); + + // Caching hashcode + hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode(); + } + + public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, Set uni, UnifyPair base) { + this.lhs = lhs; + this.rhs = rhs; + pairOp = op; + substitution = uni; + basePair = base; + this.variance = variance; + // Caching hashcode hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode(); @@ -63,6 +103,41 @@ public class UnifyPair { return pairOp; } + public byte getVariance() { + return variance; + } + + public void setVariance(byte v) { + variance = v; + } + + public void setUndefinedPair() { + undefinedPair = true; + } + public Set getSubstitution() { + return substitution; + } + + public UnifyPair getBasePair() { + return basePair; + } + public boolean isUndefinedPair() { + return undefinedPair; + } + + public Set getAllSubstitutions () { + Set ret = new HashSet<>(); + ret.addAll(getSubstitution()); + if (basePair != null) { + ret.addAll(basePair.getAllSubstitutions()); + } + return ret; + } + + public Boolean wrongWildcard() { + return lhs.wrongWildcard() || rhs.wrongWildcard(); + } + @Override public boolean equals(Object obj) { if(!(obj instanceof UnifyPair)) @@ -73,6 +148,13 @@ public class UnifyPair { UnifyPair other = (UnifyPair) obj; + if (isUndefinedPair()) { + if (!other.getBasePair().equals(basePair) || + !other.getAllSubstitutions().equals(getAllSubstitutions())) { + return false; + } + } + return other.getPairOp() == pairOp && other.getLhsType().equals(lhs) && other.getRhsType().equals(rhs); @@ -85,7 +167,14 @@ public class UnifyPair { @Override public String toString() { - return "(" + lhs + " " + pairOp + " " + rhs + ")"; + String ret = ""; + if (lhs instanceof PlaceholderType) { + ret = new Integer(((PlaceholderType)lhs).getVariance()).toString(); + } + if (rhs instanceof PlaceholderType) { + ret = ret + ", " + new Integer(((PlaceholderType)rhs).getVariance()).toString(); + } + return "(" + lhs + " " + pairOp + " " + rhs + ", " + ret + ")"; } /* diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java b/src/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java index 1080f03b..715d9880 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java @@ -2,10 +2,13 @@ package de.dhbwstuttgart.typeinference.unify.model; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Set; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; /** * Represents a java type. @@ -33,6 +36,9 @@ public abstract class UnifyType { typeParams = p; } + + abstract public UnifyType accept(UnifyTypeVisitor visitor, T ht); + /** * Returns the name of the type. * @return The name e.q. List for List, Integer or ? extends Integer @@ -96,6 +102,10 @@ public abstract class UnifyType { ret.addAll(typeParams.getInvolvedPlaceholderTypes()); return ret; } + + public Boolean wrongWildcard() {//default + return false; + } @Override public int hashCode() { diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/WildcardType.java b/src/de/dhbwstuttgart/typeinference/unify/model/WildcardType.java index 2bc51460..81999492 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/WildcardType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/WildcardType.java @@ -40,6 +40,11 @@ public abstract class WildcardType extends UnifyType { return wildcardedType.getTypeParams(); } + @Override + public Boolean wrongWildcard () {//This is an error + return (wildcardedType instanceof WildcardType); + } + @Override public int hashCode() { return wildcardedType.hashCode() + getName().hashCode() + 17; diff --git a/src/de/dhbwstuttgart/typeinference/unify/visitUnifyTypeVisitor.java b/src/de/dhbwstuttgart/typeinference/unify/visitUnifyTypeVisitor.java new file mode 100644 index 00000000..9ea3dc59 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/visitUnifyTypeVisitor.java @@ -0,0 +1,47 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.HashMap; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; +import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +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; + +public class visitUnifyTypeVisitor implements UnifyTypeVisitor { + + public ReferenceType visit(ReferenceType refty, T ht) { + return new ReferenceType(refty.getName(), + new TypeParams( + Arrays.stream(refty.getTypeParams().get()) + .map(x -> x.accept(this, ht)) + .collect(Collectors.toCollection(ArrayList::new)))); + } + + public PlaceholderType visit(PlaceholderType phty, T ht) { + return phty; + } + + public FunNType visit(FunNType funnty, T ht) { + return FunNType.getFunNType( + new TypeParams( + Arrays.stream(funnty.getTypeParams().get()) + .map(x -> x.accept(this, ht)) + .collect(Collectors.toCollection(ArrayList::new))) + ); + } + + public SuperType visit(SuperType suty, T ht) { + return new SuperType(suty.getWildcardedType().accept(this, ht)); + } + + public ExtendsType visit(ExtendsType extty, T ht) { + return new ExtendsType(extty.getWildcardedType().accept(this, ht)); + } +} diff --git a/test/bytecode/ATest.java b/test/bytecode/ATest.java deleted file mode 100644 index 14dbacbf..00000000 --- a/test/bytecode/ATest.java +++ /dev/null @@ -1,8 +0,0 @@ -package bytecode; - -public class ATest extends JavaTXCompilerTest { - public ATest() { - fileName = "Example"; - } - -} diff --git a/test/bytecode/AssignToLitTest.java b/test/bytecode/AssignToLitTest.java deleted file mode 100644 index dc5d397b..00000000 --- a/test/bytecode/AssignToLitTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class AssignToLitTest extends JavaTXCompilerTest { - public AssignToLitTest() { - this.fileName = "AssignToLit"; - } -} diff --git a/test/bytecode/DuMethodTest.java b/test/bytecode/DuMethodTest.java deleted file mode 100644 index a4c8a226..00000000 --- a/test/bytecode/DuMethodTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class DuMethodTest extends JavaTXCompilerTest{ - public DuMethodTest() { - this.fileName = "DuMethod"; - } -} diff --git a/test/bytecode/ForTest.java b/test/bytecode/ForTest.java deleted file mode 100644 index c95138d3..00000000 --- a/test/bytecode/ForTest.java +++ /dev/null @@ -1,11 +0,0 @@ -package bytecode; - -import org.objectweb.asm.Opcodes; - -public class ForTest extends JavaTXCompilerTest { - - public ForTest() { - this.fileName = "For"; - } - -} diff --git a/test/bytecode/Gen.jav b/test/bytecode/Gen.jav deleted file mode 100644 index 1f873919..00000000 --- a/test/bytecode/Gen.jav +++ /dev/null @@ -1,5 +0,0 @@ -public class Gen{ - Vector m(Vector v){ - return v; - } -} \ No newline at end of file diff --git a/test/bytecode/GenTest.java b/test/bytecode/GenTest.java new file mode 100644 index 00000000..d0067d08 --- /dev/null +++ b/test/bytecode/GenTest.java @@ -0,0 +1,41 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class GenTest { + + 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/Gen.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Gen"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() { + fail("Not yet implemented"); + } + +} diff --git a/test/bytecode/Generics2Test.java b/test/bytecode/Generics2Test.java deleted file mode 100644 index 26e52665..00000000 --- a/test/bytecode/Generics2Test.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class Generics2Test extends JavaTXCompilerTest{ - public Generics2Test() { - this.fileName = "Generics2"; - } -} diff --git a/test/bytecode/GenericsTest.java b/test/bytecode/GenericsTest.java deleted file mode 100644 index cca16129..00000000 --- a/test/bytecode/GenericsTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class GenericsTest extends JavaTXCompilerTest { - public GenericsTest() { - this.fileName = "Generics"; - } -} diff --git a/test/bytecode/GreaterEqualTest.java b/test/bytecode/GreaterEqualTest.java new file mode 100644 index 00000000..c65a4015 --- /dev/null +++ b/test/bytecode/GreaterEqualTest.java @@ -0,0 +1,140 @@ +package bytecode; + +import static org.junit.Assert.*; + +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.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class GreaterEqualTest { + + 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/GreaterEqual.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("File://"+pathToClassFile)}); + classToTest = loader.loadClass("GreaterEqual"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testName() { + assertEquals("GreaterEqual", classToTest.getName()); + } + @Test + public void testIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 7, 5); + assertTrue(result); + } + + @Test + public void testIntegers2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5, 7); + assertFalse(result); + } + + @Test + public void testEqIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5, 5); + assertTrue(result); + } + + @Test + public void testLongs() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Long.class, Long.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 10L,7L); + assertTrue(result); + } + + @Test + public void testFloats() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Float.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5F,7F); + assertFalse(result); + } + + @Test + public void testDoubles() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Double.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5.0,7.0); + assertFalse(result); + } + + @Test + public void testLongInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Long.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 15L,7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5F,7); + assertFalse(result); + } + + @Test + public void testDoubleInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 25.0,17); + assertTrue(result); + } + + @Test + public void testFloatLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Long.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 75F,70L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Long.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5.0,7L); + assertFalse(result); + } + + @Test + public void testEqDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 7.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 15.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 9.0,17F); + assertFalse(result); + } + +} diff --git a/test/bytecode/GreaterThanTest.java b/test/bytecode/GreaterThanTest.java new file mode 100644 index 00000000..8ab07ff1 --- /dev/null +++ b/test/bytecode/GreaterThanTest.java @@ -0,0 +1,139 @@ +package bytecode; + +import static org.junit.Assert.*; + +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.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class GreaterThanTest { + + 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/GreaterThan.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("File://"+pathToClassFile)}); + classToTest = loader.loadClass("GreaterThan"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testName() { + assertEquals("GreaterThan", classToTest.getName()); + } + + public void testIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 7, 5); + assertTrue(result); + } + + @Test + public void testIntegers2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5, 7); + assertFalse(result); + } + + @Test + public void testEqIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5, 5); + assertFalse(result); + } + + @Test + public void testLongs() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Long.class, Long.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 10L,7L); + assertTrue(result); + }@Test + + public void testFloats() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Float.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5F,7F); + assertFalse(result); + } + + @Test + public void testDoubles() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Double.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5.0,7.0); + assertFalse(result); + } + + @Test + public void testLongInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Long.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 15L,7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5F,7); + assertFalse(result); + } + + @Test + public void testDoubleInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 25.0,17); + assertTrue(result); + } + + @Test + public void testFloatLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Long.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 75F,70L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Long.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5.0,7L); + assertFalse(result); + } + + @Test + public void testEqDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 7.0,7F); + assertFalse(result); + } + + @Test + public void testDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 15.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 9.0,17F); + assertFalse(result); + } + +} diff --git a/test/bytecode/ImportTest.java b/test/bytecode/ImportTest.java deleted file mode 100644 index b7244e15..00000000 --- a/test/bytecode/ImportTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class ImportTest extends JavaTXCompilerTest{ - public ImportTest() { - this.fileName = "Import"; - } -} diff --git a/test/bytecode/InterfaceTest.java b/test/bytecode/InterfaceTest.java deleted file mode 100644 index ed378127..00000000 --- a/test/bytecode/InterfaceTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class InterfaceTest extends JavaTXCompilerTest{ - public InterfaceTest() { - this.fileName = "Interface1"; - } -} diff --git a/test/bytecode/JavaTXCompilerTest.java b/test/bytecode/JavaTXCompilerTest.java deleted file mode 100644 index 623fc96e..00000000 --- a/test/bytecode/JavaTXCompilerTest.java +++ /dev/null @@ -1,90 +0,0 @@ -package bytecode; - -import de.dhbwstuttgart.bytecode.BytecodeGen; -import de.dhbwstuttgart.core.JavaTXCompiler; -import de.dhbwstuttgart.syntaxtree.SourceFile; -import de.dhbwstuttgart.typeinference.result.ResultPair; -import de.dhbwstuttgart.typeinference.result.ResultSet; -import org.junit.Test; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -import static org.junit.Assert.*; - -public class JavaTXCompilerTest { - - private static final String rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; - private static final List filesToTest = new ArrayList<>(); - - protected String fileName = ""; - - @Test - public void test() throws IOException, java.lang.ClassNotFoundException { - System.out.println(rootDirectory); - filesToTest.add(new File(rootDirectory+fileName+".jav")); - System.out.println(rootDirectory+fileName+".jav"); - JavaTXCompiler compiler = new JavaTXCompiler(filesToTest); - for(File f : filesToTest){ - String content = readFile(f.getPath(), StandardCharsets.UTF_8); - List typeinferenceResult = compiler.typeInference(); - HashMap bytecode = this.getBytecode(compiler.sourceFiles.get(f), typeinferenceResult.get(0)); - -// for(ResultPair ep : typeinferenceResult.get(0).results) { -// System.out.println(ep.getLeft() + " ->" + ep.getRight()); -// } - - String name; - int pos = f.getName().lastIndexOf("."); - if(pos != -1) { - name = f.getName().substring(0, pos); - } - this.writeClassFile(bytecode); - } - - } - - - public HashMap getBytecode(SourceFile sf, ResultSet resultSet) { - HashMap classFiles = new HashMap<>(); - BytecodeGen bytecodeGen = new BytecodeGen(classFiles,resultSet); - bytecodeGen.visit(sf); - return bytecodeGen.getClassFiles(); - } - - public void writeClassFile(HashMap classFiles) { - FileOutputStream output; - for(String name : classFiles.keySet()) { - byte[] bytecode = classFiles.get(name); - try { - System.out.println("generating "+name+ ".class file ..."); - output = new FileOutputStream(new File(System.getProperty("user.dir") + "/testBytecode/generatedBC/" +name+".class")); - output.write(bytecode); - output.close(); - System.out.println(name+".class file generated"); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - } - - static String readFile(String path, Charset encoding) - throws IOException - { - byte[] encoded = Files.readAllBytes(Paths.get(path)); - return new String(encoded, encoding); - } - -} \ No newline at end of file diff --git a/test/bytecode/LamAssignTest.java b/test/bytecode/LamAssignTest.java deleted file mode 100644 index 3442c1d1..00000000 --- a/test/bytecode/LamAssignTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class LamAssignTest extends JavaTXCompilerTest{ - public LamAssignTest() { - this.fileName = "LamAssign"; - } -} diff --git a/test/bytecode/LambdaTest.java b/test/bytecode/LambdaTest.java new file mode 100644 index 00000000..f29690cb --- /dev/null +++ b/test/bytecode/LambdaTest.java @@ -0,0 +1,23 @@ +package bytecode; + +import java.io.File; + +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class LambdaTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Lambda.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + } + + +} diff --git a/test/bytecode/LessEqualTest.java b/test/bytecode/LessEqualTest.java new file mode 100644 index 00000000..de9cdb8c --- /dev/null +++ b/test/bytecode/LessEqualTest.java @@ -0,0 +1,133 @@ +package bytecode; + +import static org.junit.Assert.*; + +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.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class LessEqualTest { + + 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/LessEqual.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("LessEqual"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testName() { + assertEquals("LessEqual", classToTest.getName()); + } + + @Test + public void testIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Integer.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5,7); + assertTrue(result); + } + + @Test + public void testEqualIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Integer.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5,5); + assertTrue(result); + } + + @Test + public void testLongs() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Long.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5L,7L); + assertTrue(result); + }@Test + + public void testFloats() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5F,7F); + assertTrue(result); + } + + @Test + public void testDoubles() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Double.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5.0,7.0); + assertTrue(result); + } + + @Test + public void testLongInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Long.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5L,7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5F,7); + assertTrue(result); + } + + @Test + public void testDoubleInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5.0,7); + assertTrue(result); + } + + @Test + public void testFloatLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5F,7L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5.0,7L); + assertTrue(result); + } + + @Test + public void testEqDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 7.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 9.0,7F); + assertFalse(result); + } + +} diff --git a/test/bytecode/LessThanTest.java b/test/bytecode/LessThanTest.java new file mode 100644 index 00000000..6846f820 --- /dev/null +++ b/test/bytecode/LessThanTest.java @@ -0,0 +1,141 @@ +package bytecode; + +import static org.junit.Assert.*; + +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.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class LessThanTest { + + 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/LessThan.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("LessThan"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testClassName() { + assertEquals("LessThan", classToTest.getName()); + } + + @Test + public void testLessThanInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class,Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 5, 7); + assertTrue(result); + } + + @Test + public void testLessThanInt2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7, 5); + assertFalse(result); + } + + @Test + public void testLessThanInt3() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 5, 5); + assertFalse(result); + } + + @Test + public void testLessThanLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class,Long.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 5L, 7L); + assertTrue(result); + } + + @Test + public void testLessThanLong2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7L, 5L); + assertFalse(result); + } + + @Test + public void testLessThanLong3() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 5L, 5L); + assertFalse(result); + } + + @Test + public void testLessThanFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Float.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7F, 5F); + assertFalse(result); + } + + @Test + public void testLessThanDouble() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Double.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7.0, 5.0); + assertFalse(result); + } + + @Test + public void testLessThanLongInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7L, 5); + assertFalse(result); + } + + @Test + public void testLessThanFloatInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7F, 5); + assertFalse(result); + } + + @Test + public void testLessThanDoubleInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7.0, 5); + assertFalse(result); + } + + @Test + public void testLessThanFloatLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7F, 5L); + assertFalse(result); + } + + @Test + public void testLessThanDoubleLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7.0, 5L); + assertFalse(result); + } + + @Test + public void testLessThanDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Float.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7.0, 5F); + assertFalse(result); + } + +} diff --git a/test/bytecode/MatrixTest.java b/test/bytecode/MatrixTest.java new file mode 100644 index 00000000..98884151 --- /dev/null +++ b/test/bytecode/MatrixTest.java @@ -0,0 +1,40 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class MatrixTest { + 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/Matrix.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Matrix"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() { + fail("Not yet implemented"); + } + +} diff --git a/test/bytecode/MethodsTest.java b/test/bytecode/MethodsTest.java deleted file mode 100644 index 11195b71..00000000 --- a/test/bytecode/MethodsTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class MethodsTest extends JavaTXCompilerTest { - public MethodsTest() { - this.fileName = "Methods"; - } -} diff --git a/test/bytecode/OLTest.java b/test/bytecode/OLTest.java new file mode 100644 index 00000000..ff91073e --- /dev/null +++ b/test/bytecode/OLTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class OLTest { + 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/OL.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("OL"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + @Test + public void test() { + fail("Not yet implemented"); + } + +} diff --git a/test/bytecode/Op.jav b/test/bytecode/Op.jav deleted file mode 100644 index 9c05b0a2..00000000 --- a/test/bytecode/Op.jav +++ /dev/null @@ -1,12 +0,0 @@ -import java.lang.Integer; - -class Op { - m(Integer a, Integer b) { - Integer c = a+b; -// d = a-b; -// e = a*b; -// f = a/b; - - return c; - } -} \ No newline at end of file diff --git a/test/bytecode/OpTest.java b/test/bytecode/OpTest.java index cd8fee06..1d213a78 100644 --- a/test/bytecode/OpTest.java +++ b/test/bytecode/OpTest.java @@ -1,7 +1,61 @@ package bytecode; -public class OpTest extends JavaTXCompilerTest { - public OpTest() { - this.fileName = "Op"; +import static org.junit.Assert.*; + +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.BeforeClass; +import org.junit.Test; +import org.objectweb.asm.Opcodes; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class OpTest { + 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/Op.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Op"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); } + + @Test + public void testAddString() throws NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException, InstantiationException { + + Method m = classToTest.getDeclaredMethod("m", String.class,String.class); + + String result = (String) m.invoke(instanceOfClass, "Byte","Code"); + + assertEquals("ByteCode", result); + } + + @Test + public void testAddInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException, InstantiationException { + + Method m = classToTest.getDeclaredMethod("m", Integer.class,Integer.class); + + Integer result = (Integer) m.invoke(instanceOfClass, 7,3); + + assertEquals(10, result); + } + + } diff --git a/test/bytecode/OverlaodGenTest.java b/test/bytecode/OverlaodGenTest.java deleted file mode 100644 index 72bde4f9..00000000 --- a/test/bytecode/OverlaodGenTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class OverlaodGenTest extends JavaTXCompilerTest { - public OverlaodGenTest() { - this.fileName = "OverlaodGen"; - } -} diff --git a/test/bytecode/OverloadingTest.java b/test/bytecode/OverloadingTest.java new file mode 100644 index 00000000..294bf533 --- /dev/null +++ b/test/bytecode/OverloadingTest.java @@ -0,0 +1,57 @@ +package bytecode; + +import static org.junit.Assert.*; + +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.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class OverloadingTest { + 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; + + private static Class classOL2; + private static Object instanceOfClassOL2; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Overloading.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Overloading"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + classOL2 = loader.loadClass("Overloading2"); + instanceOfClassOL2 = classOL2.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method meth = classToTest.getDeclaredMethod("test", classToTest); + String res = (String) meth.invoke(instanceOfClass, instanceOfClass); + assertEquals("Overloading", res); + } + + @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/PlusTest.java b/test/bytecode/PlusTest.java new file mode 100644 index 00000000..016cb706 --- /dev/null +++ b/test/bytecode/PlusTest.java @@ -0,0 +1,54 @@ +package bytecode; + +import static org.junit.Assert.*; + +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.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class PlusTest { + 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/Plus.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/examples/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Plus"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testAddInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException, InstantiationException { + Method addInt = classToTest.getDeclaredMethod("m", Integer.class,Integer.class); + Number result = (Number) addInt.invoke(instanceOfClass, 7,3); + assertEquals(10, result); + } + + @Test + public void testAddString() throws NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException, InstantiationException { + Method addString = classToTest.getDeclaredMethod("m", String.class,String.class); + String result = (String) addString.invoke(instanceOfClass, "Byte","Code"); + assertEquals("ByteCode", result); + } + +} diff --git a/test/bytecode/PostIncTest.java b/test/bytecode/PostIncTest.java new file mode 100644 index 00000000..36e63816 --- /dev/null +++ b/test/bytecode/PostIncTest.java @@ -0,0 +1,65 @@ +package bytecode; + +import static org.junit.Assert.*; + +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.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class PostIncTest { + 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/PostIncDec.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("PostIncDec"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testM1() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(1, res); + } + + @Test + public void testM2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(0, res); + } + + @Test + public void testD1() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("d"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(-1, res); + } + + @Test + public void testD2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("d2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(0, res); + } + +} diff --git a/test/bytecode/PreIncTest.java b/test/bytecode/PreIncTest.java new file mode 100644 index 00000000..434b88e1 --- /dev/null +++ b/test/bytecode/PreIncTest.java @@ -0,0 +1,65 @@ +package bytecode; + +import static org.junit.Assert.*; + +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.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class PreIncTest { + 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/PreInc.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://" + pathToClassFile)}); + classToTest = loader.loadClass("PreInc"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testM() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(1, res); + } + + @Test + public void testM2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(1, res); + } + + @Test + public void testD() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("d"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(-1, res); + } + + @Test + public void testD2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("d2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(-1, res); + } + +} diff --git a/test/bytecode/StaticTest.java b/test/bytecode/StaticTest.java new file mode 100644 index 00000000..f639645c --- /dev/null +++ b/test/bytecode/StaticTest.java @@ -0,0 +1,41 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class StaticTest { + + 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/StaticM.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://" + pathToClassFile)}); + classToTest = loader.loadClass("StaticM"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() { + fail("Not yet implemented"); + } + +} diff --git a/test/bytecode/TestIfTest.java b/test/bytecode/TestIfTest.java deleted file mode 100644 index 804a0616..00000000 --- a/test/bytecode/TestIfTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class TestIfTest extends JavaTXCompilerTest{ - public TestIfTest() { - this.fileName = "IfTest"; - } -} diff --git a/test/bytecode/WhileTest.java b/test/bytecode/WhileTest.java new file mode 100644 index 00000000..5690facb --- /dev/null +++ b/test/bytecode/WhileTest.java @@ -0,0 +1,44 @@ +package bytecode; + +import static org.junit.Assert.*; + +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.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class WhileTest { + 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/While.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("While"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", Integer.class); + Integer result = (Integer) m.invoke(instanceOfClass, 0); + assertEquals(2, result); + } + +} diff --git a/test/bytecode/AssignToLit.jav b/test/bytecode/javFiles/AssignToLit.jav similarity index 100% rename from test/bytecode/AssignToLit.jav rename to test/bytecode/javFiles/AssignToLit.jav diff --git a/test/bytecode/DuMethod.jav b/test/bytecode/javFiles/DuMethod.jav similarity index 100% rename from test/bytecode/DuMethod.jav rename to test/bytecode/javFiles/DuMethod.jav diff --git a/test/bytecode/EmptyMethod.jav b/test/bytecode/javFiles/EmptyMethod.jav similarity index 100% rename from test/bytecode/EmptyMethod.jav rename to test/bytecode/javFiles/EmptyMethod.jav diff --git a/test/bytecode/Example.jav b/test/bytecode/javFiles/Example.jav similarity index 100% rename from test/bytecode/Example.jav rename to test/bytecode/javFiles/Example.jav diff --git a/test/bytecode/Exceptions.jav b/test/bytecode/javFiles/Exceptions.jav similarity index 100% rename from test/bytecode/Exceptions.jav rename to test/bytecode/javFiles/Exceptions.jav diff --git a/test/bytecode/Faculty.jav b/test/bytecode/javFiles/Faculty.jav similarity index 100% rename from test/bytecode/Faculty.jav rename to test/bytecode/javFiles/Faculty.jav diff --git a/test/bytecode/Faculty2.jav b/test/bytecode/javFiles/Faculty2.jav similarity index 100% rename from test/bytecode/Faculty2.jav rename to test/bytecode/javFiles/Faculty2.jav diff --git a/test/bytecode/For.jav b/test/bytecode/javFiles/For.jav similarity index 100% rename from test/bytecode/For.jav rename to test/bytecode/javFiles/For.jav diff --git a/test/bytecode/javFiles/Gen.jav b/test/bytecode/javFiles/Gen.jav new file mode 100644 index 00000000..5d579eb8 --- /dev/null +++ b/test/bytecode/javFiles/Gen.jav @@ -0,0 +1,8 @@ +import java.lang.Integer; +import java.util.Vector; + +public class Gen{ + Vector m(Vector v){ + return v; + } +} diff --git a/test/bytecode/Generics.jav b/test/bytecode/javFiles/Generics.jav similarity index 100% rename from test/bytecode/Generics.jav rename to test/bytecode/javFiles/Generics.jav diff --git a/test/bytecode/Generics2.jav b/test/bytecode/javFiles/Generics2.jav similarity index 100% rename from test/bytecode/Generics2.jav rename to test/bytecode/javFiles/Generics2.jav diff --git a/test/bytecode/javFiles/GreaterEqual.jav b/test/bytecode/javFiles/GreaterEqual.jav new file mode 100644 index 00000000..3ec69e8a --- /dev/null +++ b/test/bytecode/javFiles/GreaterEqual.jav @@ -0,0 +1,57 @@ +import java.lang.Integer; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; + +public class GreaterEqual { + + gE(Integer a, Integer b){ + var c = a>=b; + return c; + } + + gE(Long a, Long b){ + var c = a>=b; + return c; + } + + gE(Float a, Float b){ + var c = a>=b; + return c; + } + + gE(Double a, Double b){ + var c = a>=b; + return c; + } + + gE(Long a, Integer b){ + var c = a>=b; + return c; + } + + gE(Float a, Integer b){ + var c = a>=b; + return c; + } + + gE(Double a, Integer b){ + var c = a>=b; + return c; + } + + gE(Float a, Long b){ + var c = a>=b; + return c; + } + + gE(Double a, Long b){ + var c = a>=b; + return c; + } + + gE(Double a, Float b){ + var c = a>=b; + return c; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/GreaterThan.jav b/test/bytecode/javFiles/GreaterThan.jav new file mode 100644 index 00000000..9077f5b1 --- /dev/null +++ b/test/bytecode/javFiles/GreaterThan.jav @@ -0,0 +1,56 @@ +import java.lang.Integer; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; + +public class GreaterThan { + gT(Integer a, Integer b){ + var c = a>b; + return c; + } + + gT(Long a, Long b){ + var c = a>b; + return c; + } + + gT(Float a, Float b){ + var c = a>b; + return c; + } + + gT(Double a, Double b){ + var c = a>b; + return c; + } + + gT(Long a, Integer b){ + var c = a>b; + return c; + } + + gT(Float a, Integer b){ + var c = a>b; + return c; + } + + gT(Double a, Integer b){ + var c = a>b; + return c; + } + + gT(Float a, Long b){ + var c = a>b; + return c; + } + + gT(Double a, Long b){ + var c = a>b; + return c; + } + + gT(Double a, Float b){ + var c = a>b; + return c; + } +} \ No newline at end of file diff --git a/test/bytecode/IfTest.jav b/test/bytecode/javFiles/IfTest.jav similarity index 100% rename from test/bytecode/IfTest.jav rename to test/bytecode/javFiles/IfTest.jav diff --git a/test/bytecode/Import.jav b/test/bytecode/javFiles/Import.jav similarity index 100% rename from test/bytecode/Import.jav rename to test/bytecode/javFiles/Import.jav diff --git a/test/bytecode/Interface1.jav b/test/bytecode/javFiles/Interface1.jav similarity index 100% rename from test/bytecode/Interface1.jav rename to test/bytecode/javFiles/Interface1.jav diff --git a/test/bytecode/LamRunnable.jav b/test/bytecode/javFiles/LamRunnable.jav similarity index 100% rename from test/bytecode/LamRunnable.jav rename to test/bytecode/javFiles/LamRunnable.jav diff --git a/test/bytecode/LamAssign.jav b/test/bytecode/javFiles/Lambda.jav similarity index 63% rename from test/bytecode/LamAssign.jav rename to test/bytecode/javFiles/Lambda.jav index 82bb31b1..3aeded25 100644 --- a/test/bytecode/LamAssign.jav +++ b/test/bytecode/javFiles/Lambda.jav @@ -1,6 +1,6 @@ import java.lang.Integer; -class LamAssign { +public class Lambda { m () { var lam1 = (Integer x) -> { @@ -9,7 +9,3 @@ class LamAssign { return lam1; } } - -interface Fun1{ - public A apply(B b); -} \ No newline at end of file diff --git a/test/bytecode/Lambda2.jav b/test/bytecode/javFiles/Lambda2.jav similarity index 100% rename from test/bytecode/Lambda2.jav rename to test/bytecode/javFiles/Lambda2.jav diff --git a/test/bytecode/Lambda3.jav b/test/bytecode/javFiles/Lambda3.jav similarity index 100% rename from test/bytecode/Lambda3.jav rename to test/bytecode/javFiles/Lambda3.jav diff --git a/test/bytecode/Lambda.jav b/test/bytecode/javFiles/Lambda4.jav similarity index 100% rename from test/bytecode/Lambda.jav rename to test/bytecode/javFiles/Lambda4.jav diff --git a/test/bytecode/javFiles/LessEqual.jav b/test/bytecode/javFiles/LessEqual.jav new file mode 100644 index 00000000..2e3b7024 --- /dev/null +++ b/test/bytecode/javFiles/LessEqual.jav @@ -0,0 +1,56 @@ +import java.lang.Integer; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; + +public class LessEqual { + lessEqual(Integer a, Integer b){ + var c = a<=b; + return c; + } + + lessEqual(Long a, Long b){ + var c = a<=b; + return c; + } + + lessEqual(Float a, Float b){ + var c = a<=b; + return c; + } + + lessEqual(Double a, Double b){ + var c = a<=b; + return c; + } + + lessEqual(Long a, Integer b){ + var c = a<=b; + return c; + } + + lessEqual(Float a, Integer b){ + var c = a<=b; + return c; + } + + lessEqual(Double a, Integer b){ + var c = a<=b; + return c; + } + + lessEqual(Float a, Long b){ + var c = a<=b; + return c; + } + + lessEqual(Double a, Long b){ + var c = a<=b; + return c; + } + + lessEqual(Double a, Float b){ + var c = a<=b; + return c; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/LessThan.jav b/test/bytecode/javFiles/LessThan.jav new file mode 100644 index 00000000..04e1e83e --- /dev/null +++ b/test/bytecode/javFiles/LessThan.jav @@ -0,0 +1,57 @@ +import java.lang.Integer; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; + +public class LessThan { + + lessThan(Integer a, Integer b){ + var c = a> { + mul(m) { + var ret = new Matrix(); + var i = 0; + while(i < size()) { + var v1 = this.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) + * m.elementAt(k).elementAt(j); + k++; } + v2.addElement(new Integer(erg)); + j++; } + ret.addElement(v2); + i++; + } + return ret; + } +} diff --git a/test/bytecode/Methods.jav b/test/bytecode/javFiles/Methods.jav similarity index 100% rename from test/bytecode/Methods.jav rename to test/bytecode/javFiles/Methods.jav diff --git a/test/bytecode/javFiles/OL.jav b/test/bytecode/javFiles/OL.jav new file mode 100644 index 00000000..493c2499 --- /dev/null +++ b/test/bytecode/javFiles/OL.jav @@ -0,0 +1,9 @@ +import java.lang.Integer; +import java.lang.Boolean; + +class OL { + + m(Integer x) { return x + x; } + + m(Boolean x) {return x || x; } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/Op.jav b/test/bytecode/javFiles/Op.jav new file mode 100644 index 00000000..c01e7e6e --- /dev/null +++ b/test/bytecode/javFiles/Op.jav @@ -0,0 +1,16 @@ +import java.lang.Integer; +import java.lang.String; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; +import java.lang.Boolean; +import java.lang.Short; +import java.lang.Byte; + +public class Op { + + Integer m(Integer a, Integer b) { + //var c = a+b; + return a+b; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/Op2.jav b/test/bytecode/javFiles/Op2.jav new file mode 100644 index 00000000..9d446eb2 --- /dev/null +++ b/test/bytecode/javFiles/Op2.jav @@ -0,0 +1,11 @@ +import java.lang.Integer; +import java.lang.String; + +public class Op2 { + m(){ + var x = ""; + var a = 5+x; + + return a; + } +} \ No newline at end of file diff --git a/test/bytecode/OverlaodGen.jav b/test/bytecode/javFiles/OverlaodGen.jav similarity index 100% rename from test/bytecode/OverlaodGen.jav rename to test/bytecode/javFiles/OverlaodGen.jav diff --git a/test/bytecode/javFiles/Overloading.jav b/test/bytecode/javFiles/Overloading.jav new file mode 100644 index 00000000..fb48fe0f --- /dev/null +++ b/test/bytecode/javFiles/Overloading.jav @@ -0,0 +1,18 @@ +import java.lang.String; + +public class Overloading{ + + test(x){ + return x.methode(); + } + + methode(){ + return "Overloading"; + } +} + +public class Overloading2{ + methode(){ + return "Overloading2"; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/Plus.jav b/test/bytecode/javFiles/Plus.jav new file mode 100644 index 00000000..4d425bf0 --- /dev/null +++ b/test/bytecode/javFiles/Plus.jav @@ -0,0 +1,8 @@ +import java.lang.Integer; + +public class Plus { + + m(a,b) { + return a+b; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/PostIncDec.jav b/test/bytecode/javFiles/PostIncDec.jav new file mode 100644 index 00000000..29c2ef17 --- /dev/null +++ b/test/bytecode/javFiles/PostIncDec.jav @@ -0,0 +1,27 @@ +import java.lang.Integer; + +public class PostIncDec { + m() { + var i = 0; + i++; + return i; + } + + m2() { + var i = 0; + var j = i++; + return j; + } + + d() { + var i = 0; + i--; + return i; + } + + d2() { + var i = 0; + var j = i--; + return j; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/PreInc.jav b/test/bytecode/javFiles/PreInc.jav new file mode 100644 index 00000000..011501f1 --- /dev/null +++ b/test/bytecode/javFiles/PreInc.jav @@ -0,0 +1,28 @@ +import java.lang.Integer; + +public class PreInc { + m() { + var i = 0; + ++i; + return i; + } + + m2() { + var i = 0; + var j = ++i; + return j; + } + + d() { + var i = 0; + --i; + return i; + } + + d2() { + var i = 0; + var j = --i; + return j; + } + +} \ No newline at end of file diff --git a/test/bytecode/RecursiveMeth.jav b/test/bytecode/javFiles/RecursiveMeth.jav similarity index 100% rename from test/bytecode/RecursiveMeth.jav rename to test/bytecode/javFiles/RecursiveMeth.jav diff --git a/test/bytecode/ReturnMethod.jav b/test/bytecode/javFiles/ReturnMethod.jav similarity index 100% rename from test/bytecode/ReturnMethod.jav rename to test/bytecode/javFiles/ReturnMethod.jav diff --git a/test/bytecode/javFiles/StaticM.jav b/test/bytecode/javFiles/StaticM.jav new file mode 100644 index 00000000..66890033 --- /dev/null +++ b/test/bytecode/javFiles/StaticM.jav @@ -0,0 +1,10 @@ +public class StaticM { + + public static void m() { + System.out.println("Test"); + } + + public static void m2() { + m(); + } +} \ No newline at end of file diff --git a/test/bytecode/VoidMeth.jav b/test/bytecode/javFiles/VoidMeth.jav similarity index 100% rename from test/bytecode/VoidMeth.jav rename to test/bytecode/javFiles/VoidMeth.jav diff --git a/test/bytecode/javFiles/While.jav b/test/bytecode/javFiles/While.jav new file mode 100644 index 00000000..7ef43793 --- /dev/null +++ b/test/bytecode/javFiles/While.jav @@ -0,0 +1,10 @@ +import java.lang.Integer; + +public class While { + m(x) { + while(x < 2) { + x = x+1; + } + return x; + } +} \ No newline at end of file diff --git a/test/javFiles/FC_Matrix.jav b/test/javFiles/FC_Matrix.jav new file mode 100644 index 00000000..75ead472 --- /dev/null +++ b/test/javFiles/FC_Matrix.jav @@ -0,0 +1,10 @@ +import java.util.Vector; + +class Matrix extends Vector> { + + methode(m) { + m.add(1); + Matrix i; + methode(i); + } + } diff --git a/test/javFiles/Lambda.jav b/test/javFiles/Lambda.jav index 378eb4d3..553dc496 100644 --- a/test/javFiles/Lambda.jav +++ b/test/javFiles/Lambda.jav @@ -1,18 +1,13 @@ -class Lambda{ +import java.lang.Integer; +import java.lang.Number; -methode(){ - return ((f) -> f); -} -} -/* -interface Fun0{ - A apply(); +public class Lambda { + + m () { + var lam1 = (x) -> { + return x; + }; + return lam1; + } } -interface Fun1{ - A apply(B b); -} -*/ -interface Fun2{ - A apply(B b, C c); -} \ No newline at end of file diff --git a/test/javFiles/Lambda2.jav b/test/javFiles/Lambda2.jav index fbcdaf55..cf1e910b 100644 --- a/test/javFiles/Lambda2.jav +++ b/test/javFiles/Lambda2.jav @@ -1,3 +1,4 @@ +import java.lang.String; public class Lambda2 { diff --git a/test/javFiles/Lambda3.jav b/test/javFiles/Lambda3.jav index 9c4e960c..9e22f302 100644 --- a/test/javFiles/Lambda3.jav +++ b/test/javFiles/Lambda3.jav @@ -1,3 +1,4 @@ +import java.lang.String; public class Lambda2 { diff --git a/test/javFiles/LambdaField.jav b/test/javFiles/LambdaField.jav new file mode 100644 index 00000000..4eb53738 --- /dev/null +++ b/test/javFiles/LambdaField.jav @@ -0,0 +1,6 @@ +public class LambdaField { + + f = x -> x; + +} + diff --git a/test/javFiles/Matrix.jav b/test/javFiles/Matrix.jav index aa8966c9..8b01c235 100644 --- a/test/javFiles/Matrix.jav +++ b/test/javFiles/Matrix.jav @@ -1,26 +1,28 @@ import java.util.Vector; import java.lang.Integer; -import java.lang.Boolean; class Matrix extends Vector> { + Integer mul1(Integer x, Integer y) { return x;} + Integer add1(Integer x, Integer y) { return x;} mul(m) { var ret = new Matrix(); var i = 0; - //while(i < size()) { + while(i < size()) { var v1 = this.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) - // * m.elementAt(k).elementAt(j); - //k++; } - //v2.addElement(new Integer(erg)); - //j++; } - //ret.addElement(v2); - //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) * m.elementAt(k).elementAt(j); + //erg = add1(erg, mul1(v1.elementAt(k), + // m.elementAt(k).elementAt(j))); + k++; } + v2.addElement(new Integer(erg)); + j++; } + ret.addElement(v2); + i++; } return ret; } } diff --git a/test/javFiles/Meth_Gen.jav b/test/javFiles/Meth_Gen.jav new file mode 100644 index 00000000..056dd82f --- /dev/null +++ b/test/javFiles/Meth_Gen.jav @@ -0,0 +1,11 @@ +class Meth_Gen { + + m1(x, y) { + m2(x); + x = y; + } + + m2(y) { + m1(y, y); + } +} \ No newline at end of file diff --git a/test/typeinference/JavaTXCompilerTest.java b/test/typeinference/JavaTXCompilerTest.java index ba004cb5..122f2359 100644 --- a/test/typeinference/JavaTXCompilerTest.java +++ b/test/typeinference/JavaTXCompilerTest.java @@ -104,7 +104,11 @@ public class JavaTXCompilerTest { // //filesToTest.add(new File(rootDirectory+"mathStruc.jav")); // //filesToTest.add(new File(rootDirectory+"test.jav")); JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); - + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + } List results = compiler.typeInference(); for(File f : compiler.sourceFiles.keySet()){ diff --git a/test/typeinference/Meth_GenTest.java b/test/typeinference/Meth_GenTest.java new file mode 100644 index 00000000..f5e64f9f --- /dev/null +++ b/test/typeinference/Meth_GenTest.java @@ -0,0 +1,139 @@ +package typeinference; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class Meth_GenTest { + + public static final String rootDirectory = System.getProperty("user.dir")+"/test/javFiles/"; +/* + @Test + public void finiteClosure() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"fc.jav")); + } + @Test + public void lambda() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda.jav")); + } + @Test + public void lambda2() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda2.jav")); + } + @Test + public void lambda3() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda3.jav")); + } + @Test + public void mathStruc() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"mathStruc.jav")); + } + @Test + public void generics() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Generics.jav")); + } + + @Test + public void faculty() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Faculty.jav")); + } + + @Test + public void facultyTyped() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"FacultyTyped.jav")); + } +*/ + @Test + public void matrix() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Meth_Gen.jav")); + } +/* + @Test + public void vector() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Vector.jav")); + } + @Test + public void lambdaRunnable() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"LambdaRunnable.jav")); + } + @Test + public void expressions() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Expressions.jav")); + } + @Test + public void matrixFC() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"FC_Matrix.jav")); + } +*/ + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException { + //filesToTest.add(new File(rootDirectory+"fc.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda2.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda3.jav")); + //filesToTest.add(new File(rootDirectory+"Vector.jav")); + //filesToTest.add(new File(rootDirectory+"Generics.jav")); + //filesToTest.add(new File(rootDirectory+"MethodsEasy.jav")); + //filesToTest.add(new File(rootDirectory+"Matrix.jav")); + //filesToTest.add(new File(rootDirectory+"Import.jav")); + // //filesToTest.add(new File(rootDirectory+"Faculty.jav")); + // //filesToTest.add(new File(rootDirectory+"mathStruc.jav")); + // //filesToTest.add(new File(rootDirectory+"test.jav")); + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + } + List results = compiler.typeInference(); + + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + //List results = compiler.typeInference(); PL 2017-10-03 vor die For-Schleife gezogen + assert results.size()>0; + Set insertedTypes = new HashSet<>(); + for(ResultSet resultSet : results){ + Set result = TypeInsertFactory.createTypeInsertPoints(sf, resultSet); + assert result.size()>0; + String content = readFile(f.getPath(), StandardCharsets.UTF_8); + for(TypeInsert tip : result){ + insertedTypes.add(tip.insert(content)); + } + } + for(String s : insertedTypes){ + System.out.println(s); + } + } + return new TestResultSet(); + } + + static String readFile(String path, Charset encoding) + throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } + +} + diff --git a/test/typeinference/UnifyTest.java b/test/typeinference/UnifyTest.java new file mode 100644 index 00000000..2a496166 --- /dev/null +++ b/test/typeinference/UnifyTest.java @@ -0,0 +1,158 @@ +package typeinference; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class UnifyTest { + + public static final String rootDirectory = System.getProperty("user.dir")+"/test/javFiles/"; +/* + @Test + public void finiteClosure() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"fc.jav")); + } + */ +/* + @Test + public void lambda() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda.jav")); + } +*/ + /* + @Test + public void lambda2() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda2.jav")); + } + */ +/* + @Test + public void lambda3() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda3.jav")); + } + + @Test + public void lambdafield() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"LambdaField.jav")); + } + + @Test + public void mathStruc() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"mathStruc.jav")); + } + @Test + public void generics() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Generics.jav")); + } +*/ +/* + @Test + public void faculty() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Faculty.jav")); + } +*/ +/* + @Test + public void facultyTyped() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"FacultyTyped.jav")); + } + */ + + + @Test + public void matrix() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Matrix.jav")); + //JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"Matrix.jav")); + //compiler.generateBytecode(); + } + +/* + @Test + public void vector() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Vector.jav")); + } + @Test + public void lambdaRunnable() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"LambdaRunnable.jav")); + } + @Test + public void expressions() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Expressions.jav")); + } + @Test + public void matrixFC() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"FC_Matrix.jav")); + } +*/ + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException { + //filesToTest.add(new File(rootDirectory+"fc.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda2.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda3.jav")); + //filesToTest.add(new File(rootDirectory+"Vector.jav")); + //filesToTest.add(new File(rootDirectory+"Generics.jav")); + //filesToTest.add(new File(rootDirectory+"MethodsEasy.jav")); + //filesToTest.add(new File(rootDirectory+"Matrix.jav")); + //filesToTest.add(new File(rootDirectory+"Import.jav")); + // //filesToTest.add(new File(rootDirectory+"Faculty.jav")); + // //filesToTest.add(new File(rootDirectory+"mathStruc.jav")); + // //filesToTest.add(new File(rootDirectory+"test.jav")); + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + } + List results = compiler.typeInference(); + + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + //List results = compiler.typeInference(); PL 2017-10-03 vor die For-Schleife gezogen + assert results.size()>0; + Set insertedTypes = new HashSet<>(); + for(ResultSet resultSet : results){ + Set result = TypeInsertFactory.createTypeInsertPoints(sf, resultSet); + assert result.size()>0; + String content = readFile(f.getPath(), StandardCharsets.UTF_8); + for(TypeInsert tip : result){ + insertedTypes.add(tip.insert(content)); + } + } + for(String s : insertedTypes){ + System.out.println(s); + } + } + return new TestResultSet(); + } + + static String readFile(String path, Charset encoding) + throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } + +} +