From 11bee80969c9f0a47872a6777dc7eea8e84ad68a Mon Sep 17 00:00:00 2001 From: Michael Uhl Date: Sat, 27 Apr 2019 16:29:38 +0200 Subject: [PATCH] =?UTF-8?q?Bytecode-Generierung=20generiert=20jetzt=20wied?= =?UTF-8?q?er=20Bytecode=20f=C3=BCr=20alle=20m=C3=B6glichen=20Typen.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dhbwstuttgart/bytecode/BytecodeGen.java | 1353 +++++++++-------- .../typeinference/result/ResultSet.java | 20 +- 2 files changed, 693 insertions(+), 680 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java index 8ae7da1e..eddca626 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -1,676 +1,677 @@ -package de.dhbwstuttgart.bytecode; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import 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 List 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, 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, 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.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(); + } + + +} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java b/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java index 9b9aef4e..2f08d1eb 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java @@ -32,22 +32,34 @@ public class ResultSet { if(type instanceof TypePlaceholder) return new Resolver(this).resolve((TypePlaceholder)type); if(type instanceof GenericRefType)return new ResolvedType(type, new HashSet<>()); - if(type instanceof RefType){ + if(type instanceof RefType) { RelatedTypeWalker related = new RelatedTypeWalker(null, this); type.accept(related); return new ResolvedType(type, related.relatedTPHs); - }else{ + } else { throw new NotImplementedException(); //return new ResolvedType(type,new HashSet<>()); } } - //TODO Beim Einsetzen eines Generics, müssen die new und Methodenaufrufe verändert werden - public String toString() { return results.toString(); } + @Override + public boolean equals(Object o) { + if (o instanceof ResultSet) { + ResultSet other = (ResultSet)o; + return this.results.equals(other.results); + } else { + return false; + } + } + + @Override + public int hashCode() { + return results.hashCode(); + } } class Resolver implements ResultSetVisitor {