Merge branch 'bytecode2' of ssh://gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into plugin

This commit is contained in:
Martin Plümicke 2018-06-18 11:50:55 +02:00
commit 1437788f5a
18 changed files with 438 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.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.bytecode.signature.Signature; import de.dhbwstuttgart.bytecode.signature.Signature;
import de.dhbwstuttgart.bytecode.signature.TypeToString; import de.dhbwstuttgart.bytecode.signature.TypeToString;
import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH;
import de.dhbwstuttgart.bytecode.utilities.NormalConstructor; import de.dhbwstuttgart.bytecode.utilities.NormalConstructor;
import de.dhbwstuttgart.bytecode.utilities.NormalMethod; import de.dhbwstuttgart.bytecode.utilities.NormalMethod;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; 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.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.result.GenericInsertPair;
import de.dhbwstuttgart.typeinference.result.ResultPair; import de.dhbwstuttgart.typeinference.result.ResultPair;
import de.dhbwstuttgart.typeinference.result.ResultSet; import de.dhbwstuttgart.typeinference.result.ResultSet;
@ -43,6 +45,8 @@ public class BytecodeGen implements ASTVisitor {
private ResultSet resultSet; private ResultSet resultSet;
private int indexOfFirstParam = 0; private int indexOfFirstParam = 0;
private String superClass;
// stores parameter, local vars and the next index on the local variable table, which use for aload_i, astore_i,... // stores parameter, local vars and the next index on the local variable table, which use for aload_i, astore_i,...
HashMap<String, Integer> paramsAndLocals = new HashMap<>(); HashMap<String, Integer> paramsAndLocals = new HashMap<>();
// stores generics and their bounds of class // stores generics and their bounds of class
@ -50,6 +54,9 @@ public class BytecodeGen implements ASTVisitor {
// stores generics and their bounds of method // stores generics and their bounds of method
HashMap<String, String> genericsAndBoundsMethod = new HashMap<>(); 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<>(); HashMap<String,RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes = new HashMap<>();
byte[] bytecode; byte[] bytecode;
HashMap<String,byte[]> classFiles; HashMap<String,byte[]> classFiles;
@ -90,6 +97,7 @@ public class BytecodeGen implements ASTVisitor {
@Override @Override
public void visit(ClassOrInterface classOrInterface) { public void visit(ClassOrInterface classOrInterface) {
className = classOrInterface.getClassName().toString(); className = classOrInterface.getClassName().toString();
cw.visitSource(className +".jav", null); cw.visitSource(className +".jav", null);
@ -97,27 +105,42 @@ public class BytecodeGen implements ASTVisitor {
isInterface = (classOrInterface.getModifiers()&512)==512; isInterface = (classOrInterface.getModifiers()&512)==512;
int acc = isInterface?classOrInterface.getModifiers()+Opcodes.ACC_ABSTRACT:classOrInterface.getModifiers()+Opcodes.ACC_SUPER; 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); // resultSet = listOfResultSets.get(0);
boolean isConsWithNoParamsVisited = false; boolean isConsWithNoParamsVisited = false;
boolean isVisited = false;
for(ResultSet rs : listOfResultSets) { for(ResultSet rs : listOfResultSets) {
superClass = classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor());
resultSet = rs; 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()) { for(Constructor c : classOrInterface.getConstructors()) {
if(!isConsWithNoParamsVisited) if(!isConsWithNoParamsVisited)
c.accept(this); c.accept(this);
@ -133,6 +156,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 @Override
public void visit(Constructor field) { public void visit(Constructor field) {
field.getParameterList().accept(this); field.getParameterList().accept(this);
@ -156,7 +209,7 @@ public class BytecodeGen implements ASTVisitor {
desc = constructor.accept(new DescriptorToString(resultSet)); desc = constructor.accept(new DescriptorToString(resultSet));
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", desc, sig, null); MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", desc, sig, null);
mv.visitCode(); mv.visitCode();
BytecodeGenMethod gen = new BytecodeGenMethod(className,resultSet,field, mv,paramsAndLocals,cw, BytecodeGenMethod gen = new BytecodeGenMethod(className,superClass,resultSet,field, mv,paramsAndLocals,cw,
genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles); genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles);
if(!field.getParameterList().iterator().hasNext()) { if(!field.getParameterList().iterator().hasNext()) {
mv.visitInsn(Opcodes.RETURN); mv.visitInsn(Opcodes.RETURN);
@ -215,11 +268,18 @@ public class BytecodeGen implements ASTVisitor {
/* if method has generics or return type is TPH, create signature */ /* if method has generics or return type is TPH, create signature */
// 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 ArrayList<GenericInsertPair> pairs = new ArrayList<>();
Signature signature = new Signature(method, genericsAndBoundsMethod, methodParamsAndTypes,resultSet); 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(); sig = signature.toString();
} }
// System.out.println(sig); System.out.println(method.getName()+" ==> "+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));
@ -227,7 +287,7 @@ public class BytecodeGen implements ASTVisitor {
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC+acc, method.getName(), methDesc, sig, null); MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC+acc, method.getName(), methDesc, sig, null);
mv.visitCode(); mv.visitCode();
BytecodeGenMethod gen = new BytecodeGenMethod(className,resultSet,method, mv,paramsAndLocals,cw, BytecodeGenMethod gen = new BytecodeGenMethod(className,superClass,resultSet,method, mv,paramsAndLocals,cw,
genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles); genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles);
mv.visitMaxs(0, 0); mv.visitMaxs(0, 0);
@ -475,5 +535,49 @@ public class BytecodeGen implements ASTVisitor {
public void visit(UnaryExpr unaryExpr) { public void visit(UnaryExpr unaryExpr) {
throw new NotImplementedException(); throw new NotImplementedException();
} }
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) {
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

@ -29,15 +29,18 @@ import org.objectweb.asm.signature.SignatureWriter;
import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString; import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.bytecode.signature.Signature; import de.dhbwstuttgart.bytecode.signature.Signature;
import de.dhbwstuttgart.bytecode.signature.TypeToSignature;
import de.dhbwstuttgart.bytecode.utilities.KindOfLambda; import de.dhbwstuttgart.bytecode.utilities.KindOfLambda;
import de.dhbwstuttgart.bytecode.utilities.Lambda; 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 {
@ -50,10 +53,11 @@ public class BytecodeGenMethod implements StatementVisitor {
private ClassWriter cw; private ClassWriter cw;
private ResultSet resultSet; private ResultSet resultSet;
private boolean isInterface; private boolean isInterface;
HashMap<String, String> genericsAndBoundsMethod; private HashMap<String, String> genericsAndBoundsMethod;
private HashMap<String, String> genericsAndBounds; private HashMap<String, String> genericsAndBounds;
private boolean isBinaryExp = false; private boolean isBinaryExp = false;
private String superClass;
private IStatement statement = null; private IStatement statement = null;
// for tests ** // for tests **
@ -67,11 +71,12 @@ public class BytecodeGenMethod implements StatementVisitor {
private ArrayList<RefTypeOrTPHOrWildcardOrGeneric> varsFunInterface = new ArrayList<>();; private ArrayList<RefTypeOrTPHOrWildcardOrGeneric> varsFunInterface = new ArrayList<>();;
public BytecodeGenMethod(String className, ResultSet resultSet, Method m, MethodVisitor mv, public BytecodeGenMethod(String className, String superClass,ResultSet resultSet, Method m, MethodVisitor mv,
HashMap<String, Integer> paramsAndLocals, ClassWriter cw, HashMap<String, String> genericsAndBoundsMethod, HashMap<String, Integer> paramsAndLocals, ClassWriter cw, HashMap<String, String> genericsAndBoundsMethod,
HashMap<String, String> genericsAndBounds, boolean isInterface, HashMap<String, byte[]> classFiles) { HashMap<String, String> genericsAndBounds, boolean isInterface, HashMap<String, byte[]> classFiles) {
this.className = className; this.className = className;
this.superClass = superClass;
this.resultSet = resultSet; this.resultSet = resultSet;
this.m = m; this.m = m;
this.mv = mv; this.mv = mv;
@ -104,7 +109,11 @@ public class BytecodeGenMethod implements StatementVisitor {
} }
lambdaExpression.methodBody.accept(this); lambdaExpression.methodBody.accept(this);
} }
public void isBinary(boolean isBinary) {
this.isBinaryExp =isBinary;
}
private String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { private String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) {
return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor()); return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor());
} }
@ -120,7 +129,7 @@ public class BytecodeGenMethod implements StatementVisitor {
public void visit(SuperCall superCall) { public void visit(SuperCall superCall) {
superCall.receiver.accept(this); superCall.receiver.accept(this);
superCall.arglist.accept(this); superCall.arglist.accept(this);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), superCall.name, "()V", mv.visitMethodInsn(Opcodes.INVOKESPECIAL, this.superClass, superCall.name, "()V",
isInterface); isInterface);
} }
@ -167,6 +176,11 @@ public class BytecodeGenMethod implements StatementVisitor {
doBoxing(binaryType); doBoxing(binaryType);
isBinaryExp = false; isBinaryExp = false;
} }
System.out.println("ASSIGN TYPE R: " + getResolvedType(assign.rightSide.getType()));
String typeOfRightSide = getResolvedType(assign.rightSide.getType());
if(typeOfRightSide.contains("<")) {
mv.visitTypeInsn(Opcodes.CHECKCAST, typeOfRightSide.substring(0, typeOfRightSide.indexOf('<')));
}
assign.lefSide.accept(this); assign.lefSide.accept(this);
statement = null; statement = null;
@ -621,14 +635,15 @@ public class BytecodeGenMethod implements StatementVisitor {
@Override @Override
public void visit(MethodCall methodCall) { public void visit(MethodCall methodCall) {
System.out.println("Methodcall type : " + resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor()));
methodCall.receiver.accept(this); methodCall.receiver.accept(this);
methodCall.arglist.accept(this); methodCall.arglist.accept(this);
MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(),
genericsAndBoundsMethod, genericsAndBounds); genericsAndBoundsMethod, genericsAndBounds);
String mDesc = method.accept(new DescriptorToString(resultSet)); String mDesc = method.accept(new DescriptorToString(resultSet));
System.out.println("Methodcall Desc : " + mDesc);
// is methodCall.receiver functional Interface)? // is methodCall.receiver functional Interface)?
if (varsFunInterface.contains(methodCall.receiver.getType())) { if (varsFunInterface.contains(methodCall.receiver.getType())) {
mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()), methodCall.name, mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()), methodCall.name,
@ -641,6 +656,9 @@ public class BytecodeGenMethod implements StatementVisitor {
// if(!methodCall.getType().toString().equals("V")) { // if(!methodCall.getType().toString().equals("V")) {
// mv.visitInsn(Opcodes.POP); // mv.visitInsn(Opcodes.POP);
// } // }
if(isBinaryExp) {
doUnboxing(getResolvedType(methodCall.getType()));
}
} }
@Override @Override
@ -799,7 +817,7 @@ public class BytecodeGenMethod implements StatementVisitor {
statement = new LoopStmt(whileStmt.expr, whileStmt.loopBlock); statement = new LoopStmt(whileStmt.expr, whileStmt.loopBlock);
isBinaryExp = statement.isExprBinary(); isBinaryExp = statement.isExprBinary();
whileStmt.expr.accept(this); whileStmt.expr.accept(this);
isBinaryExp = false; // isBinaryExp = false;
statement = null; statement = null;
} }
@ -1040,13 +1058,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

@ -18,6 +18,7 @@ public class LoopStmt extends AStatement {
@Override @Override
public void genBCForRelOp(MethodVisitor mv,Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod) { public void genBCForRelOp(MethodVisitor mv,Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod) {
bytecodeGenMethod.isBinary(false);
this.loopBlock.accept(bytecodeGenMethod); this.loopBlock.accept(bytecodeGenMethod);
mv.visitJumpInsn(Opcodes.GOTO, endLabel); mv.visitJumpInsn(Opcodes.GOTO, endLabel);
mv.visitLabel(branchLabel); mv.visitLabel(branchLabel);

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+ ";";
} }
@ -141,26 +145,34 @@ public class DescriptorToString implements DescriptorVisitor{
public String visit(MethodFromMethodCall methodFromMethodCall) { public String visit(MethodFromMethodCall methodFromMethodCall) {
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 = resultSet.resolveType(e.getType()).resolvedType.acceptTV(new TypeToDescriptor());
if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(d)) {
desc += "L"+methodFromMethodCall.getGenericsAndBoundsMethod().get(d)+ ";"; if(d.substring(0, 4).equals("TPH ") ||d.contains("<")) {
}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())+ ";";
}
} }
} }
String retType = resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor());
if(resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.toString().equals("void")) { System.out.println("DescriptorToString retType = " + retType);
if(retType.equals("void")) {
desc += ")V"; desc += ")V";
}else if(retType.substring(0, 4).equals("TPH ")|| retType.contains("<")){
desc += ")L"+Type.getInternalName(Object.class)+ ";";
}else { }else {
String ret = resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(retType)) {
if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(ret)) { desc += ")L"+methodFromMethodCall.getGenericsAndBoundsMethod().get(retType)+ ";";
desc += ")L"+methodFromMethodCall.getGenericsAndBoundsMethod().get(ret)+ ";"; }else if(methodFromMethodCall.getGenericsAndBounds().containsKey(retType)){
}else if(methodFromMethodCall.getGenericsAndBounds().containsKey(ret)){ desc += ")L"+methodFromMethodCall.getGenericsAndBounds().get(retType)+ ";";
desc += ")L"+methodFromMethodCall.getGenericsAndBounds().get(ret)+ ";";
}else { }else {
desc += ")" + "L"+resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; desc += ")" + "L"+retType+ ";";
} }
} }
// desc = addReturnType(desc, methodFromMethodCall.getReturnType(), resultSet); // desc = addReturnType(desc, methodFromMethodCall.getReturnType(), resultSet);

