2
0

Compare commits

..

18 Commits

Author SHA1 Message Date
77fbe99fed merge 2017-01-27 14:20:33 +01:00
f92a53ce74 Aufräumen 2017-01-26 17:16:06 +01:00
acf9cbd20b Merge mit antlr-branch. Löschen aller ino.Kommentare 2017-01-20 15:20:45 +01:00
049f435537 Unnötige ino-Kommentare entfernen 2017-01-20 13:57:20 +01:00
f2ddce2e89 Merge mit antlr 2017-01-20 13:54:06 +01:00
72bcfd41d3 Merge mit ANTLR branch 2017-01-13 17:49:58 +01:00
3b6363d71a Aufrömen 2016-12-21 15:06:55 +01:00
ddbcc5ee6e GenericType für Bytecodegenerierung eingeführt 2016-12-16 14:33:04 +01:00
1b99f74f39 Generics als RefType entfernen 2016-12-16 13:26:28 +01:00
7b9a00a7e6 Revert "Syntaxbaum bereinigen. Allen Code löschen. Nur Struktur bleibt erhalten"
This reverts commit 3ab96a3ed7.
2016-12-16 01:05:54 +01:00
c329ba6cef merge 2016-12-16 01:05:45 +01:00
76880708a1 Merge 2016-12-15 17:07:17 +01:00
7d09131c27 ObjectClass einführen 2016-11-16 13:41:25 +01:00
388685d3b2 Bugfix (FunVoidN Typen) 2016-11-15 23:00:07 +01:00
642394c25b ObjectClass added 2016-11-15 21:15:09 +01:00
85dc60169a Merge, ObjectClass anfügen 2016-11-15 19:47:46 +01:00
73e6e5c45f LambdaTest30 anfügen 2016-11-15 19:46:50 +01:00
1a94f449a0 bugfix 2016-11-11 11:50:55 +01:00
589 changed files with 25916 additions and 269 deletions
src/de/dhbwstuttgart
JvmDisassembler
bytecode
core
logger
parser
syntaxtree
ClassOrInterface.javaConstructor.javaField.javaFieldDeclaration.javaFormalParameter.javaGTVDeclarationContext.javaGeneric.javaGenericDeclarationList.javaGenericTypeVar.javaMethod.javaObjectClass.javaParameterList.javaSourceFile.javaSyntaxTreeNode.java
factory
modifier
operator
statement
type
typeinference
test
KomplexeMenge
bytecode
ASTBytecodeTest.javaAssign.javAssignTest.javaBinary.javBinary2.javBinaryTest.javaBinaryTest2.javaBoolLit.javBoolLitTest.javaCharLitTest.javaCondition.javConditionTest.javaEmptyClass.javEmptyClassTest.javaFieldDeclaration.javFieldDeclarationTest.javaForTest.javForTest.javaFun0.javaId.javIdTest.javaIdentity.javIdentityField.javIdentityFieldTest.javaIdentityTest.javaIfElseIfStatement.javIfElseIfStatementTest.javaIfElseStatement.javIfElseStatementTest.javaIfStatement.javIfStatementTest.javaLambdaExpr.javLambdaExpr2.javLambdaExpr2Test.javaLambdaExprTest.javaLambdaRunnable.javLambdaRunnableTest.javaMain.javMainTest.javaMatrix_lambda.javMatrix_lambda2.javMatrix_lambda3.javMatrix_lambdaTest.javaMatrix_lambdaTest2.javaMatrix_lambdaTest3.javaMethodAndVariable.javMethodCall.javMethodCallTest.javaMethodEmpty.javMethodEmpty.javaMethodEmptyRetType.javMethodEmptyRetType.javaMethodsAndVariableTest.javaMultiClass.javMultiClassTest.javaNewArray.javNewClass.javNewClassTest.javaNewStatement.javNewStatementTest.javaOL.javOLTest.javaParameter.javParameterTest.javaPostDecrement.javPostDecrement.javaPostIncrement.javPostIncrement.javaReturn.javReturnTest.javaRunnable.javRunnableTest.javaSingleClassTester.javaSourceFileBytecodeTest.javaStringLitTest.javStringLitTest.javaSystemOutPrintln.javSystemOutPrintlnTest.javaTest.javaUninitializedVariable.javUninitializedVariableTest.javaVariable.javVariableMultimethods.javVariableMultimethodsTest.javaVariableTest.javaWhileTest.javWhileTest.javaasdf.java
lambda
main
operators
stackmaptable
types
parser
plugindevelopment
InsertSingleTypeTest.java
MartinTestCases
MethodTypeInsertTest.javMethodTypeInsertTest.javaMethodTypeInsertTestSolution.javParameterInsertTest.javaParameterTypeInsertTest.javParameterTypeInsertTestSolution.javSingleTypeInsertTest.javSyntaxTreeTests.javaTypeInsertSetEqualTest.javTypeInsertTester.java
TypeInsertTests
.LambdaTest2_3.jav.log.swpAdd.javAdd.javaAnalysis.txtBoundedGenericTest.javBoundedGenericsTest.javaConstructorTest.javConstructorTest.javaFunNInsertTest.javFunNInsertTest.javaFunVoid.javFunVoid.javaGenTypeTest.javGenTypeTest.javaGenericParaListInsertTest.javGenericParaListInsertTest.javaGenericParaListInsertTest2.javGenericParaListInsertTest2.javaGenericTypeVarTest.javGenericTypeVarTest.javaGenericTypeVarTest2.javGenericTypeVarTest2.javaGenericVarInsertTest.javGenericVarInsertTest.javaGenericVarTest.javGenericVarTest.javaGenericVarTest2.javGenericVarTest2.javaGenericVarTest3.javGenericVarTest3.javaId.javId.javaImportSubClassTest.javImportSubClassTest.javaImportTest.javImportTest.javaImportTest2.javImportTest2.javaIntTest.javIntTest.javaLambdaTest1.javLambdaTest1.javaLambdaTest10.javLambdaTest10.javaLambdaTest11.javLambdaTest11.javaLambdaTest12.javLambdaTest12.javaLambdaTest13.javLambdaTest13.javaLambdaTest14.javLambdaTest14.javaLambdaTest15.javLambdaTest15.javaLambdaTest16.javLambdaTest16.javaLambdaTest17.javLambdaTest17.javaLambdaTest18.javLambdaTest18.javaLambdaTest19.javLambdaTest19.javaLambdaTest2.javLambdaTest2.javaLambdaTest20.javLambdaTest20.javaLambdaTest21.javLambdaTest22.javLambdaTest23.javLambdaTest23.javaLambdaTest24.javLambdaTest24.javaLambdaTest25.javLambdaTest25.javaLambdaTest26.javLambdaTest26.javaLambdaTest27.javLambdaTest27.javaLambdaTest28.javLambdaTest28.javaLambdaTest29.javLambdaTest29.javaLambdaTest2_2.javLambdaTest2_2.javaLambdaTest2_3.javLambdaTest2_3.javaLambdaTest3.javLambdaTest3.javaLambdaTest30.javLambdaTest30.javaLambdaTest4.javLambdaTest4.javaLambdaTest5.javLambdaTest5.javaLambdaTest6.javLambdaTest6.javaLambdaTest7.javLambdaTest7.javaLambdaTest8.javLambdaTest8.javaLambdaTest9.javLambdaTest9.java
LargeSourceCodeTests
Matrix.javMatrix_simple.javMatrix_simple.javaMultipleTypesInsertTester.javaMutlitpleTestCases.javaOL.javOL.javaOperatorTest.javOperatorTest.javaOverloadingExample.javOverloadingExample.javaOverloadingInMethod.javOverloadingInMethod.javaOverloadingInMethod2.javOverloadingInMethod2.javaOverloadingInMethod2Simple.javOverloadingInMethod2Simple.javaOverloadingInsertTest.javOverloadingInsertTest.javaOverloadingRecursive.javOverloadingRecursive.javaOverloadingVector.javOverloadingVectorTest.javaRecursive.javRecursive2.javRelOpTest.javRelOpTest.javaReursiveTest.javaReursiveTest2.javaSuperTest.javSuperTest.javaTest1.javTest2.javThisTest.javThisTest.javaTypedMatrixSimpleTest.javTypedMatrixTest.javUnifyPaper.javUnifyPaper.javaUnifyPaper2.javUnifyPaper2.javaWildcardTestForLambda.javWildcardTestForLambda.javaWildcardTestForLambda2.javWildcardTestForLambda2.java
VariableTypeInsertTest.javVariableTypeInsertTest.javaVariableTypeInsertTestSolution.jav
syntaxTree
unify

@ -0,0 +1,3 @@
jvmDisassebler.class
*~*
*.class

@ -0,0 +1,18 @@
package de.dhbwstuttgart.JvmDisassembler;
class GenericsTest<a,b> {
Integer k;
GenericsTest<Integer,Integer> pp;
Object j;
a meth(a arg) {
return arg;
}
<t extends Integer> t meth2(b arg, t arg2) {
return arg2;
}
}

@ -0,0 +1,231 @@
package de.dhbwstuttgart.JvmDisassembler;
import java.util.*;
import java.io.*;
import de.dhbwstuttgart.typeinference.Menge;
//GenricsTest.java Testfile fuer jvmDisassembler
class jvmDisassembler {
static int makePosByte(int code) {
return (code & 0x7f | code & 0x80);
}
static int makePosShort(int code) {
return (code & 0x7fff | code & 0x8000);
}
static long makePosInt(long code) {
return (code & 0x7fffffff | code & 0x80000000);
}
static void parse_attribute(DataInputStream d, Menge<String> const_pool) throws IOException, Exception {
int attribut_count = d.readShort();
System.out.println("attribut_count = " + attribut_count);
if (attribut_count == 0) System.out.println("attributes = {}");
else {
for (int j = 0; j < attribut_count; j++) {
System.out.println("attribut[" + j + "] =\n{");
int attribut_name_index = d.readShort();
System.out.println("attribut_name_index = " + attribut_name_index
+ " //" + const_pool.elementAt(makePosShort(attribut_name_index)));
if (const_pool.elementAt(makePosShort(attribut_name_index)).equals("Code")) {
parse_code(d, const_pool);
int exception_table_length = d.readShort();
System.out.println("exception_table_length = " + exception_table_length);
if (exception_table_length == 0) System.out.println("exception_table = {}");
else throw new Exception("exceptiones not implemented");
parse_attribute(d, const_pool);
} else {
if ((const_pool.elementAt(makePosShort(attribut_name_index)).equals("Signature"))) {
long attribut_length = d.readInt();
System.out.println("attribut_length = " + attribut_length);
int sigdescriptor_index = d.readShort();
System.out.println("descriptor_index = " + sigdescriptor_index
+ " //" + const_pool.elementAt(makePosShort(sigdescriptor_index)));
} else {
long attribut_length = d.readInt();
System.out.println("attribut_length = " + attribut_length);
for(int ll = 0; ll < attribut_length; ll++) {
System.out.println(Integer.toHexString(makePosByte(d.readByte())));
}
System.out.println("}");
}
}
System.out.println("}");
}
}
}
static void parse_code(DataInputStream d, Menge<String> const_pool) throws IOException {
long attribut_length = d.readInt();
System.out.println("attribut_length = " + attribut_length);
int max_stack = d.readShort();
System.out.println("max_stack = " + max_stack);
int max_locals = d.readShort();
System.out.println("max_locals = " + max_locals);
long code_length = makePosInt(d.readInt());
System.out.println("code_length = " + code_length);
System.out.println("code =\n{");
int code;
int codenr = 1;
for(; codenr <= code_length;) {
//CODE VERVOLLSTAENDIGEN PL 06-04-01
code = makePosByte(d.readByte());
//System.out.println("DEBUG: " + Integer.toHexString(code));
switch(code) {
case 0x4: System.out.println(" " + codenr + " iconst_1");
codenr++;
break;
case 0x2a: System.out.println(" " + codenr + " aload_0");
codenr++;
break;
case 0x2b: System.out.println(" " + codenr + " aload_1");
codenr++;
break;
case 0x2c: System.out.println(" " + codenr + " aload_2");
codenr++;
break;
case 0xac: System.out.println(" " + codenr + " ireturn");
codenr++;
break;
case 0xb0: System.out.println(" " + codenr + " areturn");
codenr++;
break;
case 0xb1: System.out.println(" " + codenr + " return");
codenr++;
break;
case 0xb7: System.out.println(" " + codenr + " invokespecial " +
d.readShort());
codenr+=3;
break;
default: System.out.println(" " + Integer.toHexString(code));
codenr++;
break;
}
}
System.out.println("}");
}
public static void main (String[] args) throws FileNotFoundException, IOException, Exception {
DataInputStream d = new DataInputStream(new FileInputStream(new File (args[0])));
int magic = d.readInt();
System.out.println("magic = 0x " + Integer.toHexString(magic));
int minor = d.readShort();
System.out.println("minor_version = " + minor);
int major = d.readShort();
System.out.println("major_version = " + major);
//CONSTANT POOL START
int constant_pool_count = makePosShort(d.readShort());
System.out.println("constant_pool_count = " + constant_pool_count);
Menge<String> const_pool = new Menge<String>();
const_pool.addElement(""); // Konstatenpool beginnt bei 1, Stelle 0 auffuellen
System.out.println("constant_pool =\n{");
short constant_pool_tag;
for (int i = 1; i < constant_pool_count; i++) {
constant_pool_tag = d.readByte();
switch(constant_pool_tag) {
//Tags vervollstaendigen PL 06-04-01
case 1: System.out.print(i + "| tag = CONSTANT_Utf8, length = ");
int length = makePosShort(d.readShort());
System.out.print(length + ", ");
byte[] bytes = new byte[length];
d.read(bytes, 0, length);
System.out.println(new String(bytes));
const_pool.addElement(new String(bytes));
break;
case 7: System.out.println(i + "| tag = CONSTANT_Class, name_index = " + d.readShort());
const_pool.addElement("");
break;
case 10: System.out.println(i + "| tag = CONSTANT_Methodref, class_index = " +
d.readShort() + ", name_and_type_index = " + d.readShort());
const_pool.addElement("");
break;
case 12:System.out.println(i + "| tag = CONSTANT_NameAndType, name_index = " +
d.readShort() + ", descriptor_index = " + d.readShort());
const_pool.addElement("");
break;
}
}
//CONSTANT POOL END
int access_flags = d.readShort();
System.out.println("access_flags = " + access_flags);
int this_class = d.readShort();
System.out.println("this_class = " + this_class);
int super_class = d.readShort();
System.out.println("super_class = " + super_class);
//INTERFACE START
int interface_count = d.readShort();
System.out.println("interface_count = " + interface_count);
if (interface_count == 0) System.out.println("interfaces ={}");
else
//Interface implementieren PL 06-04-01
throw new Exception("no interfaces implemented");
//INTERFACE END
//FIELD START
int field_count = d.readShort();
System.out.println("field_count = " + field_count);
if (field_count == 0) System.out.println("fields = {}");
else {
for(int o = 1; o <= field_count; o++) {
System.out.println("field[" + o + "] =\n{");
int faccess_flags = d.readShort();
System.out.println("access_flags = " + faccess_flags);
int fname_index = d.readShort();
System.out.println("name_index = " + fname_index);
int fdescriptor_index = d.readShort();
System.out.println("descriptor_index = " + fdescriptor_index);
parse_attribute(d, const_pool);
System.out.println("}");
}
}
//FIELD END
//METHOD START
int method_count = makePosShort(d.readShort());
System.out.println("method_count = " + method_count);
if (method_count == 0) System.out.println("methods ={}");
else {
for(int i = 1; i <= method_count; i++) {
System.out.println("method[" + i + "] =\n{");
int maccess_flags = d.readShort();
System.out.println("access_flags = " + maccess_flags);
int mname_index = d.readShort();
System.out.println("name_index = " + mname_index);
int descriptor_index = d.readShort();
System.out.println("descriptor_index = " + descriptor_index);
parse_attribute(d, const_pool);
System.out.println("}");
}
}
//METHOD END
//FILE ATTRIBUTES START
parse_attribute(d, const_pool);
//FILE ATTRIBUTES END
}
}

@ -0,0 +1,89 @@
package de.dhbwstuttgart.bytecode;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
public class BytecodeTypeFactory {
/**
* @see https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-FieldType
*/
public static String generateFieldDescriptor(RefType t){
String ret = "";
if(t instanceof RefType){
ret += "L" + t.getName().toString().replace('.', '/') + ";";
}else{
throw new NotImplementedException();
}
return ret;
}
/**
* @see https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-ClassSignature
*/
public static String generateClassSignature(de.dhbwstuttgart.syntaxtree.Class c){
String ret = "";
if(c.getGenericParameter() != null && c.getGenericParameter().size() > 0){
ret += "<";
for(GenericTypeVar gtv : c.getGenericParameter()){
ret += generateTypeParameter(gtv);
}
ret += ">";
}
//Add the SuperClassSignature:
c.getSuperClass();
ret += generateClassTypeSignature();
return ret;
}
public static String generateSuperClassSignature(RefType superClass){
String ret = "";
//TODO:
throw new NotImplementedException();
}
private static String generateTypeParameter(GenericTypeVar gtv){
String ret = gtv.getName() + ":";
for(RefType t : gtv.getBounds()){
ret += generateReferenceTypeSignature(t);
ret += ":";
}
ret = ret.substring(0, ret.length()-1);
return ret;
}
/**
* @see https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-ClassTypeSignature
*/
private static String generateClassTypeSignature(){
return null;
}
/**
* @see https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-ReferenceTypeSignature
*/
private static String generateTypeSignature(RefType t){
if(t.isGenericType())return generateGenericTypeSignature(t);
return generateReferenceTypeSignature(t);
}
private static String generateReferenceTypeSignature(RefType t){
String ret = "L" + t.getName();
if(t.getParaList() != null && t.getParaList().size() > 0){
ret += "<";
for(RefType p : t.getParaList()){
ret += generateReferenceTypeSignature(p);
}
ret+=">";
}
return ret + ";";
}
private static String generateGenericTypeSignature(RefType t){
String ret = "T" + t.getName();
return ret + ";";
}
}

@ -0,0 +1,253 @@
package de.dhbwstuttgart.bytecode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.bcel.classfile.BootstrapMethod;
import org.apache.bcel.classfile.BootstrapMethods;
import org.apache.bcel.classfile.InnerClass;
import org.apache.bcel.classfile.InnerClasses;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.classfile.Signature;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import de.dhbwstuttgart.typecheck.JavaClassName;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.TypeinferenceResults;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
public class ClassGenerator extends ClassGen{
private DHBWConstantPoolGen cp;
private DHBWInstructionFactory factory;
private TypeinferenceResults tiResult;
private int lambdaMethodeNr = 0;
private Type superClass;
private List<GenericTypeVar> generics;
private Menge<TypePlaceholder> usedTPHs = new Menge<>();
private Map<String, ClassGenerator> extraClasses = new HashMap<>();
private List<String> methodsNamesAndTypes = new LinkedList<>();
private MethodGenerator methodGenerator;
public ClassGenerator(JavaClassName name, Type superClass, List<GenericTypeVar> generics,
String sourceFileName, short accessflags, String[] implementedInterfaces, TypeinferenceResults rs) {
super(name.toString(),superClass.get_Name(),sourceFileName,accessflags,implementedInterfaces, new DHBWConstantPoolGen());
//this.tiResult = typeinferenceResultSet;
this.superClass = superClass;
this.generics = generics;
tiResult = rs;
cp = (DHBWConstantPoolGen) super.getConstantPool();
factory = new DHBWInstructionFactory(this, cp);
this.setMajor(52); //Java 8 Version 52.0
this.setMinor(0);
}
public DHBWInstructionFactory getInstructionFactory() {
return factory;
}
/**
* Versucht einen Type zu finden von dem dieser TPH ein Subtyp sein muss.
* @param toTPH
* @return Es gilt dann "toTPH extends Type"
public org.apache.bcel.generic.Type getNearestUsedType(Type t, Menge<TypePlaceholder> usedTypes){
if(t == null){
return this.getInstructionFactory().createObjectType();
}else if(t instanceof TypePlaceholder){ //Es muss sich in diesem Fall um einen TPH handeln:
//return getNearestType((TypePlaceholder) t);
return new TypePlaceholderType((TypePlaceholder) t);
}else{
return t.getBytecodeType(this, getTypeinferenceResultSet().getTypeReconstructions().get(0));
}
}
public org.apache.bcel.generic.Type getNearestUsedType(TypePlaceholder toTPH){
return this.getNearestUsedType(toTPH, null);
}
*/
public String createLambdaMethodName() {
return "lambda$methode$"+(lambdaMethodeNr++);
}
@Override
public DHBWConstantPoolGen getConstantPool(){
return this.cp;
}
@Override
public void setConstantPool(ConstantPoolGen gen){
throw new DebugException("Ungültige Operation. ClassGenerator muss ein DHBWConstantPool besitzen");
}
private List<InnerClass> innerClasses = new ArrayList<>();
/**
* Anmerkung: Kann in diesem Zustand nur einmal aufgerufen werden.
* @param innerClassAttribute
*/
public void addInnerClass(InnerClass innerClassAttribute) {
for(InnerClass innerClass : innerClasses){
//Equal-Check:
if(innerClassCompare(innerClassAttribute, innerClass)){
return; //Ist die Innere Klasse bereits vorhanden, ist ein weiteres Anfügen nicht notwendig
}
}
innerClasses.add(innerClassAttribute);
}
/**
* Prüft die InnerClass Attribute a und b auf Gleichheit.
* Hierbei wird davon ausgegangen, dass beide den gleichen ConstantPool benutzen und dieser keine redundanten Einträge enthält
* @param a
* @param b
* @return
*/
private boolean innerClassCompare(InnerClass a, InnerClass b){
if(a.getInnerAccessFlags() != b.getInnerAccessFlags()){
return false;
}else if(a.getInnerClassIndex() != b.getInnerClassIndex()){
return false;
}else if(a.getInnerNameIndex() != b.getInnerNameIndex()){
return false;
}else if(a.getOuterClassIndex() != b.getOuterClassIndex()){
return false;
}
return true;
}
private List<BootstrapMethod> bootstrapMethods= new ArrayList<>();
public int addBootstrapMethod(BootstrapMethod bMethod) {
bootstrapMethods.add(bMethod);
return bootstrapMethods.size()-1;
}
public void addUsedTPH(TypePlaceholder tph){
if(! this.getUsedTPH().contains(tph, (a, b)->{
return a.get_Name().equals(b.get_Name()); //Vergleich auf Namensgleichheit. Was anderes zählt im Bytecode nicht
}))
{ //Nur wenn noch nicht vorhanden anfügen:
this.usedTPHs.add(tph);
}
}
public Menge<TypePlaceholder> getUsedTPH() {
return usedTPHs;
}
@Override
public JavaClass getJavaClass() {
//Hier werden die letzten Schritte vor der Klassengenerierung ausgeführt:
//Signatur setzen:
String typeParameters = this.generateParameterSignature();
String superClassSignature = BytecodeTypeFactory.generateSuperClassSignature(this.superClass);//"L" + this.superClass.getBytecodeType(cg, rs)
superClassSignature = superClassSignature.substring(0, superClassSignature.length()-1); //Das ";" am Ende entfernen
if(this.superClass instanceof RefType &&
((RefType)superClass).get_ParaList() != null &&
((RefType)superClass).get_ParaList().size() > 0){
superClassSignature += "<";
RefType superRefType = (RefType) this.superClass;
for(Type param : superRefType.get_ParaList()){
superClassSignature += param.getBytecodeSignature(this, null);
}
superClassSignature += ">;";
}
String classSignature = typeParameters + superClassSignature; //TOOD: Hier noch die Signaturen der SuperInterfaces anfügen
if(classSignature.length()>0){
this.addAttribute(new Signature(cp.addUtf8("Signature"),2,cp.addUtf8(classSignature),cp.getConstantPool()));
}
//InnerClass Attribut hinzufügen:
int innerClassesUTF8 = this.getConstantPool().addUtf8("InnerClasses");
this.addAttribute(new InnerClasses(innerClassesUTF8,innerClasses.size()*8+2,
innerClasses.toArray(new InnerClass[innerClasses.size()]),this.getConstantPool().getConstantPool()));
//Bootstrap Methoden generieren:
int name_index = this.getConstantPool().addUtf8("BootstrapMethods");
int length = 2 + bootstrapMethods.size() * 4;// + bMethod.getNumBootstrapArguments() * 2;
for(BootstrapMethod bMethod : bootstrapMethods){
length += 2 * bMethod.getNumBootstrapArguments();
}
BootstrapMethod[] bootstrap_methods = bootstrapMethods.toArray(new BootstrapMethod[bootstrapMethods.size()]);
BootstrapMethods bootstrapAttribute = new BootstrapMethods(name_index, length, bootstrap_methods, this.getConstantPool().getConstantPool());
this.addAttribute(bootstrapAttribute);
return super.getJavaClass();
}
private String generateParameterSignature(){
String ret = "";
//ret += "L" + this.getClassName().replace(".", "/") + ";";
if(this.generics != null && this.generics.size() > 0){
ret += "<";
for(GenericTypeVar gtv : this.generics){
ret += gtv.getBytecodeSignature(this, tiResult.getTypeReconstructions().get(0));
}
ret += ">";
}
/*
if(this.getUsedTPH().size()>0){
ret += "<";
Iterator<TypePlaceholder> it = ((Menge<TypePlaceholder>)this.getUsedTPH().clone()).iterator();
while(it.hasNext()){
TypePlaceholder tph = it.next();
//ret += tph.getBytecodeMethodSignature(this);
//ret += ":";
ret += tph.getClassSignature(this, null); //Es wird null übergeben. Die ClassSignaturen dürfen von keinem ResultSet abhängen.
}
ret += ">";
}
*/
return ret;
}
public void addExtraClass(ClassGenerator cg){
extraClasses.put(cg.getClassName(), cg);
}
public Map<String, ClassGenerator> getExtraClasses() {
return extraClasses;
}
/*
public TypeinferenceResults getTypeinferenceResultSet() {
return tiResult;
}
*/
@Override
public void addMethod(Method m) {
//TODO: Die Prüfung, ob Methode bereits vorhanden vor die Bytecodegenerierung verlegen (Beispielsweise in Method)
String methodNameAndTypes = m.getReturnType().toString()+";"+m.getName()+"("+Arrays.toString(m.getArgumentTypes());
if(methodsNamesAndTypes.contains(methodNameAndTypes)){
return;
}
methodsNamesAndTypes.add(methodNameAndTypes);
super.addMethod(m);
}
public void setMethodeGenerator(MethodGenerator methodGenerator) {
this.methodGenerator = methodGenerator;
}
public MethodGenerator getMethodGenerator() {
return methodGenerator;
}
}

