Merge branch 'bytecode2' into simplifyRes

This commit is contained in:
Michael Uhl 2019-09-17 09:41:08 +02:00
commit 0138e4fe2d
12 changed files with 367 additions and 368 deletions

View File

@ -1,9 +1,5 @@
package de.dhbwstuttgart.bytecode;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
@ -14,11 +10,10 @@ import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import de.dhbwstuttgart.bytecode.utilities.*;
import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.syntaxtree.statement.*;
import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr.Operator;
@ -30,28 +25,15 @@ import org.objectweb.asm.Label;
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.bytecode.Exception.NotInCurrentPackageException;
import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.bytecode.signature.Signature;
import de.dhbwstuttgart.bytecode.signature.TypeToSignature;
import de.dhbwstuttgart.bytecode.utilities.KindOfLambda;
import de.dhbwstuttgart.bytecode.utilities.Lambda;
import de.dhbwstuttgart.bytecode.utilities.MethodCallHelper;
import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall;
import de.dhbwstuttgart.bytecode.utilities.Resolver;
import de.dhbwstuttgart.bytecode.utilities.SamMethod;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.syntaxtree.AbstractASTWalker;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.result.ResultSet;
@ -64,7 +46,7 @@ public class BytecodeGenMethod implements StatementVisitor {
private MethodVisitor mv;
private HashMap<String, Integer> paramsAndLocals = new HashMap<>();
private String className;
private int lamCounter = -1;
private int lamCounter;
private ClassWriter cw;
private ResultSet resultSet;
private boolean isInterface;
@ -114,6 +96,7 @@ public class BytecodeGenMethod implements StatementVisitor {
this.classFiles = classFiles;
this.sf = sf;
this.path = path;
this.lamCounter = -1;
this.constructorPos = constructorPos;
if(block != null)
this.blockFieldInit = block;
@ -140,16 +123,17 @@ public class BytecodeGenMethod implements StatementVisitor {
this.classFiles = classFiles;
this.sf = sf;
this.path = path;
this.lamCounter = -1;
if (!isInterface)
this.m.block.accept(this);
}
public BytecodeGenMethod(LambdaExpression lambdaExpression, ArrayList<String> usedVars, ResultSet resultSet, MethodVisitor mv,
public BytecodeGenMethod(String className, ClassWriter cw, LambdaExpression lambdaExpression, ArrayList<String> usedVars, ResultSet resultSet, MethodVisitor mv,
int indexOfFirstParamLam, boolean isInterface, HashMap<String, byte[]> classFiles, String path, int lamCounter, SourceFile sf,HashMap<String, String> genericsAndBoundsMethod,
HashMap<String, String> genericsAndBounds) {
this.className = className;
this.cw = cw;
this.resultSet = resultSet;
this.resolver = new Resolver(resultSet);
this.mv = mv;
@ -192,7 +176,7 @@ public class BytecodeGenMethod implements StatementVisitor {
stmt.accept(this);
if(stmt instanceof MethodCall) {
String ret = resolver.getResolvedType(((MethodCall) stmt).getType());
if(!ret.equals("void"))
if(!ret.equals(CONSTANTS.VOID))
mv.visitInsn(Opcodes.POP);
}
}
@ -267,7 +251,7 @@ public class BytecodeGenMethod implements StatementVisitor {
System.out.println("ASSIGN TYPE R: " + resolver.getResolvedType(assign.rightSide.getType()));
String typeOfRightSide = resolver.getResolvedType(assign.rightSide.getType());
if(typeOfRightSide.contains("<")) {
if(typeOfRightSide.contains(CONSTANTS.ANGLEBRACKET)) {
mv.visitTypeInsn(Opcodes.CHECKCAST, typeOfRightSide.substring(0, typeOfRightSide.indexOf('<')));
}
assign.lefSide.accept(this);
@ -380,11 +364,11 @@ public class BytecodeGenMethod implements StatementVisitor {
private void doCast(String sourceType, String dest) {
switch (dest) {
case "java/lang/Long":
case CONSTANTS.REFTYPE_LONG:
mv.visitInsn(Opcodes.I2L);
break;
case "java/lang/Double":
case CONSTANTS.REFTYPE_DOUBLE:
if (sourceType.equals(Type.getInternalName(Long.class))) {
mv.visitInsn(Opcodes.L2D);
} else if (sourceType.equals(Type.getInternalName(Float.class))) {
@ -394,7 +378,7 @@ public class BytecodeGenMethod implements StatementVisitor {
}
break;
case "java/lang/Float":
case CONSTANTS.REFTYPE_FLOAT:
if (sourceType.equals(Type.getInternalName(Long.class))) {
mv.visitInsn(Opcodes.L2F);
} else {
@ -402,7 +386,7 @@ public class BytecodeGenMethod implements StatementVisitor {
}
break;
// braucht man eigentlich nicht, muss getestet werden
case "java/lang/String":
case CONSTANTS.REFTYPE_STRING:
if (sourceType.equals(Type.getInternalName(Double.class))) {
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf",
"(D)Ljava/lang/String;", false);
@ -425,15 +409,15 @@ public class BytecodeGenMethod implements StatementVisitor {
private void doVisitRelOpInsn(Operator op, String typeOfBinary, Label branchLabel, Label endLabel) {
System.out.println("TypeOfBinary: " + typeOfBinary);
switch (typeOfBinary) {
case "java/lang/Long":
case CONSTANTS.REFTYPE_LONG:
mv.visitInsn(Opcodes.LCMP);
doVisitIfInRelOp(op, branchLabel, endLabel);
break;
case "java/lang/Double":
case CONSTANTS.REFTYPE_DOUBLE:
mv.visitInsn(Opcodes.DCMPG);
doVisitIfInRelOp(op, branchLabel, endLabel);
break;
case "java/lang/Float":
case CONSTANTS.REFTYPE_FLOAT:
mv.visitInsn(Opcodes.FCMPG);
doVisitIfInRelOp(op, branchLabel, endLabel);
break;
@ -497,13 +481,13 @@ public class BytecodeGenMethod implements StatementVisitor {
private void doVisitModOpInsn(String typeOfBinary) {
switch (typeOfBinary) {
case "java/lang/Long":
case CONSTANTS.REFTYPE_LONG:
mv.visitInsn(Opcodes.LREM);
break;
case "java/lang/Double":
case CONSTANTS.REFTYPE_DOUBLE:
mv.visitInsn(Opcodes.DREM);
break;
case "java/lang/Float":
case CONSTANTS.REFTYPE_FLOAT:
mv.visitInsn(Opcodes.FREM);
break;
default:
@ -514,13 +498,13 @@ public class BytecodeGenMethod implements StatementVisitor {
private void doVisitDivOpInsn(String typeOfBinary) {
switch (typeOfBinary) {
case "java/lang/Long":
case CONSTANTS.REFTYPE_LONG:
mv.visitInsn(Opcodes.LDIV);
break;
case "java/lang/Double":
case CONSTANTS.REFTYPE_DOUBLE:
mv.visitInsn(Opcodes.DDIV);
break;
case "java/lang/Float":
case CONSTANTS.REFTYPE_FLOAT:
mv.visitInsn(Opcodes.FDIV);
break;
default:
@ -531,13 +515,13 @@ public class BytecodeGenMethod implements StatementVisitor {
private void doVisitMulOpInsn(String typeOfBinary) {
switch (typeOfBinary) {
case "java/lang/Long":
case CONSTANTS.REFTYPE_LONG:
mv.visitInsn(Opcodes.LMUL);
break;
case "java/lang/Double":
case CONSTANTS.REFTYPE_DOUBLE:
mv.visitInsn(Opcodes.DMUL);
break;
case "java/lang/Float":
case CONSTANTS.REFTYPE_FLOAT:
mv.visitInsn(Opcodes.FMUL);
break;
default:
@ -548,13 +532,13 @@ public class BytecodeGenMethod implements StatementVisitor {
private void doVisitSubOpInsn(String typeOfBinary) {
switch (typeOfBinary) {
case "java/lang/Long":
case CONSTANTS.REFTYPE_LONG:
mv.visitInsn(Opcodes.LSUB);
break;
case "java/lang/Double":
case CONSTANTS.REFTYPE_DOUBLE:
mv.visitInsn(Opcodes.DSUB);
break;
case "java/lang/Float":
case CONSTANTS.REFTYPE_FLOAT:
mv.visitInsn(Opcodes.FSUB);
break;
default:
@ -566,26 +550,26 @@ public class BytecodeGenMethod implements StatementVisitor {
private void doVisitAddOpInsn(String typeOfBinary) {
switch (typeOfBinary) {
case "java/lang/Byte":
case CONSTANTS.REFTYPE_BYTE:
mv.visitInsn(Opcodes.IADD);
break;
case "java/lang/Short":
case CONSTANTS.REFTYPE_SHORT:
mv.visitInsn(Opcodes.IADD);
break;
case "java/lang/Integer":
case CONSTANTS.REFTYPE_INTEGER:
mv.visitInsn(Opcodes.IADD);
break;
case "java/lang/Long":
case CONSTANTS.REFTYPE_LONG:
mv.visitInsn(Opcodes.LADD);
break;
case "java/lang/Double":
case CONSTANTS.REFTYPE_DOUBLE:
mv.visitInsn(Opcodes.DADD);
break;
case "java/lang/Float":
case CONSTANTS.REFTYPE_FLOAT:
mv.visitInsn(Opcodes.FADD);
break;
case "java/lang/String":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;",
case CONSTANTS.REFTYPE_STRING:
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", CONSTANTS.TO_STRING, "()Ljava/lang/String;",
false);
break;
default:
@ -596,17 +580,10 @@ public class BytecodeGenMethod implements StatementVisitor {
@Override
public void visit(LambdaExpression lambdaExpression) {
this.lamCounter++;
String typeErasure = "(";
Iterator<FormalParameter> itr = lambdaExpression.params.iterator();
while (itr.hasNext()) {
itr.next();
typeErasure += "L" + Type.getInternalName(Object.class) + ";";
}
typeErasure += ")L" + Type.getInternalName(Object.class) + ";";
generateBCForFunN(lambdaExpression, typeErasure);
String typeErasure = createDescriptorWithTypeErasure(lambdaExpression);
ByteCodeForFunNGenerator.generateBCForFunN(lambdaExpression, typeErasure,path);
Lambda lam = new Lambda(lambdaExpression);
@ -619,7 +596,7 @@ 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 desugaredMethodName = CONSTANTS.DESUGAREDMETHODNAME + this.lamCounter;
// Für die Parameter-Typen und Return-Typ braucht man die Bounds (für die
// Typlöschung)
@ -630,37 +607,22 @@ public class BytecodeGenMethod implements StatementVisitor {
// real Type
Type arg3 = Type.getMethodType(lamDesc);
int staticOrSpecial = 0;
int staticOrInstance = 0;
int indexOfFirstParamLam = 0;
int staticOrSpecial, staticOrInstance = 0, indexOfFirstParamLam = 0;
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));
}
loadUsedVarsInLambda();
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<kindOfLambda.getArgumentList().size();i++) {
String t = "L" + resolver.getResolvedType(kindOfLambda.getArgumentList().get(i)) + ";";
newDesc += t;
}
newDesc += lamDesc.substring(1);
String newDesc = addUsedVarsToDesugaredMethodDescriptor(lamDesc);
// first check if capturing lambda then invokestatic or invokespecial
Handle arg2 = new Handle(staticOrSpecial, this.className, methodName, newDesc, false);
Handle arg2 = new Handle(staticOrSpecial, this.className, desugaredMethodName, newDesc, false);
// Descriptor of functional interface methode
SamMethod samMethod = new SamMethod(kindOfLambda.getArgumentList(), lambdaExpression.getType());
// Desc: (this/nothing)TargetType
@ -668,11 +630,11 @@ public class BytecodeGenMethod implements StatementVisitor {
mv.visitInvokeDynamicInsn("apply", fiMethodDesc, bootstrap, arg1, arg2, arg3);
if(constructorPos<2) {
MethodVisitor mvLambdaBody = cw.visitMethod(Opcodes.ACC_PRIVATE + staticOrInstance + Opcodes.ACC_SYNTHETIC,
methodName, newDesc, null, null);
desugaredMethodName, newDesc, null, null);
ArrayList<String> usedVars = kindOfLambda.getUsedVars();
new BytecodeGenMethod(lambdaExpression, usedVars,this.resultSet, mvLambdaBody, indexOfFirstParamLam, isInterface,
new BytecodeGenMethod(className, cw,lambdaExpression, usedVars,this.resultSet, mvLambdaBody, indexOfFirstParamLam, isInterface,
classFiles,this.path, lamCounter, sf, genericsAndBoundsMethod,
genericsAndBounds);
@ -684,49 +646,41 @@ public class BytecodeGenMethod implements StatementVisitor {
// generateBCForFunN(lambdaExpression, typeErasure);
}
private void generateBCForFunN(LambdaExpression lambdaExpression, String methDesc) {
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
private String addUsedVarsToDesugaredMethodDescriptor(String lamDesc) {
String newDesc = "(";
int pos = 0;
if(kindOfLambda.isThisUsed()) {
pos = 1;
}
SignatureWriter methSig = new SignatureWriter();
for(int i=pos;i<kindOfLambda.getArgumentList().size();i++) {
String t = "L" + resolver.getResolvedType(kindOfLambda.getArgumentList().get(i)) + ";";
newDesc += t;
}
newDesc += lamDesc.substring(1);
return newDesc;
}
int numberOfParams = 0;
SignatureVisitor paramVisitor = methSig.visitParameterType();
private void loadUsedVarsInLambda() {
for(String v : kindOfLambda.getUsedVars()) {
mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(v));
}
}
private String createDescriptorWithTypeErasure(LambdaExpression lambdaExpression) {
String typeErasure = "(";
Iterator<FormalParameter> itr = lambdaExpression.params.iterator();
while (itr.hasNext()) {
numberOfParams++;
// getBounds
paramVisitor.visitTypeVariable("T" + numberOfParams);
itr.next();
}
methSig.visitReturnType().visitTypeVariable("R");
// ")"+lam.getReturn.getBounds
Signature sig = new Signature(numberOfParams);
String name = "Fun" + numberOfParams + "$$";
classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC+Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(),
Type.getInternalName(Object.class), null);
MethodVisitor mvApply = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "apply", methDesc,
methSig.toString(), null);
mvApply.visitEnd();
writeClassFile(classWriter.toByteArray(), name);
}
public void writeClassFile(byte[] bytecode, String name) {
FileOutputStream output;
try {
System.out.println("generating " + name + ".class file...");
output = new FileOutputStream(
new File(path + name + ".class"));
output.write(bytecode);
output.close();
System.out.println(name + ".class file generated");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
typeErasure += "L" + Type.getInternalName(Object.class) + ";";
}
typeErasure += ")L" + Type.getInternalName(Object.class) + ";";
return typeErasure;
}
@Override
public void visit(CastExpr castExpr) {
@ -802,8 +756,6 @@ public class BytecodeGenMethod implements StatementVisitor {
MethodCallHelper helper = new MethodCallHelper(methodCall, sf, resultSet, path);
boolean toCreate = false;
ClassLoader cLoader = ClassLoader.getSystemClassLoader();
// This will be used if the class is not standard class (not in API)
ClassLoader cLoader2;
@ -811,9 +763,7 @@ public class BytecodeGenMethod implements StatementVisitor {
String methCallType = resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor());
String[] typesOfParams = getTypes(methodCall.arglist.getArguments());
try {
if (receiverName.contains("<")) {
clazz = clazz.substring(0, receiverName.indexOf("<"));
}
clazz = getRawClassName(receiverName, clazz);
java.lang.reflect.Method[] methods = cLoader.loadClass(clazz).getMethods();
System.out.println("Methods of " + receiverName + " ");
@ -827,19 +777,12 @@ public class BytecodeGenMethod implements StatementVisitor {
try {
String superClazz = superClass.replace("/", ".");
if(superClass.contains("<")) {
superClazz = superClazz.substring(0, superClass.indexOf("<"));
}
superClazz = getRawClassName(superClass, superClazz);
java.lang.reflect.Method[] methods = cLoader.loadClass(superClazz).getMethods();
System.out.println("Methods of " + superClass + " ");
for(java.lang.reflect.Method m : methods) {
if(methodCall.name.equals(m.getName())) {
methodRefl = m;
break;
}
}
methodRefl = getMethod(methodCall.name, methodCall.arglist.getArguments().size(), methods);
break;
} catch (Exception e3) {
receiverName = superClass;
@ -854,7 +797,7 @@ public class BytecodeGenMethod implements StatementVisitor {
}
if(methodRefl == null) {
toCreate = !receiverName.equals(className) && helper.isInCurrPkg(clazz);
boolean toCreate = !receiverName.equals(className) && helper.isInCurrPkg(clazz);
if(toCreate) {
try {
mDesc = helper.getDesc(clazz);
@ -862,8 +805,9 @@ public class BytecodeGenMethod implements StatementVisitor {
e.printStackTrace();
}
} else if(!helper.isInCurrPkg(clazz)){
if(clazz.contains("$$")) {
mDesc = helper.generateBCForFunN();
if(clazz.contains(CONSTANTS.$$)) {
mDesc = helper.getDescriptorOfApplyMethod(methCallType);
helper.generateBCForFunN(mDesc);
// mDesc = helper.generateBCForFunN(methCallType,typesOfParams);
}else {
try {
@ -896,18 +840,10 @@ public class BytecodeGenMethod implements StatementVisitor {
} else if(methodRefl != null) {
System.out.println(methodCall.name + " -> Refl != null");
receiverRefl = methodRefl.getAnnotatedReceiverType().getType().toString();
for(Parameter p:methodRefl.getParameters()) {
System.out.println(p.getName() + " und is Primitive = " + p.getType().isPrimitive());
argListMethCall.add(p.getType().isPrimitive());
}
getBoolListOfType(methodRefl, argListMethCall);
System.out.println("Receiver = " + methodRefl.getAnnotatedReceiverType().getType().toString());
mDesc = getMethodDesc(methodRefl);
for (Expression al : methodCall.arglist.getArguments()) {
statement = new ArgumentExpr(al);
ArgumentVisitor argV = new ArgumentVisitor(argListMethCall,this);
al.accept(argV);
statement = null;
}
visitArgumentListOfMethodCallFromStandardAPI(methodCall, argListMethCall);
} else {
methodCall.arglist.accept(this);
}
@ -916,27 +852,20 @@ public class BytecodeGenMethod implements StatementVisitor {
// methodCall.arglist.accept(this);
// is methodCall.receiver functional Interface)?
if (varsFunInterface.contains(methodCall.receiver.getType()) || (methodRefl!= null && receiverRefl.contains("interface")) ||
receiverName.contains("$$")) {
mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, clazz.replace(".", "/"), methodCall.name,
mDesc, true);
} else {
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, clazz.replace(".", "/"), methodCall.name,
mDesc, isInterface);
}
visitInvokeInsn(methodCall, receiverName, methodRefl, clazz, mDesc, receiverRefl);
if(methodRefl != null && !methodRefl.getReturnType().isPrimitive()) {
if(methodRefl.getReturnType().equals(Object.class)) {
helper.createCheckCast(methodCall,mv);
}
if(isBinaryExp) {
/*if(isBinaryExp) {
doUnboxing(resolver.getResolvedType(methodCall.getType()));
}*/
if(parentBinary || isBinaryExp) {
doUnboxing(resolver.getResolvedType(methodCall.getType()));
}
} else if(receiverName.contains("$$") && !methCallType.equals(Type.getInternalName(Object.class))) {
} else if(receiverName.contains(CONSTANTS.$$) && !methCallType.equals(Type.getInternalName(Object.class))) {
helper.createCheckCast(methodCall,mv);
}
System.out.println("ISParent Binary = "+isParentBinary +" -> " + parentBinary);
@ -947,18 +876,39 @@ public class BytecodeGenMethod implements StatementVisitor {
}
private String getDescForMethInCurrPkg(String name) {
// TODO Auto-generated method stub
return null;
private void getBoolListOfType(java.lang.reflect.Method methodRefl, List<Boolean> argListMethCall) {
for(Parameter p:methodRefl.getParameters()) {
System.out.println(p.getName() + " und is Primitive = " + p.getType().isPrimitive());
argListMethCall.add(p.getType().isPrimitive());
}
}
private boolean isInCurrPkg(String superClass) {
for(ClassOrInterface cl : sf.KlassenVektor) {
if(superClass.equals(cl.getClassName().toString()))
return true;
private void visitArgumentListOfMethodCallFromStandardAPI(MethodCall methodCall, List<Boolean> argListMethCall) {
for (Expression al : methodCall.arglist.getArguments()) {
statement = new ArgumentExpr(al);
ArgumentVisitor argV = new ArgumentVisitor(argListMethCall,this);
al.accept(argV);
statement = null;
}
return false;
}
private void visitInvokeInsn(MethodCall methodCall, String receiverName, java.lang.reflect.Method methodRefl, String clazz, String mDesc, String receiverRefl) {
// is methodCall.receiver functional Interface)?
if (varsFunInterface.contains(methodCall.receiver.getType()) || (methodRefl!= null && receiverRefl.contains("interface")) ||
receiverName.contains(CONSTANTS.$$)) {
mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, clazz.replace(".", "/"), methodCall.name,
mDesc, true);
} else {
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, clazz.replace(".", "/"), methodCall.name,
mDesc, isInterface);
}
}
private String getRawClassName(String receiverName, String clazz) {
if (receiverName.contains(CONSTANTS.ANGLEBRACKET)) {
clazz = clazz.substring(0, receiverName.indexOf(CONSTANTS.ANGLEBRACKET));
}
return clazz;
}
private String[] getTypes(List<Expression> arguments) {
@ -1067,15 +1017,24 @@ public class BytecodeGenMethod implements StatementVisitor {
mv.visitInsn(Opcodes.DUP);
// creates Descriptor
methodCall.arglist.accept(this);
String d = "(";
for (Expression e : methodCall.arglist.getArguments()) {
d = d + "L" + resolver.getResolvedType(e.getType()) + ";";
}
d += ")V";
String d = createDescriptorForInitMethod(methodCall);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, methodCall.name.replace(".", "/"), "<init>", d, isInterface);
}
private String createDescriptorForInitMethod(NewClass methodCall) {
String d = "(";
for (Expression e : methodCall.arglist.getArguments()) {
String type = resolver.getResolvedType(e.getType());
if(type.contains("TPH ")){
type = Type.getInternalName(Object.class);
}
d = d + "L" + type + ";";
}
d += ")V";
return d;
}
@Override
public void visit(NewArray newArray) {
// TODO Auto-generated method stub
@ -1136,13 +1095,13 @@ public class BytecodeGenMethod implements StatementVisitor {
private void doVisitNegIns(String typeOfUnary) {
switch (typeOfUnary) {
case "java/lang/Long":
case CONSTANTS.REFTYPE_LONG:
mv.visitInsn(Opcodes.LNEG);
break;
case "java/lang/Double":
case CONSTANTS.REFTYPE_DOUBLE:
mv.visitInsn(Opcodes.DNEG);
break;
case "java/lang/Float":
case CONSTANTS.REFTYPE_FLOAT:
mv.visitInsn(Opcodes.FNEG);
break;
default:
@ -1260,23 +1219,23 @@ public class BytecodeGenMethod implements StatementVisitor {
case "java/lang/Boolean":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
break;
case "java/lang/Byte":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false);
case CONSTANTS.REFTYPE_BYTE:
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CONSTANTS.REFTYPE_BYTE, "byteValue", "()B", false);
break;
case "java/lang/Short":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false);
case CONSTANTS.REFTYPE_SHORT:
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CONSTANTS.REFTYPE_SHORT, "shortValue", "()S", false);
break;
case "java/lang/Integer":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
break;
case "java/lang/Long":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
case CONSTANTS.REFTYPE_LONG:
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CONSTANTS.REFTYPE_LONG, "longValue", "()J", false);
break;
case "java/lang/Float":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false);
case CONSTANTS.REFTYPE_FLOAT:
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CONSTANTS.REFTYPE_FLOAT, "floatValue", "()F", false);
break;
case "java/lang/Double":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false);
case CONSTANTS.REFTYPE_DOUBLE:
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CONSTANTS.REFTYPE_DOUBLE, "doubleValue", "()D", false);
break;
case "java/lang/Character":
break;
@ -1289,19 +1248,19 @@ public class BytecodeGenMethod implements StatementVisitor {
private void loadValue(String type, Object value, boolean isOperator) {
switch (type) {
case "java/lang/String":
case CONSTANTS.REFTYPE_STRING:
mv.visitLdcInsn(String.valueOf(value));
break;
case "java/lang/Boolean":
visitBooleanLiteral((Boolean) value);
break;
case "java/lang/Byte":
case CONSTANTS.REFTYPE_BYTE:
if(value instanceof Double)
visitByteLiteral(((Double) value).byteValue(), false);
if(value instanceof Integer)
visitByteLiteral(((Integer) value).byteValue(), false);
break;
case "java/lang/Short":
case CONSTANTS.REFTYPE_SHORT:
if(value instanceof Double)
visitShortLiteral(((Double) value).shortValue(), false);
if(value instanceof Integer)
@ -1315,19 +1274,19 @@ public class BytecodeGenMethod implements StatementVisitor {
if(value instanceof Integer)
visitIntegerLiteral(((Integer) value).intValue(), false);
break;
case "java/lang/Long":
case CONSTANTS.REFTYPE_LONG:
if(value instanceof Double)
visitLongLiteral(((Double) value).longValue(), true);
if(value instanceof Integer)
visitLongLiteral(((Integer) value).longValue(), true);
break;
case "java/lang/Float":
case CONSTANTS.REFTYPE_FLOAT:
if(value instanceof Double)
visitFloatLiteral(((Double) value).floatValue());
if(value instanceof Integer)
visitFloatLiteral(((Integer) value).floatValue());
break;
case "java/lang/Double":
case CONSTANTS.REFTYPE_DOUBLE:
if(value instanceof Double)
visitDoubleLiteral((Double) value);
if(value instanceof Integer)
@ -1343,7 +1302,7 @@ public class BytecodeGenMethod implements StatementVisitor {
break;
}
// Boxing
if (!type.equals("java/lang/String") && !type.equals("java/lang/Boolean")) {
if (!type.equals(CONSTANTS.REFTYPE_STRING) && !type.equals("java/lang/Boolean")) {
if (!this.isBinaryExp && !isOperator)
doBoxing(type);
}
@ -1360,23 +1319,23 @@ public class BytecodeGenMethod implements StatementVisitor {
case "java/lang/Boolean":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
break;
case "java/lang/Byte":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
case CONSTANTS.REFTYPE_BYTE:
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CONSTANTS.REFTYPE_BYTE, "valueOf", "(B)Ljava/lang/Byte;", false);
break;
case "java/lang/Short":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
case CONSTANTS.REFTYPE_SHORT:
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CONSTANTS.REFTYPE_SHORT, "valueOf", "(S)Ljava/lang/Short;", false);
break;
case "java/lang/Integer":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
break;
case "java/lang/Long":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
case CONSTANTS.REFTYPE_LONG:
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CONSTANTS.REFTYPE_LONG, "valueOf", "(J)Ljava/lang/Long;", false);
break;
case "java/lang/Float":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
case CONSTANTS.REFTYPE_FLOAT:
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CONSTANTS.REFTYPE_FLOAT, "valueOf", "(F)Ljava/lang/Float;", false);
break;
case "java/lang/Double":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
case CONSTANTS.REFTYPE_DOUBLE:
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CONSTANTS.REFTYPE_DOUBLE, "valueOf", "(D)Ljava/lang/Double;", false);
break;
case "java/lang/Character":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;",

View File

@ -3,29 +3,27 @@ package de.dhbwstuttgart.bytecode.descriptor;
import java.util.HashMap;
import java.util.Iterator;
import de.dhbwstuttgart.bytecode.utilities.*;
import de.dhbwstuttgart.syntaxtree.statement.ArgumentList;
import org.objectweb.asm.Type;
import de.dhbwstuttgart.bytecode.signature.TypeToSignature;
import de.dhbwstuttgart.bytecode.utilities.Lambda;
import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall;
import de.dhbwstuttgart.bytecode.utilities.NormalConstructor;
import de.dhbwstuttgart.bytecode.utilities.NormalMethod;
import de.dhbwstuttgart.bytecode.utilities.SamMethod;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.typeinference.result.ResultSet;
public class DescriptorToString implements DescriptorVisitor{
public class DescriptorToString implements DescriptorVisitor, CONSTANTS {
ResultSet resultSet;
public DescriptorToString() {
}
public DescriptorToString(ResultSet resultSet) {
this.resultSet = resultSet;
}
private String addReturnType(String desc, RefTypeOrTPHOrWildcardOrGeneric returnType, ResultSet resultSet) {
if(resultSet.resolveType(returnType).resolvedType.toString().equals("void")){
if(resultSet.resolveType(returnType).resolvedType.toString().equals(CONSTANTS.VOID)){
desc = desc + ")V";
}else {
desc = desc + ")" + "L"+resultSet.resolveType(returnType).resolvedType.acceptTV(new TypeToDescriptor())+ ";";
@ -53,7 +51,7 @@ public class DescriptorToString implements DescriptorVisitor{
}else {
// desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";";
String resType = resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor());
if(resType.contains("TPH ")/*resType.subSequence(0, 4).equals("TPH ")*/) {
if(resType.contains(CONSTANTS.TPH)/*resType.subSequence(0, 4).equals("TPH ")*/) {
// Bound ist immer Object
desc += "L"+Type.getInternalName(Object.class)+ ";";
} else {
@ -71,15 +69,15 @@ public class DescriptorToString implements DescriptorVisitor{
}
}
//TODO: generate a class java%% ... %%
else if(resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()).contains("<")){
desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "$$").replace("<", "$$$").replace(">", "$$$")+ ";";
else if(resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()).contains(CONSTANTS.ANGLEBRACKET)){
desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "$$").replace(CONSTANTS.ANGLEBRACKET, "$$$").replace(">", "$$$")+ ";";
}
else {
desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";";
}
}
if(resultSet.resolveType(method.getReturnType()).resolvedType.toString().equals("void")) {
if(resultSet.resolveType(method.getReturnType()).resolvedType.toString().equals(CONSTANTS.VOID)) {
desc += ")V";
}else {
if(method.hasGen()) {
@ -90,7 +88,7 @@ public class DescriptorToString implements DescriptorVisitor{
desc += ")L"+method.getGenericsAndBounds().get(ret)+ ";";
}else {
String resType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor());
if(resType.contains("TPH ")/*resType.subSequence(0, 4).equals("TPH ")*/) {
if(resType.contains(CONSTANTS.TPH)/*resType.subSequence(0, 4).equals("TPH ")*/) {
// desc += ")" + "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";";
desc += ")" + "L"+Type.getInternalName(Object.class)+ ";";
} else {
@ -139,7 +137,7 @@ public class DescriptorToString implements DescriptorVisitor{
}else {
// desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";";
String resType = resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor());
if(resType.subSequence(0, 4).equals("TPH ")) {
if(resType.subSequence(0, 4).equals(CONSTANTS.TPH)) {
// Bound ist immer Object
desc += "L"+Type.getInternalName(Object.class)+ ";";
} else {
@ -162,7 +160,7 @@ public class DescriptorToString implements DescriptorVisitor{
while(itr.hasNext()) {
FormalParameter fp = itr.next();
String d = resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor());
if(d.contains("TPH ") ||d.contains("<")) {
if(d.contains(CONSTANTS.TPH) ||d.contains(CONSTANTS.ANGLEBRACKET)) {
desc += "L"+Type.getInternalName(Object.class)+ ";";
}else {
desc = desc + "L"+ d + ";";
@ -171,7 +169,7 @@ public class DescriptorToString implements DescriptorVisitor{
String retType = resultSet.resolveType(lambdaExpression.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor());
if(retType.contains("TPH ")|| retType.contains("<")){
if(retType.contains(CONSTANTS.TPH)|| retType.contains(CONSTANTS.ANGLEBRACKET)){
desc += ")L"+Type.getInternalName(Object.class)+ ";";
}else {
desc = desc + ")"+"L"+retType+";";
@ -187,7 +185,7 @@ public class DescriptorToString implements DescriptorVisitor{
RefTypeOrTPHOrWildcardOrGeneric rt = itr.next();
String d = resultSet.resolveType(rt).resolvedType.acceptTV(new TypeToDescriptor());
if(d.contains("TPH ") ||d.contains("<")) {
if(d.contains(CONSTANTS.TPH) ||d.contains(CONSTANTS.ANGLEBRACKET)) {
desc += "L"+Type.getInternalName(Object.class)+ ";";
}else {
desc += "L"+ d + ";";
@ -196,7 +194,7 @@ public class DescriptorToString implements DescriptorVisitor{
}
String retType = resultSet.resolveType(samMethod.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor());
if(retType.contains("TPH ")|| retType.contains("<")){
if(retType.contains(CONSTANTS.TPH)|| retType.contains(CONSTANTS.ANGLEBRACKET)){
desc += ")L"+Type.getInternalName(Object.class)+ ";";
}else {
desc = desc + ")"+"L"+retType+";";
@ -210,7 +208,7 @@ public class DescriptorToString implements DescriptorVisitor{
for(Expression e : methodFromMethodCall.getArgList().getArguments()) {
String d = resultSet.resolveType(e.getType()).resolvedType.acceptTV(new TypeToDescriptor());
if(d.contains("TPH ") ||d.contains("<") || methodFromMethodCall.getReceiverName().contains("$$")) {
if(d.contains(CONSTANTS.TPH) ||d.contains(CONSTANTS.ANGLEBRACKET) || methodFromMethodCall.getReceiverName().contains("$$")) {
desc += "L"+Type.getInternalName(Object.class)+ ";";
}else {
if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(d)) {
@ -225,9 +223,9 @@ public class DescriptorToString implements DescriptorVisitor{
}
String retType = resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor());
System.out.println("DescriptorToString retType = " + retType);
if(retType.equals("void")) {
if(retType.equals(CONSTANTS.VOID)) {
desc += ")V";
}else if(retType.contains("TPH ")|| retType.contains("<") || methodFromMethodCall.getReceiverName().contains("$$")){
}else if(retType.contains(CONSTANTS.TPH)|| retType.contains(CONSTANTS.ANGLEBRACKET) || methodFromMethodCall.getReceiverName().contains("$$")){
desc += ")L"+Type.getInternalName(Object.class)+ ";";
}else {
if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(retType)) {
@ -241,5 +239,21 @@ public class DescriptorToString implements DescriptorVisitor{
// desc = addReturnType(desc, methodFromMethodCall.getReturnType(), resultSet);
return desc;
}
@Override
public String createDescForFunN(ArgumentList argumentList, String returnType) {
Iterator<Expression> itr1 = argumentList.getArguments().iterator();
String methDesc = "(";
while(itr1.hasNext()) {
methDesc += "L" + Type.getInternalName(Object.class) + ";";
itr1.next();
}
if (returnType.equals(CONSTANTS.VOID)){
methDesc += ")V";
} else {
methDesc += ")L" + Type.getInternalName(Object.class) + ";";
}
return methDesc;
}
}

View File

@ -5,11 +5,13 @@ import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall;
import de.dhbwstuttgart.bytecode.utilities.NormalConstructor;
import de.dhbwstuttgart.bytecode.utilities.NormalMethod;
import de.dhbwstuttgart.bytecode.utilities.SamMethod;
import de.dhbwstuttgart.syntaxtree.statement.ArgumentList;
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);
String visit(NormalMethod method);
String visit(NormalConstructor constructor);
String visit(Lambda lambdaExpression);
String visit(SamMethod samMethod);
String visit(MethodFromMethodCall methodFromMethodCall);
String createDescForFunN(ArgumentList argumentList, String returnType);
}

View File

@ -132,7 +132,7 @@ public class GenericsGenerator {
return new GenericsGeneratorResult(constraint, equalSet);
}
/* TODO Remove this method*/
/* TODO Remove this methoda*/
private static GenericsGeneratorResult generateGGResultForClass(LinkedList<String> tphsInRel,
ConstraintsSimplierResult simplifiedConstraints, List<String> tphsClass) {
String subType = tphsInRel.getFirst();

View File

@ -0,0 +1,94 @@
package de.dhbwstuttgart.bytecode.utilities;
import de.dhbwstuttgart.bytecode.signature.Signature;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.statement.ArgumentList;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
import org.objectweb.asm.ClassWriter;
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 java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
public class ByteCodeForFunNGenerator {
public static void generateBCForFunN(LambdaExpression lambdaExpression, String methDesc, String path) {
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
SignatureWriter methSig = new SignatureWriter();
int numberOfParams = 0;
SignatureVisitor paramVisitor = methSig.visitParameterType();
Iterator<FormalParameter> itr = lambdaExpression.params.iterator();
while (itr.hasNext()) {
numberOfParams++;
// getBounds
paramVisitor.visitTypeVariable(CONSTANTS.T + numberOfParams);
itr.next();
}
methSig.visitReturnType().visitTypeVariable(CONSTANTS.R);
// ")"+lam.getReturn.getBounds
Signature sig = new Signature(numberOfParams);
String name = CONSTANTS.FUN + numberOfParams + CONSTANTS.$$;
classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC+Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(),
Type.getInternalName(Object.class), null);
MethodVisitor mvApply = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "apply", methDesc,
methSig.toString(), null);
mvApply.visitEnd();
writeClassFile(classWriter.toByteArray(), name, path);
}
public static void generateBCForFunN(ArgumentList argumentList, String methDesc, String path) {
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
SignatureWriter methSig = new SignatureWriter();
int numberOfParams = 0;
SignatureVisitor paramVisitor = methSig.visitParameterType();
Iterator<Expression> itr1 = argumentList.getArguments().iterator();
while(itr1.hasNext()) {
numberOfParams++;
// getBounds
paramVisitor.visitTypeVariable(CONSTANTS.T + numberOfParams);
itr1.next();
}
methSig.visitReturnType().visitTypeVariable(CONSTANTS.R);
// ")"+lam.getReturn.getBounds
Signature sig = new Signature(numberOfParams);
String name = CONSTANTS.FUN + numberOfParams + CONSTANTS.$$;
classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC+Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(),
Type.getInternalName(Object.class), null);
MethodVisitor mvApply = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "apply", methDesc,
methSig.toString(), null);
mvApply.visitEnd();
writeClassFile(classWriter.toByteArray(), name, path);
}
public static void writeClassFile(byte[] bytecode, String name, String path) {
FileOutputStream output;
try {
System.out.println("generating " + name + ".class file...");
output = new FileOutputStream(
new File(path + name + CONSTANTS.EXTENSIONCLASS));
output.write(bytecode);
output.close();
System.out.println(name + ".class file generated");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,22 @@
package de.dhbwstuttgart.bytecode.utilities;
public interface CONSTANTS {
String VOID = "void";
String TPH = "TPH ";
String ANGLEBRACKET = "<";
String FUN = "Fun";
String EXTENSIONCLASS = ".class";
String $$ = "$$";
String T = "T";
String R = "R";
String DESUGAREDMETHODNAME = "lambda$new$";
String REFTYPE_BYTE = "java/lang/Byte";
String REFTYPE_SHORT = "java/lang/Short";
String REFTYPE_INTEGER = "java/lang/Integer";
String REFTYPE_LONG = "java/lang/Long";
String REFTYPE_DOUBLE = "java/lang/Double";
String REFTYPE_FLOAT = "java/lang/Float";
String REFTYPE_STRING = "java/lang/String";
String TO_STRING = "toString";
}

View File

@ -1,6 +1,5 @@
package de.dhbwstuttgart.bytecode.utilities;
import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.syntaxtree.statement.*;
import java.util.ArrayList;
@ -19,7 +18,8 @@ public class KindOfLambda implements StatementVisitor{
private boolean isInstanceCapturingLambda = false;
private List<RefTypeOrTPHOrWildcardOrGeneric> argumentList = new ArrayList<>();
private ArrayList<String> usedVars = new ArrayList<>();
private boolean hasThis = false;
private ArrayList<String> varsFromInnerLambdas = new ArrayList<>();
private boolean thisUsed = false;
private ArrayList<String> definedLocals = new ArrayList<>();
public KindOfLambda(LambdaExpression lambdaExpression) {
@ -40,19 +40,20 @@ public class KindOfLambda implements StatementVisitor{
return argumentList;
}
public boolean isHasThis() {
return hasThis;
public boolean isThisUsed() {
return thisUsed;
}
@Override
public void visit(ArgumentList argumentList) {
// TODO Auto-generated method stub
argumentList.getArguments().forEach(a->a.accept(this));
}
@Override
public void visit(LambdaExpression lambdaExpression) {
lambdaExpression.params.getFormalparalist().forEach(p->varsFromInnerLambdas.add(p.getName()));
lambdaExpression.methodBody.accept(this);
}
@Override
@ -111,9 +112,11 @@ public class KindOfLambda implements StatementVisitor{
@Override
public void visit(LocalVar localVar) {
if(!contain(params, localVar.name) && !definedLocals.contains(localVar.name)) {
boolean addVar = !contain(params, localVar.name) && !definedLocals.contains(localVar.name) &&
!varsFromInnerLambdas.contains(localVar.name) && !usedVars.contains(localVar.name);
if(addVar) {
argumentList.add(localVar.getType());
if(hasThis) {
if(thisUsed) {
usedVars.add(1, localVar.name);
} else {
usedVars.add(0, localVar.name);
@ -141,12 +144,13 @@ public class KindOfLambda implements StatementVisitor{
@Override
public void visit(MethodCall methodCall) {
methodCall.receiver.accept(this);
methodCall.arglist.accept(this);
}
@Override
public void visit(NewClass methodCall) {
// TODO Auto-generated method stub
methodCall.receiver.accept(this);
methodCall.arglist.accept(this);
}
@Override
@ -190,8 +194,8 @@ public class KindOfLambda implements StatementVisitor{
@Override
public void visit(This aThis) {
if(!hasThis) {
hasThis = true;
if(!thisUsed) {
thisUsed = true;
this.argumentList.add(0,aThis.getType());
}
if(!isInstanceCapturingLambda) {

View File

@ -3,45 +3,20 @@
*/
package de.dhbwstuttgart.bytecode.utilities;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.objectweb.asm.ClassWriter;
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.bytecode.Exception.NotInCurrentPackageException;
import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.bytecode.signature.Signature;
import de.dhbwstuttgart.bytecode.signature.TypeToSignature;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.GenericDeclarationList;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.ParameterList;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
import de.dhbwstuttgart.syntaxtree.statement.MethodCall;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import javassist.NotFoundException;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.util.*;
/**
* @author fayez
@ -244,83 +219,12 @@ public class MethodCallHelper {
}
}
public String generateBCForFunN() {
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
SignatureWriter methSig = new SignatureWriter();
int numberOfParams = 0;
SignatureVisitor paramVisitor = methSig.visitParameterType();
Iterator<Expression> itr1 = methCall.arglist.getArguments().iterator();
String methDesc = "(";
while(itr1.hasNext()) {
numberOfParams++;
// getBounds
paramVisitor.visitTypeVariable("T" + numberOfParams);
methDesc += "L" + Type.getInternalName(Object.class) + ";";
itr1.next();
}
methDesc += ")L" + Type.getInternalName(Object.class) + ";";
methSig.visitReturnType().visitTypeVariable("R");
// ")"+lam.getReturn.getBounds
Signature sig = new Signature(numberOfParams);
String name = "Fun" + numberOfParams + "$$";
classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC+Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(),
Type.getInternalName(Object.class), null);
MethodVisitor mvApply = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "apply", methDesc,
methSig.toString(), null);
mvApply.visitEnd();
writeClassFile(classWriter.toByteArray(), name);
return methDesc;
}
public String generateBCForFunN(String returnType, String[] paramTypes) {
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
SignatureWriter methSig = new SignatureWriter();
int numberOfParams = 0;
SignatureVisitor paramVisitor = methSig.visitParameterType();
Iterator<Expression> itr1 = methCall.arglist.getArguments().iterator();
String methDesc = "(";
while(itr1.hasNext()) {
numberOfParams++;
// getBounds
paramVisitor.visitTypeVariable("T" + numberOfParams);
methDesc += "L" + paramTypes[numberOfParams-1] + ";";
itr1.next();
}
methDesc += ")L" + returnType + ";";
methSig.visitReturnType().visitTypeVariable("R");
// ")"+lam.getReturn.getBounds
Signature sig = new Signature(numberOfParams,returnType,paramTypes);
String name = "Fun" + numberOfParams + "$$";
classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC+Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(),
Type.getInternalName(Object.class), null);
MethodVisitor mvApply = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "apply", methDesc,
methSig.toString(), null);
mvApply.visitEnd();
writeClassFile(classWriter.toByteArray(), name);
return methDesc;
public void generateBCForFunN(String methodDescriptor) {
ByteCodeForFunNGenerator.generateBCForFunN(methCall.arglist,methodDescriptor,path);
}
private void writeClassFile(byte[] bytecode, String name) {
FileOutputStream output;
try {
System.out.println("generating " + name + ".class file...");
output = new FileOutputStream(
new File(path + name + ".class"));
output.write(bytecode);
output.close();
System.out.println(name + ".class file generated");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
public String getDescriptorOfApplyMethod(String methodCallType) {
return new DescriptorToString().createDescForFunN(methCall.arglist, methodCallType);
}
/**

View File

@ -25,11 +25,11 @@ public class YTest {
public void generateBC() throws Exception {
path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/Y.jav";
fileToTest = new File(path);
// compiler = new JavaTXCompiler(fileToTest);
// compiler.generateBytecode(System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/");
// pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/";
// loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
// classToTest = loader.loadClass("Y");
compiler = new JavaTXCompiler(fileToTest);
compiler.generateBytecode(System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/");
pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/";
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("Y");
/*
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();

View File

@ -32,7 +32,7 @@ public class mathStrucTest {
pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/";
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("mathStruc");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
instanceOfClass = classToTest.getDeclaredConstructor(Object.class).newInstance("A");
}
}

View File

@ -1,26 +1,26 @@
public class FieldTphConsMeth {
a;
/*public FieldTphConsMeth(c) {
public FieldTphConsMeth(c) {
a = id(c);
}*/
}
id(b) {
return b;
}
setA(x) {
/*setA(x) {
a = x;
return a;
}
}*/
m(x,y) {
x = id(y);
}
m2(x,y) {
/*m2(x,y) {
x = setA(y);
return x;
}
}*/
}

View File

@ -1,10 +1,10 @@
class mathStruc {
public class mathStruc {
model;
//Fun1*<Fun2*<A,A,A>, Fun1*<MathStruc <A>,MathStruc <A>>>
innerOp = (o) -> (ms) -> new mathStruc<>(o.apply(model,ms.model));
mathStruc(m) {
public mathStruc(m) {
model =m;
//innerOp = (o) -> (ms) -> new mathStruc<>(o.apply(this.model,ms.model));
}