From 73f412d22d1e30e8612f16914e60ec7dea3a67f4 Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia <fayez.abu-alia@student.uni-tuebingen.de> Date: Fri, 26 Apr 2019 11:56:58 +0200 Subject: [PATCH] Klassendatei fuer FunN beim Methodaufruf wird erzeugt, wenn der Receiver den Typ FunN besitzt. Die Loesung vom Duplicate Field Problem wird angepasst. --- .../dhbwstuttgart/bytecode/BytecodeGen.java | 435 +++++++++--------- .../bytecode/BytecodeGenMethod.java | 35 +- .../bytecode/signature/Signature.java | 6 +- .../bytecode/utilities/MethodCallHelper.java | 72 ++- .../utilities/MethodFromMethodCall.java | 1 + 5 files changed, 310 insertions(+), 239 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java index e721fd9f..0ff140b3 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -46,11 +46,11 @@ 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); - + + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + String type; - + public static RefTypeOrTPHOrWildcardOrGeneric THISTYPE = null; String className; private boolean isInterface; @@ -58,35 +58,38 @@ public class BytecodeGen implements ASTVisitor { private ResultSet resultSet; private SourceFile sf; private String path; - + private Optional<Constructor> fieldInitializations; - + private int indexOfFirstParam = 0; - + private String superClass; - + private ArrayList<String> tphsClass; - - // stores parameter, local vars and the next index on the local variable table, which use for aload_i, astore_i,... + + // stores parameter, local vars and the next index on the local variable table, + // which use for aload_i, astore_i,... HashMap<String, Integer> paramsAndLocals = new HashMap<>(); // stores generics and their bounds of class HashMap<String, String> genericsAndBounds = new HashMap<>(); - + private int constructorPos = 0; - + private final TPHExtractor tphExtractor = new TPHExtractor(); private final ArrayList<GenericInsertPair> commonPairs = new ArrayList<>(); - - HashMap<String,RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes = new HashMap<>(); + + HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes = new HashMap<>(); byte[] bytecode; - HashMap<String,byte[]> classFiles; - + HashMap<String, byte[]> classFiles; + private final ArrayList<String> methodNameAndParamsT = new ArrayList<>(); private final ArrayList<String> fieldNameAndParamsT = new ArrayList<>(); - + private HashMap<String, SimplifyResult> simplifyResults = new HashMap<>(); private List<HashMap<String, SimplifyResult>> simplifyResultsList = new ArrayList<>(); - + + private final ArrayList<String> fieldNameSignature = new ArrayList<>(); + public List<HashMap<String, SimplifyResult>> getSimplifyResultsList() { return simplifyResultsList; } @@ -95,16 +98,17 @@ public class BytecodeGen implements ASTVisitor { this.simplifyResultsList = simplifyResultsList; } - public BytecodeGen(HashMap<String,byte[]> classFiles, List<ResultSet> listOfResultSets,SourceFile sf ,String path) { + public BytecodeGen(HashMap<String, byte[]> classFiles, List<ResultSet> 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()) { + for (ClassOrInterface cl : sourceFile.getClasses()) { System.out.println("in Class: " + cl.getClassName().toString()); BytecodeGen classGen = new BytecodeGen(classFiles, listOfResultSets, sf, path); cl.accept(classGen); @@ -112,73 +116,74 @@ public class BytecodeGen implements ASTVisitor { 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} + * 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<String,byte[]> getClassFiles() { + + public HashMap<String, byte[]> 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; - + 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) { + for (ResultSet rs : listOfResultSets) { superClass = classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()); resultSet = rs; tphExtractor.setResultSet(resultSet); - + // Nur einmal ausführen!! - if(!isVisited) { + if (!isVisited) { classOrInterface.accept(tphExtractor); getCommonTPHS(tphExtractor); - + tphsClass = new ArrayList<>(); - for(String t : tphExtractor.allTPHS.keySet()) { - if(!tphExtractor.allTPHS.get(t)) + 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: - * <E:Ljava/...>Superclass + /* + * if class has generics then creates signature Signature looks like: + * <E:Ljava/...>Superclass */ - if(classOrInterface.getGenerics().iterator().hasNext() || !commonPairs.isEmpty() || - classOrInterface.getSuperClass().acceptTV(new TypeToSignature()).contains("<") + if (classOrInterface.getGenerics().iterator().hasNext() || !commonPairs.isEmpty() + || classOrInterface.getSuperClass().acceptTV(new TypeToSignature()).contains("<") || !tphsClass.isEmpty()) { - HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraintsClass(tphExtractor,tphsClass); + HashMap<TPHConstraint, HashSet<String>> constraints = Simplify + .simplifyConstraintsClass(tphExtractor, tphsClass); ArrayList<TPHConstraint> consClass = new ArrayList<>(); - for(TPHConstraint cons : constraints.keySet()) { + for (TPHConstraint cons : constraints.keySet()) { String right = null; boolean isToAdd = false; - for(String tph : tphsClass) { - if(cons.getLeft().equals(tph)) { - + for (String tph : tphsClass) { + if (cons.getLeft().equals(tph)) { + consClass.add(cons); try { right = getTPH(cons.getRight()); @@ -186,14 +191,14 @@ public class BytecodeGen implements ASTVisitor { } catch (NoSuchElementException e) { continue; } - + } } - if(isToAdd) { + if (isToAdd) { tphsClass.add(right); removeFromMethod(right); right = null; - isToAdd= false; + isToAdd = false; } // if(right != null) { // tphsClass.add(right); @@ -201,73 +206,74 @@ public class BytecodeGen implements ASTVisitor { // right = null; // } } - + SimplifyResult sRes = new SimplifyResult(consClass, tphsClass, new HashMap<>()); simplifyResults.put(className, sRes); - - Signature signature = new Signature(classOrInterface, genericsAndBounds,commonPairs,tphsClass, consClass); + + 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); - + + cw.visit(Opcodes.V1_8, acc, classOrInterface.getClassName().toString(), sig, + classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()), null); + isVisited = true; } - - for(Field f : classOrInterface.getFieldDecl()) { + + for (Field f : classOrInterface.getFieldDecl()) { f.accept(this); } - - for(Constructor c : classOrInterface.getConstructors()) { + + for (Constructor c : classOrInterface.getConstructors()) { // if(!isConsWithNoParamsVisited) { - c.accept(this); + c.accept(this); // } - + // if(!c.getParameterList().iterator().hasNext()) // isConsWithNoParamsVisited = true; } - - for(Method m : classOrInterface.getMethods()) { + + for (Method m : classOrInterface.getMethods()) { m.accept(this); } - + } - + } private void removeFromMethod(String name) { - for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) { + for (MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) { ArrayList<String> toRemove = new ArrayList<>(); - for(String tph : m.getTphs()) { - if(tph.equals(name)) { + for (String tph : m.getTphs()) { + if (tph.equals(name)) { toRemove.add(tph); } } - - if(!toRemove.isEmpty()) { + + if (!toRemove.isEmpty()) { m.getTphs().removeAll(toRemove); return; } } - + } private String getTPH(String name) { - for(String tph: tphExtractor.allTPHS.keySet()) { - if(tph.equals(name)) + for (String tph : tphExtractor.allTPHS.keySet()) { + if (tph.equals(name)) return tph; } - throw new NoSuchElementException("TPH "+name +" does not exist"); + throw new NoSuchElementException("TPH " + name + " does not exist"); } private void getCommonTPHS(TPHExtractor tphExtractor) { // Gemeinsame TPHs ArrayList<String> cTPHs = new ArrayList<>(); // Alle TPHs der Felder speichern - for(String tph : tphExtractor.allTPHS.keySet()) { - if(!tphExtractor.allTPHS.get(tph)) + for (String tph : tphExtractor.allTPHS.keySet()) { + if (!tphExtractor.allTPHS.get(tph)) cTPHs.add(tph); } } @@ -275,157 +281,168 @@ public class BytecodeGen implements ASTVisitor { @Override public void visit(Constructor field) { System.out.println("ResultSet: "); - resultSet.results.forEach(a->{ + resultSet.results.forEach(a -> { System.out.println(a.getLeft().toString() + " = " + a.getRight().toString()); }); System.out.println("---------------"); - + // stores generics and their bounds of method HashMap<String, String> genericsAndBoundsMethod = new HashMap<>(); - + field.getParameterList().accept(this); - - String methParamTypes = field.name+"%%"; - + + String methParamTypes = field.name + "%%"; + Iterator<FormalParameter> itr = field.getParameterList().iterator(); - while(itr.hasNext()) { + while (itr.hasNext()) { FormalParameter fp = itr.next(); - methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+";"; + 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); + + 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); - + System.out.println("Method: " + field.name + " , paramsType: " + methParamTypes); + String desc = null; boolean hasGen = false; - - for(String paramName : methodParamsAndTypes.keySet()) { + + 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("<")) { + if (genericsAndBounds.containsKey(typeOfParam) || typeOfParam.contains("$") || typeOfParam.contains("<")) { hasGen = true; break; } } String sig = null; - if(hasGen) { - HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraints(field.name, tphExtractor,tphsClass); - Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes,resultSet,constraints); + if (hasGen) { + HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraints(field.name, tphExtractor, + tphsClass); + Signature signature = new Signature(field, genericsAndBounds, methodParamsAndTypes, resultSet, constraints); sig = signature.toString(); } - if(field.getParameterList().iterator().hasNext()) + if (field.getParameterList().iterator().hasNext()) System.out.println(field.getParameterList().iterator().next().getType().acceptTV(new TypeToDescriptor())); - - NormalConstructor constructor = new NormalConstructor(field,genericsAndBounds,hasGen); + + NormalConstructor constructor = new NormalConstructor(field, genericsAndBounds, hasGen); desc = constructor.accept(new DescriptorToString(resultSet)); - System.out.println("Constructor: " + field.getName() + " Sig: "+ sig + " Desc: " + desc); + System.out.println("Constructor: " + field.getName() + " Sig: " + sig + " Desc: " + desc); MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", desc, sig, null); - mv.visitCode(); - + 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)) { + + 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 + // 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+"%%"; + String methParamTypes = retType + method.name + "%%"; method.getParameterList().accept(this); Iterator<FormalParameter> itr = method.getParameterList().iterator(); - while(itr.hasNext()) { + while (itr.hasNext()) { FormalParameter fp = itr.next(); - methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+";"; + methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()) + ";"; // methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToSignature())+";"; } - - if(methodNameAndParamsT.contains(methParamTypes)) { + + if (methodNameAndParamsT.contains(methParamTypes)) { return; } methodNameAndParamsT.add(methParamTypes); - System.out.println("Method: "+method.name +" , paramsType: "+methParamTypes); + System.out.println("Method: " + method.name + " , paramsType: " + methParamTypes); // stores generics and their bounds of method HashMap<String, String> genericsAndBoundsMethod = new HashMap<>(); String methDesc = null; - + // Method getModifiers() ? - int acc = isInterface?Opcodes.ACC_ABSTRACT:method.modifier; + 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()) { + + /* 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("<")) { + 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. - + // 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(..) - * */ + /* + * 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")) { + 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())); + tphExtractor.allCons.forEach(c -> System.out.println(c.toString())); System.out.println("----------------"); - HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraints(method.name, tphExtractor, tphsClass); + HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraints(method.name, + tphExtractor, tphsClass); // ArrayList<GenericInsertPair> pairs = simplifyPairs(method.name,tphExtractor.allPairs,tphExtractor.allCons); - Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds,methodParamsAndTypes,resultSet,constraints); + Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds, + methodParamsAndTypes, resultSet, constraints); sig = signature.toString(); - if(simplifyResults.containsKey(className)) { + 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); - + } + 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<String, SimplifyResult> getSimplifyResults() { return simplifyResults; } @@ -436,7 +453,7 @@ public class BytecodeGen implements ASTVisitor { methodParamsAndTypes = new HashMap<>(); Iterator<FormalParameter> itr = formalParameters.iterator(); int i = 1; - while(itr.hasNext()) { + while (itr.hasNext()) { FormalParameter fp = itr.next(); paramsAndLocals.put(fp.getName(), i); methodParamsAndTypes.put(fp.getName(), resultSet.resolveType(fp.getType()).resolvedType); @@ -444,39 +461,39 @@ public class BytecodeGen implements ASTVisitor { i++; } } - + @Override public void visit(FormalParameter formalParameter) { formalParameter.getType().accept(this); } - + @Override public void visit(RefType refType) { - type = "L"+refType.toString()+";"; + 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 - + } // ?? @@ -484,48 +501,51 @@ public class BytecodeGen implements ASTVisitor { 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); + 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) { + if (resultSet.resolveType(field.getType()).resolvedType instanceof TypePlaceholder) { des += Type.getInternalName(Object.class); } else { des += resultSet.resolveType(field.getType()).resolvedType.acceptTV(new TypeToDescriptor()); } - des +=";"; + 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 +=";"; - } + if (sig.charAt(sig.length() - 1) != (";").charAt(0)) { + sig += ";"; + } String nameAndDesc = field.getName() + "%%" + des; - - if(fieldNameAndParamsT.contains(nameAndDesc)) + 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); - - cw.visitField(field.modifier, field.getName(), - des, sig, - null); + 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 @@ -536,151 +556,151 @@ public class BytecodeGen implements ASTVisitor { @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 @@ -693,6 +713,5 @@ public class BytecodeGen implements ASTVisitor { 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 f047e251..abf7237a 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -678,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); @@ -778,9 +778,9 @@ public class BytecodeGenMethod implements StatementVisitor { String mDesc = ""; - MethodCallHelper helper = new MethodCallHelper(methodCall, sf, resultSet); + MethodCallHelper helper = new MethodCallHelper(methodCall, sf, resultSet, path); - boolean isCreated = false; + boolean toCreate = false; ClassLoader cLoader = ClassLoader.getSystemClassLoader(); // This will be used if the class is not standard class (not in API) @@ -799,7 +799,6 @@ public class BytecodeGenMethod implements StatementVisitor { } catch (Exception e) { String superClass = ""; - // TODO: Test SubMatrix.jav while(true) { try { superClass = helper.getSuperClass(receiverName); @@ -833,25 +832,29 @@ public class BytecodeGenMethod implements StatementVisitor { } if(methodRefl == null) { - isCreated = !receiverName.equals(className) && helper.isInCurrPkg(clazz); - if(isCreated) { + toCreate = !receiverName.equals(className) && helper.isInCurrPkg(clazz); + if(toCreate) { try { mDesc = helper.getDesc(clazz); } catch (NotInCurrentPackageException | NotFoundException e) { e.printStackTrace(); } } else if(!helper.isInCurrPkg(clazz)){ - 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<methods.length; i++) { - System.out.println(methods[i]); + if(clazz.contains("$$")) { + mDesc = helper.generateBCForFunN(); + }else { + 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<methods.length; i++) { + System.out.println(methods[i]); + } + methodRefl = getMethod(methodCall.name,methodCall.arglist.getArguments().size(),methCallType, typesOfParams,methods); + } + catch (Exception e2) { + e2.printStackTrace(); } - methodRefl = getMethod(methodCall.name,methodCall.arglist.getArguments().size(),methCallType, typesOfParams,methods); - } - catch (Exception e2) { - e2.printStackTrace(); } } diff --git a/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java b/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java index dd7f5d60..62a55d12 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -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<numberOfParams;i++) { diff --git a/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodCallHelper.java b/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodCallHelper.java index 7a48d10b..afeaa6c1 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodCallHelper.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodCallHelper.java @@ -3,6 +3,10 @@ */ 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; @@ -11,11 +15,17 @@ 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; @@ -23,6 +33,8 @@ 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; @@ -38,16 +50,19 @@ 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) { + 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) { @@ -189,19 +204,52 @@ public class MethodCallHelper { } } - private String createDesc(Method m) { - String desc = "("; - for (FormalParameter fp : m.getParameterList()) { - String typeName = getResolvedType(fp.getType()); - RefTypeOrTPHOrWildcardOrGeneric type = resultSet.resolveType(fp.getType()).resolvedType; - if (type instanceof TypePlaceholder) { - desc += "L" + Type.getInternalName(Object.class) + ";"; - } else if (type instanceof GenericRefType) { - GenericRefType grt = (GenericRefType) type; + 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<Expression> itr1 = methCall.arglist.getArguments().iterator(); + String methDesc = "("; + while(itr1.hasNext()) { + numberOfParams++; + // getBounds + paramVisitor.visitTypeVariable("T" + numberOfParams); + methDesc += "L" + Type.getInternalName(Object.class) + ";"; + itr1.next(); } - return null; + 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 2028c772..28d135e6 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; }