From 0f29bc038a8b1dc514ea9fbeed00258a7f21e3f5 Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Wed, 23 May 2018 15:38:41 +0200 Subject: [PATCH] =?UTF-8?q?Bugs=20gefixt.=20Tests=20f=C3=BCr=20relationale?= =?UTF-8?q?n=20Operatoren(GreaterEqualTest,=20...)=20laufen.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Für Typplaceholder werden Generics verwendet. Neue Tests angefügt. --- .../dhbwstuttgart/bytecode/BytecodeGen.java | 7 +- .../bytecode/BytecodeGenMethod.java | 220 +++++++++--------- .../descriptor/DescriptorToString.java | 17 +- .../bytecode/descriptor/TypeToDescriptor.java | 5 +- .../bytecode/signature/Signature.java | 51 +++- .../bytecode/signature/TypeToSignature.java | 2 + test/bytecode/BinaryTest.java | 40 ++++ test/bytecode/FacTest.java | 44 ++++ test/bytecode/PlusTest.java | 2 +- test/bytecode/RelOpsTest.java | 44 ++++ test/bytecode/javFiles/BinaryInMeth.jav | 11 + test/bytecode/javFiles/Fac.jav | 16 ++ test/bytecode/javFiles/Gen.jav | 2 +- test/bytecode/javFiles/Matrix.jav | 26 +-- test/bytecode/javFiles/Op.jav | 2 +- test/bytecode/javFiles/Plus.jav | 2 +- test/bytecode/javFiles/RelOps.jav | 7 + test/bytecode/javFiles/While.jav | 4 + test/logFiles/log | 107 +++++++++ 19 files changed, 467 insertions(+), 142 deletions(-) create mode 100644 test/bytecode/BinaryTest.java create mode 100644 test/bytecode/FacTest.java create mode 100644 test/bytecode/RelOpsTest.java create mode 100644 test/bytecode/javFiles/BinaryInMeth.jav create mode 100644 test/bytecode/javFiles/Fac.jav create mode 100644 test/bytecode/javFiles/RelOps.jav create mode 100644 test/logFiles/log diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java index 36c7173a..f9bf72ed 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -117,7 +117,7 @@ public class BytecodeGen implements ASTVisitor { boolean isConsWithNoParamsVisited = false; for(ResultSet rs : listOfResultSets) { resultSet = rs; - + for(Constructor c : classOrInterface.getConstructors()) { if(!isConsWithNoParamsVisited) c.accept(this); @@ -191,13 +191,13 @@ public class BytecodeGen implements ASTVisitor { System.out.println(acc); /*Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist*/ - boolean hasGenInParameterList = genericsAndBounds.containsKey(resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())); + boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.subSequence(0, 4).equals("TPH "); /*Wenn die Rückgabe-Type eine Typ-variable ist, erzeuge direkt die Signature, wenn nicht, * prüfe, ob einer der Parameter Typ-Variable als Typ hat*/ if(!hasGenInParameterList) { for(String paramName : methodParamsAndTypes.keySet()) { String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToDescriptor()); - if(genericsAndBounds.containsKey(typeOfParam)) { + if(genericsAndBounds.containsKey(typeOfParam)||typeOfParam.substring(0, 4).equals("TPH ")) { hasGenInParameterList = true; break; } @@ -213,6 +213,7 @@ public class BytecodeGen implements ASTVisitor { boolean hasGen = method.getGenerics().iterator().hasNext() || hasGenInParameterList; /* if method has generics or return type is TPH, create signature */ + // zwite operand muss weggelassen werden if(hasGen||method.getReturnType().acceptTV(new TypeToString()).equals("TPH")) { // resultset hier zum testen Signature signature = new Signature(method, genericsAndBoundsMethod, methodParamsAndTypes,resultSet); diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index 8b928a31..8bb7dca1 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -29,8 +29,6 @@ import org.objectweb.asm.signature.SignatureWriter; 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.KindOfLambda; import de.dhbwstuttgart.bytecode.utilities.Lambda; import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall; @@ -55,20 +53,17 @@ public class BytecodeGenMethod implements StatementVisitor { HashMap genericsAndBoundsMethod; private HashMap genericsAndBounds; private boolean isBinaryExp = false; - - private IStatement statement; + + private IStatement statement = null; // for tests ** private String fieldName; private String fieldDesc; private Expression rightSideTemp; - + private boolean isRightSideALambda = false; private KindOfLambda kindOfLambda; private HashMap classFiles; - - private boolean isAssignStmt = false; - private Statement loopBlock; private ArrayList varsFunInterface = new ArrayList<>();; @@ -113,7 +108,7 @@ public class BytecodeGenMethod implements StatementVisitor { private String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor()); } - + @Override public void visit(Block block) { for (Statement stmt : block.getStatements()) { @@ -138,7 +133,7 @@ public class BytecodeGenMethod implements StatementVisitor { mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name)); if (isBinaryExp) { - getVlaueIns(getResolvedType(localVar.getType())); + doUnboxing(getResolvedType(localVar.getType())); } } @@ -151,8 +146,6 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(Assign assign) { statement = new AssignStmt(assign.rightSide); - isAssignStmt = true; - // if the right side is a lambda => the left side must be a functional interface if (assign.rightSide instanceof LambdaExpression) { isRightSideALambda = true; @@ -161,7 +154,6 @@ public class BytecodeGenMethod implements StatementVisitor { } isBinaryExp = statement.isExprBinary(); - if (assign.lefSide instanceof AssignToField) { // load_0, ldc or .. then putfield @@ -171,26 +163,24 @@ public class BytecodeGenMethod implements StatementVisitor { } if (isBinaryExp) { BinaryExpr binary = (BinaryExpr) assign.rightSide; - String lexpType = getResolvedType(binary.lexpr.getType()); - String rexpType = getResolvedType(binary.rexpr.getType()); - getValueOfIns(getLargerType(lexpType, rexpType)); + String binaryType = getResolvedType(binary.getType()); + doBoxing(binaryType); isBinaryExp = false; } assign.lefSide.accept(this); - - isAssignStmt =false; - } + statement = null; + } @Override public void visit(BinaryExpr binary) { - + String lexpType = getResolvedType(binary.lexpr.getType()); String rexpType = getResolvedType(binary.rexpr.getType()); - - String largerType = getLargerType(lexpType,rexpType); + + 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); @@ -200,23 +190,21 @@ public class BytecodeGenMethod implements StatementVisitor { Label endLabel = new Label(); // this case for while loops - if(statement instanceof LoopStmt) + if (statement instanceof LoopStmt) mv.visitLabel(endLabel); - + binary.lexpr.accept(this); - - if(!lexpType.equals(rexpType) && - !lexpType.equals(largerType)) + + if (!lexpType.equals(rexpType) && !lexpType.equals(largerType)) doCast(lexpType, largerType); - + binary.rexpr.accept(this); - - if(!lexpType.equals(rexpType) && - !rexpType.equals(largerType)) + + if (!lexpType.equals(rexpType) && !rexpType.equals(largerType)) doCast(rexpType, largerType); - + Operator op = binary.operation; - + switch (op) { case ADD: doVisitAddOpInsn(largerType); @@ -243,28 +231,31 @@ public class BytecodeGenMethod implements StatementVisitor { case BIGGERTHAN: case BIGGEREQUAL: Label branchLabel = new Label(); - doVisitRelOpInsn(op,largerType, branchLabel, endLabel); + doVisitRelOpInsn(op, largerType, branchLabel, endLabel); break; - + default: break; } } + /* + * 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))) { + if (lexpType.equals(Type.getInternalName(String.class)) + || rexpType.equals(Type.getInternalName(String.class))) { return Type.getInternalName(String.class); - } else - if(lexpType.equals(Type.getInternalName(Double.class)) || - rexpType.equals(Type.getInternalName(Double.class))) { + } else if (lexpType.equals(Type.getInternalName(Double.class)) + || rexpType.equals(Type.getInternalName(Double.class))) { return Type.getInternalName(Double.class); - } else if(lexpType.equals(Type.getInternalName(Float.class)) || - rexpType.equals(Type.getInternalName(Float.class))) { + } else if (lexpType.equals(Type.getInternalName(Float.class)) + || rexpType.equals(Type.getInternalName(Float.class))) { return Type.getInternalName(Float.class); - } else if(lexpType.equals(Type.getInternalName(Long.class)) || - rexpType.equals(Type.getInternalName(Long.class))) { + } else if (lexpType.equals(Type.getInternalName(Long.class)) + || rexpType.equals(Type.getInternalName(Long.class))) { return Type.getInternalName(Long.class); } else { return Type.getInternalName(Integer.class); @@ -276,19 +267,19 @@ public class BytecodeGenMethod implements StatementVisitor { case "java/lang/Long": mv.visitInsn(Opcodes.I2L); break; - + case "java/lang/Double": - if(sourceType.equals(Type.getInternalName(Long.class))) { + if (sourceType.equals(Type.getInternalName(Long.class))) { mv.visitInsn(Opcodes.L2D); - } else if(sourceType.equals(Type.getInternalName(Float.class))) { + } else if (sourceType.equals(Type.getInternalName(Float.class))) { mv.visitInsn(Opcodes.F2D); } else { mv.visitInsn(Opcodes.I2D); } break; - + case "java/lang/Float": - if(sourceType.equals(Type.getInternalName(Long.class))) { + if (sourceType.equals(Type.getInternalName(Long.class))) { mv.visitInsn(Opcodes.L2F); } else { mv.visitInsn(Opcodes.I2F); @@ -296,14 +287,18 @@ public class BytecodeGenMethod implements StatementVisitor { break; // braucht man eigentlic nicht, muss getestet werden case "java/lang/String": - if(sourceType.equals(Type.getInternalName(Double.class))) { - mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(D)Ljava/lang/String;", false); - } else if(sourceType.equals(Type.getInternalName(Long.class))) { - mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(J)Ljava/lang/String;", false); - } else if(sourceType.equals(Type.getInternalName(Float.class))) { - mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(F)Ljava/lang/String;", false); + if (sourceType.equals(Type.getInternalName(Double.class))) { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", + "(D)Ljava/lang/String;", false); + } else if (sourceType.equals(Type.getInternalName(Long.class))) { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", + "(J)Ljava/lang/String;", false); + } else if (sourceType.equals(Type.getInternalName(Float.class))) { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", + "(F)Ljava/lang/String;", false); } else { - mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(I)Ljava/lang/String;", false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", + "(I)Ljava/lang/String;", false); } break; default: @@ -312,7 +307,7 @@ public class BytecodeGenMethod implements StatementVisitor { } private void doVisitRelOpInsn(Operator op, String typeOfBinary, Label branchLabel, Label endLabel) { - + switch (typeOfBinary) { case "java/lang/Long": mv.visitInsn(Opcodes.LCMP); @@ -343,9 +338,9 @@ public class BytecodeGenMethod implements StatementVisitor { default: break; } - - statement.genBCForRelOp(mv, branchLabel, endLabel,this); - + + statement.genBCForRelOp(mv, branchLabel, endLabel, this); + break; } } @@ -368,8 +363,8 @@ public class BytecodeGenMethod implements StatementVisitor { default: break; } + statement.genBCForRelOp(mv, branchLabel, endLabel, this); - } private void doVisitModOpInsn(String typeOfBinary) { @@ -532,7 +527,7 @@ public class BytecodeGenMethod implements StatementVisitor { cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup", "java/lang/invoke/MethodHandles", "Lookup", Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL); - generateBCForFunN(lambdaExpression,typeErasure); + generateBCForFunN(lambdaExpression, typeErasure); } private void generateBCForFunN(LambdaExpression lambdaExpression, String methDesc) { @@ -626,7 +621,7 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(MethodCall methodCall) { - + methodCall.receiver.accept(this); methodCall.arglist.accept(this); @@ -634,7 +629,7 @@ public class BytecodeGenMethod implements StatementVisitor { genericsAndBoundsMethod, genericsAndBounds); String mDesc = method.accept(new DescriptorToString(resultSet)); - // is methodCall.receiver functional Interface)? + // is methodCall.receiver functional Interface)? if (varsFunInterface.contains(methodCall.receiver.getType())) { mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()), methodCall.name, mDesc, false); @@ -650,7 +645,7 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(NewClass methodCall) { - + mv.visitTypeInsn(Opcodes.NEW, methodCall.name.replace(".", "/")); mv.visitInsn(Opcodes.DUP); // creates Descriptor @@ -679,40 +674,40 @@ public class BytecodeGenMethod implements StatementVisitor { public void visit(UnaryExpr unaryExpr) { unaryExpr.expr.accept(this); Operation op = unaryExpr.operation; - + String typeOfUnary = getResolvedType(unaryExpr.getType()); - + boolean isIncOrDec = false; - + switch (op) { case POSTDECREMENT: case POSTINCREMENT: - if(isAssignStmt) + if (statement instanceof AssignStmt) mv.visitInsn(Opcodes.DUP); genBCForIncAndDec(op, typeOfUnary); - getValueOfIns(typeOfUnary); + doBoxing(typeOfUnary); isIncOrDec = true; break; case PREDECREMENT: case PREINCREMENT: genBCForIncAndDec(op, typeOfUnary); - getValueOfIns(typeOfUnary); - if(isAssignStmt) + doBoxing(typeOfUnary); + if (statement instanceof AssignStmt) mv.visitInsn(Opcodes.DUP); isIncOrDec = true; break; - + case MINUS: doVisitNegIns(typeOfUnary); break; default: break; } - + // 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)) { LocalVar local = (LocalVar) unaryExpr.expr; mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.get(local.name)); } @@ -733,14 +728,14 @@ public class BytecodeGenMethod implements StatementVisitor { mv.visitInsn(Opcodes.INEG); break; } - + } private void genBCForIncAndDec(Operation op, String typeOfUnary) { - - getVlaueIns(typeOfUnary); - doAssign(typeOfUnary, 1.0, true); - + + doUnboxing(typeOfUnary); + loadValue(typeOfUnary, 1.0, true); + switch (op) { case POSTDECREMENT: case PREDECREMENT: @@ -751,7 +746,7 @@ public class BytecodeGenMethod implements StatementVisitor { case PREINCREMENT: doVisitAddOpInsn(typeOfUnary); break; - + default: break; } @@ -759,22 +754,19 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(Return aReturn) { - statement = new ReturnStmt(aReturn.retexpr); - isBinaryExp = statement.isExprBinary(); - + aReturn.retexpr.accept(this); - + if (isBinaryExp) { BinaryExpr binary = (BinaryExpr) aReturn.retexpr; - String lexpType = getResolvedType(binary.lexpr.getType()); - String rexpType = getResolvedType(binary.rexpr.getType()); - getValueOfIns(getLargerType(lexpType, rexpType)); + doBoxing(getResolvedType(binary.getType())); isBinaryExp = false; } - + mv.visitInsn(Opcodes.ARETURN); + statement = null; } @Override @@ -787,7 +779,8 @@ public class BytecodeGenMethod implements StatementVisitor { // mv.visitMethodInsn(Opcodes.INVOKESTATIC, // staticClassName.getType().toString().replace(".", "/"), // staticClassName.toString(), staticClassName.getType().toString(), false); - //mv.visitFieldInsn(Opcodes.GETSTATIC, getResolvedType(staticClassName.getType()), fieldName, fieldDesc); + // mv.visitFieldInsn(Opcodes.GETSTATIC, + // getResolvedType(staticClassName.getType()), fieldName, fieldDesc); throw new NotImplementedException("Static noch nicht implementiert!"); } @@ -803,16 +796,11 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(WhileStmt whileStmt) { - statement = new LoopStmt(whileStmt.expr, whileStmt.loopBlock); - this.loopBlock = whileStmt.loopBlock; - - isBinaryExp = statement.isExprBinary(); - whileStmt.expr.accept(this); - isBinaryExp = false; + statement = null; } @Override @@ -825,12 +813,13 @@ public class BytecodeGenMethod implements StatementVisitor { public void visit(Literal literal) { Object value = literal.value; String typeOfLiteral = getResolvedType(literal.getType()); - // Name der Methode muss geändert werden - doAssign(typeOfLiteral, value, false); - + // Der Wert des Literals wird auf den Stack geladen und + // geboxt, wenn es nötig ist. + loadValue(typeOfLiteral, value, false); } - private void getVlaueIns(String type) { + // Unboxing: RefType -> prim + private void doUnboxing(String type) { switch (type) { case "java/lang/String": mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(StringBuilder.class), "append", @@ -860,11 +849,13 @@ public class BytecodeGenMethod implements StatementVisitor { case "java/lang/Character": break; default: + // mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", + // "()I", false); break; } } - private void doAssign(String type, Object value, boolean isOperator) { + private void loadValue(String type, Object value, boolean isOperator) { switch (type) { case "java/lang/String": mv.visitLdcInsn(String.valueOf(value)); @@ -895,17 +886,21 @@ public class BytecodeGenMethod implements StatementVisitor { visitCharLiteral((Character) value); break; default: + // wenn die Typ des Literals = Number ist, wird integer-value + // verwendet + // visitIntegerLiteral(((Double) value).intValue(), false); break; } - - if(!type.equals("java/lang/String")&&!type.equals("java/lang/Boolean")) { + // Boxing + if (!type.equals("java/lang/String") && !type.equals("java/lang/Boolean")) { if (!this.isBinaryExp && !isOperator) - getValueOfIns(type); + doBoxing(type); } - + } - private void getValueOfIns(String type) { + // Boxing: prim -> RefType + private void doBoxing(String type) { switch (type) { case "java/lang/String": mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", @@ -943,7 +938,7 @@ public class BytecodeGenMethod implements StatementVisitor { private void visitCharLiteral(Character value) { mv.visitIntInsn(Opcodes.BIPUSH, (int) value); - + } private void visitDoubleLiteral(Double value) { @@ -1019,6 +1014,7 @@ public class BytecodeGenMethod implements StatementVisitor { for (Expression al : argumentList.getArguments()) { statement = new ArgumentExpr(al); al.accept(this); + statement = null; } } @@ -1042,12 +1038,12 @@ public class BytecodeGenMethod implements StatementVisitor { varsFunInterface.add(assignLeftSide.localVar.getType()); int index = paramsAndLocals.size(); String var = assignLeftSide.localVar.name; - if(!paramsAndLocals.containsKey(var)) { + if (!paramsAndLocals.containsKey(var)) { paramsAndLocals.put(var, index + 1); - }else { + } else { paramsAndLocals.put(var, index); } - + mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.size()); // Debug::: diff --git a/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java b/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java index cba540f8..0e97ca4c 100644 --- a/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java +++ b/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java @@ -46,12 +46,18 @@ public class DescriptorToString implements DescriptorVisitor{ }else if(method.getGenericsAndBounds().containsKey(fpDesc)){ desc += "L"+method.getGenericsAndBounds().get(fpDesc)+ ";"; }else { - 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()); + if(resType.subSequence(0, 4).equals("TPH ")) { + desc += "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";"; + } else { + desc += "L"+resType+ ";"; + } } } //TODO: generate a class java%% ... %% else if(resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()).contains("<")){ - desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "%").replace("<", "%%").replace(">", "%%")+ ";"; + desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "$$").replace("<", "$$$").replace(">", "$$$")+ ";"; } else { desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; @@ -68,7 +74,12 @@ public class DescriptorToString implements DescriptorVisitor{ }else if(method.getGenericsAndBounds().containsKey(ret)){ desc += ")L"+method.getGenericsAndBounds().get(ret)+ ";"; }else { - desc += ")" + "L"+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 ")) { + desc += ")" + "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";"; + } else { + desc += ")" + "L"+resType+ ";"; + } } }else { desc += ")" + "L"+resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; diff --git a/src/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java b/src/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java index e374bb93..e5c853b3 100644 --- a/src/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java +++ b/src/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java @@ -13,6 +13,8 @@ public class TypeToDescriptor implements TypeVisitor{ @Override public String visit(RefType refType) { return refType.getName().toString().replace(".", "/"); +// String t = refType.getName().toString().replace(".", "/"); +// return t.equals("Fun1")?(t+"$$"):t; } @Override @@ -27,7 +29,8 @@ public class TypeToDescriptor implements TypeVisitor{ @Override public String visit(ExtendsWildcardType extendsWildcardType) { - throw new NotImplementedException(); + return extendsWildcardType.getInnerType().toString(); + //throw new NotImplementedException(); } @Override diff --git a/src/de/dhbwstuttgart/bytecode/signature/Signature.java b/src/de/dhbwstuttgart/bytecode/signature/Signature.java index 8c2cc1d3..48804661 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/Signature.java +++ b/src/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -59,7 +59,7 @@ public class Signature { private void createSignatureForFunN(LambdaExpression lambdaExpression, int numberOfParams) { - sw.visitClassBound().visitEnd(); +// sw.visitClassBound().visitEnd(); for(int i = 0;i 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)+"$"; + sw.visitFormalTypeParameter(g); + sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); + genericsAndBoundsMethod.put(g, Type.getInternalName(Object.class)); + sw.visitClassBound().visitEnd(); + } + + for(String paramName : methodParamsAndTypes.keySet()) { + RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName); + String pT = t.acceptTV(new TypeToSignature()); + // S.o + if(pT.substring(0,4).equals("TPH ") && !genericsAndBoundsMethod.containsKey(pT)) { + String gP = pT.substring(4)+"$"; + sw.visitFormalTypeParameter(gP); + sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); + genericsAndBoundsMethod.put(gP, Type.getInternalName(Object.class)); + sw.visitClassBound().visitEnd(); + } + } + + // visit each method-parameter to create the signature for(String paramName : methodParamsAndTypes.keySet()) { RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName); // parameter type deswegen ist true @@ -101,6 +125,15 @@ public class Signature { if(isConstructor) { sw.visitReturnType().visitBaseType('V'); }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(); // return type deswegen ist false doVisitParamsOrReturn(returnType, false); @@ -132,10 +165,16 @@ public class Signature { break; case "TPH": RefTypeOrTPHOrWildcardOrGeneric r = resultSet.resolveType(t).resolvedType; - if(!r.acceptTV(new TypeToSignature()).substring(0, 4).equals("TPH ")) - sv.visitInterface().visitClassType(r.acceptTV(new TypeToSignature())); -// sv.visitClassType(r.acceptTV(new TypeToSignature())); - System.out.println(r.getClass()+" Signature TPH: "+r.acceptTV(new TypeToSignature())); + // 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 ")) { +// sv.visitInterface().visitClassType(r.acceptTV(new TypeToSignature())); + sv.visitClassType(r.acceptTV(new TypeToSignature())); + } else { + System.out.println(r.getClass()+" Signature TPH: "+r.acceptTV(new TypeToSignature())); + sv.visitTypeVariable(r.acceptTV(new TypeToSignature()).substring(4)+"$"); + } break; default: if(!isParameterType) diff --git a/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java b/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java index 78b2fb22..a1357d4c 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java +++ b/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java @@ -27,6 +27,8 @@ public class TypeToSignature implements TypeVisitor { } params += ";>"; } +// String t = refType.getName().toString().replace(".", "/"); +// return t.equals("Fun1")?t+"$$"+params+";":t+params+";"; return refType.getName().toString().replace(".", "/") + params+";"; } diff --git a/test/bytecode/BinaryTest.java b/test/bytecode/BinaryTest.java new file mode 100644 index 00000000..7f2f5fa4 --- /dev/null +++ b/test/bytecode/BinaryTest.java @@ -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 BinaryTest { + 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/BinaryInMeth.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("BinaryInMeth"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() { + fail("Not yet implemented"); + } + +} diff --git a/test/bytecode/FacTest.java b/test/bytecode/FacTest.java new file mode 100644 index 00000000..b2840026 --- /dev/null +++ b/test/bytecode/FacTest.java @@ -0,0 +1,44 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class FacTest { + 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/Fac.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("Fac"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method getFac = classToTest.getDeclaredMethod("getFac", Integer.class,Integer.class); + Integer result = (Integer) getFac.invoke(instanceOfClass,3); + assertEquals(result, 6); + } + +} diff --git a/test/bytecode/PlusTest.java b/test/bytecode/PlusTest.java index 016cb706..51503c58 100644 --- a/test/bytecode/PlusTest.java +++ b/test/bytecode/PlusTest.java @@ -29,7 +29,7 @@ public class PlusTest { compiler = new JavaTXCompiler(fileToTest); compiler.generateBytecode(); - pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/examples/"; + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); classToTest = loader.loadClass("Plus"); instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); diff --git a/test/bytecode/RelOpsTest.java b/test/bytecode/RelOpsTest.java new file mode 100644 index 00000000..06b24630 --- /dev/null +++ b/test/bytecode/RelOpsTest.java @@ -0,0 +1,44 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class RelOpsTest { + 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/RelOps.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("RelOps"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", Integer.class,Integer.class); + Boolean result = (Boolean) m.invoke(instanceOfClass, 7,3); + assertFalse(result); + } + +} diff --git a/test/bytecode/javFiles/BinaryInMeth.jav b/test/bytecode/javFiles/BinaryInMeth.jav new file mode 100644 index 00000000..f5a11798 --- /dev/null +++ b/test/bytecode/javFiles/BinaryInMeth.jav @@ -0,0 +1,11 @@ +import java.lang.Integer; +public class BinaryInMeth { + + m(a){ + return ++a; + } + + m2(a,b){ + return m(a+b); + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/Fac.jav b/test/bytecode/javFiles/Fac.jav new file mode 100644 index 00000000..d3d1a8d9 --- /dev/null +++ b/test/bytecode/javFiles/Fac.jav @@ -0,0 +1,16 @@ +import java.lang.Integer; +import java.lang.Long; +import java.lang.Double; + +public class Fac { + + getFac(n){ + var res = 1; + var i = 1; + while(i<=n) { + res = res * i; + i++; + } + return res; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/Gen.jav b/test/bytecode/javFiles/Gen.jav index 5d579eb8..3b58b188 100644 --- a/test/bytecode/javFiles/Gen.jav +++ b/test/bytecode/javFiles/Gen.jav @@ -2,7 +2,7 @@ import java.lang.Integer; import java.util.Vector; public class Gen{ - Vector m(Vector v){ + Vector m(Vector v){ return v; } } diff --git a/test/bytecode/javFiles/Matrix.jav b/test/bytecode/javFiles/Matrix.jav index 8120a7c5..80f41b16 100644 --- a/test/bytecode/javFiles/Matrix.jav +++ b/test/bytecode/javFiles/Matrix.jav @@ -7,19 +7,19 @@ class Matrix extends Vector> { 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); +// 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++; } return ret; diff --git a/test/bytecode/javFiles/Op.jav b/test/bytecode/javFiles/Op.jav index c01e7e6e..082f48d8 100644 --- a/test/bytecode/javFiles/Op.jav +++ b/test/bytecode/javFiles/Op.jav @@ -9,7 +9,7 @@ import java.lang.Byte; public class Op { - Integer m(Integer a, Integer b) { + m(a, b) { //var c = a+b; return a+b; } diff --git a/test/bytecode/javFiles/Plus.jav b/test/bytecode/javFiles/Plus.jav index 4d425bf0..86b4eb36 100644 --- a/test/bytecode/javFiles/Plus.jav +++ b/test/bytecode/javFiles/Plus.jav @@ -1,4 +1,4 @@ -import java.lang.Integer; +//import java.lang.Integer; public class Plus { diff --git a/test/bytecode/javFiles/RelOps.jav b/test/bytecode/javFiles/RelOps.jav new file mode 100644 index 00000000..d75ee2f3 --- /dev/null +++ b/test/bytecode/javFiles/RelOps.jav @@ -0,0 +1,7 @@ +import java.lang.Integer; + +public class RelOps { + m(a,b){ + return a Deswegen kann +// nicht auf den Stack geladen. +//import java.lang.Long; public class While { m(x) { diff --git a/test/logFiles/log b/test/logFiles/log new file mode 100644 index 00000000..5d17ab28 --- /dev/null +++ b/test/logFiles/log @@ -0,0 +1,107 @@ +FC:\{java.lang.Number=Elem: Node(java.lang.Number) +Prec: [java.lang.Object, java.io.Serializable] +Desc: [java.lang.Integer] + +, java.lang.Comparable=Elem: Node(java.lang.Comparable) +Prec: [] +Desc: [java.lang.Integer] + +, java.lang.Comparable=Elem: Node(java.lang.Comparable) +Prec: [java.lang.Object] +Desc: [] + +, java.lang.Integer=Elem: Node(java.lang.Integer) +Prec: [java.lang.Number, java.lang.Object, java.lang.Comparable, java.io.Serializable] +Desc: [] + +, java.lang.Iterable=Elem: Node(java.lang.Iterable) +Prec: [java.lang.Object] +Desc: [] + +, java.lang.Iterable=Elem: Node(java.lang.Iterable) +Prec: [java.lang.Object] +Desc: [] + +, java.util.Collection=Elem: Node(java.util.Collection) +Prec: [] +Desc: [java.util.AbstractList, java.util.Vector, java.util.List, java.util.AbstractCollection] + +, java.util.AbstractCollection=Elem: Node(java.util.AbstractCollection) +Prec: [java.lang.Object, java.util.Collection] +Desc: [java.util.AbstractList, java.util.Vector] + +, java.util.AbstractList=Elem: Node(java.util.AbstractList) +Prec: [java.lang.Object, java.util.Collection, java.util.AbstractCollection, java.util.List] +Desc: [java.util.Vector] + +, java.lang.Cloneable=Elem: Node(java.lang.Cloneable) +Prec: [java.lang.Object] +Desc: [java.util.Vector] + +, java.lang.Comparable=Elem: Node(java.lang.Comparable) +Prec: [java.lang.Object] +Desc: [] + +, java.lang.Object=Elem: Node(java.lang.Object) +Prec: [java.lang.Object] +Desc: [java.lang.Number, java.lang.Comparable, java.lang.Integer, java.lang.Iterable, java.lang.Iterable, java.util.AbstractCollection, java.util.AbstractList, java.lang.Cloneable, java.lang.Comparable, Gen, java.lang.Object, java.util.Vector, java.util.Collection, java.util.RandomAccess, java.util.Collection, java.util.List, java.io.Serializable, java.lang.Iterable, java.util.Collection] + +, java.util.Vector=Elem: Node(java.util.Vector) +Prec: [java.util.AbstractList, java.lang.Cloneable, java.lang.Object, java.util.Collection, java.util.RandomAccess, java.io.Serializable, java.util.AbstractCollection, java.util.List] +Desc: [] + +, Gen=Elem: Node(Gen) +Prec: [java.lang.Object] +Desc: [] + +, java.util.Collection=Elem: Node(java.util.Collection) +Prec: [java.lang.Object, java.lang.Iterable] +Desc: [] + +, java.util.RandomAccess=Elem: Node(java.util.RandomAccess) +Prec: [java.lang.Object] +Desc: [java.util.Vector] + +, java.util.List=Elem: Node(java.util.List) +Prec: [java.lang.Object, java.util.Collection] +Desc: [] + +, java.util.Collection=Elem: Node(java.util.Collection) +Prec: [java.lang.Object, java.lang.Iterable] +Desc: [] + +, java.io.Serializable=Elem: Node(java.io.Serializable) +Prec: [java.lang.Object] +Desc: [java.lang.Number, java.util.Vector, java.lang.Integer] + +, java.lang.Iterable=Elem: Node(java.lang.Iterable) +Prec: [java.lang.Object] +Desc: [] + +, java.lang.Iterable=Elem: Node(java.lang.Iterable) +Prec: [] +Desc: [java.util.Collection, java.util.Collection, java.util.Collection] + +, java.util.Collection=Elem: Node(java.util.Collection) +Prec: [java.lang.Object, java.lang.Iterable] +Desc: [] + +, java.util.List=Elem: Node(java.util.List) +Prec: [] +Desc: [java.util.AbstractList, java.util.Vector] + +} +class Gen { + + java.util.Vector m(java.util.Vector v)({ + return (v)::java.util.Vector; + })::TPH K + + Gen()({ + super(()); + })::TPH N + +}Unifikation: [(java.util.Vector <. java.util.Vector, )] +Unifikation: [] +[] +RES: []