From 52c445435debb4365a5c415806580d3104dba0b0 Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Mon, 6 Aug 2018 13:25:41 +0200 Subject: [PATCH 1/3] MergeTest --- .../bytecode/signature/Signature.java | 42 +++++++++++++++++- .../bytecode/signature/TypeToSignature.java | 4 +- test/bytecode/MergeTest.java | 43 +++++++++++++++++++ test/bytecode/javFiles/Merge.jav | 17 ++++++++ test/bytecode/javFiles/PTGen.jav | 5 +++ 5 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 test/bytecode/MergeTest.java create mode 100644 test/bytecode/javFiles/Merge.jav create mode 100644 test/bytecode/javFiles/PTGen.jav diff --git a/src/de/dhbwstuttgart/bytecode/signature/Signature.java b/src/de/dhbwstuttgart/bytecode/signature/Signature.java index c32cbf86..ae91932a 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/Signature.java +++ b/src/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -20,6 +20,7 @@ import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.syntaxtree.type.WildcardType; import de.dhbwstuttgart.typeinference.result.GenericInsertPair; import de.dhbwstuttgart.typeinference.result.ResolvedType; import de.dhbwstuttgart.typeinference.result.ResultSet; @@ -104,10 +105,13 @@ public class Signature { Iterator itr = method.getGenerics().iterator(); // visits all formal type parameter and visits their bounds while(itr.hasNext()) { + System.out.println("HAS GENERICS!!"); GenericTypeVar g = itr.next(); getBoundsOfTypeVar(g,genericsAndBoundsMethod); } + //TODO: paramtrisierte Typen mit Generics, Type Variablen müssen definiert werden. + // 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 if(!isConstructor) { @@ -131,7 +135,9 @@ public class Signature { if(hasTPHs(ref)) { createSignatureForParameterizedType(ref); } - + System.out.println("HAS WC = " + hasWC(ref)); + if(hasWC(ref)) + createSigForParamTypeWithWC(ref); } } } @@ -170,6 +176,10 @@ public class Signature { RefType ref = (RefType) methodParamsAndTypes.get(paramName); if(hasTPHs(ref)) createSignatureForParameterizedType(ref); + + System.out.println("HAS WC = " + hasWC(ref)); + if(hasWC(ref)) + createSigForParamTypeWithWC(ref); } for(GenericInsertPair p:methodPairs) { @@ -218,6 +228,34 @@ public class Signature { // sw.visitEnd(); } + private void createSigForParamTypeWithWC(RefType ref) { + for(RefTypeOrTPHOrWildcardOrGeneric p : ref.getParaList()) { + if(p instanceof WildcardType) { + if(((WildcardType) p).getInnerType() instanceof GenericRefType) { + String name = new TypeToSignature().visit((GenericRefType)((WildcardType) p).getInnerType()); + if(!genericsAndBoundsMethod.containsKey(name) && !genericsAndBounds.containsKey(name)) { + sw.visitFormalTypeParameter(name); + sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); + sw.visitClassBound().visitEnd(); + genericsAndBoundsMethod.put(name, Type.getInternalName(Object.class)); + } + } + } + } + + } + + private boolean hasWC(RefType ref) { + for(RefTypeOrTPHOrWildcardOrGeneric p : ref.getParaList()) { + System.out.println("HAS WCs: " + p.acceptTV(new TypeToString())); + System.out.println("HAS WCs: " + p.getClass()); + if(p.acceptTV(new TypeToString()).contains("WC")) + return true; + + } + return false; + } + private void createSignatureForParameterizedType(RefType ref) { ArrayList allPairs = getAllPairs(ref); allPairs.addAll(methodPairs); @@ -347,7 +385,7 @@ public class Signature { private boolean hasTPHs(RefType ref) { for(RefTypeOrTPHOrWildcardOrGeneric p : ref.getParaList()) { - System.out.println(p.acceptTV(new TypeToString())); + System.out.println("HAS TPHs: " + p.acceptTV(new TypeToString())); if(p.acceptTV(new TypeToString()).contains("WC")){ continue; } diff --git a/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java b/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java index 31d288f7..3bad4066 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java +++ b/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java @@ -48,7 +48,7 @@ public class TypeToSignature implements TypeVisitor { @Override public String visit(SuperWildcardType superWildcardType) { // throw new NotImplementedException(); - return "-" + superWildcardType.getInnerType().acceptTV(new TypeToSignature()); + return "+" + superWildcardType.getInnerType().acceptTV(new TypeToSignature()); } @Override @@ -60,7 +60,7 @@ public class TypeToSignature implements TypeVisitor { @Override public String visit(ExtendsWildcardType extendsWildcardType) { // throw new NotImplementedException(); - return "+" + extendsWildcardType.getInnerType().acceptTV(new TypeToSignature()); + return "-" + extendsWildcardType.getInnerType().acceptTV(new TypeToSignature()); } @Override diff --git a/test/bytecode/MergeTest.java b/test/bytecode/MergeTest.java new file mode 100644 index 00000000..37345ca8 --- /dev/null +++ b/test/bytecode/MergeTest.java @@ -0,0 +1,43 @@ +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 MergeTest { + 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/Merge.jav"; +// fileToTest = new File(path); +// compiler = new JavaTXCompiler(fileToTest); +// compiler.generateBytecode(System.getProperty("user.dir")+"/testBytecode/generatedBC/"); +// pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; +// loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); +// classToTest = loader.loadClass("Merge"); +// instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); +// } + + @Test + public void generateBC() throws Exception{ + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Merge.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/testBytecode/generatedBC/"); + } + +} diff --git a/test/bytecode/javFiles/Merge.jav b/test/bytecode/javFiles/Merge.jav new file mode 100644 index 00000000..b2cd9920 --- /dev/null +++ b/test/bytecode/javFiles/Merge.jav @@ -0,0 +1,17 @@ +import java.util.List; +import java.lang.Integer; +import java.util.Collection; + +class Merge { + + merge(a, b) { + a.addAll(b); + return a; + } + + sort(in){ + var firstHalf = in.subList(1,2); + var secondHalf = in.subList(1,2); + return merge(sort(firstHalf), sort(secondHalf)); + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/PTGen.jav b/test/bytecode/javFiles/PTGen.jav new file mode 100644 index 00000000..f08bdc83 --- /dev/null +++ b/test/bytecode/javFiles/PTGen.jav @@ -0,0 +1,5 @@ +public class PTGen { + m(List list) { + return list; + } +} \ No newline at end of file From dd8b4f322e19e8a9f50a109c1c88e66260e6fd8b Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Mon, 6 Aug 2018 14:46:54 +0200 Subject: [PATCH 2/3] BinaryTest funktioniert --- .../bytecode/BytecodeGenMethod.java | 30 +++++++++++++++---- test/bytecode/javFiles/PTGen.jav | 5 ---- 2 files changed, 24 insertions(+), 11 deletions(-) delete mode 100644 test/bytecode/javFiles/PTGen.jav diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index 32570541..1719d64d 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -69,6 +69,10 @@ public class BytecodeGenMethod implements StatementVisitor { private SourceFile sf; private IStatement statement = null; + private boolean returnParentOfUnary = false; + // speichert, ob der Argument RefType ist. + private List argList = new LinkedList<>(); + // private int numMethodCalls = 0; // for tests ** @@ -273,10 +277,6 @@ public class BytecodeGenMethod implements StatementVisitor { } - /* - * Diese Methode wird nicht mehr gebraucht, da es jetzt nicht möglich ist, dass - * solche Fälle: Integer -> Integer (OP) Short ,... usw, nicht vorkommen! - */ private String getLargerType(String lexpType, String rexpType) { if (lexpType.equals(Type.getInternalName(String.class)) || rexpType.equals(Type.getInternalName(String.class))) { @@ -713,6 +713,10 @@ public class BytecodeGenMethod implements StatementVisitor { String mDesc = ""; List argListMethCall = new LinkedList<>(); if(methodRefl == null) { + // Alle Argumente sind nicht Primitiv + for(Expression arg : methodCall.arglist.getArguments()) { + argList.add(true); + } MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), receiverName, genericsAndBoundsMethod, genericsAndBounds); mDesc = method.accept(new DescriptorToString(resultSet)); @@ -864,10 +868,13 @@ public class BytecodeGenMethod implements StatementVisitor { // Für Byte und Short muss noch einen Cast geben i2b, i2s // das wird später gemacht, da bytecode für cast noch nicht erzeugt wird - if (isIncOrDec && (unaryExpr.expr instanceof LocalVar)) { + if (isIncOrDec && (unaryExpr.expr instanceof LocalVar) && !returnParentOfUnary) { LocalVar local = (LocalVar) unaryExpr.expr; mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.get(local.name)); } + + if(returnParentOfUnary) + returnParentOfUnary = false; } private void doVisitNegIns(String typeOfUnary) { @@ -913,7 +920,10 @@ public class BytecodeGenMethod implements StatementVisitor { public void visit(Return aReturn) { statement = new ReturnStmt(aReturn.retexpr); isBinaryExp = statement.isExprBinary(); - + + if(aReturn.retexpr instanceof UnaryExpr) + returnParentOfUnary = true; + aReturn.retexpr.accept(this); if (isBinaryExp) { @@ -1173,7 +1183,15 @@ public class BytecodeGenMethod implements StatementVisitor { public void visit(ArgumentList argumentList) { for (Expression al : argumentList.getArguments()) { statement = new ArgumentExpr(al); + isBinaryExp = statement.isExprBinary(); al.accept(this); + //TODO: teste, ob man das für unary braucht + if (isBinaryExp) { + BinaryExpr binary = (BinaryExpr) al; + String binaryType = getResolvedType(binary.getType()); + doBoxing(binaryType); + isBinaryExp = false; + } statement = null; } } diff --git a/test/bytecode/javFiles/PTGen.jav b/test/bytecode/javFiles/PTGen.jav deleted file mode 100644 index f08bdc83..00000000 --- a/test/bytecode/javFiles/PTGen.jav +++ /dev/null @@ -1,5 +0,0 @@ -public class PTGen { - m(List list) { - return list; - } -} \ No newline at end of file From f99d4dae5a3bf074794d80308f5145223747193a Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Mon, 6 Aug 2018 16:14:09 +0200 Subject: [PATCH 3/3] DUP Befehl fuer UnaryExpr --- .../bytecode/BytecodeGenMethod.java | 37 ++++++++++--------- test/bytecode/BinaryTest.java | 7 ++++ test/bytecode/MergeTest.java | 6 +-- test/bytecode/javFiles/BinaryInMeth.jav | 4 ++ 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index 1719d64d..643e98d5 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -69,11 +69,7 @@ public class BytecodeGenMethod implements StatementVisitor { private SourceFile sf; private IStatement statement = null; - private boolean returnParentOfUnary = false; - // speichert, ob der Argument RefType ist. - private List argList = new LinkedList<>(); - -// private int numMethodCalls = 0; + private boolean needDUP = false; // for tests ** private String fieldName; @@ -163,7 +159,7 @@ public class BytecodeGenMethod implements StatementVisitor { // 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) { doUnboxing(getResolvedType(localVar.getType())); } @@ -199,6 +195,7 @@ public class BytecodeGenMethod implements StatementVisitor { doBoxing(binaryType); isBinaryExp = false; } + System.out.println("ASSIGN TYPE R: " + getResolvedType(assign.rightSide.getType())); String typeOfRightSide = getResolvedType(assign.rightSide.getType()); if(typeOfRightSide.contains("<")) { @@ -229,12 +226,18 @@ public class BytecodeGenMethod implements StatementVisitor { // this case for while loops if (statement instanceof LoopStmt) mv.visitLabel(endLabel); - + + if(binary.lexpr instanceof UnaryExpr) + needDUP = true; + binary.lexpr.accept(this); if (!lexpType.equals(rexpType) && !lexpType.equals(largerType)) doCast(lexpType, largerType); - + + if(binary.rexpr instanceof UnaryExpr) + needDUP = true; + binary.rexpr.accept(this); if (!lexpType.equals(rexpType) && !rexpType.equals(largerType)) @@ -713,10 +716,6 @@ public class BytecodeGenMethod implements StatementVisitor { String mDesc = ""; List argListMethCall = new LinkedList<>(); if(methodRefl == null) { - // Alle Argumente sind nicht Primitiv - for(Expression arg : methodCall.arglist.getArguments()) { - argList.add(true); - } MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), receiverName, genericsAndBoundsMethod, genericsAndBounds); mDesc = method.accept(new DescriptorToString(resultSet)); @@ -832,7 +831,6 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(UnaryExpr unaryExpr) { - unaryExpr.expr.accept(this); Operation op = unaryExpr.operation; @@ -868,13 +866,14 @@ public class BytecodeGenMethod implements StatementVisitor { // Für Byte und Short muss noch einen Cast geben i2b, i2s // das wird später gemacht, da bytecode für cast noch nicht erzeugt wird - if (isIncOrDec && (unaryExpr.expr instanceof LocalVar) && !returnParentOfUnary) { + if (isIncOrDec && (unaryExpr.expr instanceof LocalVar)) { + if(needDUP) { + mv.visitInsn(Opcodes.DUP); + needDUP = false; + } LocalVar local = (LocalVar) unaryExpr.expr; mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.get(local.name)); } - - if(returnParentOfUnary) - returnParentOfUnary = false; } private void doVisitNegIns(String typeOfUnary) { @@ -922,7 +921,7 @@ public class BytecodeGenMethod implements StatementVisitor { isBinaryExp = statement.isExprBinary(); if(aReturn.retexpr instanceof UnaryExpr) - returnParentOfUnary = true; + needDUP = true; aReturn.retexpr.accept(this); @@ -1184,6 +1183,8 @@ public class BytecodeGenMethod implements StatementVisitor { for (Expression al : argumentList.getArguments()) { statement = new ArgumentExpr(al); isBinaryExp = statement.isExprBinary(); + if(al instanceof UnaryExpr) + needDUP = true; al.accept(this); //TODO: teste, ob man das für unary braucht if (isBinaryExp) { diff --git a/test/bytecode/BinaryTest.java b/test/bytecode/BinaryTest.java index 543786ad..84f102b7 100644 --- a/test/bytecode/BinaryTest.java +++ b/test/bytecode/BinaryTest.java @@ -39,5 +39,12 @@ public class BinaryTest { Integer res = (Integer) m2.invoke(instanceOfClass, 2,3); assertEquals(6, res); } + + @Test + public void testM3() throws Exception { + Method m3 = classToTest.getDeclaredMethod("m3", Integer.class); + Integer res = (Integer) m3.invoke(instanceOfClass, 2); + assertEquals(4, res); + } } diff --git a/test/bytecode/MergeTest.java b/test/bytecode/MergeTest.java index 6a0044ce..9f3943ca 100644 --- a/test/bytecode/MergeTest.java +++ b/test/bytecode/MergeTest.java @@ -28,9 +28,9 @@ public class MergeTest { fileToTest = new File(path); compiler = new JavaTXCompiler(fileToTest); compiler.generateBytecode(System.getProperty("user.dir")+"/testBytecode/generatedBC/"); - pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; - loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); - classToTest = loader.loadClass("Merge"); +// pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; +// loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); +// classToTest = loader.loadClass("Merge"); //instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); //Method m = classToTest.getDeclaredMethod("m"); diff --git a/test/bytecode/javFiles/BinaryInMeth.jav b/test/bytecode/javFiles/BinaryInMeth.jav index c77d7767..3b5fa77b 100644 --- a/test/bytecode/javFiles/BinaryInMeth.jav +++ b/test/bytecode/javFiles/BinaryInMeth.jav @@ -10,4 +10,8 @@ public class BinaryInMeth { m2(a,b){ return m(a+b); } + + m3(a) { + return m(++a); + } } \ No newline at end of file