@ -0,0 +1,36 @@
package de.dhbwstuttgart.bytecode;
import java.util.HashMap;
import org.apache.bcel.classfile.Constant;
import org.apache.bcel.classfile.ConstantMethodHandle;
import org.apache.bcel.classfile.ConstantMethodType;
import org.apache.bcel.generic.ConstantPoolGen;
public class DHBWConstantPoolGen extends ConstantPoolGen{
private static final long serialVersionUID = -8282768548793548585L;
private final HashMap<Constant, Integer> constantTable = new HashMap<>();
//private static final String DELIMITER = "$";
/*
public int addConstantMethodType(ConstantMethodType methodType) {
if(constantTable.containsKey(methodType))return constantTable.get(methodType);
}
public int addConstantMethodHandle(ConstantMethodHandle methodHandle) {
if(constantTable.containsKey(methodHandle))return constantTable.get(methodHandle);
int ret = this.index;
return ret;
}
*/
public int addConstant(Constant c){
if(constantTable.containsKey(c))return constantTable.get(c);
int ret = this.index;
this.constants[this.index++] = c;
constantTable.put(c, ret);
return ret;
}
}

@ -0,0 +1,70 @@
package de.dhbwstuttgart.bytecode;
import java.awt.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.apache.bcel.Constants;
import org.apache.bcel.classfile.Attribute;
import org.apache.bcel.classfile.BootstrapMethod;
import org.apache.bcel.classfile.ConstantInvokeDynamic;
import org.apache.bcel.classfile.ConstantMethodHandle;
import org.apache.bcel.classfile.ConstantMethodType;
import org.apache.bcel.classfile.InnerClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.classfile.Signature;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.INVOKEDYNAMIC;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.LocalVariableInstruction;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.Type;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.ParameterList;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.statement.Return;
import de.dhbwstuttgart.syntaxtree.type.FunN;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
public class DHBWInstructionFactory extends InstructionFactory{
private DHBWConstantPoolGen cp;
private ClassGenerator cg;
private static Map<String, Integer> storeIndexes = new HashMap<>();
public DHBWInstructionFactory(ClassGenerator cg, DHBWConstantPoolGen cp) {
super(cg, cp);
this.cp = cp;
this.cg = cg;
}
/**
*
* @param interfaceMethodName - Momentan immer "apply"
* @param invokeDynamicMethodType - Der Typ der Methode, welche Dynamisch aufgerufen werden soll
* @return
*/
public INVOKEDYNAMIC createInvokeDynamic( String interfaceMethodName, String invokeDynamicMethodType, BootstrapMethod bMethod) {
int bootstrap_method_attr_index = cg.addBootstrapMethod(bMethod);
int invokeDynamicFunktionstyp = cp.addNameAndType(interfaceMethodName, invokeDynamicMethodType);
ConstantInvokeDynamic cInvokeDynamic = new ConstantInvokeDynamic(bootstrap_method_attr_index, invokeDynamicFunktionstyp);
int index = cp.addConstant(cInvokeDynamic);
return new INVOKEDYNAMIC(index);
}
public static Type createObjectType() {
return new org.apache.bcel.generic.ObjectType("java.lang.Object");
}
public Attribute createSignatureAttribute(String signature) {
return new Signature(cp.addUtf8("Signature"),2,cp.addUtf8(signature),cp.getConstantPool());
}
}

@ -0,0 +1,132 @@
package de.dhbwstuttgart.bytecode;
import java.awt.List;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
import org.apache.bcel.classfile.Attribute;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.ConstantUtf8;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.classfile.Signature;
import org.apache.bcel.classfile.StackMap;
import org.apache.bcel.classfile.StackMapEntry;
import org.apache.bcel.classfile.Visitor;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.LocalVariableInstruction;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.StackMapTableGen;
import org.apache.bcel.generic.Type;
import org.apache.bcel.Const;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.logger.Section;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.ParameterList;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.statement.Return;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
public class MethodGenerator extends MethodGen{
private Map<String, Integer> storeIndexes = new HashMap<>();
public MethodGenerator(int access_flags, Type return_type, Type[] arg_types, String[] arg_names, String method_name,
String class_name, InstructionList il, ConstantPoolGen cp) {
super(access_flags, return_type, arg_types, arg_names, method_name, class_name, il, cp);
for(String name: arg_names){
getStoreIndex(name);
}
}
public Method createMethod(ClassGenerator cg, ParameterList parameter, de.dhbwstuttgart.syntaxtree.type.Type retType,
Block block, TypeinferenceResultSet rs){
MethodGen method = this;
DHBWInstructionFactory factory = cg.getInstructionFactory();
InstructionList blockInstructions = block.genByteCode(cg, rs);
InstructionList il = this.getInstructionList();
il.append(blockInstructions);//Die vom Block generierten Instructions an die InstructionList der Methode anfügen
//Ein return Statement anfügen, falls nicht vorhanden:
//TODO: Das ist schlecht! Der Parser oder der Typinferenzalgorithmus muss dafür sorgen, dass sich in jeder Methode ein Return befindet.
if (block.get_Statement().size() == 0) { il.append(factory.createReturn( org.apache.bcel.generic.Type.VOID)); }
else {
java.util.List<Statement> stmts = block.get_Statement();
if (!(stmts.get(stmts.size()-1) instanceof Return) &&
this.getType().equals(org.apache.bcel.generic.Type.VOID)) {
il.append(factory.createReturn( org.apache.bcel.generic.Type.VOID));
}
}
method.getInstructionList().setPositions();
method.stripAttributes(true);
method.setMaxStack(); //Die Stack Größe automatisch berechnen lassen (erst nach dem alle Instructions angehängt wurden)
method.setMaxLocals();
//Die korrekte Signatur für die Methode anhängen. Hier sind dann auch die Parameter von RefTypes enthalten:
String methodDescriptor = getMethodDescriptor(parameter, retType, cg, rs);
method.addAttribute(factory.createSignatureAttribute(methodDescriptor));
System.out.println(this.getInstructionList().size());
StackMap stackMap = new StackMapTableGen(this, cp).getStackMap();
if(stackMap != null)method.addCodeAttribute(stackMap);
return method.getMethod();
}
/**
* Erstellt den Deskriptor für eine Method mit den angegebenen Parametern und Return Typ.
* Dies ist eine optionale Angabe im java Bytecode und enthält im Gegensatz zur Signatur der Methode auch Generics.
* @param parameter
* @param returnType
* @param cg
* @param rs
* @return
*/
public static String getMethodDescriptor(ParameterList parameter, de.dhbwstuttgart.syntaxtree.type.Type returnType, ClassGenerator cg, TypeinferenceResultSet rs){
String paramTypesSig = "(";
for(FormalParameter p : parameter){
paramTypesSig += p.getType().getBytecodeSignature(cg, rs);
//Logger.getLogger("MethodGenerator").error(paramTypesSig, Section.CODEGEN);
}
paramTypesSig += ")";
String retTypeSig = returnType.getBytecodeSignature(cg, rs);
return paramTypesSig+retTypeSig;
}
public LocalVariableInstruction createLoad(org.apache.bcel.generic.Type bytecodeType, String variableName) {
return InstructionFactory.createLoad(bytecodeType, getStoreIndex(variableName));
}
public LocalVariableInstruction createStore(org.apache.bcel.generic.Type bytecodeType, String variableName) {
return InstructionFactory.createStore(bytecodeType, getStoreIndex(variableName));
}
public Integer getStoreIndex(String variableName) {
if(storeIndexes.get(variableName) == null){
Integer index = storeIndexes.size()+1;
storeIndexes.put(variableName, index);
}
return storeIndexes.get(variableName);
}
}

@ -0,0 +1,22 @@
package de.dhbwstuttgart.bytecode;
import org.apache.bcel.Constants;
import org.apache.bcel.generic.ReferenceType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
public class TypePlaceholderType extends ReferenceType{
private final TypePlaceholder tph;
public TypePlaceholderType(TypePlaceholder tph) {
super(Constants.T_REFERENCE, "T" + tph.get_Name() + ";");
this.tph = tph;
if(this.tph == null)throw new NullPointerException();
}
public TypePlaceholder getTPH() {
return tph;
}
}

@ -0,0 +1,16 @@
package de.dhbwstuttgart.bytecode;
import org.apache.bcel.Constants;
import org.apache.bcel.classfile.Utility;
import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.ReferenceType;
import org.apache.bcel.generic.Type;
public class WildcardType extends ReferenceType{
public WildcardType(String class_name, String preString) {
super(Constants.T_REFERENCE, preString + "L" + class_name.replace('.', '/') + ";");
//this.type = Constants.T_UNKNOWN;
}
}

@ -3,6 +3,66 @@ package de.dhbwstuttgart.core;
import java.util.*;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.logger.LoggerConfiguration;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException;
public class ConsoleInterface {
private static final String directory = System.getProperty("user.dir");
private static final Logger log = Logger.getLogger( ConsoleInterface.class.getName() );
/**
* @param args
*/
public static void main(String[] args) {
Menge<String> filenames = new Menge<String>();
for(String file : args){
filenames.add(file);
}
Logger.setStandardConfiguration(new LoggerConfiguration()); // sämtliches Logging unterdrücken
run(filenames);
}
public static void run(Menge<String> filenames){
Menge<TypeinferenceResultSet> resultSet = null;
MyCompilerAPI compiler = MyCompiler.getAPI(new LoggerConfiguration());
try{
/////////////////////////
// Parsen:
/////////////////////////
Menge<SourceFile> sourceFiles = compiler.parse(filenames);
/////////////////////////
// Typrekonstruktion:
/////////////////////////
try{
resultSet = compiler.typeReconstruction(sourceFiles);
}catch(TypeinferenceException texc){
texc.printStackTrace();
throw new DebugException("Fehler bei Typinferenzalgorithmus. Message: "+texc.getMessage());
}
///////////////////////
// Ausgabe:
///////////////////////
if(resultSet == null)System.out.println("Keine Lösung!");
ArrayList<String> resultJavaCodes = new ArrayList<String>();
for(TypeinferenceResultSet result : resultSet){
String javaCode = result.getInterferedClass().printJavaCode(result);
if(!resultJavaCodes.contains(javaCode))resultJavaCodes.add(javaCode);
}
for(String out : resultJavaCodes){
System.out.println("\nMögliche Typisierung:\n\n");
System.out.println(out);
}
}catch(Exception e){
e.printStackTrace();
if(resultSet == null)throw new DebugException("Fehler bei Typinferenzalgorithmus. Message: "+e.getMessage());
}
}
}

@ -3,4 +3,5 @@ package de.dhbwstuttgart.core;
public interface IItemWithOffset
{
public int getOffset();
}

