diff --git a/src/de/dhbwstuttgart/.DS_Store b/src/de/dhbwstuttgart/.DS_Store index f20299e8..aa8a1074 100644 Binary files a/src/de/dhbwstuttgart/.DS_Store and b/src/de/dhbwstuttgart/.DS_Store differ diff --git a/src/de/dhbwstuttgart/bytecode/ArgumentVisitor.java b/src/de/dhbwstuttgart/bytecode/ArgumentVisitor.java new file mode 100644 index 00000000..be0e1bc7 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/ArgumentVisitor.java @@ -0,0 +1,255 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.List; + +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; +import de.dhbwstuttgart.syntaxtree.statement.Assign; +import de.dhbwstuttgart.syntaxtree.statement.AssignToField; +import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr; +import de.dhbwstuttgart.syntaxtree.statement.Block; +import de.dhbwstuttgart.syntaxtree.statement.CastExpr; +import de.dhbwstuttgart.syntaxtree.statement.DoStmt; +import de.dhbwstuttgart.syntaxtree.statement.EmptyStmt; +import de.dhbwstuttgart.syntaxtree.statement.ExpressionReceiver; +import de.dhbwstuttgart.syntaxtree.statement.FieldVar; +import de.dhbwstuttgart.syntaxtree.statement.ForStmt; +import de.dhbwstuttgart.syntaxtree.statement.IfStmt; +import de.dhbwstuttgart.syntaxtree.statement.InstanceOf; +import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; +import de.dhbwstuttgart.syntaxtree.statement.Literal; +import de.dhbwstuttgart.syntaxtree.statement.LocalVar; +import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl; +import de.dhbwstuttgart.syntaxtree.statement.MethodCall; +import de.dhbwstuttgart.syntaxtree.statement.NewArray; +import de.dhbwstuttgart.syntaxtree.statement.NewClass; +import de.dhbwstuttgart.syntaxtree.statement.Return; +import de.dhbwstuttgart.syntaxtree.statement.ReturnVoid; +import de.dhbwstuttgart.syntaxtree.statement.StaticClassName; +import de.dhbwstuttgart.syntaxtree.statement.Super; +import de.dhbwstuttgart.syntaxtree.statement.SuperCall; +import de.dhbwstuttgart.syntaxtree.statement.This; +import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr; +import de.dhbwstuttgart.syntaxtree.statement.WhileStmt; + +public class ArgumentVisitor implements StatementVisitor { + private List argListMethCall; + private BytecodeGenMethod bytecodeGenMethod; + + public ArgumentVisitor(List argListMethCall, BytecodeGenMethod bytecodeGenMethod) { + this.argListMethCall = argListMethCall; + this.bytecodeGenMethod = bytecodeGenMethod; + } + + @Override + public void visit(ArgumentList argumentList) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + lambdaExpression.accept(bytecodeGenMethod); + // Zieltype des Lambas ist Funktionale Interface + // kann nie primitiv sein => un-/boxing wird hier nicht gebraucht + argListMethCall.remove(0); + } + + @Override + public void visit(Assign assign) { + assign.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(assign.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(BinaryExpr binary) { + binary.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(binary.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(Block block) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(CastExpr castExpr) { + castExpr.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(castExpr.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(EmptyStmt emptyStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(FieldVar fieldVar) { + fieldVar.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(fieldVar.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(ForStmt forStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(IfStmt ifStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(InstanceOf instanceOf) { + instanceOf.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(instanceOf.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(LocalVar localVar) { + localVar.accept(bytecodeGenMethod); + if(!bytecodeGenMethod.isBinaryExp) { + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(localVar.getType())); + } + argListMethCall.remove(0); + } + + @Override + public void visit(LocalVarDecl localVarDecl) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(MethodCall methodCall) { + methodCall.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(methodCall.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(NewClass methodCall) { + methodCall.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(methodCall.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(NewArray newArray) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Return aReturn) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ReturnVoid aReturn) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(StaticClassName staticClassName) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Super aSuper) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(This aThis) { + aThis.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(aThis.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(WhileStmt whileStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(DoStmt whileStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(AssignToField assignLeftSide) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(AssignToLocal assignLeftSide) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(SuperCall superCall) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ExpressionReceiver expressionReceiver) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(UnaryExpr unaryExpr) { + unaryExpr.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(unaryExpr.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(Literal literal) { + literal.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(literal.getType())); + argListMethCall.remove(0); + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java index f9bf72ed..da114c2c 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -16,7 +16,9 @@ import org.objectweb.asm.Type; import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; import de.dhbwstuttgart.bytecode.signature.Signature; +import de.dhbwstuttgart.bytecode.signature.TypeToSignature; import de.dhbwstuttgart.bytecode.signature.TypeToString; +import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; import de.dhbwstuttgart.bytecode.utilities.NormalConstructor; import de.dhbwstuttgart.bytecode.utilities.NormalMethod; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; @@ -28,6 +30,8 @@ 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.GenericInsertPair; +import de.dhbwstuttgart.typeinference.result.ResolvedType; import de.dhbwstuttgart.typeinference.result.ResultPair; import de.dhbwstuttgart.typeinference.result.ResultSet; @@ -41,8 +45,13 @@ public class BytecodeGen implements ASTVisitor { private boolean isInterface; private List listOfResultSets; private ResultSet resultSet; + private SourceFile sf; + private String path; + private int indexOfFirstParam = 0; + private String superClass; + // stores parameter, local vars and the next index on the local variable table, which use for aload_i, astore_i,... HashMap paramsAndLocals = new HashMap<>(); // stores generics and their bounds of class @@ -50,22 +59,27 @@ public class BytecodeGen implements ASTVisitor { // stores generics and their bounds of method HashMap genericsAndBoundsMethod = new HashMap<>(); + private final TPHExtractor tphExtractor = new TPHExtractor(); + private final ArrayList commonPairs = new ArrayList<>(); + HashMap methodParamsAndTypes = new HashMap<>(); byte[] bytecode; HashMap classFiles; ArrayList methodNameAndParamsT = new ArrayList<>(); - public BytecodeGen(HashMap classFiles, List listOfResultSets) { + public BytecodeGen(HashMap classFiles, List listOfResultSets,SourceFile sf ,String path) { this.classFiles = classFiles; this.listOfResultSets = listOfResultSets; + this.sf = sf; + this.path = path; } @Override public void visit(SourceFile sourceFile) { for(ClassOrInterface cl : sourceFile.getClasses()) { System.out.println("in Class: " + cl.getClassName().toString()); - BytecodeGen classGen = new BytecodeGen(classFiles, listOfResultSets); + BytecodeGen classGen = new BytecodeGen(classFiles, listOfResultSets, sf, path); cl.accept(classGen); classGen.writeClass(cl.getClassName().toString()); } @@ -90,6 +104,7 @@ public class BytecodeGen implements ASTVisitor { @Override public void visit(ClassOrInterface classOrInterface) { + className = classOrInterface.getClassName().toString(); cw.visitSource(className +".jav", null); @@ -97,27 +112,42 @@ public class BytecodeGen implements ASTVisitor { isInterface = (classOrInterface.getModifiers()&512)==512; int acc = isInterface?classOrInterface.getModifiers()+Opcodes.ACC_ABSTRACT:classOrInterface.getModifiers()+Opcodes.ACC_SUPER; - String sig = null; - /* if class has generics then creates signature - * Signature looks like: - * Superclass - */ - if(classOrInterface.getGenerics().iterator().hasNext()) { - Signature signature = new Signature(classOrInterface, genericsAndBounds); - sig = signature.toString(); - } - // needs implemented Interfaces? - cw.visit(Opcodes.V1_8, acc, classOrInterface.getClassName().toString() - , sig, classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()), null); - for(Field f : classOrInterface.getFieldDecl()) { - f.accept(this); - } + // resultSet = listOfResultSets.get(0); boolean isConsWithNoParamsVisited = false; + boolean isVisited = false; for(ResultSet rs : listOfResultSets) { + superClass = classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()); resultSet = rs; + // Nur einmal ausführen!! + if(!isVisited) { + classOrInterface.accept(tphExtractor); + getCommonTPHS(tphExtractor); + + String sig = null; + /* if class has generics then creates signature + * Signature looks like: + * Superclass + */ + if(classOrInterface.getGenerics().iterator().hasNext() || !commonPairs.isEmpty() || + classOrInterface.getSuperClass().acceptTV(new TypeToSignature()).contains("<")) { + Signature signature = new Signature(classOrInterface, genericsAndBounds,commonPairs); + sig = signature.toString(); + System.out.println("Signature: => " + sig); + } + + cw.visit(Opcodes.V1_8, acc, classOrInterface.getClassName().toString() + , sig, classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()), null); + + isVisited = true; + } + + for(Field f : classOrInterface.getFieldDecl()) { + f.accept(this); + } + for(Constructor c : classOrInterface.getConstructors()) { if(!isConsWithNoParamsVisited) c.accept(this); @@ -133,6 +163,16 @@ public class BytecodeGen implements ASTVisitor { } + private void getCommonTPHS(TPHExtractor tphExtractor) { + // Gemeinsame TPHs + ArrayList cTPHs = new ArrayList<>(); + // Alle TPHs der Felder speichern + for(TypePlaceholder tph : tphExtractor.allTPHS.keySet()) { + if(!tphExtractor.allTPHS.get(tph)) + cTPHs.add(tph); + } + } + @Override public void visit(Constructor field) { field.getParameterList().accept(this); @@ -141,23 +181,25 @@ public class BytecodeGen implements ASTVisitor { boolean hasGen = false; for(String paramName : methodParamsAndTypes.keySet()) { - String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToDescriptor()); - if(genericsAndBounds.containsKey(typeOfParam)) { + String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature()); + if(genericsAndBounds.containsKey(typeOfParam) ||typeOfParam.substring(0, 4).equals("TPH ") + || typeOfParam.contains("<")) { hasGen = true; break; } } String sig = null; if(hasGen) { - Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes); + ArrayList pairs = simplifyPairs(field.name,tphExtractor.allPairs); + Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes,resultSet,pairs); sig = signature.toString(); } NormalConstructor constructor = new NormalConstructor(field,genericsAndBounds,hasGen); desc = constructor.accept(new DescriptorToString(resultSet)); MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", desc, sig, null); mv.visitCode(); - BytecodeGenMethod gen = new BytecodeGenMethod(className,resultSet,field, mv,paramsAndLocals,cw, - genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles); + BytecodeGenMethod gen = new BytecodeGenMethod(className,superClass,resultSet,field, mv,paramsAndLocals,cw, + genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles, sf,path); if(!field.getParameterList().iterator().hasNext()) { mv.visitInsn(Opcodes.RETURN); } @@ -191,13 +233,15 @@ public class BytecodeGen implements ASTVisitor { System.out.println(acc); /*Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist*/ - boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.subSequence(0, 4).equals("TPH "); + boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.subSequence(0, 4).equals("TPH ") || + resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()).contains("<"); /*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()); - if(genericsAndBounds.containsKey(typeOfParam)||typeOfParam.substring(0, 4).equals("TPH ")) { + String sigOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature()); + if(genericsAndBounds.containsKey(typeOfParam)||typeOfParam.substring(0, 4).equals("TPH ")||sigOfParam.contains("<")) { hasGenInParameterList = true; break; } @@ -211,15 +255,16 @@ public class BytecodeGen implements ASTVisitor { /* method.getGenerics: <....> RT method(..) * */ boolean hasGen = method.getGenerics().iterator().hasNext() || hasGenInParameterList; - /* if method has generics or return type is TPH, create signature */ // zwite operand muss weggelassen werden - if(hasGen||method.getReturnType().acceptTV(new TypeToString()).equals("TPH")) { - // resultset hier zum testen - Signature signature = new Signature(method, genericsAndBoundsMethod, methodParamsAndTypes,resultSet); + if(hasGen||resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToString()).equals("TPH")) { + ArrayList pairs = simplifyPairs(method.name,tphExtractor.allPairs); + System.out.println(method.name + " => Simplified Pairs: "); + pairs.forEach(p->System.out.println(p.TA1.getName() + " -> "+p.TA2.getName())); + Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds,methodParamsAndTypes,resultSet, pairs); sig = signature.toString(); } -// System.out.println(sig); + System.out.println(method.getName()+" ==> "+sig); NormalMethod meth = new NormalMethod(method,genericsAndBounds,genericsAndBoundsMethod,hasGen); methDesc = meth.accept(new DescriptorToString(resultSet)); @@ -227,13 +272,103 @@ public class BytecodeGen implements ASTVisitor { 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, - genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles); + BytecodeGenMethod gen = new BytecodeGenMethod(className,superClass,resultSet,method, mv,paramsAndLocals,cw, + genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles, sf,path); mv.visitMaxs(0, 0); mv.visitEnd(); } + private ArrayList simplifyPairs(String methodName, ArrayList allPairs) { + allPairs.forEach(p->System.out.print(p.TA1 + " < "+ p.TA2+ " ; ")); + + if(allPairs.size() < 2) + return allPairs; + + ArrayList simplifiedPairs = new ArrayList<>(); + + MethodAndTPH method; + ArrayList methodTphs = new ArrayList<>(); + ArrayList methodPairs = new ArrayList<>(); + for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) { + if(m.getName().equals(methodName)) { + methodTphs = m.getTphs(); + methodPairs = m.getPairs(); + break; + } + } + + HashMap subAndSuperTph = new HashMap<>(); + for(GenericInsertPair p : allPairs) { + // Tph2.jav + if(subAndSuperTph.containsKey(p.TA1)) { + if(methodTphs.contains(subAndSuperTph.get(p.TA1))) + continue; + } + subAndSuperTph.put(p.TA1, p.TA2); + } + int numOfVisitedPairs = 0; + for(TypePlaceholder subTph: subAndSuperTph.keySet()) { + + if(numOfVisitedPairs>=subAndSuperTph.size()) + break; + + if(!methodTphs.contains(subTph)) + continue; + + HashMap tphsInRel= new HashMap<>(); + + tphsInRel.put(tphsInRel.size(), subTph); + TypePlaceholder superTph = subAndSuperTph.get(subTph); + tphsInRel.put(tphsInRel.size(), superTph); + + numOfVisitedPairs++; + + while(subAndSuperTph.containsKey(superTph)) { + superTph = subAndSuperTph.get(superTph); + tphsInRel.put(tphsInRel.size(), superTph); + numOfVisitedPairs++; + } + + // Subtype + TypePlaceholder subTphRes = tphsInRel.get(0); + // Die größte Supertype + TypePlaceholder superTphRes = tphsInRel.get(tphsInRel.size()-1); + + while(subAndSuperTph.containsValue(subTphRes)) { + for(TypePlaceholder tph : subAndSuperTph.keySet()) { + if(methodTphs.contains(tph) && subAndSuperTph.get(tph).equals(subTphRes)) { + subTphRes = tph; + break; + } + } + if(subTphRes.equals(tphsInRel.get(0))) { + break; + } + tphsInRel.put(0, subTphRes); + numOfVisitedPairs++; + } + + subTphRes = tphsInRel.get(0); + + int i = 2; + while(!methodTphs.contains(superTphRes) && (tphsInRel.size()-i) >0) { + superTphRes = tphsInRel.get(tphsInRel.size()-i); + i++; + } + // teste noch den Fall X < Y und Y nicht in TPHS der Methode + // Dann hat man nach der While-Schleife X < Y + // Y muss durch Object ersetzt. + + // Zweite Operand für die Fälle wie in Lambda.jav (Paramtrisierte Typen) + if(methodTphs.contains(superTphRes) || !tphExtractor.allTPHS.containsKey(superTphRes)) { + GenericInsertPair sPair = new GenericInsertPair(subTphRes, superTphRes); + simplifiedPairs.add(sPair); + } + } + return simplifiedPairs; + } + @Override public void visit(ParameterList formalParameters) { paramsAndLocals = new HashMap<>(); @@ -475,5 +610,50 @@ public class BytecodeGen implements ASTVisitor { public void visit(UnaryExpr unaryExpr) { throw new NotImplementedException(); } + + private class TPHExtractor extends AbstractASTWalker{ + // Alle TPHs der Felder werden iKopf der Klasse definiert + // alle TPHs der Klasse: (TPH, is in Method?) + final HashMap allTPHS = new HashMap<>(); + MethodAndTPH methodAndTph; + Boolean inMethod = false; + final ArrayList ListOfMethodsAndTph = new ArrayList<>(); + final ArrayList allPairs = new ArrayList<>(); + + @Override + public void visit(TypePlaceholder tph) { + if(resultSet.resolveType(tph).resolvedType instanceof TypePlaceholder) { + TypePlaceholder resolvedTPH = (TypePlaceholder) resultSet.resolveType(tph).resolvedType; + if(inMethod) + methodAndTph.getTphs().add(resolvedTPH); + + allTPHS.put(resolvedTPH,inMethod); + resultSet.resolveType(tph).additionalGenerics.forEach(ag ->{ + if(ag.contains(resolvedTPH)&&ag.TA1.equals(resolvedTPH)&&!contains(allPairs,ag)) { + if(inMethod) + methodAndTph.getPairs().add(ag); + allPairs.add(ag); + } + }); + } + } + private boolean contains(ArrayList pairs, GenericInsertPair genPair) { + for(int i=0; i genericsAndBoundsMethod; + private HashMap genericsAndBoundsMethod; private HashMap genericsAndBounds; - private boolean isBinaryExp = false; - + public boolean isBinaryExp = false; + private String superClass; + private String path; + private SourceFile sf; private IStatement statement = null; - + +// private int numMethodCalls = 0; + // for tests ** private String fieldName; private String fieldDesc; @@ -67,11 +82,12 @@ public class BytecodeGenMethod implements StatementVisitor { private ArrayList varsFunInterface = new ArrayList<>();; - public BytecodeGenMethod(String className, ResultSet resultSet, Method m, MethodVisitor mv, + public BytecodeGenMethod(String className, String superClass,ResultSet resultSet, Method m, MethodVisitor mv, HashMap paramsAndLocals, ClassWriter cw, HashMap genericsAndBoundsMethod, - HashMap genericsAndBounds, boolean isInterface, HashMap classFiles) { + HashMap genericsAndBounds, boolean isInterface, HashMap classFiles, SourceFile sf,String path) { this.className = className; + this.superClass = superClass; this.resultSet = resultSet; this.m = m; this.mv = mv; @@ -81,19 +97,22 @@ public class BytecodeGenMethod implements StatementVisitor { this.genericsAndBounds = genericsAndBounds; this.isInterface = isInterface; this.classFiles = classFiles; - + this.sf = sf; + this.path = path; + if (!isInterface) this.m.block.accept(this); } public BytecodeGenMethod(LambdaExpression lambdaExpression, ResultSet resultSet, MethodVisitor mv, - int indexOfFirstParamLam, boolean isInterface, HashMap classFiles) { + int indexOfFirstParamLam, boolean isInterface, HashMap classFiles, String path) { this.resultSet = resultSet; this.mv = mv; this.isInterface = isInterface; this.classFiles = classFiles; + this.path = path; Iterator itr = lambdaExpression.params.iterator(); int i = indexOfFirstParamLam; @@ -104,8 +123,12 @@ public class BytecodeGenMethod implements StatementVisitor { } lambdaExpression.methodBody.accept(this); } - - private String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { + + public void isBinary(boolean isBinary) { + this.isBinaryExp =isBinary; + } + + public String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor()); } @@ -113,6 +136,11 @@ public class BytecodeGenMethod implements StatementVisitor { public void visit(Block block) { for (Statement stmt : block.getStatements()) { stmt.accept(this); + if(stmt instanceof MethodCall) { + String ret = getResolvedType(((MethodCall) stmt).getType()); + if(!ret.equals("void")) + mv.visitInsn(Opcodes.POP); + } } } @@ -120,7 +148,7 @@ public class BytecodeGenMethod implements StatementVisitor { public void visit(SuperCall superCall) { superCall.receiver.accept(this); superCall.arglist.accept(this); - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), superCall.name, "()V", + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, this.superClass, superCall.name, "()V", isInterface); } @@ -129,7 +157,7 @@ public class BytecodeGenMethod implements StatementVisitor { 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. - + System.out.println(localVar.name); mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name)); if (isBinaryExp) { @@ -167,6 +195,11 @@ public class BytecodeGenMethod implements StatementVisitor { doBoxing(binaryType); isBinaryExp = false; } + System.out.println("ASSIGN TYPE R: " + getResolvedType(assign.rightSide.getType())); + String typeOfRightSide = getResolvedType(assign.rightSide.getType()); + if(typeOfRightSide.contains("<")) { + mv.visitTypeInsn(Opcodes.CHECKCAST, typeOfRightSide.substring(0, typeOfRightSide.indexOf('<'))); + } assign.lefSide.accept(this); statement = null; @@ -180,7 +213,7 @@ public class BytecodeGenMethod implements StatementVisitor { 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); @@ -520,7 +553,7 @@ public class BytecodeGenMethod implements StatementVisitor { methodName, arg3.toString(), null, null); new BytecodeGenMethod(lambdaExpression, this.resultSet, mvLambdaBody, indexOfFirstParamLam, isInterface, - classFiles); + classFiles,this.path); mvLambdaBody.visitMaxs(0, 0); mvLambdaBody.visitEnd(); @@ -548,7 +581,7 @@ public class BytecodeGenMethod implements StatementVisitor { // ")"+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(), + classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC+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); @@ -561,7 +594,7 @@ public class BytecodeGenMethod implements StatementVisitor { try { System.out.println("generating " + name + ".class file..."); output = new FileOutputStream( - new File(System.getProperty("user.dir") + "/testBytecode/generatedBC/" + name + ".class")); + new File(path + name + ".class")); output.write(bytecode); output.close(); System.out.println(name + ".class file generated"); @@ -575,7 +608,6 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(CastExpr castExpr) { - // TODO Auto-generated method stub } @@ -587,7 +619,6 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(FieldVar fieldVar) { - fieldName = fieldVar.fieldVarName; fieldDesc = "L" + getResolvedType(fieldVar.getType()) + ";"; @@ -615,32 +646,157 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(InstanceOf instanceOf) { - // TODO Auto-generated method stub } @Override public void visit(MethodCall methodCall) { - + System.out.println("In MethodCall = " + methodCall.name); + String receiverName = getResolvedType(methodCall.receiver.getType()); + System.out.println("Methods of " + receiverName + " "); + ClassLoader cLoader = ClassLoader.getSystemClassLoader(); + java.lang.reflect.Method methodRefl = null; + String clazz = receiverName.replace("/", "."); + try { + if(receiverName.contains("<")) { + clazz = clazz.substring(0, receiverName.indexOf("<")); + } + java.lang.reflect.Method[] methods = cLoader.loadClass(clazz).getMethods(); + System.out.println("Methods of " + receiverName + " "); + for(java.lang.reflect.Method m : methods) { + if(methodCall.name.equals(m.getName())) { + methodRefl = m; + break; + } + } + } catch (Exception e) { + String superClass = ""; + // TODO: Test SubMatrix.jav + while(true) { + for(ClassOrInterface cl : sf.getClasses()) { + if(receiverName.equals(cl.getClassName().toString())) { + superClass = cl.getSuperClass().getName().toString(); + break; + } + } + System.out.println(superClass); + + if(superClass.equals("")) + break; + + try { + String superClazz = superClass.replace("/", "."); + if(superClass.contains("<")) { + superClazz = superClazz.substring(0, superClass.indexOf("<")); + } + java.lang.reflect.Method[] methods = cLoader.loadClass(superClazz).getMethods(); + System.out.println("Methods of " + superClass + " "); + + for(java.lang.reflect.Method m : methods) { + if(methodCall.name.equals(m.getName())) { + methodRefl = m; + break; + } + } + + break; + } catch (Exception e2) { + receiverName = superClass; + continue; + } + } + + } methodCall.receiver.accept(this); - methodCall.arglist.accept(this); - - MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), - genericsAndBoundsMethod, genericsAndBounds); - String mDesc = method.accept(new DescriptorToString(resultSet)); - + + System.out.println("Methodcall type : " + resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor())); + String mDesc = ""; + List argListMethCall = new LinkedList<>(); + if(methodRefl == null) { + MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), + receiverName, genericsAndBoundsMethod, genericsAndBounds); + mDesc = method.accept(new DescriptorToString(resultSet)); + methodCall.arglist.accept(this); + } else { + for(Parameter p:methodRefl.getParameters()) { + System.out.println(p.getName() + " und is Primitive = " + p.getType().isPrimitive()); + argListMethCall.add(p.getType().isPrimitive()); + } + mDesc = getMethodDesc(methodRefl); + for (Expression al : methodCall.arglist.getArguments()) { + statement = new ArgumentExpr(al); + ArgumentVisitor argV = new ArgumentVisitor(argListMethCall,this); + al.accept(argV); + statement = null; + } + } + + System.out.println("Methodcall Desc : " + mDesc); + + +// methodCall.arglist.accept(this); + // is methodCall.receiver functional Interface)? if (varsFunInterface.contains(methodCall.receiver.getType())) { - mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()), methodCall.name, - mDesc, false); + mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, clazz.replace(".", "/"), methodCall.name, + mDesc, true); } else { - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, getResolvedType(methodCall.receiver.getType()), methodCall.name, + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, clazz.replace(".", "/"), methodCall.name, mDesc, isInterface); } - // test - // if(!methodCall.getType().toString().equals("V")) { - // mv.visitInsn(Opcodes.POP); - // } + + if(methodRefl != null && !methodRefl.getReturnType().isPrimitive()) { + if(methodRefl.getReturnType().equals(Object.class)) { + String checkCast = getResolvedType(methodCall.getType()); + int pos = checkCast.length(); + if(checkCast.contains("<")) + pos = checkCast.indexOf("<"); + mv.visitTypeInsn(Opcodes.CHECKCAST,checkCast.substring(0,pos)); + } + if(isBinaryExp) + doUnboxing(getResolvedType(methodCall.getType())); + } + + } + + private String getMethodDesc(java.lang.reflect.Method methodRefl) { + StringBuilder sb = new StringBuilder("("); + + for(final Class c:(methodRefl.getParameterTypes())) + sb= sb.append(getDescriptorForClass(c)); + + sb.append(')'); + sb.append(getDescriptorForClass(methodRefl.getReturnType())); + return sb.toString(); + } + + private String getDescriptorForClass(final Class c) { + if(c.isPrimitive()) + { + if(c==byte.class) + return "B"; + if(c==char.class) + return "C"; + if(c==double.class) + return "D"; + if(c==float.class) + return "F"; + if(c==int.class) + return "I"; + if(c==long.class) + return "J"; + if(c==short.class) + return "S"; + if(c==boolean.class) + return "Z"; + if(c==void.class) + return "V"; + + } + if(c.isArray()) + return c.getName().replace('.', '/'); + + return ('L'+c.getName()+';').replace('.', '/'); } @Override @@ -672,6 +828,7 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(UnaryExpr unaryExpr) { + unaryExpr.expr.accept(this); Operation op = unaryExpr.operation; @@ -799,7 +956,7 @@ public class BytecodeGenMethod implements StatementVisitor { statement = new LoopStmt(whileStmt.expr, whileStmt.loopBlock); isBinaryExp = statement.isExprBinary(); whileStmt.expr.accept(this); - isBinaryExp = false; +// isBinaryExp = false; statement = null; } @@ -819,7 +976,7 @@ public class BytecodeGenMethod implements StatementVisitor { } // Unboxing: RefType -> prim - private void doUnboxing(String type) { + public void doUnboxing(String type) { switch (type) { case "java/lang/String": mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(StringBuilder.class), "append", @@ -1040,13 +1197,9 @@ public class BytecodeGenMethod implements StatementVisitor { 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::: - + } + + mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.get(var)); } } diff --git a/src/de/dhbwstuttgart/bytecode/LoopStmt.java b/src/de/dhbwstuttgart/bytecode/LoopStmt.java index 109efd34..0f7788d4 100644 --- a/src/de/dhbwstuttgart/bytecode/LoopStmt.java +++ b/src/de/dhbwstuttgart/bytecode/LoopStmt.java @@ -18,6 +18,7 @@ public class LoopStmt extends AStatement { @Override public void genBCForRelOp(MethodVisitor mv,Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod) { + bytecodeGenMethod.isBinary(false); this.loopBlock.accept(bytecodeGenMethod); mv.visitJumpInsn(Opcodes.GOTO, endLabel); mv.visitLabel(branchLabel); diff --git a/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java b/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java index 0e97ca4c..d92efe5a 100644 --- a/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java +++ b/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java @@ -2,6 +2,8 @@ package de.dhbwstuttgart.bytecode.descriptor; import java.util.Iterator; +import org.objectweb.asm.Type; + import de.dhbwstuttgart.bytecode.signature.TypeToSignature; import de.dhbwstuttgart.bytecode.utilities.Lambda; import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall; @@ -49,7 +51,8 @@ public class DescriptorToString implements DescriptorVisitor{ // desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; String resType = resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()); if(resType.subSequence(0, 4).equals("TPH ")) { - desc += "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";"; + // Bound ist immer Object + desc += "L"+Type.getInternalName(Object.class)+ ";"; } else { desc += "L"+resType+ ";"; } @@ -76,7 +79,8 @@ public class DescriptorToString implements DescriptorVisitor{ }else { String resType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); if(resType.subSequence(0, 4).equals("TPH ")) { - desc += ")" + "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";"; +// desc += ")" + "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";"; + desc += ")" + "L"+Type.getInternalName(Object.class)+ ";"; } else { desc += ")" + "L"+resType+ ";"; } @@ -119,9 +123,21 @@ public class DescriptorToString implements DescriptorVisitor{ Iterator itr = lambdaExpression.getParams().iterator(); while(itr.hasNext()) { FormalParameter fp = itr.next(); - desc = desc + "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()) + ";"; + String d = resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + if(d.substring(0, 4).equals("TPH ") ||d.contains("<")) { + desc += "L"+Type.getInternalName(Object.class)+ ";"; + }else { + desc = desc + "L"+ d + ";"; + } + } + + String retType = resultSet.resolveType(lambdaExpression.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); + + if(retType.substring(0, 4).equals("TPH ")|| retType.contains("<")){ + desc += ")L"+Type.getInternalName(Object.class)+ ";"; + }else { + desc = desc + ")"+"L"+retType+";"; } - desc = addReturnType(desc, lambdaExpression.getReturnType(), resultSet); return desc; } @@ -131,9 +147,22 @@ public class DescriptorToString implements DescriptorVisitor{ Iterator itr = samMethod.getArgumentList().iterator(); while(itr.hasNext()) { RefTypeOrTPHOrWildcardOrGeneric rt = itr.next(); - desc = desc + "L"+resultSet.resolveType(rt).resolvedType.acceptTV(new TypeToDescriptor())+";"; + String d = resultSet.resolveType(rt).resolvedType.acceptTV(new TypeToDescriptor()); + + if(d.substring(0, 4).equals("TPH ") ||d.contains("<")) { + desc += "L"+Type.getInternalName(Object.class)+ ";"; + }else { + desc += "L"+ d + ";"; + + } + } + String retType = resultSet.resolveType(samMethod.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); + + if(retType.substring(0, 4).equals("TPH ")|| retType.contains("<")){ + desc += ")L"+Type.getInternalName(Object.class)+ ";"; + }else { + desc = desc + ")"+"L"+retType+";"; } - desc = desc + ")"+"L"+resultSet.resolveType(samMethod.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+";"; return desc; } @@ -141,26 +170,34 @@ public class DescriptorToString implements DescriptorVisitor{ public String visit(MethodFromMethodCall methodFromMethodCall) { String desc = "("; for(Expression e : methodFromMethodCall.getArgList().getArguments()) { - String d = e.getType().acceptTV(new TypeToDescriptor()); - if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(d)) { - desc += "L"+methodFromMethodCall.getGenericsAndBoundsMethod().get(d)+ ";"; - }else if(methodFromMethodCall.getGenericsAndBounds().containsKey(d)) { - desc += "L"+methodFromMethodCall.getGenericsAndBounds().get(d)+ ";"; + String d = resultSet.resolveType(e.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + + if(d.substring(0, 4).equals("TPH ") ||d.contains("<") || methodFromMethodCall.getReceiverName().contains("$$")) { + desc += "L"+Type.getInternalName(Object.class)+ ";"; }else { - desc += "L"+resultSet.resolveType(e.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(d)) { + desc += "L"+methodFromMethodCall.getGenericsAndBoundsMethod().get(d)+ ";"; + }else if(methodFromMethodCall.getGenericsAndBounds().containsKey(d)) { + desc += "L"+methodFromMethodCall.getGenericsAndBounds().get(d)+ ";"; + }else { + desc += "L"+resultSet.resolveType(e.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } } + } - - if(resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.toString().equals("void")) { + String retType = resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); + System.out.println("DescriptorToString retType = " + retType); + if(retType.equals("void")) { desc += ")V"; + }else if(retType.substring(0, 4).equals("TPH ")|| retType.contains("<") || methodFromMethodCall.getReceiverName().contains("$$")){ + desc += ")L"+Type.getInternalName(Object.class)+ ";"; }else { - String ret = resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); - if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(ret)) { - desc += ")L"+methodFromMethodCall.getGenericsAndBoundsMethod().get(ret)+ ";"; - }else if(methodFromMethodCall.getGenericsAndBounds().containsKey(ret)){ - desc += ")L"+methodFromMethodCall.getGenericsAndBounds().get(ret)+ ";"; + if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(retType)) { + desc += ")L"+methodFromMethodCall.getGenericsAndBoundsMethod().get(retType)+ ";"; + }else if(methodFromMethodCall.getGenericsAndBounds().containsKey(retType)){ + desc += ")L"+methodFromMethodCall.getGenericsAndBounds().get(retType)+ ";"; }else { - desc += ")" + "L"+resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + desc += ")" + "L"+retType+ ";"; } } // desc = addReturnType(desc, methodFromMethodCall.getReturnType(), resultSet); diff --git a/src/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java b/src/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java index 69ac6d13..8ee84328 100644 --- a/src/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java +++ b/src/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java @@ -19,7 +19,9 @@ public class TypeToDescriptor implements TypeVisitor{ @Override public String visit(SuperWildcardType superWildcardType) { - throw new NotImplementedException(); + System.out.println("\nWILDCARD ="+superWildcardType.getInnerType().toString().replace(".", "/")); + return superWildcardType.getInnerType().toString().replace(".", "/"); + //throw new NotImplementedException(); } @Override @@ -29,6 +31,7 @@ public class TypeToDescriptor implements TypeVisitor{ @Override public String visit(ExtendsWildcardType extendsWildcardType) { + System.out.println("\nWILDCARD extends ="+extendsWildcardType.getInnerType().toString().replace(".", "/")); return extendsWildcardType.getInnerType().toString().replace(".", "/"); //throw new NotImplementedException(); } diff --git a/src/de/dhbwstuttgart/bytecode/signature/Signature.java b/src/de/dhbwstuttgart/bytecode/signature/Signature.java index 48804661..c049cac3 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/Signature.java +++ b/src/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.bytecode.signature; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -8,13 +9,19 @@ import org.objectweb.asm.signature.SignatureVisitor; import org.objectweb.asm.signature.SignatureWriter; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; +import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; +import de.dhbwstuttgart.syntaxtree.AbstractASTWalker; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.Constructor; import de.dhbwstuttgart.syntaxtree.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.result.GenericInsertPair; +import de.dhbwstuttgart.typeinference.result.ResolvedType; import de.dhbwstuttgart.typeinference.result.ResultSet; public class Signature { @@ -26,28 +33,36 @@ public class Signature { private Method method; private HashMap methodParamsAndTypes; private ResultSet resultSet; + private ArrayList commonPairs; + private ArrayList methodPairs; - public Signature(ClassOrInterface classOrInterface, HashMap genericsAndBounds) { + public Signature(ClassOrInterface classOrInterface, HashMap genericsAndBounds,ArrayList commonPairs) { this.classOrInterface = classOrInterface; this.genericsAndBounds = genericsAndBounds; + this.commonPairs = commonPairs; sw = new SignatureWriter(); createSignatureForClassOrInterface(); } - public Signature(Constructor constructor, HashMap genericsAndBounds, HashMap methodParamsAndTypes) { + public Signature(Constructor constructor, HashMap genericsAndBounds, + HashMap methodParamsAndTypes,ResultSet resultSet,ArrayList methodPairs) { this.constructor = constructor; this.genericsAndBounds = genericsAndBounds; this.methodParamsAndTypes = methodParamsAndTypes; + this.resultSet = resultSet; + this.methodPairs = methodPairs; sw = new SignatureWriter(); createSignatureForConsOrMethod(this.constructor,true); } - public Signature(Method method, HashMap genericsAndBoundsMethod, - HashMap methodParamsAndTypes, ResultSet resultSet) { + public Signature(Method method, HashMap genericsAndBoundsMethod,HashMap genericsAndBounds, + HashMap methodParamsAndTypes, ResultSet resultSet, ArrayList methodPairs) { this.method = method; this.genericsAndBoundsMethod = genericsAndBoundsMethod; + this.genericsAndBounds = genericsAndBounds; this.methodParamsAndTypes = methodParamsAndTypes; this.resultSet = resultSet; + this.methodPairs = methodPairs; sw = new SignatureWriter(); createSignatureForConsOrMethod(this.method,false); } @@ -92,27 +107,101 @@ public class Signature { GenericTypeVar g = itr.next(); getBoundsOfTypeVar(g,genericsAndBoundsMethod); } + // Wenn die RückgabeType eine TPH ist, wird als generic behandelt // z.B: Type = TPH K => wird eine Formal Type Parameter K$ erzeugt und Bound = Object - String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); - if(ret.substring(0,4).equals("TPH ")) { - String g = ret.substring(4)+"$"; - sw.visitFormalTypeParameter(g); - sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); - genericsAndBoundsMethod.put(g, Type.getInternalName(Object.class)); - sw.visitClassBound().visitEnd(); + if(!isConstructor) { + String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); + System.out.println("RET:::: " + ret); + if(!ret.equals("V")) { + // TODO TypeToSignature nochmal kontrollieren und schauen ob man dort wirklich + // T... braucht und L ... + if(ret.contains("$") && !ret.contains("$$")) { +// String g = ret.substring(4,ret.length())+"$"; + if(genericsAndBounds.containsKey(ret)) { + genericsAndBoundsMethod.put(ret.substring(1), genericsAndBounds.get(ret.substring(1))); + }else { + sw.visitFormalTypeParameter(ret.substring(1)); + sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); + genericsAndBoundsMethod.put(ret.substring(1), Type.getInternalName(Object.class)); + sw.visitClassBound().visitEnd(); + } + } + + if(ret.contains("<")) { + RefType ref = (RefType) resultSet.resolveType(method.getReturnType()).resolvedType; + if(hasTPHs(ref)) { + createSignatureForParameterizedType(ref); + } + + } + } } + // Parameters for(String paramName : methodParamsAndTypes.keySet()) { RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName); String pT = t.acceptTV(new TypeToSignature()); // S.o - if(pT.substring(0,4).equals("TPH ") && !genericsAndBoundsMethod.containsKey(pT)) { - String gP = pT.substring(4)+"$"; - sw.visitFormalTypeParameter(gP); - sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); - genericsAndBoundsMethod.put(gP, Type.getInternalName(Object.class)); - sw.visitClassBound().visitEnd(); +// if(pT.substring(0,4).equals("TPH ")) { + if(t instanceof TypePlaceholder) { +// String gP = pT.substring(4,pT.length())+"$"; + String gP = t.acceptTV(new TypeToSignature()); + if(!genericsAndBounds.containsKey(gP.substring(1)) && !genericsAndBoundsMethod.containsKey(gP.substring(1))) { + sw.visitFormalTypeParameter(gP.substring(1)); + String bound = Type.getInternalName(Object.class); + boolean isTypeVar = false; + for(GenericInsertPair pair : methodPairs) { + if(pT.substring(1,pT.length()-1).equals(pair.TA1.getName())) { + bound = pair.TA2.getName()+"$"; + isTypeVar = true; + break; + } + } + + if(isTypeVar) { + sw.visitClassBound().visitTypeVariable(bound); + }else { + sw.visitClassBound().visitClassType(bound); + sw.visitClassBound().visitEnd(); + } + + genericsAndBoundsMethod.put(gP.substring(1), bound); + } + } + + if(pT.contains("<")) { + RefType ref = (RefType) methodParamsAndTypes.get(paramName); + if(hasTPHs(ref)) + createSignatureForParameterizedType(ref); + } + + for(GenericInsertPair p:methodPairs) { + String name = p.TA1.getName()+"$"; + if(!genericsAndBoundsMethod.containsKey(name)) { + sw.visitFormalTypeParameter(name); + sw.visitClassBound().visitTypeVariable(p.TA2.getName()+"$"); + genericsAndBoundsMethod.put(name, p.TA2.getName()+"$"); + } + } + + ArrayList types = new ArrayList<>(); + ArrayList superTypes = new ArrayList<>(); + + for(GenericInsertPair p : methodPairs) { + types.add(p.TA1); + superTypes.add(p.TA2); + } + + for(GenericInsertPair p : methodPairs) { + String name = p.TA2.getName()+"$"; + if(!types.contains(p.TA2) && !genericsAndBoundsMethod.containsKey(name)) { + String bound = Type.getInternalName(Object.class); + sw.visitFormalTypeParameter(name); + sw.visitClassBound().visitClassType(bound); + genericsAndBoundsMethod.put(name, bound); + sw.visitClassBound().visitEnd(); + } } } @@ -122,24 +211,156 @@ public class Signature { // parameter type deswegen ist true doVisitParamsOrReturn(t,true); } - if(isConstructor) { + if(isConstructor || + resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()).equals("V")) { sw.visitReturnType().visitBaseType('V'); }else { -// String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); -// if(ret.substring(0,4).equals("TPH ")) { -// String g = ret.substring(4); -// if(!genericsAndBoundsMethod.containsKey(g)) { -// genericsAndBoundsMethod.put(g, Type.getInternalName(Object.class)); -// } else { -// genericsAndBoundsMethod.put(g+"_", Type.getInternalName(Object.class)); -// } -// } RefTypeOrTPHOrWildcardOrGeneric returnType = method.getReturnType(); // return type deswegen ist false doVisitParamsOrReturn(returnType, false); } // sw.visitEnd(); } + + private void createSignatureForParameterizedType(RefType ref) { + ArrayList allPairs = getAllPairs(ref); + allPairs.addAll(methodPairs); + ArrayList simplifiedPairs = simplifyPairs(allPairs); + + HashMap names = new HashMap<>(); + + for(GenericInsertPair pair : simplifiedPairs) { + if(ref.getParaList().contains(pair.TA1)) { + String sub = pair.TA1.getName()+"$"; + String superT = pair.TA2.getName()+"$"; + names.put(sub, superT); + } + } + + for(String sub : names.keySet()) { + if(!genericsAndBoundsMethod.containsKey(sub) && !genericsAndBounds.containsKey(sub)) { + sw.visitFormalTypeParameter(sub); + String bound = names.get(sub); + sw.visitClassBound().visitTypeVariable(bound); + genericsAndBoundsMethod.put(sub, bound); + } + } + + for(String superT : names.values()) { + if(!names.containsKey(superT)) { + if(!genericsAndBoundsMethod.containsKey(superT) && !genericsAndBounds.containsKey(superT)) { + sw.visitFormalTypeParameter(superT); + sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); + sw.visitClassBound().visitEnd(); + genericsAndBoundsMethod.put(superT, Type.getInternalName(Object.class)); + } + } + } + + for(RefTypeOrTPHOrWildcardOrGeneric p: ref.getParaList()) { + if(p instanceof TypePlaceholder) { + String name = ((TypePlaceholder) p).getName() + "$"; + if(!genericsAndBoundsMethod.containsKey(name) && !genericsAndBounds.containsKey(name)) { + sw.visitFormalTypeParameter(name); + sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); + sw.visitClassBound().visitEnd(); + genericsAndBoundsMethod.put(name, Type.getInternalName(Object.class)); + } + } + } + } + + private ArrayList getAllPairs(RefType ref) { + final ArrayList res = new ArrayList<>(); + for(RefTypeOrTPHOrWildcardOrGeneric p : ref.getParaList()) { + RefTypeOrTPHOrWildcardOrGeneric resolved = resultSet.resolveType(p).resolvedType; + if(resolved instanceof TypePlaceholder) { + resultSet.resolveType(p).additionalGenerics.forEach(ag ->{ + if(!contains(res,ag)) { + res.add(ag); + } + }); + } + + } + return res; + } + + private boolean contains(ArrayList pairs, GenericInsertPair genPair) { + for(int i=0; i simplifyPairs(ArrayList allPairs) { + ArrayList simplifiedPairs = new ArrayList<>(); + + HashMap subAndSuperTph = new HashMap<>(); + for(GenericInsertPair p : allPairs) { + subAndSuperTph.put(p.TA1, p.TA2); + } + + subAndSuperTph.forEach((k,v)->System.out.println(k.getName() + " || " + v.getName())); + + int numOfVisitedPairs = 0; + for(TypePlaceholder subTph: subAndSuperTph.keySet()) { + + if(numOfVisitedPairs>=subAndSuperTph.size()) + break; + + HashMap tphsInRel= new HashMap<>(); + + tphsInRel.put(tphsInRel.size(), subTph); + TypePlaceholder superTph = subAndSuperTph.get(subTph); + tphsInRel.put(tphsInRel.size(), superTph); + + numOfVisitedPairs++; + + while(subAndSuperTph.containsKey(superTph)) { + superTph = subAndSuperTph.get(superTph); + tphsInRel.put(tphsInRel.size(), superTph); + numOfVisitedPairs++; + } + + // Subtype + TypePlaceholder subTphRes = tphsInRel.get(0); + // Die größte Supertype + TypePlaceholder superTphRes = tphsInRel.get(tphsInRel.size()-1); + + + while(subAndSuperTph.containsValue(subTphRes)) { + for(TypePlaceholder tph : subAndSuperTph.keySet()) { + if(subAndSuperTph.get(tph).equals(subTphRes)) { + subTphRes = tph; + break; + } + } + tphsInRel.put(0, subTphRes); + numOfVisitedPairs++; + } + + subTphRes = tphsInRel.get(0); + GenericInsertPair sPair = new GenericInsertPair(subTphRes, superTphRes); + simplifiedPairs.add(sPair); + } + return simplifiedPairs; + } + + private boolean hasTPHs(RefType ref) { + for(RefTypeOrTPHOrWildcardOrGeneric p : ref.getParaList()) { + System.out.println(p.acceptTV(new TypeToString())); + if(p.acceptTV(new TypeToString()).contains("WC")){ + continue; + } + if(resultSet.resolveType(p).resolvedType instanceof TypePlaceholder) + return true; + } + return false; + } + /** * Visits parameter type or return type with {@link SignatureVisitor} to create * the method signature @@ -157,24 +378,34 @@ public class Signature { } switch (type) { case "RT": - sv.visitClassType(t.acceptTV(new TypeToSignature())); + String sig = t.acceptTV(new TypeToSignature()); + sv.visitClassType(sig.substring(1, sig.length())); break; case "GRT": GenericRefType g = (GenericRefType) t; - sv.visitTypeVariable(g.acceptTV(new TypeToSignature())); + sv.visitTypeVariable(g.acceptTV(new TypeToSignature()).substring(1)); break; case "TPH": RefTypeOrTPHOrWildcardOrGeneric r = resultSet.resolveType(t).resolvedType; // der Fall wenn die Type eine Interface ist, muss betrachtet werden // Deswegen muss in ResutSet noch enthalten werden, ob die Type eine // Interface oder eine Klasse ist. - if(!r.acceptTV(new TypeToSignature()).substring(0, 4).equals("TPH ")) { + + // das braucht man nicht es reicht: sv.visitTypeVariable(r.acceptTV(new TypeToSignature()) + // +// if(!r.acceptTV(new TypeToSignature()).substring(0, 4).equals("TPH ")) { + String sig2 = r.acceptTV(new TypeToSignature()); + if(!(r instanceof TypePlaceholder)) { + // sv.visitInterface().visitClassType(r.acceptTV(new TypeToSignature())); - sv.visitClassType(r.acceptTV(new TypeToSignature())); +// sv.visitClassType(r.acceptTV(new TypeToSignature())); + sv.visitClassType(sig2.substring(1, sig2.length())); } else { System.out.println(r.getClass()+" Signature TPH: "+r.acceptTV(new TypeToSignature())); - sv.visitTypeVariable(r.acceptTV(new TypeToSignature()).substring(4)+"$"); +// sv.visitTypeVariable(r.acceptTV(new TypeToSignature()).substring(4)+"$"); + sv.visitTypeVariable(sig2.substring(1, sig2.length())); } + break; default: if(!isParameterType) @@ -194,8 +425,36 @@ public class Signature { GenericTypeVar g = itr.next(); getBoundsOfTypeVar(g,genericsAndBounds); } - - sw.visitSuperclass().visitClassType(classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()));; + if(!commonPairs.isEmpty()) { + ArrayList types = new ArrayList<>(); + ArrayList superTypes = new ArrayList<>(); + + for(GenericInsertPair p : commonPairs) { + types.add(p.TA1); + superTypes.add(p.TA2); + } + + for(GenericInsertPair p : commonPairs) { + String t = p.TA1.getName()+"$"; + String bound = p.TA2.getName()+"$"; + sw.visitFormalTypeParameter(t); + sw.visitClassBound().visitTypeVariable(bound); + genericsAndBounds.put(t, bound); + } + + for(GenericInsertPair p : commonPairs) { + if(!types.contains(p.TA2)) { + String t = p.TA2.getName()+"$"; + String bound = Type.getInternalName(Object.class); + sw.visitFormalTypeParameter(t); + sw.visitClassBound().visitClassType(bound); + genericsAndBounds.put(t, bound); + sw.visitClassBound().visitEnd(); + } + } + } + String sClass = classOrInterface.getSuperClass().acceptTV(new TypeToSignature()); + sw.visitSuperclass().visitClassType(sClass.substring(1, sClass.length()-1)); sw.visitEnd(); } /** diff --git a/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java b/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java index a1357d4c..785bfabe 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java +++ b/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java @@ -15,6 +15,8 @@ public class TypeToSignature implements TypeVisitor { @Override public String visit(RefType refType) { + if(refType.getName().toString().equals("void")) + return "V"; // return refType.toString().replace(".", "/"); String params = ""; if(refType.getParaList().size()>0){ @@ -22,29 +24,41 @@ public class TypeToSignature implements TypeVisitor { Iterator it = refType.getParaList().iterator(); while(it.hasNext()){ RefTypeOrTPHOrWildcardOrGeneric param = it.next(); - params += "L"+param.toString().replace(".", "/"); - if(it.hasNext())params += ";"; +// if(param instanceof TypePlaceholder) { +// params += "T" + ((TypePlaceholder) param).getName() + "$"; +// } else if(param instanceof ExtendsWildcardType) { +// params += "+" + ((ExtendsWildcardType) param).getInnerType().acceptTV(new TypeToSignature()); +// } else if(param instanceof SuperWildcardType) { +// params += "-" + ((SuperWildcardType) param).getInnerType().acceptTV(new TypeToSignature()); +// } else { +// params += "L"+param.toString().replace(".", "/"); +// } + params += param.acceptTV(new TypeToSignature()); +// if(it.hasNext())params += ";"; } - params += ";>"; + params += ">"; } // String t = refType.getName().toString().replace(".", "/"); // return t.equals("Fun1")?t+"$$"+params+";":t+params+";"; - return refType.getName().toString().replace(".", "/") + params+";"; + return "L"+refType.getName().toString().replace(".", "/") + params+";"; } @Override public String visit(SuperWildcardType superWildcardType) { - throw new NotImplementedException(); +// throw new NotImplementedException(); + return "-" + superWildcardType.getInnerType().acceptTV(new TypeToSignature()); } @Override public String visit(TypePlaceholder typePlaceholder) { - return typePlaceholder.toString().replace(".", "/"); +// return typePlaceholder.toString().replace(".", "/"); + return "T" + typePlaceholder.getName() + "$"; } @Override public String visit(ExtendsWildcardType extendsWildcardType) { - throw new NotImplementedException(); +// throw new NotImplementedException(); + return "+" + extendsWildcardType.getInnerType().acceptTV(new TypeToSignature()); } @Override diff --git a/src/de/dhbwstuttgart/bytecode/signature/TypeToString.java b/src/de/dhbwstuttgart/bytecode/signature/TypeToString.java index 94314afe..a0e280c2 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/TypeToString.java +++ b/src/de/dhbwstuttgart/bytecode/signature/TypeToString.java @@ -17,7 +17,7 @@ public class TypeToString implements TypeVisitor{ @Override public String visit(SuperWildcardType superWildcardType) { - throw new NotImplementedException(); + return "SWC"; } @Override @@ -27,7 +27,7 @@ public class TypeToString implements TypeVisitor{ @Override public String visit(ExtendsWildcardType extendsWildcardType) { - throw new NotImplementedException(); + return "EWC"; } @Override diff --git a/src/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java b/src/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java new file mode 100644 index 00000000..99ec3163 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java @@ -0,0 +1,29 @@ +package de.dhbwstuttgart.bytecode.utilities; + +import java.util.ArrayList; + +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.result.GenericInsertPair; + +public class MethodAndTPH { + + private String name; + private final ArrayList tphs = new ArrayList<>(); + private final ArrayList pairs = new ArrayList<>(); + + public MethodAndTPH(String name) { + this.name = name; + } + + public ArrayList getTphs() { + return tphs; + } + + public ArrayList getPairs(){ + return pairs; + } + + public String getName() { + return name; + } +} diff --git a/src/de/dhbwstuttgart/bytecode/utilities/MethodFromMethodCall.java b/src/de/dhbwstuttgart/bytecode/utilities/MethodFromMethodCall.java index cd8f5372..2028c772 100644 --- a/src/de/dhbwstuttgart/bytecode/utilities/MethodFromMethodCall.java +++ b/src/de/dhbwstuttgart/bytecode/utilities/MethodFromMethodCall.java @@ -9,13 +9,16 @@ import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; public class MethodFromMethodCall { private ArgumentList argList; private RefTypeOrTPHOrWildcardOrGeneric returnType; + private String receiverName; private HashMap genericsAndBoundsMethod; private HashMap genericsAndBounds; - public MethodFromMethodCall(ArgumentList argList,RefTypeOrTPHOrWildcardOrGeneric returnType, - HashMap genericsAndBoundsMethod,HashMap genericsAndBounds) { + public MethodFromMethodCall(ArgumentList argList,RefTypeOrTPHOrWildcardOrGeneric returnType, + String receiverName, HashMap genericsAndBoundsMethod, + HashMap genericsAndBounds) { this.argList = argList; this.returnType = returnType; + this.receiverName = receiverName; this.genericsAndBoundsMethod = genericsAndBoundsMethod; this.genericsAndBounds = genericsAndBounds; } @@ -28,6 +31,10 @@ public class MethodFromMethodCall { return returnType; } + public String getReceiverName() { + return receiverName; + } + public HashMap getGenericsAndBoundsMethod(){ return genericsAndBoundsMethod; } diff --git a/src/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/de/dhbwstuttgart/core/JavaTXCompiler.java index 8646b484..ffa8d54d 100644 --- a/src/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -240,25 +240,26 @@ public class JavaTXCompiler { SourceFile ret = generator.convert(tree, environment.packageCrawler); return ret; } - - public void generateBytecode() throws ClassNotFoundException, IOException { + // um pfad erweitern + public void generateBytecode(String path) 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,sf,path); // BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult.get(0)); bytecodeGen.visit(sf); - this.writeClassFile(bytecodeGen.getClassFiles()); + this.writeClassFile(bytecodeGen.getClassFiles(), path); } } - private void writeClassFile(HashMap classFiles) throws IOException { + private void writeClassFile(HashMap classFiles, String path) 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 = new FileOutputStream(new File(System.getProperty("user.dir") + "/testBytecode/generatedBC/" +name+".class")); + output = new FileOutputStream(new File(path +name+".class")); output.write(bytecode); output.close(); System.out.println(name+".class file generated"); diff --git a/src/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java b/src/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java index b05dd0ee..71985334 100644 --- a/src/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java +++ b/src/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java @@ -208,7 +208,7 @@ public class UnifyTypeFactory { } public static RefTypeOrTPHOrWildcardOrGeneric convert(FunNType t, Map tphs) { - RefType ret = new RefType(new JavaClassName(t.getName()), convert(t.getTypeParams(), tphs), new NullToken()); + RefType ret = new RefType(new JavaClassName(t.getName()+"$$"), convert(t.getTypeParams(), tphs), new NullToken()); return ret; } diff --git a/src/de/dhbwstuttgart/syntaxtree/type/FunN.java b/src/de/dhbwstuttgart/syntaxtree/type/FunN.java index 84fe1ace..46de6566 100644 --- a/src/de/dhbwstuttgart/syntaxtree/type/FunN.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/FunN.java @@ -24,7 +24,7 @@ public class FunN extends RefType { * @return */ public FunN(List params) { - super(new JavaClassName("Fun"+params.size()), params, new NullToken()); + super(new JavaClassName("Fun"+(params.size())), params, new NullToken()); } /** diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/FunNClass.java b/src/de/dhbwstuttgart/typeinference/assumptions/FunNClass.java index 3518c16a..0c8220f1 100644 --- a/src/de/dhbwstuttgart/typeinference/assumptions/FunNClass.java +++ b/src/de/dhbwstuttgart/typeinference/assumptions/FunNClass.java @@ -8,32 +8,36 @@ import de.dhbwstuttgart.syntaxtree.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; import de.dhbwstuttgart.syntaxtree.factory.NameGenerator; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + import org.antlr.v4.runtime.Token; import java.util.ArrayList; import java.util.List; public class FunNClass extends ClassOrInterface { - public FunNClass(List funNParams) { - super(0, new JavaClassName("Fun"+(funNParams.size()-1)), new ArrayList<>(), + public FunNClass(List funNParams) { + super(0, new JavaClassName("Fun"+(funNParams.size())), new ArrayList<>(), createMethods(funNParams), new ArrayList<>(), createGenerics(funNParams), ASTFactory.createObjectType(), true, new ArrayList<>(), new NullToken()); } - private static GenericDeclarationList createGenerics(List funNParams) { + private static GenericDeclarationList createGenerics(List funNParams) { + //PL 2018-06-22: so geaendert, dass generierte Generics den Namen der funParams entsprechen. List generics = new ArrayList<>(); - for(RefTypeOrTPHOrWildcardOrGeneric param : funNParams){ - generics.add(new GenericTypeVar(NameGenerator.makeNewName(), + for(GenericRefType param : funNParams){ + generics.add(new GenericTypeVar(param.getParsedName(),//NameGenerator.makeNewName(), new ArrayList<>(), new NullToken(), new NullToken())); } return new GenericDeclarationList(generics, new NullToken()); } - private static List createMethods(List funNParams) { + private static List createMethods(List funNParams) { return null; } } diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java b/src/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java index e17281e5..294c8507 100644 --- a/src/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java +++ b/src/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java @@ -16,10 +16,10 @@ import java.util.List; public class MethodAssumption extends Assumption{ private ClassOrInterface receiver; private RefTypeOrTPHOrWildcardOrGeneric retType; - List params; + List params; public MethodAssumption(ClassOrInterface receiver, RefTypeOrTPHOrWildcardOrGeneric retType, - List params, TypeScope scope){ + List params, TypeScope scope){ super(scope); this.receiver = receiver; this.retType = retType; @@ -38,7 +38,9 @@ public class MethodAssumption extends Assumption{ } public RefTypeOrTPHOrWildcardOrGeneric getReturnType(GenericsResolver resolver) { - if(retType instanceof GenericRefType)return resolver.resolve(retType); + if(retType instanceof GenericRefType) { + return resolver.resolve(retType); + } return retType; } diff --git a/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index 6b9f4919..68907c56 100644 --- a/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -6,6 +6,7 @@ import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.syntaxtree.factory.NameGenerator; import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption; @@ -222,50 +223,75 @@ public class TYPEStmt implements StatementVisitor{ //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 - 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); + Constraint numeric; + //PL eingefuegt 2018-07-17 + if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(bytee.getName())) { + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), bytee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), bytee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), integer, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + } + //PL eingefuegt 2018-07-17 + if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(shortt.getName())) { + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), shortt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), shortt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), integer, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + } + //PL eingefuegt 2018-07-17 + if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(integer.getName())) { + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), integer, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), integer, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), integer, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + } + //PL eingefuegt 2018-07-17 + if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(longg.getName())) { + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), longg, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), longg, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), longg, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + } + //PL eingefuegt 2018-07-17 + if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(floatt.getName())) { + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), floatt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), floatt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), floatt, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + } + //PL eingefuegt 2018-07-17 + if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(doublee.getName())) { + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), doublee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), doublee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), doublee, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + } + /* PL auskommentiert Anfang 2018-07-17 /* 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 Das bedeutet, dass Java die Typen je nach belieben castet, so lange sie nur von Number erben - */ + + numeric = new Constraint<>(); numeric.add(new Pair(binary.getType(), number, PairOperator.SMALLERDOT)); numericAdditionOrStringConcatenation.add(numeric); + * PL auskommentiert Ende 2018-07-17 */ + if(binary.operation.equals(BinaryExpr.Operator.ADD)) { //Dann kann der Ausdruck auch das aneinanderfügen zweier Strings sein: ("a" + "b") oder (1 + 2) - Constraint stringConcat = new Constraint<>(); - stringConcat.add(new Pair(binary.lexpr.getType(), string, PairOperator.EQUALSDOT)); - stringConcat.add(new Pair(binary.rexpr.getType(), string, PairOperator.EQUALSDOT)); - stringConcat.add(new Pair(binary.getType(), string, PairOperator.EQUALSDOT)); - numericAdditionOrStringConcatenation.add(stringConcat); + if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(string.getName())) { + Constraint stringConcat = new Constraint<>(); + stringConcat.add(new Pair(binary.lexpr.getType(), string, PairOperator.EQUALSDOT)); + stringConcat.add(new Pair(binary.rexpr.getType(), string, PairOperator.EQUALSDOT)); + stringConcat.add(new Pair(binary.getType(), string, PairOperator.EQUALSDOT)); + numericAdditionOrStringConcatenation.add(stringConcat); + } } constraintsSet.addOderConstraint(numericAdditionOrStringConcatenation); }else if(binary.operation.equals(BinaryExpr.Operator.LESSEQUAL) || @@ -327,7 +353,16 @@ public class TYPEStmt implements StatementVisitor{ @Override public void visit(Literal literal) { - //Nothing to do here. Literale erzeugen keine Constraints + //Nothing to do here. Literale erzeugen keine Constraints + //PL 2018-06-23 Sie haben einen Typ. Der muesste hier eingefuegt werden + //wie hier fuer double gezeigt. Im Momment auskommentiert, weil zu wenige Literaltypen + //funktionieren + //if (literal.value instanceof Double) { + // constraintsSet.addUndConstraint(new Pair(literal.getType(), doublee, PairOperator.EQUALSDOT)); + //} + //else { + // throw new NotImplementedException(); + //} } @Override @@ -451,11 +486,14 @@ public class TYPEStmt implements StatementVisitor{ List ret = new ArrayList<>(); //TODO: apply Methoden wieder anfügen. Diese könnten möglicherweise auch in den Assumptions auftauchen (überdenken) if(name.equals("apply")){ - List funNParams = new ArrayList<>(); + List funNParams = new ArrayList<>(); for(int i = 0; i< numArgs + 1 ; i++){ - funNParams.add(TypePlaceholder.fresh(new NullToken())); + //funNParams.add(TypePlaceholder.fresh(new NullToken())); + funNParams.add(new GenericRefType(NameGenerator.makeNewName(), + new NullToken())); } - ret.add(new MethodAssumption(new FunNClass(funNParams), funNParams.get(0), funNParams.subList(1, funNParams.size()), + funNParams.get(funNParams.size()-1); + ret.add(new MethodAssumption(new FunNClass(funNParams), funNParams.get(funNParams.size()-1), funNParams.subList(0, funNParams.size()-1), new TypeScope() { @Override public Iterable getGenerics() { @@ -498,7 +536,7 @@ public class TYPEStmt implements StatementVisitor{ */ List params = new ArrayList<>(); for(FormalParameter fp : parameterList.getFormalparalist()){ - params.add(info.checkGTV(fp.getType())); + params.add(fp.getType()); //info.checkGTV(fp.getType())); //PL 2018-06-22 GTV sollen in Argumenten erhalten bleiben } return params; } diff --git a/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java b/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java index b40dee30..6c3cfaad 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java +++ b/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java @@ -938,7 +938,9 @@ public class RuleSet implements IRuleSet{ else { UnifyType freshTph = PlaceholderType.freshPlaceholder(); 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())); + Set fBounded = pair.getfBounded(); + fBounded.add(lhsType); + result.add(new UnifyPair(freshTph, superedType, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair(), fBounded)); } return Optional.of(result); diff --git a/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java b/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java index 0545fb95..e38e1443 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java +++ b/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java @@ -13,6 +13,7 @@ import java.util.Map.Entry; import java.util.Optional; import java.util.Set; import java.util.concurrent.RecursiveTask; +import java.util.function.BiFunction; import java.util.function.BinaryOperator; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -144,12 +145,12 @@ public class TypeUnifyTask extends RecursiveTask>> { * @return The set of all principal type unifiers */ 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(""); - } + //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 */ @@ -447,6 +448,7 @@ public class TypeUnifyTask extends RecursiveTask>> { System.out.print(""); if (nextSetasList.iterator().next().stream().filter(x -> x.getLhsType().getName().equals("D")).findFirst().isPresent() && nextSetasList.size()>1) System.out.print(""); + writeLog("nextSetasList: " + nextSetasList.toString()); while (nextSetasList.size() > 0) { //(nextSetasList.size() != 0) { Set a = null; if (variance == 1) { @@ -488,6 +490,7 @@ public class TypeUnifyTask extends RecursiveTask>> { 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 + //writeLog("Vor unify2 Aufruf: " + eq.toString()); Set> res = unify2(elems, eq, fc, parallel); if (!isUndefinedPairSetSet(res) && isUndefinedPairSetSet(result)) { //wenn korrektes Ergebnis gefunden alle Fehlerfaelle loeschen @@ -512,7 +515,8 @@ public class TypeUnifyTask extends RecursiveTask>> { //else {//duerfte gar nicht mehr vorkommen PL 2018-04-03 //result.addAll(computeCartesianRecursive(elems, remainingSets, eq, fc, parallel)); //} - + + /* auskommentiert um alle Max und min Betrachtung auszuschalten ANFANG */ if (!result.isEmpty() && !isUndefinedPairSetSet(res)) { if (nextSetasList.iterator().hasNext() && nextSetasList.iterator().next().stream().filter(x -> x.getLhsType().getName().equals("D")).findFirst().isPresent() && nextSetasList.size()>1) System.out.print(""); @@ -542,6 +546,8 @@ public class TypeUnifyTask extends RecursiveTask>> { } } } + /* auskommentiert um alle Max und min Betrachtung auszuschalten ENDE */ + if (isUndefinedPairSetSet(res)) { Set abhSubst = res.stream() .map(b -> @@ -1094,7 +1100,7 @@ public class TypeUnifyTask extends RecursiveTask>> { UnifyType supAPrime = new SuperType(aPrime); UnifyType thetaPrime = subThetaPrime.getSuperedType(); Set resultPrime = new HashSet<>(); - resultPrime.add(new UnifyPair(thetaPrime, a, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(thetaPrime, a, PairOperator.SMALLERDOT, pair.getSubstitution(), pair, pair.getfBounded())); result.add(resultPrime); //writeLog(resultPrime.toString()); @@ -1124,14 +1130,34 @@ public class TypeUnifyTask extends RecursiveTask>> { break; } - for(UnifyType thetaS : fc.greater(theta, new HashSet<>())) { + for(UnifyType thetaS : fc.greater(theta, pair.getfBounded())) { Set resultPrime = new HashSet<>(); + Match match = new Match(); UnifyType[] freshTphs = new UnifyType[thetaS.getTypeParams().size()]; for(int i = 0; !allGen && i < freshTphs.length; i++) { freshTphs[i] = PlaceholderType.freshPlaceholder(); ((PlaceholderType)freshTphs[i]).setVariance(((PlaceholderType)a).getVariance()); - resultPrime.add(new UnifyPair(thetaS.getTypeParams().get(i), freshTphs[i], PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair)); + Set fBounded = pair.getfBounded(); + + int i_ef = i; + BiFunction f = (x,y) -> + { + ArrayList termList = new ArrayList(); + termList.add(new UnifyPair(y,thetaS.getTypeParams().get(i_ef), PairOperator.EQUALSDOT)); + return ((match.match(termList).isPresent()) || x); + }; + //if (parai.getName().equals("java.lang.Integer")) { + // System.out.println(""); + //} + BinaryOperator bo = (x,y) -> (x || y); + if (fBounded.stream().reduce(false,f,bo)) { + resultPrime.add(new UnifyPair(thetaS.getTypeParams().get(i), freshTphs[i], PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + } + else { + fBounded.add(thetaS.getTypeParams().get(i)); + resultPrime.add(new UnifyPair(thetaS.getTypeParams().get(i), freshTphs[i], PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair, fBounded)); + } } if(allGen) @@ -1165,9 +1191,9 @@ public class TypeUnifyTask extends RecursiveTask>> { ((PlaceholderType)freshTph).setVariance(a.getVariance()); resultPrime = new HashSet<>(); resultPrime.add(new UnifyPair(a, new ExtendsType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); - resultPrime.add(new UnifyPair(theta, freshTph, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(theta, freshTph, PairOperator.SMALLERDOT, pair.getSubstitution(), pair, pair.getfBounded())); result.add(resultPrime); - //writeLog(resultPrime.toString()); + //writeLog("resultPrime: " + resultPrime.toString()); resultPrime = new HashSet<>(); resultPrime.add(new UnifyPair(a, new SuperType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java b/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java index 8f594844..f2bc5277 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java @@ -102,7 +102,7 @@ public class Unifier implements Function, Iterable fBounded = new HashSet<>(); private final int hashCode; @@ -82,6 +89,12 @@ public class UnifyPair { hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode(); } + public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, Set uni, UnifyPair base, Set fBounded) { + this(lhs, rhs, op, uni, base); + + this.fBounded = fBounded; + } + /** * Returns the type on the left hand side of the pair. */ @@ -138,6 +151,10 @@ public class UnifyPair { return lhs.wrongWildcard() || rhs.wrongWildcard(); } + public Set getfBounded() { + return this.fBounded; + } + @Override public boolean equals(Object obj) { if(!(obj instanceof UnifyPair)) @@ -177,7 +194,7 @@ public class UnifyPair { if (rhs instanceof PlaceholderType) { ret = ret + ", " + new Integer(((PlaceholderType)rhs).getVariance()).toString(); } - return "(" + lhs + " " + pairOp + " " + rhs + ", " + ret + ")"; + return "(" + lhs + " " + pairOp + " " + rhs + ", " + ret + ", [" + getfBounded().toString()+ "])"; } /* diff --git a/test/bytecode/BinaryTest.java b/test/bytecode/BinaryTest.java index 7f2f5fa4..07a70d54 100644 --- a/test/bytecode/BinaryTest.java +++ b/test/bytecode/BinaryTest.java @@ -25,8 +25,8 @@ public class BinaryTest { path = System.getProperty("user.dir")+"/test/bytecode/javFiles/BinaryInMeth.jav"; fileToTest = new File(path); compiler = new JavaTXCompiler(fileToTest); - compiler.generateBytecode(); pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); classToTest = loader.loadClass("BinaryInMeth"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); diff --git a/test/bytecode/FacTest.java b/test/bytecode/FacTest.java index 0875db05..f5dd86ea 100644 --- a/test/bytecode/FacTest.java +++ b/test/bytecode/FacTest.java @@ -27,8 +27,8 @@ public class FacTest { path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Fac.jav"; fileToTest = new File(path); compiler = new JavaTXCompiler(fileToTest); - compiler.generateBytecode(); pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); classToTest = loader.loadClass("Fac"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); @@ -37,8 +37,8 @@ public class FacTest { @Test public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Method getFac = classToTest.getDeclaredMethod("getFac", Integer.class); - Integer result = (Integer) getFac.invoke(instanceOfClass,3); - assertEquals(result, 6); + Double result = (Double) getFac.invoke(instanceOfClass,3); + assertEquals(result, 6.0); } } diff --git a/test/bytecode/GenTest.java b/test/bytecode/GenTest.java index d0067d08..e8ca6938 100644 --- a/test/bytecode/GenTest.java +++ b/test/bytecode/GenTest.java @@ -26,8 +26,8 @@ public class GenTest { 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/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); classToTest = loader.loadClass("Gen"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); diff --git a/test/bytecode/GreaterEqualTest.java b/test/bytecode/GreaterEqualTest.java index c65a4015..b60c446c 100644 --- a/test/bytecode/GreaterEqualTest.java +++ b/test/bytecode/GreaterEqualTest.java @@ -28,8 +28,8 @@ public class GreaterEqualTest { 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/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("File://"+pathToClassFile)}); classToTest = loader.loadClass("GreaterEqual"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); diff --git a/test/bytecode/GreaterThanTest.java b/test/bytecode/GreaterThanTest.java index 8ab07ff1..1a460a8c 100644 --- a/test/bytecode/GreaterThanTest.java +++ b/test/bytecode/GreaterThanTest.java @@ -28,8 +28,8 @@ public class GreaterThanTest { 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/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("File://"+pathToClassFile)}); classToTest = loader.loadClass("GreaterThan"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); diff --git a/test/bytecode/LambdaTest.java b/test/bytecode/LambdaTest.java index f29690cb..5ec28970 100644 --- a/test/bytecode/LambdaTest.java +++ b/test/bytecode/LambdaTest.java @@ -1,6 +1,12 @@ package bytecode; +import static org.junit.Assert.assertEquals; + import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; import org.junit.Test; @@ -10,13 +16,31 @@ public class LambdaTest { private static String path; private static File fileToTest; private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; @Test public void generateBC() throws Exception { path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Lambda.jav"; fileToTest = new File(path); compiler = new JavaTXCompiler(fileToTest); - compiler.generateBytecode(); + compiler.generateBytecode(System.getProperty("user.dir")+"/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Lambda"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + Method m = classToTest.getDeclaredMethod("m"); + Class lambda = m.invoke(instanceOfClass).getClass(); + Method apply = lambda.getMethod("apply", Object.class); + apply.setAccessible(true); + + Integer i = 77; + // result = 77*77 = 5929 + Integer result = (Integer) apply.invoke(m.invoke(instanceOfClass), i); + assertEquals(5929, result); } diff --git a/test/bytecode/LessEqualTest.java b/test/bytecode/LessEqualTest.java index de9cdb8c..dc439af9 100644 --- a/test/bytecode/LessEqualTest.java +++ b/test/bytecode/LessEqualTest.java @@ -28,8 +28,8 @@ public class LessEqualTest { 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/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); classToTest = loader.loadClass("LessEqual"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); diff --git a/test/bytecode/LessThanTest.java b/test/bytecode/LessThanTest.java index 6846f820..99eba80c 100644 --- a/test/bytecode/LessThanTest.java +++ b/test/bytecode/LessThanTest.java @@ -28,8 +28,8 @@ public class LessThanTest { 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/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); classToTest = loader.loadClass("LessThan"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); diff --git a/test/bytecode/MatrixTest.java b/test/bytecode/MatrixTest.java index 98884151..325cc1d8 100644 --- a/test/bytecode/MatrixTest.java +++ b/test/bytecode/MatrixTest.java @@ -3,8 +3,12 @@ package bytecode; import static org.junit.Assert.*; import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; +import java.util.Vector; import org.junit.BeforeClass; import org.junit.Test; @@ -18,23 +22,70 @@ public class MatrixTest { private static ClassLoader loader; private static Class classToTest; private static String pathToClassFile; - private static Object instanceOfClass; - - @BeforeClass - public static void setUpBeforeClass() throws Exception { + private static Object instanceOfClass_m1; + private static Object instanceOfClass_m2; + private static Object instanceOfClass_m3; + + @Test + public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, IOException, InstantiationException { path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Matrix.jav"; fileToTest = new File(path); compiler = new JavaTXCompiler(fileToTest); - compiler.generateBytecode(); pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); - classToTest = loader.loadClass("Matrix"); - instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); - } + classToTest = loader.loadClass("Matrix"); + + Vector> vv = new Vector>(); + Vector v1 = new Vector (); + v1.addElement(2); + v1.addElement(2); + Vector v2 = new Vector (); + v2.addElement(3); + v2.addElement(3); + //Matrix m1 = new Matrix(); + //m1.addElement(v1); + //m1.addElement(v2); + vv.addElement(v1); + vv.addElement(v2); + instanceOfClass_m1 = classToTest.getDeclaredConstructor(Vector.class).newInstance(vv); //Matrix m1 = new Matrix(vv); - @Test - public void test() { - fail("Not yet implemented"); + Vector> vv1 = new Vector>(); + Vector v3 = new Vector (); + v3.addElement(2); + v3.addElement(2); + Vector v4 = new Vector (); + v4.addElement(3); + v4.addElement(3); + //Matrix m2 = new Matrix(); + //m2.addElement(v3); + //m2.addElement(v4); + vv1.addElement(v3); + vv1.addElement(v4); + instanceOfClass_m2 = classToTest.getDeclaredConstructor(Vector.class).newInstance(vv1);//Matrix m2 = new Matrix(vv1); + + + + //Matrix m3 = m1.mul(vv1); + Method mul = classToTest.getDeclaredMethod("mul", Vector.class); + Object result = mul.invoke(instanceOfClass_m1, instanceOfClass_m2); + System.out.println(instanceOfClass_m1.toString() + " * " + instanceOfClass_m1.toString() + " = " + result.toString()); + + Vector> res = new Vector>(); + Vector v5 = new Vector (); + v5.addElement(10); + v5.addElement(10); + Vector v6 = new Vector (); + v6.addElement(15); + v6.addElement(15); + //Matrix m2 = new Matrix(); + //m2.addElement(v3); + //m2.addElement(v4); + res.addElement(v5); + res.addElement(v6); + instanceOfClass_m3 = classToTest.getDeclaredConstructor(Vector.class).newInstance(res); + assertEquals(result, instanceOfClass_m3); + } } diff --git a/test/bytecode/OLTest.java b/test/bytecode/OLTest.java index ff91073e..d6ab4dd1 100644 --- a/test/bytecode/OLTest.java +++ b/test/bytecode/OLTest.java @@ -3,6 +3,8 @@ 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; @@ -17,23 +19,74 @@ public class OLTest { private static JavaTXCompiler compiler; private static ClassLoader loader; private static Class classToTest; + private static Class classToTest1; private static String pathToClassFile; private static Object instanceOfClass; + private static Object instanceOfClass1; @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/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); classToTest = loader.loadClass("OL"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + classToTest1 = loader.loadClass("OLMain"); + instanceOfClass1 = classToTest1.getDeclaredConstructor().newInstance(); } + @Test - public void test() { - fail("Not yet implemented"); + public void testOLClassName() { + assertEquals("OL", classToTest.getName()); + } + + @Test + public void testmInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", Integer.class); + Integer result = (Integer) m.invoke(instanceOfClass, 5); + assertEquals(10, result); + } + + @Test + public void testmDouble() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", Double.class); + Double result = (Double) m.invoke(instanceOfClass, 5.0); + assertEquals(10.0, result); + } + + @Test + public void testmString() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", String.class); + String result = (String) m.invoke(instanceOfClass, "xxx"); + assertEquals("xxxxxx", result); + } + + @Test + public void testOLMainClassName() { + assertEquals("OLMain", classToTest1.getName()); + } + + @Test + public void testmainInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest1.getDeclaredMethod("main", Integer.class); + Integer result = (Integer) main.invoke(instanceOfClass1, 5); + assertEquals(10, result); + } + + @Test + public void testmainDouble() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest1.getDeclaredMethod("main", Double.class); + Double result = (Double) main.invoke(instanceOfClass1, 5.0); + assertEquals(10.0, result); + } + + @Test + public void testmainString() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest1.getDeclaredMethod("main", String.class); + String result = (String) main.invoke(instanceOfClass1, "xxx"); + assertEquals("xxxxxx", result); } - } diff --git a/test/bytecode/OpTest.java b/test/bytecode/OpTest.java index 1d213a78..3909f0cd 100644 --- a/test/bytecode/OpTest.java +++ b/test/bytecode/OpTest.java @@ -28,8 +28,8 @@ public class OpTest { 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/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); classToTest = loader.loadClass("Op"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); diff --git a/test/bytecode/OverloadingTest.java b/test/bytecode/OverloadingTest.java index 294bf533..6b4bf8eb 100644 --- a/test/bytecode/OverloadingTest.java +++ b/test/bytecode/OverloadingTest.java @@ -30,8 +30,8 @@ public class OverloadingTest { 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/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); classToTest = loader.loadClass("Overloading"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); diff --git a/test/bytecode/PlusTest.java b/test/bytecode/PlusTest.java index 51503c58..85f05b75 100644 --- a/test/bytecode/PlusTest.java +++ b/test/bytecode/PlusTest.java @@ -27,9 +27,8 @@ public class PlusTest { 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/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); classToTest = loader.loadClass("Plus"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); diff --git a/test/bytecode/PostIncTest.java b/test/bytecode/PostIncTest.java index 36e63816..6c3ebc33 100644 --- a/test/bytecode/PostIncTest.java +++ b/test/bytecode/PostIncTest.java @@ -27,8 +27,8 @@ public class PostIncTest { 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/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); classToTest = loader.loadClass("PostIncDec"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); diff --git a/test/bytecode/PreIncTest.java b/test/bytecode/PreIncTest.java index 434b88e1..29feac33 100644 --- a/test/bytecode/PreIncTest.java +++ b/test/bytecode/PreIncTest.java @@ -27,8 +27,8 @@ public class PreIncTest { 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/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("file://" + pathToClassFile)}); classToTest = loader.loadClass("PreInc"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); diff --git a/test/bytecode/RelOpsTest.java b/test/bytecode/RelOpsTest.java index 06b24630..1bdf1a1d 100644 --- a/test/bytecode/RelOpsTest.java +++ b/test/bytecode/RelOpsTest.java @@ -27,8 +27,8 @@ public class RelOpsTest { path = System.getProperty("user.dir")+"/test/bytecode/javFiles/RelOps.jav"; fileToTest = new File(path); compiler = new JavaTXCompiler(fileToTest); - compiler.generateBytecode(); pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); classToTest = loader.loadClass("RelOps"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); diff --git a/test/bytecode/StaticTest.java b/test/bytecode/StaticTest.java index f639645c..98642b4e 100644 --- a/test/bytecode/StaticTest.java +++ b/test/bytecode/StaticTest.java @@ -26,8 +26,8 @@ public class StaticTest { 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/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("file://" + pathToClassFile)}); classToTest = loader.loadClass("StaticM"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); diff --git a/test/bytecode/SubMatTest.java b/test/bytecode/SubMatTest.java new file mode 100644 index 00000000..8818bd40 --- /dev/null +++ b/test/bytecode/SubMatTest.java @@ -0,0 +1,27 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class SubMatTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static String pathToClassFile; + + @Test + public void test() throws ClassNotFoundException, IOException { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/SubMatrix.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + } + +} diff --git a/test/bytecode/Tph2Test.java b/test/bytecode/Tph2Test.java new file mode 100644 index 00000000..f267f45a --- /dev/null +++ b/test/bytecode/Tph2Test.java @@ -0,0 +1,69 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +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 Tph2Test { + + 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/Tph2.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Tph2"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test1() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1,2); + + assertEquals(1,result); + } + + @Test + public void test2() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, "sss",2); + + assertEquals("sss",result); + } + + @Test + public void test3() throws Exception { + Method m = classToTest.getDeclaredMethod("m2", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1,2); + + assertEquals(2,result); + } + + @Test + public void test4() throws Exception { + Method m = classToTest.getDeclaredMethod("m2", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1,"xxx"); + + assertEquals("xxx",result); + } + +} diff --git a/test/bytecode/Tph3Test.java b/test/bytecode/Tph3Test.java new file mode 100644 index 00000000..d2cad1af --- /dev/null +++ b/test/bytecode/Tph3Test.java @@ -0,0 +1,69 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +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 Tph3Test { + + 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/Tph3.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Tph2"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test1() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1,2); + + assertEquals(1,result); + } + + @Test + public void test2() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, "sss",2); + + assertEquals("sss",result); + } + + @Test + public void test3() throws Exception { + Method m = classToTest.getDeclaredMethod("m2", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1,2); + + assertEquals(2,result); + } + + @Test + public void test4() throws Exception { + Method m = classToTest.getDeclaredMethod("m2", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1,"xxx"); + + assertEquals("xxx",result); + } + +} diff --git a/test/bytecode/TphTest.java b/test/bytecode/TphTest.java new file mode 100644 index 00000000..3f0a7bb3 --- /dev/null +++ b/test/bytecode/TphTest.java @@ -0,0 +1,69 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +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 TphTest { + + 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/Tph.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Tph"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test1() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1,2); + + assertEquals(2,result); + } + + @Test + public void test2() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1, "sss"); + + assertEquals("sss",result); + } + + @Test + public void test3() throws Exception { + Method m = classToTest.getDeclaredMethod("m2", Object.class); + Object result = m.invoke(instanceOfClass, 2); + + assertEquals(2,result); + } + + @Test + public void test4() throws Exception { + Method m = classToTest.getDeclaredMethod("m2", Object.class); + Object result = m.invoke(instanceOfClass,"xxx"); + + assertEquals("xxx",result); + } + +} diff --git a/test/bytecode/WhileTest.java b/test/bytecode/WhileTest.java index 5690facb..b3020ffe 100644 --- a/test/bytecode/WhileTest.java +++ b/test/bytecode/WhileTest.java @@ -27,8 +27,8 @@ public class WhileTest { 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/"; + compiler.generateBytecode(pathToClassFile); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); classToTest = loader.loadClass("While"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); diff --git a/test/bytecode/applyLambdaTest.java b/test/bytecode/applyLambdaTest.java new file mode 100644 index 00000000..b73cf507 --- /dev/null +++ b/test/bytecode/applyLambdaTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class applyLambdaTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/applyLambda.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("applyLambda"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + Method m = classToTest.getDeclaredMethod("m"); + Object result = m.invoke(instanceOfClass); + + assertEquals(result.getClass(), loader.loadClass("Apply")); + } +} diff --git a/test/bytecode/javFiles/Faculty.jav b/test/bytecode/javFiles/Faculty.jav index cea028c1..a5c649b8 100644 --- a/test/bytecode/javFiles/Faculty.jav +++ b/test/bytecode/javFiles/Faculty.jav @@ -2,14 +2,15 @@ import java.lang.Integer; class Faculty { - Integer mul(Integer x, Integer y) { - return x; - } - m () { var fact = (Integer x) -> { - return mul(x, x); + if (x == 1) { + return x; + } + else { + return x * fact.apply(x-1); + } }; return fact; } diff --git a/test/bytecode/javFiles/IfTest.jav b/test/bytecode/javFiles/IfTest.jav index 806e2157..33f9ecba 100644 --- a/test/bytecode/javFiles/IfTest.jav +++ b/test/bytecode/javFiles/IfTest.jav @@ -1,3 +1,6 @@ +import java.lang.Integer; +import java.lang.Boolean; + public class IfTest{ Integer m1(Boolean b) { Integer i; diff --git a/test/bytecode/javFiles/Lambda.jav b/test/bytecode/javFiles/Lambda.jav index 3aeded25..d7809e7e 100644 --- a/test/bytecode/javFiles/Lambda.jav +++ b/test/bytecode/javFiles/Lambda.jav @@ -4,7 +4,7 @@ public class Lambda { m () { var lam1 = (Integer x) -> { - return x; + return x * x; }; return lam1; } diff --git a/test/bytecode/javFiles/Matrix.jav b/test/bytecode/javFiles/Matrix.jav index 80f41b16..2ba7f307 100644 --- a/test/bytecode/javFiles/Matrix.jav +++ b/test/bytecode/javFiles/Matrix.jav @@ -1,25 +1,41 @@ import java.util.Vector; import java.lang.Integer; +//import java.lang.Byte; import java.lang.Boolean; -class Matrix extends Vector> { - mul(m) { +public class Matrix extends Vector> { + + Matrix () { + } + + Matrix(vv) { + Integer i; + i = 0; + while(i < vv.size()) { +// Boolean a = this.add(vv.elementAt(i)); + this.add(vv.elementAt(i)); + i=i+1; + } + } + + mul(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++; } + 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); + v2.addElement(erg); + j++; } + ret.addElement(v2); i++; } return ret; diff --git a/test/bytecode/javFiles/OL.jav b/test/bytecode/javFiles/OL.jav index fd2c30a4..263cf1ec 100644 --- a/test/bytecode/javFiles/OL.jav +++ b/test/bytecode/javFiles/OL.jav @@ -1,10 +1,11 @@ +import java.lang.String; import java.lang.Integer; import java.lang.Double; -class OL { +public class OL { - m(java.lang.Double x) { return x + x; } + m(x) { return x + x; } //m(x) { return x || x; } @@ -12,7 +13,7 @@ class OL { } -class Main { +public class OLMain { main(x) { var ol; diff --git a/test/bytecode/javFiles/SubMatrix.jav b/test/bytecode/javFiles/SubMatrix.jav new file mode 100644 index 00000000..f761321c --- /dev/null +++ b/test/bytecode/javFiles/SubMatrix.jav @@ -0,0 +1,13 @@ +import java.util.Vector; +import java.lang.Integer; + +public class Matrix2 extends Vector { + +} + +public class SubMatrix extends Matrix2 { + m(){ + Vector v = new Vector(); + v.add(1); + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/Tph.jav b/test/bytecode/javFiles/Tph.jav new file mode 100644 index 00000000..8dbb1507 --- /dev/null +++ b/test/bytecode/javFiles/Tph.jav @@ -0,0 +1,11 @@ +public class Tph { + + m(a,b){ + var c = m2(b); + return c; + } + + m2(b){ + return b; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/Tph2.jav b/test/bytecode/javFiles/Tph2.jav new file mode 100644 index 00000000..c957eae6 --- /dev/null +++ b/test/bytecode/javFiles/Tph2.jav @@ -0,0 +1,10 @@ +public class Tph2 { + m(a,b){ + var c = m2(a,b); + return a; + } + + m2(a,b){ + return b; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/Tph3.jav b/test/bytecode/javFiles/Tph3.jav new file mode 100644 index 00000000..42d5d687 --- /dev/null +++ b/test/bytecode/javFiles/Tph3.jav @@ -0,0 +1,10 @@ +public class Tph3 { + m(a,b){ + var c = m2(a,b); + return c; + } + + m2(a,b){ + return m(a,b); + } +} diff --git a/test/bytecode/javFiles/applyLambda.jav b/test/bytecode/javFiles/applyLambda.jav new file mode 100644 index 00000000..331bfbfe --- /dev/null +++ b/test/bytecode/javFiles/applyLambda.jav @@ -0,0 +1,16 @@ +import java.util.Vector; +class Apply { } + +public class applyLambda { + + m () { + var lam1 = (x) -> { + return x; + }; + + return lam1.apply(new Apply()); + //return lam1; + //return new Vector(); + } +} + diff --git a/test/javFiles/Lambda.jav b/test/javFiles/Lambda.jav index 553dc496..b9a2c3f9 100644 --- a/test/javFiles/Lambda.jav +++ b/test/javFiles/Lambda.jav @@ -1,5 +1,4 @@ -import java.lang.Integer; -import java.lang.Number; +class Apply { } public class Lambda { @@ -7,7 +6,7 @@ public class Lambda { var lam1 = (x) -> { return x; }; - return lam1; + return lam1.apply(new Apply()); } } diff --git a/test/javFiles/Matrix.jav b/test/javFiles/Matrix.jav index 4c55c410..5e1eac08 100644 --- a/test/javFiles/Matrix.jav +++ b/test/javFiles/Matrix.jav @@ -16,7 +16,7 @@ class Matrix extends Vector> { var k = 0; while(k < v1.size()) { erg = erg + v1.elementAt(k) * m.elementAt(k).elementAt(j); - // erg = add1(erg, mul1(v1.elementAt(k), + //erg = add1(erg, mul1(v1.elementAt(k), // m.elementAt(k).elementAt(j))); k++; } v2.addElement(new Integer(erg)); diff --git a/test/javFiles/Vector.jav b/test/javFiles/Vector.jav index 40072fe4..5c21cfff 100644 --- a/test/javFiles/Vector.jav +++ b/test/javFiles/Vector.jav @@ -1,8 +1,23 @@ +import java.util.ArrayList; import java.util.Vector; +import java.lang.Object; class MyVector{ id(x){ - return (x.elementAt(0)); + Object i; + x.add(i); + x.add(i); + x.add(i); + x.add(i); + x.add(i); + x.add(i); + x.add(i); + x.add(i); + x.add(i); + x.add(i); + x.add(i); + x.add(i); + return x; } } \ No newline at end of file diff --git a/test/typeinference/UnifyTest.java b/test/typeinference/UnifyTest.java index 2a496166..8ce8c71a 100644 --- a/test/typeinference/UnifyTest.java +++ b/test/typeinference/UnifyTest.java @@ -28,13 +28,20 @@ public class UnifyTest { 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 vector() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Vector.jav")); + } + */ + /* @Test public void lambda2() throws IOException, ClassNotFoundException { @@ -74,6 +81,7 @@ public class UnifyTest { } */ + @Test public void matrix() throws IOException, ClassNotFoundException { @@ -81,6 +89,7 @@ public class UnifyTest { //JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"Matrix.jav")); //compiler.generateBytecode(); } + /* @Test