View File

@ -19,7 +19,9 @@ public class TypeToDescriptor implements TypeVisitor<String>{
@Override @Override
public String visit(SuperWildcardType superWildcardType) { public String visit(SuperWildcardType superWildcardType) {
throw new NotImplementedException(); System.out.println("\nWILDCARD ="+superWildcardType.getInnerType().toString().replace(".", "/"));
return superWildcardType.getInnerType().toString().replace(".", "/");
//throw new NotImplementedException();
} }
@Override @Override
@ -29,6 +31,7 @@ public class TypeToDescriptor implements TypeVisitor<String>{
@Override @Override
public String visit(ExtendsWildcardType extendsWildcardType) { public String visit(ExtendsWildcardType extendsWildcardType) {
System.out.println("\nWILDCARD extends ="+extendsWildcardType.getInnerType().toString().replace(".", "/"));
return extendsWildcardType.getInnerType().toString().replace(".", "/"); return extendsWildcardType.getInnerType().toString().replace(".", "/");
//throw new NotImplementedException(); //throw new NotImplementedException();
} }

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,10 +30,13 @@ 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;
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.classOrInterface = classOrInterface;
this.genericsAndBounds = genericsAndBounds; this.genericsAndBounds = genericsAndBounds;
this.commonPairs = commonPairs;
sw = new SignatureWriter(); sw = new SignatureWriter();
createSignatureForClassOrInterface(); createSignatureForClassOrInterface();
} }
@ -42,12 +49,14 @@ public class Signature {
createSignatureForConsOrMethod(this.constructor,true); createSignatureForConsOrMethod(this.constructor,true);
} }
public Signature(Method method, HashMap<String, String> genericsAndBoundsMethod, public Signature(Method method, HashMap<String, String> genericsAndBoundsMethod,HashMap<String, String> genericsAndBounds,
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes, ResultSet resultSet) { HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes, ResultSet resultSet, ArrayList<GenericInsertPair> methodPairs) {
this.method = method; this.method = method;
this.genericsAndBoundsMethod = genericsAndBoundsMethod; this.genericsAndBoundsMethod = genericsAndBoundsMethod;
this.genericsAndBounds = genericsAndBounds;
this.methodParamsAndTypes = methodParamsAndTypes; this.methodParamsAndTypes = methodParamsAndTypes;
this.resultSet = resultSet; this.resultSet = resultSet;
this.methodPairs = methodPairs;
sw = new SignatureWriter(); sw = new SignatureWriter();
createSignatureForConsOrMethod(this.method,false); createSignatureForConsOrMethod(this.method,false);
} }
@ -92,28 +101,62 @@ public class Signature {
GenericTypeVar g = itr.next(); GenericTypeVar g = itr.next();
getBoundsOfTypeVar(g,genericsAndBoundsMethod); getBoundsOfTypeVar(g,genericsAndBoundsMethod);
} }
// Wenn die RückgabeType eine TPH ist, wird als generic behandelt // 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 // 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 ")) {
String g = ret.substring(4)+"$"; String g = ret.substring(4)+"$";
sw.visitFormalTypeParameter(g); if(genericsAndBounds.containsKey(g)) {
sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); genericsAndBoundsMethod.put(g, genericsAndBounds.get(g));
genericsAndBoundsMethod.put(g, Type.getInternalName(Object.class)); }else {
sw.visitClassBound().visitEnd(); 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()) { for(String paramName : methodParamsAndTypes.keySet()) {
RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName); RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName);
String pT = t.acceptTV(new TypeToSignature()); String pT = t.acceptTV(new TypeToSignature());
// S.o // S.o
if(pT.substring(0,4).equals("TPH ") && !genericsAndBoundsMethod.containsKey(pT)) { if(pT.substring(0,4).equals("TPH ")) {
String gP = pT.substring(4)+"$"; String gP = pT.substring(4)+"$";
sw.visitFormalTypeParameter(gP); if(!genericsAndBounds.containsKey(gP) && !genericsAndBoundsMethod.containsKey(gP)) {
sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); sw.visitFormalTypeParameter(gP);
genericsAndBoundsMethod.put(gP, Type.getInternalName(Object.class)); String bound = Type.getInternalName(Object.class);
sw.visitClassBound().visitEnd(); 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);
}
} }
// 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);
// }
// });
} }
// visit each method-parameter to create the signature // visit each method-parameter to create the signature
@ -125,15 +168,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);
@ -194,7 +228,34 @@ public class Signature {
GenericTypeVar g = itr.next(); GenericTypeVar g = itr.next();
getBoundsOfTypeVar(g,genericsAndBounds); 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.visitSuperclass().visitClassType(classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()));;
sw.visitEnd(); 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

