diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java index a3103657..a8dce3cf 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -44,7 +44,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 +67,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 +78,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()); } @@ -194,7 +195,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 +269,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..b3bf8650 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -8,9 +8,12 @@ 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.Map; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.syntaxtree.statement.*; @@ -36,9 +39,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; @@ -58,8 +64,10 @@ public class BytecodeGenMethod implements StatementVisitor { private boolean isBinaryExp = false; private String superClass; private String path; + private SourceFile sf; private IStatement statement = null; - + + private Map argListMethRefl = new LinkedHashMap<>(); // for tests ** private String fieldName; private String fieldDesc; @@ -73,7 +81,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 +94,7 @@ public class BytecodeGenMethod implements StatementVisitor { this.genericsAndBounds = genericsAndBounds; this.isInterface = isInterface; this.classFiles = classFiles; + this.sf = sf; this.path = path; if (!isInterface) @@ -140,12 +149,19 @@ 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)); - + // Für Matrix Test if (isBinaryExp) { doUnboxing(getResolvedType(localVar.getType())); } + if(!argListMethRefl.isEmpty() && !isBinaryExp) { + System.out.println("is Empty?? " + argListMethRefl.isEmpty()); + argListMethRefl.forEach((k,v) -> System.out.println(k + "->" + v)); + System.out.println("Local Var= " + localVar.name); + if(argListMethRefl.get(localVar.name)) + doUnboxing(getResolvedType(localVar.getType())); + } } // ?? @@ -637,45 +653,161 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(MethodCall methodCall) { - + System.out.println("In MethodCall = " + methodCall.name); //ClassLoader.getSystemClassLoader().loadClass(className).getMethod(name, parameterTypes) 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 = cl.loadClass("java.util.Vector").getMethods(); + 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 = ""; +// boolean findSuper = true; + // TODO: Test SubMatrix.jav + while(true) { +// findSuper = false; + 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) { +// findSuper = true; + 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 = ""; + if(methodRefl == null) { + MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), + receiverName, genericsAndBoundsMethod, genericsAndBounds); + mDesc = method.accept(new DescriptorToString(resultSet)); + } else { + for(Parameter p:methodRefl.getParameters()) { + System.out.println(p.getName() + " und is Primitive = " + p.getType().isPrimitive()); + argListMethRefl.put(p.getName(), p.getType().isPrimitive()); + } + int i = 0; + for(Expression a:methodCall.arglist.getArguments()) { + if(a instanceof LocalVar) { + LocalVar lv = (LocalVar) a; + Boolean isPrim = argListMethRefl.remove("arg"+i); + argListMethRefl.put(lv.name, isPrim); + } + i++; + } + mDesc = getMethodDesc(methodRefl); + } + 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())); } + argListMethRefl.clear(); + } + + 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 @@ -1079,14 +1211,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..0509c678 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/Signature.java +++ b/src/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -133,8 +133,10 @@ 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); @@ -338,6 +340,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 +367,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 +379,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 c4db69f2..ffa8d54d 100644 --- a/src/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -246,7 +246,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..64132861 100644 --- a/test/bytecode/javFiles/Matrix.jav +++ b/test/bytecode/javFiles/Matrix.jav @@ -8,19 +8,19 @@ public class Matrix extends Vector> { 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(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