@ -1,10 +1,285 @@
package de.dhbwstuttgart.core;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
public class MyCompiler {
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.logger.LoggerConfiguration;
import de.dhbwstuttgart.logger.Section;
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.ClassBody;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.ParameterList;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.IMatchable;
import de.dhbwstuttgart.syntaxtree.type.ITypeContainer;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.ByteCodeResult;
import de.dhbwstuttgart.typeinference.FunNInterface;
import de.dhbwstuttgart.typeinference.FunVoidNInterface;
import de.dhbwstuttgart.typeinference.Pair;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResults;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
import de.dhbwstuttgart.typeinference.exceptions.ParserError;
import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException;
public class MyCompiler implements MyCompilerAPI{
// PL: Der Zusammenhang zwischen paralist und vParaOrg muesste
// noch geklaert werden 05-01-07
public static final int NO_LINENUMBER = -1;
protected static Logger inferencelog = Logger.getLogger(MyCompiler.class.getName());
protected String OutputDir = "";
public Menge<Pair> testPair = null;
/**
* Author: J�rg B�uerle<br/>
* Der private Konstruktor. Es soll von au�en kein Compiler angelegt werden
* k�nnen, sondern nur eine API zur Verf�gung gestellt werden.
* @param logger Konfiguration für Debug Ausgabe TODO
*/
private MyCompiler(){
this.init();
}
/**
* Author: Jörg Bäuerle<br/>
* Stellt eine neue Instanz der CompilerAPI zur Verf�gung.
* Diese Methode sollte von der IDE aus aufgerufen werden,
* um eine Quellcode-Datei zu kompilieren.
* @return Die Compiler-API
*/
public static MyCompilerAPI getAPI(LoggerConfiguration loggerConfig){
Logger.setStandardConfiguration(loggerConfig);
return new MyCompiler();
}
/**
* Parst den Quellcode und baut den abstrakten Syntaxbaum auf. Danach wird
* automatisch der von Thomas Ott implementierte Algorithmus
* <code>NewTVar(jclass)</code> (siehe Algorithmus 5.17 TRProg, Martin Pl�micke)
* aufgerufen.
* <br/>Author: J�rg B�uerle
* @param reader
* @throws IOException
* @throws JavaParser.yyException
*/
private void parse_backup(Reader reader) throws IOException, JavaParser.yyException{
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Implementierte API-Methoden:
/////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Author: J�rg B�uerle<br/>
* Initialisiert den Compiler
*/
public void init(){
TypePlaceholder.deleteRegistry();
}
/**
* Author: J�rg B�uerle<br/>
* Ruft die Parse-Methode.
* @param file Die Quellcode-Datei
* @throws FileNotFoundException Wenn die Quellcode-Datei nicht existiert.
* @throws IOException Wenn was schief l�uft.
* @throws JavaParser.yyException Wenn ein Fehler beim Parsen auftritt.
*/
public SourceFile parse(File file) throws FileNotFoundException, IOException, JavaParser.yyException{
FileReader fr = new FileReader(file);
SourceFile ret = this.parse2SyntaxTree(fr);
fr.close();
return ret;
}
/**
* Author: J�rg B�uerle<br/>
* Ruft den Typrekonstruktionsalgorithmus auf.
* @return Die Menge aller m�glichen Typkombinationen
* @throws NullPointerException Wenn noch kein abstrakter Syntaxbaum vorhanden
* ist. @throws CTypeReconstructionException Wenn ein Fehler bei der
* Typrekonstruktion auftritt.
*/
public Menge<TypeinferenceResultSet> typeReconstruction(Menge<SourceFile> m_AbstractSyntaxTree) throws NullPointerException{
inferencelog.info("##########################################", Section.TYPEINFERENCE);
inferencelog.info("# TypeReconstruction-Algorithmus - START #", Section.TYPEINFERENCE);
inferencelog.info("##########################################\n", Section.TYPEINFERENCE);
TypeAssumptions globalAssumptions = makeFunNAssumptions();
Menge<TypeinferenceResultSet> result = new Menge<TypeinferenceResultSet>();
for(SourceFile srcFile : m_AbstractSyntaxTree){
result.addAll(srcFile.typeReconstruction(globalAssumptions));
}
inferencelog.info("#########################################", Section.TYPEINFERENCE);
inferencelog.info("# TypeReconstruction-Algorithmus - ENDE #", Section.TYPEINFERENCE);
inferencelog.info("#########################################\n", Section.TYPEINFERENCE);
return result;
}
/**
* Erstellt die FunN-Assumptions
* Fun0-FunN (momentan für N = 6)
* @return
*/
public static TypeAssumptions makeFunNAssumptions(){
TypeAssumptions ret = new TypeAssumptions();
//Basic Assumptions für die FunN Interfaces:
//TODO: Hier mehr als Fun1-Fun5 implementieren
for(int i = 0; i<6; i++){
FunNInterface funN = new FunNInterface(i);
ret.add(funN.getPublicFieldAssumptions());
}
for(int i = 0; i<6; i++){
FunVoidNInterface funN = new FunVoidNInterface(i);
ret.add(funN.getPublicFieldAssumptions());
}
return ret;
}
/**
* Die Main-Funktion, �ber die der Compiler auch per Konsole gestartet
* werden kann.
* @param args Klassendatei
*/
public static void main(String[] args){
MyCompilerAPI compiler = MyCompiler.getAPI(new LoggerConfiguration());
// Hier koennten ggf. Aenderungen der Ausgabeeinstellungen
// (Debuginfos) vorgenommen werden -> LOG4J
try {
compiler.parse(new File(args[0]));
} catch (FileNotFoundException e) {
System.err.println("Die Datei \""+args[0]+"\" konnte nicht gefunden werden.");
System.exit(0);
} catch (IOException e) {
System.err.println("Fehler beim Parsen:");
System.err.println(e);
System.exit(0);
} catch (yyException e) {
System.err.println("Fehler beim Parsen:");
System.err.println(e);
System.exit(0);
}
}
public void setOutputDir(String dir){
char c = dir.charAt(dir.length()-1);
if (c != '/' & c != '\\') dir = dir + "/";
OutputDir = dir;
// Verzeichnis(se) ggf. anlegen
File f = new File(dir);
f.mkdirs();
}
public String getOutputDir(){
return OutputDir;
}
/**
* Parst den Inhalt einer Datei zu einem Syntaxbaum.
*/
private SourceFile parse2SyntaxTree(Reader fileContent) throws ParserError{
//StringReader reader = new StringReader(fileContent);
//////////////////////////////////////
// Scanner und Parser erzeugen:
//////////////////////////////////////
Scanner scanner = new Scanner(fileContent);
JavaParser parser = new JavaParser();
//////////////////////////////////////
// Parsen ==> Ergebnis: srcFile
//////////////////////////////////////
SourceFile srcFile = null;
try {
srcFile = (SourceFile) parser.yyparse( scanner );
} catch (IOException | yyException e) {
e.printStackTrace();
if(e instanceof yyException)throw new ParserError((yyException)e);
}
//////////////////////////////////////
// Postprocessing:
//////////////////////////////////////
srcFile.parserPostProcessing(null); //Muss mit null aufgerufen werden.
//Fertig:
return srcFile;
}
/**
* Diese Funktion nimmt einen Menge von Dateinamen. Alle diese Dateien werden zu einem SyntaxBaum geparst.
* @return
*/
public Menge<SourceFile> parse(Menge<String> filenames) throws ParserError {
Menge<SourceFile> m_AbstractSyntaxTree = new Menge<SourceFile>();
for(String filename : filenames){
StringBuffer fileData = new StringBuffer();
BufferedReader reader;
try {
reader = new BufferedReader(
new FileReader(filename));
} catch (FileNotFoundException e) {
throw new DebugException("Die Datei "+ filename+" konnte nicht gelesen werden.");
}
char[] buf = new char[1024];
int numRead=0;
try {
while((numRead=reader.read(buf)) != -1){
String readData = String.valueOf(buf, 0, numRead);
fileData.append(readData);
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
StringReader srcreader = new StringReader(fileData.toString());
//Den aus der Datei ausgelesenen Quellcode zu einem Syntaxbaum parsen:
m_AbstractSyntaxTree.add(parse2SyntaxTree(srcreader)); // Alle Dateien nacheinander hintereinander anhängen...
}
return m_AbstractSyntaxTree;
}
@Override
public SourceFile parse(String sourceCode) {
return parse2SyntaxTree(new StringReader(sourceCode));
}
@Override
public Menge<ByteCodeResult> generateBytecode(Menge<SourceFile> m_AbstractSyntaxTree, TypeinferenceResults typeinferenceResults) {
//SourceFile parsedFile = this.m_AbstractSyntaxTree.firstElement();
//Class parsedClass = parsedFile.KlassenVektor.firstElement();
Menge<ByteCodeResult> ret = new Menge<>();
for(SourceFile sf : m_AbstractSyntaxTree){
ret.addAll(sf.generateBytecode(typeinferenceResults));
}
return ret;
}
}

@ -1,5 +1,19 @@
package de.dhbwstuttgart.core;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.parser.JavaParser;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.typeinference.ByteCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResults;
import de.dhbwstuttgart.typeinference.exceptions.ParserError;
import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException;
/**
* Schnittstellen-Klasse zum Compiler. Diese Klasse soll der
* IDE als Compiler-API zum Kompilieren einer Quellcode-Datei
@ -16,4 +30,69 @@ public interface MyCompilerAPI
* Initialisiert den Compiler
*/
public void init();
/**
* Author: Jörg Bäuerle<br/>
* Parst eine Quellcodedatei und baut den abstrakten Syntaxbaum auf.
* @param file Die Quellcode-Datei
* @throws FileNotFoundException Wenn die Quellcode-Datei nicht existiert.
* @throws IOException Wenn was schief läuft.
* @throws JavaParser.yyException Wenn ein Fehler beim Parsen auftritt.
*/
public SourceFile parse(File file)
throws FileNotFoundException, IOException, JavaParser.yyException;
/**
* Author: Jörg Bäuerle<br/>
* Parst einen String und baut den abstrakten Syntaxbaum auf.
* @param srcCode Der zu parsende Quellcode
* @throws IOException Wenn was schief läuft.
* @throws JavaParser.yyException Wenn ein Fehler beim Parsen auftritt.
public void parse(String srcCode)
throws IOException, JavaParser.yyException;
*/
/**
* Author: Jörg Bäuerle<br/>
* Ruft den Typrekonstruktionsalgorithmus auf.
* @return Die Menge aller möglichen Typkombinationen
* @throws NullPointerException Wenn noch kein abstrakter Syntaxbaum vorhanden
* ist. @throws CTypeReconstructionException Wenn ein Fehler bei der
* Typrekonstruktion auftritt.
*/
public Menge<TypeinferenceResultSet> typeReconstruction(Menge<SourceFile> m_AbstractSyntaxTree) throws NullPointerException;
/**
* Author: Juergen Schmiing <br>
* Legt das Ausgabeverzeichnis fuer die class-Files fest.
*/
public void setOutputDir(String dir);
/**
* Author: Juergen Schmiing <br>
* Gibt das Ausgabeverzeichnis fuer die class-Files zurueck.
*/
public String getOutputDir();
/**
* Parst zusammenhängende JavaKlassen in verschiedenen Dateien.
* @param filenames - Eine Liste von Quellcodedateien, welche gseparst werden sollen
* @return
*/
public Menge<SourceFile> parse(Menge<String> filenames) throws ParserError;
/**
* Parst den SourceCode einer Datei.
* @param sourceCode - SourceCode einer Java-Quellcodedatei
* @return den aus dem sourceCode generierten Syntaxbaum
*/
public SourceFile parse(String sourceCode) throws ParserError;
/**
* Generiert für jede geparste Klasse im SourceFile ein ByteCodeResult.
* Dafür müssen die Schritte Parsen und typeReconstruction ausgeführt werden.
* @return
*/
public Menge<ByteCodeResult> generateBytecode(Menge<SourceFile> m_AbstractSyntaxTree, TypeinferenceResults typeinferenceResults);
}

@ -0,0 +1,165 @@
package de.dhbwstuttgart.logger;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
public class Logger {
private static LoggerConfiguration standardConfiguration = null;
private static final HashMap<String, Logger> LOGGER_DIRECTORY = new HashMap<>();
private String name;
private final HashMap<Section, java.util.logging.Logger> logger;
private static final LogHistory LOG_HISTORY = new LogHistory();
protected Logger(String name, LoggerConfiguration config) {
this.name = name;
this.logger = new HashMap<>();
if(config != null){
config.forEach((s,o)->{
java.util.logging.Logger log = java.util.logging.Logger.getLogger( name );
log.setLevel(Level.FINE);
log.addHandler(new OutputHandler(o));
logger.put(s, log);
});
}
}
/**
* Logt eine Debug Message, welche zusätzlich einer bestimmten Section zugewiesen wird.
* Dadurch lässt sich die DEBUG ausgabe übersichtlicher gestalten.
* @param message
* @param section
*/
public void debug(String message, Section section){
output(message, Level.FINE, section);
}
/**
* Liefert den Logger mit dem angegebenen Namen.
* Üblicherweise wird diese Methode mit dem Namen der Klasse aufgerufen, in welcher der Logger tätig ist.
* @param name - Name der Klasse ( Ermittelbar mittels <Klasse>.class.getName() )
* @return
*/
public static Logger getLogger(String name) {
Logger ret;
if(LOGGER_DIRECTORY.containsKey(name)){
ret = LOGGER_DIRECTORY.get(name);
}else{
ret = new Logger(name, standardConfiguration);
LOGGER_DIRECTORY.put(name, ret);
}
return ret;
}
public static SectionLogger getSectionLogger(String name, Section s) {
Logger ret;
if(LOGGER_DIRECTORY.containsKey(name)){
ret = LOGGER_DIRECTORY.get(name);
}else{
ret = new Logger(name, standardConfiguration);
LOGGER_DIRECTORY.put(name, ret);
}
return new SectionLogger(ret,s);
}
protected void output(String msg , Level logLevel, Section section){
Logger.LOG_HISTORY.add(new LogLine(msg, this.name, section, logLevel));
if(logger.containsKey(section)){
java.util.logging.Logger log = logger.get(section);
log.log(logLevel, msg);
}
}
public void info(String message, Section s) {
output(message, Level.INFO, s);
}
public void error(String message, Section s) {
output(message, Level.WARNING, s);
}
/**
* wird hier null übergeben, so wird sämtliches Logging unterdrückt.
*/
public static void setStandardConfiguration(LoggerConfiguration config) {
Logger.standardConfiguration = config;
}
public static String getWholeLog(){
String ret = "";
LOG_HISTORY.removeIf((logLine)->logLine==null);
Logger.LOG_HISTORY.sort((log1, log2)->log1.timestamp.compareTo(log2.timestamp));
ret += Logger.LOG_HISTORY.toString();
return ret;
}
}
class OutputHandler extends Handler{
private PrintStream output;
public OutputHandler(PrintStream output){
this.output = output;
}
@Override
public void publish(LogRecord record) {
output.println(record.getMessage());
}
@Override
public void flush() {
}
@Override
public void close() throws SecurityException {
}
}
class LogHistory extends ArrayList<LogLine>{
private static final long serialVersionUID = -1785228323497318261L;
@Override
public String toString(){
StringBuilder ret = new StringBuilder();
for(LogLine l : this){
ret.append(l.toString() + "\n");
}
return ret.toString();
}
}
class LogLine {
Date timestamp;
String message;
String name;
Section section;
Level level;
LogLine(String msg, String loggerName, Section section, Level logLevel){
this.timestamp = new Date();
this.message = msg;
this.name = loggerName;
this.section = section;
this.level = logLevel;
}
public String toString(){
String ret = "";
ret += name + ": ";
ret += message;
ret += " - " + section.name();
return ret;
}
public String toJSON(){
return "";
}
}

@ -0,0 +1,48 @@
package de.dhbwstuttgart.logger;
import java.io.PrintStream;
import java.util.HashMap;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
public class LoggerConfiguration{
private final HashMap<Section,Menge<PrintStream>> outputs = new HashMap<>(Section.values().length);
public LoggerConfiguration setOutput(Section forSection, PrintStream output){
if(outputs.containsKey(forSection)){
//throw new DebugException("Eine outputStream für Section "+forSection+" ist bereits vorhanden");
if(outputs.get(forSection).equals(output)){
//do nothing
}else{
outputs.get(forSection).add(output);
}
}else{
Menge<PrintStream> outMenge = new Menge<>();
outMenge.add(output);
outputs.put(forSection, outMenge);
}
return this;
}
public void forEach(ConfigurationEvaluater action){
for(Section key : outputs.keySet()){
for(PrintStream out : outputs.get(key)){
action.apply(key, out);
}
}
}
public void mergeConfiguration(LoggerConfiguration config){
for(Section key : config.outputs.keySet()){
for(PrintStream out : config.outputs.get(key)){
this.setOutput(key, out);
}
}
}
}
interface ConfigurationEvaluater {
public void apply(Section s, PrintStream o);
}

@ -0,0 +1,8 @@
package de.dhbwstuttgart.logger;
public enum Section {
TYPEINFERENCE,
PARSER,
CODEGEN,
UNIFY, FINITECLOSURE, ASSUMPTIONS;
}

@ -0,0 +1,26 @@
package de.dhbwstuttgart.logger;
import java.util.logging.Level;
/**
* Sämtliche Logging Ausgaben werden in die bei der Erstellung des Loggers übergebene Section eingeteilt
* @author janulrich
*
*/
public class SectionLogger {
private Logger log;
private Section section;
protected SectionLogger(Logger logger, Section s){
this.log = logger;
this.section = s;
}
public void debug(String message){
log.debug(message, section);
}
public void info(String string) {
log.info(string, section);
}
public void error(String string) {
log.error(string, section);
}
}

@ -0,0 +1,50 @@
package de.dhbwstuttgart.logger;
import java.util.Stack;
public class Timestamp{
String name;
Stack<Long> timestamps = new Stack<>();
Long accumulatedTime = 0L;
Timestamp(String name){
this.name = name;
}
public void start(){
timestamps.push(System.currentTimeMillis());
}
public Long stop(){
if(timestamps.isEmpty())return 0L;
Long timeStart = timestamps.pop();
Long currentTime = getTime();
Long difference = currentTime-timeStart;
accumulatedTime += difference;
return difference;
}
public Long currentTime(){
if(timestamps.isEmpty())return 0L;
Long timeStart = timestamps.peek();
Long currentTime = getTime();
return currentTime-timeStart;
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof Timestamp))return false;
return this.name.equals(((Timestamp)obj).name);
}
public String toString(){
String ret = "Zeit für Aktivität "+this.name+": "+this.accumulatedTime;
return ret;
}
private Long getTime(){
return System.currentTimeMillis();
}
}

@ -0,0 +1,74 @@
package de.dhbwstuttgart.logger;
import java.util.HashMap;
import java.util.Stack;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
public class Timewatch {
private static final Timewatch time = new Timewatch();
private final Timestamp startTime;
private Timers timers = new Timers();
private Timewatch(){
//Privater Konstruktor
startTime = new Timestamp("Timewatch Global");
startTime.start();
}
public static Timewatch getTimewatch() {
return time;
}
public String dumpTimeData(){
String ret = "Momentan insgesamt verstrichene Zeit: "+this.startTime.currentTime() +"\n";
ret += timers.toString();
return ret;
}
public Timestamp start(String name){
if(!timers.contains(name)){
Timestamp ret = new Timestamp(name);
timers.add(ret);
ret.start();
return ret;
}else{
//Timer läuft noch... einfach neue Instanz starten:
Timestamp ret = timers.get(name);
ret.start();
return ret;
}
}
}
class Timers{
private Menge<Timestamp> timers = new Menge<>();
public Timestamp get(String name) {
for(Timestamp timer:timers){
if(timer.name.equals(name))return timer;
}
throw new DebugException("Fehler in Timewatch: Der gesuchte Timer "+name+" ist nicht vorhanden.");
}
public void add(Timestamp timer) {
timers.add(timer);
}
public boolean contains(String name) {
return timers.contains(new Timestamp(name));
}
public String toString(){
String ret ="";
for(Timestamp timer : timers){
ret += timer.toString() + "\n";
}
return ret;
}
}

@ -1,8 +1,7 @@
package de.dhbwstuttgart.parser;
import de.dhbwstuttgart.parser.antlr.Java8BaseListener;
import de.dhbwstuttgart.parser.antlr.Java8Parser;
public class CompilationUnitEvaluator extends Java8BaseListener {
import org.antlr.v4.runtime.tree.*;
import de.dhbwstuttgart.syntaxtree.*;
public class CompilationUnitEvaluator extends Java8BaseListener{
@Override
public void enterCompilationUnit(Java8Parser.CompilationUnitContext ctx) {
System.out.println("SourceFile(");

@ -1,5 +1,5 @@
// Generated from Java8.g4 by ANTLR 4.5.3
package de.dhbwstuttgart.parser.antlr;
package de.dhbwstuttgart.parser;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ErrorNode;

@ -1,5 +1,5 @@
// Generated from Java8.g4 by ANTLR 4.5.3
package de.dhbwstuttgart.parser.antlr;
package de.dhbwstuttgart.parser;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Token;

@ -1,5 +1,5 @@
// Generated from Java8.g4 by ANTLR 4.5.3
package de.dhbwstuttgart.parser.antlr;
package de.dhbwstuttgart.parser;
import org.antlr.v4.runtime.tree.ParseTreeListener;
/**

@ -1,11 +1,13 @@
// Generated from Java8.g4 by ANTLR 4.5.3
package de.dhbwstuttgart.parser.antlr;
package de.dhbwstuttgart.parser;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.misc.*;
import org.antlr.v4.runtime.tree.*;
import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class Java8Parser extends Parser {

@ -1,7 +0,0 @@
package de.dhbwstuttgart.parser;
/**
* Created by janulrich on 26.01.17.
*/
public class JavaXParser {
}

@ -1,10 +1,12 @@
package de.dhbwstuttgart.parser;
import de.dhbwstuttgart.parser.antlr.Java8Lexer;
import de.dhbwstuttgart.parser.antlr.Java8Parser;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.modifier.*;
import de.dhbwstuttgart.typecheck.*;
import java.util.Scanner;
import java.io.ByteArrayInputStream;

@ -1,9 +1,9 @@
package de.dhbwstuttgart.parser;
import de.dhbwstuttgart.parser.antlr.Java8Parser;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.modifier.*;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.statement.Expr;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.typecheck.*;
import java.util.ArrayList;

@ -1,13 +1,22 @@
package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.core.IItemWithOffset;
import de.dhbwstuttgart.logger.Section;
import de.dhbwstuttgart.typecheck.JavaClassName;
import de.dhbwstuttgart.syntaxtree.modifier.Modifiers;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.statement.Expr;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.assumptions.ClassAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
@ -49,15 +58,220 @@ public class ClassOrInterface extends GTVDeclarationContext implements IItemWith
this.implementedInterfaces = implementedInterfaces;
}
}
// Gets class name
public JavaClassName getClassName(){
return this.name;
}
/////////////////////////////////////////////////////////////////////////
// TypeReconstructionAlgorithmus
/////////////////////////////////////////////////////////////////////////
/**
* Ausgangspunkt f�r den Typrekonstruktionsalgorithmus. Hier werden zun�chst
* die Mengen von Typannahmen V_fields_methods und V_i erstellt, die als Eingabe
* f�r den Algorithmus dienen.<br/>
* (siehe Algorithmus 5.17 TRProg, Martin Pl�micke)
* <br/>Author: J�rg B�uerle
*
* @param supportData
* @param globalAssumptions
* @return Liste aller bisher berechneten, m�glichen Typkombinationen
* @throws CTypeReconstructionException
*/
public ConstraintsSet typeReconstruction(TypeAssumptions globalAssumptions) {
//////////////////////////////
// Und los geht's:
//////////////////////////////
inferencelog.info("Rufe TRStart()...", Section.TYPEINFERENCE);
//////////////////////////////
// Ab hier ...
// @author A10023 - Andreas Stadelmeier:
//////////////////////////////
//Erzeuge Assumptions:
TypeAssumptions assumptions = this.getPrivateFieldAssumptions();
//Globale Assumptions anfügen:
assumptions.add(globalAssumptions);
ConstraintsSet oderConstraints = new ConstraintsSet();
typinferenzLog.debug("Erstellte Assumptions: " + assumptions, Section.TYPEINFERENCE);
//Gibt es hier eine ClassCastException stimmt etwas grundsätzlich nicht!
//this.superClass = (RefType)this.superClass.TYPE(assumptions, this);
for (Field f : this.getFields()) {
oderConstraints.add(f.TYPE(assumptions));
}
typinferenzLog.debug("Erstellte Constraints: " + oderConstraints, Section.TYPEINFERENCE);
return oderConstraints;
}
/**
* Ermittelt alle privaten Felder und Methoden der Klasse und Erstellt eine Assumption für diese.
* Bemerkung: Momentan werden noch alle Felder dieser Klasse zurückgegeben.
* @return Die erstellten TypeAssumptions
*/
private TypeAssumptions getPrivateFieldAssumptions() {
if(this.typeAssumptions != null)return this.typeAssumptions; //Das sorgt dafür, dass die Assumptions nur einmalig generiert werden.
TypeAssumptions assumptions = new TypeAssumptions(this.getName());
for(Field field : this.getFields()){
if(!field.isPublic())assumptions.add(field.createTypeAssumptions(this));
}
this.typeAssumptions = assumptions; //Diese müssen anschließend nicht wieder generiert werden.
return assumptions;
}
/**
* <br/>Author: Martin Pl�micke
* @return
*/
public String toString() {
return name.toString();
}
// Get modifiers
public Modifiers getModifiers(){
return this.modifiers;
}
/**
* Generiert den JavaCode dieser Klasse im Falle für das übergebene resultSet.
* Dem ResultSet entsprechend werden in diesem Java-Code die TypePlaceholder durch die in ResultSet stehenden Typen ersetzt.
* @return Java-Sourcefile
*/
public JavaCodeResult printJavaCode(ResultSet reconstructionResult){
JavaCodeResult ret = new JavaCodeResult("class ");
JavaCodeResult classBodyCode = new JavaCodeResult();
if(this.modifiers!=null)classBodyCode.attach(this.modifiers.printJavaCode(reconstructionResult)).attach(" ");
classBodyCode.attach(this.name + " extends ").attach(this.superClass.printJavaCode(reconstructionResult)).attach("\n");
JavaCodeResult bodyString = new JavaCodeResult("{\n");
for(Field field : this.fielddecl)bodyString.attach( field.printJavaCode(reconstructionResult) ).attach( "\n" );
bodyString.attach("}\n");
classBodyCode.attach(bodyString);
//Zuerst die generischen Parameter für diese Klasse berechnen:
//this.createGenericTypeVars(classBodyCode.getUnresolvedTPH());
if(this.genericClassParameters != null && this.genericClassParameters.size()>0){
ret.attach("<");
Iterator<GenericTypeVar> it = this.genericClassParameters.iterator();
while(it.hasNext()){
GenericTypeVar tph = it.next();
ret.attach(tph.printJavaCode(reconstructionResult));
if(it.hasNext())ret.attach(", ");
}
ret.attach(">");
}
String stringReturn = ret.attach(classBodyCode).toString();
return new JavaCodeResult(stringReturn);
}
public int getOffset(){
return this.offset;
}
/**
* Erstellt einen RefType, welcher auf diese Klasse verweist
* Ersetzt alle Generischen Variablen in der Parameterliste mit TPH
* @return
*/
public RefType getType() {
return new RefType(this.getName().toString(), this.get_ParaList(),this, 0);
}
/**
* Ermittelt die Sichtbaren Felder und Methoden der Klasse.
* (Momentan sind im Projekt alle Felder und Methoden "package private", da der Parser keine Access-Modifier einlesen kann.
* @return
*/
public TypeAssumptions getPublicFieldAssumptions() {
TypeAssumptions ret = new TypeAssumptions();//this.getPrivateFieldAssumptions();
ret.addClassAssumption(new ClassAssumption(this));
for(Field f : this.getFields()){
if(f.isPublic())ret.add(f.createTypeAssumptions(this));
}
for(GenericTypeVar gtv : this.getGenericParameter()){
ret.add(gtv.createAssumptions());
}
return ret;
}
@Override
public boolean equals(Object obj){
if(!(obj instanceof Class))return false;
Class cl = (Class) obj;
if(!(cl.getName().equals(this.getName())))return false;
return true;
}
@Override
public GenericDeclarationList getGenericParameter() {
return this.genericClassParameters;
}
@Override
public List<? extends SyntaxTreeNode> getChildren() {
throw new NotImplementedException();
}
@Override
public String getDescription(){
return "class "+this.getName();
}
@Override
public String getGenericVarDeclarationString(String genericVarDeclaration) {
if(this.genericClassParameters != null){
return ", "+genericVarDeclaration;
}else{
return "<"+genericVarDeclaration+">";
}
}
@Override
public int getGenericVarDeclarationOffset(){
// Falls Generische Parameterliste vorhanden, hier Wert der Liste zurückgegebn
if(this.genericClassParameters != null){
return this.genericClassParameters.getEndOffset();
}else{
return this.offset;
}
}
/**
* Die Super Klasse dieser Klasse.
* @return null für Klasse Object
*/
public RefType getSuperClass(){
return this.superClass;
}
@Override
public boolean isClass() {
return true;
}
public boolean isInterface(){
return isInterface;
}
public List<Field> getFields() {
return fields;
}
}

@ -1,16 +1,95 @@
package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import org.apache.bcel.Constants;
import org.apache.bcel.generic.InstructionList;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.bytecode.DHBWConstantPoolGen;
import de.dhbwstuttgart.bytecode.MethodGenerator;
import de.dhbwstuttgart.typecheck.JavaClassName;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.statement.SuperCall;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.typeinference.TypeinferenceResults;
import de.dhbwstuttgart.typeinference.assumptions.ConstructorAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
import de.dhbwstuttgart.syntaxtree.type.Void;
public class Constructor extends Method {
public Constructor(String name, RefType returnType, ParameterList parameterList, Block block, GenericDeclarationList gtvDeclarations, int offset) {
super(name, returnType, parameterList, block, gtvDeclarations, offset);
/**
* Parser kann nicht zwischen einem Konstruktor und einer Methode unterscheiden.
* Diese Klasse beherbegt den als Methode geparsten Konstruktor und wandelt sein verhalten zu dem eines Konstruktors ab.
*/
public Constructor(Method methode, Class parent){
super(methode.get_Name(), methode.getType(), methode.getParameterList(),
methode.get_Block(), methode.getGenericDeclarationList(), methode.getOffset());
//Sicherstellen, dass das erste Statement in der Methode ein SuperCall ist:
if(this.get_Block().get_Statement().size() <1 || ! (this.get_Block().get_Statement().get(0) instanceof SuperCall)){
this.get_Block().statements.add(0, new SuperCall(this.get_Block()));
this.parserPostProcessing(parent);
}
}
@Override
public TypeAssumptions createTypeAssumptions(Class classmember) {
this.parent = classmember;
Class parentClass = classmember;
TypeAssumptions ret = new TypeAssumptions();
ret.addAssumption(new ConstructorAssumption(this, parentClass));
return ret;
}
public void genByteCode(ClassGenerator cg, InstructionList fieldInitializations){
DHBWConstantPoolGen _cp = cg.getConstantPool();
InstructionList il = new InstructionList(); //sollte nicht new sein sondern aus Block kommen
MethodGenerator method = new MethodGenerator(Constants.ACC_PUBLIC, this.getType().getBytecodeType(cg, null),
this.parameterlist.getBytecodeTypeList(cg,null) , this.parameterlist.getParameterNameArray(),
"<init>", cg.getClassName(), il, _cp);
//FieldInitializations an Block anfügen
Block block = this.get_Block();
if(! (block.statements.get(0) instanceof SuperCall)){
throw new DebugException("Fehlender SuperCall im Konstruktor");
}
//method.setMaxStack(); //Die Stack Größe automatisch berechnen lassen (erst nach dem alle Instructions angehängt wurden)
cg.addMethod(method.createMethod(cg, getParameterList(), this.getType(), get_Block(), null));
}
@Override
public void genByteCode(ClassGenerator cg, Class classObj, TypeinferenceResults resultSets) {
this.genByteCode(cg, new InstructionList());
}
// super statement muss drin sein
// stmt genByteCode + im block genByteCode implementieren & dann Hierarchie ausprobieren
// de.dhbw.systanxtree.stmts supercall
// Aufrufhierarchie: Class->Felder->Konstruktor->Methode innerhalb Konstruktor->Block->Statements (in diesem Fall nur super())->hier wird bytecode f<>r superaufruf generiert
@Override
public void parserPostProcessing(SyntaxTreeNode parent){
super.parserPostProcessing(parent);
if(this.parameterlist != null){
for(FormalParameter fp : this.parameterlist){
fp.parserPostProcessing(this);
}
}
for(GenericTypeVar gtv : this.getGenericParameter()){
gtv.parserPostProcessing(this);
}
}
@Override
public JavaClassName getTypeName() {
return this.getType().getName();
}
}

@ -1,18 +1,130 @@
package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import org.apache.bcel.generic.ClassGen;
public abstract class Field extends GTVDeclarationContext implements Generic {
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.GenericTypeInsertable;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeInsertable;
import de.dhbwstuttgart.typeinference.Typeable;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint;
public abstract class Field extends GTVDeclarationContext implements TypeInsertable, Typeable, Generic, GenericTypeInsertable{
private String name;
protected Type typ;
private GenericDeclarationList genericParameters;
public Field(String name, RefType type, int offset){
public Field(String name, Type type, int offset){
super(offset);
this.name = name;
this.typ = type;
}
@Override
public void setOffset(int offset){
this.offset = offset;
}
@Override
public int getOffset(){
return this.offset;
}
@Override
public Type getType() {
return typ;
}
@Override
public Menge<GenericTypeVar> getGenericParameter() {
Menge<GenericTypeVar> ret = new Menge<>();
if(this.genericParameters == null)return ret;
ret.addAll(this.genericParameters.getGTVList());
return ret;
}
GenericDeclarationList getGenericDeclarationList(){
return this.genericParameters;
}
public abstract JavaCodeResult printJavaCode(ResultSet resultSet);
/**
* Diese Methode generiert die Assumptions für dieses Feld der Klasse classmember
* @param classmember
* @return
*/
public abstract TypeAssumptions createTypeAssumptions(Class classmember);
public abstract ConstraintsSet TYPE(TypeAssumptions publicAssumptions);
public String getIdentifier() {
return name;
}
@Override
public String getDescription(){
return this.getIdentifier();
}
@Override
public TypeInsertPoint createTypeInsertPoint(TypePlaceholder tph,
ResultSet resultSet) {
return new TypeInsertPoint(this, this, resultSet.getTypeEqualTo(tph), resultSet);
}
public boolean isPublic() {
//TODO: momentan ist jedes Feld public!
return true;
}
@Override
public String getGenericVarDeclarationString(String genericVarDeclaration) {
if(this.genericParameters != null){
return ", "+genericVarDeclaration;
}else{
return "<"+genericVarDeclaration+">";
}
}
@Override
public int getGenericVarDeclarationOffset(){
// Falls Generische Parameterliste vorhanden, hier Wert der Liste zurückgegebn
if(this.genericParameters != null){
return this.genericParameters.getEndOffset();
}else{
return this.offset;
}
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<>();
if(this.getType()!=null)ret.add(this.getType());
ret.addAll(this.getGenericParameter());
return ret;
}
@Override
public void setGenericParameter(GenericDeclarationList params) {
this.genericParameters = params;
}
@Override
public boolean isClass() {
return false;
}
}

@ -7,8 +7,24 @@ import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.Const;
import org.apache.bcel.generic.ClassGen;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.syntaxtree.statement.Expr;
import de.dhbwstuttgart.syntaxtree.statement.This;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.OderConstraint;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.UndConstraint;
import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException;
/**
* Eine Feldinitialisation steht für eine Felddeklaration mit gleichzeitiger Wertzuweisung
* Beispiel: 'public Feld FeldVar = FeldWert;'
@ -23,10 +39,109 @@ public class FieldDeclaration extends Field{
* Dieser Konstruktor der FieldDeclaration erstellt den Syntaxknoten vollständig.
* Kein nachträgliches hinzfügen von Informationen oder aufrufen von parserPostProcessing ist notwendig.
*/
public FieldDeclaration(String name, RefType typ, Expr value){
public FieldDeclaration(String name, Type typ, Expr value){
super(name, typ, 0);//Dieser Deklarator wird nicht vom Parser aufgerufen. Dadurch gibt es auch keinen Offset
this.wert = value;
}
public Expr getWert(){
return this.wert;
}
@Override
public String toString()
{
if(getWert()!=null)return super.toString() + "=" + getWert().toString();
return super.toString();
}
public JavaCodeResult printJavaCode(TypeinferenceResultSet resultSet) {
JavaCodeResult ret = new JavaCodeResult();
JavaCodeResult toAttach = this.getType().printJavaCode(resultSet).attach(" ").attach( this.getIdentifier());
if(this.wert!=null)toAttach.attach(" = ").attach(this.getWert().printJavaCode(resultSet) );
toAttach.attach( ";");
ret.attach(toAttach);
return ret;
}
@Override
public TypeAssumptions createTypeAssumptions(Class classmember) {
//////////////////////////////
//Felder:
//////////////////////////////
TypeAssumptions assumptions = new TypeAssumptions();
/*
* Der Feld-Assumption muss ein TPH als Typ hinzugefügt werden, falls er Typlos initialisiert wurde. Dies kann auch der Type-Algorithmus der Inst/FieldVar - Klasse machen.
* Wird das Feld mit einem Typ initialisiert so muss dieser auch in die Assumptions.
*/
if(this.getType() == null)throw new TypeinferenceException("Der Typ eines Feldes darf nicht null sein", this);
//assumptions.add(TypeAssumptions.createFieldVarAssumption(classmember.getName(), this.getName(), this.getType()));
assumptions.addAssumption(new FieldAssumption(this,classmember));
return assumptions;
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = super.getChildren();
if(this.wert!=null)ret.add(this.wert);
return ret;
}
@Override
public ConstraintsSet TYPE(TypeAssumptions publicAssumptions) {
if(this.wert == null && (this.getType() == null || this.getType() instanceof TypePlaceholder))
throw new TypeinferenceException("Typlose Felder müssen mit Wert initialisiert werden", this);
ConstraintsSet ret = new ConstraintsSet();
TypeAssumptions localAssumptions = publicAssumptions.clone();
for(GenericTypeVar gp : this.getGenericParameter()){
localAssumptions.add(gp.createAssumptions());
}
for(GenericTypeVar gp : this.getGenericParameter()){
gp.TYPE(localAssumptions);
}
//TypeCheck, falls es sich um einen RefType handelt:
Type thisType = this.getType();
UndConstraint c1 = ConstraintsSet.createSingleConstraint(thisType, thisType);
ret.add(c1); //Damit die TypVariable des Felds in den Constraints auftaucht
if(this.wert!=null){
//Falls bei der Deklaration ein Wert zugewiesen wird, verhält sich das Constraintserzeugen wie bei dem Assign-Statement:
ret.add(this.wert.TYPEExpr(localAssumptions));
ret.add(ConstraintsSet.createSingleConstraint(this.wert.getType().TYPE(localAssumptions,this), thisType));
}
return ret;
}
/**
* Das besondere bei genByteCode einer FieldDeclaration ist, dass ein InstructionList zurückgegeben wird.
* Dieser muss in jeden Konstruktor eingefügt werden um das Feld zu initialisieren.
* @param cg
* @return - Die InstructionList, welche das Feld initialisiert
*/
public InstructionList genByteCode(ClassGenerator cg, TypeinferenceResultSet rs) {
//Das Feld an die Klasse anfügen:
FieldGen field = new FieldGen(0, this.getType().getBytecodeType(cg, rs), this.getDescription(), cg.getConstantPool());
field.addAttribute(cg.getInstructionFactory().createSignatureAttribute(this.getType().getBytecodeSignature(cg, rs)));
cg.addField(field.getField());
//Die Felddekleration an den Konstruktor anhängen:
InstructionList il = new InstructionList();
il.append(new This(this).genByteCode(cg, rs));
if(wert != null){
il.append(this.wert.genByteCode(cg, rs));
}
FieldInstruction putFieldInstruction =
cg.getInstructionFactory().createFieldAccess(cg.getClassName(),
this.getDescription(), this.getType().getBytecodeType(cg, rs), Const.PUTFIELD);
il.append(putFieldInstruction );
return il;
}
}

@ -1,15 +1,94 @@
package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.typeinference.Menge;
public class FormalParameter extends SyntaxTreeNode
import java.util.List;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeInsertable;
import de.dhbwstuttgart.typeinference.Typeable;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException;
import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint;
import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet;
public class FormalParameter extends SyntaxTreeNode implements Typeable, TypeInsertable
{
private RefType type;
private String name;
protected static Logger inferencelog = Logger.getLogger("inference");
public FormalParameter(String name, RefType type, int offset){
super(offset);
this.name = name;
this.type = type;
}
@Override
public boolean equals(Object object) {
//if(!super.equals(object))return false; //Nicht die Position im SyntaxBaum prüfen.
if(!(object instanceof FormalParameter))return false;
FormalParameter equals = (FormalParameter)object;
if((this.type==null)!=(equals.type == null))return false;
if(this.type != null){
return this.type.equals(equals.type);
}
return true;
}
public String getIdentifier()
{
return name;
}
public RefType getType()
{
return type;
}
@Override
public String toString(){
String ret = "";
if(this.getType() != null)ret += this.getType().toString();
if(this.getIdentifier() != null)ret += " "+getIdentifier();
return ret;
}
public JavaCodeResult printJavaCode(ResultSet resultSet) {
JavaCodeResult ret = new JavaCodeResult();
if(this.getType() != null)ret.attach(this.getType().printJavaCode(resultSet));
if(this.getIdentifier() != null)ret.attach(" "+getIdentifier());
return ret;
}
@Override
public TypeInsertPoint createTypeInsertPoint(TypePlaceholder tph,
ResultSet resultSet) {
if(this.getOffset()<=0)return null;
RefType t = resultSet.getTypeEqualTo(tph);
return new TypeInsertPoint(this, this, t, resultSet);
}
@Override
public List<? extends SyntaxTreeNode> getChildren() {
return null;
}
@Override
public String getDescription(){
String ret = "";
if(this.getType() != null && !(this.getType() instanceof TypePlaceholder)){
ret += this.getType().toString();//getBytecodeSignature(null, null);
}
return ret+this.getIdentifier();
}
}

@ -5,4 +5,12 @@ package de.dhbwstuttgart.syntaxtree;
* dass bei seiner Deklaration auch Generische Typvariablen deklariert wurden.
*/
public abstract class GTVDeclarationContext extends SyntaxTreeNode {
public GTVDeclarationContext(int offset) {
super(offset);
}
@Override
public GTVDeclarationContext getGTVDeclarationContext(){
return this;
}
public abstract boolean isClass();
}

@ -1,9 +1,15 @@
package de.dhbwstuttgart.syntaxtree;
import java.util.Iterator;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
/**
* Wird von allen Klassen implementiert, welche generische Parameter halten können. (Class, Method und Field)
* @author janulrich
*
*/
public interface Generic {
public Iterable<GenericTypeVar> getGenericParameter();
}

@ -1,7 +1,14 @@
package de.dhbwstuttgart.syntaxtree;
import java.util.*;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.ResultSet;
/**
* Stellt eine Deklarations-Liste von Generischen Variablen dar.
@ -12,9 +19,10 @@ import java.util.*;
public class GenericDeclarationList extends SyntaxTreeNode implements Iterable<GenericTypeVar>{
private int offsetOfLastElement;
private List<GenericTypeVar> gtvs = new ArrayList<>();
private List<GenericTypeVar> gtvs = new Menge<>();
public GenericDeclarationList(List<GenericTypeVar> values, int endOffset) {
super(endOffset);
gtvs = values;
this.offsetOfLastElement = endOffset;
}
@ -24,7 +32,38 @@ public class GenericDeclarationList extends SyntaxTreeNode implements Iterable<G
}
@Override
public Iterator<GenericTypeVar> iterator() {
public int getOffset() {
return getEndOffset();
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
return null;
}
@Override
public Iterator<GenericTypeVar> iterator() {
return this.gtvs.iterator();
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<>();
for(GenericTypeVar gtv : gtvs){
ret.add(gtv);
}
return ret;
}
public int size() {
return gtvs.size();
}
public void add(GenericTypeVar t) {
this.gtvs.add(t);
}
public List<GenericTypeVar> getGTVList() {
return this.gtvs;
}
}

@ -1,6 +1,11 @@
package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.typecheck.JavaClassName;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
import java.util.ArrayList;
import java.util.List;
@ -22,10 +27,11 @@ public class GenericTypeVar extends SyntaxTreeNode
*/
List<RefType> bounds=new ArrayList<RefType>();
private int endOffset;
private String name;
private GenericTypeName name;
public GenericTypeVar(String s, List<RefType> bounds, int offset, int endOffset)
public GenericTypeVar(GenericTypeName s, List<RefType> bounds, int offset, int endOffset)
{
super(offset);
name = s;
if(bounds != null)for(RefType t : bounds){
//if(t!=null)this.extendVars.add(t);
@ -49,4 +55,31 @@ public class GenericTypeVar extends SyntaxTreeNode
return "BoGTV " + this.name;
}
@Override
public List<SyntaxTreeNode> getChildren() {
List<SyntaxTreeNode> ret = new ArrayList<>();
ret.addAll(this.bounds);
return ret;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
throw new NotImplementedException();
}
public GenericTypeName getName() {
return name;
}
}
public class GenericTypeName{
private final String simpleName;
public GenericTypeName(JavaClassName inClass, String name){
this.simpleName = name;
}
public GenericTypeName(JavaClassName inClass, String inField, String name){
this(inClass, name);
}
}

@ -1,5 +1,6 @@
package de.dhbwstuttgart.syntaxtree;
import java.sql.Ref;
import java.util.ArrayList;
import java.util.List;
@ -7,11 +8,27 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
import org.apache.bcel.Constants;
import org.apache.bcel.generic.InstructionList;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.bytecode.DHBWConstantPoolGen;
import de.dhbwstuttgart.bytecode.DHBWInstructionFactory;
import de.dhbwstuttgart.bytecode.MethodGenerator;
import de.dhbwstuttgart.core.IItemWithOffset;
import de.dhbwstuttgart.typecheck.JavaClassName;
import de.dhbwstuttgart.syntaxtree.modifier.Modifiers;
import de.dhbwstuttgart.syntaxtree.modifier.Static;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeInsertable;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResults;
import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption;
import de.dhbwstuttgart.typeinference.assumptions.ParameterAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
/**
* Stellt eine Methode dar. Problem: Parser kann nicht zwischen Methode und
@ -21,22 +38,251 @@ import de.dhbwstuttgart.syntaxtree.statement.Block;
* @author janulrich
*
*/
public class Method extends Field implements IItemWithOffset
public class Method extends Field implements IItemWithOffset, TypeInsertable
{
private Block block;
public ParameterList parameterlist = new ParameterList(null);
public ParameterList parameterlist = new ParameterList();
private ExceptionList exceptionlist;
private RefType returntype;
private String name;
private List<String> types_in_parameterlist = new ArrayList<>();
private Menge<String> types_in_parameterlist = new Menge<String>();
private Modifiers modifiers;
protected static Logger inferencelog = Logger.getLogger("inference");
protected static Logger parserlog = Logger.getLogger("parser");
/**
*
* @param name
* @param returnType
* @param params
* @param block - use null to create abstract method
* @param offset
*/
public Method(String name, RefType returnType, ParameterList params, Block block, int offset) {
this(name, returnType, params, new ExceptionList(), block, offset);
}
public Method(String name, RefType returnType, ParameterList params, ExceptionList exceptions, Block block, int offset){
super(name, generateMethodType(returnType, params), offset);
}
public Method(String name, RefType returnType, ParameterList parameterList, Block block,
GenericDeclarationList gtvDeclarations, int offset) {
super(name, returnType, offset);
super(offset);
this.name = name;
this.parameterlist = parameterList;
this.block = block;
this.setGenericParameter(gtvDeclarations);
this.returntype = returnType;
}
public Block get_Block()
{
return block;
}
public ParameterList getParameterList()
{
return this.parameterlist;
}
/**
* Author: Jrg Buerle<br/>
*
* @return Die Anzahl der Methoden-Paramater
*/
public int getParameterCount()
{
if (this.getParameterList() == null)
return 0;
else
return this.getParameterList().getParameterCount();
}
public ExceptionList get_ExceptionList()
{
// otth: gibt die Exceptionliste zurueck
return this.exceptionlist;
}
/**
* <br/>
* Author: Martin Pl�micke
*
* @return
*/
public String toString()
{
return this.getType() + " " + this.get_Name() + ((block != null) ? block.toString() : "");
}
/**
* Gibt zurueck, ob ByteCode innerhabl der Methode generiert wird.
*/
public boolean isAbstract()
{
return isAbstract;
}
public ConstraintsSet TYPE(TypeAssumptions ass) {
ConstraintsSet ret = new ConstraintsSet();
TypeAssumptions localAss = new TypeAssumptions();
localAss.add(ass); // Die globalen Assumptions anhängen
// Generische Parameterdeklarationen den Assumptions anfügen:
for (GenericTypeVar gtv : this.getGenericParameter()) {
localAss.add(gtv.createAssumptions());
}
for (GenericTypeVar gtv : this.getGenericParameter()) {
ret.add(gtv.TYPE(localAss));
}
// TypeCheck, falls es sich um einen RefType handelt:
this.returntype = this.returntype.checkTYPE(localAss, this);
// Die Parameter zu den Assumptions hinzufügen:
if (this.parameterlist != null)
for (FormalParameter param : this.parameterlist) {
localAss.addAssumption(new ParameterAssumption(param));
}
ret.add(this.block.TYPEStmt(localAss));
// eine Verknüpfung mit der Type Assumption aus dem Assumption Set
// und dem ermittelten Typ der Methode:
ret.add(ConstraintsSet.createSingleConstraint(this.block.getType().TYPE(localAss, this), this.returntype.TYPE(localAss, this)));
return ret;
}
/**
* @author Andreas Stadelmeier, a10023
* @return die TypInformationen der Statements dieser Methode.
*/
public String getTypeInformation() {
if (this.parameterlist != null)
return "Methode " + this.get_Name() + " Parameter: "
+ this.parameterlist.getTypeInformation() + ", Block: "
+ this.block.getTypeInformation();
return "Methode " + this.get_Name() + " : " + this.getType()
+ ", Block: " + this.block.getTypeInformation();
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
JavaCodeResult ret = new JavaCodeResult();
ret.attach(this.getType().printJavaCode(resultSet)).attach(" ")
.attach(this.get_Name()).attach("(")
.attach(this.getParameterList().printJavaCode(resultSet))
.attach(")\n");
ret.attach(this.block.printJavaCode(resultSet));
return ret;
}
/**
* Liefert die MethodAssumption zu dieser Methode
*/
@Override
public TypeAssumptions createTypeAssumptions(Class classmember) {
Class parentClass = classmember;// this.getParentClass();
TypeAssumptions ret = new TypeAssumptions();
ret.addAssumption(new MethodAssumption(this, parentClass));
return ret;
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
ret.add(this.block);
ret.add(this.parameterlist);
ret.addAll(this.getGenericParameter());
ret.add(this.returntype);
return ret;
}
/**
* Der Typ einer Methode ist ihr Returntype
*/
@Override
public RefType getType() {
// Methode und Block teilen sich einen ReturnType:
return this.returntype;
}
public static Method createEmptyMethod(Block withBlock, String withSignature) {
Method ret = Method.createEmptyMethod(withSignature, parent);
ret.set_Block(withBlock);
return ret;
}
public static Method createEmptyMethod(String withSignature) {
Block block = new Block(new List<Statement>());
Method ret = new Method(withSignature, new de.dhbwstuttgart.syntaxtree.type.Void(0), new ParameterList(), block, new EmptyGenericDeclarationList(), 0);
DImethod.set_Name(withSignature);
ret.set_DeclId(DImethod);
Block tempBlock = new Block();
ret.set_Block(tempBlock);
ret.parserPostProcessing(parent);
return ret;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Method))
return false;
Method equals = (Method) obj;
if ((this.returntype != null && equals.returntype == null))
return false;
if ((this.returntype == null && equals.returntype != null))
return false;
if (this.returntype != null && equals.returntype != null)
if (!this.returntype.equals(equals.returntype))
return false;
if (!this.parameterlist.equals(equals.parameterlist))
return false;
return super.equals(obj);
}
public void genByteCode(ClassGenerator cg, Class classObj, TypeinferenceResults resultSets) {
List<TypeinferenceResultSet> typeInterferenceResults = resultSets.getTypeReconstructions(this, cg);
DHBWInstructionFactory _factory = cg.getInstructionFactory();
for(TypeinferenceResultSet t: typeInterferenceResults){
addMethodToClassGenerator(cg, _factory, t, classObj);
}
}
private void addMethodToClassGenerator(ClassGenerator cg, DHBWInstructionFactory _factory, TypeinferenceResultSet t, Class parentClass) {
DHBWConstantPoolGen _cp = cg.getConstantPool();
InstructionList il = new InstructionList();
ArrayList<org.apache.bcel.generic.Type> argumentTypes = new ArrayList<org.apache.bcel.generic.Type>();
ArrayList<String> argumentNames = new ArrayList<String>();
if (this.parameterlist != null && this.parameterlist.size() > 0) {
generateArgumentList(argumentTypes, argumentNames, cg, t);
}
short constants = Constants.ACC_PUBLIC;
if (this.modifiers != null && this.modifiers.includesModifier(new Static())) constants += Constants.ACC_STATIC;
RefType returnType = this.getType();
MethodGenerator method = new MethodGenerator(constants, returnType.getBytecodeType(cg, t),
argumentTypes.toArray(new org.apache.bcel.generic.Type[parameterlist.size()]),
argumentNames.toArray(new String[parameterlist.size()]), this.getName(),
parentClass.name.toString(), il, _cp);
cg.setMethodeGenerator(method);
cg.addMethod(method.createMethod(cg, getParameterList(), returnType, get_Block(), t));
}
private void generateArgumentList(ArrayList<org.apache.bcel.generic.Type> argumentTypes, ArrayList<String> argumentNames, ClassGenerator cg, TypeinferenceResultSet t) {
for(FormalParameter parameter : this.parameterlist){
argumentTypes.add(parameter.getType().getBytecodeType(cg, t));
argumentNames.add(parameter.getIdentifier());
}
}
public String getName() {
return name;
}
}

@ -0,0 +1,17 @@
package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.syntaxtree.type.RefType;
public class ObjectClass extends Class{
public ObjectClass() {
super("java.lang.Object", 0);
}
@Override
public RefType getSuperClass() {
return this.getType();
}
}

@ -1,14 +1,21 @@
package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.typeinference.Menge;
import java.util.Iterator;
import java.util.List;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
public class ParameterList extends SyntaxTreeNode implements Iterable<FormalParameter>
{
public List<FormalParameter> formalparameter;
public List<FormalParameter> formalparameter = new Menge<FormalParameter>();
public ParameterList(List<FormalParameter> params){
this.formalparameter = params;
@ -26,9 +33,88 @@ public class ParameterList extends SyntaxTreeNode implements Iterable<FormalPara
{
return formalparameter;
}
/**
* Author: J�rg B�uerle<br/>
* @return Die Anzahl der Parameter
*/
public int getParameterCount()
{
return formalparameter.size();
}
public String toString(){
if(formalparameter == null)return "[]"; //"Leere Parameterliste";
//String ret = "ParameterListe, "+formalparameter.size()+" Einträge [ ";
String ret = " [ ";
for(FormalParameter param : this.formalparameter){
ret += param.toString()+", ";
}
return ret + "]";
}
public JavaCodeResult printJavaCode(ResultSet resultSet) {
JavaCodeResult ret = new JavaCodeResult();
Iterator<FormalParameter> it = this.formalparameter.iterator();
while(it.hasNext()){
FormalParameter param = it.next();
ret.attach(param.printJavaCode(resultSet));
if(it.hasNext())ret.attach(", ");
}
//if(this.formalparameter.size()>0)ret = ret.substring(0, ret.length() - 2);
return ret;
}
@Override
public Iterator<FormalParameter> iterator() {
return null;
return this.formalparameter.iterator();
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof ParameterList))return false;
ParameterList equals = (ParameterList)obj;
if((this.formalparameter == null )!=(equals.formalparameter==null))return false;
if(this.formalparameter!=null)return this.formalparameter.equals(equals.formalparameter);
return true;
}
@Override
public int getOffset() {
if(formalparameter == null || formalparameter.size()==0)return 0;
return formalparameter.get(0).getOffset();
}
@Override
public List<? extends SyntaxTreeNode> getChildren() {
return formalparameter;
}
public int size() {
return this.formalparameter.size();
}
public org.apache.bcel.generic.Type[] getBytecodeTypeList(ClassGenerator cg, TypeinferenceResultSet rs){
org.apache.bcel.generic.Type[] ret = new org.apache.bcel.generic.Type[formalparameter.size()];
int i = 0;
for(FormalParameter f : formalparameter){
ret[i] = f.getType().getBytecodeType(cg, rs);
i++;
}
return ret;
}
public String[] getParameterNameArray() {
String[] ret = new String[formalparameter.size()];
int i = 0;
for(FormalParameter f : formalparameter){
ret[i] = f.getIdentifier();
i++;
}
return ret;
}
}

@ -1,41 +1,529 @@
package de.dhbwstuttgart.syntaxtree;
import java.util.*;
import de.dhbwstuttgart.typeinference.*;
import java.util.stream.Stream;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.logger.Section;
import de.dhbwstuttgart.core.MyCompiler;
import de.dhbwstuttgart.typecheck.JavaClassName;
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
import de.dhbwstuttgart.syntaxtree.modifier.Modifiers;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.typeinference.assumptions.ClassAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException;
import de.dhbwstuttgart.typeinference.unify.TypeUnify;
import de.dhbwstuttgart.typeinference.unify.Unifikationsalgorithmus;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
public class SourceFile extends SyntaxTreeNode{
private String pkgName;
public List<ClassOrInterface> KlassenVektor = new ArrayList<>();
private List<JavaClassName> imports;
private String pkgName;
public List<ClassOrInterface> KlassenVektor = new ArrayList<>();
private List<JavaClassName> imports;
/**
* Die SourceFile repräsntiert eine zu einem Syntaxbaum eingelesene Java-Datei.
* SourceFile stellt dabei den Wurzelknoten des Syntaxbaumes dar.
*/
public SourceFile(String pkgName,List<ClassOrInterface> classDefinitions,List<JavaClassName> imports){
this.KlassenVektor = classDefinitions;
if(pkgName != null){
this.pkgName = pkgName;
public SourceFile(String pkgName,List<ClassOrInterface> classDefinitions,List<JavaClassName> imports){
this.KlassenVektor = classDefinitions;
if(pkgName != null){
this.pkgName = pkgName;
}
if(imports != null){
this.imports = imports;
}
}
public SourceFile(List<ClassOrInterface> classDefinitions){
this(null, classDefinitions, null);
}
public SourceFile(String pkgName, List<ClassOrInterface> classDefinitions){
this(pkgName, classDefinitions, null);
}
public SourceFile(List<ClassOrInterface> classDefinitions, List<JavaClassName> imports){
this(null, classDefinitions, imports);
}
/**
* PL 2014-10-25
* schnitt1 checkt ob die Typeplaceholders aus in den Elemeneten aus vars enthalten sind
* Rückgabe ist die Menge der Indizies von vars der Schnittmengen mit var nicht leer sind.
* @param var
* @param vars
* @param indexe
* @return
*/
static Menge<Integer> schnitt1 (Menge<PlaceholderType> var, Menge<Menge<PlaceholderType>> vars, Menge<Integer> indexe) {
int j = -1;
for (Menge<PlaceholderType> varelems : vars) {
j++;
if (varelems != null) {
if (var.stream().map(x -> varelems.contains(x)).reduce(false, (a,b) -> (a || b))
&& (!indexe.contains(j)))
{
Menge<PlaceholderType> rekvarelements = vars.elementAt(j);
vars.setElementAt(null, j);//Element erledigt muss nicht nochmals bearbeitet werden.
indexe.addElement(j);
indexe = schnitt1(rekvarelements, vars, indexe);
}
}
}
return indexe;
}
if(imports != null){
this.imports = imports;
/**
* Bildet Schnittmengen der Mengen von Typeplaceholders
* Rueckgabe ist die Menge der Menge von Indizies die Schnittmengen sind.
* @param vars
* @return
*/
public static Menge<Menge<Integer>> schnitt (Menge<Menge<PlaceholderType>> vars) {
Menge<Menge<Integer>> ret = new Menge<>();
int i = -1;
for (Menge<PlaceholderType> var : vars) {
i++;
if (var != null) {//Element wurde noch bearbeitet
Menge<Integer> indexe = new Menge<>();
indexe.add(i);
ret.add(schnitt1(var, vars, indexe));
}
}
return ret;
}
}
public SourceFile(List<ClassOrInterface> classDefinitions){
this(null, classDefinitions, null);
}
public SourceFile(String pkgName, List<ClassOrInterface> classDefinitions){
this(pkgName, classDefinitions, null);
}
public SourceFile(List<ClassOrInterface> classDefinitions, List<JavaClassName> imports){
this(null, classDefinitions, imports);
}
public static Set<Set<UnifyPair>> cartesianProduct(List<UnifyPair> constraints, FiniteClosure finiteClosure){
//IDEE: Man bildet Zusammenhangskomponenten von Paaren, die gemeinsame Variablen haben
// und unifizert nur die Zusammenhangskomponenten in Schritten 1 - 5
//Schritt 1: Alle Variablen in den Paaren von Elementen einsammeln
Menge<Menge<PlaceholderType>> constraintsclonevars = constraints.stream().map(p -> {Menge<PlaceholderType> TPHs = new Menge<>();
TPHs.addAll(p.getInvolvedPlaceholderTypes());
TPHs.addAll(p.getInvolvedPlaceholderTypes());
return TPHs;}
).collect(Menge::new, Menge::add, Menge::addAll);
//Schritt 2: Schnittmengen jedes Elements mit jedem Elememt von vars bilden und dann index zusammenfassen
//in indexset sind dann die Mengen von Indizes enthalten, die gemeisam unifiziert wreden müssen
Menge<Menge<Integer>> indexeset = new Menge<>();
if (constraintsclonevars != null && constraintsclonevars.size()>0) {
indexeset = SourceFile.schnitt(constraintsclonevars);
}
//Schritt 3: Umwandlung der Indizes in die zugehoerigen Elemente
// In streamconstraintsclone sind die Mengen von Paar enthalten die unifiziert werden muessen
Stream<Menge<UnifyPair>> streamconstraintsclone = indexeset.stream().<Menge<UnifyPair>>map(x -> x.stream()
.<UnifyPair>map(i -> constraints.get(i))
.<Menge<UnifyPair>>collect(Menge::new, Menge::add, Menge::addAll));
//Menge<Menge<Pair>> vecconstraintsclone = streamconstraintsclone.collect(Menge::new, Menge::add, Menge::addAll);
//System.out.println();
//Schritt 4: Unifikation
Menge<Set<Set<UnifyPair>>> vecunifyResult =
//streamconstraintsclone.map(x -> Unify.unify(x, finiteClosure)).collect(Menge::new, Menge::add, Menge::addAll);
//DEBUG-Variante
streamconstraintsclone.map(x ->
{ Set<Set<UnifyPair>> z = new TypeUnify().unify(x, finiteClosure);
return z;
}
).collect(Menge::new, Menge::add, Menge::addAll);
//card gibt die Cardinalitaet der unifizierten Mengen an
Menge<Integer> card = vecunifyResult.stream().map(x -> x.size()).collect(Menge::new, Menge::add, Menge::addAll);
;//.reduce(1,(a,b) -> { if ((a > 0) && (b > 0)) return (a * b); else return 1; });
//Schritt 5: Bildung des cartesischen Produkts
//sollte wieder entfernt werden: Weiterarbeit mit:
//[[x_1 -> t_1, x_2 -> t2], [x_1 -> t'_1, x_2 -> t'_2]] x ... x [[x_n -> t_1n], [x_n -> t2n], [x_n -> t3n]]
Set<Set<UnifyPair>> cardprodret_start = new Menge<>();
cardprodret_start.add(new Menge<UnifyPair>());
//cart. Produkt mit Linkverschiebung
Set<Set<UnifyPair>> unifyResult = vecunifyResult.stream().reduce(cardprodret_start, (x, y) -> {
Set<Set<UnifyPair>> cardprodret= new Menge<>();
if (y.size() > 0) {
//System.out.println(y);
//Menge<Menge<Pair>> cardprodretold = x;
//cardprodret = new Menge<>();
for(Set<UnifyPair> xElement : x) {
for (Set<UnifyPair> yElement : y){
Set<UnifyPair> help = new Menge<>();
help.addAll(yElement);
help.addAll(xElement);
cardprodret.add(help);
}
}
}
else
return new Menge<>(); //kein unifiziertes Ergebnis, damit wird das Geseamtergebnis []
return cardprodret;
});
return unifyResult;
}
/////////////////////////////////////////////////////////////////////////
// TypeReconstructionAlgorithmus
/////////////////////////////////////////////////////////////////////////
/**
* Tyrekonstruktionsalgorithmus: ruft f�r jede Klasse den Algorithmus TRProg auf.
* Dessen Ergebnismenge A, die Menge aller Typannahmen, f�r eine Klasse dient als
* Eingabe f�r TRProg der n�chsten Klasse. Am Ende enth�lt A alle m�glichen
* Typkombinationen f�r alle Klassen zusammen.
* <br>Author: J�rg B�uerle
* @return Liste aller m�glichen Typkombinationen
* @throws CTypeReconstructionException Wenn was schief l�uft
*/
public Menge<TypeinferenceResultSet> typeReconstruction(TypeAssumptions globalAssumptions)
{
Menge<TypeinferenceResultSet> ret = new Menge<TypeinferenceResultSet>();
//Logger initialisieren:
Logger typinferenzLog = Logger.getLogger("Typeinference");
//Alle Assumptions für diese SourceFile sammeln:
for(Class klasse : this.KlassenVektor){
globalAssumptions.add(klasse.getPublicFieldAssumptions());
}
//Assumptions der importierten Klassen sammeln:
TypeAssumptions importAssumptions = this.makeBasicAssumptionsFromJRE(imports, true);
globalAssumptions.add(importAssumptions);
typinferenzLog.debug("Von JRE erstellte Assumptions: "+importAssumptions, Section.TYPEINFERENCE);
ConstraintsSet oderConstraints = new ConstraintsSet();
//Alle Constraints der in dieser SourceFile enthaltenen Klassen sammeln:
for(Class klasse : KlassenVektor){
oderConstraints.add(klasse.typeReconstruction(globalAssumptions));
}
/*////////////////
* Paare in MPairs umwandeln
* (Wird zunächst mal weggelassen. Constraints werden erst beim Unifizieren umgewandelt
*/////////////////
//UnifyTypeFactory.convert(oderConstraints);
//FiniteClosure generieren:
FiniteClosure finiteClosure = UnifyTypeFactory.generateFC(globalAssumptions);
typinferenzLog.debug("FiniteClosure: \n"+finiteClosure, Section.TYPEINFERENCE);
////////////////
//Typen in UnifyTypen umwandeln:
////////////////
UnifyConstraintsSet unifyConstraints = UnifyTypeFactory.convert(oderConstraints);
//Unmögliche ConstraintsSets aussortieren durch Unifizierung
Unifikationsalgorithmus unifier = (pairs)->new TypeUnify().unify(pairs, finiteClosure);
unifyConstraints.filterWrongConstraints(unifier);
//unifyConstraints.unifyUndConstraints(unifier); //rausgeworfen für Tests (08.12.2015)
typinferenzLog.debug("Übriggebliebene Konstraints:\n"+oderConstraints+"\n", Section.TYPEINFERENCE);
typinferenzLog.debug("Übriggebliebene Konvertierte Konstraints:\n"+unifyConstraints+"\n", Section.TYPEINFERENCE);
////////////////
//Karthesisches Produkt bilden:
////////////////
Set<Set<UnifyPair>> xConstraints = unifyConstraints.cartesianProduct();
//Sets zu Listen umwandeln:
//Set<List<UnifyPair>> allUnifiedConstraints = xConstraints.stream().map((set)-> new ArrayList<>(set)).collect(Menge::new, Menge::add, Menge::addAll);;
typinferenzLog.debug("Finite Closure: "+finiteClosure, Section.TYPEINFERENCE);
typinferenzLog.debug("Karthesisches Produkt der Constraints: "+xConstraints, Section.TYPEINFERENCE);
//finiteClosure.generateFullyNamedTypes(globalAssumptions);
//////////////////////////////
// Unifizierung der Constraints:
//////////////////////////////
boolean unifyFail = true;
for(Set<UnifyPair> constraints : xConstraints){
//Alle durch das Karthesische Produkt entstandenen Möglichkeiten durchgehen:
typinferenzLog.debug("\nUnifiziere Constraints:\n"+constraints, Section.TYPEINFERENCE);
typinferenzLog.debug("\nFC:\n"+finiteClosure, Section.TYPEINFERENCE);
long start = System.currentTimeMillis();
Set<Set<UnifyPair>> unifyResult = new TypeUnify().unify(constraints, finiteClosure);
long time = System.currentTimeMillis()-start;
typinferenzLog.debug("\nErgebnis der Unifizierung:\n"+unifyResult, Section.TYPEINFERENCE);
typinferenzLog.debug("\nAnzahl Lösungen:\n"+unifyResult.size(), Section.TYPEINFERENCE);
//typinferenzLog.debug("\nZeit für Unifizierung: "+time + "ms", Section.TYPEINFERENCE);
Menge<Menge<Pair>> convertedResult = unifyResult.parallelStream().<Menge<Pair>>map((Set<UnifyPair> resultSet)->{
Menge<Pair> innerConvert = resultSet.stream().map((UnifyPair mp)->UnifyTypeFactory.convert(mp))
.collect(Menge<Pair>::new, Menge::add, Menge::addAll);
return innerConvert;
}).collect(Menge::new, Menge::add, Menge::addAll);
Menge<Pair> convertedConstraints = constraints.stream().map(
(UnifyPair mp)->{return UnifyTypeFactory.convert(mp);}
).collect(Menge<Pair>::new, Menge::add, Menge::addAll);
//Dann den Ergebnissen anfügen
typinferenzLog.debug("\nErgebnis der Unifizierung (Konvertiert):\n"+convertedResult, Section.TYPEINFERENCE);
//result.addAll(convertedResult);
typinferenzLog.debug("\nJavaFiles:\n", Section.TYPEINFERENCE);
//typinferenzLog.debug(this.printJavaCode(new ResultSet(new Menge<Pair>())));
//Für jede Klasse in diesem SourceFile gilt das selbe ResultSet:
for(Class klasse : this.KlassenVektor){
//Der Unifikationsalgorithmus kann wiederum auch mehrere Lösungen errechnen, diese werden im folgenden durchlaufen:
for(Menge<Pair> resultSet : convertedResult){
unifyFail = false; //Ein Unifiziertes Ergebnis ist entstanden (es kann auch leer sein, das bedeutet nur, dass die Constraints mindestens in einem Fall Sinn ergaben)
//Add Result set as a new ReconstructionResult to ret:
TypeinferenceResultSet reconstructionResult = new TypeinferenceResultSet(klasse, convertedConstraints, new ResultSet(resultSet));
ret.add(reconstructionResult);
//ResultSet res = new ResultSet(resultSet);
typinferenzLog.debug("JavaFile für ResultSet "+reconstructionResult+"\n", Section.TYPEINFERENCE);
typinferenzLog.debug(klasse.printJavaCode(reconstructionResult), Section.TYPEINFERENCE);
}
}
}
if(unifyFail){
if(!this.KlassenVektor.isEmpty())throw new TypeinferenceException("Fehler in Typinferierung", this.KlassenVektor.firstElement());
}
return ret;
}
/**
* Erstellt die Assumptions der standardmäßig importierten Packages (java.lang.) sowie der von imports übergebenen Klassen zusammen.
* @param imports
* @param withSuptypes - Gibt an, ob auch die subklassen der Packages den Assumptions angefügt werden sollen.
* @return
* TODO: Diese Methode neu erstellen
*/
public TypeAssumptions makeBasicAssumptionsFromJRE(List<JavaClassName> imports, boolean withSubtypes)
{
return null;
}
private Class getSuperClassOfJREClass(java.lang.Class<?> x, TypeAssumptions ass) {
Class ret;
java.lang.Class s = x.getSuperclass();
if(s == null){
return new ObjectClass();
}
Menge<String> supertypeGenPara = new Menge<>();//Die Generischen Parameter für die Superklasse berechnen:
java.lang.reflect.TypeVariable[] superclassTVS=s.getTypeParameters();
for(int tvi=0;tvi<superclassTVS.length;tvi++){
supertypeGenPara.addElement(superclassTVS[tvi].getName());
}
Class ss = this.getSuperClassOfJREClass(s, ass);
ret = new Class(s.getName(),ss.getType(),new Modifiers(),supertypeGenPara);
ass.addClassAssumption(new ClassAssumption(ss)); //Die beiden SuperKlassen den Assumptions anfügen...
ass.addClassAssumption(new ClassAssumption(ret));
return ret;
}
private boolean isBaseType(String type)
{
return baseTypeTranslationTable.containsValue(type);
}
/*Die contains Methode des Menges vergleicht bei Strings nicht korrekt,
* da zwei Strings mit dem gleichen Inhalt unterschiedliche Instanzen sind.
* Deshalb diese Methode 07-01-20 luar*/
private boolean containsString(Menge<UsedId> searchMenge, String searchString)
{
boolean found = false;
for(UsedId id : searchMenge)
{
String s = id.getQualifiedName().toString();
found |= s.equals(searchString);
}
return found;
}
private Type createTypeFromJavaGenericType(java.lang.reflect.Type type, java.lang.Class<?> cl, Hashtable<String,GenericTypeVar>jreSpiderRegistry, Class parentClass)
{
/* auskommentiert, da die Klassen von Sun in der Open JDK 1.8 nicht unterstützt werden.
if(type instanceof TypeVariableImpl){
TypeVariableImpl tvi=((TypeVariableImpl)type);
return(new GenericTypeVar(jreSpiderRegistry.get(tvi.getName()).getName().toString(),parentClass,-1));
}else{
*/
GenericTypeVar gtv = jreSpiderRegistry.get(type.getTypeName());
if(gtv != null)return gtv;
//new GenericTypeVar(jreSpiderRegistry.get(type.getTypeName()).getName().toString(),parentClass,-1));
//String jccNameForClass=baseTypeTranslationTable.get(cl.getSimpleName());
String jccNameForClass=baseTypeTranslationTable.get(cl.getName());
if(cl.getSimpleName().equalsIgnoreCase("void")){
return(new Void(parentClass,-1));
}else if(jccNameForClass!=null){
RefType rt=new RefType(jccNameForClass,parentClass,-1);
rt.setPrimitiveFlag(true);
return(rt);
}else{
//return(new RefType(cl.getSimpleName()));
return(new RefType(cl.getName(),parentClass,-1));
}
//}
}
/**
* Erzeugt f�r jede Klasse einen Menge, in den Referenzen auf die GenericTypeVars
* dieser Klasse gespeichert werden. Diese Mengeen werden unter den Klassennamen
* in der
* Ergebnisdatenstruktur abgelegt. Au�erdem werden alle Klassennamen gespeichert.
* <br/>Author: J�rg B�uerle
* @param res
* /
* /*private void addClassNamesAndGenericsToRR(CTypeReconstructionResult res){
* Iterator<Class> it = this.getClassIterator();
* while(it.hasNext()){
* Class cl = it.next();
* res.addClassName(cl.get_classname());
* Menge<GenericTypeVar> genericsList = new Menge<GenericTypeVar>();
*
* for(int i =0; i<cl.get_ParaList().size(); i++){
* Type para = (Type)cl.get_ParaList().elementAt(i);
* if(para instanceof GenericTypeVar){
* genericsList.addElement((GenericTypeVar)para);
* }
* }
* res.addGenericTypeVars(cl.get_classname(), genericsList);
* }
* }
*/
public UsedId getPackageName()
{
return pkgName;
}
public void setPackageName(UsedId pkgName)
{
this.pkgName = pkgName;
// Die Package-Namen fuer alle Klassen und Interfaces
// im Source-File nachziehen
for (int i=0; i<KlassenVektor.size(); i++) {
KlassenVektor.elementAt(i).setPackageName(pkgName);
}
}
public ImportDeclarations getImports()
{
return(imports);
}
public Iterator<Class> getClassIterator()
{
return KlassenVektor.iterator();
}
public Iterator<Interface> getInterfaceIterator()
{
return InterfaceVektor.iterator();
}
@Override
public void parserPostProcessing(SyntaxTreeNode parent) {
if(parent!=null)throw new DebugException("Eine SourceFile hat kein Elternelement im Syntaxbaum");
super.parserPostProcessing(this);
//for(SyntaxTreeNode node : this.getChildren())node.parserPostProcessing(this);
}
@Override
public SyntaxTreeNode getParent() {
return null;
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
for(Class cl : this.KlassenVektor){
ret.add(cl);
}
return ret;
}
/**
* SourceFile stellt eine geparste Java-Datei dar. Mit dieser Methode wird der Name der eingelesenen Datei gesetzt.
* @param filename - Der Name der eingelesenen JavaDatei
*/
@Deprecated
public void setFileName(String filename) {
//this.filename = filename;
}
@Override
public int getOffset() {
// TODO Auto-generated method stub
return 0;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
throw new NotImplementedException();
}
@Override
public int getVariableLength() {
// TODO Auto-generated method stub
return 0;
}
/**
* Bytecode generieren für das resultSet
* @return
*/
public Menge<ByteCodeResult> generateBytecode(TypeinferenceResults results) {
Menge<ByteCodeResult> ret = new Menge<>();
for(Class cl : this.KlassenVektor){
ret.add(cl.genByteCode(results));
}
//Alle FunN Klassen erzeugen:
for(ClassAssumption funNAss : MyCompiler.makeFunNAssumptions().getClassAssumptions()){
ret.add(funNAss.getAssumedClass().genByteCode(results));
}
/*
//Add all FunN Interfaces
for(Pair ucons : results.getUnifiedConstraints()){
for(Type t : ucons.getTypes()){
List<Class> xClasses = t.isClassFromJavaX();
for(Class xClass : xClasses){
ByteCodeResult bC = xClass.genByteCode(results);
if(! ret.contains(bC))ret.add(bC);
}
}
}
*/
return ret;
}
public String getPkgName(){
return this.pkgName;

@ -2,8 +2,136 @@ package de.dhbwstuttgart.syntaxtree;
import java.util.List;
import org.apache.bcel.generic.ClassGen;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.core.IItemWithOffset;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.Pair;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeInsertable;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException;
import de.dhbwstuttgart.typeinference.typedeployment.GenericTypeInsertPoint;
import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint;
import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet;
public abstract class SyntaxTreeNode implements IItemWithOffset{
protected SyntaxTreeNode parent;
protected int offset;
public SyntaxTreeNode(int offset){
this.offset = offset;
}
/**
* Wird nach dem Parsen aufgerufen.
* Erfüllt folgenden Aufgaben:
* 1. Füllt fehlende Typangaben mit TPHs auf.
* 2. Verknüpft die Knoten des Syntaxbaums. (setzt Parent)
* 3. Wechselt RefTypes gegebenenfalls mit GenericTypeVars aus.
* 4. Führt einen Teil des Syntaxckecks durch.
*
*/
public void parserPostProcessing(SyntaxTreeNode parent) {
if(parent == null)throw new NullPointerException();
this.parent = parent;
for(SyntaxTreeNode node : this.getChildren())
if(node!=null)node.parserPostProcessing(this);
}
public SyntaxTreeNode getParent() {
//if(this.parent == null)throw new NullPointerException();
return this.parent;
}
public abstract List<? extends SyntaxTreeNode> getChildren();
/**
* Eine Beschreibung/Name des SyntaxTree-Nodes
* Hat nichts mit der Description im Bytecode zu tun,
* wird für die Anzeige des AST im Plugin verwendet
* @return
*/
public String getDescription(){
return this.toString();
}
@Override
public boolean equals(Object object){
if(!(object instanceof SyntaxTreeNode))return false;
SyntaxTreeNode equal = (SyntaxTreeNode)object;
if(!equal.getDescription().equals(this.getDescription()))return false;
if(this.getParent()!=null)
if(!this.getParent().equals(equal.getParent()))return false; //auch das Elternelement überprüfen.
return true;
}
/**
* Methode zur Generierung der TypeInsertPoints
* @param insertSet - Generierte InsertPoints werden dem insertSet angefügt
* @param result - Das ResultSet auf dessen Basis die InsertPoints generiert werden
*/
public void addTypeInsertPoints(TypeInsertSet insertSet,ResultSet result) {
for(SyntaxTreeNode node : this.getChildren()){
node.addTypeInsertPoints(insertSet, result);
}
TypeInsertPoint tip = null; //Der TypInsertPoint für diesen Knoten
//Fall der Knoten ein TypeInsertable ist, kann direkt der TypeInsertPoint generiert werden.
if(this instanceof TypeInsertable){
TypeInsertable that = (TypeInsertable)this;
Type t = that.getType();
if(t instanceof TypePlaceholder){
tip = that.createTypeInsertPoint((TypePlaceholder) t, result);
insertSet.add(tip);//ret.addAll(((TypePlaceholder)t).getTypeInsertPoints(result));
}
/*
//Für den Fall, dass dieser Knoten Generische Variablen halten kann.
if(that instanceof Generic && that.getOffset()>=0){
//Alle unresolvedTPHs ermitteln und GenericTypeVarInsertPoints bilden:
Menge<TypePlaceholder> uTPHs = insertSet.getUnresolvedTPHs();
if(uTPHs.size()>0){//Nur wenn es auch unresolvedTPHs gibt:
Menge<Pair> gPairs = result.getConstraintsFor(uTPHs);
if(gPairs.size()>0){
GenericTypeInsertPoint genericTIP = new GenericTypeInsertPoint(that,gPairs,result);
insertSet.add(genericTIP);
}
}
}
*/
}
}
public SyntaxTreeNode getMatchingParentNode(SyntaxTreeNode inNode) {
SyntaxTreeNode node = inNode;
while(node!=null){
if(node.equals(this))return this;
node = inNode.getParent();
}
if(this.getParent()!=null)return this.getParent().getMatchingParentNode(inNode);
return null;
}
public GTVDeclarationContext getGTVDeclarationContext(){
if(this.getParent()==null)
throw new NullPointerException();//throw new DebugException("getGTVDeclarationContext auf unzulässiger Klasse aufgerufen");
return this.getParent().getGTVDeclarationContext();
}
public int getOffset(){
return offset;
}
public abstract JavaCodeResult printJavaCode(ResultSet resultSet);
}

@ -0,0 +1,181 @@
package de.dhbwstuttgart.syntaxtree.factory;
import java.lang.reflect.Parameter;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.List;
import de.dhbwstuttgart.typecheck.JavaClassName;
import de.dhbwstuttgart.typecheck.JavaClassRegistry;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.modifier.Modifiers;
import de.dhbwstuttgart.syntaxtree.modifier.Public;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
import de.dhbwstuttgart.syntaxtree.statement.SuperCall;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.typeinference.Menge;
public class ASTFactory {
private final JavaClassRegistry names;
/**
* Anmerkung:
* Die ASTFactory Methoden, welche ASTBäume aus java.lang.Class Objekten generieren, können davon ausgehen,
* dass alle Imports und Typnamen korrekt sind und müssen diese nicht überprüfen.
*/
//private JavaClassRegistry names;
public ASTFactory(JavaClassRegistry scope){
names = scope;
}
public Method createEmptyMethod(String withSignature, Class parent) {
return ASTFactory.createMethod(withSignature, new ParameterList(), new Block(), parent);
}
public Constructor createEmptyConstructor(Class parent){
Block block = new Block();
block.setType(new de.dhbwstuttgart.syntaxtree.type.Void(block, 0));
block.statements.add(new SuperCall(block));
return ASTFactory.createConstructor(parent, new ParameterList(), block);
}
public static Constructor createConstructor(Class superClass, ParameterList paralist, Block block){
block.parserPostProcessing(superClass);
Method method = ASTFactory.createMethod("<init>", paralist, block, superClass);
method.setType(new de.dhbwstuttgart.syntaxtree.type.Void(block, 0));
return new Constructor(method, superClass);
}
public static Class createClass(String className, RefType type, Modifiers modifiers, Menge supertypeGenPara, SourceFile parent) {
// TODO bytecode createClass
//String name, RefType superClass, Modifiers modifiers, Menge<String> supertypeGenPara
Class generatedClass = new Class(className, type, modifiers, supertypeGenPara);
generatedClass.addField(ASTFactory.createEmptyConstructor(generatedClass));
generatedClass.parserPostProcessing(parent);
return generatedClass;
}
public static Class createObject(){
return createClass(java.lang.Object.class);
}
/**
*
* @param jreClass
* @return
*/
public Class createClass(java.lang.Class jreClass){
JavaClassName name = names.getName(jreClass.getName());
List<Method> methoden = new ArrayList<>();
for(java.lang.reflect.Constructor constructor : jreClass.getConstructors()){
}
for(java.lang.reflect.Method method : jreClass.getMethods()){
methoden.add(createMethod(method, jreClass));
}
List<Field> felder = new ArrayList<>();
Modifiers modifier = new Modifiers();
modifier.addModifier(new Public());
boolean isInterface = jreClass.isInterface();
java.lang.Class superjreClass = jreClass.getSuperclass();
RefType superClass = null;
if(superjreClass != null){
superClass = createType(superjreClass);
}else{//Jede Klasse und jedes Interface erbt von Object: (auch Object selbst!)
superClass = createType(java.lang.Object.class);
}
List<RefType> implementedInterfaces = new ArrayList<>();
for(java.lang.Class jreInterface : jreClass.getInterfaces()){
implementedInterfaces.add(createType(jreInterface));
}
int offset = 0; //Braucht keinen Offset, da diese Klasse nicht aus einem Quellcode geparst wurde
return new Class(name, methoden, felder, modifier, isInterface, superClass, implementedInterfaces, offset);
}
/**
* Wandelt eine Methode aus der JRE in eine Methode für unseren AST um.
* @param jreMethod
* @param inClass
* @return
*/
public Method createMethod(java.lang.reflect.Method jreMethod, java.lang.Class inClass){
String name = jreMethod.getName();
RefType returnType = createType(jreMethod.getReturnType());
Parameter[] jreParams = jreMethod.getParameters();
List<FormalParameter> params = new ArrayList<>();
for(Parameter jreParam : jreParams){
RefType paramType = createType(jreParam.getType());
params.add(new FormalParameter(jreParam.getName(),paramType,-1));
}
ParameterList parameterList = new ParameterList(params);
Block block = new Block(new ArrayList<Statement>(), -1);
List<GenericTypeVar> gtvs = new ArrayList<>();
for(TypeVariable jreTV : jreMethod.getTypeParameters()){
GenericTypeVar gtv = createGeneric(jreTV, new GenericTypeName(new JavaClassName(inClass.getName()),jreTV.getName()));
gtvs.add(gtv);
}
GenericDeclarationList gtvDeclarations = new GenericDeclarationList(gtvs,-1);
int offset = -1;
return new Method(name, returnType, parameterList, block, gtvDeclarations, offset);
}
public RefType createType(java.lang.Class jreClass){
List<RefType> params = new ArrayList<>();
for(TypeVariable jreTV : jreClass.getTypeParameters()){
RefType gtv = createType(jreTV);
params.add(gtv);
}
jreClass
return new RefType(jreClass.getName(), params, -1);
}
public RefType createType(java.lang.reflect.Type type){
RefType ret = new RefType(type.getTypeName(), -1);
//TODO hier die Generischen Variablen extrahieren
return ret;
}
/**
* Erstellt eine GenericTypeVar oder eine BoundedGenericTypeVar
* @param jreTypeVar
* @return
*/
public GenericTypeVar createGeneric(TypeVariable jreTypeVar, GenericTypeName name){
List<RefType> genericBounds = new ArrayList<>();
java.lang.reflect.Type[] bounds = jreTypeVar.getBounds();
if(bounds.length > 0){
for(java.lang.reflect.Type bound : bounds){
genericBounds.add(createType(bound));
}
}
return new GenericTypeVar(name, genericBounds, -1, -1);
}
public static Class createInterface(String className, RefType superClass, Modifiers modifiers,
Menge supertypeGenPara, SourceFile parent){
Class generatedClass = new Class(new JavaClassName(className), new ArrayList<Method>(), new ArrayList<Field>(), modifiers,
true, superClass, new ArrayList<RefType>(), new GenericDeclarationList(), -1);
generatedClass.parserPostProcessing(parent);
return generatedClass;
}
public static Class createObjectClass() {
Class generatedClass = new Class("java.lang.Object", 0);
return generatedClass;
}
public static RefType createObjectType(){
return createObjectClass().getType();
}
}

@ -0,0 +1,81 @@
package de.dhbwstuttgart.syntaxtree.factory;
public class NameGenerator {
private static String strNextName = "A";
/**
* Berechnet einen neuen, eindeutigen Namen f�r eine neue
* <code>TypePlaceholder</code>. <br>Author: J�rg B�uerle
* @return Der Name
*/
public static String makeNewName()
{
// otth: Funktion berechnet einen neuen Namen anhand eines alten gespeicherten
String strReturn = strNextName;
// n�chster Name berechnen und in strNextName speichern
inc( strNextName.length() - 1 );
return strReturn;
}
/**
* Hilfsfunktion zur Berechnung eines neuen Namens
* <br>Author: J�rg B�uerle
* @param i
*/
private static void inc(int i)
{
// otth: Hilfsfunktion zur Berechnung eines neuen Namens
// otth: Erh�hung des Buchstabens an der Stelle i im String strNextName
// otth: Nach �berlauf: rekursiver Aufruf
// falls i = -1 --> neuer Buchstabe vorne anf�gen
if ( i == -1 )
{
strNextName = "A" + strNextName;
return;
}
char cBuchstabe = (char)(strNextName.charAt( i ));
cBuchstabe++;
if ( cBuchstabe - 65 > 25 )
{
// aktuelle Stelle: auf A zuruecksetzen
manipulate( i, 'A' );
// vorherige Stelle erh�hen
inc( i - 1 );
}
else
{
// aktueller Buchstabe �ndern
manipulate( i, cBuchstabe );
}
}
/**
* Hilfsfunktion zur Berechnung eines neuen Namens.
* <br>Author: J�rg B�uerle
* @param nStelle
* @param nWert
*/
private static void manipulate( int nStelle, char nWert )
{
// otth: Hilfsfunktion zur Berechnung eines neuen Namens
// otth: Ersetzt im String 'strNextName' an der Position 'nStelle' den Buchstaben durch 'nWert'
String strTemp = "";
for( int i = 0; i < strNextName.length(); i++)
{
if ( i == nStelle )
strTemp = strTemp + nWert;
else
strTemp = strTemp + strNextName.charAt( i );
}
strNextName = strTemp;
}
}

@ -0,0 +1,9 @@
package de.dhbwstuttgart.syntaxtree.factory;
/**
* Generiert Hilfsmethoden für die Unary und Binary Operatoren
* Diese Methoden stellen die möglichen Operationen +,-,++, etc dar
*/
public class PrimitiveMethodsGenerator {
}

@ -0,0 +1,39 @@
package de.dhbwstuttgart.syntaxtree.factory;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.Pair;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
public class UnifyPairMengenBuilder {
private Menge<Pair> buildMenge = new Menge<Pair>();
public void addPair(Type t1, Type t2) {
buildMenge.add(new Pair(t1, t2));
}
public void addPair(Type t1, Type t2, PairOperator pairOp) {
buildMenge.add(new Pair(t1, t2, pairOp));
}
public Menge<Pair> getPairMenge() {
return buildMenge;
}
public Menge<Menge<Pair>> getNestedPairMenge() {
Menge<Menge<Pair>> nested = new Menge<>();
for(Pair p : buildMenge) {
Menge<Pair> m = new Menge<Pair>();
m.add(p);
nested.add(m);
}
return nested;
}
public void clear() {
buildMenge = new Menge<Pair>();
}
}

@ -0,0 +1,218 @@
package de.dhbwstuttgart.syntaxtree.factory;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
import de.dhbwstuttgart.syntaxtree.type.FunN;
import de.dhbwstuttgart.syntaxtree.type.FunVoidN;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
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.syntaxtree.type.Void;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.EinzelElement;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.OderConstraint;
import de.dhbwstuttgart.typeinference.Pair;
import de.dhbwstuttgart.typeinference.UndConstraint;
import de.dhbwstuttgart.typeinference.UnifyConstraintsSet;
import de.dhbwstuttgart.typeinference.UnifyOderConstraint;
import de.dhbwstuttgart.typeinference.UnifyUndConstraint;
import de.dhbwstuttgart.typeinference.assumptions.ClassAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.unify.model.ExtendsType;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.FunNType;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.ReferenceType;
import de.dhbwstuttgart.typeinference.unify.model.SuperType;
import de.dhbwstuttgart.typeinference.unify.model.TypeParams;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
public class UnifyTypeFactory {
private final static NullSyntaxTreeNode NULL_NODE = new NullSyntaxTreeNode();
public static FiniteClosure generateFC(TypeAssumptions fromAss){
HashSet<UnifyPair> pairs = new HashSet<>();
for(ClassAssumption cAss : fromAss.getClassAssumptions()){
UnifyType tl = UnifyTypeFactory.convert(cAss.getAssumedClass().getType().TYPE(fromAss, cAss.getAssumedClass()));
Type superClass = cAss.getAssumedClass().getSuperClass();
if(superClass != null){
UnifyType tr = UnifyTypeFactory.convert(superClass.TYPE(fromAss, cAss.getAssumedClass()));
pairs.add(generateSmallerPair(tl, tr));
}
}
return new FiniteClosure(pairs);
}
public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr){
return new UnifyPair(tl, tr, PairOperator.SMALLER);
}
public static UnifyPair generateSmallerDotPair(UnifyType tl, UnifyType tr){
return new UnifyPair(tl, tr, PairOperator.SMALLERDOT);
}
public static UnifyType convert(Type t){
//Es wurde versucht ein Typ umzuwandeln, welcher noch nicht von der Factory abgedeckt ist
if(t instanceof GenericTypeVar){
return UnifyTypeFactory.convert((GenericTypeVar)t);
}else if(t instanceof FunN){
return UnifyTypeFactory.convert((FunN)t);
}else if(t instanceof TypePlaceholder){
return UnifyTypeFactory.convert((TypePlaceholder)t);
}else if(t instanceof ExtendsWildcardType){
return UnifyTypeFactory.convert((ExtendsWildcardType)t);
}else if(t instanceof SuperWildcardType){
return UnifyTypeFactory.convert((SuperWildcardType)t);
}else if(t instanceof RefType){
return UnifyTypeFactory.convert((RefType)t);
}
throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden");
}
public static UnifyType convert(RefType t){
UnifyType ret;
if(t.getParaList() != null && t.getParaList().size() > 0){
Menge<UnifyType> params = new Menge<>();
for(Type pT : t.getParaList()){
params.add(UnifyTypeFactory.convert(pT));
}
ret = new ReferenceType(t.get_Name(),new TypeParams(params));
}else{
ret = new ReferenceType(t.get_Name());
}
return ret;
}
public static UnifyType convert(FunN t){
UnifyType ret;
Menge<UnifyType> params = new Menge<>();
if(t.getParaList() != null && t.getParaList().size() > 0){
for(Type pT : t.getParaList()){
params.add(UnifyTypeFactory.convert(pT));
}
}
ret = FunNType.getFunNType(t.getName().toString(), new TypeParams(params));
return ret;
}
public static UnifyType convert(TypePlaceholder tph){
return new PlaceholderType(tph.get_Name());
}
public static UnifyType convert(ExtendsWildcardType t){
return new ExtendsType(UnifyTypeFactory.convert(t.get_ExtendsType()));
}
public static UnifyType convert(SuperWildcardType t){
return new SuperType(UnifyTypeFactory.convert(t.get_SuperType()));
}
public static UnifyType convert(GenericTypeVar t){
return new PlaceholderType(TypePlaceholder.fresh(NULL_NODE).get_Name());
//return new ReferenceType(t.get_Name());
}
public static UnifyConstraintsSet convert(ConstraintsSet constraints) {
UnifyConstraintsSet ret = new UnifyConstraintsSet();
for(OderConstraint oC : constraints.getOderConstraints()){
ret.add(UnifyTypeFactory.convert(oC));
}
return ret;
}
public static UnifyOderConstraint convert(OderConstraint set) {
UnifyOderConstraint ret = new UnifyOderConstraint();
for(UndConstraint oC : set.getUndConstraints()){
ret.addConstraint(UnifyTypeFactory.convert(oC));
}
return ret;
}
public static UnifyUndConstraint convert(UndConstraint set) {
UnifyUndConstraint ret = new UnifyUndConstraint();
for(EinzelElement<Pair> oC : set.getPairs()){
ret.add(UnifyTypeFactory.convert(oC));
}
return ret;
}
public static UnifyPair convert(EinzelElement<Pair> p) {
return convert(p.getItem());
}
public static UnifyPair convert(Pair p) {
if(!p.OperatorSmaller())throw new NotImplementedException();
UnifyPair ret = generateSmallerDotPair(UnifyTypeFactory.convert(p.TA1)
, UnifyTypeFactory.convert(p.TA2));
return ret;
}
public static Pair convert(UnifyPair mp) {
Type tl = UnifyTypeFactory.convert(mp.getLhsType());
Type tr = UnifyTypeFactory.convert(mp.getRhsType());
return new Pair(tl, tr, mp.getPairOp());
}
public static Type convert(ReferenceType t) {
//TODO: Hier kann man die GTVs extrahieren
if(t.getName().toString().equals(Void.VOID_NAME))return new Void( 0);
RefType ret = new RefType(t.getName(),0);
ret.set_ParaList(convert(t.getTypeParams()));
return ret;
}
public static Type convert(FunNType t) {
RefType ret = new RefType(t.getName(),0);
ret.set_ParaList(convert(t.getTypeParams()));
return ret;
}
public static Type convert(SuperType t) {
RefType innerType = new RefType(t.getSuperedType().getName(),0);
return new SuperWildcardType(innerType);
}
public static Type convert(ExtendsType t) {
RefType innerType = new RefType(t.getExtendedType().getName(),0);
return new ExtendsWildcardType(innerType);
}
public static Type convert(PlaceholderType t) {
TypePlaceholder ret = TypePlaceholder.getInstance(t.getName());
if(ret == null){ //Dieser TPH wurde vom Unifikationsalgorithmus erstellt
ret = TypePlaceholder.fresh(t.getName(), NULL_NODE);
}
return ret;
}
public static Type convert(UnifyType t) {
if(t instanceof FunNType)return convert((FunNType) t);
if(t instanceof ReferenceType)return convert((ReferenceType) t);
if(t instanceof SuperType)return convert((SuperType) t);
if(t instanceof ExtendsType)return convert((ExtendsType) t);
if(t instanceof PlaceholderType)return convert((PlaceholderType) t);
throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden");
}
private static List<Type> convert(TypeParams typeParams) {
List<Type> ret = new ArrayList<>();
for(UnifyType uT : typeParams){
Type toAdd = convert(uT);
ret.add(toAdd);
}
return ret;
}
}

@ -0,0 +1,32 @@
package de.dhbwstuttgart.syntaxtree.factory;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.Pair;
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
public class Unify_FC_TTO_Builder {
private Menge<Pair> fc = new Menge<Pair>();
private Menge<Class> classes = new Menge<Class>();
/*
public void AddInheritance(Type t1, Type t2) {
if(t1 instanceof RefType)
if(!classes.stream().anyMatch(x -> x.getName().equals(t1.getName())))
classes.add(new Class(t1.get_Name(), t1.getOffset()));
if(t2 instanceof RefType)
if(!classes.stream().anyMatch(x -> x.getName().equals(t2.getName())))
classes.add(new Class(t2.get_Name(), t2.getOffset()));
fc.add(new Pair(t1, t2));
}
*/
public void clear() {
fc = new Menge<Pair>();
classes = new Menge<Class>();
}
}

@ -1,5 +1,7 @@
package de.dhbwstuttgart.syntaxtree.modifier;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
/**
* Stellt den Modifier Abstract dar.
@ -13,5 +15,9 @@ public class Abstract extends Modifier
return 0x0400;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
return new JavaCodeResult("abstract");
}
}

@ -1,5 +1,9 @@
package de.dhbwstuttgart.syntaxtree.modifier;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
/**
* Stellt den Modifier Final dar.
*
@ -12,4 +16,9 @@ public class Final extends Modifier
return 0x10;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
return new JavaCodeResult("final");
}
}

@ -3,6 +3,8 @@
*/
package de.dhbwstuttgart.syntaxtree.modifier;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
/**
* @author Daniel
@ -14,5 +16,8 @@ public class InterfaceModifier extends Modifier {
return 0x0200;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
return new JavaCodeResult("interface");
}
}

@ -1,5 +1,7 @@
package de.dhbwstuttgart.syntaxtree.modifier;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
public abstract class Modifier
{
@ -9,4 +11,5 @@ public abstract class Modifier
*/
public abstract short getBitmask();
public abstract JavaCodeResult printJavaCode(ResultSet resultSet);
}

@ -1,10 +1,14 @@
package de.dhbwstuttgart.syntaxtree.modifier;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import java.util.ArrayList;
import java.util.List;
/**
* Die Klasse beinhaltet die Liste der Access-Modifier fuer eine Klasse,
* Methode usw.

@ -1,5 +1,9 @@
package de.dhbwstuttgart.syntaxtree.modifier;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
public class Private extends Modifier
{
@ -8,4 +12,9 @@ public class Private extends Modifier
return 2;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
return new JavaCodeResult("private");
}
}

@ -1,5 +1,8 @@
package de.dhbwstuttgart.syntaxtree.modifier;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
public class Protected extends Modifier
{
@ -9,4 +12,9 @@ public class Protected extends Modifier
return 4;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
return new JavaCodeResult("protected");
}
}

@ -1,5 +1,9 @@
package de.dhbwstuttgart.syntaxtree.modifier;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
public class Public extends Modifier
{
@ -8,4 +12,9 @@ public class Public extends Modifier
return 1;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
return new JavaCodeResult("public");
}
}

@ -1,5 +1,8 @@
package de.dhbwstuttgart.syntaxtree.modifier;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
public class Static extends Modifier
{
@ -9,4 +12,9 @@ public class Static extends Modifier
return 8;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
return new JavaCodeResult("static");
}
}

@ -3,6 +3,9 @@
*/
package de.dhbwstuttgart.syntaxtree.modifier;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
/**
* @author Daniel
*
@ -13,4 +16,8 @@ public class Super extends Modifier {
return 0x0020;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
return new JavaCodeResult("super");
}
}

@ -11,12 +11,140 @@ import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.InvokeInstruction;
import org.apache.bcel.generic.ObjectType;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.bytecode.DHBWInstructionFactory;
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.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
import de.dhbwstuttgart.typeinference.unify.TypeUnify;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
public abstract class AddOp extends Operator
{
public AddOp(int offset, int variableLength)
{
super(offset,variableLength);
}
@Override
protected Hashtable<RefType,RefType> getOperatorTypes() {
Hashtable<RefType, RefType> types = new Hashtable<RefType, RefType>();
types.put(new RefType("java.lang.Integer",this,-1),new RefType("java.lang.Integer",this,-1));
types.put(new RefType("java.lang.Double",this,-1),new RefType("java.lang.Double",this,-1));
types.put(new RefType("java.lang.Float",this,-1), new RefType("java.lang.Float",this,-1));
types.put(new RefType("java.lang.Long",this,-1), new RefType("java.lang.Long",this,-1));
types.put(new RefType("java.lang.String",this,-1), new RefType("java.lang.String",this,-1));
return types;
}
@Override
public HashMap<Type,Type> getReturnTypes(TypeAssumptions ass) {
HashMap<Type,Type> ret = new HashMap<Type,Type>();
ret.put(new RefType("java.lang.Integer",this,-1).TYPE(ass, this), new RefType("java.lang.Integer",this,-1).TYPE(ass, this));
ret.put(new RefType("java.lang.Double",this,-1).TYPE(ass, this), new RefType("java.lang.Double",this,-1).TYPE(ass, this));
ret.put(new RefType("java.lang.Float",this,-1).TYPE(ass, this), new RefType("java.lang.Float",this,-1).TYPE(ass, this));
ret.put(new RefType("java.lang.Long",this,-1).TYPE(ass, this), new RefType("java.lang.Long",this,-1).TYPE(ass, this));
ret.put(new RefType("java.lang.String",this,-1).TYPE(ass, this), new RefType("java.lang.String",this,-1).TYPE(ass, this));
return ret;
}
@Override
public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs, Binary operator) {
/*
0: aload_1
1: invokevirtual #2 // Method java/lang/Integer.intValue:()I
4: aload_1
5: invokevirtual #2 // Method java/lang/Integer.intValue:()I
8: iadd
9: invokestatic #3 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
12: areturn
*/
String returnType = getReturnType(operator.get_Expr1(), operator.get_Expr2(), rs);
if(returnType.equals("java.lang.String")){
DHBWInstructionFactory _factory = _cg.getInstructionFactory();
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.bcel.generic.Type.VOID, new org.apache.bcel.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.bcel.generic.Type[] {org.apache.bcel.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.bcel.generic.Type[] {org.apache.bcel.generic.Type.STRING}, Constants.INVOKEVIRTUAL));
il.append(_cg.getInstructionFactory().createInvoke("java.lang.StringBuilder", "toString", new ObjectType("java.lang.String"), new org.apache.bcel.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, 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);
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.bcel.generic.Type[] {org.apache.bcel.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.bcel.generic.Type[] {org.apache.bcel.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.bcel.generic.Type[] {org.apache.bcel.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.bcel.generic.Type[] {org.apache.bcel.generic.Type.LONG}, Constants.INVOKESTATIC);
}else{
throw new NotImplementedException();
}
}
}

@ -1,8 +1,17 @@
package de.dhbwstuttgart.syntaxtree.operator;
import de.dhbwstuttgart.typeinference.Menge;
import org.apache.bcel.generic.InstructionList;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.statement.Binary;
import org.apache.bcel.generic.InstructionList;
import de.dhbwstuttgart.syntaxtree.statement.Expr;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
public class AndOp extends LogOp
{
@ -12,6 +21,11 @@ public class AndOp extends LogOp
super(offset,variableLength);
}
@Override
public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs, Binary operator) {
// TODO Auto-generated method stub
return null;
}
}

@ -1,4 +1,6 @@
package de.dhbwstuttgart.syntaxtree.operator;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
import org.apache.bcel.generic.ArithmeticInstruction;
import org.apache.bcel.generic.DADD;
@ -21,5 +23,20 @@ public class DivideOp extends MulOp
{
public DivideOp(int offset, int variableLength)
{
super(offset,variableLength);
}
ArithmeticInstruction getOperator(String returnType) {
if(returnType.equals("java.lang.Integer")){
return new IDIV();
}else if(returnType.equals("java.lang.Double")){
return new DDIV();
}else if(returnType.equals("java.lang.Float")){
return new FDIV();
}else if(returnType.equals("java.lang.Long")){
return new LDIV();
}else{
throw new NotImplementedException();
}
}
}

@ -8,7 +8,12 @@ public class EqualOp extends RelOp
{
public EqualOp(int offset, int variableLength)
{
super(offset, variableLength);
}
@Override
BranchInstruction getOperator() {
return new IF_ICMPNE(null);
}
}

@ -1,4 +1,5 @@
package de.dhbwstuttgart.syntaxtree.operator;
import de.dhbwstuttgart.typeinference.Menge;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.IF_ICMPLT;
@ -13,7 +14,12 @@ public class GreaterEquOp extends RelOp
{
public GreaterEquOp(int offset, int variableLength)
{
super(offset,variableLength);
}
@Override
BranchInstruction getOperator() {
return new IF_ICMPLT(null);
}
}

@ -1,4 +1,6 @@
package de.dhbwstuttgart.syntaxtree.operator;
import de.dhbwstuttgart.typeinference.Menge;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.IF_ICMPLE;
import de.dhbwstuttgart.syntaxtree.statement.Binary;
@ -11,6 +13,12 @@ public class GreaterOp extends RelOp
{
public GreaterOp(int offset, int variableLength)
{
super(offset,variableLength);
}
@Override
BranchInstruction getOperator() {
return new IF_ICMPLE(null);
}
}

@ -1,4 +1,5 @@
package de.dhbwstuttgart.syntaxtree.operator;
import de.dhbwstuttgart.typeinference.Menge;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.IF_ICMPGT;
@ -12,7 +13,12 @@ public class LessEquOp extends RelOp
{
public LessEquOp(int offset, int variableLength)
{
super(offset,variableLength);
}
@Override
BranchInstruction getOperator() {
return new IF_ICMPGT(null);
}
}

@ -1,4 +1,5 @@
package de.dhbwstuttgart.syntaxtree.operator;
import de.dhbwstuttgart.typeinference.Menge;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.IF_ICMPGE;
import de.dhbwstuttgart.syntaxtree.statement.Binary;
@ -11,6 +12,12 @@ public class LessOp extends RelOp
{
public LessOp(int offset, int variableLength)
{
super(offset,variableLength);
}
@Override
BranchInstruction getOperator() {
return new IF_ICMPGE(null);
}
}

@ -2,6 +2,20 @@ package de.dhbwstuttgart.syntaxtree.operator;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.syntaxtree.statement.Binary;
import de.dhbwstuttgart.syntaxtree.statement.Expr;
import de.dhbwstuttgart.syntaxtree.statement.NotExpr;
import de.dhbwstuttgart.syntaxtree.statement.Null;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.Pair;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
import de.dhbwstuttgart.typeinference.unify.TypeUnify;
@ -10,6 +24,26 @@ public abstract class LogOp extends Operator
public LogOp(int offset, int variableLength)
{
super(offset, variableLength);
}
@Override
protected Hashtable<RefType, RefType> getOperatorTypes() {
Hashtable<RefType, RefType> types = new Hashtable<RefType, RefType>();
types.put(new RefType("java.lang.Boolean",this,-1), new RefType("java.lang.Boolean",this,-1));
return types;
}
@Override
public HashMap<Type,Type> getReturnTypes(TypeAssumptions ass) {
HashMap<Type,Type> ret = new HashMap<>();
ret.put(new RefType("java.lang.Boolean",this,-1).TYPE(ass, this), new RefType("java.lang.Boolean",this,-1).TYPE(ass, this));
return ret;
}
}

