Bytecode für Post-/Preincrement und Post-/Predecrement

This commit is contained in:
Fayez Abu Alia 2018-03-21 13:08:39 +01:00
parent 3233ccd845
commit e1c6369bcb
6 changed files with 187 additions and 30 deletions

View File

@ -175,10 +175,7 @@ public class BytecodeGenMethod implements StatementVisitor {
isAssignStmt =false; isAssignStmt =false;
} }
/*
* Die folgeneden Fälle müssen noch betrachtet werden: - Long OPARATION Integer
* usw.
*/
@Override @Override
public void visit(BinaryExpr binary) { public void visit(BinaryExpr binary) {
@ -194,7 +191,7 @@ public class BytecodeGenMethod implements StatementVisitor {
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(StringBuilder.class), "<init>", "()V", mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(StringBuilder.class), "<init>", "()V",
false); false);
} }
// tmp!!
Label endLabel = new Label(); Label endLabel = new Label();
// this case for while loops // this case for while loops
if(!isAssignStmt) if(!isAssignStmt)
@ -687,35 +684,76 @@ public class BytecodeGenMethod implements StatementVisitor {
String typeOfUnary = getResolvedType(unaryExpr.getType()); String typeOfUnary = getResolvedType(unaryExpr.getType());
boolean isIncOrDec = false;
switch (op) { switch (op) {
case POSTDECREMENT: case POSTDECREMENT:
case POSTINCREMENT: case POSTINCREMENT:
genBCForPostUnary(op, typeOfUnary); if(isAssignStmt)
mv.visitInsn(Opcodes.DUP);
genBCForIncAndDec(op, typeOfUnary);
getValueOfIns(typeOfUnary);
isIncOrDec = true;
break;
case PREDECREMENT:
case PREINCREMENT:
genBCForIncAndDec(op, typeOfUnary);
getValueOfIns(typeOfUnary);
if(isAssignStmt)
mv.visitInsn(Opcodes.DUP);
isIncOrDec = true;
break; break;
case MINUS:
doVisitNegIns(typeOfUnary);
break;
default: default:
break; break;
} }
getValueOfIns(typeOfUnary);
if(unaryExpr.expr instanceof LocalVar) { // Für Byte und Short muss noch einen Cast geben i2b, i2s
// das wird später gemacht, da bytecode für cast noch nicht erzeugt wird
if(isIncOrDec && (unaryExpr.expr instanceof LocalVar)) {
LocalVar local = (LocalVar) unaryExpr.expr; LocalVar local = (LocalVar) unaryExpr.expr;
mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.get(local.name)); mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.get(local.name));
} }
} }
private void genBCForPostUnary(Operation op, String typeOfUnary) { private void doVisitNegIns(String typeOfUnary) {
if(isAssignStmt) switch (typeOfUnary) {
mv.visitInsn(Opcodes.DUP); case "java/lang/Long":
mv.visitInsn(Opcodes.LNEG);
break;
case "java/lang/Double":
mv.visitInsn(Opcodes.DNEG);
break;
case "java/lang/Float":
mv.visitInsn(Opcodes.FNEG);
break;
default:
mv.visitInsn(Opcodes.INEG);
break;
}
}
private void genBCForIncAndDec(Operation op, String typeOfUnary) {
getVlaueIns(typeOfUnary); getVlaueIns(typeOfUnary);
doAssign(typeOfUnary, 1.0, true); doAssign(typeOfUnary, 1.0, true);
switch (op) { switch (op) {
case POSTDECREMENT: case POSTDECREMENT:
throw new NotImplementedException(); case PREDECREMENT:
doVisitSubOpInsn(typeOfUnary);
break;
case POSTINCREMENT: case POSTINCREMENT:
case PREINCREMENT:
doVisitAddOpInsn(typeOfUnary); doVisitAddOpInsn(typeOfUnary);
break; break;
default: default:
break; break;
} }

View File

@ -24,13 +24,13 @@ public class PostIncTest {
@BeforeClass @BeforeClass
public static void setUpBeforeClass() throws Exception { public static void setUpBeforeClass() throws Exception {
path = System.getProperty("user.dir")+"/test/bytecode/javFiles/PostInc.jav"; path = System.getProperty("user.dir")+"/test/bytecode/javFiles/PostIncDec.jav";
fileToTest = new File(path); fileToTest = new File(path);
compiler = new JavaTXCompiler(fileToTest); compiler = new JavaTXCompiler(fileToTest);
compiler.generateBytecode(); compiler.generateBytecode();
pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/";
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("PostInc"); classToTest = loader.loadClass("PostIncDec");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
} }
@ -48,4 +48,18 @@ public class PostIncTest {
assertEquals(0, res); assertEquals(0, res);
} }
@Test
public void testD1() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method m = classToTest.getDeclaredMethod("d");
Integer res = (Integer) m.invoke(instanceOfClass);
assertEquals(-1, res);
}
@Test
public void testD2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method m = classToTest.getDeclaredMethod("d2");
Integer res = (Integer) m.invoke(instanceOfClass);
assertEquals(0, res);
}
} }

View File

@ -0,0 +1,65 @@
package bytecode;
import static org.junit.Assert.*;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import de.dhbwstuttgart.core.JavaTXCompiler;
public class PreIncTest {
private static String path;
private static File fileToTest;
private static JavaTXCompiler compiler;
private static ClassLoader loader;
private static Class<?> classToTest;
private static String pathToClassFile;
private static Object instanceOfClass;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
path = System.getProperty("user.dir")+"/test/bytecode/javFiles/PreInc.jav";
fileToTest = new File(path);
compiler = new JavaTXCompiler(fileToTest);
compiler.generateBytecode();
pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/";
loader = new URLClassLoader(new URL[] {new URL("file://" + pathToClassFile)});
classToTest = loader.loadClass("PreInc");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}
@Test
public void testM() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method m = classToTest.getDeclaredMethod("m");
Integer res = (Integer) m.invoke(instanceOfClass);
assertEquals(1, res);
}
@Test
public void testM2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method m = classToTest.getDeclaredMethod("m2");
Integer res = (Integer) m.invoke(instanceOfClass);
assertEquals(1, res);
}
@Test
public void testD() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method m = classToTest.getDeclaredMethod("d");
Integer res = (Integer) m.invoke(instanceOfClass);
assertEquals(-1, res);
}
@Test
public void testD2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method m = classToTest.getDeclaredMethod("d2");
Integer res = (Integer) m.invoke(instanceOfClass);
assertEquals(-1, res);
}
}

View File

@ -1,15 +0,0 @@
import java.lang.Integer;
public class PostInc {
m() {
var i = 0;
i++;
return i;
}
m2() {
var i = 0;
var j = i++;
return j;
}
}

View File

@ -0,0 +1,27 @@
import java.lang.Integer;
public class PostIncDec {
m() {
var i = 0;
i++;
return i;
}
m2() {
var i = 0;
var j = i++;
return j;
}
d() {
var i = 0;
i--;
return i;
}
d2() {
var i = 0;
var j = i--;
return j;
}
}

View File

@ -0,0 +1,28 @@
import java.lang.Integer;
public class PreInc {
m() {
var i = 0;
++i;
return i;
}
m2() {
var i = 0;
var j = ++i;
return j;
}
d() {
var i = 0;
--i;
return i;
}
d2() {
var i = 0;
var j = --i;
return j;
}
}