diff --git a/src/de/dhbwstuttgart/bytecode/ArgumentVisitor.java b/src/de/dhbwstuttgart/bytecode/ArgumentVisitor.java new file mode 100644 index 00000000..be0e1bc7 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/ArgumentVisitor.java @@ -0,0 +1,255 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.List; + +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; +import de.dhbwstuttgart.syntaxtree.statement.Assign; +import de.dhbwstuttgart.syntaxtree.statement.AssignToField; +import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr; +import de.dhbwstuttgart.syntaxtree.statement.Block; +import de.dhbwstuttgart.syntaxtree.statement.CastExpr; +import de.dhbwstuttgart.syntaxtree.statement.DoStmt; +import de.dhbwstuttgart.syntaxtree.statement.EmptyStmt; +import de.dhbwstuttgart.syntaxtree.statement.ExpressionReceiver; +import de.dhbwstuttgart.syntaxtree.statement.FieldVar; +import de.dhbwstuttgart.syntaxtree.statement.ForStmt; +import de.dhbwstuttgart.syntaxtree.statement.IfStmt; +import de.dhbwstuttgart.syntaxtree.statement.InstanceOf; +import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; +import de.dhbwstuttgart.syntaxtree.statement.Literal; +import de.dhbwstuttgart.syntaxtree.statement.LocalVar; +import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl; +import de.dhbwstuttgart.syntaxtree.statement.MethodCall; +import de.dhbwstuttgart.syntaxtree.statement.NewArray; +import de.dhbwstuttgart.syntaxtree.statement.NewClass; +import de.dhbwstuttgart.syntaxtree.statement.Return; +import de.dhbwstuttgart.syntaxtree.statement.ReturnVoid; +import de.dhbwstuttgart.syntaxtree.statement.StaticClassName; +import de.dhbwstuttgart.syntaxtree.statement.Super; +import de.dhbwstuttgart.syntaxtree.statement.SuperCall; +import de.dhbwstuttgart.syntaxtree.statement.This; +import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr; +import de.dhbwstuttgart.syntaxtree.statement.WhileStmt; + +public class ArgumentVisitor implements StatementVisitor { + private List argListMethCall; + private BytecodeGenMethod bytecodeGenMethod; + + public ArgumentVisitor(List argListMethCall, BytecodeGenMethod bytecodeGenMethod) { + this.argListMethCall = argListMethCall; + this.bytecodeGenMethod = bytecodeGenMethod; + } + + @Override + public void visit(ArgumentList argumentList) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + lambdaExpression.accept(bytecodeGenMethod); + // Zieltype des Lambas ist Funktionale Interface + // kann nie primitiv sein => un-/boxing wird hier nicht gebraucht + argListMethCall.remove(0); + } + + @Override + public void visit(Assign assign) { + assign.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(assign.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(BinaryExpr binary) { + binary.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(binary.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(Block block) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(CastExpr castExpr) { + castExpr.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(castExpr.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(EmptyStmt emptyStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(FieldVar fieldVar) { + fieldVar.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(fieldVar.getType())); + argListMethCall.remove(0); + } + + @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) { + instanceOf.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(instanceOf.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(LocalVar localVar) { + localVar.accept(bytecodeGenMethod); + if(!bytecodeGenMethod.isBinaryExp) { + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(localVar.getType())); + } + argListMethCall.remove(0); + } + + @Override + public void visit(LocalVarDecl localVarDecl) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(MethodCall methodCall) { + methodCall.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(methodCall.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(NewClass methodCall) { + methodCall.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(methodCall.getType())); + argListMethCall.remove(0); + } + + @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) { + aThis.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(aThis.getType())); + argListMethCall.remove(0); + } + + @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(AssignToField assignLeftSide) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(AssignToLocal assignLeftSide) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(SuperCall superCall) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ExpressionReceiver expressionReceiver) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(UnaryExpr unaryExpr) { + unaryExpr.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(unaryExpr.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(Literal literal) { + literal.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(literal.getType())); + argListMethCall.remove(0); + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java index a3103657..7e3bcac5 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -16,6 +16,7 @@ import org.objectweb.asm.Type; 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.signature.TypeToString; import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; import de.dhbwstuttgart.bytecode.utilities.NormalConstructor; @@ -44,7 +45,7 @@ public class BytecodeGen implements ASTVisitor { private boolean isInterface; private List listOfResultSets; private ResultSet resultSet; - + private SourceFile sf; private String path; private int indexOfFirstParam = 0; @@ -67,9 +68,10 @@ public class BytecodeGen implements ASTVisitor { ArrayList methodNameAndParamsT = new ArrayList<>(); - public BytecodeGen(HashMap classFiles, List listOfResultSets, String path) { + public BytecodeGen(HashMap classFiles, List listOfResultSets,SourceFile sf ,String path) { this.classFiles = classFiles; this.listOfResultSets = listOfResultSets; + this.sf = sf; this.path = path; } @@ -77,7 +79,7 @@ public class BytecodeGen implements ASTVisitor { public void visit(SourceFile sourceFile) { for(ClassOrInterface cl : sourceFile.getClasses()) { System.out.println("in Class: " + cl.getClassName().toString()); - BytecodeGen classGen = new BytecodeGen(classFiles, listOfResultSets,path); + BytecodeGen classGen = new BytecodeGen(classFiles, listOfResultSets, sf, path); cl.accept(classGen); classGen.writeClass(cl.getClassName().toString()); } @@ -178,15 +180,17 @@ public class BytecodeGen implements ASTVisitor { boolean hasGen = false; for(String paramName : methodParamsAndTypes.keySet()) { - String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToDescriptor()); - if(genericsAndBounds.containsKey(typeOfParam)) { + String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature()); + if(genericsAndBounds.containsKey(typeOfParam) ||typeOfParam.substring(0, 4).equals("TPH ") + || typeOfParam.contains("<")) { hasGen = true; break; } } String sig = null; if(hasGen) { - Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes); + ArrayList pairs = simplifyPairs(field.name,tphExtractor.allPairs); + Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes,resultSet,pairs); sig = signature.toString(); } NormalConstructor constructor = new NormalConstructor(field,genericsAndBounds,hasGen); @@ -194,7 +198,7 @@ public class BytecodeGen implements ASTVisitor { MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", desc, sig, null); mv.visitCode(); BytecodeGenMethod gen = new BytecodeGenMethod(className,superClass,resultSet,field, mv,paramsAndLocals,cw, - genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles, path); + genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles, sf,path); if(!field.getParameterList().iterator().hasNext()) { mv.visitInsn(Opcodes.RETURN); } @@ -268,7 +272,7 @@ public class BytecodeGen implements ASTVisitor { mv.visitCode(); BytecodeGenMethod gen = new BytecodeGenMethod(className,superClass,resultSet,method, mv,paramsAndLocals,cw, - genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles, path); + genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles, sf,path); mv.visitMaxs(0, 0); mv.visitEnd(); diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index 6b6cab17..6b24d23b 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -8,9 +8,14 @@ import java.lang.invoke.CallSite; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.lang.reflect.Parameter; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.syntaxtree.statement.*; @@ -36,9 +41,12 @@ import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall; import de.dhbwstuttgart.bytecode.utilities.SamMethod; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.syntaxtree.AbstractASTWalker; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.FormalParameter; import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.SourceFile; import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.result.ResultSet; @@ -55,11 +63,14 @@ public class BytecodeGenMethod implements StatementVisitor { private boolean isInterface; private HashMap genericsAndBoundsMethod; private HashMap genericsAndBounds; - private boolean isBinaryExp = false; + public boolean isBinaryExp = false; private String superClass; private String path; + private SourceFile sf; private IStatement statement = null; - + +// private int numMethodCalls = 0; + // for tests ** private String fieldName; private String fieldDesc; @@ -73,7 +84,7 @@ public class BytecodeGenMethod implements StatementVisitor { public BytecodeGenMethod(String className, String superClass,ResultSet resultSet, Method m, MethodVisitor mv, HashMap paramsAndLocals, ClassWriter cw, HashMap genericsAndBoundsMethod, - HashMap genericsAndBounds, boolean isInterface, HashMap classFiles, String path) { + HashMap genericsAndBounds, boolean isInterface, HashMap classFiles, SourceFile sf,String path) { this.className = className; this.superClass = superClass; @@ -86,6 +97,7 @@ public class BytecodeGenMethod implements StatementVisitor { this.genericsAndBounds = genericsAndBounds; this.isInterface = isInterface; this.classFiles = classFiles; + this.sf = sf; this.path = path; if (!isInterface) @@ -116,7 +128,7 @@ public class BytecodeGenMethod implements StatementVisitor { this.isBinaryExp =isBinary; } - private String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { + public String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor()); } @@ -124,6 +136,11 @@ public class BytecodeGenMethod implements StatementVisitor { public void visit(Block block) { for (Statement stmt : block.getStatements()) { stmt.accept(this); + if(stmt instanceof MethodCall) { + String ret = getResolvedType(((MethodCall) stmt).getType()); + if(!ret.equals("void")) + mv.visitInsn(Opcodes.POP); + } } } @@ -140,7 +157,7 @@ public class BytecodeGenMethod implements StatementVisitor { public void visit(LocalVar localVar) { // wenn String + String zuerst wird ein StringBuilder initialisiert dann // wird die lokale Var geladen. Sonst wird zuerst die lokale Var geladen. - + System.out.println(localVar.name); mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name)); if (isBinaryExp) { @@ -196,7 +213,7 @@ public class BytecodeGenMethod implements StatementVisitor { String largerType = getLargerType(lexpType, rexpType); String typeOfBinary = getResolvedType(binary.getType()); - + if (typeOfBinary.equals(Type.getInternalName(String.class))) { mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(StringBuilder.class)); mv.visitInsn(Opcodes.DUP); @@ -591,7 +608,6 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(CastExpr castExpr) { - // TODO Auto-generated method stub } @@ -603,7 +619,6 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(FieldVar fieldVar) { - fieldName = fieldVar.fieldVarName; fieldDesc = "L" + getResolvedType(fieldVar.getType()) + ";"; @@ -631,51 +646,157 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(InstanceOf instanceOf) { - // TODO Auto-generated method stub } @Override public void visit(MethodCall methodCall) { - - //ClassLoader.getSystemClassLoader().loadClass(className).getMethod(name, parameterTypes) + System.out.println("In MethodCall = " + methodCall.name); String receiverName = getResolvedType(methodCall.receiver.getType()); System.out.println("Methods of " + receiverName + " "); - ClassLoader cl = ClassLoader.getSystemClassLoader(); + ClassLoader cLoader = ClassLoader.getSystemClassLoader(); + java.lang.reflect.Method methodRefl = null; + String clazz = receiverName.replace("/", "."); try { - java.lang.reflect.Method[] methods = cl.loadClass("java.util.Vector").getMethods(); + if(receiverName.contains("<")) { + clazz = clazz.substring(0, receiverName.indexOf("<")); + } + java.lang.reflect.Method[] methods = cLoader.loadClass(clazz).getMethods(); System.out.println("Methods of " + receiverName + " "); for(java.lang.reflect.Method m : methods) { - System.out.println(m.getName() + " " + m.toGenericString()+ " ==> "); + if(methodCall.name.equals(m.getName())) { + methodRefl = m; + break; + } } } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); + 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 + " "); + + for(java.lang.reflect.Method m : methods) { + if(methodCall.name.equals(m.getName())) { + methodRefl = m; + break; + } + } + + break; + } catch (Exception e2) { + receiverName = superClass; + continue; + } + } + } + methodCall.receiver.accept(this); System.out.println("Methodcall type : " + resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor())); - methodCall.receiver.accept(this); - methodCall.arglist.accept(this); - - MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), - receiverName, genericsAndBoundsMethod, genericsAndBounds); - String mDesc = method.accept(new DescriptorToString(resultSet)); + String mDesc = ""; + List argListMethCall = new LinkedList<>(); + if(methodRefl == null) { + MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), + receiverName, genericsAndBoundsMethod, genericsAndBounds); + mDesc = method.accept(new DescriptorToString(resultSet)); + methodCall.arglist.accept(this); + } else { + for(Parameter p:methodRefl.getParameters()) { + System.out.println(p.getName() + " und is Primitive = " + p.getType().isPrimitive()); + argListMethCall.add(p.getType().isPrimitive()); + } + mDesc = getMethodDesc(methodRefl); + for (Expression al : methodCall.arglist.getArguments()) { + statement = new ArgumentExpr(al); + ArgumentVisitor argV = new ArgumentVisitor(argListMethCall,this); + al.accept(argV); + statement = null; + } + } + System.out.println("Methodcall Desc : " + mDesc); + + +// methodCall.arglist.accept(this); + // is methodCall.receiver functional Interface)? if (varsFunInterface.contains(methodCall.receiver.getType())) { - mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()), methodCall.name, + mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, clazz.replace(".", "/"), methodCall.name, mDesc, true); } else { - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, getResolvedType(methodCall.receiver.getType()), methodCall.name, + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, clazz.replace(".", "/"), methodCall.name, mDesc, isInterface); } - // test - // if(!methodCall.getType().toString().equals("V")) { - // mv.visitInsn(Opcodes.POP); - // } - if(isBinaryExp) { - doUnboxing(getResolvedType(methodCall.getType())); + + if(methodRefl != null && !methodRefl.getReturnType().isPrimitive()) { + if(methodRefl.getReturnType().equals(Object.class)) { + String checkCast = getResolvedType(methodCall.getType()); + int pos = checkCast.length(); + if(checkCast.contains("<")) + pos = checkCast.indexOf("<"); + mv.visitTypeInsn(Opcodes.CHECKCAST,checkCast.substring(0,pos)); + } + if(isBinaryExp) + doUnboxing(getResolvedType(methodCall.getType())); } + + } + + private String getMethodDesc(java.lang.reflect.Method methodRefl) { + StringBuilder sb = new StringBuilder("("); + + for(final Class c:(methodRefl.getParameterTypes())) + sb= sb.append(getDescriptorForClass(c)); + + sb.append(')'); + sb.append(getDescriptorForClass(methodRefl.getReturnType())); + return sb.toString(); + } + + private String getDescriptorForClass(final Class c) { + if(c.isPrimitive()) + { + if(c==byte.class) + return "B"; + if(c==char.class) + return "C"; + if(c==double.class) + return "D"; + if(c==float.class) + return "F"; + if(c==int.class) + return "I"; + if(c==long.class) + return "J"; + if(c==short.class) + return "S"; + if(c==boolean.class) + return "Z"; + if(c==void.class) + return "V"; + + } + if(c.isArray()) + return c.getName().replace('.', '/'); + + return ('L'+c.getName()+';').replace('.', '/'); } @Override @@ -707,6 +828,7 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(UnaryExpr unaryExpr) { + unaryExpr.expr.accept(this); Operation op = unaryExpr.operation; @@ -854,7 +976,7 @@ public class BytecodeGenMethod implements StatementVisitor { } // Unboxing: RefType -> prim - private void doUnboxing(String type) { + public void doUnboxing(String type) { switch (type) { case "java/lang/String": mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(StringBuilder.class), "append", @@ -1079,14 +1201,5 @@ public class BytecodeGenMethod implements StatementVisitor { mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.get(var)); } - - private class TPHEx extends AbstractASTWalker{ - // Liste enthält alle tph der Methode - ArrayList allTPHS = new ArrayList<>(); - @Override - public void visit(TypePlaceholder tph) { - allTPHS.add(tph); - } - } } diff --git a/src/de/dhbwstuttgart/bytecode/signature/Signature.java b/src/de/dhbwstuttgart/bytecode/signature/Signature.java index 11f3ca20..8c3fb466 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/Signature.java +++ b/src/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -44,10 +44,13 @@ public class Signature { createSignatureForClassOrInterface(); } - public Signature(Constructor constructor, HashMap genericsAndBounds, HashMap methodParamsAndTypes) { + public Signature(Constructor constructor, HashMap genericsAndBounds, + HashMap methodParamsAndTypes,ResultSet resultSet,ArrayList methodPairs) { this.constructor = constructor; this.genericsAndBounds = genericsAndBounds; this.methodParamsAndTypes = methodParamsAndTypes; + this.resultSet = resultSet; + this.methodPairs = methodPairs; sw = new SignatureWriter(); createSignatureForConsOrMethod(this.constructor,true); } @@ -107,25 +110,28 @@ public class Signature { // 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,ret.length())+"$"; - 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(); - } - } - - if(ret.contains("<")) { - RefType ref = (RefType) resultSet.resolveType(method.getReturnType()).resolvedType; - if(hasTPHs(ref)) { - createSignatureForParameterizedType(ref); - } + if(!isConstructor) { + String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); + System.out.println("RET:::: " + ret); +// if(ret.substring(0,4).equals("TPH ")) { +// String g = ret.substring(4,ret.length())+"$"; + if(genericsAndBounds.containsKey(ret)) { + genericsAndBoundsMethod.put(ret, genericsAndBounds.get(ret)); + }else { + sw.visitFormalTypeParameter(ret); + sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); + genericsAndBoundsMethod.put(ret, Type.getInternalName(Object.class)); + sw.visitClassBound().visitEnd(); + } +// } + if(ret.contains("<")) { + RefType ref = (RefType) resultSet.resolveType(method.getReturnType()).resolvedType; + if(hasTPHs(ref)) { + createSignatureForParameterizedType(ref); + } + + } } // Parameters @@ -133,14 +139,16 @@ public class Signature { 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,pT.length())+"$"; +// if(pT.substring(0,4).equals("TPH ")) { + if(t instanceof TypePlaceholder) { +// String gP = pT.substring(4,pT.length())+"$"; + String gP = t.acceptTV(new TypeToSignature()); 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())) { + if(pT.substring(0,pT.length()).equals(pair.TA1.getName())) { bound = pair.TA2.getName()+"$"; isTypeVar = true; break; @@ -338,6 +346,10 @@ public class Signature { private boolean hasTPHs(RefType ref) { for(RefTypeOrTPHOrWildcardOrGeneric p : ref.getParaList()) { + System.out.println(p.acceptTV(new TypeToString())); + if(p.acceptTV(new TypeToString()).contains("WC")){ + continue; + } if(resultSet.resolveType(p).resolvedType instanceof TypePlaceholder) return true; } @@ -361,7 +373,8 @@ public class Signature { } switch (type) { case "RT": - sv.visitClassType(t.acceptTV(new TypeToSignature())); + String sig = t.acceptTV(new TypeToSignature()); + sv.visitClassType(sig.substring(1, sig.length())); break; case "GRT": GenericRefType g = (GenericRefType) t; @@ -372,13 +385,22 @@ public class Signature { // der Fall wenn die Type eine Interface ist, muss betrachtet werden // Deswegen muss in ResutSet noch enthalten werden, ob die Type eine // Interface oder eine Klasse ist. - if(!r.acceptTV(new TypeToSignature()).substring(0, 4).equals("TPH ")) { + + // das braucht man nicht es reicht: sv.visitTypeVariable(r.acceptTV(new TypeToSignature()) + // +// if(!r.acceptTV(new TypeToSignature()).substring(0, 4).equals("TPH ")) { + String sig2 = r.acceptTV(new TypeToSignature()); + if(!(r instanceof TypePlaceholder)) { + // sv.visitInterface().visitClassType(r.acceptTV(new TypeToSignature())); - sv.visitClassType(r.acceptTV(new TypeToSignature())); +// sv.visitClassType(r.acceptTV(new TypeToSignature())); + sv.visitClassType(sig2.substring(1, sig2.length())); } else { System.out.println(r.getClass()+" Signature TPH: "+r.acceptTV(new TypeToSignature())); - sv.visitTypeVariable(r.acceptTV(new TypeToSignature()).substring(4)+"$"); +// sv.visitTypeVariable(r.acceptTV(new TypeToSignature()).substring(4)+"$"); + sv.visitTypeVariable(sig2.substring(1, sig2.length())); } + break; default: if(!isParameterType) diff --git a/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java b/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java index 62227c8e..02e2a565 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java +++ b/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java @@ -22,34 +22,41 @@ public class TypeToSignature implements TypeVisitor { Iterator it = refType.getParaList().iterator(); while(it.hasNext()){ RefTypeOrTPHOrWildcardOrGeneric param = it.next(); - if(param instanceof TypePlaceholder) { - params += "T" + ((TypePlaceholder) param).getName() + "$"; - } else { - params += "L"+param.toString().replace(".", "/"); - } - +// if(param instanceof TypePlaceholder) { +// params += "T" + ((TypePlaceholder) param).getName() + "$"; +// } else if(param instanceof ExtendsWildcardType) { +// params += "+" + ((ExtendsWildcardType) param).getInnerType().acceptTV(new TypeToSignature()); +// } else if(param instanceof SuperWildcardType) { +// params += "-" + ((SuperWildcardType) param).getInnerType().acceptTV(new TypeToSignature()); +// } else { +// params += "L"+param.toString().replace(".", "/"); +// } + params += param.acceptTV(new TypeToSignature()); if(it.hasNext())params += ";"; } - params += ";>"; + params += ">"; } // String t = refType.getName().toString().replace(".", "/"); // return t.equals("Fun1")?t+"$$"+params+";":t+params+";"; - return refType.getName().toString().replace(".", "/") + params+";"; + return "L"+refType.getName().toString().replace(".", "/") + params+";"; } @Override public String visit(SuperWildcardType superWildcardType) { - throw new NotImplementedException(); +// throw new NotImplementedException(); + return "-" + superWildcardType.getInnerType().acceptTV(new TypeToSignature()); } @Override public String visit(TypePlaceholder typePlaceholder) { - return typePlaceholder.toString().replace(".", "/"); +// return typePlaceholder.toString().replace(".", "/"); + return "T" + typePlaceholder.getName() + "$"; } @Override public String visit(ExtendsWildcardType extendsWildcardType) { - throw new NotImplementedException(); +// throw new NotImplementedException(); + return "+" + extendsWildcardType.getInnerType().acceptTV(new TypeToSignature()); } @Override diff --git a/src/de/dhbwstuttgart/bytecode/signature/TypeToString.java b/src/de/dhbwstuttgart/bytecode/signature/TypeToString.java index 94314afe..a0e280c2 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/TypeToString.java +++ b/src/de/dhbwstuttgart/bytecode/signature/TypeToString.java @@ -17,7 +17,7 @@ public class TypeToString implements TypeVisitor{ @Override public String visit(SuperWildcardType superWildcardType) { - throw new NotImplementedException(); + return "SWC"; } @Override @@ -27,7 +27,7 @@ public class TypeToString implements TypeVisitor{ @Override public String visit(ExtendsWildcardType extendsWildcardType) { - throw new NotImplementedException(); + return "EWC"; } @Override diff --git a/src/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/de/dhbwstuttgart/core/JavaTXCompiler.java index 12845234..6c9763a2 100644 --- a/src/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -235,7 +235,7 @@ public class JavaTXCompiler { HashMap classFiles = new HashMap<>(); SourceFile sf = sourceFiles.get(f); List typeinferenceResult = this.typeInference(); - BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult,path); + BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult,sf,path); // BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult.get(0)); bytecodeGen.visit(sf); this.writeClassFile(bytecodeGen.getClassFiles(), path); diff --git a/test/bytecode/MatrixTest.java b/test/bytecode/MatrixTest.java index db8dc8ab..3ec35e4b 100644 --- a/test/bytecode/MatrixTest.java +++ b/test/bytecode/MatrixTest.java @@ -3,8 +3,12 @@ package bytecode; import static org.junit.Assert.*; import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; +import java.util.Vector; import org.junit.BeforeClass; import org.junit.Test; @@ -20,21 +24,46 @@ public class MatrixTest { private static String pathToClassFile; private static Object instanceOfClass; - @BeforeClass - public static void setUpBeforeClass() throws Exception { +// @BeforeClass +// public static void setUpBeforeClass() throws Exception { +// path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Matrix.jav"; +// fileToTest = new File(path); +// compiler = new JavaTXCompiler(fileToTest); +// pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; +// compiler.generateBytecode(pathToClassFile); +// loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); +// classToTest = loader.loadClass("Matrix"); +// instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); +// } + + @Test + public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, IOException { +// Vector> m1 = new Vector<>(); +// Vector r1 = new Vector<>(); +// r1.addElement(1); +// r1.addElement(0); +// m1.addElement(r1); +// Vector r2 = new Vector<>(); +// r2.addElement(0); +// r2.addElement(1); +// m1.add(r2); +// +// Vector> m2 = new Vector<>(); +// Vector mr1 = new Vector<>(); +// mr1.addElement(1); +// mr1.addElement(2); +// m2.add(mr1); +// Vector mr2 = new Vector<>(); +// mr2.addElement(3); +// mr2.addElement(4); +// m2.add(mr2); + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Matrix.jav"; fileToTest = new File(path); compiler = new JavaTXCompiler(fileToTest); pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; compiler.generateBytecode(pathToClassFile); - loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); - classToTest = loader.loadClass("Matrix"); - instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); - } - - @Test - public void test() { - fail("Not yet implemented"); + } } diff --git a/test/bytecode/javFiles/Matrix.jav b/test/bytecode/javFiles/Matrix.jav index eff095c7..60b9c298 100644 --- a/test/bytecode/javFiles/Matrix.jav +++ b/test/bytecode/javFiles/Matrix.jav @@ -3,24 +3,39 @@ import java.lang.Integer; import java.lang.Boolean; public class Matrix extends Vector> { - mul(m) { + + Matrix () { + } + + Matrix(vv) { + Integer i; + i = 0; + while(i < vv.size()) { +// Boolean a = this.add(vv.elementAt(i)); + this.add(vv.elementAt(i)); + i=i+1; + } + } + + mul(m) { var ret = new Matrix(); var i = 0; while(i < size()) { var v1 = this.elementAt(i); -// var v2 = new Vector(); -// var j = 0; -// while(j < v1.size()) { -// var erg = 0; - // var k = 0; - // while(k < v1.size()) { -// erg = erg + v1.elementAt(k) - // * m.elementAt(k).elementAt(j); - // k++; } - // v2.addElement(new Integer(erg)); -// j++; } -// ret.addElement(v2); -// i++; + var v2 = new Vector(); + var j = 0; + while(j < v1.size()) { + var erg = 0; + var k = 0; + while(k < v1.size()) { + erg = erg + v1.elementAt(k) + * m.elementAt(k).elementAt(j); + k++; } +// v2.addElement(new Integer(erg)); + v2.addElement(erg); + j++; } + ret.addElement(v2); + i++; } return ret; } diff --git a/test/bytecode/javFiles/SubMatrix.jav b/test/bytecode/javFiles/SubMatrix.jav new file mode 100644 index 00000000..4358bbfe --- /dev/null +++ b/test/bytecode/javFiles/SubMatrix.jav @@ -0,0 +1,3 @@ +public class SubMatrix extends Matrix { + +} \ No newline at end of file