diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java index 6f7acd64..f1994c20 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.bytecode; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -8,6 +9,9 @@ import org.objectweb.asm.ClassWriter; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.signature.SignatureVisitor; +import org.objectweb.asm.signature.SignatureWriter; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.syntaxtree.*; @@ -16,6 +20,7 @@ import de.dhbwstuttgart.syntaxtree.statement.literal.Null; import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.result.ResultSet; @@ -23,7 +28,6 @@ import de.dhbwstuttgart.typeinference.result.ResultSet; public class BytecodeGen implements ASTVisitor { ClassWriter cw =new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS); -// String methDesc; String type; @@ -34,6 +38,12 @@ public class BytecodeGen implements ASTVisitor { // stores parameter, local vars and the next index on the local variable table, which use for aload_i, astore_i,... HashMap paramsAndLocals = new HashMap<>(); + // stores generics and their bounds of class + HashMap genericsAndBounds = new HashMap<>(); + // stores generics and their bounds of method + HashMap genericsAndBoundsMethod = new HashMap<>(); + + HashMap methodParamsAndTypes = new HashMap<>(); byte[] bytecode; HashMap classFiles; @@ -45,14 +55,19 @@ public class BytecodeGen implements ASTVisitor { @Override public void visit(SourceFile sourceFile) { for(ClassOrInterface cl : sourceFile.getClasses()) { - isInterface = (cl.getModifiers()&512)==512; - System.out.println("IS Interface = "+"modifiers= "+cl.getModifiers()+" ->"+(cl.getModifiers()&512) + isInterface); BytecodeGen classGen = new BytecodeGen(classFiles, resultSet); cl.accept(classGen); + System.out.println("In CLASS: "+(cl.getClassName().toString())); classGen.writeClass(cl.getClassName().toString()); } } - + + /** + * Associates the bytecode of the class that was build with the classWriter {@link #cw} + * with the class name in the map {@link #classFiles} + * + * @param name name of the class with which the the bytecode is to be associated + */ private void writeClass(String name) { bytecode = cw.toByteArray(); classFiles.put(name, bytecode); @@ -62,12 +77,30 @@ public class BytecodeGen implements ASTVisitor { public HashMap getClassFiles() { return classFiles; } + + @Override public void visit(ClassOrInterface classOrInterface) { className = classOrInterface.getClassName().toString(); - // access flages?? - cw.visit(Opcodes.V1_8, classOrInterface.getModifiers()+Opcodes.ACC_SUPER, classOrInterface.getClassName().toString() - , null, classOrInterface.getSuperClass().toString().replace(".", "/"), null); + + isInterface = (classOrInterface.getModifiers()&512)==512; + System.out.println("IS Interface = "+"modifiers= "+classOrInterface.getModifiers()+" ->"+(classOrInterface.getModifiers()&512) + isInterface); + + int acc = isInterface?classOrInterface.getModifiers()+Opcodes.ACC_ABSTRACT:classOrInterface.getModifiers()+Opcodes.ACC_SUPER; + String sig = null; + /* if class has generics then creates signature + * Signature looks like: + * Superclass + */ + if(classOrInterface.getGenerics().iterator().hasNext()) { + Signature signature = new Signature(classOrInterface, genericsAndBounds); + + System.out.println(signature.toString()); + sig = signature.toString(); + } + // needs implemented Interfaces? + cw.visit(Opcodes.V1_8, acc, classOrInterface.getClassName().toString() + , sig, classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()), null); // for each field in the class for(Field f : classOrInterface.getFieldDecl()) { @@ -85,16 +118,34 @@ public class BytecodeGen implements ASTVisitor { } cw.visitSource(classOrInterface.getClassName().toString()+".jav", null); } - + @Override public void visit(Constructor field) { - Descriptor desc = new Descriptor(field, resultSet); - MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", desc.getDesc(), null, null); + field.getParameterList().accept(this); + + String desc = null; + boolean hasGen = false; + for(String paramName : methodParamsAndTypes.keySet()) { + genericsAndBounds.containsKey(paramName); + hasGen = true; + } + String sig = null; + if(hasGen) { + System.out.println("IM IN CONST HAS Gens"); + Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes); + sig = signature.toString(); + System.out.println(sig); + } + NormalConstructor constructor = new NormalConstructor(field,genericsAndBounds,hasGen); + desc = constructor.accept(new DescriptorToString(resultSet)); + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", desc, sig, null); mv.visitCode(); System.out.println("-----Constructor-----"); - BytecodeGenMethod gen = new BytecodeGenMethod(className,resultSet,field, mv,paramsAndLocals,desc.getDesc(),cw,isInterface); - - mv.visitInsn(Opcodes.RETURN); + BytecodeGenMethod gen = new BytecodeGenMethod(className,resultSet,field, mv,paramsAndLocals,cw, + genericsAndBoundsMethod,genericsAndBounds,isInterface); + if(!field.getParameterList().iterator().hasNext()) { + mv.visitInsn(Opcodes.RETURN); + } mv.visitMaxs(0, 0); mv.visitEnd(); } @@ -104,12 +155,49 @@ public class BytecodeGen implements ASTVisitor { // TODO: check if the method is static => if static then the first param will be stored in pos 0 // else it will be stored in pos 1 and this will be stored in pos 0 method.getParameterList().accept(this); - Descriptor methDesc = new Descriptor(method,resultSet); + + String methDesc = null; + + // Method getModifiers() ? + int acc = isInterface?Opcodes.ACC_ABSTRACT:0; + System.out.println("-----Method-----"); - MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, method.getName(), methDesc.getDesc(), null, null); + + boolean hasGenInParameterList = genericsAndBounds.containsKey(method.getReturnType().acceptTV(new TypeToDescriptor())); + if(!hasGenInParameterList) { + for(String paramName : methodParamsAndTypes.keySet()) { + if(genericsAndBounds.containsKey(paramName)) { + hasGenInParameterList = true; + break; + } + } + } + String sig = null; + boolean hasGen = method.getGenerics().iterator().hasNext() || hasGenInParameterList; + // Wenn ReturnType has Generics?? Fun1<...> wie testet man das generic hat?? + System.out.println(method.getReturnType().acceptTV(new TypeToString())); +// if(method.getReturnType().acceptTV(new TypeToString()).equals("TPH")) { +// Signature signature = new Signature(method, genericsAndBoundsMethod, methodParamsAndTypes,resultSet); +// sig = signature.toString(); +// System.out.println(sig); +// } + /* if method has generics, create signature */ + if(hasGen) { + // resultset hier zum testen + Signature signature = new Signature(method, genericsAndBoundsMethod, methodParamsAndTypes,resultSet); + sig = signature.toString(); + System.out.println(sig); + + } + + NormalMethod meth = new NormalMethod(method,genericsAndBounds,genericsAndBoundsMethod,hasGen); + methDesc = meth.accept(new DescriptorToString(resultSet)); + System.out.println("methDesc" + methDesc); + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC+acc, method.getName(), methDesc, sig, null); + mv.visitCode(); - BytecodeGenMethod gen = new BytecodeGenMethod(className,resultSet,method, mv,paramsAndLocals,methDesc.getDesc(),cw,isInterface); + BytecodeGenMethod gen = new BytecodeGenMethod(className,resultSet,method, mv,paramsAndLocals,cw,genericsAndBounds,genericsAndBounds,isInterface); mv.visitMaxs(0, 0); mv.visitEnd(); } @@ -117,11 +205,13 @@ public class BytecodeGen implements ASTVisitor { @Override public void visit(ParameterList formalParameters) { paramsAndLocals = new HashMap<>(); + methodParamsAndTypes = new HashMap<>(); Iterator itr = formalParameters.iterator(); int i = 1; while(itr.hasNext()) { FormalParameter fp = itr.next(); paramsAndLocals.put(fp.getName(), i); + methodParamsAndTypes.put(fp.getName(), fp.getType()); fp.accept(this); i++; } diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index c2acaba0..5368cf93 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -21,6 +21,7 @@ import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.statement.literal.Literal; import de.dhbwstuttgart.syntaxtree.statement.literal.Null; +import de.dhbwstuttgart.syntaxtree.type.FunN; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.typeinference.result.ResultSet; @@ -29,12 +30,13 @@ public class BytecodeGenMethod implements StatementVisitor{ private Method m; private MethodVisitor mv; private HashMap paramsAndLocals = new HashMap<>(); - private String desc; private String className; private int lamCounter; private ClassWriter cw; private ResultSet resultSet; private boolean isInterface; + HashMap genericsAndBoundsMethod; + private HashMap genericsAndBounds; //for tests ** private String fieldName; @@ -46,8 +48,9 @@ public class BytecodeGenMethod implements StatementVisitor{ private ArrayList varsFunInterface; - public BytecodeGenMethod(String className,ResultSet resultSet, Method m, MethodVisitor mv, HashMap paramsAndLocals, - String desc, ClassWriter cw, boolean isInterface) { + public BytecodeGenMethod(String className,ResultSet resultSet, Method m, MethodVisitor mv, + HashMap paramsAndLocals, ClassWriter cw, + HashMap genericsAndBoundsMethod, HashMap genericsAndBounds, boolean isInterface) { this.where = "<<<<<< NORMAL METHOD >>>>>>"; @@ -56,29 +59,32 @@ public class BytecodeGenMethod implements StatementVisitor{ this.m = m; this.mv = mv; this.paramsAndLocals = paramsAndLocals; - this.desc = desc; this.cw = cw; + this.genericsAndBoundsMethod = genericsAndBoundsMethod; + this.genericsAndBounds = genericsAndBounds; this.isInterface = isInterface; this.lamCounter = -1; this.varsFunInterface = new ArrayList<>(); System.out.println("PARAMS = "+this.paramsAndLocals.size()); - this.m.block.accept(this); - System.out.println("PARAMS = "+this.paramsAndLocals.size()); - for(int i = 0; i(); @@ -94,7 +100,8 @@ public class BytecodeGenMethod implements StatementVisitor{ } private String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { - return resultSet.resolveType(type).resolvedType.toString().replace(".", "/"); +// return resultSet.resolveType(type).resolvedType.toString().replace(".", "/"); + return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor()); } @@ -113,7 +120,7 @@ public class BytecodeGenMethod implements StatementVisitor{ superCall.receiver.accept(this); superCall.arglist.accept(this); // mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", superCall.name, desc,false); - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), superCall.name, desc,isInterface); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), superCall.name, "()V",isInterface); } // ?? @@ -150,9 +157,6 @@ public class BytecodeGenMethod implements StatementVisitor{ assign.rightSide.accept(this); assign.lefSide.accept(this); } - - - } @Override @@ -164,7 +168,11 @@ public class BytecodeGenMethod implements StatementVisitor{ public void visit(LambdaExpression lambdaExpression) { System.out.println("\n++ In Lambda: "); this.lamCounter++; - Descriptor lamDesc = new Descriptor(lambdaExpression, resultSet); + + System.out.println("Lam Hs Gens: " + lambdaExpression.getGenerics().iterator().hasNext()); + System.out.println("Lam Hs Gens: " + lambdaExpression.getReturnType().acceptTV(new TypeToString())); + Lambda lam = new Lambda(lambdaExpression); + String lamDesc = lam.accept(new DescriptorToString(resultSet)); //Call site, which, when invoked, returns an instance of the functional interface to which //the lambda is being converted MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, @@ -174,10 +182,12 @@ public class BytecodeGenMethod implements StatementVisitor{ Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", mt.toMethodDescriptorString(), false); String methodName = "lambda$new$" + this.lamCounter; +// String typeErasure = "(Ljava/lang/Object;)Ljava/lang/Object;"; // Type erasure - Type arg1 = Type.getMethodType(lamDesc.getDesc()); +// Type arg1 = Type.getMethodType(typeErasure); + Type arg1 = Type.getMethodType(lamDesc); // real Type - Type arg3 = Type.getMethodType(lamDesc.getDesc()); + Type arg3 = Type.getMethodType(lamDesc); int staticOrSpecial=0; int staticOrInstance=0; @@ -197,16 +207,16 @@ public class BytecodeGenMethod implements StatementVisitor{ Handle arg2 = new Handle(staticOrSpecial, this.className, methodName, arg3.toString(),false); // Descriptor of functional interface methode - Descriptor fiMethodDesc = new Descriptor(kindOfLambda.getArgumentList(), lambdaExpression.getType(),resultSet); - + SamMethod samMethod = new SamMethod(kindOfLambda.getArgumentList(), lambdaExpression.getType()); // Desc: (this/nothing)TargetType - mv.visitInvokeDynamicInsn("apply", fiMethodDesc.getDesc(), bootstrap, + String fiMethodDesc = samMethod.accept(new DescriptorToString(resultSet)); + mv.visitInvokeDynamicInsn("apply", fiMethodDesc, bootstrap, arg1, arg2,arg3); - + MethodVisitor mvLambdaBody = cw.visitMethod(Opcodes.ACC_PRIVATE+ staticOrInstance + Opcodes.ACC_SYNTHETIC, methodName, arg3.toString(), null, null); - new BytecodeGenMethod(lambdaExpression,this.resultSet,mvLambdaBody,arg3.toString(),indexOfFirstParamLam,isInterface); + new BytecodeGenMethod(lambdaExpression,this.resultSet,mvLambdaBody,indexOfFirstParamLam,isInterface); mvLambdaBody.visitMaxs(0, 0); mvLambdaBody.visitEnd(); @@ -274,17 +284,20 @@ public class BytecodeGenMethod implements StatementVisitor{ methodCall.receiver.accept(this); methodCall.arglist.accept(this); - Descriptor mDesc = new Descriptor(methodCall.arglist, methodCall.getType(),resultSet); + MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), + genericsAndBoundsMethod,genericsAndBounds); + String mDesc = method.accept(new DescriptorToString(resultSet)); System.out.println("is Vars empty: "+varsFunInterface.isEmpty()); // is methodCall.receiver functional Interface)? if(varsFunInterface.contains(methodCall.receiver.getType())) { mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()), - methodCall.name, mDesc.getDesc(), false); + methodCall.name, mDesc, false); }else { + System.out.println("mDesc = " + mDesc); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, getResolvedType(methodCall.receiver.getType()), - methodCall.name, mDesc.getDesc(), isInterface); + methodCall.name, mDesc, isInterface); } // test // if(!methodCall.getType().toString().equals("V")) { @@ -303,7 +316,7 @@ public class BytecodeGenMethod implements StatementVisitor{ methodCall.arglist.accept(this); String d = "("; for(Expression e : methodCall.arglist.getArguments()) { - d = d + "L"+e.getType().toString().replace(".", "/") + ";"; + d = d + "L"+getResolvedType(e.getType()) + ";"; } d += ")V"; @@ -339,7 +352,7 @@ public class BytecodeGenMethod implements StatementVisitor{ System.out.println("In StaticClassName: "); // mv.visitMethodInsn(Opcodes.INVOKESTATIC, staticClassName.getType().toString().replace(".", "/"), // staticClassName.toString(), staticClassName.getType().toString(), false); - mv.visitFieldInsn(Opcodes.GETSTATIC, staticClassName.getType().toString().replace(".", "/"), + mv.visitFieldInsn(Opcodes.GETSTATIC, getResolvedType(staticClassName.getType()), fieldName, fieldDesc); } @@ -379,7 +392,7 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(Literal literal) { // value? - mv.visitLdcInsn(literal.getType().toString()); + mv.visitLdcInsn(getResolvedType(literal.getType())); } @Override @@ -393,14 +406,16 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(AssignToField assignLeftSide) { +// temporäre Lösung für testen, bis ich weiss wie man funktionale +// interfaces erkennt if(isRightSideALambda) varsFunInterface.add(assignLeftSide.field.getType()); // Loads the an object reference from the local variable // array slot onto the top of the operand stack. assignLeftSide.field.receiver.accept(this); this.rightSideTemp.accept(this); - mv.visitFieldInsn(Opcodes.PUTFIELD, assignLeftSide.field.receiver.getType().toString(), - assignLeftSide.field.fieldVarName, assignLeftSide.field.getType().toString()); + mv.visitFieldInsn(Opcodes.PUTFIELD, getResolvedType(assignLeftSide.field.receiver.getType()), + assignLeftSide.field.fieldVarName, getResolvedType(assignLeftSide.field.getType())); } @Override diff --git a/src/de/dhbwstuttgart/bytecode/Descriptor.java b/src/de/dhbwstuttgart/bytecode/Descriptor.java deleted file mode 100644 index 3b024d71..00000000 --- a/src/de/dhbwstuttgart/bytecode/Descriptor.java +++ /dev/null @@ -1,112 +0,0 @@ -package de.dhbwstuttgart.bytecode; - -import java.util.List; -import java.util.Iterator; - -import de.dhbwstuttgart.exceptions.NotImplementedException; -import de.dhbwstuttgart.syntaxtree.Constructor; -import de.dhbwstuttgart.syntaxtree.FormalParameter; -import de.dhbwstuttgart.syntaxtree.Method; -import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; -import de.dhbwstuttgart.syntaxtree.statement.Expression; -import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; -import de.dhbwstuttgart.syntaxtree.type.*; -import de.dhbwstuttgart.typeinference.result.ResultSet; - -public class Descriptor { - String desc; - - public Descriptor(Method method, ResultSet resultSet) { - desc = "("; - Iterator itr = method.getParameterList().iterator(); - while(itr.hasNext()) { - FormalParameter fp = itr.next(); - desc = desc + "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; - } - desc = addReturnType(desc,method.getReturnType(), resultSet); - - - } - - private class TypeToDescriptor implements TypeVisitor{ - - @Override - public String visit(RefType refType) { - return refType.getName().toString().replace(".", "/"); - } - - @Override - public String visit(SuperWildcardType superWildcardType) { - throw new NotImplementedException(); - } - - @Override - public String visit(TypePlaceholder typePlaceholder) { - return typePlaceholder.toString(); - } - - @Override - public String visit(ExtendsWildcardType extendsWildcardType) { - throw new NotImplementedException(); - } - - @Override - public String visit(GenericRefType genericRefType) { - return genericRefType.getParsedName(); - } - } - - private String addReturnType(String desc2, RefTypeOrTPHOrWildcardOrGeneric returnType, ResultSet resultSet) { - System.out.println("DescType = "+returnType.toString()); - if(resultSet.resolveType(returnType).resolvedType.toString().equals("void")){ - desc = desc + ")V"; - }else { - desc = desc + ")" + "L"+resultSet.resolveType(returnType).resolvedType.toString().replace(".", "/")+";"; - } - return desc; - } - - public Descriptor(Constructor constructor, ResultSet resultSet) { - desc = "("; - Iterator itr = constructor.getParameterList().iterator(); - while(itr.hasNext()) { - FormalParameter fp = itr.next(); - desc = desc + "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "/") + ";"; - } - desc = desc + ")V"; - } - - public Descriptor(LambdaExpression lambdaExpr, ResultSet resultSet) { - desc = "("; - Iterator itr = lambdaExpr.params.iterator(); - while(itr.hasNext()) { - FormalParameter fp = itr.next(); - desc = desc + "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "/") + ";"; - } - desc = addReturnType(desc, lambdaExpr.getReturnType(), resultSet); - } - - public Descriptor(ArgumentList argList, RefTypeOrTPHOrWildcardOrGeneric returnType, ResultSet resultSet) { - desc = "("; - for(Expression e : argList.getArguments()) { - desc = desc + "L"+resultSet.resolveType(e.getType()).resolvedType.toString().replace(".", "/") + ";"; - } - desc = addReturnType(desc, returnType, resultSet); - - } - - public Descriptor(List argumentList,RefTypeOrTPHOrWildcardOrGeneric returnType ,ResultSet resultSet) { - desc = "("; - Iterator itr = argumentList.iterator(); - while(itr.hasNext()) { - RefTypeOrTPHOrWildcardOrGeneric rt = itr.next(); - desc = desc + "L"+resultSet.resolveType(rt).resolvedType.toString().replace(".", "/")+";"; - } - desc = desc + ")"+"L"+resultSet.resolveType(returnType).resolvedType.toString().replace(".", "/")+";"; - } - - public String getDesc() { - return this.desc; - } - -} diff --git a/src/de/dhbwstuttgart/bytecode/DescriptorToString.java b/src/de/dhbwstuttgart/bytecode/DescriptorToString.java new file mode 100644 index 00000000..481dbc5d --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/DescriptorToString.java @@ -0,0 +1,146 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.Iterator; + +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +public class DescriptorToString implements DescriptorVisitor{ + ResultSet resultSet; + + public DescriptorToString(ResultSet resultSet) { + this.resultSet = resultSet; + } + + private String addReturnType(String desc, RefTypeOrTPHOrWildcardOrGeneric returnType, ResultSet resultSet) { + if(resultSet.resolveType(returnType).resolvedType.toString().equals("void")){ + desc = desc + ")V"; + }else { + desc = desc + ")" + "L"+resultSet.resolveType(returnType).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + return desc; + } + + @Override + public String visit(NormalMethod method) { + + String desc = "("; + Iterator itr = method.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + if(method.hasGen()) { + String fpDesc = fp.getType().acceptTV(new TypeToDescriptor()); + if(method.getGenericsAndBoundsMethod().containsKey(fpDesc)) { + desc += "L"+method.getGenericsAndBoundsMethod().get(fpDesc)+ ";"; + }else if(method.getGenericsAndBounds().containsKey(fpDesc)){ + desc += "L"+method.getGenericsAndBounds().get(fpDesc)+ ";"; + }else { + desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + }else { + desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + } + + if(resultSet.resolveType(method.getReturnType()).resolvedType.toString().equals("void")) { + desc += ")V"; + }else { + if(method.hasGen()) { + String ret = method.getReturnType().acceptTV(new TypeToDescriptor()); + if(method.getGenericsAndBoundsMethod().containsKey(ret)) { + desc += ")L"+method.getGenericsAndBoundsMethod().get(ret)+ ";"; + }else if(method.getGenericsAndBounds().containsKey(ret)){ + desc += ")L"+method.getGenericsAndBounds().get(ret)+ ";"; + }else { + desc += ")" + "L"+resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + }else { + desc += ")" + "L"+resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + } +// desc = addReturnType(desc,method.getReturnType(), resultSet); + return desc; + } + + @Override + public String visit(NormalConstructor constructor) { + String desc = "("; + Iterator itr = constructor.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + if(constructor.hasGen()) { + System.out.println("Cons has Gens"); + String fpDesc = fp.getType().acceptTV(new TypeToDescriptor()); + System.out.println(fpDesc); + if(constructor.getGenericsAndBounds().containsKey(fpDesc)){ + desc += "L"+constructor.getGenericsAndBounds().get(fpDesc)+ ";"; + }else { + desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + }else { + System.out.println("Cons has NOT Gens"); + desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + } + desc = desc + ")V"; + return desc; + } + + @Override + public String visit(Lambda lambdaExpression) { + String desc = "("; + Iterator itr = lambdaExpression.getParams().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + desc = desc + "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()) + ";"; + } + System.out.println("LamReturnType: "+lambdaExpression.getReturnType().acceptTV(new TypeToString())); + desc = addReturnType(desc, lambdaExpression.getReturnType(), resultSet); + return desc; + } + + @Override + public String visit(SamMethod samMethod) { + String desc = "("; + Iterator itr = samMethod.getArgumentList().iterator(); + while(itr.hasNext()) { + RefTypeOrTPHOrWildcardOrGeneric rt = itr.next(); + desc = desc + "L"+resultSet.resolveType(rt).resolvedType.acceptTV(new TypeToDescriptor())+";"; + } + desc = desc + ")"+"L"+resultSet.resolveType(samMethod.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+";"; + return desc; + } + + @Override + public String visit(MethodFromMethodCall methodFromMethodCall) { + String desc = "("; + for(Expression e : methodFromMethodCall.getArgList().getArguments()) { + String d = e.getType().acceptTV(new TypeToDescriptor()); + if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(d)) { + desc += "L"+methodFromMethodCall.getGenericsAndBoundsMethod().get(d)+ ";"; + }else if(methodFromMethodCall.getGenericsAndBounds().containsKey(d)) { + desc += "L"+methodFromMethodCall.getGenericsAndBounds().get(d)+ ";"; + }else { + desc += "L"+resultSet.resolveType(e.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + } + + if(resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.toString().equals("void")) { + desc += ")V"; + }else { + String ret = resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); + if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(ret)) { + desc += ")L"+methodFromMethodCall.getGenericsAndBoundsMethod().get(ret)+ ";"; + }else if(methodFromMethodCall.getGenericsAndBounds().containsKey(ret)){ + desc += ")L"+methodFromMethodCall.getGenericsAndBounds().get(ret)+ ";"; + }else { + desc += ")" + "L"+resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + } +// desc = addReturnType(desc, methodFromMethodCall.getReturnType(), resultSet); + return desc; + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/DescriptorVisitor.java b/src/de/dhbwstuttgart/bytecode/DescriptorVisitor.java new file mode 100644 index 00000000..63198828 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/DescriptorVisitor.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.bytecode; + +public interface DescriptorVisitor { + public String visit(NormalMethod method); + public String visit(NormalConstructor constructor); + public String visit(Lambda lambdaExpression); + public String visit(SamMethod samMethod); + public String visit(MethodFromMethodCall methodFromMethodCall); +} diff --git a/src/de/dhbwstuttgart/bytecode/Lambda.java b/src/de/dhbwstuttgart/bytecode/Lambda.java new file mode 100644 index 00000000..283b7393 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/Lambda.java @@ -0,0 +1,25 @@ +package de.dhbwstuttgart.bytecode; + +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class Lambda { + private LambdaExpression lambdaExpression; + + public Lambda(LambdaExpression lambdaExpression) { + this.lambdaExpression = lambdaExpression; + } + + public ParameterList getParams() { + return lambdaExpression.params; + } + + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return lambdaExpression.getReturnType(); + } + + public String accept(DescriptorVisitor descVisitor) { + return descVisitor.visit(this); + } +} diff --git a/src/de/dhbwstuttgart/bytecode/MethodFromMethodCall.java b/src/de/dhbwstuttgart/bytecode/MethodFromMethodCall.java new file mode 100644 index 00000000..330b0666 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/MethodFromMethodCall.java @@ -0,0 +1,41 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.HashMap; + +import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class MethodFromMethodCall { + private ArgumentList argList; + private RefTypeOrTPHOrWildcardOrGeneric returnType; + private HashMap genericsAndBoundsMethod; + private HashMap genericsAndBounds; + + public MethodFromMethodCall(ArgumentList argList,RefTypeOrTPHOrWildcardOrGeneric returnType, + HashMap genericsAndBoundsMethod,HashMap genericsAndBounds) { + this.argList = argList; + this.returnType = returnType; + this.genericsAndBoundsMethod = genericsAndBoundsMethod; + this.genericsAndBounds = genericsAndBounds; + } + + public ArgumentList getArgList() { + return argList; + } + + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return returnType; + } + + public HashMap getGenericsAndBoundsMethod(){ + return genericsAndBoundsMethod; + } + + public HashMap getGenericsAndBounds(){ + return genericsAndBounds; + } + + public String accept(DescriptorVisitor descVisitor) { + return descVisitor.visit(this); + } +} diff --git a/src/de/dhbwstuttgart/bytecode/NormalConstructor.java b/src/de/dhbwstuttgart/bytecode/NormalConstructor.java new file mode 100644 index 00000000..d2174fd4 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/NormalConstructor.java @@ -0,0 +1,39 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.HashMap; + +import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.ParameterList; + +public class NormalConstructor { + private Constructor constructor; + private HashMap genericsAndBounds; + private boolean hasGenerics; + + public NormalConstructor(Constructor constructor, boolean hasGenerics) { + this.constructor = constructor; + this.hasGenerics = hasGenerics; + } + + public NormalConstructor(Constructor constructor, HashMap genericsAndBounds, boolean hasGenerics) { + this.constructor = constructor; + this.genericsAndBounds = genericsAndBounds; + this.hasGenerics = hasGenerics; + } + + public HashMap getGenericsAndBounds() { + return genericsAndBounds; + } + + public boolean hasGen() { + return hasGenerics; + } + + public ParameterList getParameterList() { + return constructor.getParameterList(); + } + + public String accept(DescriptorVisitor descVisitor) { + return descVisitor.visit(this); + } +} diff --git a/src/de/dhbwstuttgart/bytecode/NormalMethod.java b/src/de/dhbwstuttgart/bytecode/NormalMethod.java new file mode 100644 index 00000000..3f6bf2b4 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/NormalMethod.java @@ -0,0 +1,55 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.HashMap; + +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class NormalMethod { + private Method method; + private HashMap genericsAndBounds; + private HashMap genericsAndBoundsMethod; + private boolean hasGenerics; + + public NormalMethod(Method method, boolean hasGenerics) { + this.method = method; + this.hasGenerics = hasGenerics; + } + + public NormalMethod(Method method, HashMap genericsAndBounds, + HashMap genericsAndBoundsMethod,boolean hasGenerics) { + this.method = method; + this.genericsAndBounds = genericsAndBounds; + this.genericsAndBoundsMethod = genericsAndBoundsMethod; + this.hasGenerics = hasGenerics; + } + + public Method getMethod() { + return method; + } + + public ParameterList getParameterList() { + return method.getParameterList(); + } + + public HashMap getGenericsAndBounds(){ + return genericsAndBounds; + } + + public HashMap getGenericsAndBoundsMethod(){ + return genericsAndBoundsMethod; + } + + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return method.getType(); + } + + public boolean hasGen() { + return this.hasGenerics; + } + + public String accept(DescriptorVisitor descVisitor) { + return descVisitor.visit(this); + } +} diff --git a/src/de/dhbwstuttgart/bytecode/SamMethod.java b/src/de/dhbwstuttgart/bytecode/SamMethod.java new file mode 100644 index 00000000..9cf039a2 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/SamMethod.java @@ -0,0 +1,31 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.List; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class SamMethod { + private List argumentList; + private RefTypeOrTPHOrWildcardOrGeneric returnType; + + public SamMethod(List argumentList, RefTypeOrTPHOrWildcardOrGeneric returnType) { + this.argumentList = argumentList; + this.returnType = returnType; + } + + public List getArgumentList() { + return argumentList; + } + + + + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return returnType; + } + + + + public String accept(DescriptorVisitor descVisitor) { + return descVisitor.visit(this); + } +} diff --git a/src/de/dhbwstuttgart/bytecode/Signature.java b/src/de/dhbwstuttgart/bytecode/Signature.java new file mode 100644 index 00000000..362429a3 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/Signature.java @@ -0,0 +1,155 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.HashMap; +import java.util.Iterator; + +import org.objectweb.asm.signature.SignatureVisitor; +import org.objectweb.asm.signature.SignatureWriter; + +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +public class Signature { + private ClassOrInterface classOrInterface; + private HashMap genericsAndBounds; + private HashMap genericsAndBoundsMethod; + private SignatureWriter sw; + private Constructor constructor; + private Method method; + private HashMap methodParamsAndTypes; + private ResultSet resultSet; + + public Signature(ClassOrInterface classOrInterface, HashMap genericsAndBounds) { + this.classOrInterface = classOrInterface; + this.genericsAndBounds = genericsAndBounds; + sw = new SignatureWriter(); + createSignatureForClassOrInterface(); + } + + public Signature(Constructor constructor, HashMap genericsAndBounds, HashMap methodParamsAndTypes) { + this.constructor = constructor; + this.genericsAndBounds = genericsAndBounds; + this.methodParamsAndTypes = methodParamsAndTypes; + sw = new SignatureWriter(); + createSignatureForConsOrMethod(this.constructor,true); + } + + public Signature(Method method, HashMap genericsAndBoundsMethod, + HashMap methodParamsAndTypes, ResultSet resultSet) { + this.method = method; + this.genericsAndBoundsMethod = genericsAndBoundsMethod; + this.methodParamsAndTypes = methodParamsAndTypes; + this.resultSet = resultSet; + sw = new SignatureWriter(); + createSignatureForConsOrMethod(this.method,false); + } + + /** + * Creates signature for a method or constructor with @see {@link SignatureWriter} + * Signature looks like: + * (params L.. OR T.. Or basistape)ReturnType + * + * @param method method or constructor + * @param isConstructor true if constructor + */ + private void createSignatureForConsOrMethod(Method method, boolean isConstructor) { + Iterator itr = method.getGenerics().iterator(); + // visits all formal type parameter and visits their bounds + while(itr.hasNext()) { + GenericTypeVar g = itr.next(); + getBoundsOfTypeVar(g,genericsAndBoundsMethod); + } + // visits each method-parameter to create the signature + for(String paramName : methodParamsAndTypes.keySet()) { + RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName); + // parameter type deswegen ist true + doVisitParamsOrReturn(t,true); + } + if(isConstructor) { + sw.visitReturnType().visitBaseType('V'); + }else { + RefTypeOrTPHOrWildcardOrGeneric returnType = method.getReturnType(); + // return type deswegen ist false + doVisitParamsOrReturn(returnType, false); + } +// sw.visitEnd(); + } + /** + * Visits parameter type or return type with {@link SignatureVisitor} to create + * the method signature + * @param t type of parameter or return type + * @param isParameterType true if t is type of parameter + */ + private void doVisitParamsOrReturn(RefTypeOrTPHOrWildcardOrGeneric t, boolean isParameterType) { + String type = t.acceptTV(new TypeToString()); + SignatureVisitor sv; + if(isParameterType) { + sv = sw.visitParameterType(); + } + else { + sv = sw.visitReturnType(); + } + switch (type) { + case "RT": + sv.visitClassType(t.acceptTV(new TypeToDescriptor())); + break; + case "GRT": + GenericRefType g = (GenericRefType) t; + sv.visitTypeVariable(g.getParsedName()); + break; + case "TPH": + System.out.println(resultSet.resolveType(t).resolvedType.acceptTV(new TypeToDescriptor())); +// sv.visitInterface().visitClassType(resultSet.resolveType(t).resolvedType.acceptTV(new TypeToDescriptor())+";"); + + break; + default: + if(!isParameterType) + sv.visitBaseType('V'); + break; + } + } + /** + * Creates signature for class or interface with {@link SignatureWriter} + * Signature looks like: + * superclass + */ + private void createSignatureForClassOrInterface() { + Iterator itr = classOrInterface.getGenerics().iterator(); + + while(itr.hasNext()) { + GenericTypeVar g = itr.next(); + getBoundsOfTypeVar(g,genericsAndBounds); + } + + sw.visitSuperclass().visitClassType(classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()));; + sw.visitEnd(); + } + /** + * Get bounds of type variable + * @param g type variable + * @param genAndBounds + */ + private void getBoundsOfTypeVar(GenericTypeVar g, HashMap genAndBounds) { + sw.visitFormalTypeParameter(g.getParsedName()); + + Iterator bItr = g.getBounds().iterator(); + while(bItr.hasNext()) { + RefTypeOrTPHOrWildcardOrGeneric b =bItr.next(); + String boundDesc = b.acceptTV(new TypeToDescriptor()); + // Ensure that <...> extends java.lang.Object OR ... + sw.visitClassBound().visitClassType(boundDesc); + genAndBounds.put(g.getParsedName(), boundDesc); + } + sw.visitClassBound().visitEnd(); + } + + public String toString() { + return sw.toString(); + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/TypeToDescriptor.java b/src/de/dhbwstuttgart/bytecode/TypeToDescriptor.java new file mode 100644 index 00000000..5271e63d --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/TypeToDescriptor.java @@ -0,0 +1,37 @@ +package de.dhbwstuttgart.bytecode; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.syntaxtree.type.TypeVisitor; + +public class TypeToDescriptor implements TypeVisitor{ + + @Override + public String visit(RefType refType) { + return refType.getName().toString().replace(".", "/"); + } + + @Override + public String visit(SuperWildcardType superWildcardType) { + throw new NotImplementedException(); + } + + @Override + public String visit(TypePlaceholder typePlaceholder) { + return typePlaceholder.toString().replace(".", "/"); + } + + @Override + public String visit(ExtendsWildcardType extendsWildcardType) { + throw new NotImplementedException(); + } + + @Override + public String visit(GenericRefType genericRefType) { + return genericRefType.getParsedName().replace(".", "/"); + } +} \ No newline at end of file diff --git a/src/de/dhbwstuttgart/bytecode/TypeToString.java b/src/de/dhbwstuttgart/bytecode/TypeToString.java new file mode 100644 index 00000000..86d4124a --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/TypeToString.java @@ -0,0 +1,38 @@ +package de.dhbwstuttgart.bytecode; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.syntaxtree.type.TypeVisitor; + +public class TypeToString implements TypeVisitor{ + + @Override + public String visit(RefType refType) { + return "RT"; + } + + @Override + public String visit(SuperWildcardType superWildcardType) { + throw new NotImplementedException(); + } + + @Override + public String visit(TypePlaceholder typePlaceholder) { + return "TPH"; + } + + @Override + public String visit(ExtendsWildcardType extendsWildcardType) { + throw new NotImplementedException(); + } + + @Override + public String visit(GenericRefType genericRefType) { + return "GRT"; + } + +} diff --git a/src/de/dhbwstuttgart/syntaxtree/type/RefType.java b/src/de/dhbwstuttgart/syntaxtree/type/RefType.java index 002e792d..4cf85297 100644 --- a/src/de/dhbwstuttgart/syntaxtree/type/RefType.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/RefType.java @@ -6,6 +6,7 @@ import de.dhbwstuttgart.typeinference.result.ResultSetVisitor; import org.antlr.v4.runtime.Token; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; @@ -28,7 +29,15 @@ public class RefType extends RefTypeOrTPHOrWildcardOrGeneric @Override public String toString(){ - return this.name.toString(); + String params = "<"; + Iterator it = parameter.iterator(); + while(it.hasNext()){ + RefTypeOrTPHOrWildcardOrGeneric param = it.next(); + params += param.toString(); + if(it.hasNext())params += ", "; + } + params += ">"; + return this.name.toString() + params; } @Override diff --git a/test/bytecode/Generics.jav b/test/bytecode/Generics.jav index 2c7a67b6..bb7b2af5 100644 --- a/test/bytecode/Generics.jav +++ b/test/bytecode/Generics.jav @@ -1,5 +1,7 @@ class Generics { + Generics(B b){ + } B mt1(B b){ return mt1(b); } diff --git a/test/bytecode/Generics2.jav b/test/bytecode/Generics2.jav new file mode 100644 index 00000000..52d5caa2 --- /dev/null +++ b/test/bytecode/Generics2.jav @@ -0,0 +1,6 @@ +class Generics2{ + B m1(B b){ + return b; + } + +} \ No newline at end of file diff --git a/test/bytecode/Generics2Test.java b/test/bytecode/Generics2Test.java new file mode 100644 index 00000000..26e52665 --- /dev/null +++ b/test/bytecode/Generics2Test.java @@ -0,0 +1,7 @@ +package bytecode; + +public class Generics2Test extends JavaTXCompilerTest{ + public Generics2Test() { + this.fileName = "Generics2"; + } +} diff --git a/test/bytecode/GenericsTest.java b/test/bytecode/GenericsTest.java new file mode 100644 index 00000000..cca16129 --- /dev/null +++ b/test/bytecode/GenericsTest.java @@ -0,0 +1,7 @@ +package bytecode; + +public class GenericsTest extends JavaTXCompilerTest { + public GenericsTest() { + this.fileName = "Generics"; + } +} diff --git a/test/bytecode/InterfaceTest.java b/test/bytecode/InterfaceTest.java new file mode 100644 index 00000000..ed378127 --- /dev/null +++ b/test/bytecode/InterfaceTest.java @@ -0,0 +1,7 @@ +package bytecode; + +public class InterfaceTest extends JavaTXCompilerTest{ + public InterfaceTest() { + this.fileName = "Interface1"; + } +} diff --git a/test/bytecode/JavaTXCompilerTest.java b/test/bytecode/JavaTXCompilerTest.java index f43a0740..f017e23e 100644 --- a/test/bytecode/JavaTXCompilerTest.java +++ b/test/bytecode/JavaTXCompilerTest.java @@ -25,11 +25,12 @@ public class JavaTXCompilerTest { private static final String rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; private static final List filesToTest = new ArrayList<>(); - + + protected String fileName = ""; + @Test public void test() throws IOException, java.lang.ClassNotFoundException { System.out.println(rootDirectory); - String fileName = "Generics"; filesToTest.add(new File(rootDirectory+fileName+".jav")); System.out.println(rootDirectory+fileName+".jav"); JavaTXCompiler compiler = new JavaTXCompiler(filesToTest); @@ -48,7 +49,7 @@ public class JavaTXCompilerTest { if(pos != -1) { name = f.getName().substring(0, pos); } - this.writeClassFile(bytecode, name); + this.writeClassFile(bytecode); } } @@ -61,20 +62,23 @@ public class JavaTXCompilerTest { return bytecodeGen.getClassFiles(); } - public void writeClassFile(HashMap classFiles, String name) { + public void writeClassFile(HashMap classFiles) { FileOutputStream output; - byte[] bytecode = classFiles.get(name); - try { - System.out.println("generating .class file"); - output = new FileOutputStream(new File(System.getProperty("user.dir") + "/testBytecode/generatedBC/" +name+".class")); - output.write(bytecode); - output.close(); - System.out.println(".class file generated"); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } + for(String name : classFiles.keySet()) { + byte[] bytecode = classFiles.get(name); + try { + System.out.println("generating"+name+ ".class file"); + output = new FileOutputStream(new File(System.getProperty("user.dir") + "/testBytecode/generatedBC/" +name+".class")); + output.write(bytecode); + output.close(); + System.out.println(name+".class file generated"); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } static String readFile(String path, Charset encoding) diff --git a/test/bytecode/LamAssign.jav b/test/bytecode/LamAssign.jav index e522bd3b..3df81780 100644 --- a/test/bytecode/LamAssign.jav +++ b/test/bytecode/LamAssign.jav @@ -7,3 +7,7 @@ class LamAssign { return lam1; } } + +interface Fun1{ + A apply(B b); +} diff --git a/test/bytecode/LamAssignTest.java b/test/bytecode/LamAssignTest.java new file mode 100644 index 00000000..3442c1d1 --- /dev/null +++ b/test/bytecode/LamAssignTest.java @@ -0,0 +1,7 @@ +package bytecode; + +public class LamAssignTest extends JavaTXCompilerTest{ + public LamAssignTest() { + this.fileName = "LamAssign"; + } +}