From 602216d9e2a4a14709813a92242f33aea25e8617 Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Thu, 11 Apr 2019 11:26:54 +0200 Subject: [PATCH 1/9] Generics beruecksichtigt --- .../dhbwstuttgart/bytecode/BytecodeGen.java | 39 ++++++---- .../dhbwstuttgart/bytecode/TPHExtractor.java | 78 +++++++++++++++++-- .../bytecode/signature/Signature.java | 4 +- .../bytecode/utilities/Simplify.java | 27 +++++-- .../bytecode/utilities/SimplifyResult.java | 6 +- src/test/java/bytecode/ClassGenLamTest.java | 37 +++++++++ .../bytecode/javFiles/ClassGenLam.jav | 8 ++ 7 files changed, 169 insertions(+), 30 deletions(-) create mode 100644 src/test/java/bytecode/ClassGenLamTest.java create mode 100644 src/test/resources/bytecode/javFiles/ClassGenLam.jav diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java index 8ae7da1e..d5dba757 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -64,7 +64,7 @@ public class BytecodeGen implements ASTVisitor { private String superClass; - private ArrayList tphsClass; + 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<>(); @@ -156,7 +156,7 @@ public class BytecodeGen implements ASTVisitor { getCommonTPHS(tphExtractor); tphsClass = new ArrayList<>(); - for(TypePlaceholder t : tphExtractor.allTPHS.keySet()) { + for(String t : tphExtractor.allTPHS.keySet()) { if(!tphExtractor.allTPHS.get(t)) tphsClass.add(t); } @@ -172,19 +172,32 @@ public class BytecodeGen implements ASTVisitor { 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())) { + String right = null; + boolean isToAdd = false; + for(String tph : tphsClass) { + if(cons.getLeft().equals(tph)) { consClass.add(cons); - right = getTPH(cons.getRight()); + try { + right = getTPH(cons.getRight()); + isToAdd = true; + } catch (NoSuchElementException e) { + continue; + } + } } - if(right != null) { + if(isToAdd) { tphsClass.add(right); - removeFromMethod(right.getName()); + removeFromMethod(right); right = null; + isToAdd= false; } +// if(right != null) { +// tphsClass.add(right); +// removeFromMethod(right); +// right = null; +// } } SimplifyResult sRes = new SimplifyResult(consClass, tphsClass, new HashMap<>()); @@ -239,9 +252,9 @@ public class BytecodeGen implements ASTVisitor { } - private TypePlaceholder getTPH(String name) { - for(TypePlaceholder tph: tphExtractor.allTPHS.keySet()) { - if(tph.getName().equals(name)) + 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"); @@ -249,9 +262,9 @@ public class BytecodeGen implements ASTVisitor { private void getCommonTPHS(TPHExtractor tphExtractor) { // Gemeinsame TPHs - ArrayList cTPHs = new ArrayList<>(); + ArrayList cTPHs = new ArrayList<>(); // Alle TPHs der Felder speichern - for(TypePlaceholder tph : tphExtractor.allTPHS.keySet()) { + for(String tph : tphExtractor.allTPHS.keySet()) { if(!tphExtractor.allTPHS.get(tph)) cTPHs.add(tph); } diff --git a/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java b/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java index c100eb4a..36753138 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java @@ -5,7 +5,11 @@ package de.dhbwstuttgart.bytecode; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint; import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; @@ -13,11 +17,15 @@ import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; import de.dhbwstuttgart.syntaxtree.AbstractASTWalker; import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.Field; import de.dhbwstuttgart.syntaxtree.FormalParameter; import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.ParameterList; import de.dhbwstuttgart.syntaxtree.statement.LocalVar; import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.result.GenericInsertPair; import de.dhbwstuttgart.typeinference.result.ResultSet; @@ -29,7 +37,7 @@ import de.dhbwstuttgart.typeinference.result.ResultSet; public class TPHExtractor extends AbstractASTWalker { // Alle TPHs der Felder werden iKopf der Klasse definiert // alle TPHs der Klasse: (TPH, is in Method?) - final HashMap allTPHS = new HashMap<>(); + final HashMap allTPHS = new HashMap<>(); MethodAndTPH methodAndTph; Boolean inMethod = false; @@ -58,19 +66,79 @@ public class TPHExtractor extends AbstractASTWalker { methodAndTph.getLocalTphs().add(resolvedTPH.getName()); } - allTPHS.put(resolvedTPH, inMethod); + 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).additionalGenerics.forEach(ag -> { - if (ag.contains(resolvedTPH) && ag.TA1.equals(resolvedTPH) && !contains(allPairs, 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); - } + 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 ca191b7d..c3891a61 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; diff --git a/src/main/java/de/dhbwstuttgart/bytecode/utilities/Simplify.java b/src/main/java/de/dhbwstuttgart/bytecode/utilities/Simplify.java index 89b55efb..2a4a3bd2 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 96feb4dc..6517c2bc 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/test/java/bytecode/ClassGenLamTest.java b/src/test/java/bytecode/ClassGenLamTest.java new file mode 100644 index 00000000..33b9ee76 --- /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 00000000..0e9cf050 --- /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 From 588212389ac1bab505d0f500e839a23cb5528b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Pl=C3=BCmicke?= Date: Fri, 12 Apr 2019 10:28:39 +0200 Subject: [PATCH 2/9] Die Bestimmung der Constraints aus dem ResolvedType herausgenommen und im ResultSet integriert. Damit kommen immer die gleichen Constraints raus. Diese werden ohnehin in der Bytecodegenerierung nochmals ausgewertet. modified: ../../../../main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java Zugriff auf Constraints ueber ResultSet eingefuehrt modified: ../../../../main/java/de/dhbwstuttgart/bytecode/signature/Signature.java Zugriff auf Constraints ueber ResultSet eingefuehrt modified: ../../../../main/java/de/dhbwstuttgart/core/JavaTXCompiler.java modified: ../../../../main/java/de/dhbwstuttgart/typeinference/result/GenericInsertPair.java modified: ../../../../main/java/de/dhbwstuttgart/typeinference/result/PairTPHequalRefTypeOrWildcardType.java modified: ../../../../main/java/de/dhbwstuttgart/typeinference/result/PairTPHsmallerTPH.java toString veraendert modified: ../../../../main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java Attribut genIns eingefuehrt, indem alle GenericInsertPairs gespeichert werden, die Form (TPH a <. TPH b) im Attribut results haben modified: ../../../../main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java modified: ../../bytecode/javFiles/Id.jav modified: ../../bytecode/javFiles/MatrixOP.jav --- src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java | 3 ++- .../de/dhbwstuttgart/bytecode/signature/Signature.java | 6 ++++-- src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java | 5 +++-- .../typeinference/result/GenericInsertPair.java | 5 +++++ .../result/PairTPHequalRefTypeOrWildcardType.java | 5 +++++ .../typeinference/result/PairTPHsmallerTPH.java | 5 +++++ .../de/dhbwstuttgart/typeinference/result/ResultSet.java | 5 +++++ .../dhbwstuttgart/typeinference/unify/TypeUnifyTask.java | 7 ++++++- src/test/resources/bytecode/javFiles/Id.jav | 2 +- src/test/resources/bytecode/javFiles/MatrixOP.jav | 4 ++-- 10 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java b/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java index 36753138..e9f8e257 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java @@ -90,7 +90,8 @@ public class TPHExtractor extends AbstractASTWalker { // } // } - resultSet.resolveType(tph).additionalGenerics.forEach(ag -> { + //resultSet.resolveType(tph).getAdditionalGenerics().forEach(ag -> { + resultSet.genIns.forEach(ag -> { // if (ag.contains(resolvedTPH) /* && ag.TA1.equals(resolvedTPH) */ && !contains(allPairs, ag)) { if (inMethod) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java b/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java index c3891a61..94052f9c 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -235,7 +235,8 @@ public class Signature { RefTypeOrTPHOrWildcardOrGeneric resolved = resType.resolvedType; if(resolved instanceof TypePlaceholder) { - resType.additionalGenerics.forEach(ag ->{ + //resType.getAdditionalGenerics().forEach(ag ->{ + resultSet.genIns.forEach(ag ->{ TPHConstraint constr = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); if(!contains(res,constr)) { res.add(constr); @@ -246,7 +247,8 @@ public class Signature { WildcardType resWC = (WildcardType) resolved; ResolvedType resType2 = resultSet.resolveType(resWC.getInnerType()); if(resType2.resolvedType instanceof TypePlaceholder) { - resType2.additionalGenerics.forEach(ag ->{ + //resType2.getAdditionalGenerics().forEach(ag ->{ + resultSet.genIns.forEach(ag ->{ TPHConstraint constr = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); if(!contains(res,constr)) { res.add(constr); diff --git a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java index c8c9802b..0d13045f 100644 --- a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -51,6 +51,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 +564,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(); diff --git a/src/main/java/de/dhbwstuttgart/typeinference/result/GenericInsertPair.java b/src/main/java/de/dhbwstuttgart/typeinference/result/GenericInsertPair.java index 824d2083..f864905d 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 0bc1aee0..0c0a5872 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 bc605a27..8d586f4b 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/ResultSet.java b/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java index eef72ab0..955c388b 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java @@ -6,11 +6,16 @@ import de.dhbwstuttgart.syntaxtree.type.*; import java.util.HashSet; import java.util.Set; +import java.util.stream.Collectors; public class ResultSet { public final Set results; + public Set genIns; public ResultSet(Set results){ this.results = results; + this.genIns = results.stream().filter(a -> a instanceof PairTPHsmallerTPH) + .map(b -> new GenericInsertPair( (TypePlaceholder)(b.getLeft()), (TypePlaceholder)(b.getRight()))) + .collect(Collectors.toCollection(HashSet::new)); } public ResolvedType resolveType(RefTypeOrTPHOrWildcardOrGeneric type) { diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java index f1e3b7a7..e11c81bc 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/resources/bytecode/javFiles/Id.jav b/src/test/resources/bytecode/javFiles/Id.jav index a8d85dfd..5f84acc5 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/MatrixOP.jav b/src/test/resources/bytecode/javFiles/MatrixOP.jav index 4de9dc6c..991db9c0 100644 --- a/src/test/resources/bytecode/javFiles/MatrixOP.jav +++ b/src/test/resources/bytecode/javFiles/MatrixOP.jav @@ -1,6 +1,6 @@ import java.util.Vector; import java.lang.Integer; -import java.lang.Byte; +//import java.lang.Byte; import java.lang.Boolean; public class MatrixOP extends Vector> { @@ -18,7 +18,7 @@ public class MatrixOP extends Vector> { } } - Fun2$$>, java.util.Vector>, MatrixOP> mul = (m1, m2) -> { + mul = (m1, m2) -> { var ret = new MatrixOP(); var i = 0; while(i < m1.size()) { From e086ff187e9f34ac9da310d5616277a7da2fa7e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Pl=C3=BCmicke?= Date: Fri, 12 Apr 2019 10:41:42 +0200 Subject: [PATCH 3/9] modified: ../../../../main/java/de/dhbwstuttgart/typeinference/result/ResolvedType.java Attribut additionalGenerics auskommentiert. --- .../de/dhbwstuttgart/typeinference/result/ResolvedType.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/typeinference/result/ResolvedType.java b/src/main/java/de/dhbwstuttgart/typeinference/result/ResolvedType.java index b9e6985b..eb43a296 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; } } From 709041f024d215df4a5384b3a6b6b791ece2f166 Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Thu, 18 Apr 2019 10:48:59 +0200 Subject: [PATCH 4/9] Adapted TypedID jav-file --- src/test/resources/bytecode/javFiles/TypedID.jav | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/test/resources/bytecode/javFiles/TypedID.jav b/src/test/resources/bytecode/javFiles/TypedID.jav index 6e2477a5..aa885831 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 From 6a519ff6dca1e2ccf5f0a7211fe54fa4fa813706 Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Thu, 18 Apr 2019 13:17:50 +0200 Subject: [PATCH 5/9] Ein Feld wird nur einmal in Bytecode uebersetzt. genIns in ResultSet wird angepasst. --- .../java/de/dhbwstuttgart/bytecode/BytecodeGen.java | 12 ++++++++++-- .../java/de/dhbwstuttgart/bytecode/TPHExtractor.java | 5 +++-- .../dhbwstuttgart/bytecode/signature/Signature.java | 4 ++-- .../bytecode/utilities/MethodAndTPH.java | 10 ++++++++-- .../typeinference/result/ResultSet.java | 4 ++-- src/test/resources/bytecode/javFiles/MatrixOP.jav | 2 +- 6 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java index d5dba757..f901036f 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -80,7 +80,8 @@ public class BytecodeGen implements ASTVisitor { byte[] bytecode; HashMap classFiles; - ArrayList methodNameAndParamsT = new ArrayList<>(); + private final ArrayList methodNameAndParamsT = new ArrayList<>(); + private final ArrayList fieldNameAndParamsT = new ArrayList<>(); private HashMap simplifyResults = new HashMap<>(); private List> simplifyResultsList = new ArrayList<>(); @@ -501,7 +502,14 @@ public class BytecodeGen implements ASTVisitor { System.out.println(sig); if(sig.charAt(sig.length()-1) != (";").charAt(0)) { sig +=";"; - } + } + String nameAndDesc = field.getName() + "%%" + des; + + if(fieldNameAndParamsT.contains(nameAndDesc)) + return; + + fieldNameAndParamsT.add(nameAndDesc); + cw.visitField(field.modifier, field.getName(), des, sig, null); diff --git a/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java b/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java index e9f8e257..66723205 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java @@ -28,6 +28,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.result.GenericInsertPair; +import de.dhbwstuttgart.typeinference.result.ResultPair; import de.dhbwstuttgart.typeinference.result.ResultSet; /** @@ -44,7 +45,7 @@ public class TPHExtractor extends AbstractASTWalker { 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; @@ -97,7 +98,7 @@ public class TPHExtractor extends AbstractASTWalker { if (inMethod) methodAndTph.getPairs().add(ag); allPairs.add(ag); - TPHConstraint con = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); + TPHConstraint con = new ExtendsConstraint(ag.getLeft().getName(), ag.getRight().getName(), Relation.EXTENDS); if(!containsConstraint(allCons,con)) allCons.add(con); // } diff --git a/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java b/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java index 94052f9c..dd7f5d60 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -237,7 +237,7 @@ public class Signature { if(resolved instanceof TypePlaceholder) { //resType.getAdditionalGenerics().forEach(ag ->{ resultSet.genIns.forEach(ag ->{ - TPHConstraint constr = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); + TPHConstraint constr = new ExtendsConstraint(ag.getLeft().getName(), ag.getRight().getName(), Relation.EXTENDS); if(!contains(res,constr)) { res.add(constr); } @@ -249,7 +249,7 @@ public class Signature { if(resType2.resolvedType instanceof TypePlaceholder) { //resType2.getAdditionalGenerics().forEach(ag ->{ resultSet.genIns.forEach(ag ->{ - TPHConstraint constr = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); + 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 e21f974c..c2c0210e 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/typeinference/result/ResultSet.java b/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java index 955c388b..8858f364 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java @@ -10,11 +10,11 @@ import java.util.stream.Collectors; public class ResultSet { public final Set results; - public Set genIns; + public Set> genIns; public ResultSet(Set results){ this.results = results; this.genIns = results.stream().filter(a -> a instanceof PairTPHsmallerTPH) - .map(b -> new GenericInsertPair( (TypePlaceholder)(b.getLeft()), (TypePlaceholder)(b.getRight()))) + //.map(b -> new GenericInsertPair( (TypePlaceholder)(b.getLeft()), (TypePlaceholder)(b.getRight()))) .collect(Collectors.toCollection(HashSet::new)); } diff --git a/src/test/resources/bytecode/javFiles/MatrixOP.jav b/src/test/resources/bytecode/javFiles/MatrixOP.jav index 991db9c0..21d37347 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> { } } - mul = (m1, m2) -> { + public mul = (m1, m2) -> { var ret = new MatrixOP(); var i = 0; while(i < m1.size()) { From d9f084cd0f05f10d58c194c4b603035ffe1a5fd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Pl=C3=BCmicke?= Date: Sun, 21 Apr 2019 22:31:55 +0200 Subject: [PATCH 6/9] modified: ../../bytecode/javFiles/Faculty.jav neue Imports hinzugefuegt --- .../resources/bytecode/javFiles/Faculty.jav | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/test/resources/bytecode/javFiles/Faculty.jav b/src/test/resources/bytecode/javFiles/Faculty.jav index 2754b7f8..6d85bb05 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) -> { From 5950fcc0a97d2876596fa1518ac23eacb5149a0e Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Wed, 24 Apr 2019 15:43:00 +0200 Subject: [PATCH 7/9] Neue Klasse MethodCallHelper und Exceptions definiert, die fuer die Uebersetzung von MethodCalls verwendet werden --- .../bytecode/BytecodeGenMethod.java | 128 +++++++---- .../bytecode/Exception/NotFoundException.java | 25 +++ .../NotInCurrentPackageException.java | 26 +++ .../bytecode/utilities/MethodCallHelper.java | 207 ++++++++++++++++++ src/test/resources/bytecode/javFiles/OL.jav | 2 - 5 files changed, 342 insertions(+), 46 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/bytecode/Exception/NotFoundException.java create mode 100644 src/main/java/de/dhbwstuttgart/bytecode/Exception/NotInCurrentPackageException.java create mode 100644 src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodCallHelper.java diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index b1ea614f..69bb9250 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 { @@ -763,7 +766,7 @@ public class BytecodeGenMethod implements StatementVisitor { public void visit(InstanceOf instanceOf) { } - + @Override public void visit(MethodCall methodCall) { boolean parentBinary = isParentBinary; @@ -772,6 +775,12 @@ public class BytecodeGenMethod implements StatementVisitor { System.out.println("Methods of " + receiverName + " "); java.lang.reflect.Method methodRefl = null; String clazz = receiverName.replace("/", "."); + + String mDesc = ""; + + MethodCallHelper helper = new MethodCallHelper(methodCall, sf, resultSet); + + boolean isCreated = false; // if(!receiverName.equals(className)) { ClassLoader cLoader = ClassLoader.getSystemClassLoader(); // This will be used if the class is not standard class (not in API) @@ -801,71 +810,75 @@ public class BytecodeGenMethod implements StatementVisitor { String superClass = ""; // TODO: Test SubMatrix.jav while(true) { - for(ClassOrInterface cl : sf.getClasses()) { - if(receiverName.equals(cl.getClassName().toString())) { - superClass = cl.getSuperClass().getName().toString(); - break; - } - } - System.out.println(superClass); - - if(superClass.equals("")) - break; - try { - String superClazz = superClass.replace("/", "."); - if(superClass.contains("<")) { - superClazz = superClazz.substring(0, superClass.indexOf("<")); - } - java.lang.reflect.Method[] methods = cLoader.loadClass(superClazz).getMethods(); - System.out.println("Methods of " + superClass + " "); + superClass = helper.getSuperClass(receiverName); - for(java.lang.reflect.Method m : methods) { - if(methodCall.name.equals(m.getName())) { - methodRefl = m; - break; + try { + String superClazz = superClass.replace("/", "."); + if(superClass.contains("<")) { + superClazz = superClazz.substring(0, superClass.indexOf("<")); } + java.lang.reflect.Method[] methods = cLoader.loadClass(superClazz).getMethods(); + System.out.println("Methods of " + superClass + " "); + + for(java.lang.reflect.Method m : methods) { + if(methodCall.name.equals(m.getName())) { + methodRefl = m; + break; + } + } + + break; + } catch (Exception e3) { + receiverName = superClass; + continue; } - + } catch (NotInCurrentPackageException e2) { break; - } catch (Exception e3) { - receiverName = superClass; - continue; } + } // } } if(methodRefl == null) { - 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 +893,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 +932,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 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); + } + } + + 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; + + } + } + return null; + } + +} diff --git a/src/test/resources/bytecode/javFiles/OL.jav b/src/test/resources/bytecode/javFiles/OL.jav index 700e50f0..83361d3c 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) { From 9ffc74467bd222e610cff375bb5d69d65a728d1d Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Fri, 26 Apr 2019 10:27:15 +0200 Subject: [PATCH 8/9] Wenn ein Attribut mehrere Loesungen bekommt, wird die Bytecodeerzeugung abgebrochen und ensprechende Exception geworfen. --- .../dhbwstuttgart/bytecode/BytecodeGen.java | 3 +- .../bytecode/BytecodeGenMethod.java | 43 +++++++------------ .../Exception/BytecodeGeneratorError.java | 19 ++++++++ .../de/dhbwstuttgart/core/JavaTXCompiler.java | 3 +- 4 files changed, 39 insertions(+), 29 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/bytecode/Exception/BytecodeGeneratorError.java diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java index f901036f..e721fd9f 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -17,6 +17,7 @@ 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.ExtendsConstraint; import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; @@ -506,7 +507,7 @@ public class BytecodeGen implements ASTVisitor { String nameAndDesc = field.getName() + "%%" + des; if(fieldNameAndParamsT.contains(nameAndDesc)) - return; + throw new BytecodeGeneratorError("Bytecode generation aborted due to duplicate field name&signature"); fieldNameAndParamsT.add(nameAndDesc); diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index 69bb9250..f047e251 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -781,32 +781,23 @@ public class BytecodeGenMethod implements StatementVisitor { MethodCallHelper helper = new MethodCallHelper(methodCall, sf, resultSet); boolean isCreated = false; -// 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); - + + 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 classFiles = new HashMap<>(); SourceFile sf = sourceFiles.get(f); From 73f412d22d1e30e8612f16914e60ec7dea3a67f4 Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Fri, 26 Apr 2019 11:56:58 +0200 Subject: [PATCH 9/9] 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 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,... + + // 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<>(); + + HashMap methodParamsAndTypes = new HashMap<>(); byte[] bytecode; - HashMap classFiles; - + 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; } @@ -95,16 +98,17 @@ public class BytecodeGen implements ASTVisitor { this.simplifyResultsList = simplifyResultsList; } - public BytecodeGen(HashMap classFiles, List listOfResultSets,SourceFile sf ,String path) { + 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()) { + 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 getClassFiles() { + + 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; - + 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: - * Superclass + /* + * if class has generics then creates signature Signature looks like: + * 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> constraints = Simplify.simplifyConstraintsClass(tphExtractor,tphsClass); + HashMap> constraints = Simplify + .simplifyConstraintsClass(tphExtractor, tphsClass); ArrayList 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 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 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 genericsAndBoundsMethod = new HashMap<>(); - + field.getParameterList().accept(this); - - String methParamTypes = field.name+"%%"; - + + String methParamTypes = field.name + "%%"; + Iterator 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> constraints = Simplify.simplifyConstraints(field.name, tphExtractor,tphsClass); - Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes,resultSet,constraints); + 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()) + 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, "", 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 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 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> constraints = Simplify.simplifyConstraints(method.name, tphExtractor, tphsClass); + 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); + 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 getSimplifyResults() { return simplifyResults; } @@ -436,7 +453,7 @@ public class BytecodeGen implements ASTVisitor { methodParamsAndTypes = new HashMap<>(); Iterator 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 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; }