- Addition für alle Typen implementiert

- Mehrere Klassen in einer jav Datei möglich
- OLTest läuft
This commit is contained in:
Enrico Schrödter 2016-04-29 15:52:20 +02:00
parent ba6ae74ad1
commit 32741f41e9
19 changed files with 488 additions and 47 deletions

View File

@ -8,6 +8,7 @@ import java.util.Iterator;
import org.apache.commons.bcel6.Constants;
import org.apache.commons.bcel6.generic.ArithmeticInstruction;
import org.apache.commons.bcel6.generic.DUP;
import org.apache.commons.bcel6.generic.IADD;
import org.apache.commons.bcel6.generic.InstructionList;
import org.apache.commons.bcel6.generic.InvokeInstruction;
@ -20,8 +21,11 @@ import de.dhbwstuttgart.myexception.CTypeReconstructionException;
import de.dhbwstuttgart.myexception.JVMCodeException;
import de.dhbwstuttgart.syntaxtree.statement.Binary;
import de.dhbwstuttgart.syntaxtree.statement.Expr;
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.Pair;
import de.dhbwstuttgart.typeinference.SingleConstraint;
@ -75,7 +79,6 @@ public abstract class AddOp extends Operator
@Override
public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs, Binary operator) {
// TODO Plus Operator ist bis jetzt nur für Integer implementiert
/*
0: aload_1
1: invokevirtual #2 // Method java/lang/Integer.intValue:()I
@ -85,22 +88,60 @@ public abstract class AddOp extends Operator
9: invokestatic #3 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
12: areturn
*/
DHBWInstructionFactory _factory = _cg.getInstructionFactory();
String returnType = getReturnType(operator.get_Expr1(), operator.get_Expr2());
String returnType = getReturnType(operator.get_Expr1(), operator.get_Expr2(), rs);
if(returnType.equals("java.lang.String")){
DHBWInstructionFactory _factory = _cg.getInstructionFactory();
InstructionList il = getInstructionListForOperand(_cg, rs, operator.get_Expr1(), returnType);
il.append(getInstructionListForOperand(_cg, rs, operator.get_Expr2(), returnType));
il.append(getOperator(returnType));
il.append(convertValueToObject(_factory, returnType));
return il;
ObjectType objectType = new ObjectType("java.lang.StringBuilder");
InstructionList il = new InstructionList();
il.append(_factory.createNew("java.lang.StringBuilder"));
il.append(new DUP());
il.append(_cg.getInstructionFactory().createInvoke("java.lang.StringBuilder", "<init>", org.apache.commons.bcel6.generic.Type.VOID, new org.apache.commons.bcel6.generic.Type[] {}, Constants.INVOKESPECIAL));
il.append(operator.get_Expr1().genByteCode(_cg, rs));
il.append(_cg.getInstructionFactory().createInvoke("java.lang.StringBuilder", "append", objectType, new org.apache.commons.bcel6.generic.Type[] {org.apache.commons.bcel6.generic.Type.STRING}, Constants.INVOKEVIRTUAL));
il.append(operator.get_Expr2().genByteCode(_cg, rs));
il.append(_cg.getInstructionFactory().createInvoke("java.lang.StringBuilder", "append", objectType, new org.apache.commons.bcel6.generic.Type[] {org.apache.commons.bcel6.generic.Type.STRING}, Constants.INVOKEVIRTUAL));
il.append(_cg.getInstructionFactory().createInvoke("java.lang.StringBuilder", "toString", new ObjectType("java.lang.String"), new org.apache.commons.bcel6.generic.Type[] {}, Constants.INVOKEVIRTUAL));
return il;
}else{
DHBWInstructionFactory _factory = _cg.getInstructionFactory();
InstructionList il = getInstructionListForOperand(_cg, rs, operator.get_Expr1(), returnType);
il.append(getInstructionListForOperand(_cg, rs, operator.get_Expr2(), returnType));
il.append(getOperator(returnType));
il.append(convertValueToObject(_factory, returnType));
return il;
}
}
private String getReturnType(Expr expr1, Expr expr2) {
return "java.lang.Integer";
private String getReturnType(Expr expr1, Expr expr2, TypeinferenceResultSet rs) {
Type type = expr1.getType();
if(type instanceof TypePlaceholder){
Type tphType = rs.getTypeOfPlaceholder((TypePlaceholder) expr1.getType());
if(tphType instanceof ExtendsWildcardType){
return ((ExtendsWildcardType) tphType).get_ExtendsType().get_Name();
}else if(tphType instanceof SuperWildcardType){
return ((SuperWildcardType) tphType).get_SuperType().get_Name();
}else{
return tphType.getName().toString();
}
}else{
return type.get_Name();
}
}
abstract ArithmeticInstruction getOperator(String returnType);
@ -108,6 +149,12 @@ public abstract class AddOp extends Operator
private InvokeInstruction convertValueToObject(DHBWInstructionFactory _factory, String returnType) {
if(returnType.equals("java.lang.Integer")){
return _factory.createInvoke("java.lang.Integer", "valueOf", new ObjectType("java.lang.Integer"), new org.apache.commons.bcel6.generic.Type[] {org.apache.commons.bcel6.generic.Type.INT}, Constants.INVOKESTATIC);
}else if(returnType.equals("java.lang.Double")){
return _factory.createInvoke("java.lang.Double", "valueOf", new ObjectType("java.lang.Double"), new org.apache.commons.bcel6.generic.Type[] {org.apache.commons.bcel6.generic.Type.DOUBLE}, Constants.INVOKESTATIC);
}else if(returnType.equals("java.lang.Float")){
return _factory.createInvoke("java.lang.Float", "valueOf", new ObjectType("java.lang.Float"), new org.apache.commons.bcel6.generic.Type[] {org.apache.commons.bcel6.generic.Type.FLOAT}, Constants.INVOKESTATIC);
}else if(returnType.equals("java.lang.Long")){
return _factory.createInvoke("java.lang.Long", "valueOf", new ObjectType("java.lang.Long"), new org.apache.commons.bcel6.generic.Type[] {org.apache.commons.bcel6.generic.Type.LONG}, Constants.INVOKESTATIC);
}else{
throw new NotImplementedException();
}

View File

@ -7,7 +7,11 @@ import java.util.Hashtable;
import java.util.Iterator;
import org.apache.commons.bcel6.Constants;
import org.apache.commons.bcel6.generic.DADD;
import org.apache.commons.bcel6.generic.FADD;
import org.apache.commons.bcel6.generic.IADD;
import org.apache.commons.bcel6.generic.InstructionList;
import org.apache.commons.bcel6.generic.LADD;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
@ -27,6 +31,7 @@ import de.dhbwstuttgart.typeinference.SingleConstraint;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.UndConstraint;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException;
import de.dhbwstuttgart.typeinference.unify.Unify;
@ -103,7 +108,19 @@ public abstract class Operator extends SyntaxTreeNode
protected InstructionList getInstructionListForOperand(ClassGenerator _cg, TypeinferenceResultSet rs, Expr operand, String returnType){
InstructionList il = new InstructionList();
il.append(operand.genByteCode(_cg, rs));
il.append(_cg.getInstructionFactory().createInvoke("java.lang.Integer", "intValue", org.apache.commons.bcel6.generic.Type.INT, new org.apache.commons.bcel6.generic.Type[] {}, Constants.INVOKEVIRTUAL));
if(returnType.equals("java.lang.Integer")){
il.append(_cg.getInstructionFactory().createInvoke("java.lang.Integer", "intValue", org.apache.commons.bcel6.generic.Type.INT, new org.apache.commons.bcel6.generic.Type[] {}, Constants.INVOKEVIRTUAL));
}else if(returnType.equals("java.lang.Double")){
il.append(_cg.getInstructionFactory().createInvoke("java.lang.Double", "doubleValue", org.apache.commons.bcel6.generic.Type.DOUBLE, new org.apache.commons.bcel6.generic.Type[] {}, Constants.INVOKEVIRTUAL));
}else if(returnType.equals("java.lang.Float")){
il.append(_cg.getInstructionFactory().createInvoke("java.lang.Float", "floatValue", org.apache.commons.bcel6.generic.Type.FLOAT, new org.apache.commons.bcel6.generic.Type[] {}, Constants.INVOKEVIRTUAL));
}else if(returnType.equals("java.lang.Long")){
il.append(_cg.getInstructionFactory().createInvoke("java.lang.Long", "longValue", org.apache.commons.bcel6.generic.Type.LONG, new org.apache.commons.bcel6.generic.Type[] {}, Constants.INVOKEVIRTUAL));
}else if(returnType.equals("java.lang.String")){
}else{
throw new NotImplementedException(returnType);
}
return il;
}
}

View File

@ -9,6 +9,8 @@ import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
import org.apache.commons.bcel6.Constants;
import org.apache.commons.bcel6.generic.ArithmeticInstruction;
import org.apache.commons.bcel6.generic.BranchInstruction;
import org.apache.commons.bcel6.generic.DADD;
import org.apache.commons.bcel6.generic.FADD;
import org.apache.commons.bcel6.generic.GOTO;
import org.apache.commons.bcel6.generic.IADD;
import org.apache.commons.bcel6.generic.IFEQ;
@ -16,6 +18,7 @@ import org.apache.commons.bcel6.generic.IFNE;
import org.apache.commons.bcel6.generic.InstructionConstants;
import org.apache.commons.bcel6.generic.InstructionList;
import org.apache.commons.bcel6.generic.InvokeInstruction;
import org.apache.commons.bcel6.generic.LADD;
import org.apache.commons.bcel6.generic.ObjectType;
import de.dhbwstuttgart.bytecode.ClassGenerator;
@ -43,7 +46,18 @@ public class PlusOp extends AddOp
// ino.end
ArithmeticInstruction getOperator(String returnType) {
return new IADD();
if(returnType.equals("java.lang.Integer")){
return new IADD();
}else if(returnType.equals("java.lang.Double")){
return new DADD();
}else if(returnType.equals("java.lang.Float")){
return new FADD();
}else if(returnType.equals("java.lang.Long")){
return new LADD();
}else{
throw new NotImplementedException();
}
}
}
// ino.end

