From a8274bdc698316f8523cdba423e5c1634056d58b Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Wed, 29 Nov 2017 14:45:15 +0100 Subject: [PATCH] erzeugt bytecode fuer lambda --- .../dhbwstuttgart/bytecode/BytecodeGen.java | 26 ++--- .../bytecode/BytecodeGenMethod.java | 94 ++++++++++++++----- src/de/dhbwstuttgart/bytecode/Descriptor.java | 55 ++++++++--- ...tecodeGenLambda.java => KindOfLambda.java} | 52 +++++----- test/bytecode/DuMethod.jav | 11 +++ test/bytecode/EmptyMethod.jav | 8 ++ test/bytecode/Faculty.jav | 14 +++ test/bytecode/Faculty2.jav | 10 ++ test/bytecode/JavaTXCompilerTest.java | 16 +++- test/bytecode/LamAssign.jav | 9 ++ test/bytecode/Lambda.jav | 18 ++++ test/bytecode/Lambda2.jav | 32 +++++++ test/bytecode/Lambda3.jav | 23 +++++ test/bytecode/ReturnMethod.jav | 6 ++ testBytecode/LamRun.java | 2 +- testBytecode/TestMyTest.java | 3 +- testBytecode/manually/Fac1.java | 6 ++ testBytecode/manually/Fac2.java | 14 +++ testBytecode/manually/LamAssign.java | 10 ++ testBytecode/manually/LamAssignWithM.java | 12 +++ testBytecode/manually/LamWithAnField.java | 14 +++ testBytecode/manually/LamWithField.java | 14 +++ testBytecode/manually/ReturnM1.java | 6 ++ 23 files changed, 378 insertions(+), 77 deletions(-) rename src/de/dhbwstuttgart/bytecode/{BytecodeGenLambda.java => KindOfLambda.java} (75%) create mode 100644 test/bytecode/DuMethod.jav create mode 100644 test/bytecode/EmptyMethod.jav create mode 100644 test/bytecode/Faculty.jav create mode 100644 test/bytecode/Faculty2.jav create mode 100644 test/bytecode/LamAssign.jav create mode 100644 test/bytecode/Lambda.jav create mode 100644 test/bytecode/Lambda2.jav create mode 100644 test/bytecode/Lambda3.jav create mode 100644 test/bytecode/ReturnMethod.jav create mode 100644 testBytecode/manually/Fac1.java create mode 100644 testBytecode/manually/Fac2.java create mode 100644 testBytecode/manually/LamAssign.java create mode 100644 testBytecode/manually/LamAssignWithM.java create mode 100644 testBytecode/manually/LamWithAnField.java create mode 100644 testBytecode/manually/LamWithField.java create mode 100644 testBytecode/manually/ReturnM1.java diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java index dbdb1dc2..a1bd4ae5 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -1,7 +1,5 @@ package de.dhbwstuttgart.bytecode; -import java.awt.List; -import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -20,6 +18,7 @@ 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.typeinference.result.ResultSet; public class BytecodeGen implements ASTVisitor { @@ -30,15 +29,17 @@ public class BytecodeGen implements ASTVisitor { String className; private boolean isInterface; + private ResultSet resultSet; + private int indexOfFirstParam = 0; // stores parameter, local vars and the next index on the local variable table, which use for aload_i, astore_i,... - HashMap paramsAndLocals;// = new HashMap<>(); + HashMap paramsAndLocals = new HashMap<>(); byte[] bytecode; HashMap classFiles; - public BytecodeGen(HashMap classFiles) { + public BytecodeGen(HashMap classFiles, ResultSet resultSet) { this.classFiles = classFiles; - paramsAndLocals = new HashMap<>(); + this.resultSet = resultSet; } @Override @@ -46,7 +47,7 @@ public class BytecodeGen implements ASTVisitor { 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); + BytecodeGen classGen = new BytecodeGen(classFiles, resultSet); cl.accept(classGen); classGen.writeClass(cl.getClassName().toString()); } @@ -87,32 +88,35 @@ public class BytecodeGen implements ASTVisitor { @Override public void visit(Constructor field) { - Descriptor desc = new Descriptor(field); + Descriptor desc = new Descriptor(field, resultSet); MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", desc.getDesc(), null, null); mv.visitCode(); System.out.println("-----Constructor-----"); - BytecodeGenMethod gen = new BytecodeGenMethod(className,field, mv,paramsAndLocals,desc.getDesc(),cw,isInterface); + BytecodeGenMethod gen = new BytecodeGenMethod(className,resultSet,field, mv,paramsAndLocals,desc.getDesc(),cw,isInterface); -// mv.visitInsn(Opcodes.RETURN); + mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } @Override public void visit(Method method) { + // 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); + Descriptor methDesc = new Descriptor(method,resultSet); System.out.println("-----Method-----"); MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, method.getName(), methDesc.getDesc(), null, null); mv.visitCode(); - BytecodeGenMethod gen = new BytecodeGenMethod(className,method, mv,paramsAndLocals,methDesc.getDesc(),cw,isInterface); + BytecodeGenMethod gen = new BytecodeGenMethod(className,resultSet,method, mv,paramsAndLocals,methDesc.getDesc(),cw,isInterface); mv.visitMaxs(0, 0); mv.visitEnd(); } @Override public void visit(ParameterList formalParameters) { + paramsAndLocals = new HashMap<>(); Iterator itr = formalParameters.iterator(); int i = 1; while(itr.hasNext()) { diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index ff9c8faa..c2acaba0 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -6,6 +6,7 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import de.dhbwstuttgart.syntaxtree.statement.*; import org.objectweb.asm.ClassWriter; @@ -15,11 +16,13 @@ import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.FormalParameter; 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.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.result.ResultSet; public class BytecodeGenMethod implements StatementVisitor{ @@ -30,6 +33,7 @@ public class BytecodeGenMethod implements StatementVisitor{ private String className; private int lamCounter; private ClassWriter cw; + private ResultSet resultSet; private boolean isInterface; //for tests ** @@ -37,16 +41,18 @@ public class BytecodeGenMethod implements StatementVisitor{ private String fieldDesc; private Expression rightSideTemp; private String where; - private boolean isRightSideALambda = false; + private boolean isRightSideALambda = false; + private KindOfLambda kindOfLambda; private ArrayList varsFunInterface; - public BytecodeGenMethod(String className, Method m, MethodVisitor mv, HashMap paramsAndLocals, + public BytecodeGenMethod(String className,ResultSet resultSet, Method m, MethodVisitor mv, HashMap paramsAndLocals, String desc, ClassWriter cw, boolean isInterface) { this.where = "<<<<<< NORMAL METHOD >>>>>>"; this.className = className; + this.resultSet = resultSet; this.m = m; this.mv = mv; this.paramsAndLocals = paramsAndLocals; @@ -56,27 +62,42 @@ public class BytecodeGenMethod implements StatementVisitor{ 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 paramsAndLocals, String desc,boolean isInterface) { + public BytecodeGenMethod(LambdaExpression lambdaExpression,ResultSet resultSet ,MethodVisitor mv, + String desc,int indexOfFirstParamLam, boolean isInterface) { System.out.println("\t\t++++++IN LAMBDA -------"); this.where = "<<<<<< LAMBDA METHOD >>>>>>"; - + this.resultSet = resultSet; this.mv = mv; - this.paramsAndLocals = paramsAndLocals; this.desc = desc; this.isInterface = isInterface; this.lamCounter = -1; this.varsFunInterface = new ArrayList<>(); - + + Iterator itr = lambdaExpression.params.iterator(); + int i = indexOfFirstParamLam; + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + this.paramsAndLocals.put(fp.getName(), i); + i++; + } lambdaExpression.methodBody.accept(this); } + private String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { + return resultSet.resolveType(type).resolvedType.toString().replace(".", "/"); + } + + @Override public void visit(Block block) { for(Statement stmt : block.getStatements()) { @@ -98,7 +119,7 @@ public class BytecodeGenMethod implements StatementVisitor{ // ?? @Override public void visit(LocalVar localVar) { - System.out.println("in Local Var"); + System.out.println("in Local Var: " + localVar.name); mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name)); } // ?? @@ -106,7 +127,7 @@ public class BytecodeGenMethod implements StatementVisitor{ public void visit(LocalVarDecl localVarDecl) { // Integer i; // paramsAndLocals.put(localVarDecl.getName(), paramsAndLocals.size()+1); - System.out.println("In localVarDecl"); + System.out.println("In localVarDecl :: "+localVarDecl.getName()); } @Override @@ -143,28 +164,49 @@ public class BytecodeGenMethod implements StatementVisitor{ public void visit(LambdaExpression lambdaExpression) { System.out.println("\n++ In Lambda: "); this.lamCounter++; + Descriptor lamDesc = new Descriptor(lambdaExpression, 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, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class); + Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", mt.toMethodDescriptorString(), false); String methodName = "lambda$new$" + this.lamCounter; // Type erasure - Type arg1 = Type.getMethodType("()V"); + Type arg1 = Type.getMethodType(lamDesc.getDesc()); // real Type - Type arg3 = Type.getMethodType("()V"); - Handle arg2 = new Handle(Opcodes.H_INVOKESTATIC, this.className, methodName, + Type arg3 = Type.getMethodType(lamDesc.getDesc()); + + int staticOrSpecial=0; + int staticOrInstance=0; + int indexOfFirstParamLam = 0; + this.kindOfLambda = new KindOfLambda(lambdaExpression); + + if(kindOfLambda.isInstanceCapturingLambda()) { + mv.visitVarInsn(Opcodes.ALOAD, 0); + staticOrSpecial = Opcodes.H_INVOKESPECIAL; + indexOfFirstParamLam = 1; + }else { + staticOrSpecial = Opcodes.H_INVOKESTATIC; + staticOrInstance = Opcodes.ACC_STATIC; + } + + // first check if capturing lambda then invokestatic or invokespecial + Handle arg2 = new Handle(staticOrSpecial, this.className, methodName, arg3.toString(),false); - mv.visitInvokeDynamicInsn("run", "()Ljava/lang/Runnable;", bootstrap, + // Descriptor of functional interface methode + Descriptor fiMethodDesc = new Descriptor(kindOfLambda.getArgumentList(), lambdaExpression.getType(),resultSet); + + // Desc: (this/nothing)TargetType + mv.visitInvokeDynamicInsn("apply", fiMethodDesc.getDesc(), bootstrap, arg1, arg2,arg3); - MethodVisitor mvLambdaBody = cw.visitMethod(Opcodes.ACC_PRIVATE+ Opcodes.ACC_STATIC + Opcodes.ACC_SYNTHETIC, + MethodVisitor mvLambdaBody = cw.visitMethod(Opcodes.ACC_PRIVATE+ staticOrInstance + Opcodes.ACC_SYNTHETIC, methodName, arg3.toString(), null, null); -// new BytecodeGenLambda(lambdaExpression, mvLambdaBody); - HashMap paramsAndLocalsLambda = new HashMap<>(); - new BytecodeGenMethod(lambdaExpression, mvLambdaBody, paramsAndLocalsLambda, arg3.toString(),isInterface); + + new BytecodeGenMethod(lambdaExpression,this.resultSet,mvLambdaBody,arg3.toString(),indexOfFirstParamLam,isInterface); mvLambdaBody.visitMaxs(0, 0); mvLambdaBody.visitEnd(); @@ -189,12 +231,13 @@ public class BytecodeGenMethod implements StatementVisitor{ System.out.println("in fieldVar " + fieldVar.fieldVarName + " ** receiver: "+fieldVar.receiver); fieldName = fieldVar.fieldVarName; - fieldDesc = fieldVar.getType().toString(); + fieldDesc = "L"+getResolvedType(fieldVar.getType())+";"; fieldVar.receiver.accept(this); // test (if) if(!fieldVar.receiver.getClass().equals(StaticClassName.class)) { - mv.visitFieldInsn(Opcodes.GETFIELD,fieldVar.getType().toString(),fieldName ,fieldDesc); + mv.visitFieldInsn(Opcodes.GETFIELD,getResolvedType(fieldVar.receiver.getType()), + fieldName ,fieldDesc); } // mv.visitFieldInsn(Opcodes.GETSTATIC, fieldVar.receiver.getType().toString().replace(".", "/"), @@ -231,16 +274,16 @@ public class BytecodeGenMethod implements StatementVisitor{ methodCall.receiver.accept(this); methodCall.arglist.accept(this); - Descriptor mDesc = new Descriptor(methodCall.arglist, methodCall.getType()); + Descriptor mDesc = new Descriptor(methodCall.arglist, methodCall.getType(),resultSet); System.out.println("is Vars empty: "+varsFunInterface.isEmpty()); // is methodCall.receiver functional Interface)? if(varsFunInterface.contains(methodCall.receiver.getType())) { - mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, methodCall.receiver.getType().toString().replace(".", "/"), + mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()), methodCall.name, mDesc.getDesc(), false); }else { - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, methodCall.receiver.getType().toString().replace(".", "/"), + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, getResolvedType(methodCall.receiver.getType()), methodCall.name, mDesc.getDesc(), isInterface); } // test @@ -282,6 +325,7 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(Return aReturn) { + aReturn.retexpr.accept(this); mv.visitInsn(Opcodes.ARETURN); } @@ -340,9 +384,11 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(ArgumentList argumentList) { + System.out.println("in ArgumentList: "); for(Expression al : argumentList.getArguments()) { al.accept(this); } + System.out.println("out from Argumentlist"); } @Override @@ -364,6 +410,8 @@ public class BytecodeGenMethod implements StatementVisitor{ varsFunInterface.add(assignLeftSide.localVar.getType()); paramsAndLocals.put(assignLeftSide.localVar.name, paramsAndLocals.size()+1); mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.size()); + // Debug::: + } } diff --git a/src/de/dhbwstuttgart/bytecode/Descriptor.java b/src/de/dhbwstuttgart/bytecode/Descriptor.java index 41f7ab5d..fb57e682 100644 --- a/src/de/dhbwstuttgart/bytecode/Descriptor.java +++ b/src/de/dhbwstuttgart/bytecode/Descriptor.java @@ -1,6 +1,6 @@ package de.dhbwstuttgart.bytecode; -import java.awt.List; +import java.util.List; import java.util.Iterator; import de.dhbwstuttgart.syntaxtree.Constructor; @@ -8,45 +8,74 @@ 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.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.result.ResultSet; public class Descriptor { String desc; - public Descriptor(Method method) { + public Descriptor(Method method, ResultSet resultSet) { desc = "("; Iterator itr = method.getParameterList().iterator(); while(itr.hasNext()) { FormalParameter fp = itr.next(); - desc = desc + "L"+fp.getType().toString().replace(".", "/") + ";"; - } - if(method.getReturnType().toString().equals("void")){ - desc = desc + ")V"; - }else { - desc = desc + ")" + "L"+method.getReturnType().toString().replace(".", "/")+";"; + desc = desc + "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "/") + ";"; } + desc = addReturnType(desc,method.getReturnType(), resultSet); + } - public Descriptor(Constructor constructor) { + 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"+fp.getType().toString().replace(".", "/") + ";"; + desc = desc + "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "/") + ";"; } desc = desc + ")V"; } - public Descriptor(ArgumentList argList, RefTypeOrTPHOrWildcardOrGeneric returnType) { + 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"+e.getType().toString().replace(".", "/") + ";"; + desc = desc + "L"+resultSet.resolveType(e.getType()).resolvedType.toString().replace(".", "/") + ";"; } - desc = desc + ")"+returnType.toString(); + 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/BytecodeGenLambda.java b/src/de/dhbwstuttgart/bytecode/KindOfLambda.java similarity index 75% rename from src/de/dhbwstuttgart/bytecode/BytecodeGenLambda.java rename to src/de/dhbwstuttgart/bytecode/KindOfLambda.java index 679a1365..36a28ce6 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenLambda.java +++ b/src/de/dhbwstuttgart/bytecode/KindOfLambda.java @@ -1,24 +1,33 @@ package de.dhbwstuttgart.bytecode; import de.dhbwstuttgart.syntaxtree.statement.*; -import org.objectweb.asm.MethodVisitor; + +import java.util.ArrayList; +import java.util.List; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.statement.literal.Literal; import de.dhbwstuttgart.syntaxtree.statement.literal.Null; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; -public class BytecodeGenLambda implements StatementVisitor{ - private LambdaExpression lambdaExpression; - private MethodVisitor mv; +public class KindOfLambda implements StatementVisitor{ + private boolean isInstanceCapturingLambda = false; + private List argumentList = new ArrayList<>(); - public BytecodeGenLambda(LambdaExpression lambdaExpression, MethodVisitor mv) { - this.lambdaExpression = lambdaExpression; - this.mv = mv; - + public KindOfLambda(LambdaExpression lambdaExpression) { + lambdaExpression.methodBody.accept(this); } - + + public boolean isInstanceCapturingLambda() { + return this.isInstanceCapturingLambda; + } + + public List getArgumentList() { + return argumentList; + } + @Override public void visit(ArgumentList argumentList) { // TODO Auto-generated method stub @@ -27,14 +36,12 @@ public class BytecodeGenLambda implements StatementVisitor{ @Override public void visit(LambdaExpression lambdaExpression) { - // TODO Auto-generated method stub } @Override public void visit(Assign assign) { - // TODO Auto-generated method stub - + assign.rightSide.accept(this); } @Override @@ -45,8 +52,9 @@ public class BytecodeGenLambda implements StatementVisitor{ @Override public void visit(Block block) { - // TODO Auto-generated method stub - + for(Statement stmt : block.getStatements()) { + stmt.accept(this); + } } @Override @@ -63,8 +71,7 @@ public class BytecodeGenLambda implements StatementVisitor{ @Override public void visit(FieldVar fieldVar) { - // TODO Auto-generated method stub - + fieldVar.receiver.accept(this); } @Override @@ -99,8 +106,7 @@ public class BytecodeGenLambda implements StatementVisitor{ @Override public void visit(MethodCall methodCall) { - // TODO Auto-generated method stub - + methodCall.receiver.accept(this); } @Override @@ -117,14 +123,12 @@ public class BytecodeGenLambda implements StatementVisitor{ @Override public void visit(ExpressionReceiver receiver) { - // TODO Auto-generated method stub - + receiver.expr.accept(this); } @Override public void visit(Return aReturn) { - // TODO Auto-generated method stub - + aReturn.retexpr.accept(this); } @Override @@ -147,8 +151,8 @@ public class BytecodeGenLambda implements StatementVisitor{ @Override public void visit(This aThis) { - // TODO Auto-generated method stub - + this.isInstanceCapturingLambda = true; + this.argumentList.add(aThis.getType()); } @Override diff --git a/test/bytecode/DuMethod.jav b/test/bytecode/DuMethod.jav new file mode 100644 index 00000000..b56f6c55 --- /dev/null +++ b/test/bytecode/DuMethod.jav @@ -0,0 +1,11 @@ +public class DuMethod{ + + method(a){ + return a; + } + + method(a){ + return a; + } + +} \ No newline at end of file diff --git a/test/bytecode/EmptyMethod.jav b/test/bytecode/EmptyMethod.jav new file mode 100644 index 00000000..961989df --- /dev/null +++ b/test/bytecode/EmptyMethod.jav @@ -0,0 +1,8 @@ +public class EmptyMethod{ + + public void m1(){ + System.out.println("test"); + } + + public void m2(){} +} diff --git a/test/bytecode/Faculty.jav b/test/bytecode/Faculty.jav new file mode 100644 index 00000000..5742d720 --- /dev/null +++ b/test/bytecode/Faculty.jav @@ -0,0 +1,14 @@ +class Faculty { + + Integer mul(Integer x, Integer y) { + return x; + } + + m () { + + var fact = (Integer x) -> { + return mul(x, x); + }; + return fact; + } +} diff --git a/test/bytecode/Faculty2.jav b/test/bytecode/Faculty2.jav new file mode 100644 index 00000000..828f06f5 --- /dev/null +++ b/test/bytecode/Faculty2.jav @@ -0,0 +1,10 @@ +class Faculty2 { + + m () { + + var fact = (Integer x) -> { + return x; + }; + return fact; + } +} \ No newline at end of file diff --git a/test/bytecode/JavaTXCompilerTest.java b/test/bytecode/JavaTXCompilerTest.java index 5c3e0a87..4dfdf92e 100644 --- a/test/bytecode/JavaTXCompilerTest.java +++ b/test/bytecode/JavaTXCompilerTest.java @@ -3,6 +3,8 @@ package bytecode; import de.dhbwstuttgart.bytecode.BytecodeGen; import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.typeinference.result.ResultPair; +import de.dhbwstuttgart.typeinference.result.ResultSet; import org.junit.Test; import java.io.File; @@ -27,14 +29,20 @@ public class JavaTXCompilerTest { @Test public void test() throws IOException, java.lang.ClassNotFoundException { System.out.println(rootDirectory); - String fileName = "LamRunnable"; + String fileName = "DuMethod"; filesToTest.add(new File(rootDirectory+fileName+".jav")); System.out.println(rootDirectory+fileName+".jav"); JavaTXCompiler compiler = new JavaTXCompiler(filesToTest); System.out.println("test"); for(File f : filesToTest){ String content = readFile(f.getPath(), StandardCharsets.UTF_8); - HashMap bytecode = this.getBytecode(compiler.sourceFiles.get(f)); + List typeinferenceResult = compiler.typeInference(); + HashMap bytecode = this.getBytecode(compiler.sourceFiles.get(f), typeinferenceResult.get(0)); + + for(ResultPair ep : typeinferenceResult.get(0).results) { + System.out.println(ep.getLeft() + " ->" + ep.getRight()); + } + String name = ""; int pos = f.getName().lastIndexOf("."); if(pos != -1) { @@ -46,9 +54,9 @@ public class JavaTXCompilerTest { } - public HashMap getBytecode(SourceFile sf) { + public HashMap getBytecode(SourceFile sf, ResultSet resultSet) { HashMap classFiles = new HashMap<>(); - BytecodeGen bytecodeGen = new BytecodeGen(classFiles); + BytecodeGen bytecodeGen = new BytecodeGen(classFiles,resultSet); bytecodeGen.visit(sf); return bytecodeGen.getClassFiles(); } diff --git a/test/bytecode/LamAssign.jav b/test/bytecode/LamAssign.jav new file mode 100644 index 00000000..e522bd3b --- /dev/null +++ b/test/bytecode/LamAssign.jav @@ -0,0 +1,9 @@ +class LamAssign { + + m () { + var lam1 = (Integer x) -> { + return x; + }; + return lam1; + } +} diff --git a/test/bytecode/Lambda.jav b/test/bytecode/Lambda.jav new file mode 100644 index 00000000..378eb4d3 --- /dev/null +++ b/test/bytecode/Lambda.jav @@ -0,0 +1,18 @@ +class Lambda{ + +methode(){ + return ((f) -> f); +} +} +/* +interface Fun0{ + A apply(); +} + +interface Fun1{ + A apply(B b); +} +*/ +interface Fun2{ + A apply(B b, C c); +} \ No newline at end of file diff --git a/test/bytecode/Lambda2.jav b/test/bytecode/Lambda2.jav new file mode 100644 index 00000000..fbcdaf55 --- /dev/null +++ b/test/bytecode/Lambda2.jav @@ -0,0 +1,32 @@ + +public class Lambda2 +{ + public static void main(List args){ + var listOfStrings = new List(); + var listOfObjects; + listOfObjects = map(listOfStrings, (a) -> a); +} + +public map(a , b){ + b.apply(a); + return a; +} + +/* +public static List map(List input, Function func) { + List output; + output = new List(); + output.add(func.apply(input.get())); + return output; +} +*/ +} + +class List{ + A get(); + void add(A); +} + +class Function{ + B apply(A a); +} \ No newline at end of file diff --git a/test/bytecode/Lambda3.jav b/test/bytecode/Lambda3.jav new file mode 100644 index 00000000..9c4e960c --- /dev/null +++ b/test/bytecode/Lambda3.jav @@ -0,0 +1,23 @@ + +public class Lambda2 +{ + /* + public static List map(List input, + Function func){ + input.add(func.apply(input.get())); + } + */ + public map(input,func){ + input.add(func.apply(input.get())); + return map(new List(), func); + } +} + +class List{ + A get(); + void add(A); +} + +class Function{ + B apply(A a); +} \ No newline at end of file diff --git a/test/bytecode/ReturnMethod.jav b/test/bytecode/ReturnMethod.jav new file mode 100644 index 00000000..38386d0d --- /dev/null +++ b/test/bytecode/ReturnMethod.jav @@ -0,0 +1,6 @@ +class ReturnMethod{ + Integer r; + Integer mul(Integer x, Integer y) { + return r; + } +} \ No newline at end of file diff --git a/testBytecode/LamRun.java b/testBytecode/LamRun.java index f4920700..fdaf0852 100644 --- a/testBytecode/LamRun.java +++ b/testBytecode/LamRun.java @@ -1,6 +1,6 @@ public class LamRun{ - public LamRun(){ + public void mRun(){ Runnable lam = () -> System.out.println("lambda"); lam.run(); diff --git a/testBytecode/TestMyTest.java b/testBytecode/TestMyTest.java index 1b3db588..e1305f76 100644 --- a/testBytecode/TestMyTest.java +++ b/testBytecode/TestMyTest.java @@ -5,6 +5,7 @@ public static void main(String[] a){ //test if statement //new TestIf(new Boolean(true)); // test lambda - new TestClass(); + //new TestClass(); + new LamRun(); } } diff --git a/testBytecode/manually/Fac1.java b/testBytecode/manually/Fac1.java new file mode 100644 index 00000000..e36ad3ae --- /dev/null +++ b/testBytecode/manually/Fac1.java @@ -0,0 +1,6 @@ +class Fuc1{ + + Integer mul(Integer x, Integer y) { + return x; + } +} diff --git a/testBytecode/manually/Fac2.java b/testBytecode/manually/Fac2.java new file mode 100644 index 00000000..dbf307b8 --- /dev/null +++ b/testBytecode/manually/Fac2.java @@ -0,0 +1,14 @@ +import java.util.function.Function; +class Fac2 { + + Integer mul(Integer x, Integer y) { + return x; + } + + Function m () { + Function fact = (Integer x) -> { + return mul(x, x); + }; + return fact; + } +} diff --git a/testBytecode/manually/LamAssign.java b/testBytecode/manually/LamAssign.java new file mode 100644 index 00000000..8d45a641 --- /dev/null +++ b/testBytecode/manually/LamAssign.java @@ -0,0 +1,10 @@ +import java.util.function.Function; +class LamAssign { + + Function m () { + Function lam1 = (Integer x) -> { + return x; + }; + return lam1; + } +} diff --git a/testBytecode/manually/LamAssignWithM.java b/testBytecode/manually/LamAssignWithM.java new file mode 100644 index 00000000..61077d27 --- /dev/null +++ b/testBytecode/manually/LamAssignWithM.java @@ -0,0 +1,12 @@ +import java.util.function.Function; +class LamAssignWithM { + Integer mul(Integer x, Integer y) { + return x; + } + Function m () { + Function lam1 = (Integer x) -> { + return mul(x,x); + }; + return lam1; + } +} diff --git a/testBytecode/manually/LamWithAnField.java b/testBytecode/manually/LamWithAnField.java new file mode 100644 index 00000000..ae6da4fc --- /dev/null +++ b/testBytecode/manually/LamWithAnField.java @@ -0,0 +1,14 @@ +import java.util.function.Function; +class LamWithAnField { + Integer mul(Integer x, Integer y) { + return x; + } + LamWithField temp= new LamWithField(); + Function m () { + Function lam1 = (Integer x) -> { + return temp.res*x; + }; + return lam1; + } +} + diff --git a/testBytecode/manually/LamWithField.java b/testBytecode/manually/LamWithField.java new file mode 100644 index 00000000..dacdca8b --- /dev/null +++ b/testBytecode/manually/LamWithField.java @@ -0,0 +1,14 @@ +import java.util.function.Function; +class LamWithField { + Integer mul(Integer x, Integer y) { + return x; + } + Integer res = new Integer(5); + Function m () { + Function lam1 = (Integer x) -> { + return res*x; + }; + return lam1; + } +} + diff --git a/testBytecode/manually/ReturnM1.java b/testBytecode/manually/ReturnM1.java new file mode 100644 index 00000000..3f89147d --- /dev/null +++ b/testBytecode/manually/ReturnM1.java @@ -0,0 +1,6 @@ +class ReturnM1{ + Integer r; + Integer mul(Integer x, Integer y) { + return r; + } +}