@ -1,4 +1,12 @@
package de.dhbwstuttgart.syntaxtree.operator;
import de.dhbwstuttgart.typeinference.Menge;
import org.apache.bcel.generic.ArithmeticInstruction;
import org.apache.bcel.generic.IADD;
import org.apache.bcel.generic.ISUB;
import de.dhbwstuttgart.syntaxtree.statement.Binary;
import de.dhbwstuttgart.syntaxtree.statement.Expr;
@ -8,4 +16,8 @@ public class MinusOp extends AddOp
{
super(offset,variableLength);
}
ArithmeticInstruction getOperator(String returnType) {
return new ISUB();
}
}

@ -1,4 +1,5 @@
package de.dhbwstuttgart.syntaxtree.operator;
import de.dhbwstuttgart.typeinference.Menge;
import org.apache.bcel.generic.ArithmeticInstruction;
import org.apache.bcel.generic.IREM;
@ -12,6 +13,12 @@ public class ModuloOp extends MulOp
{
public ModuloOp(int offset, int variableLength)
{
super(offset,variableLength);
}
@Override
ArithmeticInstruction getOperator(String returnType) {
return new IREM();
}
}

@ -1,5 +1,113 @@
package de.dhbwstuttgart.syntaxtree.operator;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import org.apache.bcel.Constants;
import org.apache.bcel.generic.ArithmeticInstruction;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.InvokeInstruction;
import org.apache.bcel.generic.ObjectType;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.bytecode.DHBWInstructionFactory;
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.Pair;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
import de.dhbwstuttgart.typeinference.unify.TypeUnify;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
public abstract class MulOp extends Operator
{
public MulOp(int offset, int variableLength)
{
super(offset, variableLength);
}
@Override
protected Hashtable<RefType, RefType> getOperatorTypes() {
Hashtable<RefType, RefType> types = new Hashtable<RefType, RefType>();
return types;
}
@Override
public HashMap<Type,Type> getReturnTypes(TypeAssumptions ass) {
HashMap<Type,Type> ret = new HashMap<>();
ret.put(new RefType("java.lang.Integer",this,-1).TYPE(ass, this), new RefType("java.lang.Integer",this,-1).TYPE(ass, this));
ret.put(new RefType("java.lang.Double",this,-1).TYPE(ass, this), new RefType("java.lang.Double",this,-1).TYPE(ass, this));
ret.put(new RefType("java.lang.Float",this,-1).TYPE(ass, this), new RefType("java.lang.Float",this,-1).TYPE(ass, this));
ret.put(new RefType("java.lang.Long",this,-1).TYPE(ass, this), new RefType("java.lang.Long",this,-1).TYPE(ass, this));
return ret;
}
@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
4: aload_1
5: invokevirtual #2 // Method java/lang/Integer.intValue:()I
8: imul
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(), rs);
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, 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);
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.bcel.generic.Type[] {org.apache.bcel.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.bcel.generic.Type[] {org.apache.bcel.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.bcel.generic.Type[] {org.apache.bcel.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.bcel.generic.Type[] {org.apache.bcel.generic.Type.LONG}, Constants.INVOKESTATIC);
}else{
throw new NotImplementedException();
}
}
}

