Methoden visit(assign)/visit(literal) angepasst und generiert bytecode für Binaryexpressions. noch nicht fertig

This commit is contained in:
Fayez Abu Alia 2018-02-23 20:10:11 +01:00
parent 6808535f67
commit 4fbcf87e0c
6 changed files with 157 additions and 69 deletions

View File

@ -43,30 +43,28 @@ 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; private int lamCounter = -1;
private ClassWriter cw; private ClassWriter cw;
private ResultSet resultSet; private ResultSet resultSet;
private boolean isInterface; private boolean isInterface;
HashMap<String, String> genericsAndBoundsMethod; HashMap<String, String> genericsAndBoundsMethod;
private HashMap<String,String> genericsAndBounds; private HashMap<String,String> genericsAndBounds;
private boolean isBinaryExp = false;
//for tests ** //for tests **
private String fieldName; private String fieldName;
private String fieldDesc; private String fieldDesc;
private Expression rightSideTemp; private Expression rightSideTemp;
// private String where;
private boolean isRightSideALambda = false; private boolean isRightSideALambda = false;
private KindOfLambda kindOfLambda; private KindOfLambda kindOfLambda;
private HashMap<String, byte[]> classFiles; private HashMap<String, byte[]> classFiles;
private ArrayList<RefTypeOrTPHOrWildcardOrGeneric> varsFunInterface; private ArrayList<RefTypeOrTPHOrWildcardOrGeneric> varsFunInterface = new ArrayList<>();;
public BytecodeGenMethod(String className,ResultSet resultSet, Method m, MethodVisitor mv, public BytecodeGenMethod(String className,ResultSet resultSet, Method m, MethodVisitor mv,
HashMap<String, Integer> paramsAndLocals, ClassWriter cw, HashMap<String, String> genericsAndBoundsMethod, HashMap<String, Integer> paramsAndLocals, ClassWriter cw, HashMap<String, String> genericsAndBoundsMethod,
HashMap<String,String> genericsAndBounds, boolean isInterface, HashMap<String, byte[]> classFiles) { HashMap<String,String> genericsAndBounds, boolean isInterface, HashMap<String, byte[]> classFiles) {
// this.where = "<<<<<< NORMAL METHOD >>>>>>";
this.className = className; this.className = className;
this.resultSet = resultSet; this.resultSet = resultSet;
this.m = m; this.m = m;
@ -77,9 +75,6 @@ public class BytecodeGenMethod implements StatementVisitor{
this.genericsAndBounds = genericsAndBounds; this.genericsAndBounds = genericsAndBounds;
this.isInterface = isInterface; this.isInterface = isInterface;
this.classFiles = classFiles; this.classFiles = classFiles;
this.lamCounter = -1;
this.varsFunInterface = new ArrayList<>();
if(!isInterface) if(!isInterface)
this.m.block.accept(this); this.m.block.accept(this);
@ -89,13 +84,10 @@ public class BytecodeGenMethod implements StatementVisitor{
public BytecodeGenMethod(LambdaExpression lambdaExpression,ResultSet resultSet ,MethodVisitor mv, public BytecodeGenMethod(LambdaExpression lambdaExpression,ResultSet resultSet ,MethodVisitor mv,
int indexOfFirstParamLam, boolean isInterface, HashMap<String, byte[]> classFiles) { int indexOfFirstParamLam, boolean isInterface, HashMap<String, byte[]> classFiles) {
// this.where = "<<<<<< LAMBDA METHOD >>>>>>";
this.resultSet = resultSet; this.resultSet = resultSet;
this.mv = mv; this.mv = mv;
this.isInterface = isInterface; this.isInterface = isInterface;
this.classFiles = classFiles; this.classFiles = classFiles;
this.lamCounter = -1;
this.varsFunInterface = new ArrayList<>();
Iterator<FormalParameter> itr = lambdaExpression.params.iterator(); Iterator<FormalParameter> itr = lambdaExpression.params.iterator();
int i = indexOfFirstParamLam; int i = indexOfFirstParamLam;
@ -124,50 +116,60 @@ public class BytecodeGenMethod implements StatementVisitor{
public void visit(SuperCall superCall) { public void visit(SuperCall superCall) {
superCall.receiver.accept(this); superCall.receiver.accept(this);
superCall.arglist.accept(this); superCall.arglist.accept(this);
// mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", superCall.name, desc,false);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), superCall.name, "()V",isInterface); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), superCall.name, "()V",isInterface);
} }
// ?? // ??
@Override @Override
public void visit(LocalVar localVar) { public void visit(LocalVar localVar) {
// System.out.println("in Local Var: " + localVar.name);
mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name)); mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name));
if(isBinaryExp) {
getVlaue(getResolvedType(localVar.getType()));
}
} }
// ?? // ??
@Override @Override
public void visit(LocalVarDecl localVarDecl) { public void visit(LocalVarDecl localVarDecl) {
// Integer i;
// paramsAndLocals.put(localVarDecl.getName(), paramsAndLocals.size()+1);
// System.out.println("In localVarDecl :: "+localVarDecl.getName());
} }
@Override @Override
public void visit(Assign assign) { public void visit(Assign assign) {
// System.out.println("Assign : \nright = "+assign.rightSide + "\nLeft = " + assign.lefSide);
// if the right side is a lambda => the left side must be a functional interface // if the right side is a lambda => the left side must be a functional interface
if(assign.rightSide.getClass().equals(LambdaExpression.class)) { if(assign.rightSide instanceof LambdaExpression) {
isRightSideALambda = true; isRightSideALambda = true;
}else { }else {
isRightSideALambda = false; isRightSideALambda = false;
} }
if(assign.lefSide.getClass().equals(AssignToField.class)) { if(assign.rightSide instanceof BinaryExpr)
isBinaryExp = true;
if(assign.lefSide instanceof AssignToField) {
// load_0, ldc or .. then putfield // load_0, ldc or .. then putfield
this.rightSideTemp = assign.rightSide; this.rightSideTemp = assign.rightSide;
assign.lefSide.accept(this);
}else { }else {
assign.rightSide.accept(this); assign.rightSide.accept(this);
assign.lefSide.accept(this);
} }
if(isBinaryExp) {
doAssign(getResolvedType(assign.lefSide.getType()));
isBinaryExp = false;
}
assign.lefSide.accept(this);
} }
@Override @Override
public void visit(BinaryExpr binary) { public void visit(BinaryExpr binary) {
System.out.println("\t++ In Binary: "); binary.lexpr.accept(this);
System.out.println(binary.operation.toString()); binary.rexpr.accept(this);
switch (binary.operation.toString()) {
case "ADD":
mv.visitInsn(Opcodes.IADD);
break;
default:
break;
}
} }
@ -330,12 +332,6 @@ public class BytecodeGenMethod implements StatementVisitor{
@Override @Override
public void visit(MethodCall methodCall) { public void visit(MethodCall methodCall) {
// if(methodCall.receiver instanceof ExpressionReceiver){
// System.out.print(((ExpressionReceiver) methodCall.receiver).expr + "\n");
// }else{
// System.out.print(((StaticClassName) methodCall.receiver).getType().toString() + "\n");
// }
methodCall.receiver.accept(this); methodCall.receiver.accept(this);
methodCall.arglist.accept(this); methodCall.arglist.accept(this);
@ -343,8 +339,6 @@ public class BytecodeGenMethod implements StatementVisitor{
genericsAndBoundsMethod,genericsAndBounds); genericsAndBoundsMethod,genericsAndBounds);
String mDesc = method.accept(new DescriptorToString(resultSet)); String mDesc = method.accept(new DescriptorToString(resultSet));
// System.out.println("is Vars empty: "+varsFunInterface.isEmpty());
// is methodCall.receiver functional Interface)? // is methodCall.receiver functional Interface)?
if(varsFunInterface.contains(methodCall.receiver.getType())) { if(varsFunInterface.contains(methodCall.receiver.getType())) {
mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()), mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()),
@ -361,8 +355,6 @@ public class BytecodeGenMethod implements StatementVisitor{
@Override @Override
public void visit(NewClass methodCall) { public void visit(NewClass methodCall) {
// System.out.println("In NewClass: ");
// System.out.println("\t\tname: " + methodCall.name + " *** " + "Receiver: " + methodCall.receiver);
mv.visitTypeInsn(Opcodes.NEW, methodCall.name.replace(".", "/")); mv.visitTypeInsn(Opcodes.NEW, methodCall.name.replace(".", "/"));
mv.visitInsn(Opcodes.DUP); mv.visitInsn(Opcodes.DUP);
@ -437,9 +429,53 @@ public class BytecodeGenMethod implements StatementVisitor{
@Override @Override
public void visit(Literal literal) { public void visit(Literal literal) {
Object value = literal.value; Object value = literal.value;
switch (resultSet.resolveType(literal.getType()).resolvedType.acceptTV(new TypeToDescriptor())) { String typeOfLiteral = resultSet.resolveType(literal.getType()).resolvedType.acceptTV(new TypeToDescriptor());
if(this.isBinaryExp) {
getVlaue(typeOfLiteral);
}else {
doAssign(typeOfLiteral, value);
}
}
private void getVlaue(String typeOfLiteral) {
switch (typeOfLiteral) {
case "java/lang/String": case "java/lang/String":
mv.visitLdcInsn(value); break;
case "java/lang/Boolean":
break;
case "java/lang/Byte":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/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);
break;
case "java/lang/Integer":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue",
"()I", false);
break;
case "java/lang/Long":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf",
"(J)Ljava/lang/Long;", false);
break;
case "java/lang/Float":
break;
case "java/lang/Double":
break;
case "java/lang/Character":
break;
default:
break;
}
}
private void doAssign(String type, Object value) {
switch (type) {
case "java/lang/String":
mv.visitLdcInsn(String.valueOf(value));
break; break;
case "java/lang/Boolean": case "java/lang/Boolean":
visitBooleanLiteral((Boolean) value); visitBooleanLiteral((Boolean) value);
@ -479,8 +515,41 @@ public class BytecodeGenMethod implements StatementVisitor{
} }
} }
private void doAssign(String type) {
switch (type) {
case "java/lang/String":
break;
case "java/lang/Boolean":
break;
case "java/lang/Byte":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/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);
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);
break;
case "java/lang/Float":
break;
case "java/lang/Double":
break;
case "java/lang/Character":
break;
default:
break;
}
}
private void visitCharLiteral(Character value) { private void visitCharLiteral(Character value) {
mv.visitIntInsn(Opcodes.BIPUSH, Character.getNumericValue(value.charValue())); mv.visitIntInsn(Opcodes.BIPUSH, (int) value);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf",
"(C)Ljava/lang/Character;", false); "(C)Ljava/lang/Character;", false);
} }

View File

@ -10,21 +10,21 @@ import java.lang.Character;
class AssignToLit { class AssignToLit {
void m(){ void m(){
String s = "Test"; // String s = "Test";
Boolean b = false; // Boolean b = false;
Byte byte1 = 5; // Byte byte1 = 5;
Byte byte2 = 55; // Byte byte2 = 55;
Short short1 = 5; // Short short1 = 5;
Short short2 = 55; // Short short2 = 55;
Integer int1 = 5; // Integer int1 = 5;
Integer int2 = 8888888; // Integer int2 = 8888888;
Long long1 = 1; // Long long1 = 1;
Long long2 = 5; // Long long2 = 5;
Long long3 = 89989898; // Long long3 = 89989898;
Float float1 = 1; // Float float1 = 1;
Float float2 = 55; // Float float2 = 55;
Double d1 = 1; // Double d1 = 1;
Double d2 = 55; // Double d2 = 55;
Character c = 'A'; Character c = 'A';
} }
} }

View File

@ -2,19 +2,19 @@ import java.lang.Integer;
import java.lang.Boolean; import java.lang.Boolean;
class For{ class For{
m(Integer x){ Integer m(Integer x){
var c = x + 2;
Boolean b = true; // Boolean b = true;
c = 5; // c = 5;
c++; // c++;
++c; // ++c;
c--; // c--;
--c; // --c;
while(x<2){ // while(x<2){
x = x +1; // x = x +1;
b = false; // b = false;
} // }
return x; return c;
// for(int i = 0;i<10;i++) { // for(int i = 0;i<10;i++) {
// x = x + 5; // x = x + 5;
// } // }

12
test/bytecode/Op.jav Normal file
View File

@ -0,0 +1,12 @@
import java.lang.Integer;
class Op {
m(Integer a, Integer b) {
Integer c = a+b;
// d = a-b;
// e = a*b;
// f = a/b;
return c;
}
}

View File

@ -0,0 +1,7 @@
package bytecode;
public class OpTest extends JavaTXCompilerTest {
public OpTest() {
this.fileName = "Op";
}
}

View File

@ -3,9 +3,9 @@ import java.lang.Integer;
class OpratorTest { class OpratorTest {
m(Integer a, Integer b) { m(Integer a, Integer b) {
c = a+b; c = a+b;
d = a-b; // d = a-b;
e = a*b; // e = a*b;
f = a/b; // f = a/b;
return c; return c;
} }