Fixed bugs 163 and 169

This commit is contained in:
Fayez Abu Alia 2019-09-17 09:33:18 +02:00
parent d1637b8eb9
commit c2030123d5
12 changed files with 367 additions and 368 deletions

View File

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

View File

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

View File

@ -3,45 +3,20 @@
*/ */
package de.dhbwstuttgart.bytecode.utilities; 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.Exception.NotInCurrentPackageException;
import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString; import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.bytecode.signature.Signature;
import de.dhbwstuttgart.bytecode.signature.TypeToSignature; import de.dhbwstuttgart.bytecode.signature.TypeToSignature;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.*;
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.statement.Expression; import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
import de.dhbwstuttgart.syntaxtree.statement.MethodCall; import de.dhbwstuttgart.syntaxtree.statement.MethodCall;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.result.ResultSet; import de.dhbwstuttgart.typeinference.result.ResultSet;
import javassist.NotFoundException; import javassist.NotFoundException;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.util.*;
/** /**
* @author fayez * @author fayez
@ -244,83 +219,12 @@ public class MethodCallHelper {
} }
} }
public String generateBCForFunN() { public void generateBCForFunN(String methodDescriptor) {
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); ByteCodeForFunNGenerator.generateBCForFunN(methCall.arglist,methodDescriptor,path);
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;
} }
private void writeClassFile(byte[] bytecode, String name) { public String getDescriptorOfApplyMethod(String methodCallType) {
FileOutputStream output; return new DescriptorToString().createDescForFunN(methCall.arglist, methodCallType);
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();
}
} }
/** /**

View File

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

View File

@ -32,7 +32,7 @@ public class mathStrucTest {
pathToClassFile = 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)}); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("mathStruc"); classToTest = loader.loadClass("mathStruc");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); instanceOfClass = classToTest.getDeclaredConstructor(Object.class).newInstance("A");
} }
} }

View File

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

View File

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