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;
}
/*
* Die folgeneden Fälle müssen noch betrachtet werden: - Long OPARATION Integer
* usw.
*/
@Override
public void visit(BinaryExpr binary) {
@ -194,7 +191,7 @@ public class BytecodeGenMethod implements StatementVisitor {
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(StringBuilder.class), "<init>", "()V",
false);
}
// tmp!!
Label endLabel = new Label();
// this case for while loops
if(!isAssignStmt)
@ -687,35 +684,76 @@ public class BytecodeGenMethod implements StatementVisitor {
String typeOfUnary = getResolvedType(unaryExpr.getType());
boolean isIncOrDec = false;
switch (op) {
case POSTDECREMENT:
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;
case MINUS:
doVisitNegIns(typeOfUnary);
break;
default:
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;
mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.get(local.name));
}
}
private void genBCForPostUnary(Operation op, String typeOfUnary) {
if(isAssignStmt)
mv.visitInsn(Opcodes.DUP);
private void doVisitNegIns(String typeOfUnary) {
switch (typeOfUnary) {
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);
doAssign(typeOfUnary, 1.0, true);
switch (op) {
case POSTDECREMENT:
throw new NotImplementedException();
case PREDECREMENT:
doVisitSubOpInsn(typeOfUnary);
break;
case POSTINCREMENT:
case PREINCREMENT:
doVisitAddOpInsn(typeOfUnary);
break;
default:
break;
}

View File

@ -24,13 +24,13 @@ public class PostIncTest {
@BeforeClass
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);
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("PostInc");
classToTest = loader.loadClass("PostIncDec");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}
@ -48,4 +48,18 @@ public class PostIncTest {
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;
}
}