forked from JavaTX/JavaCompilerCore
erzeugt bytecode fuer lambda
This commit is contained in:
parent
e702f745c3
commit
a8274bdc69
@ -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<String, Integer> paramsAndLocals;// = new HashMap<>();
|
||||
HashMap<String, Integer> paramsAndLocals = new HashMap<>();
|
||||
byte[] bytecode;
|
||||
HashMap<String,byte[]> classFiles;
|
||||
|
||||
public BytecodeGen(HashMap<String,byte[]> classFiles) {
|
||||
public BytecodeGen(HashMap<String,byte[]> 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, "<init>", 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<FormalParameter> itr = formalParameters.iterator();
|
||||
int i = 1;
|
||||
while(itr.hasNext()) {
|
||||
|
@ -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<RefTypeOrTPHOrWildcardOrGeneric> varsFunInterface;
|
||||
|
||||
public BytecodeGenMethod(String className, Method m, MethodVisitor mv, HashMap<String, Integer> paramsAndLocals,
|
||||
public BytecodeGenMethod(String className,ResultSet resultSet, Method m, MethodVisitor mv, HashMap<String, Integer> 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<this.paramsAndLocals.size();i++) {
|
||||
System.out.println(this.paramsAndLocals.keySet().toArray()[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public BytecodeGenMethod(LambdaExpression lambdaExpression, MethodVisitor mv,
|
||||
HashMap<String, Integer> 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<FormalParameter> 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<String, Integer> 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:::
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<FormalParameter> 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<FormalParameter> 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<FormalParameter> 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<RefTypeOrTPHOrWildcardOrGeneric> argumentList,RefTypeOrTPHOrWildcardOrGeneric returnType ,ResultSet resultSet) {
|
||||
desc = "(";
|
||||
Iterator<RefTypeOrTPHOrWildcardOrGeneric> 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;
|
||||
}
|
||||
|
@ -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<RefTypeOrTPHOrWildcardOrGeneric> 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<RefTypeOrTPHOrWildcardOrGeneric> 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
|
11
test/bytecode/DuMethod.jav
Normal file
11
test/bytecode/DuMethod.jav
Normal file
@ -0,0 +1,11 @@
|
||||
public class DuMethod{
|
||||
|
||||
method(a){
|
||||
return a;
|
||||
}
|
||||
|
||||
method(a){
|
||||
return a;
|
||||
}
|
||||
|
||||
}
|
8
test/bytecode/EmptyMethod.jav
Normal file
8
test/bytecode/EmptyMethod.jav
Normal file
@ -0,0 +1,8 @@
|
||||
public class EmptyMethod{
|
||||
|
||||
public void m1(){
|
||||
System.out.println("test");
|
||||
}
|
||||
|
||||
public void m2(){}
|
||||
}
|
14
test/bytecode/Faculty.jav
Normal file
14
test/bytecode/Faculty.jav
Normal file
@ -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;
|
||||
}
|
||||
}
|
10
test/bytecode/Faculty2.jav
Normal file
10
test/bytecode/Faculty2.jav
Normal file
@ -0,0 +1,10 @@
|
||||
class Faculty2 {
|
||||
|
||||
m () {
|
||||
|
||||
var fact = (Integer x) -> {
|
||||
return x;
|
||||
};
|
||||
return fact;
|
||||
}
|
||||
}
|
@ -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<String,byte[]> bytecode = this.getBytecode(compiler.sourceFiles.get(f));
|
||||
List<ResultSet> typeinferenceResult = compiler.typeInference();
|
||||
HashMap<String,byte[]> 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<String,byte[]> getBytecode(SourceFile sf) {
|
||||
public HashMap<String,byte[]> getBytecode(SourceFile sf, ResultSet resultSet) {
|
||||
HashMap<String,byte[]> classFiles = new HashMap<>();
|
||||
BytecodeGen bytecodeGen = new BytecodeGen(classFiles);
|
||||
BytecodeGen bytecodeGen = new BytecodeGen(classFiles,resultSet);
|
||||
bytecodeGen.visit(sf);
|
||||
return bytecodeGen.getClassFiles();
|
||||
}
|
||||
|
9
test/bytecode/LamAssign.jav
Normal file
9
test/bytecode/LamAssign.jav
Normal file
@ -0,0 +1,9 @@
|
||||
class LamAssign {
|
||||
|
||||
m () {
|
||||
var lam1 = (Integer x) -> {
|
||||
return x;
|
||||
};
|
||||
return lam1;
|
||||
}
|
||||
}
|
18
test/bytecode/Lambda.jav
Normal file
18
test/bytecode/Lambda.jav
Normal file
@ -0,0 +1,18 @@
|
||||
class Lambda{
|
||||
|
||||
methode(){
|
||||
return ((f) -> f);
|
||||
}
|
||||
}
|
||||
/*
|
||||
interface Fun0<A>{
|
||||
A apply();
|
||||
}
|
||||
|
||||
interface Fun1<A,B>{
|
||||
A apply(B b);
|
||||
}
|
||||
*/
|
||||
interface Fun2<A,B,C>{
|
||||
A apply(B b, C c);
|
||||
}
|
32
test/bytecode/Lambda2.jav
Normal file
32
test/bytecode/Lambda2.jav
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
public class Lambda2
|
||||
{
|
||||
public static void main(List<String> args){
|
||||
var listOfStrings = new List<String>();
|
||||
var listOfObjects;
|
||||
listOfObjects = map(listOfStrings, (a) -> a);
|
||||
}
|
||||
|
||||
public map(a , b){
|
||||
b.apply(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
/*
|
||||
public static <I,O> List<O> map(List<I> input, Function<I,O> func) {
|
||||
List<O> output;
|
||||
output = new List<O>();
|
||||
output.add(func.apply(input.get()));
|
||||
return output;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
class List<A>{
|
||||
A get();
|
||||
void add(A);
|
||||
}
|
||||
|
||||
class Function<A,B>{
|
||||
B apply(A a);
|
||||
}
|
23
test/bytecode/Lambda3.jav
Normal file
23
test/bytecode/Lambda3.jav
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
public class Lambda2
|
||||
{
|
||||
/*
|
||||
public static <A> List<A> map(List<? extends A> input,
|
||||
Function<? super A, ? extends A> func){
|
||||
input.add(func.apply(input.get()));
|
||||
}
|
||||
*/
|
||||
public map(input,func){
|
||||
input.add(func.apply(input.get()));
|
||||
return map(new List<String>(), func);
|
||||
}
|
||||
}
|
||||
|
||||
class List<A>{
|
||||
A get();
|
||||
void add(A);
|
||||
}
|
||||
|
||||
class Function<A,B>{
|
||||
B apply(A a);
|
||||
}
|
6
test/bytecode/ReturnMethod.jav
Normal file
6
test/bytecode/ReturnMethod.jav
Normal file
@ -0,0 +1,6 @@
|
||||
class ReturnMethod{
|
||||
Integer r;
|
||||
Integer mul(Integer x, Integer y) {
|
||||
return r;
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
public class LamRun{
|
||||
|
||||
public LamRun(){
|
||||
public void mRun(){
|
||||
|
||||
Runnable lam = () -> System.out.println("lambda");
|
||||
lam.run();
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
6
testBytecode/manually/Fac1.java
Normal file
6
testBytecode/manually/Fac1.java
Normal file
@ -0,0 +1,6 @@
|
||||
class Fuc1{
|
||||
|
||||
Integer mul(Integer x, Integer y) {
|
||||
return x;
|
||||
}
|
||||
}
|
14
testBytecode/manually/Fac2.java
Normal file
14
testBytecode/manually/Fac2.java
Normal file
@ -0,0 +1,14 @@
|
||||
import java.util.function.Function;
|
||||
class Fac2 {
|
||||
|
||||
Integer mul(Integer x, Integer y) {
|
||||
return x;
|
||||
}
|
||||
|
||||
Function<Integer,Integer> m () {
|
||||
Function<Integer,Integer> fact = (Integer x) -> {
|
||||
return mul(x, x);
|
||||
};
|
||||
return fact;
|
||||
}
|
||||
}
|
10
testBytecode/manually/LamAssign.java
Normal file
10
testBytecode/manually/LamAssign.java
Normal file
@ -0,0 +1,10 @@
|
||||
import java.util.function.Function;
|
||||
class LamAssign {
|
||||
|
||||
Function<Integer,Integer> m () {
|
||||
Function<Integer,Integer> lam1 = (Integer x) -> {
|
||||
return x;
|
||||
};
|
||||
return lam1;
|
||||
}
|
||||
}
|
12
testBytecode/manually/LamAssignWithM.java
Normal file
12
testBytecode/manually/LamAssignWithM.java
Normal file
@ -0,0 +1,12 @@
|
||||
import java.util.function.Function;
|
||||
class LamAssignWithM {
|
||||
Integer mul(Integer x, Integer y) {
|
||||
return x;
|
||||
}
|
||||
Function<Integer,Integer> m () {
|
||||
Function<Integer,Integer> lam1 = (Integer x) -> {
|
||||
return mul(x,x);
|
||||
};
|
||||
return lam1;
|
||||
}
|
||||
}
|
14
testBytecode/manually/LamWithAnField.java
Normal file
14
testBytecode/manually/LamWithAnField.java
Normal file
@ -0,0 +1,14 @@
|
||||
import java.util.function.Function;
|
||||
class LamWithAnField {
|
||||
Integer mul(Integer x, Integer y) {
|
||||
return x;
|
||||
}
|
||||
LamWithField temp= new LamWithField();
|
||||
Function<Integer,Integer> m () {
|
||||
Function<Integer,Integer> lam1 = (Integer x) -> {
|
||||
return temp.res*x;
|
||||
};
|
||||
return lam1;
|
||||
}
|
||||
}
|
||||
|
14
testBytecode/manually/LamWithField.java
Normal file
14
testBytecode/manually/LamWithField.java
Normal file
@ -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<Integer,Integer> m () {
|
||||
Function<Integer,Integer> lam1 = (Integer x) -> {
|
||||
return res*x;
|
||||
};
|
||||
return lam1;
|
||||
}
|
||||
}
|
||||
|
6
testBytecode/manually/ReturnM1.java
Normal file
6
testBytecode/manually/ReturnM1.java
Normal file
@ -0,0 +1,6 @@
|
||||
class ReturnM1{
|
||||
Integer r;
|
||||
Integer mul(Integer x, Integer y) {
|
||||
return r;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user