Alle TPHS einer Methode und pairs (TPH < SuperTPH) werden gesammelt,

gemeinsamme TPHs werden bestimmt, die Klassenkopf als Type-Variables
	definiert werden sollen.
	Erzeugung von Signature angepasst.
This commit is contained in:
Fayez Abu Alia 2018-06-12 11:41:59 +02:00
parent 66078360da
commit ff2bca5ce5
5 changed files with 247 additions and 97 deletions

View File

@ -17,6 +17,7 @@ import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.bytecode.signature.Signature;
import de.dhbwstuttgart.bytecode.signature.TypeToString;
import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH;
import de.dhbwstuttgart.bytecode.utilities.NormalConstructor;
import de.dhbwstuttgart.bytecode.utilities.NormalMethod;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
@ -28,6 +29,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.result.GenericInsertPair;
import de.dhbwstuttgart.typeinference.result.ResultPair;
import de.dhbwstuttgart.typeinference.result.ResultSet;
@ -50,6 +52,9 @@ public class BytecodeGen implements ASTVisitor {
// stores generics and their bounds of method
HashMap<String, String> genericsAndBoundsMethod = new HashMap<>();
private final ArrayList<GenericInsertPair> commonPairs = new ArrayList<>();
private ArrayList<MethodAndTPH> ListOfMethodsAndTph = new ArrayList<>();
HashMap<String,RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes = new HashMap<>();
byte[] bytecode;
HashMap<String,byte[]> classFiles;
@ -90,6 +95,7 @@ public class BytecodeGen implements ASTVisitor {
@Override
public void visit(ClassOrInterface classOrInterface) {
className = classOrInterface.getClassName().toString();
cw.visitSource(className +".jav", null);
@ -97,27 +103,41 @@ public class BytecodeGen implements ASTVisitor {
isInterface = (classOrInterface.getModifiers()&512)==512;
int acc = isInterface?classOrInterface.getModifiers()+Opcodes.ACC_ABSTRACT:classOrInterface.getModifiers()+Opcodes.ACC_SUPER;
String sig = null;
/* if class has generics then creates signature
* Signature looks like:
* <E:Ljava/...>Superclass
*/
if(classOrInterface.getGenerics().iterator().hasNext()) {
Signature signature = new Signature(classOrInterface, genericsAndBounds);
sig = signature.toString();
}
// needs implemented Interfaces?
cw.visit(Opcodes.V1_8, acc, classOrInterface.getClassName().toString()
, sig, classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()), null);
for(Field f : classOrInterface.getFieldDecl()) {
f.accept(this);
}
// resultSet = listOfResultSets.get(0);
boolean isConsWithNoParamsVisited = false;
boolean isVisited = false;
for(ResultSet rs : listOfResultSets) {
resultSet = rs;
// Nur einmal ausführen!!
if(!isVisited) {
TPHExtractor tphExtractor = new TPHExtractor();
classOrInterface.accept(tphExtractor);
getCommonTPHS(tphExtractor);
ListOfMethodsAndTph = tphExtractor.ListOfMethodsAndTph;
String sig = null;
/* if class has generics then creates signature
* Signature looks like:
* <E:Ljava/...>Superclass
*/
if(classOrInterface.getGenerics().iterator().hasNext() || !commonPairs.isEmpty()) {
Signature signature = new Signature(classOrInterface, genericsAndBounds,commonPairs);
sig = signature.toString();
System.out.println("Signature: => " + sig);
}
cw.visit(Opcodes.V1_8, acc, classOrInterface.getClassName().toString()
, sig, classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()), null);
isVisited = true;
}
for(Field f : classOrInterface.getFieldDecl()) {
f.accept(this);
}
for(Constructor c : classOrInterface.getConstructors()) {
if(!isConsWithNoParamsVisited)
c.accept(this);
@ -133,6 +153,36 @@ public class BytecodeGen implements ASTVisitor {
}
private void getCommonTPHS(TPHExtractor tphExtractor) {
// Gemeinsame TPHs
ArrayList<TypePlaceholder> cTPHs = new ArrayList<>();
// Alle TPHs der Felder speichern
for(TypePlaceholder tph : tphExtractor.allTPHS.keySet()) {
if(!tphExtractor.allTPHS.get(tph))
cTPHs.add(tph);
}
ArrayList<MethodAndTPH> tphsMethod = tphExtractor.ListOfMethodsAndTph;
// Für jede Methode speichere die gemeinsame TPHs:
// -> Für jedes Pair prüfe ob, auf der rechten Seite ein TPH steht, der
// in der Liste der TPHs der Methode enthalten ist.
// Wenn ja -> gemeinsamer TPH
for(MethodAndTPH m:tphsMethod){
for(GenericInsertPair p : m.getPairs()){
if(!m.getTphs().contains(p.TA2))
cTPHs.add(p.TA2);
}
}
for(TypePlaceholder tph : cTPHs) {
for(GenericInsertPair p : tphExtractor.allPairs) {
if(p.contains(tph))
commonPairs.add(p);
}
}
}
@Override
public void visit(Constructor field) {
field.getParameterList().accept(this);
@ -186,11 +236,6 @@ public class BytecodeGen implements ASTVisitor {
System.out.println("Method: "+method.name +" , paramsType: "+methParamTypes);
String methDesc = null;
TPHEx tphEx = new TPHEx();
method.accept(tphEx);
System.out.println("TPHs: \n");
tphEx.allTPHS.forEach(e->System.out.println(e.getName()));
// Method getModifiers() ?
int acc = isInterface?Opcodes.ACC_ABSTRACT:method.modifier;
System.out.println(acc);
@ -220,11 +265,18 @@ public class BytecodeGen implements ASTVisitor {
/* if method has generics or return type is TPH, create signature */
// zwite operand muss weggelassen werden
if(hasGen||method.getReturnType().acceptTV(new TypeToString()).equals("TPH")) {
// resultset hier zum testen
Signature signature = new Signature(method, genericsAndBoundsMethod, methodParamsAndTypes,resultSet, tphEx.allTPHS);
ArrayList<GenericInsertPair> pairs = new ArrayList<>();
for(MethodAndTPH m : ListOfMethodsAndTph) {
if(m.getName().equals(method.name)) {
pairs = m.getPairs();
break;
}
}
Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds,methodParamsAndTypes,resultSet, pairs);
sig = signature.toString();
}
System.out.println(sig);
System.out.println(method.getName()+" ==> "+sig);
NormalMethod meth = new NormalMethod(method,genericsAndBounds,genericsAndBoundsMethod,hasGen);
methDesc = meth.accept(new DescriptorToString(resultSet));
@ -481,12 +533,47 @@ public class BytecodeGen implements ASTVisitor {
throw new NotImplementedException();
}
private class TPHEx extends AbstractASTWalker{
// Liste enthält alle tph der Klasse
ArrayList<TypePlaceholder> allTPHS = new ArrayList<>();
private class TPHExtractor extends AbstractASTWalker{
// Alle TPHs der Felder werden iKopf der Klasse definiert
// alle TPHs der Klasse: (TPH, is in Method?)
final HashMap<TypePlaceholder,Boolean> allTPHS = new HashMap<>();
MethodAndTPH methodAndTph;
Boolean inMethod = false;
final ArrayList<MethodAndTPH> ListOfMethodsAndTph = new ArrayList<>();
final ArrayList<GenericInsertPair> allPairs = new ArrayList<>();
@Override
public void visit(TypePlaceholder tph) {
allTPHS.add(tph);
if(resultSet.resolveType(tph).resolvedType instanceof TypePlaceholder) {
TypePlaceholder resolvedTPH = (TypePlaceholder) resultSet.resolveType(tph).resolvedType;
if(inMethod)
methodAndTph.getTphs().add(resolvedTPH);
allTPHS.put(resolvedTPH,inMethod);
resultSet.resolveType(tph).additionalGenerics.forEach(ag ->{
if(ag.contains(resolvedTPH)&&ag.TA1.equals(resolvedTPH)&&!contains(allPairs,ag)) {
if(inMethod)
methodAndTph.getPairs().add(ag);
allPairs.add(ag);
}
});
}
}
private boolean contains(ArrayList<GenericInsertPair> pairs, GenericInsertPair genPair) {
for(int i=0; i<pairs.size();++i) {
GenericInsertPair p = pairs.get(i);
if(p.TA1.equals(genPair.TA1) && p.TA2.equals(genPair.TA2))
return true;
}
return false;
}
@Override
public void visit(Method method) {
inMethod = true;
methodAndTph = new MethodAndTPH(method.name);
super.visit(method);
inMethod = false;
ListOfMethodsAndTph.add(methodAndTph);
}
}

View File

@ -30,11 +30,13 @@ public class Signature {
private Method method;
private HashMap<String,RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes;
private ResultSet resultSet;
ArrayList<TypePlaceholder> allTPHS;
private ArrayList<GenericInsertPair> commonPairs;
private ArrayList<GenericInsertPair> methodPairs;
public Signature(ClassOrInterface classOrInterface, HashMap<String, String> genericsAndBounds) {
public Signature(ClassOrInterface classOrInterface, HashMap<String, String> genericsAndBounds,ArrayList<GenericInsertPair> commonPairs) {
this.classOrInterface = classOrInterface;
this.genericsAndBounds = genericsAndBounds;
this.commonPairs = commonPairs;
sw = new SignatureWriter();
createSignatureForClassOrInterface();
}
@ -47,13 +49,14 @@ public class Signature {
createSignatureForConsOrMethod(this.constructor,true);
}
public Signature(Method method, HashMap<String, String> genericsAndBoundsMethod,
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes, ResultSet resultSet, ArrayList<TypePlaceholder> allTPHS) {
public Signature(Method method, HashMap<String, String> genericsAndBoundsMethod,HashMap<String, String> genericsAndBounds,
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes, ResultSet resultSet, ArrayList<GenericInsertPair> methodPairs) {
this.method = method;
this.genericsAndBoundsMethod = genericsAndBoundsMethod;
this.genericsAndBounds = genericsAndBounds;
this.methodParamsAndTypes = methodParamsAndTypes;
this.resultSet = resultSet;
this.allTPHS = allTPHS;
this.methodPairs = methodPairs;
sw = new SignatureWriter();
createSignatureForConsOrMethod(this.method,false);
}
@ -98,75 +101,66 @@ public class Signature {
GenericTypeVar g = itr.next();
getBoundsOfTypeVar(g,genericsAndBoundsMethod);
}
// Wenn die RückgabeType eine TPH ist, wird als generic behandelt
// z.B: Type = TPH K => wird eine Formal Type Parameter K$ erzeugt und Bound = Object
String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature());
if(ret.substring(0,4).equals("TPH ")) {
/* (1) Wenn TPH X -> TPH Y, dann ersetze TPH X in allTPHs durch TPH Y,
* da X = Y (in RES) ist */
if(method.getReturnType() instanceof TypePlaceholder) {
TypePlaceholder retTPH = (TypePlaceholder) method.getReturnType();
TypePlaceholder resolvedTPH = (TypePlaceholder) resultSet.resolveType(method.getReturnType()).resolvedType;
allTPHS.remove(retTPH);
allTPHS.add(resolvedTPH);
}
String g = ret.substring(4)+"$";
sw.visitFormalTypeParameter(g);
sw.visitClassBound().visitClassType(Type.getInternalName(Object.class));
genericsAndBoundsMethod.put(g, Type.getInternalName(Object.class));
sw.visitClassBound().visitEnd();
}
for(String paramName : methodParamsAndTypes.keySet()) {
RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName);
String pT = t.acceptTV(new TypeToSignature());
// S.o
if(pT.substring(0,4).equals("TPH ") && !genericsAndBoundsMethod.containsKey(pT)) {
String gP = pT.substring(4)+"$";
sw.visitFormalTypeParameter(gP);
String resolvedT = resultSet.resolveType(t).resolvedType.acceptTV(new TypeToSignature());
String bound;
if(resolvedT.subSequence(0, 4).equals("TPH ")) {
/* TODO: Prüfe, ob man hier auch (1) braucht*/
int s = resultSet.resolveType(t).additionalGenerics.size();
System.out.println(gP+"AdditionalG: "+s);
resultSet.resolveType(t).additionalGenerics.forEach(a->System.out.println(a.TA2.getName()));
Iterator<GenericInsertPair> itr2 = resultSet.resolveType(t).additionalGenerics.iterator();
//TypePlaceholder temp = null;
bound = Type.getInternalName(Object.class);
while(itr2.hasNext()) {
TypePlaceholder tph = itr2.next().TA2;
String tphName = tph.getName()+"$";
if(allTPHS.contains(tph) && !tphName.equals(gP)) {
bound = tphName;
break;
if(!methodPairs.isEmpty()) {
// Wenn die RückgabeType eine TPH ist, wird als generic behandelt
// z.B: Type = TPH K => wird eine Formal Type Parameter K$ erzeugt und Bound = Object
String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature());
if(ret.substring(0,4).equals("TPH ")) {
String g = ret.substring(4)+"$";
if(genericsAndBounds.containsKey(g)) {
genericsAndBoundsMethod.put(g, genericsAndBounds.get(g));
}else {
sw.visitFormalTypeParameter(g);
sw.visitClassBound().visitClassType(Type.getInternalName(Object.class));
genericsAndBoundsMethod.put(g, Type.getInternalName(Object.class));
sw.visitClassBound().visitEnd();
}
}
// Parameters
for(String paramName : methodParamsAndTypes.keySet()) {
RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName);
String pT = t.acceptTV(new TypeToSignature());
// S.o
if(pT.substring(0,4).equals("TPH ")) {
String gP = pT.substring(4)+"$";
if(!genericsAndBounds.containsKey(gP) && !genericsAndBoundsMethod.containsKey(gP)) {
sw.visitFormalTypeParameter(gP);
String bound = Type.getInternalName(Object.class);
boolean isTypeVar = false;
for(GenericInsertPair pair : methodPairs) {
if(pT.substring(4).equals(pair.TA1.getName())) {
bound = pair.TA2.getName()+"$";
isTypeVar = true;
break;
}
}
if(isTypeVar) {
sw.visitClassBound().visitTypeVariable(bound);
}else {
sw.visitClassBound().visitClassType(bound);
sw.visitClassBound().visitEnd();
}
genericsAndBoundsMethod.put(gP, bound);
}
}
sw.visitClassBound().visitTypeVariable(bound);
} else {
bound = Type.getInternalName(Object.class);
sw.visitClassBound().visitClassType(bound);
}
genericsAndBoundsMethod.put(gP, bound);
// sw.visitClassBound().visitEnd();
}
// methodPairs.forEach(p->{
// String name = p.TA2.getName() + "$";
// if(!genericsAndBoundsMethod.containsKey(name)) {
// sw.visitFormalTypeParameter(name);
// String bound = Type.getInternalName(Object.class);
// sw.visitClassBound().visitClassType(bound);
// sw.visitClassBound().visitEnd();
// genericsAndBoundsMethod.put(name, bound);
// }
// });
}
allTPHS.forEach(tph -> {
String tp = tph.getName()+"$";
if(!genericsAndBoundsMethod.containsKey(tp)) {
sw.visitFormalTypeParameter(tp);
String bound = Type.getInternalName(Object.class);
sw.visitClassBound().visitClassType(bound);
sw.visitClassBound().visitEnd();
genericsAndBoundsMethod.put(tp, bound);
}
});
// visit each method-parameter to create the signature
for(String paramName : methodParamsAndTypes.keySet()) {
RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName);
@ -236,7 +230,34 @@ public class Signature {
GenericTypeVar g = itr.next();
getBoundsOfTypeVar(g,genericsAndBounds);
}
if(!commonPairs.isEmpty()) {
ArrayList<TypePlaceholder> types = new ArrayList<>();
ArrayList<TypePlaceholder> superTypes = new ArrayList<>();
for(GenericInsertPair p : commonPairs) {
types.add(p.TA1);
superTypes.add(p.TA2);
}
for(GenericInsertPair p : commonPairs) {
String t = p.TA1.getName()+"$";
String bound = p.TA2.getName()+"$";
sw.visitFormalTypeParameter(t);
sw.visitClassBound().visitTypeVariable(bound);
genericsAndBounds.put(t, bound);
}
for(GenericInsertPair p : commonPairs) {
if(!types.contains(p.TA2)) {
String t = p.TA2.getName()+"$";
String bound = Type.getInternalName(Object.class);
sw.visitFormalTypeParameter(t);
sw.visitClassBound().visitClassType(bound);
genericsAndBounds.put(t, bound);
sw.visitClassBound().visitEnd();
}
}
}
sw.visitSuperclass().visitClassType(classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()));;
sw.visitEnd();
}

View File

@ -0,0 +1,29 @@
package de.dhbwstuttgart.bytecode.utilities;
import java.util.ArrayList;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.result.GenericInsertPair;
public class MethodAndTPH {
private String name;
private final ArrayList<TypePlaceholder> tphs = new ArrayList<>();
private final ArrayList<GenericInsertPair> pairs = new ArrayList<>();
public MethodAndTPH(String name) {
this.name = name;
}
public ArrayList<TypePlaceholder> getTphs() {
return tphs;
}
public ArrayList<GenericInsertPair> getPairs(){
return pairs;
}
public String getName() {
return name;
}
}

View File

@ -1,3 +1,6 @@
import java.lang.Integer;
import java.lang.Boolean;
public class IfTest{
Integer m1(Boolean b) {
Integer i;

View File

@ -0,0 +1,10 @@
public class Tph2 {
m(a,b){
var c = m2(a,b);
return a;
}
m2(a,b){
return b;
}
}