Alle TPH der Methode werden in eine Liste gespeichert.

Bug gefixt => FacTest liefert richtiges Ergebnis.
Deskriptoren von Methoden, in denen TPHs auftauchen, werden erzeugt.
Signaturen von von Methoden, in denen TPHs auftauchen, werden erzeugt.
Test, RückagbeTypen der Methoden = TPH und ParameterTypen = TPH.
This commit is contained in:
Fayez Abu Alia 2018-05-30 15:27:21 +02:00
parent bb26112a9b
commit 66078360da
8 changed files with 157 additions and 31 deletions

View File

@ -186,6 +186,11 @@ public class BytecodeGen implements ASTVisitor {
System.out.println("Method: "+method.name +" , paramsType: "+methParamTypes); System.out.println("Method: "+method.name +" , paramsType: "+methParamTypes);
String methDesc = null; 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() ? // Method getModifiers() ?
int acc = isInterface?Opcodes.ACC_ABSTRACT:method.modifier; int acc = isInterface?Opcodes.ACC_ABSTRACT:method.modifier;
System.out.println(acc); System.out.println(acc);
@ -216,10 +221,10 @@ public class BytecodeGen implements ASTVisitor {
// zwite operand muss weggelassen werden // zwite operand muss weggelassen werden
if(hasGen||method.getReturnType().acceptTV(new TypeToString()).equals("TPH")) { if(hasGen||method.getReturnType().acceptTV(new TypeToString()).equals("TPH")) {
// resultset hier zum testen // resultset hier zum testen
Signature signature = new Signature(method, genericsAndBoundsMethod, methodParamsAndTypes,resultSet); Signature signature = new Signature(method, genericsAndBoundsMethod, methodParamsAndTypes,resultSet, tphEx.allTPHS);
sig = signature.toString(); sig = signature.toString();
} }
// System.out.println(sig); System.out.println(sig);
NormalMethod meth = new NormalMethod(method,genericsAndBounds,genericsAndBoundsMethod,hasGen); NormalMethod meth = new NormalMethod(method,genericsAndBounds,genericsAndBoundsMethod,hasGen);
methDesc = meth.accept(new DescriptorToString(resultSet)); methDesc = meth.accept(new DescriptorToString(resultSet));
@ -475,5 +480,14 @@ public class BytecodeGen implements ASTVisitor {
public void visit(UnaryExpr unaryExpr) { public void visit(UnaryExpr unaryExpr) {
throw new NotImplementedException(); throw new NotImplementedException();
} }
private class TPHEx extends AbstractASTWalker{
// Liste enthält alle tph der Klasse
ArrayList<TypePlaceholder> allTPHS = new ArrayList<>();
@Override
public void visit(TypePlaceholder tph) {
allTPHS.add(tph);
}
}
} }

View File

@ -34,10 +34,12 @@ import de.dhbwstuttgart.bytecode.utilities.Lambda;
import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall; import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall;
import de.dhbwstuttgart.bytecode.utilities.SamMethod; import de.dhbwstuttgart.bytecode.utilities.SamMethod;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.syntaxtree.AbstractASTWalker;
import de.dhbwstuttgart.syntaxtree.FormalParameter; import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.result.ResultSet; import de.dhbwstuttgart.typeinference.result.ResultSet;
public class BytecodeGenMethod implements StatementVisitor { public class BytecodeGenMethod implements StatementVisitor {
@ -1040,13 +1042,18 @@ public class BytecodeGenMethod implements StatementVisitor {
String var = assignLeftSide.localVar.name; String var = assignLeftSide.localVar.name;
if (!paramsAndLocals.containsKey(var)) { if (!paramsAndLocals.containsKey(var)) {
paramsAndLocals.put(var, index + 1); paramsAndLocals.put(var, index + 1);
} else { }
paramsAndLocals.put(var, index);
mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.get(var));
}
private class TPHEx extends AbstractASTWalker{
// Liste enthält alle tph der Methode
ArrayList<TypePlaceholder> allTPHS = new ArrayList<>();
@Override
public void visit(TypePlaceholder tph) {
allTPHS.add(tph);
} }
mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.size());
// Debug:::
} }
} }

View File

