diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java index eddca6260..3b0cb4b74 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -1,677 +1,748 @@ -package de.dhbwstuttgart.bytecode; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Optional; - -import de.dhbwstuttgart.exceptions.NotImplementedException; -import de.dhbwstuttgart.syntaxtree.statement.*; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint; -import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; -import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; -import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString; -import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; -import de.dhbwstuttgart.bytecode.signature.Signature; -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.bytecode.utilities.Simplify; -import de.dhbwstuttgart.bytecode.utilities.SimplifyResult; -import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; -import de.dhbwstuttgart.syntaxtree.*; -import de.dhbwstuttgart.syntaxtree.statement.Literal; -import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; -import de.dhbwstuttgart.syntaxtree.type.GenericRefType; -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; - -public class BytecodeGen implements ASTVisitor { - - ClassWriter cw =new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS); - - String type; - - public static RefTypeOrTPHOrWildcardOrGeneric THISTYPE = null; - String className; - private boolean isInterface; - private Collection listOfResultSets; - private ResultSet resultSet; - private SourceFile sf; - private String path; - - private Optional fieldInitializations; - - private int indexOfFirstParam = 0; - - private String superClass; - - private ArrayList tphsClass; - - // 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 - HashMap genericsAndBounds = new HashMap<>(); - - private int constructorPos = 0; - - private final TPHExtractor tphExtractor = new TPHExtractor(); - private final ArrayList commonPairs = new ArrayList<>(); - - HashMap methodParamsAndTypes = new HashMap<>(); - byte[] bytecode; - HashMap classFiles; - - ArrayList methodNameAndParamsT = new ArrayList<>(); - - private HashMap simplifyResults = new HashMap<>(); - private List> simplifyResultsList = new ArrayList<>(); - - public List> getSimplifyResultsList() { - return simplifyResultsList; - } - - public void setSimplifyResultsList(List> simplifyResultsList) { - this.simplifyResultsList = simplifyResultsList; - } - - public BytecodeGen(HashMap classFiles, Collection 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, sf, path); - cl.accept(classGen); - simplifyResultsList.add(classGen.getSimplifyResults()); - classGen.writeClass(cl.getClassName().toString()); - } - } - - /** - * Associates the bytecode of the class that was build with the classWriter {@link #cw} - * with the class name in the map {@link #classFiles} - * - * @param name name of the class with which the the bytecode is to be associated - */ - private void writeClass(String name) { - bytecode = cw.toByteArray(); - classFiles.put(name, bytecode); - - } - - public HashMap getClassFiles() { - return classFiles; - } - - - @Override - public void visit(ClassOrInterface classOrInterface) { - - className = classOrInterface.getClassName().toString(); - - cw.visitSource(className +".jav", null); - - isInterface = (classOrInterface.getModifiers()&512)==512; - - int acc = isInterface?classOrInterface.getModifiers()+Opcodes.ACC_ABSTRACT:classOrInterface.getModifiers()+Opcodes.ACC_SUPER; - - fieldInitializations = classOrInterface.getfieldInitializations(); - -// resultSet = listOfResultSets.get(0); - boolean isConsWithNoParamsVisited = false; - boolean isVisited = false; - for(ResultSet rs : listOfResultSets) { - superClass = classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()); - resultSet = rs; - tphExtractor.setResultSet(resultSet); - - // Nur einmal ausführen!! - if(!isVisited) { - classOrInterface.accept(tphExtractor); - - getCommonTPHS(tphExtractor); - - tphsClass = new ArrayList<>(); - for(TypePlaceholder t : tphExtractor.allTPHS.keySet()) { - if(!tphExtractor.allTPHS.get(t)) - tphsClass.add(t); - } - - 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("<") - || !tphsClass.isEmpty()) { - HashMap> constraints = Simplify.simplifyConstraintsClass(tphExtractor,tphsClass); - ArrayList consClass = new ArrayList<>(); - for(TPHConstraint cons : constraints.keySet()) { - TypePlaceholder right = null; - for(TypePlaceholder tph : tphsClass) { - if(cons.getLeft().equals(tph.getName())) { - - consClass.add(cons); - right = getTPH(cons.getRight()); - } - } - if(right != null) { - tphsClass.add(right); - removeFromMethod(right.getName()); - right = null; - } - } - - SimplifyResult sRes = new SimplifyResult(consClass, tphsClass, new HashMap<>()); - simplifyResults.put(className, sRes); - - Signature signature = new Signature(classOrInterface, genericsAndBounds,commonPairs,tphsClass, consClass); - 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); -// } - -// if(!c.getParameterList().iterator().hasNext()) -// isConsWithNoParamsVisited = true; - } - - for(Method m : classOrInterface.getMethods()) { - m.accept(this); - } - - } - - } - - private void removeFromMethod(String name) { - for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) { - ArrayList toRemove = new ArrayList<>(); - for(String tph : m.getTphs()) { - if(tph.equals(name)) { - toRemove.add(tph); - } - } - - if(!toRemove.isEmpty()) { - m.getTphs().removeAll(toRemove); - return; - } - } - - } - - private TypePlaceholder getTPH(String name) { - for(TypePlaceholder tph: tphExtractor.allTPHS.keySet()) { - if(tph.getName().equals(name)) - return tph; - } - throw new NoSuchElementException("TPH "+name +" does not exist"); - } - - 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) { - System.out.println("ResultSet: "); - resultSet.results.forEach(a->{ - System.out.println(a.getLeft().toString() + " = " + a.getRight().toString()); - }); - System.out.println("---------------"); - - // stores generics and their bounds of method - HashMap genericsAndBoundsMethod = new HashMap<>(); - - field.getParameterList().accept(this); - - String methParamTypes = field.name+"%%"; - - Iterator itr = field.getParameterList().iterator(); - while(itr.hasNext()) { - FormalParameter fp = itr.next(); - methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+";"; -// methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToSignature())+";"; - } - - if(methodNameAndParamsT.contains(methParamTypes)) { - System.out.println("ignore - Method: "+field.name +" , paramsType: "+methParamTypes); - return; - } - methodNameAndParamsT.add(methParamTypes); - System.out.println("Method: "+field.name +" , paramsType: "+methParamTypes); - - String desc = null; - boolean hasGen = false; - - for(String paramName : methodParamsAndTypes.keySet()) { - String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature()); - System.out.println(typeOfParam); - if(genericsAndBounds.containsKey(typeOfParam) ||typeOfParam.contains("$") - || typeOfParam.contains("<")) { - hasGen = true; - break; - } - } - String sig = null; - if(hasGen) { - HashMap> constraints = Simplify.simplifyConstraints(field.name, tphExtractor,tphsClass); - Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes,resultSet,constraints); - sig = signature.toString(); - } - if(field.getParameterList().iterator().hasNext()) - System.out.println(field.getParameterList().iterator().next().getType().acceptTV(new TypeToDescriptor())); - - NormalConstructor constructor = new NormalConstructor(field,genericsAndBounds,hasGen); - desc = constructor.accept(new DescriptorToString(resultSet)); - System.out.println("Constructor: " + field.getName() + " Sig: "+ sig + " Desc: " + desc); - MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", desc, sig, null); - mv.visitCode(); - - Block block = fieldInitializations.get().block; - - constructorPos += 1; - - BytecodeGenMethod gen = new BytecodeGenMethod(className,superClass,resultSet,field, mv,paramsAndLocals,cw, - genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles, sf,path, block, constructorPos); - if(!field.getParameterList().iterator().hasNext() && !(field.block.statements.get(field.block.statements.size()-1) instanceof ReturnVoid)) { - mv.visitInsn(Opcodes.RETURN); - } - mv.visitMaxs(0, 0); - mv.visitEnd(); - } - - @Override - public void visit(Method method) { - // TODO: check if the method is static => if static then the first param will be stored in pos 0 - // else it will be stored in pos 1 and this will be stored in pos 0 - String retType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); -// String retType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); - String methParamTypes = retType+method.name+"%%"; - method.getParameterList().accept(this); - - Iterator itr = method.getParameterList().iterator(); - while(itr.hasNext()) { - FormalParameter fp = itr.next(); - methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+";"; -// methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToSignature())+";"; - } - - if(methodNameAndParamsT.contains(methParamTypes)) { - return; - } - methodNameAndParamsT.add(methParamTypes); - System.out.println("Method: "+method.name +" , paramsType: "+methParamTypes); - // stores generics and their bounds of method - HashMap genericsAndBoundsMethod = new HashMap<>(); - String methDesc = null; - - // Method getModifiers() ? - int acc = isInterface?Opcodes.ACC_ABSTRACT:method.modifier; - System.out.println(acc); - - /*Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist*/ - boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.contains("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()); - String sigOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature()); - if(genericsAndBounds.containsKey(typeOfParam)||typeOfParam.contains("TPH ")||sigOfParam.contains("<")) { - hasGenInParameterList = true; - break; - } - } - } - //TODO: Test if the return-type or any of the parameter is a parameterized type. (VP) - //then create the descriptor with the new syntax. - - String sig = null; - /* method.getGenerics: <....> RT method(..) - * */ - boolean hasGen = method.getGenerics().iterator().hasNext() || hasGenInParameterList; - /* if method has generics or return type is TPH, create signature */ - // zwite operand muss weggelassen werden - if(hasGen||resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToString()).equals("TPH")) { - System.out.println("ALL CONST: " + tphExtractor.allCons.size()); - tphExtractor.allCons.forEach(c->System.out.println(c.toString())); - System.out.println("----------------"); - HashMap> constraints = Simplify.simplifyConstraints(method.name, tphExtractor, tphsClass); -// ArrayList pairs = simplifyPairs(method.name,tphExtractor.allPairs,tphExtractor.allCons); - Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds,methodParamsAndTypes,resultSet,constraints); - sig = signature.toString(); - if(simplifyResults.containsKey(className)) { - simplifyResults.get(className).getMethodsConstraints().put(methParamTypes, constraints); - } else { - SimplifyResult sRes = new SimplifyResult(new ArrayList<>(), new ArrayList<>(), new HashMap<>()); - sRes.getMethodsConstraints().put(methParamTypes, constraints); - simplifyResults.put(className, sRes); - } - - } - System.out.println(method.getName()+" ==> "+sig); - NormalMethod meth = new NormalMethod(method,genericsAndBounds,genericsAndBoundsMethod,hasGen); - methDesc = meth.accept(new DescriptorToString(resultSet)); - -// System.out.println(methDesc); - MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC+acc, method.getName(), methDesc, sig, null); - - mv.visitCode(); - BytecodeGenMethod gen = new BytecodeGenMethod(className,superClass,resultSet,method, mv,paramsAndLocals,cw, - genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles, sf,path); - - mv.visitMaxs(0, 0); - mv.visitEnd(); - } - - public HashMap getSimplifyResults() { - return simplifyResults; - } - - @Override - public void visit(ParameterList formalParameters) { - paramsAndLocals = new HashMap<>(); - methodParamsAndTypes = new HashMap<>(); - Iterator itr = formalParameters.iterator(); - int i = 1; - while(itr.hasNext()) { - FormalParameter fp = itr.next(); - paramsAndLocals.put(fp.getName(), i); - methodParamsAndTypes.put(fp.getName(), resultSet.resolveType(fp.getType()).resolvedType); - fp.accept(this); - i++; - } - } - - @Override - public void visit(FormalParameter formalParameter) { - formalParameter.getType().accept(this); - } - - @Override - public void visit(RefType refType) { - type = "L"+refType.toString()+";"; - } - - @Override - public void visit(SuperWildcardType superWildcardType) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(TypePlaceholder typePlaceholder) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(ExtendsWildcardType extendsWildcardType) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(GenericRefType genericRefType) { - // TODO Auto-generated method stub - - } - - // ?? - @Override - public void visit(FieldVar fieldVar) { - System.out.println("In FieldVar ---"); -// cw.newField(fieldVar.receiver.toString(), fieldVar.fieldVarName.toString(), fieldVar.getType().toString()); - FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, fieldVar.fieldVarName, "L"+fieldVar.getType()+";", null, null); - fv.visitEnd(); - } - - @Override - public void visit(Field field) { - System.out.println("In Field ---"); - String des = "L"; - if(resultSet.resolveType(field.getType()).resolvedType instanceof TypePlaceholder) { - des += Type.getInternalName(Object.class); - } else { - des += resultSet.resolveType(field.getType()).resolvedType.acceptTV(new TypeToDescriptor()); - } - des +=";"; - System.out.println(des); - String sig = resultSet.resolveType(field.getType()).resolvedType.acceptTV(new TypeToSignature()); - System.out.println(sig); - if(sig.charAt(sig.length()-1) != (";").charAt(0)) { - sig +=";"; - } - cw.visitField(field.modifier, field.getName(), - des, sig, - null); - } - - @Override - public void visit(LambdaExpression lambdaExpression) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(Assign assign) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(BinaryExpr binary) { - - } - - @Override - public void visit(Block block) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(CastExpr castExpr) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(EmptyStmt emptyStmt) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(ForStmt forStmt) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(IfStmt ifStmt) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(InstanceOf instanceOf) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(LocalVar localVar) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(LocalVarDecl localVarDecl) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(MethodCall methodCall) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(NewClass methodCall) { - // TODO Auto-generated method stub - - } - - @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) { - // TODO Auto-generated method stub - - } - - @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(Literal literal) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(ArgumentList argumentList) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(GenericTypeVar genericTypeVar) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(GenericDeclarationList genericTypeVars) { - // 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) { - - } - - @Override - public void visit(ExpressionReceiver expressionReceiver) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(UnaryExpr unaryExpr) { - throw new NotImplementedException(); - } - - -} +package de.dhbwstuttgart.bytecode; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; + +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import de.dhbwstuttgart.bytecode.Exception.BytecodeGeneratorError; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +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.bytecode.utilities.Simplify; +import de.dhbwstuttgart.bytecode.utilities.SimplifyResult; +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.ASTVisitor; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.Field; +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.GenericDeclarationList; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.SourceFile; +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; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +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.ResultSet; + +public class BytecodeGen implements ASTVisitor { + + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + + String type; + + public static RefTypeOrTPHOrWildcardOrGeneric THISTYPE = null; + String className; + private boolean isInterface; + private Collection listOfResultSets; + private ResultSet resultSet; + private SourceFile sf; + private String path; + + private Optional fieldInitializations; + + private int indexOfFirstParam = 0; + + private String superClass; + + private ArrayList tphsClass; + + // 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 + HashMap genericsAndBounds = new HashMap<>(); + + private int constructorPos = 0; + + private final TPHExtractor tphExtractor = new TPHExtractor(); + private final ArrayList commonPairs = new ArrayList<>(); + + HashMap methodParamsAndTypes = new HashMap<>(); + byte[] bytecode; + HashMap classFiles; + + private final ArrayList methodNameAndParamsT = new ArrayList<>(); + private final ArrayList fieldNameAndParamsT = new ArrayList<>(); + + private HashMap simplifyResults = new HashMap<>(); + private List> simplifyResultsList = new ArrayList<>(); + + private final ArrayList fieldNameSignature = new ArrayList<>(); + + public List> getSimplifyResultsList() { + return simplifyResultsList; + } + + public void setSimplifyResultsList(List> simplifyResultsList) { + this.simplifyResultsList = simplifyResultsList; + } + + public BytecodeGen(HashMap classFiles, Collection 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, sf, path); + cl.accept(classGen); + simplifyResultsList.add(classGen.getSimplifyResults()); + classGen.writeClass(cl.getClassName().toString()); + } + } + + /** + * Associates the bytecode of the class that was build with the classWriter + * {@link #cw} with the class name in the map {@link #classFiles} + * + * @param name name of the class with which the the bytecode is to be associated + */ + private void writeClass(String name) { + bytecode = cw.toByteArray(); + classFiles.put(name, bytecode); + + } + + public HashMap getClassFiles() { + return classFiles; + } + + @Override + public void visit(ClassOrInterface classOrInterface) { + + className = classOrInterface.getClassName().toString(); + + cw.visitSource(className + ".jav", null); + + isInterface = (classOrInterface.getModifiers() & 512) == 512; + + int acc = isInterface ? classOrInterface.getModifiers() + Opcodes.ACC_ABSTRACT + : classOrInterface.getModifiers() + Opcodes.ACC_SUPER; + + fieldInitializations = classOrInterface.getfieldInitializations(); + +// resultSet = listOfResultSets.get(0); + boolean isConsWithNoParamsVisited = false; + boolean isVisited = false; + for (ResultSet rs : listOfResultSets) { + superClass = classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()); + resultSet = rs; + tphExtractor.setResultSet(resultSet); + + // Nur einmal ausführen!! + if (!isVisited) { + classOrInterface.accept(tphExtractor); + + getCommonTPHS(tphExtractor); + + tphsClass = new ArrayList<>(); + for (String t : tphExtractor.allTPHS.keySet()) { + if (!tphExtractor.allTPHS.get(t)) + tphsClass.add(t); + } + + 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("<") + || !tphsClass.isEmpty()) { + HashMap> constraints = Simplify + .simplifyConstraintsClass(tphExtractor, tphsClass); + ArrayList consClass = new ArrayList<>(); + for (TPHConstraint cons : constraints.keySet()) { + String right = null; + boolean isToAdd = false; + for (String tph : tphsClass) { + if (cons.getLeft().equals(tph)) { + + consClass.add(cons); + try { + right = getTPH(cons.getRight()); + isToAdd = true; + } catch (NoSuchElementException e) { + continue; + } + + } + } + if (isToAdd) { + tphsClass.add(right); + removeFromMethod(right); + right = null; + isToAdd = false; + } +// if(right != null) { +// tphsClass.add(right); +// removeFromMethod(right); +// right = null; +// } + } + + SimplifyResult sRes = new SimplifyResult(consClass, tphsClass, new HashMap<>()); + simplifyResults.put(className, sRes); + + Signature signature = new Signature(classOrInterface, genericsAndBounds, commonPairs, tphsClass, + consClass); + 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); +// } + +// if(!c.getParameterList().iterator().hasNext()) +// isConsWithNoParamsVisited = true; + } + + for (Method m : classOrInterface.getMethods()) { + m.accept(this); + } + + } + + } + + private void removeFromMethod(String name) { + for (MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) { + ArrayList toRemove = new ArrayList<>(); + for (String tph : m.getTphs()) { + if (tph.equals(name)) { + toRemove.add(tph); + } + } + + if (!toRemove.isEmpty()) { + m.getTphs().removeAll(toRemove); + return; + } + } + + } + + private String getTPH(String name) { + for (String tph : tphExtractor.allTPHS.keySet()) { + if (tph.equals(name)) + return tph; + } + throw new NoSuchElementException("TPH " + name + " does not exist"); + } + + private void getCommonTPHS(TPHExtractor tphExtractor) { + // Gemeinsame TPHs + ArrayList cTPHs = new ArrayList<>(); + // Alle TPHs der Felder speichern + for (String tph : tphExtractor.allTPHS.keySet()) { + if (!tphExtractor.allTPHS.get(tph)) + cTPHs.add(tph); + } + } + + @Override + public void visit(Constructor field) { + System.out.println("ResultSet: "); + resultSet.results.forEach(a -> { + System.out.println(a.getLeft().toString() + " = " + a.getRight().toString()); + }); + System.out.println("---------------"); + + // stores generics and their bounds of method + HashMap genericsAndBoundsMethod = new HashMap<>(); + + field.getParameterList().accept(this); + + String methParamTypes = field.name + "%%"; + + Iterator itr = field.getParameterList().iterator(); + while (itr.hasNext()) { + FormalParameter fp = itr.next(); + methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()) + ";"; +// methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToSignature())+";"; + } + + if (methodNameAndParamsT.contains(methParamTypes)) { + System.out.println("ignore - Method: " + field.name + " , paramsType: " + methParamTypes); + return; + } + methodNameAndParamsT.add(methParamTypes); + System.out.println("Method: " + field.name + " , paramsType: " + methParamTypes); + + String desc = null; + boolean hasGen = false; + + for (String paramName : methodParamsAndTypes.keySet()) { + String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature()); + System.out.println(typeOfParam); + if (genericsAndBounds.containsKey(typeOfParam) || typeOfParam.contains("$") || typeOfParam.contains("<")) { + hasGen = true; + break; + } + } + String sig = null; + if (hasGen) { + HashMap> constraints = Simplify.simplifyConstraints(field.name, tphExtractor, + tphsClass); + Signature signature = new Signature(field, genericsAndBounds, methodParamsAndTypes, resultSet, constraints); + sig = signature.toString(); + } + if (field.getParameterList().iterator().hasNext()) + System.out.println(field.getParameterList().iterator().next().getType().acceptTV(new TypeToDescriptor())); + + NormalConstructor constructor = new NormalConstructor(field, genericsAndBounds, hasGen); + desc = constructor.accept(new DescriptorToString(resultSet)); + System.out.println("Constructor: " + field.getName() + " Sig: " + sig + " Desc: " + desc); + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", desc, sig, null); + mv.visitCode(); + + Block block = fieldInitializations.get().block; + + constructorPos += 1; + + BytecodeGenMethod gen = new BytecodeGenMethod(className, superClass, resultSet, field, mv, paramsAndLocals, cw, + genericsAndBoundsMethod, genericsAndBounds, isInterface, classFiles, sf, path, block, constructorPos); + if (!field.getParameterList().iterator().hasNext() + && !(field.block.statements.get(field.block.statements.size() - 1) instanceof ReturnVoid)) { + mv.visitInsn(Opcodes.RETURN); + } + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + @Override + public void visit(Method method) { + // TODO: check if the method is static => if static then the first param will be + // stored in pos 0 + // else it will be stored in pos 1 and this will be stored in pos 0 + String retType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); +// String retType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); + String methParamTypes = retType + method.name + "%%"; + method.getParameterList().accept(this); + + Iterator itr = method.getParameterList().iterator(); + while (itr.hasNext()) { + FormalParameter fp = itr.next(); + methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()) + ";"; +// methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToSignature())+";"; + } + + if (methodNameAndParamsT.contains(methParamTypes)) { + return; + } + methodNameAndParamsT.add(methParamTypes); + System.out.println("Method: " + method.name + " , paramsType: " + methParamTypes); + // stores generics and their bounds of method + HashMap genericsAndBoundsMethod = new HashMap<>(); + String methDesc = null; + + // Method getModifiers() ? + int acc = isInterface ? Opcodes.ACC_ABSTRACT : method.modifier; + System.out.println(acc); + + /* Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist */ + boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.contains("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()); + String sigOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature()); + if (genericsAndBounds.containsKey(typeOfParam) || typeOfParam.contains("TPH ") + || sigOfParam.contains("<")) { + hasGenInParameterList = true; + break; + } + } + } + // TODO: Test if the return-type or any of the parameter is a parameterized + // type. (VP) + // then create the descriptor with the new syntax. + + String sig = null; + /* + * method.getGenerics: <....> RT method(..) + */ + boolean hasGen = method.getGenerics().iterator().hasNext() || hasGenInParameterList; + /* if method has generics or return type is TPH, create signature */ + // zwite operand muss weggelassen werden + if (hasGen || resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToString()) + .equals("TPH")) { + System.out.println("ALL CONST: " + tphExtractor.allCons.size()); + tphExtractor.allCons.forEach(c -> System.out.println(c.toString())); + System.out.println("----------------"); + HashMap> constraints = Simplify.simplifyConstraints(method.name, + tphExtractor, tphsClass); +// ArrayList pairs = simplifyPairs(method.name,tphExtractor.allPairs,tphExtractor.allCons); + Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds, + methodParamsAndTypes, resultSet, constraints); + sig = signature.toString(); + if (simplifyResults.containsKey(className)) { + simplifyResults.get(className).getMethodsConstraints().put(methParamTypes, constraints); + } else { + SimplifyResult sRes = new SimplifyResult(new ArrayList<>(), new ArrayList<>(), new HashMap<>()); + sRes.getMethodsConstraints().put(methParamTypes, constraints); + simplifyResults.put(className, sRes); + } + + } + System.out.println(method.getName() + " ==> " + sig); + NormalMethod meth = new NormalMethod(method, genericsAndBounds, genericsAndBoundsMethod, hasGen); + methDesc = meth.accept(new DescriptorToString(resultSet)); + +// System.out.println(methDesc); + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC + acc, method.getName(), methDesc, sig, null); + + mv.visitCode(); + BytecodeGenMethod gen = new BytecodeGenMethod(className, superClass, resultSet, method, mv, paramsAndLocals, cw, + genericsAndBoundsMethod, genericsAndBounds, isInterface, classFiles, sf, path); + + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + public HashMap getSimplifyResults() { + return simplifyResults; + } + + @Override + public void visit(ParameterList formalParameters) { + paramsAndLocals = new HashMap<>(); + methodParamsAndTypes = new HashMap<>(); + Iterator itr = formalParameters.iterator(); + int i = 1; + while (itr.hasNext()) { + FormalParameter fp = itr.next(); + paramsAndLocals.put(fp.getName(), i); + methodParamsAndTypes.put(fp.getName(), resultSet.resolveType(fp.getType()).resolvedType); + fp.accept(this); + i++; + } + } + + @Override + public void visit(FormalParameter formalParameter) { + formalParameter.getType().accept(this); + } + + @Override + public void visit(RefType refType) { + type = "L" + refType.toString() + ";"; + } + + @Override + public void visit(SuperWildcardType superWildcardType) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(TypePlaceholder typePlaceholder) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ExtendsWildcardType extendsWildcardType) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(GenericRefType genericRefType) { + // TODO Auto-generated method stub + + } + + // ?? + @Override + public void visit(FieldVar fieldVar) { + System.out.println("In FieldVar ---"); +// cw.newField(fieldVar.receiver.toString(), fieldVar.fieldVarName.toString(), fieldVar.getType().toString()); + FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, fieldVar.fieldVarName, "L" + fieldVar.getType() + ";", + null, null); + fv.visitEnd(); + } + + @Override + public void visit(Field field) { + System.out.println("In Field ---"); + String des = "L"; + if (resultSet.resolveType(field.getType()).resolvedType instanceof TypePlaceholder) { + des += Type.getInternalName(Object.class); + } else { + des += resultSet.resolveType(field.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + } + des += ";"; + System.out.println(des); + String sig = resultSet.resolveType(field.getType()).resolvedType.acceptTV(new TypeToSignature()); + System.out.println(sig); + if (sig.charAt(sig.length() - 1) != (";").charAt(0)) { + sig += ";"; + } + String nameAndDesc = field.getName() + "%%" + des; + String nameAndSig = field.getName() + "%%" + sig; + if (fieldNameAndParamsT.contains(nameAndDesc)) { + if (fieldNameSignature.contains(nameAndSig)) { + return; + } + throw new BytecodeGeneratorError("Bytecode generation aborted due to duplicate field name&signature"); + } + fieldNameAndParamsT.add(nameAndDesc); + fieldNameSignature.add(nameAndSig); + + cw.visitField(field.modifier, field.getName(), des, sig, null); + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Assign assign) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(BinaryExpr binary) { + + } + + @Override + public void visit(Block block) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(CastExpr castExpr) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(EmptyStmt emptyStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ForStmt forStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(IfStmt ifStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(InstanceOf instanceOf) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(LocalVar localVar) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(LocalVarDecl localVarDecl) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(MethodCall methodCall) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(NewClass methodCall) { + // TODO Auto-generated method stub + + } + + @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) { + // TODO Auto-generated method stub + + } + + @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(Literal literal) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ArgumentList argumentList) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(GenericTypeVar genericTypeVar) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(GenericDeclarationList genericTypeVars) { + // 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) { + + } + + @Override + public void visit(ExpressionReceiver expressionReceiver) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(UnaryExpr unaryExpr) { + throw new NotImplementedException(); + } + +} diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index b1ea614fb..abf7237a7 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -33,12 +33,14 @@ import org.objectweb.asm.Type; import org.objectweb.asm.signature.SignatureVisitor; import org.objectweb.asm.signature.SignatureWriter; +import de.dhbwstuttgart.bytecode.Exception.NotInCurrentPackageException; 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.utilities.KindOfLambda; import de.dhbwstuttgart.bytecode.utilities.Lambda; +import de.dhbwstuttgart.bytecode.utilities.MethodCallHelper; import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall; import de.dhbwstuttgart.bytecode.utilities.SamMethod; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; @@ -52,6 +54,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.result.ResultSet; +import javassist.NotFoundException; public class BytecodeGenMethod implements StatementVisitor { @@ -675,7 +678,7 @@ public class BytecodeGenMethod implements StatementVisitor { } methSig.visitReturnType().visitTypeVariable("R"); // ")"+lam.getReturn.getBounds - Signature sig = new Signature(lambdaExpression, numberOfParams); + Signature sig = new Signature(numberOfParams); String name = "Fun" + numberOfParams + "$$"; classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC+Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(), Type.getInternalName(Object.class), null); @@ -763,7 +766,7 @@ public class BytecodeGenMethod implements StatementVisitor { public void visit(InstanceOf instanceOf) { } - + @Override public void visit(MethodCall methodCall) { boolean parentBinary = isParentBinary; @@ -772,100 +775,102 @@ public class BytecodeGenMethod implements StatementVisitor { System.out.println("Methods of " + receiverName + " "); java.lang.reflect.Method methodRefl = null; String clazz = receiverName.replace("/", "."); -// if(!receiverName.equals(className)) { - ClassLoader cLoader = ClassLoader.getSystemClassLoader(); - // This will be used if the class is not standard class (not in API) - ClassLoader cLoader2; - - String methCallType = resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor()); - String[] typesOfParams = getTypes(methodCall.arglist.getArguments()); - try { - if(receiverName.contains("<")) { - clazz = clazz.substring(0, receiverName.indexOf("<")); - } - - java.lang.reflect.Method[] methods = cLoader.loadClass(clazz).getMethods(); - System.out.println("Methods of " + receiverName + " "); - methodRefl = getMethod(methodCall.name,methodCall.arglist.getArguments().size(),methods); - + + String mDesc = ""; + + MethodCallHelper helper = new MethodCallHelper(methodCall, sf, resultSet, path); + + boolean toCreate = false; + + ClassLoader cLoader = ClassLoader.getSystemClassLoader(); + // This will be used if the class is not standard class (not in API) + ClassLoader cLoader2; + + String methCallType = resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + String[] typesOfParams = getTypes(methodCall.arglist.getArguments()); + try { + if (receiverName.contains("<")) { + clazz = clazz.substring(0, receiverName.indexOf("<")); + } + + java.lang.reflect.Method[] methods = cLoader.loadClass(clazz).getMethods(); + System.out.println("Methods of " + receiverName + " "); + methodRefl = getMethod(methodCall.name, methodCall.arglist.getArguments().size(), methods); + } catch (Exception e) { -// try { -// cLoader2 = new URLClassLoader(new URL[] {new URL("file://"+path)}); -// java.lang.reflect.Method[] methods = cLoader2.loadClass(clazz).getMethods(); -// System.out.println("Methods of " + receiverName + " "); -// for(int i = 0; i argListMethCall = new LinkedList<>(); String receiverRefl=""; - if(methodRefl == null) { + if(methodRefl == null && receiverName.equals(className)) { MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), receiverName, genericsAndBoundsMethod, genericsAndBounds); mDesc = method.accept(new DescriptorToString(resultSet)); methodCall.arglist.accept(this); - } else { + } else if(methodRefl != null) { System.out.println(methodCall.name + " -> Refl != null"); receiverRefl = methodRefl.getAnnotatedReceiverType().getType().toString(); for(Parameter p:methodRefl.getParameters()) { @@ -880,6 +885,8 @@ public class BytecodeGenMethod implements StatementVisitor { al.accept(argV); statement = null; } + } else { + methodCall.arglist.accept(this); } System.out.println("Methodcall ("+ methodCall.name +") Desc : " + mDesc); @@ -917,6 +924,19 @@ public class BytecodeGenMethod implements StatementVisitor { } + private String getDescForMethInCurrPkg(String name) { + // TODO Auto-generated method stub + return null; + } + + private boolean isInCurrPkg(String superClass) { + for(ClassOrInterface cl : sf.KlassenVektor) { + if(superClass.equals(cl.getClassName().toString())) + return true; + } + return false; + } + private String[] getTypes(List arguments) { String[] types = new String[arguments.size()]; for(int i = 0; i allTPHS = new HashMap<>(); + final HashMap allTPHS = new HashMap<>(); MethodAndTPH methodAndTph; Boolean inMethod = false; boolean inLocalOrParam = false; public final ArrayList ListOfMethodsAndTph = new ArrayList<>(); - final ArrayList allPairs = new ArrayList<>(); + final ArrayList> allPairs = new ArrayList<>(); public final ArrayList allCons = new ArrayList<>(); private ResultSet resultSet; @@ -58,19 +67,80 @@ public class TPHExtractor extends AbstractASTWalker { methodAndTph.getLocalTphs().add(resolvedTPH.getName()); } - allTPHS.put(resolvedTPH, inMethod); - resultSet.resolveType(tph).additionalGenerics.forEach(ag -> { - if (ag.contains(resolvedTPH) && ag.TA1.equals(resolvedTPH) && !contains(allPairs, ag)) { + allTPHS.put(resolvedTPH.getName(), inMethod); +// final List cons = new ArrayList<>(); +// resultSet.resolveType(tph).additionalGenerics.forEach(ag -> { +// TPHConstraint con = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); +// cons.add(con); +// }); +// +// Map visitMap = new HashMap<>(); +// for(TPHConstraint cc : cons) { +// visitMap.put(cc, false); +// } +// +// String left = resolvedTPH.getName(); +// for (TPHConstraint cc : visitMap.keySet()) { +// +// if(visitMap.get(cc)) +// continue; +// +// if (cc.getLeft().equals(left)) { +// allCons.add(cc); +// List toVisit = getToVisitCons(cons,cc.getRight(), visitMap); +// } +// } + + //resultSet.resolveType(tph).getAdditionalGenerics().forEach(ag -> { + resultSet.genIns.forEach(ag -> { + +// if (ag.contains(resolvedTPH) /* && ag.TA1.equals(resolvedTPH) */ && !contains(allPairs, ag)) { if (inMethod) methodAndTph.getPairs().add(ag); allPairs.add(ag); - TPHConstraint con = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); - allCons.add(con); - } + TPHConstraint con = new ExtendsConstraint(ag.getLeft().getName(), ag.getRight().getName(), Relation.EXTENDS); + if(!containsConstraint(allCons,con)) + allCons.add(con); +// } }); + } else if (resultSet.resolveType(tph).resolvedType instanceof RefType) { + RefType rt = (RefType) resultSet.resolveType(tph).resolvedType; + rt.accept(this); } } + private static boolean containsConstraint(ArrayList allCons, TPHConstraint c) { + for(TPHConstraint con:allCons) { + if(c.getLeft().equals(con.getLeft()) && c.getRight().equals(c.getRight())) { + return true; + } + } + return false; + } + + private List getToVisitCons(List cons, String right, Map visitMap) { + List res = new ArrayList<>(); + for(TPHConstraint cc : cons) { + if(cc.getLeft().equals(right)) { + res.add(cc); + if(visitMap.get(cc)) + visitMap.replace(cc, false); + } + } + return res; + } + + @Override + public void visit(GenericRefType genericRefType) { + String name = genericRefType.getParsedName(); + if (inMethod) { + methodAndTph.getLocalTphs().add(name); + if (inLocalOrParam) + methodAndTph.getLocalTphs().add(name); + } + allTPHS.put(name, inMethod); + } + private boolean contains(ArrayList pairs, GenericInsertPair genPair) { for (int i = 0; i < pairs.size(); ++i) { GenericInsertPair p = pairs.get(i); diff --git a/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java b/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java index ca191b7d8..62a55d125 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -41,11 +41,11 @@ public class Signature { private ResultSet resultSet; private ArrayList commonPairs; private HashMap> methodConstraints; - private ArrayList tphsClass; + private ArrayList tphsClass; private ArrayList consClass; public Signature(ClassOrInterface classOrInterface, HashMap genericsAndBounds, - ArrayList commonPairs, ArrayList tphsClass, ArrayList consClass) { + ArrayList commonPairs, ArrayList tphsClass, ArrayList consClass) { this.classOrInterface = classOrInterface; this.genericsAndBounds = genericsAndBounds; this.commonPairs = commonPairs; @@ -80,12 +80,12 @@ public class Signature { createSignatureForConsOrMethod(this.method,false); } - public Signature(LambdaExpression lambdaExpression,int numberOfParams) { + public Signature(int numberOfParams) { sw = new SignatureWriter(); - createSignatureForFunN(lambdaExpression, numberOfParams); + createSignatureForFunN(numberOfParams); } - private void createSignatureForFunN(LambdaExpression lambdaExpression, int numberOfParams) { + private void createSignatureForFunN(int numberOfParams) { // sw.visitClassBound().visitEnd(); for(int i = 0;i{ - TPHConstraint constr = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); + //resType.getAdditionalGenerics().forEach(ag ->{ + resultSet.genIns.forEach(ag ->{ + TPHConstraint constr = new ExtendsConstraint(ag.getLeft().getName(), ag.getRight().getName(), Relation.EXTENDS); if(!contains(res,constr)) { res.add(constr); } @@ -246,8 +247,9 @@ public class Signature { WildcardType resWC = (WildcardType) resolved; ResolvedType resType2 = resultSet.resolveType(resWC.getInnerType()); if(resType2.resolvedType instanceof TypePlaceholder) { - resType2.additionalGenerics.forEach(ag ->{ - TPHConstraint constr = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); + //resType2.getAdditionalGenerics().forEach(ag ->{ + resultSet.genIns.forEach(ag ->{ + TPHConstraint constr = new ExtendsConstraint(ag.getLeft().getName(), ag.getRight().getName(), Relation.EXTENDS); if(!contains(res,constr)) { res.add(constr); } diff --git a/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java b/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java index e21f974cc..c2c0210e5 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java @@ -2,14 +2,17 @@ package de.dhbwstuttgart.bytecode.utilities; import java.util.ArrayList; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.result.GenericInsertPair; +import de.dhbwstuttgart.typeinference.result.ResultPair; public class MethodAndTPH { private String name; private final ArrayList tphs = new ArrayList<>(); - private final ArrayList pairs = new ArrayList<>(); + //private final ArrayList pairs = new ArrayList<>(); + private final ArrayList> pairs = new ArrayList<>(); // tphs of local variables and parameters private final ArrayList localTphs = new ArrayList<>(); @@ -21,7 +24,10 @@ public class MethodAndTPH { return tphs; } - public ArrayList getPairs(){ +// public ArrayList getPairs(){ +// return pairs; +// } + public ArrayList> getPairs(){ return pairs; } diff --git a/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodCallHelper.java b/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodCallHelper.java new file mode 100644 index 000000000..afeaa6c16 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodCallHelper.java @@ -0,0 +1,255 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.utilities; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.signature.SignatureVisitor; +import org.objectweb.asm.signature.SignatureWriter; + +import de.dhbwstuttgart.bytecode.Exception.NotInCurrentPackageException; +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.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.GenericDeclarationList; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; +import de.dhbwstuttgart.syntaxtree.statement.MethodCall; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import javassist.NotFoundException; + +/** + * @author fayez + * + */ +public class MethodCallHelper { + private MethodCall methCall; + private SourceFile sourceFile; + private ResultSet resultSet; + private String path; + + /** + * @param methCall + * @param sourceFile + * @param resultSet + * @param path TODO + */ + public MethodCallHelper(MethodCall methCall, SourceFile sourceFile, ResultSet resultSet, String path) { + this.methCall = methCall; + this.sourceFile = sourceFile; + this.resultSet = resultSet; + this.path = path; + } + + public String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { + return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor()); + } + + public boolean isInCurrPkg(String className) { + for (ClassOrInterface cl : sourceFile.KlassenVektor) { + if (className.equals(cl.getClassName().toString())) + return true; + } + return false; + } + + public String getSuperClass(String className) throws NotInCurrentPackageException { + + for (ClassOrInterface cl : sourceFile.getClasses()) { + if (className.equals(cl.getClassName().toString())) { + return cl.getSuperClass().getName().toString(); + } + } + throw new NotInCurrentPackageException("Class " + className + " is not in the current package."); + } + + public ClassOrInterface getClassFromCurrPkg(String className) throws NotInCurrentPackageException { + for (ClassOrInterface cl : sourceFile.KlassenVektor) { + if (className.equals(cl.getClassName().toString())) + return cl; + } + throw new NotInCurrentPackageException("Class of " + className + " is not in the current package."); + } + + public String getDesc(String className) throws NotInCurrentPackageException, NotFoundException { + String name = methCall.name; + ClassOrInterface clazz = getClassFromCurrPkg(className); + + Map genAndBoundsClass = getGenericsAndBounds(clazz.getGenerics()); + modifyGenAndBounds(genAndBoundsClass); + for (Method m : clazz.getMethods()) { + if (name.equals(m.getName())) { + Map genAndBoundsMethod = getGenericsAndBoundsMethod(m.getGenerics()); + modifyGenAndBounds(genAndBoundsMethod); + boolean hasGen = hasGen(m, genAndBoundsClass); + NormalMethod nm = new NormalMethod(m, (HashMap) genAndBoundsClass, + (HashMap) genAndBoundsMethod, hasGen); + return nm.accept(new DescriptorToString(resultSet)); + } + } + + throw new NotFoundException("Method " + name + " is not found"); + } + + private boolean hasGen(Method m, Map genericsAndBounds) { + String retType = resultSet.resolveType(m.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); + /*Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist*/ + boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.contains("TPH ") || retType.contains("<"); + + Map methodParamsAndTypes = new HashMap<>(); + Iterator itr = m.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + methodParamsAndTypes.put(fp.getName(), resultSet.resolveType(fp.getType()).resolvedType); + } + /*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()); + String sigOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature()); + if(genericsAndBounds.containsKey(typeOfParam)||typeOfParam.contains("TPH ")||sigOfParam.contains("<")) { + hasGenInParameterList = true; + break; + } + } + } + return m.getGenerics().iterator().hasNext() || hasGenInParameterList; + } + + private Map getGenericsAndBoundsMethod(Iterable generics) { + Map genAndBounds = new HashMap<>(); + Iterator itr = generics.iterator(); + while (itr.hasNext()) { + GenericTypeVar gtv = itr.next(); + getBoundsOfTypeVar(gtv, genAndBounds); + } + return genAndBounds; + } + + private void modifyGenAndBounds(Map genAndBoundsClass) { + List visited = new ArrayList<>(genAndBoundsClass.size()); + Map toReplace = new HashMap<>(); + for (String tv : genAndBoundsClass.keySet()) { + + if (visited.contains(tv)) + continue; + + List types = new LinkedList<>(); + String bound = genAndBoundsClass.get(tv); + types.add(tv); + visited.add(tv); + boolean doReplace = false; + while (genAndBoundsClass.keySet().contains(bound)) { + doReplace = true; + types.add(bound); + visited.add(bound); + bound = genAndBoundsClass.get(bound); + } + + if (doReplace) { + for (String tt : types) { + toReplace.put(tt, bound); + } + } + } + + for (String key : toReplace.keySet()) { + genAndBoundsClass.replace(key, toReplace.get(key)); + } + + } + + private Map getGenericsAndBounds(GenericDeclarationList generics) { + Map genAndBounds = new HashMap<>(); + Iterator itr = generics.iterator(); + while (itr.hasNext()) { + GenericTypeVar gtv = itr.next(); + getBoundsOfTypeVar(gtv, genAndBounds); + } + return genAndBounds; + } + + private void getBoundsOfTypeVar(GenericTypeVar g, Map genAndBounds) { + + Iterator bItr = g.getBounds().iterator(); + while (bItr.hasNext()) { + RefTypeOrTPHOrWildcardOrGeneric b = bItr.next(); + String boundDesc = b.acceptTV(new TypeToDescriptor()); + genAndBounds.put(g.getName(), boundDesc); + } + } + + public String generateBCForFunN() { + ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + + SignatureWriter methSig = new SignatureWriter(); + + int numberOfParams = 0; + SignatureVisitor paramVisitor = methSig.visitParameterType(); + Iterator itr1 = methCall.arglist.getArguments().iterator(); + String methDesc = "("; + while(itr1.hasNext()) { + numberOfParams++; + // getBounds + paramVisitor.visitTypeVariable("T" + numberOfParams); + methDesc += "L" + Type.getInternalName(Object.class) + ";"; + itr1.next(); + } + methDesc += ")L" + Type.getInternalName(Object.class) + ";"; + + methSig.visitReturnType().visitTypeVariable("R"); + // ")"+lam.getReturn.getBounds + Signature sig = new Signature(numberOfParams); + String name = "Fun" + numberOfParams + "$$"; + 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); + mvApply.visitEnd(); + writeClassFile(classWriter.toByteArray(), name); + return methDesc; + } + + private void writeClassFile(byte[] bytecode, String name) { + FileOutputStream output; + try { + System.out.println("generating " + name + ".class file..."); + output = new FileOutputStream( + new File(path + name + ".class")); + output.write(bytecode); + output.close(); + System.out.println(name + ".class file generated"); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + } + +} diff --git a/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodFromMethodCall.java b/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodFromMethodCall.java index 2028c7723..28d135e60 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodFromMethodCall.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodFromMethodCall.java @@ -23,6 +23,7 @@ public class MethodFromMethodCall { this.genericsAndBounds = genericsAndBounds; } + public ArgumentList getArgList() { return argList; } diff --git a/src/main/java/de/dhbwstuttgart/bytecode/utilities/Simplify.java b/src/main/java/de/dhbwstuttgart/bytecode/utilities/Simplify.java index 89b55efbe..2a4a3bd29 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/utilities/Simplify.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/utilities/Simplify.java @@ -19,7 +19,7 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; public class Simplify { public static HashMap> simplifyConstraints(String name, TPHExtractor tphExtractor, - ArrayList tphsClass) { + ArrayList tphsClass) { // 1. check if there are any simple cycles like L set L=R and: // * remove both constraints @@ -38,8 +38,10 @@ public class Simplify { ArrayList allCons = new ArrayList<>(); for(TPHConstraint c : tphExtractor.allCons) { - TPHConstraint nc = new TPHConstraint(c.getLeft(), c.getRight(), c.getRel()); - allCons.add(nc); + if(!containsConstraint(allCons,c)) { + TPHConstraint nc = new TPHConstraint(c.getLeft(), c.getRight(), c.getRel()); + allCons.add(nc); + } } ArrayList consToRemove = new ArrayList<>(); @@ -382,7 +384,7 @@ public class Simplify { if (!containTPH(methodTphs, superTphRes)) { HashSet equals = getEqualsTphsFromEqualCons(eqCons, superTphRes); - if (classTPHSContainsTPH(tphsClass, superTphRes)) { + if (tphsClass.contains(superTphRes)/*classTPHSContainsTPH(tphsClass, superTphRes)*/) { result.put(new ExtendsConstraint(subTphRes, superTphRes, Relation.EXTENDS), equals); } else { result.put(new ExtendsConstraint(subTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), @@ -450,6 +452,15 @@ public class Simplify { return result; } + private static boolean containsConstraint(ArrayList allCons, TPHConstraint c) { + for(TPHConstraint con:allCons) { + if(c.getLeft().equals(con.getLeft()) && c.getRight().equals(c.getRight())) { + return true; + } + } + return false; + } + private static void updateEqualCons(Map> replRes, ArrayList eqCons) { List oldNames = replRes.values().iterator().next(); String newName = replRes.keySet().iterator().next(); @@ -463,7 +474,7 @@ public class Simplify { } public static HashMap> simplifyConstraintsClass(TPHExtractor tphExtractor, - ArrayList tphsClass) { + ArrayList tphsClass) { // all constraints that will be simplified ArrayList allCons = tphExtractor.allCons; ArrayList consToRemove = new ArrayList<>(); @@ -627,7 +638,9 @@ public class Simplify { if (isTPHInConstraint(result, sub)) continue; - if (!classTPHSContainsTPH(tphsClass, sub)) +// if (!classTPHSContainsTPH(tphsClass, sub)) +// continue; + if (!tphsClass.contains(sub)) continue; if (numOfVisitedPairs >= size) @@ -656,7 +669,7 @@ public class Simplify { // add X at the beginning of the list. while (subAndSuper.containsValue(subTphRes)) { for (String tph : subAndSuper.keySet()) { - if (classTPHSContainsTPH(tphsClass, tph) && subAndSuper.get(tph).equals(subTphRes)) { + if (/*classTPHSContainsTPH(tphsClass, tph)*/tphsClass.contains(tph) && subAndSuper.get(tph).equals(subTphRes)) { subTphRes = tph; break; } diff --git a/src/main/java/de/dhbwstuttgart/bytecode/utilities/SimplifyResult.java b/src/main/java/de/dhbwstuttgart/bytecode/utilities/SimplifyResult.java index 96feb4dce..6517c2bcc 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/utilities/SimplifyResult.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/utilities/SimplifyResult.java @@ -16,10 +16,10 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; */ public class SimplifyResult { private final ArrayList classConstraints; - private final ArrayList tphsClass; + private final ArrayList tphsClass; private final HashMap>> methodsConstraints; - public SimplifyResult(ArrayList classConstraints, ArrayList tphsClass, + public SimplifyResult(ArrayList classConstraints, ArrayList tphsClass, HashMap>> methodsConstraints) { super(); this.classConstraints = classConstraints; @@ -35,7 +35,7 @@ public class SimplifyResult { return methodsConstraints; } - public ArrayList getTphsClass() { + public ArrayList getTphsClass() { return tphsClass; } diff --git a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java index c8c9802b9..9f1d17ebe 100644 --- a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -3,6 +3,7 @@ package de.dhbwstuttgart.core; import de.dhbwstuttgart.bytecode.BytecodeGen; +import de.dhbwstuttgart.bytecode.Exception.BytecodeGeneratorError; import de.dhbwstuttgart.bytecode.utilities.SimplifyResult; import de.dhbwstuttgart.environment.CompilationEnvironment; import de.dhbwstuttgart.parser.JavaTXParser; @@ -51,6 +52,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.antlr.v4.parse.ANTLRParser.throwsSpec_return; +import org.apache.commons.io.output.NullOutputStream; //import org.apache.commons.io.output.NullOutputStream; public class JavaTXCompiler { @@ -563,8 +565,8 @@ public class JavaTXCompiler { } /* UnifyResultModel End */ else { - Set> result = unify.unify(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure)); - //Set> result = unify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure)); + //Set> result = unify.unify(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure)); + Set> result = unify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure)); System.out.println("RESULT: " + result); logFile.write("RES: " + result.toString()+"\n"); logFile.flush(); @@ -650,7 +652,7 @@ public class JavaTXCompiler { return ret; } // um pfad erweitern - public void generateBytecode(String path) throws ClassNotFoundException, IOException { + public void generateBytecode(String path) throws ClassNotFoundException, IOException, BytecodeGeneratorError { for(File f : sourceFiles.keySet()) { HashMap classFiles = new HashMap<>(); SourceFile sf = sourceFiles.get(f); diff --git a/src/main/java/de/dhbwstuttgart/typeinference/result/GenericInsertPair.java b/src/main/java/de/dhbwstuttgart/typeinference/result/GenericInsertPair.java index 824d20838..f864905db 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/result/GenericInsertPair.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/result/GenericInsertPair.java @@ -23,4 +23,9 @@ public class GenericInsertPair { if(TA2.equals(additionalTPH))return true; return false; } + + @Override + public String toString() { + return "GenIns(" + TA1.toString() + " < " + TA2.toString() + ")"; + } } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHequalRefTypeOrWildcardType.java b/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHequalRefTypeOrWildcardType.java index 0bc1aee0f..0c0a5872a 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHequalRefTypeOrWildcardType.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHequalRefTypeOrWildcardType.java @@ -21,4 +21,9 @@ public class PairTPHequalRefTypeOrWildcardType extends ResultPair{ public void accept(ResultPairVisitor visitor) { visitor.visit(this); } + + @Override + public String toString() { + return "(" + left.toString() + " = " + right.toString() + ")"; + } } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHsmallerTPH.java b/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHsmallerTPH.java index bc605a279..8d586f4b5 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHsmallerTPH.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHsmallerTPH.java @@ -20,4 +20,9 @@ public class PairTPHsmallerTPH extends ResultPair{ public void accept(ResultPairVisitor visitor) { visitor.visit(this); } + + @Override + public String toString() { + return "(" + left.toString() + " < " + right.toString() + ")"; + } } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/result/ResolvedType.java b/src/main/java/de/dhbwstuttgart/typeinference/result/ResolvedType.java index b9e6985b2..eb43a2962 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/result/ResolvedType.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/result/ResolvedType.java @@ -8,10 +8,10 @@ import java.util.Set; public class ResolvedType{ public final RefTypeOrTPHOrWildcardOrGeneric resolvedType; - public final Set additionalGenerics; + //public final Set additionalGenerics; public ResolvedType(RefTypeOrTPHOrWildcardOrGeneric resolvedType, Set additionalGenerics){ this.resolvedType = resolvedType; - this.additionalGenerics = additionalGenerics; + //this.additionalGenerics = additionalGenerics; } } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java b/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java index 2f08d1eb8..51f3c1065 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java @@ -2,6 +2,7 @@ package de.dhbwstuttgart.typeinference.result; import java.util.HashSet; import java.util.Set; +import java.util.stream.Collectors; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; @@ -15,9 +16,14 @@ import static de.dhbwstuttgart.typeinference.result.ResultPairMap.RESULT_PAIRS; @SuppressWarnings("rawtypes") public class ResultSet { + public final Set results; - public ResultSet(Set set){ + public Set> genIns; + + public ResultSet(Set set){ this.results = set; + this.genIns = new HashSet<>(); + results.forEach(x -> { if (x instanceof PairTPHsmallerTPH) { this.genIns.add(x);}} ); } public boolean contains(ResultPair toCheck) { diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java index f1e3b7a79..e11c81bcc 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java @@ -19,6 +19,8 @@ import java.util.function.BinaryOperator; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.apache.commons.io.output.NullOutputStream; + import de.dhbwstuttgart.exceptions.TypeinferenceException; import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; @@ -46,6 +48,7 @@ import de.dhbwstuttgart.typeinference.unify.model.Pair; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.io.OutputStreamWriter; import java.io.Writer; import com.google.common.collect.Ordering; @@ -165,7 +168,9 @@ public class TypeUnifyTask extends RecursiveTask>> { thNo = totalnoOfThread; writeLog("thNo2 " + thNo); try { - this.logFile = new FileWriter(new File(System.getProperty("user.dir")+"/src/test/java/logFiles/"+"Thread_"+thNo)); + this.logFile = new OutputStreamWriter(new NullOutputStream()); + //new FileWriter(new File(System.getProperty("user.dir")+"/src/test/java/logFiles/"+"Thread_"+thNo)); + logFile.write(""); } catch (IOException e) { System.err.println("log-File nicht vorhanden"); diff --git a/src/test/java/bytecode/ClassGenLamTest.java b/src/test/java/bytecode/ClassGenLamTest.java new file mode 100644 index 000000000..33b9ee76a --- /dev/null +++ b/src/test/java/bytecode/ClassGenLamTest.java @@ -0,0 +1,37 @@ +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 ClassGenLamTest { + + 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")+"/src/test/resources/bytecode/javFiles/ClassGenLam.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("ClassGenLam"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + +} diff --git a/src/test/resources/bytecode/javFiles/ClassGenLam.jav b/src/test/resources/bytecode/javFiles/ClassGenLam.jav new file mode 100644 index 000000000..0e9cf0509 --- /dev/null +++ b/src/test/resources/bytecode/javFiles/ClassGenLam.jav @@ -0,0 +1,8 @@ +import java.lang.Integer; + +public class ClassGenLam { + lam = x-> x; +// public ClassGenLam() { +// lam = x->x; +// } +} \ No newline at end of file diff --git a/src/test/resources/bytecode/javFiles/Faculty.jav b/src/test/resources/bytecode/javFiles/Faculty.jav index 2754b7f82..6d85bb05a 100644 --- a/src/test/resources/bytecode/javFiles/Faculty.jav +++ b/src/test/resources/bytecode/javFiles/Faculty.jav @@ -1,22 +1,25 @@ import java.lang.Integer; +import java.lang.Long; +import java.lang.Short; public class Faculty { - public fact; - Faculty() { - fact = (x) -> { - if (x == 1) { - return 1; - } - else { - return x * (fact.apply(x-1)); - } - }; - } - - - public getFact(x) { - return fact.apply(x); - } + public fact; + Faculty() { + fact = (x) -> { + if (x == 1) { + return 1; + } + else { + return x * (fact.apply(x-1)); + } + }; + } + + + public getFact(x) { + return fact.apply(x); + } +} // m (x) { // //// var fact = (x) -> { diff --git a/src/test/resources/bytecode/javFiles/Id.jav b/src/test/resources/bytecode/javFiles/Id.jav index a8d85dfd1..5f84acc58 100644 --- a/src/test/resources/bytecode/javFiles/Id.jav +++ b/src/test/resources/bytecode/javFiles/Id.jav @@ -1,6 +1,6 @@ public class Id { - B id(A b){ + id(b){ return b; } } diff --git a/src/test/resources/bytecode/javFiles/Lambda.jav b/src/test/resources/bytecode/javFiles/Lambda.jav index b0321fc2a..ba466b180 100644 --- a/src/test/resources/bytecode/javFiles/Lambda.jav +++ b/src/test/resources/bytecode/javFiles/Lambda.jav @@ -7,4 +7,5 @@ public class Lambda { return x; }; return lam1; + } } diff --git a/src/test/resources/bytecode/javFiles/Matrix.jav b/src/test/resources/bytecode/javFiles/Matrix.jav index 4d1a45042..f8c426b42 100644 --- a/src/test/resources/bytecode/javFiles/Matrix.jav +++ b/src/test/resources/bytecode/javFiles/Matrix.jav @@ -19,7 +19,7 @@ public class Matrix extends Vector> { } } - mul(java.util.Vector> m) { + mul(m) { var ret = new Matrix(); var i = 0; while(i < size()) { diff --git a/src/test/resources/bytecode/javFiles/MatrixOP.jav b/src/test/resources/bytecode/javFiles/MatrixOP.jav index 4de9dc6c7..52c3fe964 100644 --- a/src/test/resources/bytecode/javFiles/MatrixOP.jav +++ b/src/test/resources/bytecode/javFiles/MatrixOP.jav @@ -18,7 +18,7 @@ public class MatrixOP extends Vector> { } } - Fun2$$>, java.util.Vector>, MatrixOP> mul = (m1, m2) -> { + public mul = (m1, m2) -> { var ret = new MatrixOP(); var i = 0; while(i < m1.size()) { diff --git a/src/test/resources/bytecode/javFiles/OL.jav b/src/test/resources/bytecode/javFiles/OL.jav index 700e50f0a..83361d3cc 100644 --- a/src/test/resources/bytecode/javFiles/OL.jav +++ b/src/test/resources/bytecode/javFiles/OL.jav @@ -10,8 +10,6 @@ public class OL { } - - public class OLMain { main(x) { diff --git a/src/test/resources/bytecode/javFiles/TypedID.jav b/src/test/resources/bytecode/javFiles/TypedID.jav index 6e2477a58..aa8858315 100644 --- a/src/test/resources/bytecode/javFiles/TypedID.jav +++ b/src/test/resources/bytecode/javFiles/TypedID.jav @@ -1,6 +1,12 @@ public class TypedID/* */ { - - id(K b){ + + lam = x-> x; + + id(b){ return b; } + + m(){ + return lam; + } } \ No newline at end of file