@ -1,9 +1,26 @@
package de.dhbwstuttgart.syntaxtree.operator;
import java.util.Iterator;
import de.dhbwstuttgart.syntaxtree.statement.Binary;
import de.dhbwstuttgart.syntaxtree.statement.Expr;
import de.dhbwstuttgart.syntaxtree.statement.Null;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.typeinference.Pair;
import de.dhbwstuttgart.typeinference.unify.TypeUnify;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.IF_ACMPEQ;
public class NotEqualOp extends RelOp
{
public NotEqualOp(int offset, int variableLength)
{
super(offset,variableLength);
}
@Override
BranchInstruction getOperator() {
return new IF_ACMPEQ(null);
}
}

@ -1,9 +1,101 @@
package de.dhbwstuttgart.syntaxtree.operator;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import org.apache.bcel.Constants;
import org.apache.bcel.generic.DADD;
import org.apache.bcel.generic.FADD;
import org.apache.bcel.generic.IADD;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.LADD;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.core.IItemWithOffset;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.statement.Binary;
import de.dhbwstuttgart.syntaxtree.statement.Expr;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.OderConstraint;
import de.dhbwstuttgart.typeinference.Pair;
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.TypeUnify;
public abstract class Operator extends SyntaxTreeNode
{
private int offset;
private int variableLength;
public Operator(int offset,int variableLength)
{
this.offset=offset;
this.variableLength=variableLength;
}
public int getOffset()
{
return offset;
}
public int getVariableLength()
{
return variableLength;
}
/**
* @author timo
* This is cool:
* we call the abstract parent to it him what operator-types he expects. the rest of the algorithm
* is implemented in this class because it's always the same...
* @see Design Pattern: Template Method
*/
protected abstract Hashtable<RefType, RefType> getOperatorTypes( );
/**
* Liefert eine HashMap der Form: HashMap<ResultType, InputType>
* @param ass
* @return
*/
public abstract HashMap<Type,Type> getReturnTypes(TypeAssumptions ass);
public abstract InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs, Binary operator);
@Override
public Menge<SyntaxTreeNode> getChildren() {
return new Menge<>();
}
protected InstructionList getInstructionListForOperand(ClassGenerator _cg, TypeinferenceResultSet rs, Expr operand, String returnType){
InstructionList il = new InstructionList();
il.append(operand.genByteCode(_cg, rs));
if(returnType.equals("java.lang.Integer")){
il.append(_cg.getInstructionFactory().createInvoke("java.lang.Integer", "intValue", org.apache.bcel.generic.Type.INT, new org.apache.bcel.generic.Type[] {}, Constants.INVOKEVIRTUAL));
}else if(returnType.equals("java.lang.Double")){
il.append(_cg.getInstructionFactory().createInvoke("java.lang.Double", "doubleValue", org.apache.bcel.generic.Type.DOUBLE, new org.apache.bcel.generic.Type[] {}, Constants.INVOKEVIRTUAL));
}else if(returnType.equals("java.lang.Float")){
il.append(_cg.getInstructionFactory().createInvoke("java.lang.Float", "floatValue", org.apache.bcel.generic.Type.FLOAT, new org.apache.bcel.generic.Type[] {}, Constants.INVOKEVIRTUAL));
}else if(returnType.equals("java.lang.Long")){
il.append(_cg.getInstructionFactory().createInvoke("java.lang.Long", "longValue", org.apache.bcel.generic.Type.LONG, new org.apache.bcel.generic.Type[] {}, Constants.INVOKEVIRTUAL));
}else if(returnType.equals("java.lang.String")){
throw new NotImplementedException(returnType);
}else if(returnType.equals("java.lang.Boolean")){
il.append(_cg.getInstructionFactory().createInvoke("java.lang.Boolean", "booleanValue", org.apache.bcel.generic.Type.BOOLEAN, new org.apache.bcel.generic.Type[] {}, Constants.INVOKEVIRTUAL));
}else{
throw new NotImplementedException(returnType);
}
return il;
}
}