@ -2,6 +2,8 @@ package de.dhbwstuttgart.bytecode.descriptor;
import java.util.Iterator; import java.util.Iterator;
import org.objectweb.asm.Type;
import de.dhbwstuttgart.bytecode.signature.TypeToSignature; import de.dhbwstuttgart.bytecode.signature.TypeToSignature;
import de.dhbwstuttgart.bytecode.utilities.Lambda; import de.dhbwstuttgart.bytecode.utilities.Lambda;
import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall; import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall;
@ -49,7 +51,8 @@ public class DescriptorToString implements DescriptorVisitor{
// desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; // desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";";
String resType = resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()); String resType = resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor());
if(resType.subSequence(0, 4).equals("TPH ")) { if(resType.subSequence(0, 4).equals("TPH ")) {
desc += "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";"; // Bound ist immer Object
desc += "L"+Type.getInternalName(Object.class)+ ";";
} else { } else {
desc += "L"+resType+ ";"; desc += "L"+resType+ ";";
} }
@ -76,7 +79,8 @@ public class DescriptorToString implements DescriptorVisitor{
}else { }else {
String resType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); String resType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor());
if(resType.subSequence(0, 4).equals("TPH ")) { if(resType.subSequence(0, 4).equals("TPH ")) {
desc += ")" + "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";"; // desc += ")" + "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";";
desc += ")" + "L"+Type.getInternalName(Object.class)+ ";";
} else { } else {
desc += ")" + "L"+resType+ ";"; desc += ")" + "L"+resType+ ";";
} }
@ -142,17 +146,25 @@ public class DescriptorToString implements DescriptorVisitor{
String desc = "("; String desc = "(";
for(Expression e : methodFromMethodCall.getArgList().getArguments()) { for(Expression e : methodFromMethodCall.getArgList().getArguments()) {
String d = e.getType().acceptTV(new TypeToDescriptor()); String d = e.getType().acceptTV(new TypeToDescriptor());
if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(d)) {
desc += "L"+methodFromMethodCall.getGenericsAndBoundsMethod().get(d)+ ";"; if(d.substring(0, 4).equals("TPH ")) {
}else if(methodFromMethodCall.getGenericsAndBounds().containsKey(d)) { desc += "L"+Type.getInternalName(Object.class)+ ";";
desc += "L"+methodFromMethodCall.getGenericsAndBounds().get(d)+ ";";
}else { }else {
desc += "L"+resultSet.resolveType(e.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(d)) {
desc += "L"+methodFromMethodCall.getGenericsAndBoundsMethod().get(d)+ ";";
}else if(methodFromMethodCall.getGenericsAndBounds().containsKey(d)) {
desc += "L"+methodFromMethodCall.getGenericsAndBounds().get(d)+ ";";
}else {
desc += "L"+resultSet.resolveType(e.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";";
}
} }
} }
if(resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.toString().equals("void")) { if(resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.toString().equals("void")) {
desc += ")V"; desc += ")V";
}else if(resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()).substring(0, 4).equals("TPH ")){
desc += ")L"+Type.getInternalName(Object.class)+ ";";
}else { }else {
String ret = resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); String ret = resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor());
if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(ret)) { if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(ret)) {

View File

@ -1,5 +1,6 @@
package de.dhbwstuttgart.bytecode.signature; package de.dhbwstuttgart.bytecode.signature;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
@ -8,6 +9,7 @@ import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.signature.SignatureWriter; import org.objectweb.asm.signature.SignatureWriter;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.syntaxtree.AbstractASTWalker;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Constructor; import de.dhbwstuttgart.syntaxtree.Constructor;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
@ -15,6 +17,8 @@ import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.result.GenericInsertPair;
import de.dhbwstuttgart.typeinference.result.ResultSet; import de.dhbwstuttgart.typeinference.result.ResultSet;
public class Signature { public class Signature {
@ -26,6 +30,7 @@ public class Signature {
private Method method; private Method method;
private HashMap<String,RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes; private HashMap<String,RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes;
private ResultSet resultSet; private ResultSet resultSet;
ArrayList<TypePlaceholder> allTPHS;
public Signature(ClassOrInterface classOrInterface, HashMap<String, String> genericsAndBounds) { public Signature(ClassOrInterface classOrInterface, HashMap<String, String> genericsAndBounds) {
this.classOrInterface = classOrInterface; this.classOrInterface = classOrInterface;
@ -43,11 +48,12 @@ public class Signature {
} }
public Signature(Method method, HashMap<String, String> genericsAndBoundsMethod, public Signature(Method method, HashMap<String, String> genericsAndBoundsMethod,
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes, ResultSet resultSet) { HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes, ResultSet resultSet, ArrayList<TypePlaceholder> allTPHS) {
this.method = method; this.method = method;
this.genericsAndBoundsMethod = genericsAndBoundsMethod; this.genericsAndBoundsMethod = genericsAndBoundsMethod;
this.methodParamsAndTypes = methodParamsAndTypes; this.methodParamsAndTypes = methodParamsAndTypes;
this.resultSet = resultSet; this.resultSet = resultSet;
this.allTPHS = allTPHS;
sw = new SignatureWriter(); sw = new SignatureWriter();
createSignatureForConsOrMethod(this.method,false); createSignatureForConsOrMethod(this.method,false);
} }
@ -96,6 +102,15 @@ public class Signature {
// z.B: Type = TPH K => wird eine Formal Type Parameter K$ erzeugt und Bound = Object // 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()); String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature());
if(ret.substring(0,4).equals("TPH ")) { 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)+"$"; String g = ret.substring(4)+"$";
sw.visitFormalTypeParameter(g); sw.visitFormalTypeParameter(g);
sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); sw.visitClassBound().visitClassType(Type.getInternalName(Object.class));
@ -110,12 +125,48 @@ public class Signature {
if(pT.substring(0,4).equals("TPH ") && !genericsAndBoundsMethod.containsKey(pT)) { if(pT.substring(0,4).equals("TPH ") && !genericsAndBoundsMethod.containsKey(pT)) {
String gP = pT.substring(4)+"$"; String gP = pT.substring(4)+"$";
sw.visitFormalTypeParameter(gP); sw.visitFormalTypeParameter(gP);
sw.visitClassBound().visitClassType(Type.getInternalName(Object.class));
genericsAndBoundsMethod.put(gP, Type.getInternalName(Object.class)); String resolvedT = resultSet.resolveType(t).resolvedType.acceptTV(new TypeToSignature());
sw.visitClassBound().visitEnd(); 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;
}
}
sw.visitClassBound().visitTypeVariable(bound);
} else {
bound = Type.getInternalName(Object.class);
sw.visitClassBound().visitClassType(bound);
}
genericsAndBoundsMethod.put(gP, bound);
// sw.visitClassBound().visitEnd();
} }
} }
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 // visit each method-parameter to create the signature
for(String paramName : methodParamsAndTypes.keySet()) { for(String paramName : methodParamsAndTypes.keySet()) {
RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName); RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName);
@ -125,15 +176,6 @@ public class Signature {
if(isConstructor) { if(isConstructor) {
sw.visitReturnType().visitBaseType('V'); sw.visitReturnType().visitBaseType('V');
}else { }else {
// String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature());
// if(ret.substring(0,4).equals("TPH ")) {
// String g = ret.substring(4);
// if(!genericsAndBoundsMethod.containsKey(g)) {
// genericsAndBoundsMethod.put(g, Type.getInternalName(Object.class));
// } else {
// genericsAndBoundsMethod.put(g+"_", Type.getInternalName(Object.class));
// }
// }
RefTypeOrTPHOrWildcardOrGeneric returnType = method.getReturnType(); RefTypeOrTPHOrWildcardOrGeneric returnType = method.getReturnType();
// return type deswegen ist false // return type deswegen ist false
doVisitParamsOrReturn(returnType, false); doVisitParamsOrReturn(returnType, false);

View File

@ -37,8 +37,8 @@ public class FacTest {
@Test @Test
public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method getFac = classToTest.getDeclaredMethod("getFac", Integer.class); Method getFac = classToTest.getDeclaredMethod("getFac", Integer.class);
Integer result = (Integer) getFac.invoke(instanceOfClass,3); Double result = (Double) getFac.invoke(instanceOfClass,3);
assertEquals(result, 6); assertEquals(result, 6.0);
} }
} }

View File

@ -0,0 +1,40 @@
package bytecode;
import static org.junit.Assert.*;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import de.dhbwstuttgart.core.JavaTXCompiler;
public class TphTest {
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;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Tph.jav";
fileToTest = new File(path);
compiler = new JavaTXCompiler(fileToTest);
compiler.generateBytecode();
pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/";
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("Tph");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}
@Test
public void test() {
fail("Not yet implemented");
}
}

View File

@ -4,7 +4,7 @@ import java.lang.Double;
public class Fac { public class Fac {
java.lang.Long getFac(n){ getFac(n){
var res = 1; var res = 1;
var i = 1; var i = 1;
while(i<=n) { while(i<=n) {

View File

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