diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java index e97b1574..70f6e7e9 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -46,7 +46,8 @@ public class BytecodeGen implements ASTVisitor { ClassWriter cw =new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS); String type; - + + public static RefTypeOrTPHOrWildcardOrGeneric THISTYPE = null; String className; private boolean isInterface; private List listOfResultSets; diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index d90daa8b..715e47f2 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -109,7 +109,7 @@ public class BytecodeGenMethod implements StatementVisitor { } - public BytecodeGenMethod(LambdaExpression lambdaExpression, ResultSet resultSet, MethodVisitor mv, + public BytecodeGenMethod(LambdaExpression lambdaExpression, ArrayList usedVars, ResultSet resultSet, MethodVisitor mv, int indexOfFirstParamLam, boolean isInterface, HashMap classFiles, String path, int lamCounter, SourceFile sf) { this.resultSet = resultSet; @@ -121,6 +121,12 @@ public class BytecodeGenMethod implements StatementVisitor { this.sf = sf; Iterator itr = lambdaExpression.params.iterator(); int i = indexOfFirstParamLam; + + for(String var : usedVars) { + this.paramsAndLocals.put(var, i); + i++; + } + while (itr.hasNext()) { FormalParameter fp = itr.next(); this.paramsAndLocals.put(fp.getName(), i); @@ -520,7 +526,7 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(LambdaExpression lambdaExpression) { this.lamCounter++; - + String typeErasure = "("; Iterator itr = lambdaExpression.params.iterator(); while (itr.hasNext()) { @@ -560,16 +566,31 @@ public class BytecodeGenMethod implements StatementVisitor { this.kindOfLambda = new KindOfLambda(lambdaExpression); if (kindOfLambda.isInstanceCapturingLambda()) { +// if(!kindOfLambda.getArgumentList().contains(BytecodeGen.THISTYPE)) +// kindOfLambda.getArgumentList().add(0, BytecodeGen.THISTYPE); mv.visitVarInsn(Opcodes.ALOAD, 0); + for(String v : kindOfLambda.getUsedVars()) { + mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(v)); + } staticOrSpecial = Opcodes.H_INVOKESPECIAL; indexOfFirstParamLam = 1; } else { staticOrSpecial = Opcodes.H_INVOKESTATIC; staticOrInstance = Opcodes.ACC_STATIC; } - + String newDesc = "("; + int pos = 0; + if(kindOfLambda.isHasThis()) { + pos = 1; + } + + for(int i=pos;i usedVars = kindOfLambda.getUsedVars(); + + new BytecodeGenMethod(lambdaExpression, usedVars,this.resultSet, mvLambdaBody, indexOfFirstParamLam, isInterface, classFiles,this.path, lamCounter, sf); mvLambdaBody.visitMaxs(0, 0); @@ -654,7 +677,10 @@ public class BytecodeGenMethod implements StatementVisitor { if (!fieldVar.receiver.getClass().equals(StaticClassName.class)) { mv.visitFieldInsn(Opcodes.GETFIELD, getResolvedType(fieldVar.receiver.getType()), fieldName, fieldDesc); } - + + if (isBinaryExp) { + doUnboxing(getResolvedType(fieldVar.getType())); + } // mv.visitFieldInsn(Opcodes.GETSTATIC, // fieldVar.receiver.getType().toString().replace(".", "/"), // fieldVar.fieldVarName, fieldVar.getType().toString()); @@ -1081,6 +1107,10 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(This aThis) { + + if(BytecodeGen.THISTYPE == null) + BytecodeGen.THISTYPE = aThis.getType(); + mv.visitVarInsn(Opcodes.ALOAD, 0); } diff --git a/src/de/dhbwstuttgart/bytecode/utilities/KindOfLambda.java b/src/de/dhbwstuttgart/bytecode/utilities/KindOfLambda.java index 53994d1e..2e5c81db 100644 --- a/src/de/dhbwstuttgart/bytecode/utilities/KindOfLambda.java +++ b/src/de/dhbwstuttgart/bytecode/utilities/KindOfLambda.java @@ -4,22 +4,33 @@ import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.syntaxtree.statement.*; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.ParameterList; import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.statement.Literal; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; public class KindOfLambda implements StatementVisitor{ + private ParameterList params; private boolean isInstanceCapturingLambda = false; private List argumentList = new ArrayList<>(); + private ArrayList usedVars = new ArrayList<>(); + private boolean hasThis = false; public KindOfLambda(LambdaExpression lambdaExpression) { + this.params = lambdaExpression.params; lambdaExpression.methodBody.accept(this); } + public ArrayList getUsedVars() { + return usedVars; + } + public boolean isInstanceCapturingLambda() { return this.isInstanceCapturingLambda; } @@ -28,6 +39,10 @@ public class KindOfLambda implements StatementVisitor{ return argumentList; } + public boolean isHasThis() { + return hasThis; + } + @Override public void visit(ArgumentList argumentList) { // TODO Auto-generated method stub @@ -95,8 +110,26 @@ public class KindOfLambda implements StatementVisitor{ @Override public void visit(LocalVar localVar) { - // TODO Auto-generated method stub - + if(!contain(params, localVar.name)) { + argumentList.add(localVar.getType()); + if(hasThis) { + usedVars.add(1, localVar.name); + } else { + usedVars.add(0, localVar.name); + } + if(!isInstanceCapturingLambda) + isInstanceCapturingLambda=true; + } + } + + private boolean contain(ParameterList params2, String name) { + Iterator itr = params2.iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + if(fp.getName().equals(name)) + return true; + } + return false; } @Override @@ -157,9 +190,13 @@ public class KindOfLambda implements StatementVisitor{ @Override public void visit(This aThis) { + if(!hasThis) { + hasThis = true; + this.argumentList.add(0,aThis.getType()); + } if(!isInstanceCapturingLambda) { this.isInstanceCapturingLambda = true; - this.argumentList.add(aThis.getType()); + } } diff --git a/test/bytecode/LambdaCapturetest.java b/test/bytecode/LambdaCapturetest.java new file mode 100644 index 00000000..438c2315 --- /dev/null +++ b/test/bytecode/LambdaCapturetest.java @@ -0,0 +1,43 @@ +/** + * + */ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +/** + * @author fayez + * + */ +public class LambdaCapturetest { + 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; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/LambdaCapture.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("LambdaCapture"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + +} diff --git a/test/bytecode/javFiles/LambdaCapture.jav b/test/bytecode/javFiles/LambdaCapture.jav new file mode 100644 index 00000000..ab1751f4 --- /dev/null +++ b/test/bytecode/javFiles/LambdaCapture.jav @@ -0,0 +1,12 @@ +import java.lang.Integer; +public class LambdaCapture { + Integer i = 8; + f; + public LambdaCapture(){ + Integer w = 7; + f = j ->{ + return w+i;}; + + } + +} \ No newline at end of file