@ -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,41 @@
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 Tph2Test {
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/Tph2.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("Tph2");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}
@Test
public void test() {
fail("Not yet implemented");
}
}

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

@ -2,14 +2,15 @@ import java.lang.Integer;
class Faculty { class Faculty {
Integer mul(Integer x, Integer y) {
return x;
}
m () { m () {
var fact = (Integer x) -> { var fact = (Integer x) -> {
return mul(x, x); if (x == 1) {
return x;
}
else {
return x * fact.apply(x-1);
}
}; };
return fact; return fact;
} }

View File

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

View File

@ -6,6 +6,6 @@ public class Lambda {
var lam1 = (Integer x) -> { var lam1 = (Integer x) -> {
return x; return x;
}; };
return lam1; return lam1.apply(1);
} }
} }

View File

@ -2,24 +2,24 @@ import java.util.Vector;
import java.lang.Integer; import java.lang.Integer;
import java.lang.Boolean; import java.lang.Boolean;
class Matrix extends Vector<Vector<Integer>> { public class Matrix extends Vector<Vector<Integer>> {
mul(m) { mul(m) {
var ret = new Matrix(); var ret = new Matrix();
var i = 0; var i = 0;
while(i < size()) { while(i < size()) {
// var v1 = this.elementAt(i); var v1 = this.elementAt(i);
// var v2 = new Vector<Integer>(); var v2 = new Vector<Integer>();
// var j = 0; var j = 0;
// while(j < v1.size()) { while(j < v1.size()) {
// var erg = 0; // var erg = 0;
// var k = 0; // var k = 0;
// while(k < v1.size()) { // while(k < v1.size()) {
// erg = erg + v1.elementAt(k) // erg = erg + v1.elementAt(k)
// * m.elementAt(k).elementAt(j); // * m.elementAt(k).elementAt(j);
// k++; } // k++; }
// v2.addElement(new Integer(erg)); // v2.addElement(new Integer(erg));
// j++; } j++; }
// ret.addElement(v2); ret.addElement(v2);
i++; i++;
} }
return ret; return ret;

View File

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

View File

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

View File

@ -7,7 +7,7 @@ public class Lambda {
var lam1 = (x) -> { var lam1 = (x) -> {
return x; return x;
}; };
return lam1; return lam1.apply(1);
} }
} }

View File

@ -29,12 +29,12 @@ public class UnifyTest {
execute(new File(rootDirectory+"fc.jav")); execute(new File(rootDirectory+"fc.jav"));
} }
*/ */
/*
@Test @Test
public void lambda() throws IOException, ClassNotFoundException { public void lambda() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Lambda.jav")); execute(new File(rootDirectory+"Lambda.jav"));
} }
*/
/* /*
@Test @Test
public void lambda2() throws IOException, ClassNotFoundException { public void lambda2() throws IOException, ClassNotFoundException {
@ -74,6 +74,7 @@ public class UnifyTest {
} }
*/ */
/*
@Test @Test
public void matrix() throws IOException, ClassNotFoundException { public void matrix() throws IOException, ClassNotFoundException {
@ -81,6 +82,7 @@ public class UnifyTest {
//JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"Matrix.jav")); //JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"Matrix.jav"));
//compiler.generateBytecode(); //compiler.generateBytecode();
} }
*/
/* /*
@Test @Test