@ -9,6 +9,10 @@ import org.apache.bcel.generic.InstructionConstants;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.ObjectType;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.bytecode.DHBWInstructionFactory;
import de.dhbwstuttgart.syntaxtree.statement.Binary;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
public class OrOp extends LogOp
{
@ -18,5 +22,45 @@ public class OrOp extends LogOp
super(offset,variableLength);
}
@Override
public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs, Binary operator) {
/*
0: aload_1
1: invokevirtual #2 // Method java/lang/Boolean.booleanValue:()Z
4: ifne 14
7: aload_2
8: invokevirtual #2 // Method java/lang/Boolean.booleanValue:()Z
11: ifeq 18
14: iconst_1
15: goto 19
18: iconst_0
19: invokestatic #3 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
22: areturn
*/
DHBWInstructionFactory _factory = _cg.getInstructionFactory();
InstructionList il = operator.get_Expr1().genByteCode(_cg, rs);
il.append(_factory.createInvoke("java.lang.Boolean", "booleanValue", org.apache.bcel.generic.Type.BOOLEAN, new org.apache.bcel.generic.Type[] {}, Constants.INVOKEVIRTUAL));
BranchInstruction firstTest = new IFNE(null);
il.append(firstTest);
il.append(operator.get_Expr2().genByteCode(_cg, rs));
il.append(_factory.createInvoke("java.lang.Boolean", "booleanValue", org.apache.bcel.generic.Type.BOOLEAN, new org.apache.bcel.generic.Type[] {}, Constants.INVOKEVIRTUAL));
BranchInstruction secondTest = new IFEQ(null);
il.append(secondTest);
firstTest.setTarget(il.append(InstructionConstants.ICONST_1));
BranchInstruction gotoInstruction = new GOTO(null);
il.append(gotoInstruction);
secondTest.setTarget(il.append(InstructionConstants.ICONST_0));
gotoInstruction.setTarget(il.append(_factory.createInvoke("java.lang.Boolean", "valueOf", new ObjectType("java.lang.Boolean"), new org.apache.bcel.generic.Type[] {org.apache.bcel.generic.Type.BOOLEAN}, Constants.INVOKESTATIC)));
return il;
}
}