View File

@ -1,5 +1,11 @@
package de.dhbwstuttgart.typeinference.exceptions;
public class NotImplementedException extends RuntimeException {
public NotImplementedException() {
}
public NotImplementedException(String string) {
super(string);
}
}

View File

@ -0,0 +1,5 @@
class MultiClass{
}
class MultiClass2{
}

View File

@ -0,0 +1,49 @@
package bytecode;
import static org.junit.Assert.*;
import java.io.File;
import java.io.IOException;
import junit.framework.TestCase;
import org.junit.Test;
import plugindevelopment.TypeInsertTester;
import de.dhbwstuttgart.core.MyCompiler;
import de.dhbwstuttgart.core.MyCompilerAPI;
import de.dhbwstuttgart.logger.LoggerConfiguration;
import de.dhbwstuttgart.logger.Section;
import de.dhbwstuttgart.parser.JavaParser.yyException;
import de.dhbwstuttgart.typeinference.ByteCodeResult;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet;
public class MultiClassTest extends SourceFileBytecodeTest{
@Override
protected void init() {
testName = "MultiClass";
rootDirectory = System.getProperty("user.dir")+"/test/bytecode/";
}
@Test
public void testConstruct() throws Exception{
ClassLoader classLoader = getClassLoader();
Class cls = classLoader.loadClass(testName);
Object obj = cls.newInstance();
assertTrue(true);
}
@Test
public void testConstruct2() throws Exception{
ClassLoader classLoader = getClassLoader();
Class cls = classLoader.loadClass(testName+2);
Object obj = cls.newInstance();
assertTrue(true);
}
}

View File

@ -38,20 +38,20 @@ public class SingleClassTester {
Menge<ByteCodeResult> bytecode = compiler.generateBytecode(sourceFiles, results);
//System.out.println(bytecode);
ByteCodeResult result = bytecode.firstElement();
JavaClass javaClass = result.getByteCode().getJavaClass();
javaClass.dump(new File(outputDirectory+javaClass.getClassName()+".class"));
for(ClassGenerator cg: result.getByteCode().getExtraClasses().values()){
JavaClass jc = cg.getJavaClass();
jc.dump(new File(outputDirectory+jc.getClassName()+".class"));
for(ByteCodeResult result: bytecode){
JavaClass javaClass = result.getByteCode().getJavaClass();
javaClass.dump(new File(outputDirectory+javaClass.getClassName()+".class"));
for(ClassGenerator cg: result.getByteCode().getExtraClasses().values()){
JavaClass jc = cg.getJavaClass();
jc.dump(new File(outputDirectory+jc.getClassName()+".class"));
}
Logger.getLogger("SingleClassTester").error(result.getByteCode().getJavaClass().toString(), Section.CODEGEN);
}
Logger.getLogger("SingleClassTester").error(result.getByteCode().getJavaClass().toString(), Section.CODEGEN);
} catch (IOException | yyException e) {

View File

@ -0,0 +1,5 @@
class AddDoubleOperator{
Double method(Double x, Double y){
return x + y;
}
}

View File

@ -0,0 +1,53 @@
package bytecode.operators;
import static org.junit.Assert.*;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Vector;
import org.junit.Ignore;
import org.junit.Test;
import bytecode.SourceFileBytecodeTest;
public class AddDoubleOperatorTest extends SourceFileBytecodeTest{
@Override
protected void init() {
testName = "AddDoubleOperator";
rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/";
}
@Test
public void testConstruct() throws Exception{
ClassLoader classLoader = getClassLoader();
Class cls = classLoader.loadClass(testName);
Object obj = cls.newInstance();
assertTrue(true);
}
@Test
public void testTwoDoubles() throws Exception{
ClassLoader classLoader = getClassLoader();
Class cls = classLoader.loadClass(testName);
Object obj = cls.newInstance();
Double x = new Double(1);
Double y = new Double(2);
Class[] params = new Class[]{
x.getClass(),
y.getClass(),
};
Method method = cls.getDeclaredMethod("method", params);
Double returnValue = (Double) method.invoke(obj, x, y);
assertEquals(new Double(3.0), returnValue);
}
}

View File

@ -0,0 +1,5 @@
class AddFloatOperator{
Float method(Float x, Float y){
return x + y;
}
}

View File

@ -0,0 +1,53 @@
package bytecode.operators;
import static org.junit.Assert.*;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Vector;
import org.junit.Ignore;
import org.junit.Test;
import bytecode.SourceFileBytecodeTest;
public class AddFloatOperatorTest extends SourceFileBytecodeTest{
@Override
protected void init() {
testName = "AddFloatOperator";
rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/";
}
@Test
public void testConstruct() throws Exception{
ClassLoader classLoader = getClassLoader();
Class cls = classLoader.loadClass(testName);
Object obj = cls.newInstance();
assertTrue(true);
}
@Test
public void testTwoFloats() throws Exception{
ClassLoader classLoader = getClassLoader();
Class cls = classLoader.loadClass(testName);
Object obj = cls.newInstance();
Float x = new Float(1.0);
Float y = new Float(2.0);
Class[] params = new Class[]{
x.getClass(),
y.getClass(),
};
Method method = cls.getDeclaredMethod("method", params);
Float returnValue = (Float) method.invoke(obj, x, y);
assertEquals(new Float(3.0), returnValue);
}
}

View File

@ -0,0 +1,5 @@
class AddIntegerOperator{
Integer method(Integer x, Integer y){
return x + y;
}
}

View File

@ -0,0 +1,53 @@
package bytecode.operators;
import static org.junit.Assert.*;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Vector;
import org.junit.Ignore;
import org.junit.Test;
import bytecode.SourceFileBytecodeTest;
public class AddIntegerOperatorTest extends SourceFileBytecodeTest{
@Override
protected void init() {
testName = "AddIntegerOperator";
rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/";
}
@Test
public void testConstruct() throws Exception{
ClassLoader classLoader = getClassLoader();
Class cls = classLoader.loadClass(testName);
Object obj = cls.newInstance();
assertTrue(true);
}
@Test
public void testTwoIntegers() throws Exception{
ClassLoader classLoader = getClassLoader();
Class cls = classLoader.loadClass(testName);
Object obj = cls.newInstance();
Integer x = new Integer(1);
Integer y = new Integer(2);
Class[] params = new Class[]{
x.getClass(),
y.getClass(),
};
Method method = cls.getDeclaredMethod("method", params);
Integer returnValue = (Integer) method.invoke(obj, x, y);
assertEquals(new Integer(3), returnValue);
}
}

View File

@ -0,0 +1,5 @@
class AddLongOperator{
Long method(Long x, Long y){
return x + y;
}
}

View File

@ -0,0 +1,53 @@
package bytecode.operators;
import static org.junit.Assert.*;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Vector;
import org.junit.Ignore;
import org.junit.Test;
import bytecode.SourceFileBytecodeTest;
public class AddLongOperatorTest extends SourceFileBytecodeTest{
@Override
protected void init() {
testName = "AddLongOperator";
rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/";
}
@Test
public void testConstruct() throws Exception{
ClassLoader classLoader = getClassLoader();
Class cls = classLoader.loadClass(testName);
Object obj = cls.newInstance();
assertTrue(true);
}
@Test
public void testTwoLongs() throws Exception{
ClassLoader classLoader = getClassLoader();
Class cls = classLoader.loadClass(testName);
Object obj = cls.newInstance();
Long x = new Long(1);
Long y = new Long(2);
Class[] params = new Class[]{
x.getClass(),
y.getClass(),
};
Method method = cls.getDeclaredMethod("method", params);
Long returnValue = (Long) method.invoke(obj, x, y);
assertEquals(new Long(3), returnValue);
}
}

View File

@ -1,5 +1,5 @@
class AddOperator{
Integer method(Integer x, Integer y){
return x + y;
method(x){
return x + x;
}
}

View File

@ -39,15 +39,70 @@ public class AddOperatorTest extends SourceFileBytecodeTest{
Object obj = cls.newInstance();
Integer x = new Integer(1);
Integer y = new Integer(2);
Class[] params = new Class[]{
x.getClass(),
y.getClass(),
x.getClass()
};
Method method = cls.getDeclaredMethod("method", params);
Integer returnValue = (Integer) method.invoke(obj, x, y);
assertEquals(new Integer(3), returnValue);
Integer returnValue = (Integer) method.invoke(obj, x);
assertEquals(new Integer(2), returnValue);
}
@Test
public void testTwoDoubles() throws Exception{
ClassLoader classLoader = getClassLoader();
Class cls = classLoader.loadClass(testName);
Object obj = cls.newInstance();
Double x = new Double(1.0);
Class[] params = new Class[]{
x.getClass()
};
Method method = cls.getDeclaredMethod("method", params);
Double returnValue = (Double) method.invoke(obj, x);
assertEquals(new Double(2.0), returnValue);
}
@Test
public void testTwoFloats() throws Exception{
ClassLoader classLoader = getClassLoader();
Class cls = classLoader.loadClass(testName);
Object obj = cls.newInstance();
Float x = new Float(1.0);
Class[] params = new Class[]{
x.getClass()
};
Method method = cls.getDeclaredMethod("method", params);
Float returnValue = (Float) method.invoke(obj, x);
assertEquals(new Float(2.0), returnValue);
}
@Test
public void testTwoLongs() throws Exception{
ClassLoader classLoader = getClassLoader();
Class cls = classLoader.loadClass(testName);
Object obj = cls.newInstance();
Long x = new Long(1);
Class[] params = new Class[]{
x.getClass()
};
Method method = cls.getDeclaredMethod("method", params);
Long returnValue = (Long) method.invoke(obj, x);
assertEquals(new Long(3), returnValue);
}
}

View File

@ -1,16 +1,6 @@
class OL {
Integer m(Integer x) { return x + x; }
m(x) { return x + x; }
Boolean m(Boolean x) {return x || x; }
}
class Main {
main(x) {
ol;
ol = new OL();
return ol.m(x);
}
}
Boolean m(Boolean x) {return x; }
}

View File

@ -46,6 +46,32 @@ public class OLTest extends SourceFileBytecodeTest{
}
}
@Test
public void testString() {
try{
ClassLoader classLoader = getClassLoader();
Class cls = classLoader.loadClass(testName);
Object obj = cls.newInstance();
File file = new File(rootDirectory);
URL url = file.toURL();
URL[] urls = new URL[]{url};
String string = "foo";
Class[] params = new Class[1];
params[0] = string.getClass();
Method method = cls.getDeclaredMethod("m", params);
method.invoke(obj, string);
assertTrue(true);
}catch(Exception e){
throw new RuntimeException(e);
}
}
@Test
public void testBoolen() {
try{