@ -1,4 +1,28 @@
package de.dhbwstuttgart.syntaxtree.operator;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
import org.apache.bcel.Constants;
import org.apache.bcel.generic.ArithmeticInstruction;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.DADD;
import org.apache.bcel.generic.FADD;
import org.apache.bcel.generic.GOTO;
import org.apache.bcel.generic.IADD;
import org.apache.bcel.generic.IFEQ;
import org.apache.bcel.generic.IFNE;
import org.apache.bcel.generic.InstructionConstants;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.InvokeInstruction;
import org.apache.bcel.generic.LADD;
import org.apache.bcel.generic.ObjectType;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.bytecode.DHBWInstructionFactory;
import de.dhbwstuttgart.syntaxtree.statement.Binary;
import de.dhbwstuttgart.syntaxtree.statement.Expr;
import de.dhbwstuttgart.syntaxtree.type.Type;
@ -9,4 +33,18 @@ public class PlusOp extends AddOp
{
super(offset,variableLength);
}
ArithmeticInstruction getOperator(String returnType) {
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();
}
}
}

@ -1,6 +1,95 @@
package de.dhbwstuttgart.syntaxtree.operator;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import org.apache.bcel.Constants;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.GOTO;
import org.apache.bcel.generic.InstructionConstants;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.ObjectType;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.bytecode.DHBWInstructionFactory;
import de.dhbwstuttgart.syntaxtree.statement.Binary;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.typeinference.Pair;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
import de.dhbwstuttgart.typeinference.unify.TypeUnify;
public abstract class RelOp extends Operator
{
public RelOp(int offset, int variableLength)
{
super(offset, variableLength);
}
protected Hashtable<RefType, RefType> getOperatorTypes() {
Hashtable<RefType, RefType> types = new Hashtable<RefType, RefType>();
types.put(new RefType("java.lang.Integer",this,-1), new RefType("java.lang.Boolean",this,-1));
types.put(new RefType("java.lang.Double",this,-1), new RefType("java.lang.Boolean",this,-1));
types.put(new RefType("java.lang.Float",this,-1), new RefType("java.lang.Boolean",this,-1));
types.put(new RefType("java.lang.Long",this,-1), new RefType("java.lang.Boolean",this,-1));
return types;
}
@Override
public HashMap<Type,Type> getReturnTypes(TypeAssumptions ass) {
HashMap<Type,Type> ret = new HashMap<>();
ret.put(new RefType("java.lang.Boolean",this,-1).TYPE(ass, this), new RefType("java.lang.Integer",this,-1).TYPE(ass, this));
ret.put(new RefType("java.lang.Boolean",this,-1).TYPE(ass, this), new RefType("java.lang.Double",this,-1).TYPE(ass, this));
ret.put(new RefType("java.lang.Boolean",this,-1).TYPE(ass, this), new RefType("java.lang.Float",this,-1).TYPE(ass, this));
ret.put(new RefType("java.lang.Boolean",this,-1).TYPE(ass, this), new RefType("java.lang.Long",this,-1).TYPE(ass, this));
return ret;
}
@Override
public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs, Binary operator) {
/*
0: aload_1
1: invokevirtual #3 // Method java/lang/Integer.intValue:()I
4: aload_2
5: invokevirtual #3 // Method java/lang/Integer.intValue:()I
8: if_icmplt 15
11: iconst_1
12: goto 16
15: iconst_0
16: invokestatic #2 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
19: areturn
*/
DHBWInstructionFactory _factory = _cg.getInstructionFactory();
InstructionList il = getInstructionListForOperand(_cg, rs, operator.get_Expr1(), "java.lang.Boolean");
il.append(getInstructionListForOperand(_cg, rs, operator.get_Expr2(), "java.lang.Boolean"));
BranchInstruction operatorBranchInstruction = getOperator();
il.append(operatorBranchInstruction);
il.append(InstructionConstants.ICONST_1);
BranchInstruction gotoInstruction = new GOTO(null);
il.append(gotoInstruction);
operatorBranchInstruction.setTarget(il.append(InstructionConstants.ICONST_0));
gotoInstruction.setTarget(il.append(_factory.createInvoke("java.lang.Boolean", "valueOf", new ObjectType("java.lang.Boolean"), new org.apache.bcel.generic.Type[] {org.apache.bcel.generic.Type.BOOLEAN}, Constants.INVOKESTATIC)));
return il;
}
abstract BranchInstruction getOperator();
}

@ -1,5 +1,8 @@
package de.dhbwstuttgart.syntaxtree.operator;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
import org.apache.bcel.generic.ArithmeticInstruction;
import org.apache.bcel.generic.DMUL;
import org.apache.bcel.generic.FMUL;
@ -13,7 +16,21 @@ public class TimesOp extends MulOp
{
public TimesOp(int offset,int variableLength)
{
super(offset,variableLength);
}
ArithmeticInstruction getOperator(String returnType) {
if(returnType.equals("java.lang.Integer")){
return new IMUL();
}else if(returnType.equals("java.lang.Double")){
return new DMUL();
}else if(returnType.equals("java.lang.Float")){
return new FMUL();
}else if(returnType.equals("java.lang.Long")){
return new LMUL();
}else{
throw new NotImplementedException();
}
}
}

@ -1,17 +1,96 @@
package de.dhbwstuttgart.syntaxtree.statement;
import java.util.Iterator;
import org.apache.bcel.generic.InstructionList;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import java.util.List;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
public class ArgumentList extends SyntaxTreeNode
{
public ArgumentList(int offset) {
super(offset);
}
public List<Expr> expr;
public Menge<Expr> expr = new Menge<Expr>();
public Object get_firstElement()
{
return expr.firstElement();
}
/**
* @author Andreas Stadelmeier, a10023
* @return Anzahl der Argumente in der ArgumentList
*/
public int size() {
return expr.size();
}
/**
* @author Andreas Stadelmeier, a10023
* @param n
* @return Das Element (Expr) in der Argumentliste an der Stelle n
*/
public Expr argumentAt(int n){
return expr.elementAt(n);
}
public String toString(){
if(expr == null)return "[]";
String ret = " [ ";
for(Expr expr : this.expr){
ret += expr.toString()+", ";
}
return ret + "]";
}
public JavaCodeResult printJavaCode(ResultSet resultSet) {
JavaCodeResult ret = new JavaCodeResult();
Iterator<Expr> it = this.expr.iterator();
while(it.hasNext()){
Expr expr = it.next();
ret.attach(expr.printJavaCode(resultSet));
if(it.hasNext())ret.attach(", ");
}
//if(this.expr.size()>0)ret = ret.substring(0, ret.length()-2);
return ret;
}
@Override
public int getOffset() {
return 0;
}
@Override
public Menge<? extends SyntaxTreeNode> getChildren() {
return expr;
}
public InstructionList generateBytecode(ClassGenerator cg, TypeinferenceResultSet rs){
InstructionList ret = new InstructionList();
for(Expr e : expr){
ret.append(e.genByteCode(cg, rs));
}
return ret;
}
public org.apache.bcel.generic.Type[] getBytecodeTypeList(ClassGenerator cg, TypeinferenceResultSet rs){
org.apache.bcel.generic.Type[] ret = new org.apache.bcel.generic.Type[expr.size()];
int i = 0;
for(Expr e : expr){
ret[i] = e.getType().getBytecodeType(cg, rs);
i++;
}
return ret;
}
}

@ -1,14 +1,27 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import org.apache.bcel.generic.InstructionList;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.bytecode.DHBWInstructionFactory;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
public class Assign extends ExprStmt
{
public Assign(RefType type, int offset) {
public Assign(Type type, int offset) {
super(type, offset);
}
@ -17,6 +30,7 @@ public class Assign extends ExprStmt
/**
* Logger log4j
*/
protected static Logger parserlog = Logger.getLogger("parser");
public void set_Expr(Expr expr1,Expr expr2)
@ -31,5 +45,108 @@ public class Assign extends ExprStmt
}
/**
* @author AI10023 - Andreas Stadelmeier
*/
@Override
public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) {
ConstraintsSet ret = new ConstraintsSet();
ret.add(expr1.TYPEExpr(assumptions));
ret.add(expr2.TYPEExpr(assumptions));
//this.setTypeVariable( TypePlaceholder.fresh(this));
//this.setType(TypePlaceholder.fresh(this));
ret.add(ConstraintsSet.createSingleConstraint(expr2.getType().TYPE(assumptions, this), expr1.getType().TYPE(assumptions, this))); //expr2.type <. expr1.type
ret.add(ConstraintsSet.createSingleConstraint(expr1.getType().TYPE(assumptions, this), this.getType().TYPE(assumptions, this)));
return ret;
}
/**
* Spezifikation:
* TYPEStmt( Ass, stmt ) =
* let (stmt : rty, ConS) = TYPEExpr( Ass, stmt )
* in (stmt : Void, ConS)
*/
@Override
public ConstraintsSet TYPEStmt(TypeAssumptions assumptions){
ConstraintsSet ret = this.TYPEExpr(assumptions); //TypeExpr aufrufen
//this.setType(new Void(0)); //Typ des Statments auf Void setzen.
return ret;
}
/**
* <br/>Author: Martin Pl�micke
* @return
*/
public String toString()
{
if(getType() == null)return "(" + expr1.toString() + " = " + expr2.toString() + ")";
return getType().toString() + "(" + expr1.toString() + " = " + expr2.toString() + ")";
}
public void wandleRefTypeAttributes2GenericAttributes(Menge<Type> paralist, Menge<GenericTypeVar> genericMethodParameters)
{
}
/*
@Override
public String getTypeInformation(){
return "(" + expr1.getTypeInformation() + " = " + expr2.getTypeInformation() + ") : "+this.getType();
}
*/
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet){
JavaCodeResult ret = new JavaCodeResult().attach(this.expr1.printJavaCode(resultSet) ).attach( " = " ).attach( this.expr2.printJavaCode(resultSet));
return ret;
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
ret.add(this.expr1);
ret.add(this.expr2);
return ret;
}
@Override
public InstructionList genByteCode(ClassGenerator cg, TypeinferenceResultSet rs) {
DHBWInstructionFactory _factory = new DHBWInstructionFactory(cg, cg.getConstantPool());
InstructionList il = expr2.genByteCode(cg, rs);//expr2 rechte expr
/*
String expr2Type = expr2.getType().get_Name().toString();
switch(expr2Type){
case "java.lang.Integer":
il.append(new ISTORE(counterAssign));
break;
case "java.lang.String":
il.append(new ASTORE(counterAssign));
break;
case "java.lang.Double":
il.append(new DSTORE(counterAssign));
break;
case "java.lang.Float":
il.append(new FSTORE(counterAssign));
break;
case "java.lang.Long":
il.append(new LSTORE(counterAssign));
break;
}
*/
//Es wird momentan immer von RefType ausgegangen:
il.append(cg.getMethodGenerator().createStore(expr2.getType().getBytecodeType(cg, rs), expr1.get_Name()));
return il;
}
}

@ -4,8 +4,20 @@ import java.util.HashMap;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.InstructionList;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.operator.Operator;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.OderConstraint;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.UndConstraint;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
// neu von Felix
@ -18,5 +30,126 @@ public class Binary extends BinaryExpr
}
/**
* Logger: log4j
*/
protected static Logger parserlog = Logger.getLogger("parser");
public Expr expr1;
public Operator op;
public Expr expr2;
public void set_Expr1(Expr exp)
{
this.expr1=exp;
}
public void set_Expr2(Expr exp)
{
this.expr2=exp;
}
public void set_Operator(Operator Op)
{
this.op=Op;
}
public String get_Name()
{
return null;
}
public Operator get_Operator()
{
return op;
}
public Expr get_Expr1()
{
return expr1;
}
public Expr get_Expr2()
{
return expr2;
}
public void wandleRefTypeAttributes2GenericAttributes(Menge<Type> paralist, Menge<GenericTypeVar> genericMethodParameters)
{
}
@Override
public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) {
ConstraintsSet ret = new ConstraintsSet();
ret.add(this.expr1.TYPEExpr(assumptions));
ret.add(this.expr2.TYPEExpr(assumptions));
/**
* Berechnet die Constraints dieses Operators für die 2 gegebenen Parameter
* Die Operatoren sind meistens überladen. Es entstehen mehrere Oder-Verknüpfte Constraints.
* @param expr1
* @param expr2
* @return
*/
//if(this.getType()==null)this.set_Type(TypePlaceholder.fresh(this));
OderConstraint oderCons = new OderConstraint();
HashMap<Type,Type> rMap = this.op.getReturnTypes(assumptions);
for(Type rT : rMap.keySet()){
UndConstraint c = new UndConstraint();
c.addConstraint(this.getType().TYPE(assumptions, this),rT);
c.addConstraint(this.expr1.getType().TYPE(assumptions, this), rMap.get(rT));
c.addConstraint(this.expr2.getType().TYPE(assumptions, this), rMap.get(rT));
oderCons.addConstraint(c);
}
ret.add(oderCons);
return ret;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
JavaCodeResult ret = new JavaCodeResult();
ret.attach(this.expr1.printJavaCode(resultSet)).attach(" ");
ret.attach(this.op.toString()+" ");
ret.attach(this.expr2.printJavaCode(resultSet));
return ret;
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
ret.add(this.expr1);
ret.add(this.expr2);
return ret;
}
private InstructionList genUnboxByteCode(ClassGen _cg, Type t){
return null;
}
@Override
public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) {
return op.genByteCode(_cg, rs, this);
}
}

@ -1,5 +1,7 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
public abstract class BinaryExpr extends Expr
@ -7,7 +9,7 @@ public abstract class BinaryExpr extends Expr
public BinaryExpr(int offset,int variableLength)
{
super(null,variableLength);
super(offset,variableLength);
}

@ -1,5 +1,8 @@
package de.dhbwstuttgart.syntaxtree.statement;
import java.util.*;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import org.apache.bcel.Constants;
import org.apache.bcel.generic.ClassGen;
@ -9,6 +12,25 @@ import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.MethodGen;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.logger.Section;
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.Field;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException;
@ -19,15 +41,23 @@ public class Block extends Statement
private ClassGen _cg;
public Block(List<Statement> statements, int offset) {
super(null, 0);
this.statements = statements;
super(offset);
this.statements = statements;
}
protected static Logger parserlog = Logger.getLogger("parser");
public List<Statement> statements = new ArrayList<>();
public List<Statement> statements = new Menge<Statement>();
//private String sc_meth_ret_type;
/**
* Logger: log4j
*/
protected static Logger inferencelog = Logger.getLogger("inference");
protected static Logger typinferenceLog = Logger.getLogger("Typeinference");
public List<Statement> get_Statement()
@ -41,6 +71,119 @@ public class Block extends Statement
/**
* <br/>Author: Martin Pl�micke
* @return
*/
public String toString()
{
return this.type + " { " + statements.toString();
}
@Override
public ConstraintsSet TYPEStmt(TypeAssumptions assumptions) {
ConstraintsSet ret = new ConstraintsSet();
/* this.setTypeVariable(TypePlaceholder.fresh(this)); */
for(Statement stmt : statements){
typinferenceLog.debug("Prozessing statement: "+stmt, Section.TYPEINFERENCE);
ret.add(stmt.TYPEStmt(assumptions));
/* if((stmt instanceof Return)){
ret.add(new Constraint(stmt.getTypeVariable(), this.getTypeVariable()));//TODO: Dies nochmal prüfen.
}
*/
}
if(statements.size()>0){
Statement stmt = statements.get(statements.size()-1);
typinferenceLog.debug("Prozessing statement: "+stmt, Section.TYPEINFERENCE);
this.setType(stmt.getType());
for(int i= statements.size()-2; i >= 0; i--) {
stmt = statements.get(i);
typinferenceLog.debug("Prozessing statement: "+stmt, Section.TYPEINFERENCE);
if (!(stmt.getReturnType() instanceof Void))
if (this.getReturnType() instanceof Void) {
//this.setTypeVariable(stmt.getTypeVariable());
throw new TypeinferenceException("Block besitzt falschen Rückgabetyp (fehlendes return-stmt)", this);
}
else {
TypePlaceholder tph = TypePlaceholder.fresh(this);
ret.add(ConstraintsSet.createSingleConstraint(this.getType().TYPE(assumptions, this), tph));
ret.add(ConstraintsSet.createSingleConstraint(stmt.getType().TYPE(assumptions, this), tph));
this.setType(tph);
}
}
}
return ret;
}
/*
@Override
public ConstraintsSet TYPEStmt(TypeAssumptions assumptions) {
ConstraintsSet ret = new ConstraintsSet();
if(this.getTypeVariable()==null)this.setTypeVariable(TypePlaceholder.fresh(this));
for(Statement stmt : statements){
typinferenceLog.debug("Prozessing statement: "+stmt);
ret.add(stmt.TYPEStmt(assumptions));
if((stmt instanceof Return)){
ret.add(new Constraint(stmt.getTypeVariable(), this.getTypeVariable()));//TODO: Dies nochmal prüfen.
}
}
return ret;
}
*/
@Override
public String getTypeInformation(){
String ret = "\n";
for(Statement s : this.get_Statement()){
ret += s.getTypeInformation()+"\n";
}
return ret;
}
public int getTypeLineNumber() {
throw new NotImplementedException();
}
public JavaCodeResult printJavaCode(ResultSet resultSet) {
JavaCodeResult ret = new JavaCodeResult().attach("{\n");
for(Statement stmt : this.get_Statement()){
ret.attach(stmt.printJavaCode(resultSet));
ret.attach((stmt instanceof ExprStmt ? ";" : "") + "\n");
}
return ret.attach("}");
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
for(Statement st : this.get_Statement()){
ret.add(st);
}
return ret;
}
@Override
public String getDescription(){
return "Block";
}
@Override
public InstructionList genByteCode(ClassGenerator cg, TypeinferenceResultSet rs) {
//ConstantPoolGen _cp = cg.getConstantPool();
InstructionList il = new InstructionList();
for(Statement stmt : this.get_Statement()){
il.append(stmt.genByteCode(cg, rs));
}
//il.dispose();
return il;
}
}

@ -6,6 +6,20 @@ import org.apache.bcel.generic.InstructionConstants;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionList;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
@ -13,11 +27,20 @@ public class BoolLiteral extends Literal
{
private boolean Bool;
protected static Logger parserlog = Logger.getLogger("parser");
public BoolLiteral()
{
super(null,-1);
super(-1,-1);
// #JB# 20.04.2005
// ###########################################################
this.setType(new RefType("java.lang.Boolean",this.getOffset()));
//this.setType(new Type("boolean"));
// ###########################################################
}
@ -47,5 +70,39 @@ public class BoolLiteral extends Literal
@Override
public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) {
return new ConstraintsSet();
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
if(Bool)return new JavaCodeResult("true");
return new JavaCodeResult("false");
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
return ret;
}
@Override
public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) {
InstructionFactory _factory = new InstructionFactory(_cg, _cg.getConstantPool());
InstructionList il = new InstructionList();
if (Bool == true){
il.append(InstructionConstants.ICONST_1);
}else {
il.append(InstructionConstants.ICONST_0);
}
return il;
}
}

@ -2,20 +2,37 @@ package de.dhbwstuttgart.syntaxtree.statement;
import java.util.Hashtable;
import java.util.Iterator;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.InstructionList;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
public class CastExpr extends Expr
{
public CastExpr(RefType castType, Expr expr, int offset)
public CastExpr(Type castType, Expr expr,int offset)
{
super(null, 0);
super(offset);
this.type = castType;
}
private Type type;
public Expr expr;
protected static Logger parserlog = Logger.getLogger("parser");
@ -26,7 +43,12 @@ public class CastExpr extends Expr
}
public void set_Type(Type ty)
{
this.type = ty;
}
public void set_Expr(Expr ex)
@ -35,5 +57,41 @@ public class CastExpr extends Expr
}
public void wandleRefTypeAttributes2GenericAttributes(Menge<Type> paralist, Menge<GenericTypeVar> genericMethodParameters)
{
}
@Override
public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) {
// TODO Auto-generated method stub
return null;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
return new JavaCodeResult("(("+this.+")").attach(this.expr.printJavaCode(resultSet)).attach(")");
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
ret.add(this.expr);
return ret;
}
@Override
public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) {
// TODO Bytecode
throw new NotImplementedException();
}
}

@ -1,6 +1,24 @@
package de.dhbwstuttgart.syntaxtree.statement;
import java.util.Hashtable;
import org.apache.bcel.generic.BIPUSH;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionList;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
@ -8,11 +26,16 @@ import java.util.Hashtable;
public class CharLiteral extends Literal
{
private char Char;
protected static Logger parserlog = Logger.getLogger("parser");
public CharLiteral()
{
super(null,-1);
super(-1,-1);
// #JB# 20.04.2005
// ###########################################################
this.setType(new RefType("Char",this,this.getOffset()));
//this.setType(new Type("char"));
// ###########################################################
}
@ -35,5 +58,47 @@ public class CharLiteral extends Literal
{
return null;
}
@Override
public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) {
// TODO Auto-generated method stub
return null;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
return new JavaCodeResult("'"+String.valueOf(this.Char)+"'");
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
return ret;
}
@Override
public void wandleRefTypeAttributes2GenericAttributes(
Menge<Type> paralist,
Menge<GenericTypeVar> genericMethodParameters) {
}
//Char-Getter fuer genByteCode
public char get_Char()
{
return Char;
}
@Override
public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) {
InstructionFactory _factory = new InstructionFactory(_cg, _cg.getConstantPool());
InstructionList il = new InstructionList();
il.append(new BIPUSH((byte) get_Char()));
return il;
}
}

@ -8,8 +8,20 @@ import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.LDC;
import org.apache.bcel.generic.LDC2_W;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
@ -17,11 +29,14 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
public class DoubleLiteral extends Literal
{
private double Double;
protected static Logger parserlog = Logger.getLogger("parser");
public DoubleLiteral()
{
super(null,-1);
super(-1,-1);
this.setType(new RefType("Double",this,this.getOffset()));
}
@ -48,5 +63,54 @@ public class DoubleLiteral extends Literal
}
/**
* <br/>Author: Martin Pl�micke
* @return
*/
public String toString()
{
return type.toString() + " " + Double;
}
public void wandleRefTypeAttributes2GenericAttributes(Menge<Type> paralist, Menge<GenericTypeVar> genericMethodParameters)
{
}
@Override
public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) {
this.setType(assumptions.checkType(new RefType("Double",this,this.getOffset()), this));
return new ConstraintsSet();
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
JavaCodeResult ret = new JavaCodeResult();
ret.attach(""+this.Double);
return ret;
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
return ret;
}
//alter Double-Versuch vermutlich inkorrekt
/*@Override
public InstructionList genByteCode(ClassGen cg) {
InstructionFactory _factory = new InstructionFactory(cg, cg.getConstantPool());
InstructionList il = new InstructionList();
il.append(new BIPUSH(new Double(get_Double()).byteValue()));
return il;
}*/
@Override
public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) {
ConstantPoolGen cp = _cg.getConstantPool();
//InstructionFactory _factory = new InstructionFactory(cg, cp);
InstructionList il = new InstructionList();
cp.addDouble(get_Double());
il.append(new LDC2_W(cp.getSize()-1));
return il;
}
}

@ -4,6 +4,19 @@ import java.util.Hashtable;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.InstructionList;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
@ -12,10 +25,51 @@ public class EmptyStmt extends Statement
{
public EmptyStmt()
{
super(null,-1);
super(-1,-1);
}
protected static Logger parserlog = Logger.getLogger("parser");
/*
public void sc_check(Menge<Class> classlist, Hashtable ch, Hashtable<String, String> bh, boolean ext, Hashtable parach, Hashtable<String, Hashtable> parabh)
{
if(ext){
parserlog.debug(" ---EmptyStmt---");
}
}
*/
public void wandleRefTypeAttributes2GenericAttributes(Menge<Type> paralist, Menge<GenericTypeVar> genericMethodParameters)
{
}
@Override
public ConstraintsSet TYPEStmt(TypeAssumptions assumptions) {
// TODO Auto-generated method stub
return null;
}
public int getTypeLineNumber() {
throw new NotImplementedException();
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
return new JavaCodeResult("");
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
return new Menge<SyntaxTreeNode>();
}
@Override
public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) {
// TODO Bytecode
throw new NotImplementedException();
}
}

@ -4,16 +4,23 @@ import java.util.Iterator;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import org.apache.bcel.generic.InstructionList;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.core.MyCompiler;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.unify.TypeUnify;
public abstract class Executeable extends SyntaxTreeNode
{
private RefType type;
public Executeable(RefType type, int offset) {
this.type = type;
public Executeable(int offset) {
super(offset);
}
//public abstract String getTypeInformation();
public abstract InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs);
}

@ -1,20 +1,32 @@
package de.dhbwstuttgart.syntaxtree.statement;
import java.util.Hashtable;
import java.util.Iterator;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.InstructionList;
import de.dhbwstuttgart.typeinference.Typeable;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
public abstract class Expr extends Executeable
public abstract class Expr extends Executeable implements Typeable
{
private RefType type;
public Expr(RefType type, int offset) {
super(type, offset);
super(offset);
this.type = type;
}
public RefType getType(){
return type;
}
public abstract String get_Name();
/**
* @author AI10023 - Andreas Stadelmeier
* Implementierung des Java 8 - Typinferenzalgorithmus von Martin Plümicke
* Jede Expression wird im Zuge des Algorithmus durch die TYPEExpr-Funktion angesprochen.
*/
public abstract ConstraintsSet TYPEExpr(TypeAssumptions assumptions);
}

@ -1,10 +1,14 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
public abstract class ExprStmt extends Executeable{
public ExprStmt(RefType type, int offset) {
super(type, offset);
public ExprStmt(Type type,int offset) {
super(type,offset);
}
public abstract ConstraintsSet TYPEExpr(TypeAssumptions assumptions);
public abstract ConstraintsSet TYPEStmt(TypeAssumptions assumptions);
}

@ -7,17 +7,34 @@ import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.LDC;
import org.apache.bcel.generic.LDC2_W;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
public class FloatLiteral extends Literal
{
private float Float;
protected static Logger parserlog = Logger.getLogger("parser");
public FloatLiteral()
{
super(null,-1);
super(-1,-1);
this.setType(new RefType("Float",this,this.getOffset()));
}
@ -44,4 +61,43 @@ public class FloatLiteral extends Literal
}
/**
* <br/>Author: Martin Pl�micke
* @return
*/
public String toString()
{
return type.toString() + " " + Float;
}
public void wandleRefTypeAttributes2GenericAttributes(Menge<Type> paralist, Menge<GenericTypeVar> genericMethodParameters)
{
}
@Override
public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) {
// TODO Auto-generated method stub
return null;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
// TODO Auto-generated method stub
return null;
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
return ret;
}
@Override
public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) {
ConstantPoolGen cp = _cg.getConstantPool();
InstructionList il = new InstructionList();
cp.addFloat(get_Float());
il.append(new LDC(cp.getSize()-1));
return il;
}
}

@ -1,9 +1,21 @@
package de.dhbwstuttgart.syntaxtree.statement;
import java.util.Hashtable;
import java.util.List;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.GOTO;
import org.apache.bcel.generic.IF_ICMPGE;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.NOP;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
public class ForStmt extends Statement
{
@ -18,13 +30,78 @@ public class ForStmt extends Statement
public ForStmt(int offset, int variableLength)
{
super(null,variableLength);
}
void sc_check(List<ClassOrInterface> classname, Hashtable ch, Hashtable<String, String> bh, boolean ext, Hashtable parach, Hashtable<String, Hashtable> parabh)
{
super(offset);
}
public String toString()
{
return "FOR ";
}
@Override
public ConstraintsSet TYPEStmt(TypeAssumptions assumptions) {
//TODO: TYPEStmt
ConstraintsSet ret = new ConstraintsSet();
ret.add(body_Loop_block.TYPEStmt(assumptions));
return ret;
}
public int getTypeLineNumber() {
throw new NotImplementedException();
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
// TODO printJavaCode
return new JavaCodeResult();
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
if(this.body_Loop_block!=null)ret.add(this.body_Loop_block);
if(this.head_Condition!=null)ret.add(this.head_Condition);
if(this.head_Condition_1!=null)ret.add(this.head_Condition_1);
if(this.head_Initializer!=null)ret.add(this.head_Initializer);
if(this.head_Initializer_1!=null)ret.add(this.head_Initializer_1);
if(this.head_Loop_expr!=null)ret.add(this.head_Loop_expr);
if(this.head_Loop_expr_1!=null)ret.add(this.head_Loop_expr_1);
//throw new NotImplementedException();
return ret;
}
@Override
public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) {
/*
0: iconst_0
1: istore_1
2: iload_1
3: bipush 10
5: if_icmpge 14
8: iinc 1, 1
11: goto 2
14: return
*/
InstructionList il = new InstructionList();
il.append(head_Initializer.genByteCode(_cg, rs));
InstructionHandle ih = il.append(head_Condition.genByteCode(_cg, rs));
BranchInstruction branch = new IF_ICMPGE(null);
il.append(branch);
il.append(body_Loop_block.genByteCode(_cg, rs));
il.append(head_Loop_expr.genByteCode(_cg, rs));
il.append(new GOTO(ih));
branch.setTarget(il.append(new NOP()));
return il;
}
}

@ -19,19 +19,44 @@ import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.NOP;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.logger.Section;
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.operator.LogOp;
import de.dhbwstuttgart.syntaxtree.operator.Operator;
import de.dhbwstuttgart.syntaxtree.operator.RelOp;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.Pair;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
import de.dhbwstuttgart.typeinference.unify.TypeUnify;
public class IfStmt extends Statement
{
public IfStmt(int offset, int variableLength)
{
super(null,variableLength);
super(offset,variableLength);
}
public boolean hamaDebug = true; //hama: Debug Ausgaben von mir ein- bzw. ausschalten
public Expr expr;
public Statement then_block;
public Statement else_block;
protected static Logger parserlog = Logger.getLogger("parser");
@ -46,5 +71,92 @@ public class IfStmt extends Statement
{
this.then_block = blk;
}
public void set_Else_block(Statement blk)
{
this.else_block = blk;
}
public void wandleRefTypeAttributes2GenericAttributes(Menge<Type> paralist, Menge<GenericTypeVar> genericMethodParameters)
{
if(then_block!=null){
then_block.wandleRefTypeAttributes2GenericAttributes(paralist,genericMethodParameters);
}
if(else_block!=null){
else_block.wandleRefTypeAttributes2GenericAttributes(paralist,genericMethodParameters);
}
}
@Override
public ConstraintsSet TYPEStmt(TypeAssumptions assumptions) {
ConstraintsSet ret = new ConstraintsSet();
this.setType(TypePlaceholder.fresh(this));
ret.add(expr.TYPEExpr(assumptions)); // die Constraints für (expressionDesIfStmt)
ret.add(this.then_block.TYPEStmt(assumptions));
if(else_block!=null){
ret.add(this.else_block.TYPEStmt(assumptions));
if(!(else_block.getType() instanceof Void))ret.add(ConstraintsSet.createSingleConstraint(else_block.getType().TYPE(assumptions, this),this.getType().TYPE(assumptions, this)));
}
ret.add(ConstraintsSet.createSingleConstraint(expr.getType().TYPE(assumptions, this),new RefType("Boolean",this,0).TYPE(assumptions, this))); //(expressionDesIfStmt)<.boolean
if(!(then_block.getType() instanceof Void))ret.add(ConstraintsSet.createSingleConstraint(then_block.getType().TYPE(assumptions, this),this.getType().TYPE(assumptions, this)));
if(then_block.getType() instanceof Void &&
(else_block == null || else_block.getType() instanceof Void))this.setType(new Void(this,this.getOffset()));
return ret;
}
public int getTypeLineNumber() {
throw new NotImplementedException();
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
JavaCodeResult ret = new JavaCodeResult("If(").attach(this.expr.printJavaCode(resultSet)).attach("){\n");
if(this.then_block!=null)ret.attach(this.then_block.printJavaCode(resultSet));
ret.attach("\n}else{\n");
if(this.else_block!=null)ret.attach(this.else_block.printJavaCode(resultSet));
ret.attach("\n}");
return ret;
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
if(this.expr!=null)ret.add(this.expr);
if(this.else_block!=null)ret.add(this.else_block);
if(this.then_block!=null)ret.add(this.then_block);
return ret;
}
@Override
public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) {
InstructionFactory _factory = _cg.getInstructionFactory();
InstructionList il = new InstructionList();
IfInstruction ifInstruction = new IFEQ(null);
il.append(expr.genByteCode(_cg, rs));
//Anmerkung: expr ist vom Typ java.lang.Boolean (per Definition)
il.append(_factory.createInvoke("java.lang.Boolean", "booleanValue", org.apache.bcel.generic.Type.BOOLEAN, org.apache.bcel.generic.Type.NO_ARGS, Constants.INVOKEVIRTUAL));
il.append(ifInstruction);
il.append(then_block.genByteCode(_cg, rs));
if(else_block != null && !(else_block instanceof EmptyStmt)){
//GotoInstruction gotoInstruction = new GOTO(null);
//il.append(gotoInstruction);
ifInstruction.setTarget(il.append(else_block.genByteCode(_cg, rs)));
//gotoInstruction.setTarget(il.append(new NOP()));
}else{
ifInstruction.setTarget(il.append(new NOP()));
}
return il;
}
}

@ -6,17 +6,170 @@ import java.util.Iterator;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.InstructionList;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.misc.UsedId;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.OderConstraint;
import de.dhbwstuttgart.typeinference.Pair;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.UndConstraint;
import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
import de.dhbwstuttgart.typeinference.unify.TypeUnify;
public class InstVar extends Expr
{
private Expr expr;
private UsedId usedid;
protected String type; //???? BRAUCHT MAN DEN???
protected static Logger parserlog = Logger.getLogger("parser");
public InstVar(Expr e, String n, int offset)
{
super(null,n.length());
super(offset,n.length());
expr = e;
usedid = new UsedId(getOffset());
usedid.set_Name(n);
}
public InstVar(String n, String t, int offset)
{
super(offset,n.length());
usedid = new UsedId(getOffset());
usedid.set_Name(n);
type = t;
}
/**
* macht aus einem UsedId mit einem Menge von Strings eine InstVar
* <br/>Author: Martin Pl�micke PL 05-08-17
* @param ui
* @return
*/
public InstVar(UsedId ui, int offset,int variableLength)
{
super(offset,variableLength);
Iterator namen = ui.get_Name().iterator();
LocalOrFieldVarOrClassname innerLOFV = new LocalOrFieldVarOrClassname((String)namen.next(),getOffset());
//innerLOFV.setType(TypePlaceholder.fresh(this));
InstVar INSTVA = new InstVar(innerLOFV, (String)namen.next(),offset);
//INSTVA.setType(TypePlaceholder.fresh(this));
while(namen.hasNext()) {
INSTVA = new InstVar(INSTVA, (String)namen.next(),offset);
//INSTVA.setType(TypePlaceholder.fresh(this));
}
expr = INSTVA.expr;
usedid = INSTVA.usedid;
}
@Override
public void parserPostProcessing(SyntaxTreeNode parent) {
super.parserPostProcessing(parent);
if(this.getType()==null)this.set_Type(TypePlaceholder.fresh(this));
}
/*
public void sc_check(Menge<Class> classname, Hashtable ch, Hashtable<String, String> bh, boolean ext, Hashtable parach, Hashtable<String, Hashtable> parabh)
{
if(ext)
parserlog.debug(" ---InstVar---");
Menge name = usedid.get_Name();
for(Enumeration el = name.elements(); el.hasMoreElements();)
{
String name1 = (String) el.nextElement();
if(bh.containsKey(name1))
{
this.type = (String)bh.get(name1); //type wird von Expr geerbt
if(ext)
parserlog.debug("Variable " + name1 + " im Block gefunden.");
}
else if(ch.containsKey(name1))
{
this.type = (String)ch.get(name1);
if(ext)
parserlog.debug("Variable " + name1 + " in Class gefunden.");
}
else
if(ext)
parserlog.debug("Typfehler: -->InstVar.sc_check() "+ name1);
}
}
*/
public String get_Name()
{
return this.usedid.get_Name_1Element();
}
public String get_codegen_UsedId()
{ return usedid.get_codegen_UsedId(); }
/**
* <br/>Author: Martin Pl�micke
* @return
*/
public String toString()
{
String superType = "";
if(super.type != null)superType += super.type.toString();
return superType + " " + usedid.toString();
}
public void wandleRefTypeAttributes2GenericAttributes(Menge<Type> paralist, Menge<GenericTypeVar> genericMethodParameters)
{
}
@Override
public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) {
ConstraintsSet ret = new ConstraintsSet();
if(this.expr == null){
this.expr = new This(0, 0);
}
ret.add(expr.TYPEExpr(assumptions));
this.setType(TypePlaceholder.fresh(this));
OderConstraint oderConstraint = new OderConstraint();
for(FieldAssumption fa : assumptions.getFieldVars(this.get_Name())){
UndConstraint undConstraint = new UndConstraint();
undConstraint.addConstraint(fa.getAssumedType().TYPE(assumptions, this),this.getType().TYPE(assumptions, this));
undConstraint.addConstraint(this.expr.getType().TYPE(assumptions, this),fa.getParentClass().getType().TYPE(assumptions, this));
oderConstraint.addConstraint(undConstraint);
}
ret.add(oderConstraint);
return ret;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
JavaCodeResult ret = new JavaCodeResult();
if(this.expr != null)ret.attach(this.expr.printJavaCode(resultSet)).attach(".");
return ret.attach(this.usedid.get_Name_1Element());
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
ret.add(this.expr);
return ret;
}
@Override
public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) {
// TODO Bytecode
throw new NotImplementedException();
}
}

@ -5,7 +5,20 @@ import java.util.Hashtable;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.InstructionList;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
@ -14,12 +27,17 @@ public class InstanceOf extends BinaryExpr
public Expr expr;
private RefType reftype;
// private boolean is_instance = false;
protected static Logger parserlog = Logger.getLogger("parser");
public InstanceOf(int offset,int variableLength)
{
super(offset,variableLength);
// #JB# 20.04.2005
// ###########################################################
this.setType(new RefType("Boolean",this,this.getOffset()));
//this.setType(new Type("boolean"));
// ###########################################################
}
public void set_Expr(Expr exp)
@ -38,5 +56,36 @@ public class InstanceOf extends BinaryExpr
return null;
}
public void wandleRefTypeAttributes2GenericAttributes(Menge<Type> paralist, Menge<GenericTypeVar> genericMethodParameters)
{
}
@Override
public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) {
// TODO Auto-generated method stub
return null;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
// TODO Auto-generated method stub
return null;
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
ret.add(this.expr);
return ret;
}
@Override
public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) {
// TODO Bytecode
throw new NotImplementedException();
}
}

@ -8,6 +8,21 @@ import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.PUSH;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
@ -15,11 +30,17 @@ import org.apache.bcel.generic.ObjectType;
public class IntLiteral extends Literal
{
private int Int;
protected static Logger parserlog = Logger.getLogger("parser");
public IntLiteral()
{
super(null,-1);
super(-1,-1);
// #JB# 20.04.2005
// ###########################################################
this.setType(new RefType("Integer",this,this.getOffset()));
//this.setType(new Type("int"));
// ###########################################################
}
public void set_Int(int i)
@ -45,4 +66,47 @@ public class IntLiteral extends Literal
}
/**
* <br/>Author: Martin Pl�micke
* @return
*/
public String toString()
{
return getType().toString() + " " + Int;
}
public void wandleRefTypeAttributes2GenericAttributes(Menge<Type> paralist, Menge<GenericTypeVar> genericMethodParameters)
{
}
@Override
public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) {
ConstraintsSet ret = new ConstraintsSet();
//this.setType(new IntegerType());
this.set_Type(assumptions.checkType(new RefType("java.lang.Integer",this,-1), this));
return ret;
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet) {
return new JavaCodeResult(String.valueOf(this.Int));
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
return ret;
}
@Override
public InstructionList genByteCode(ClassGenerator cg, TypeinferenceResultSet rs) {
InstructionFactory _factory = new InstructionFactory(cg, cg.getConstantPool());
InstructionList il = new InstructionList();
/*
* Der jetzige Compiler kann keine primitiven Typen. Ein int-Literal ist daher eine Instanz von java.lang.Integer
*/
il.append(new PUSH(cg.getConstantPool(), this.get_Int()));
il.append(_factory.createInvoke("java.lang.Integer", "valueOf", new ObjectType("java.lang.Integer"), new org.apache.bcel.generic.Type[] { org.apache.bcel.generic.Type.INT }, Constants.INVOKESTATIC));
return il;
}
}

@ -10,14 +10,29 @@ import org.apache.bcel.classfile.InnerClass;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionList;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.bytecode.DHBWConstantPoolGen;
import de.dhbwstuttgart.bytecode.MethodGenerator;
import de.dhbwstuttgart.typecheck.JavaClassName;
import de.dhbwstuttgart.syntaxtree.ClassHelper;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.ParameterList;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.type.FunN;
import de.dhbwstuttgart.syntaxtree.type.FunVoidN;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.ObjectType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.assumptions.ParameterAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException;
/**
* @author A10023 - Andreas Stadelmeier
@ -38,9 +53,237 @@ public class LambdaExpression extends Expr{
private ParameterList params;
public LambdaExpression(int offset, int variableLength) {
super(null, variableLength);
super(offset, variableLength);
setParameterList(new ParameterList());//default is empty parameterlist
}
public void setBody(Block block){
method_body = block;
}
public void setExpr(Expr expression){
Block bl = new Block();
Return returnStmt = new Return(0, 0);
returnStmt.retexpr = expression;
bl.set_Statement(returnStmt);
this.setBody(bl);
}
public void setParameterList(ParameterList params){
ParameterList lambdaParameter = new ParameterList();
for(FormalParameter fp : params){
lambdaParameter.formalparameter.add(new LambdaParameter(fp));
}
this.params = lambdaParameter;
}
@Override
public void wandleRefTypeAttributes2GenericAttributes(
Menge<Type> paralist,
Menge<GenericTypeVar> genericMethodParameters) {
Block block = this.method_body;
// Zuerst Returntype untersuchen
Type returnType=getType();
Type pendantReturnType = null;
if(returnType instanceof RefType)
pendantReturnType = ((RefType)returnType).findGenericType(paralist, new Menge<GenericTypeVar>());
//GenericTypeVar pendantReturnType=ClassHelper.findGenericType(returnType, paralist,genericMethodParameters);
if(pendantReturnType!=null){ //Wenn generisch, dann modifizieren
setType(pendantReturnType);
}
// Dann parameterlist untersuchen
for(FormalParameter fp : params){
Type fpType=fp.getType();
// Nur wenn es sich um ein RefType-Field handelt
Type pendantPara = null;
if(fpType instanceof RefType)
pendantPara = ((RefType)fpType).findGenericType(paralist, new Menge<GenericTypeVar>());
//GenericTypeVar pendantPara=ClassHelper.findGenericType(fpType,paralist,genericMethodParameters);
if(pendantPara!=null){ //Wenn generisch, dann modifizieren
fp.setType(pendantPara);
}
}
// Zuletzt alle Lokalen Variablendeklarationen durchgehen
if(block!=null){
block.wandleRefTypeAttributes2GenericAttributes(paralist,genericMethodParameters);
}
}
@Override
public String get_Name() {
// TODO Auto-generated method stub
return null;
}
/**
* Spezifikation:
*
* TYPEExpr( Ass, Lambda( (x1 , . . . , xN ), expr|stmt ) ) =
* let
* AssArgs = { xi : ai | ai fresh type variables }
* (exprt : rty, ConS) = TYPEExpr( Ass ∪ AssArgs, expr )
* | (stmtt : rty, ConS) = TYPEStmt( Ass u AssArgs, stmt )
* in
* (Lambda( (x1 : a1 , . . . , xN : aN ), exprt : rty|stmtt : rty ) : a,
* ConS ∪ { (FunN<rty, a1 , . . . , aN > a) }),
* where a is a fresh type variable
*/
@Override
public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) {
ConstraintsSet ret = new ConstraintsSet();
//Die Assumptions für die Parameter der LambdaExpression
TypeAssumptions ArgumentAssumptions = new TypeAssumptions(this.getParentClass().getName());
Menge<Type> paramTypes = new Menge<Type>();
for(FormalParameter param : params.formalparameter){
if(param.getType()==null)param.setType(TypePlaceholder.fresh(this));
int offset = 0;
//Jeder Parameter der LambdaExpression wird als CParaTypeAssumption der Assumption liste hinzugefügt:
ArgumentAssumptions.addAssumption(new ParameterAssumption(param));
paramTypes.add(param.getType());
}
this.setType(TypePlaceholder.fresh(this));
//ArgumentAssumptions + assumptions ergeben die Assumptions für die Statements innerhalb des Lambda-Bodys:
ret.add(method_body.TYPEStmt(ArgumentAssumptions.add(assumptions))); //Es gibt die LambdaExpression nur mit einem Block als Method Body, nicht mit einer einzelnen Expression
//Die Constraints für ParameterTypen und Ret Typ erstellen:
Type retType = method_body.getType();
if(typeIsVoid(retType)){//In diesem Fall, muss der Typ des LambdaAusdrucks FunVoid sein
this.lambdaType = new FunVoidN(paramTypes);
}else{
this.lambdaType = new FunN(retType, paramTypes);
}
ret.add(ConstraintsSet.createSingleConstraint(lambdaType.TYPE(assumptions, this),this.getType().TYPE(assumptions, this)));
return ret;
}
private boolean typeIsVoid(Type type){
return type.getName().equals(new JavaClassName("void"));
}
@Override
public ConstraintsSet TYPEStmt(TypeAssumptions ass){
throw new TypeinferenceException("Eine LambdaExpression darf nicht als Statement verwendet werden.", this);
}
@Override
public String getTypeInformation(){
return this.getType().toString()+" :: ("+this.params.getTypeInformation()+ ") -> " +this.method_body.getTypeInformation();
}
@Override
public String toString(){
//return "LambdaExpression, Parameter: "+this.params+ ", Body: " +this.method_body;
return this.getType() + " (("+this.params+ ") -> "+this.method_body + ")";
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet){
JavaCodeResult ret = new JavaCodeResult();
ret.attach( "(").attach(this.params.printJavaCode(resultSet)).attach(")");
ret.attach( " -> ").attach( this.method_body.printJavaCode(resultSet));
return ret;
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
ret.add(this.method_body);
for(FormalParameter fp : this.params)ret.add(fp);
return ret;
}
@Override
public InstructionList genByteCode(ClassGenerator cg, TypeinferenceResultSet rs) {
DHBWConstantPoolGen cp = cg.getConstantPool();
InstructionList il = new InstructionList();
/*
* Anpassen der Parameter
*/
ParameterList lambdaMethodParams = new ParameterList();
//if(isStatic) //TODO: Abfrage, ob der Lambda-Ausdruck sich in einem statischen Kontext befindet
lambdaMethodParams.set_AddParameter(new FormalParameter("this", this.getParentClass().getType()));
il.append(InstructionFactory.createLoad( org.apache.bcel.generic.Type.OBJECT, 0)); //This auf den Stack legen
for(Statement s : method_body.get_Statement()){
if(s instanceof LocalOrFieldVarOrClassname){
LocalOrFieldVarOrClassname var = (LocalOrFieldVarOrClassname) s;
lambdaMethodParams.set_AddParameter(new FormalParameter(var.get_Name(),var.getType()));
//Direkt die Load instruktionen für die Parameter anhängen:
il.append(var.createLoad(cg, rs)); //Hier kann noch der cg vom Lambda-Ausdruck verwendet werden
}
}
//Das sind die zusätzlich benötigten Parameter für den invokedynamic aufruf: (hier gehört auch noch das "this" dazu)
org.apache.bcel.generic.Type[] additionalParameters = lambdaMethodParams.getBytecodeTypeList(cg, rs);
for(FormalParameter param : params){
lambdaMethodParams.set_AddParameter(param);
}
//Im Anschluss wird der this Parameter wieder von den LambdaMethodParams entfernt!
lambdaMethodParams.formalparameter.remove(0);
/*
* Generieren der Methode
*/
org.apache.bcel.generic.Type retType = method_body.getType().getBytecodeType(cg, rs);
MethodGenerator lambdaMethod = new MethodGenerator(0, retType,
lambdaMethodParams.getBytecodeTypeList(cg, rs), lambdaMethodParams.getParameterNameArray(), cg.createLambdaMethodName(),
this.getParentClass().getName().toString(), new InstructionList(), cg.getConstantPool());
lambdaMethod.setAccessFlags(Const.ACC_PRIVATE+Const.ACC_SYNTHETIC);
cg.setMethodeGenerator(lambdaMethod);
cg.addMethod(lambdaMethod.createMethod(cg, lambdaMethodParams, method_body.getType(), method_body, rs));
/*
* Generieren der Bootstrap Methode
*/
//Argumentliste für die Bootstrap Methode zusammensetzen:
ArrayList<Integer> arguments = new ArrayList<Integer>();
ConstantMethodType functionalMethodType = new ConstantMethodType(cp.addUtf8(lambdaType.getBytecodeInvokeDynamicSignature(cg, rs)));
int implMethodKind = 7; // 7 = InvokeSpecial @see https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.5
ConstantMethodHandle implMethod = new ConstantMethodHandle(implMethodKind,cg.getConstantPool().addMethodref(lambdaMethod)); //Das zweite Argument ist der MethodRef zur LambdaMethode
arguments.add(cp.addConstant(functionalMethodType));
arguments.add(cp.addConstant(implMethod));
arguments.add(cp.addConstant(functionalMethodType));
String bootstrapSignature = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;";
int lambdaMetafactoryRefIndex = cp.addMethodref("java.lang.invoke.LambdaMetafactory", "metafactory", bootstrapSignature);
//reference kind 6 steht für invokestatic
int lambdaMetafactoryHandle = cp.addConstant(new ConstantMethodHandle(6, lambdaMetafactoryRefIndex));
int[] argumentsArray = new int[arguments.size()];
for(int i = 0; i<arguments.size();i++){
argumentsArray[i] = arguments.get(i);
}
BootstrapMethod bMethod = new BootstrapMethod(lambdaMetafactoryHandle, argumentsArray);
/*
* Innere Klasse für das funktionieren der Bootstrap-Methode anfügen
*/
int innerClassIndex = cp.addClass("java.lang.invoke.MethodHandles$Lookup");
int innerClassName = cp.addUtf8("Lookup");
int outerClassIndex = cp.addClass("java.lang.invoke.MethodHandles");
int accessFlags = Const.ACC_FINAL + Const.ACC_STATIC + Const.ACC_PUBLIC;
InnerClass innerClassAttribute = new InnerClass(innerClassIndex, outerClassIndex, innerClassName,accessFlags);
cg.addInnerClass(innerClassAttribute);
/*
* InvokeDynamik-Instruktion anhängen
*/
String interfaceMethodName = "apply"; //Das ist ein Hack, funktioniert momentan, da nur FunN Interfaces für LambdaAusdrücke funktionieren
//String invokeDynamicType = org.apache.bcel.generic.Type.getMethodSignature(lambdaType.getBytecodeType(cg, rs), additionalParameters);
String invokeDynamicType = org.apache.bcel.generic.Type.getMethodSignature(lambdaType.getBytecodeType(cg, rs), additionalParameters);
il.append(cg.getInstructionFactory().createInvokeDynamic(interfaceMethodName,invokeDynamicType, bMethod));
return il;
}
}

@ -1,6 +1,11 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.misc.DeclId;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint;
/**
* Der FormalParameter einer LambdaExpression hat gesonderte Eigenschaften.
@ -10,8 +15,16 @@ import de.dhbwstuttgart.syntaxtree.FormalParameter;
public class LambdaParameter extends FormalParameter {
public LambdaParameter(FormalParameter fp) {
super(null,null,0);
super(fp.getDeclId());
this.setType(fp.getType());
this.parent = fp.getParent();
this.inferencelog = fp.inferencelog;
}
@Override
public TypeInsertPoint createTypeInsertPoint(TypePlaceholder tph,
ResultSet resultSet) {
return null;//Ein LambdaParameter darf keine Typen einsetzen.
}
}

Some files were not shown because too many files have changed in this diff Show More