diff --git a/src/de/dhbwstuttgart/JvmDisassembler/.cvsignore b/src/de/dhbwstuttgart/JvmDisassembler/.cvsignore new file mode 100755 index 000000000..246022761 --- /dev/null +++ b/src/de/dhbwstuttgart/JvmDisassembler/.cvsignore @@ -0,0 +1,3 @@ +jvmDisassebler.class +*~* +*.class diff --git a/src/de/dhbwstuttgart/JvmDisassembler/GenericsTest.java b/src/de/dhbwstuttgart/JvmDisassembler/GenericsTest.java new file mode 100755 index 000000000..5185f0562 --- /dev/null +++ b/src/de/dhbwstuttgart/JvmDisassembler/GenericsTest.java @@ -0,0 +1,18 @@ +package de.dhbwstuttgart.JvmDisassembler; + + + +class GenericsTest { + + Integer k; + GenericsTest pp; + Object j; + + a meth(a arg) { + return arg; + } + + t meth2(b arg, t arg2) { + return arg2; + } +} diff --git a/src/de/dhbwstuttgart/JvmDisassembler/jvmDisassembler.java b/src/de/dhbwstuttgart/JvmDisassembler/jvmDisassembler.java new file mode 100755 index 000000000..6497d5db9 --- /dev/null +++ b/src/de/dhbwstuttgart/JvmDisassembler/jvmDisassembler.java @@ -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 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 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 const_pool = new Menge(); + 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 + } +} diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeTypeFactory.java b/src/de/dhbwstuttgart/bytecode/BytecodeTypeFactory.java new file mode 100644 index 000000000..8d9a3fe92 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/BytecodeTypeFactory.java @@ -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 generateReferenceTypeSignature(RefType t){ + if(t instanceof RefType)return generateReferenceTypeSignature((RefType)t); + throw new NotImplementedException(); + } + + 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 generateReferenceTypeSignature(GenericTypeVar t){ + String ret = "T" + t.get_Name(); + return ret + ";"; + } + + +} diff --git a/src/de/dhbwstuttgart/bytecode/ClassGenerator.java b/src/de/dhbwstuttgart/bytecode/ClassGenerator.java new file mode 100644 index 000000000..1c4faf124 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/ClassGenerator.java @@ -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 generics; + + private Menge usedTPHs = new Menge<>(); + + private Map extraClasses = new HashMap<>(); + private List methodsNamesAndTypes = new LinkedList<>(); + private MethodGenerator methodGenerator; + + public ClassGenerator(JavaClassName name, Type superClass, List 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 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 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 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 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 it = ((Menge)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 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; + } + + +} diff --git a/src/de/dhbwstuttgart/bytecode/DHBWConstantPoolGen.java b/src/de/dhbwstuttgart/bytecode/DHBWConstantPoolGen.java new file mode 100644 index 000000000..788d34b51 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/DHBWConstantPoolGen.java @@ -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 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; + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/DHBWInstructionFactory.java b/src/de/dhbwstuttgart/bytecode/DHBWInstructionFactory.java new file mode 100644 index 000000000..3b31a935c --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/DHBWInstructionFactory.java @@ -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 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()); + } +} diff --git a/src/de/dhbwstuttgart/bytecode/MethodGenerator.java b/src/de/dhbwstuttgart/bytecode/MethodGenerator.java new file mode 100644 index 000000000..f208f34d5 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/MethodGenerator.java @@ -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 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 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); + } + + +} + diff --git a/src/de/dhbwstuttgart/bytecode/TypePlaceholderType.java b/src/de/dhbwstuttgart/bytecode/TypePlaceholderType.java new file mode 100644 index 000000000..d012e827c --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/TypePlaceholderType.java @@ -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; + } + +} \ No newline at end of file diff --git a/src/de/dhbwstuttgart/bytecode/WildcardType.java b/src/de/dhbwstuttgart/bytecode/WildcardType.java new file mode 100644 index 000000000..308f7a159 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/WildcardType.java @@ -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; + } + +} diff --git a/src/de/dhbwstuttgart/core/ConsoleInterface.java b/src/de/dhbwstuttgart/core/ConsoleInterface.java index bbddfdfe8..94d40e3bd 100755 --- a/src/de/dhbwstuttgart/core/ConsoleInterface.java +++ b/src/de/dhbwstuttgart/core/ConsoleInterface.java @@ -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 filenames = new Menge(); + for(String file : args){ + filenames.add(file); + } + Logger.setStandardConfiguration(new LoggerConfiguration()); // sämtliches Logging unterdrücken + + run(filenames); + } + + public static void run(Menge filenames){ + Menge resultSet = null; + + MyCompilerAPI compiler = MyCompiler.getAPI(new LoggerConfiguration()); + try{ + ///////////////////////// + // Parsen: + ///////////////////////// + Menge 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 resultJavaCodes = new ArrayList(); + 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()); + } + } + } diff --git a/src/de/dhbwstuttgart/core/IItemWithOffset.java b/src/de/dhbwstuttgart/core/IItemWithOffset.java index a2c797c02..d6b7f3bf3 100755 --- a/src/de/dhbwstuttgart/core/IItemWithOffset.java +++ b/src/de/dhbwstuttgart/core/IItemWithOffset.java @@ -3,4 +3,5 @@ package de.dhbwstuttgart.core; public interface IItemWithOffset { + public int getOffset(); } diff --git a/src/de/dhbwstuttgart/core/MyCompiler.java b/src/de/dhbwstuttgart/core/MyCompiler.java index ce3babdf9..2bd5b2c18 100755 --- a/src/de/dhbwstuttgart/core/MyCompiler.java +++ b/src/de/dhbwstuttgart/core/MyCompiler.java @@ -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 testPair = null; + + /** + * Author: J�rg B�uerle
+ * 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
+ * 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 + * NewTVar(jclass) (siehe Algorithmus 5.17 TRProg, Martin Pl�micke) + * aufgerufen. + *
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
+ * Initialisiert den Compiler + */ + public void init(){ + TypePlaceholder.deleteRegistry(); + } + /** + * Author: J�rg B�uerle
+ * 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
+ * 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 typeReconstruction(Menge m_AbstractSyntaxTree) throws NullPointerException{ + inferencelog.info("##########################################", Section.TYPEINFERENCE); + inferencelog.info("# TypeReconstruction-Algorithmus - START #", Section.TYPEINFERENCE); + inferencelog.info("##########################################\n", Section.TYPEINFERENCE); + + TypeAssumptions globalAssumptions = makeFunNAssumptions(); + Menge result = new Menge(); + 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 parse(Menge filenames) throws ParserError { + Menge m_AbstractSyntaxTree = new Menge(); + + 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 generateBytecode(Menge m_AbstractSyntaxTree, TypeinferenceResults typeinferenceResults) { + //SourceFile parsedFile = this.m_AbstractSyntaxTree.firstElement(); + //Class parsedClass = parsedFile.KlassenVektor.firstElement(); + Menge ret = new Menge<>(); + for(SourceFile sf : m_AbstractSyntaxTree){ + ret.addAll(sf.generateBytecode(typeinferenceResults)); + } + return ret; + } } diff --git a/src/de/dhbwstuttgart/core/MyCompilerAPI.java b/src/de/dhbwstuttgart/core/MyCompilerAPI.java index a9a427265..6a192eb8b 100755 --- a/src/de/dhbwstuttgart/core/MyCompilerAPI.java +++ b/src/de/dhbwstuttgart/core/MyCompilerAPI.java @@ -2,6 +2,21 @@ package de.dhbwstuttgart.core; // ino.end +// ino.module.MyCompilerAPI.8570.import +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; + // ino.class.MyCompilerAPI.21328.description type=javadoc /** * Schnittstellen-Klasse zum Compiler. Diese Klasse soll der @@ -27,5 +42,90 @@ public interface MyCompilerAPI // ino.method.init.21331.declaration public void init(); // ino.end + + // ino.method.parse.21334.decldescription type=javadoc + /** + * Author: Jörg Bäuerle
+ * 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. + */ + // ino.end + // ino.method.parse.21334.declaration + public SourceFile parse(File file) + throws FileNotFoundException, IOException, JavaParser.yyException; + // ino.end + + // ino.method.parse.21337.decldescription type=javadoc + /** + * Author: Jörg Bäuerle
+ * 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. + + // ino.end + // ino.method.parse.21337.declaration + public void parse(String srcCode) + throws IOException, JavaParser.yyException; + // ino.end + */ + + // ino.method.typeReconstruction.21340.decldescription type=javadoc + /** + * Author: Jörg Bäuerle
+ * 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. + */ + // ino.end + // ino.method.typeReconstruction.21340.declaration + public Menge typeReconstruction(Menge m_AbstractSyntaxTree) throws NullPointerException; + // ino.end + + // ino.method.setOutputDir.21349.decldescription type=javadoc + /** + * Author: Juergen Schmiing
+ * Legt das Ausgabeverzeichnis fuer die class-Files fest. + */ + // ino.end + // ino.method.setOutputDir.21349.declaration + public void setOutputDir(String dir); + // ino.end + + // ino.method.getOutputDir.21352.decldescription type=javadoc + /** + * Author: Juergen Schmiing
+ * Gibt das Ausgabeverzeichnis fuer die class-Files zurueck. + */ + // ino.end + // ino.method.getOutputDir.21352.declaration + public String getOutputDir(); + // ino.end + + /** + * Parst zusammenhängende JavaKlassen in verschiedenen Dateien. + * @param filenames - Eine Liste von Quellcodedateien, welche gseparst werden sollen + * @return + */ + public Menge parse(Menge 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 generateBytecode(Menge m_AbstractSyntaxTree, TypeinferenceResults typeinferenceResults); } // ino.end diff --git a/src/de/dhbwstuttgart/logger/Logger.java b/src/de/dhbwstuttgart/logger/Logger.java new file mode 100755 index 000000000..725c6fd5c --- /dev/null +++ b/src/de/dhbwstuttgart/logger/Logger.java @@ -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 LOGGER_DIRECTORY = new HashMap<>(); + + private String name; + private final HashMap 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 .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{ + 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 ""; + } +} diff --git a/src/de/dhbwstuttgart/logger/LoggerConfiguration.java b/src/de/dhbwstuttgart/logger/LoggerConfiguration.java new file mode 100644 index 000000000..ce601fbc3 --- /dev/null +++ b/src/de/dhbwstuttgart/logger/LoggerConfiguration.java @@ -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> 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 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); +} diff --git a/src/de/dhbwstuttgart/logger/Section.java b/src/de/dhbwstuttgart/logger/Section.java new file mode 100644 index 000000000..0ea53b92a --- /dev/null +++ b/src/de/dhbwstuttgart/logger/Section.java @@ -0,0 +1,8 @@ +package de.dhbwstuttgart.logger; + +public enum Section { + TYPEINFERENCE, + PARSER, + CODEGEN, + UNIFY, FINITECLOSURE, ASSUMPTIONS; +} diff --git a/src/de/dhbwstuttgart/logger/SectionLogger.java b/src/de/dhbwstuttgart/logger/SectionLogger.java new file mode 100644 index 000000000..15d36289f --- /dev/null +++ b/src/de/dhbwstuttgart/logger/SectionLogger.java @@ -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); + } +} diff --git a/src/de/dhbwstuttgart/logger/Timestamp.java b/src/de/dhbwstuttgart/logger/Timestamp.java new file mode 100644 index 000000000..829ccbd8a --- /dev/null +++ b/src/de/dhbwstuttgart/logger/Timestamp.java @@ -0,0 +1,50 @@ +package de.dhbwstuttgart.logger; + +import java.util.Stack; + + +public class Timestamp{ + String name; + + Stack 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(); + } +} \ No newline at end of file diff --git a/src/de/dhbwstuttgart/logger/Timewatch.java b/src/de/dhbwstuttgart/logger/Timewatch.java new file mode 100644 index 000000000..26916feaf --- /dev/null +++ b/src/de/dhbwstuttgart/logger/Timewatch.java @@ -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 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; + } +} + diff --git a/src/de/dhbwstuttgart/syntaxtree/Class.java b/src/de/dhbwstuttgart/syntaxtree/Class.java index 9680fc7d5..5ad5122c3 100755 --- a/src/de/dhbwstuttgart/syntaxtree/Class.java +++ b/src/de/dhbwstuttgart/syntaxtree/Class.java @@ -1,11 +1,18 @@ package de.dhbwstuttgart.syntaxtree; +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.Section; import de.dhbwstuttgart.core.IItemWithOffset; 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.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.typeinference.*; +import de.dhbwstuttgart.typeinference.assumptions.ClassAssumption; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; import java.util.ArrayList; import java.util.List; @@ -13,8 +20,15 @@ import java.util.List; /** * Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces */ -public class Class extends GTVDeclarationContext implements IItemWithOffset, Generic +public class Class extends GTVDeclarationContext implements IItemWithOffset, Generic, GenericTypeInsertable { + /** + * Loggerinstanzen + */ + protected static Logger inferencelog = Logger.getLogger("inference"); + protected static Logger codegenlog = Logger.getLogger("codegen"); + protected static Logger parserlog = Logger.getLogger("parser"); + protected Logger typinferenzLog = Logger.getLogger(Class.class.getName()); protected Modifiers modifiers; protected JavaClassName name; @@ -26,5 +40,222 @@ public class Class extends GTVDeclarationContext implements IItemWithOffset, Gen protected boolean isInterface; private List implementedInterfaces; + ///////////////////////////////////////////////////////////////////////// + // 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.
+ * (siehe Algorithmus 5.17 TRProg, Martin Pl�micke) + *
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(); + + for(Type gparam : this.get_ParaList()){ + if(gparam instanceof GenericTypeVar)assumptions.add(((GenericTypeVar)gparam).createAssumptions()); //Constraints für die Generischen Variablen erstellen und diese dem AssumptionsSet hinzufügen + } + for(Type gparam : this.get_ParaList()){ + if(gparam instanceof GenericTypeVar)oderConstraints.add(((GenericTypeVar)gparam).TYPE(assumptions)); //Constraints für die Generischen Variablen erstellen und diese dem AssumptionsSet hinzufügen + } + + 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; + } + + /** + *
Author: Martin Pl�micke + * @return + */ + public String toString() + { + return name.toString(); + } + + public String getTypeInformation(Menge methodList, Menge fieldList){ + String ret = this.name+": "; + for(Expr field : fieldList){ + ret+=field.getTypeInformation()+"\n"; + } + for(Method m : methodList){ + ret+=m.getTypeInformation()+"\n"; + } + return ret; + } + + + /** + * 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 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 String getDescription(){ + return "class "+this.getName(); + } + + @Override + public void setGenericParameter(GenericDeclarationList params) { + this.genericClassParameters = params; + } + + @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; + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/Constructor.java b/src/de/dhbwstuttgart/syntaxtree/Constructor.java index 7b074f679..f52720bc7 100644 --- a/src/de/dhbwstuttgart/syntaxtree/Constructor.java +++ b/src/de/dhbwstuttgart/syntaxtree/Constructor.java @@ -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(), + "", 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(); + } + + + } diff --git a/src/de/dhbwstuttgart/syntaxtree/Field.java b/src/de/dhbwstuttgart/syntaxtree/Field.java index f9f2be2e1..f17e78700 100644 --- a/src/de/dhbwstuttgart/syntaxtree/Field.java +++ b/src/de/dhbwstuttgart/syntaxtree/Field.java @@ -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 getGenericParameter() { + Menge 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 getChildren() { + Menge 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; + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/FieldDeclaration.java b/src/de/dhbwstuttgart/syntaxtree/FieldDeclaration.java index 0e09b61ae..b9124c427 100644 --- a/src/de/dhbwstuttgart/syntaxtree/FieldDeclaration.java +++ b/src/de/dhbwstuttgart/syntaxtree/FieldDeclaration.java @@ -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 getChildren() { + Menge 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; + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/FormalParameter.java b/src/de/dhbwstuttgart/syntaxtree/FormalParameter.java index 2b632bc9e..a56767b45 100755 --- a/src/de/dhbwstuttgart/syntaxtree/FormalParameter.java +++ b/src/de/dhbwstuttgart/syntaxtree/FormalParameter.java @@ -1,15 +1,89 @@ 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.Type; +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 Type type; private String name; + protected static Logger inferencelog = Logger.getLogger("inference"); - public FormalParameter(String name, RefType type, int offset){ + public FormalParameter(String name, Type 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 Type 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; + Type t = resultSet.getTypeEqualTo(tph); + return new TypeInsertPoint(this, this, t, resultSet); + } + + @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(); + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/GTVDeclarationContext.java b/src/de/dhbwstuttgart/syntaxtree/GTVDeclarationContext.java index 100e09472..5e70575ce 100644 --- a/src/de/dhbwstuttgart/syntaxtree/GTVDeclarationContext.java +++ b/src/de/dhbwstuttgart/syntaxtree/GTVDeclarationContext.java @@ -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(); } diff --git a/src/de/dhbwstuttgart/syntaxtree/Generic.java b/src/de/dhbwstuttgart/syntaxtree/Generic.java index 227ccc5b2..743cdbc0e 100644 --- a/src/de/dhbwstuttgart/syntaxtree/Generic.java +++ b/src/de/dhbwstuttgart/syntaxtree/Generic.java @@ -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 getGenericParameter(); } \ No newline at end of file diff --git a/src/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java b/src/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java index cdf9a633e..c70663c3a 100644 --- a/src/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java +++ b/src/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java @@ -1,7 +1,12 @@ 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.Menge; +import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar; /** * Stellt eine Deklarations-Liste von Generischen Variablen dar. @@ -12,9 +17,10 @@ import java.util.*; public class GenericDeclarationList extends SyntaxTreeNode implements Iterable{ private int offsetOfLastElement; - private List gtvs = new ArrayList<>(); + private List gtvs = new Menge<>(); public GenericDeclarationList(List values, int endOffset) { + super(endOffset); gtvs = values; this.offsetOfLastElement = endOffset; } @@ -23,8 +29,34 @@ public class GenericDeclarationList extends SyntaxTreeNode implements Iterable iterator() { - return null; + return this.gtvs.iterator(); + } + + @Override + public Menge getChildren() { + Menge 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 getGTVList() { + return this.gtvs; } } diff --git a/src/de/dhbwstuttgart/syntaxtree/GenericTypeVar.java b/src/de/dhbwstuttgart/syntaxtree/GenericTypeVar.java index 7e180b990..a1ecd49c2 100755 --- a/src/de/dhbwstuttgart/syntaxtree/GenericTypeVar.java +++ b/src/de/dhbwstuttgart/syntaxtree/GenericTypeVar.java @@ -1,6 +1,10 @@ package de.dhbwstuttgart.syntaxtree; import de.dhbwstuttgart.syntaxtree.type.RefType; +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; @@ -26,6 +30,7 @@ public class GenericTypeVar extends SyntaxTreeNode public GenericTypeVar(String s, List 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 +54,19 @@ public class GenericTypeVar extends SyntaxTreeNode return "BoGTV " + this.name; } + @Override + public List getChildren() { + List ret = new ArrayList<>(); + ret.addAll(this.bounds); + return ret; + } + + @Override + public JavaCodeResult printJavaCode(ResultSet resultSet) { + throw new NotImplementedException(); + } + + public String getName() { + return name; + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/Method.java b/src/de/dhbwstuttgart/syntaxtree/Method.java index 6b77c24b3..638c095ab 100755 --- a/src/de/dhbwstuttgart/syntaxtree/Method.java +++ b/src/de/dhbwstuttgart/syntaxtree/Method.java @@ -4,15 +4,32 @@ package de.dhbwstuttgart.syntaxtree; import java.util.ArrayList; import java.util.List; -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.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.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; // ino.class.Method.23482.declaration /** @@ -23,22 +40,331 @@ 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 Type returntype; private String name; - private List types_in_parameterlist = new ArrayList<>(); + private Menge types_in_parameterlist = new Menge(); private Modifiers modifiers; + + protected static Logger inferencelog = Logger.getLogger("inference"); + protected static Logger parserlog = Logger.getLogger("parser"); - public Method(String name, RefType returnType, ParameterList parameterList, Block block, + /** + * + * @param name + * @param returnType + * @param params + * @param block - use null to create abstract method + * @param offset + */ + public Method(String name, Type returnType, ParameterList params, Block block, int offset) { + this(name, returnType, params, new ExceptionList(), block, offset); + } + + public Method(String name, Type returnType, ParameterList params, ExceptionList exceptions, Block block, int offset){ + super(name, generateMethodType(returnType, params), offset); + } + + public Method(String name, Type returnType, ParameterList parameterList, Block block, GenericDeclarationList gtvDeclarations, int offset) { - super(name, returnType, offset); + this(offset); this.name = name; this.parameterlist = parameterList; this.block = block; + this.setGenericParameter(gtvDeclarations); + this.returntype = returnType; } + public JavaClassName getTypeName() + { + if (this.getType() == null) + return null; + else + return this.getType().getName(); + } + + + public Block get_Block() + { + return block; + } + + public ParameterList getParameterList() + { + return this.parameterlist; + } + + /** + * Author: Jrg Buerle
+ * + * @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; + } + + public int getOverloadedID() + { + return (overloadedID); + } + + + public void setOverloadedID(int overloadedID) + { + this.overloadedID = overloadedID; + } + + public String get_Name() + { + return name; + } + + public Menge get_Type_Paralist() + { + return types_in_parameterlist; + } + + public int getLineNumber() + { + return m_LineNumber; + } + + public void setLineNumber(int lineNumber) + { + m_LineNumber = lineNumber; + } + + public int getOffset() + { + return m_Offset; + } + + public int getVariableLength() + { + return get_Name().length(); + } + + public void setOffset(int Offset) + { + m_Offset = Offset; + } + + /** + *
+ * Author: Jrg Buerle + * + * @return + */ + public int getTypeLineNumber() + { + return this.getLineNumber(); + } + + /** + *
+ * Author: Martin Pl�micke + * + * @return + */ + public String toString() + { + return this.getType() + " " + this.get_Name() + ((block != null) ? block.toString() : ""); + } + + /** + * Legt fuer die ByteCodeGen fest, ob Bytecode innerhalb der Methode + * generiert wird. + */ + public void setAbstract(boolean b) + { + isAbstract = b; + } + + /** + * 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 getChildren() { + Menge ret = new Menge(); + 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 Type 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()); + 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 typeInterferenceResults = resultSets.getTypeReconstructions(this, cg); + DHBWInstructionFactory _factory = cg.getInstructionFactory(); + + for(TypeinferenceResultSet t: typeInterferenceResults){ + addMethodToClassGenerator(cg, _factory, t, classObj); + } + } +<<<<<<< HEAD + + private void addMethodToClassGenerator(ClassGenerator cg, DHBWInstructionFactory _factory, TypeinferenceResultSet t, Class parentClass) { +======= + + private void addMethodToClassGenerator(ClassGenerator cg, DHBWInstructionFactory _factory, TypeinferenceResultSet t) { +>>>>>>> refactoring + DHBWConstantPoolGen _cp = cg.getConstantPool(); + InstructionList il = new InstructionList(); + + ArrayList argumentTypes = new ArrayList(); + ArrayList argumentNames = new ArrayList(); + + 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; + + Type returnType = this.getType(); + + MethodGenerator method = new MethodGenerator(constants, returnType.getBytecodeType(cg, t), +<<<<<<< HEAD + argumentTypes.toArray(new org.apache.bcel.generic.Type[parameterlist.size()]) + , argumentNames.toArray(new String[parameterlist.size()]), this.get_Name(), parentClass.name.toString(), il, _cp); +======= + argumentTypes.toArray(new org.apache.bcel.generic.Type[parameterlist.size()]) , + argumentNames.toArray(new String[parameterlist.size()]), this.get_Method_Name(), + getParentClass().name.toString(), il, _cp); +>>>>>>> refactoring + + cg.setMethodeGenerator(method); + + cg.addMethod(method.createMethod(cg, getParameterList(), returnType, get_Block(), t)); + } + + private void generateArgumentList(ArrayList argumentTypes, ArrayList argumentNames, ClassGenerator cg, TypeinferenceResultSet t) { + for(FormalParameter parameter : this.parameterlist){ + argumentTypes.add(parameter.getType().getBytecodeType(cg, t)); + argumentNames.add(parameter.getIdentifier()); + } + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/ParameterList.java b/src/de/dhbwstuttgart/syntaxtree/ParameterList.java index 68f64181b..4ad42fc5e 100755 --- a/src/de/dhbwstuttgart/syntaxtree/ParameterList.java +++ b/src/de/dhbwstuttgart/syntaxtree/ParameterList.java @@ -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 { - public List formalparameter; + public List formalparameter = new Menge(); public ParameterList(List params){ this.formalparameter = params; @@ -26,9 +33,88 @@ public class ParameterList extends SyntaxTreeNode implements Iterable + * @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 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 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 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; + } + } diff --git a/src/de/dhbwstuttgart/syntaxtree/SourceFile.java b/src/de/dhbwstuttgart/syntaxtree/SourceFile.java index 83b70d4fe..679822757 100755 --- a/src/de/dhbwstuttgart/syntaxtree/SourceFile.java +++ b/src/de/dhbwstuttgart/syntaxtree/SourceFile.java @@ -1,20 +1,45 @@ package de.dhbwstuttgart.syntaxtree; -import java.util.*; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +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.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.syntaxtree.type.Void; +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 { - + + protected static Logger codegenlog = Logger.getLogger("codegen"); + protected static Logger inferencelog = Logger.getLogger("inference"); private String pkgName; - public List KlassenVektor = new ArrayList<>(); + public List KlassenVektor = new Menge(); private List imports; /** @@ -25,6 +50,500 @@ public class SourceFile extends SyntaxTreeNode this.KlassenVektor = classDefinitions; } + /** + * 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 schnitt1 (Menge var, Menge> vars, Menge indexe) { + int j = -1; + for (Menge varelems : vars) { + j++; + if (varelems != null) { + if (var.stream().map(x -> varelems.contains(x)).reduce(false, (a,b) -> (a || b)) + && (!indexe.contains(j))) + { + Menge 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; + } + + /** + * Bildet Schnittmengen der Mengen von Typeplaceholders + * Rueckgabe ist die Menge der Menge von Indizies die Schnittmengen sind. + * @param vars + * @return + */ + public static Menge> schnitt (Menge> vars) { + Menge> ret = new Menge<>(); + int i = -1; + for (Menge var : vars) { + i++; + if (var != null) {//Element wurde noch bearbeitet + Menge indexe = new Menge<>(); + indexe.add(i); + ret.add(schnitt1(var, vars, indexe)); + } + } + return ret; + } + + public static Set> cartesianProduct(List 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> constraintsclonevars = constraints.stream().map(p -> {Menge 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> 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> streamconstraintsclone = indexeset.stream().>map(x -> x.stream() + .map(i -> constraints.get(i)) + .>collect(Menge::new, Menge::add, Menge::addAll)); + //Menge> vecconstraintsclone = streamconstraintsclone.collect(Menge::new, Menge::add, Menge::addAll); + //System.out.println(); + //Schritt 4: Unifikation + Menge>> vecunifyResult = + //streamconstraintsclone.map(x -> Unify.unify(x, finiteClosure)).collect(Menge::new, Menge::add, Menge::addAll); + //DEBUG-Variante + streamconstraintsclone.map(x -> + { Set> z = new TypeUnify().unify(x, finiteClosure); + return z; + } + ).collect(Menge::new, Menge::add, Menge::addAll); + + + //card gibt die Cardinalitaet der unifizierten Mengen an + Menge 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> cardprodret_start = new Menge<>(); + cardprodret_start.add(new Menge()); + + //cart. Produkt mit Linkverschiebung + Set> unifyResult = vecunifyResult.stream().reduce(cardprodret_start, (x, y) -> { + Set> cardprodret= new Menge<>(); + if (y.size() > 0) { + //System.out.println(y); + //Menge> cardprodretold = x; + //cardprodret = new Menge<>(); + for(Set xElement : x) { + for (Set yElement : y){ + Set 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. + *
Author: J�rg B�uerle + * @return Liste aller m�glichen Typkombinationen + * @throws CTypeReconstructionException Wenn was schief l�uft + */ + public Menge typeReconstruction(TypeAssumptions globalAssumptions) +{ + Menge ret = new Menge(); + + //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> xConstraints = unifyConstraints.cartesianProduct(); + + + //Sets zu Listen umwandeln: + //Set> 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 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> 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> convertedResult = unifyResult.parallelStream().>map((Set resultSet)->{ + Menge innerConvert = resultSet.stream().map((UnifyPair mp)->UnifyTypeFactory.convert(mp)) + .collect(Menge::new, Menge::add, Menge::addAll); + return innerConvert; + }).collect(Menge::new, Menge::add, Menge::addAll); + + Menge convertedConstraints = constraints.stream().map( + (UnifyPair mp)->{return UnifyTypeFactory.convert(mp);} + ).collect(Menge::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()))); + + + //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 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 imports, boolean withSubtypes) + // ino.end + // ino.method.makeBasicAssumptionsFromJRE.21409.body + { + return null; + } + // ino.end + + private Class getSuperClassOfJREClass(java.lang.Class x, TypeAssumptions ass) { + Class ret; + java.lang.Class s = x.getSuperclass(); + if(s == null){ + return new Class("java.lang.Object",new Modifiers(), 0); + } + + Menge supertypeGenPara = new Menge<>();//Die Generischen Parameter für die Superklasse berechnen: + java.lang.reflect.TypeVariable[] superclassTVS=s.getTypeParameters(); + for(int tvi=0;tvi searchMenge, String searchString) + { + boolean found = false; + for(UsedId id : searchMenge) + { + String s = id.getQualifiedName().toString(); + found |= s.equals(searchString); + } + return found; + } + + + // ino.method.createTypeFromJavaGenericType.21415.definition + private Type createTypeFromJavaGenericType(java.lang.reflect.Type type, java.lang.Class cl, HashtablejreSpiderRegistry, Class parentClass) + // ino.end + // ino.method.createTypeFromJavaGenericType.21415.body + { + /* 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)); + } + //} + } + + // ino.method.getPackageName.21427.defdescription type=javadoc + /** + * 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. + *
Author: J�rg B�uerle + * @param res + * / + * /*private void addClassNamesAndGenericsToRR(CTypeReconstructionResult res){ + * Iterator it = this.getClassIterator(); + * while(it.hasNext()){ + * Class cl = it.next(); + * res.addClassName(cl.get_classname()); + * Menge genericsList = new Menge(); + * + * for(int i =0; i getClassIterator() + // ino.end + // ino.method.getClassIterator.21439.body + { + return KlassenVektor.iterator(); + } + // ino.end + + // ino.method.getInterfaceIterator.21442.definition + public Iterator getInterfaceIterator() + // ino.end + // ino.method.getInterfaceIterator.21442.body + { + return InterfaceVektor.iterator(); + } + // ino.end + + + @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 getChildren() { + Menge ret = new Menge(); + 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 generateBytecode(TypeinferenceResults results) { + Menge 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 xClasses = t.isClassFromJavaX(); + for(Class xClass : xClasses){ + ByteCodeResult bC = xClass.genByteCode(results); + if(! ret.contains(bC))ret.add(bC); + } + } + } + */ + return ret; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/SyntaxTreeNode.java b/src/de/dhbwstuttgart/syntaxtree/SyntaxTreeNode.java index 01c66838e..11d64563a 100644 --- a/src/de/dhbwstuttgart/syntaxtree/SyntaxTreeNode.java +++ b/src/de/dhbwstuttgart/syntaxtree/SyntaxTreeNode.java @@ -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 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 uTPHs = insertSet.getUnresolvedTPHs(); + + if(uTPHs.size()>0){//Nur wenn es auch unresolvedTPHs gibt: + Menge 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); } diff --git a/src/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java b/src/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java new file mode 100644 index 000000000..400fc1e1a --- /dev/null +++ b/src/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java @@ -0,0 +1,189 @@ +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 static Method createEmptyMethod(String withSignature, Class parent) { + return ASTFactory.createMethod(withSignature, new ParameterList(), new Block(), parent); + } + + public static 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("", 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 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 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 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 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 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(), -1); + List gtvs = new ArrayList<>(); + for(TypeVariable jreTV : jreMethod.getTypeParameters()){ + GenericTypeVar gtv = createGeneric(jreTV, inClass); + 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 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 + * Um die Variablen korrekt zu generieren, muss die Klasse inClass übergeben werden, in der dieser Generic auftaucht + * TODO: Warum? + * Wird der AST von JREClass erzeugt, so kann davon ausgegangen werden, dass die Generics korrekt sind. + * Unser AST ist immutable und nicht im Kreis verzeigert. Generics die gleich heißen und gleiche Bounds haben, sind auch gleich. Müssen nicht die selben Instanzen sein. + * @param jreTypeVar + * @param inClass Die Klasse in der der Typ auftritt + * @return + */ + public GenericTypeVar createGeneric(TypeVariable jreTypeVar, java.lang.Class inClass){ + //TODO: Bei den Namen der Parameter des Generishen Typs nachschauen, ob er in der Klasse als Generic deklariert wurde + String name = jreTypeVar.getTypeName(); + List 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 BoundedGenericVar(); + } + return new GenericTypeVar(); + } + + + public static Class createInterface(String className, RefType superClass, Modifiers modifiers, + Menge supertypeGenPara, SourceFile parent){ + Class generatedClass = new Class(new JavaClassName(className), new ArrayList(), new ArrayList(), modifiers, + true, superClass, new ArrayList(), 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(); + } +} diff --git a/src/de/dhbwstuttgart/syntaxtree/factory/NameGenerator.java b/src/de/dhbwstuttgart/syntaxtree/factory/NameGenerator.java new file mode 100644 index 000000000..f20ea0cd5 --- /dev/null +++ b/src/de/dhbwstuttgart/syntaxtree/factory/NameGenerator.java @@ -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 + * TypePlaceholder.
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 + *
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. + *
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; + } + +} diff --git a/src/de/dhbwstuttgart/syntaxtree/factory/PrimitiveMethodsGenerator.java b/src/de/dhbwstuttgart/syntaxtree/factory/PrimitiveMethodsGenerator.java new file mode 100644 index 000000000..e8be68590 --- /dev/null +++ b/src/de/dhbwstuttgart/syntaxtree/factory/PrimitiveMethodsGenerator.java @@ -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 { + +} diff --git a/src/de/dhbwstuttgart/syntaxtree/factory/UnifyPairMengenBuilder.java b/src/de/dhbwstuttgart/syntaxtree/factory/UnifyPairMengenBuilder.java new file mode 100644 index 000000000..8caf73cc8 --- /dev/null +++ b/src/de/dhbwstuttgart/syntaxtree/factory/UnifyPairMengenBuilder.java @@ -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 buildMenge = new Menge(); + + 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 getPairMenge() { + return buildMenge; + } + + public Menge> getNestedPairMenge() { + Menge> nested = new Menge<>(); + + for(Pair p : buildMenge) { + Menge m = new Menge(); + m.add(p); + nested.add(m); + } + + return nested; + } + + public void clear() { + buildMenge = new Menge(); + } +} diff --git a/src/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java b/src/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java new file mode 100644 index 000000000..f2f48efed --- /dev/null +++ b/src/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java @@ -0,0 +1,217 @@ +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.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 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 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 params = new Menge<>(); + if(t.getParaList() != null && t.getParaList().size() > 0){ + for(Type pT : t.getParaList()){ + params.add(UnifyTypeFactory.convert(pT)); + } + } + ret = FunNType.getFunNType(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 oC : set.getPairs()){ + ret.add(UnifyTypeFactory.convert(oC)); + } + return ret; + } + + public static UnifyPair convert(EinzelElement 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 convert(TypeParams typeParams) { + List ret = new ArrayList<>(); + for(UnifyType uT : typeParams){ + Type toAdd = convert(uT); + ret.add(toAdd); + } + return ret; + } + +} diff --git a/src/de/dhbwstuttgart/syntaxtree/factory/Unify_FC_TTO_Builder.java b/src/de/dhbwstuttgart/syntaxtree/factory/Unify_FC_TTO_Builder.java new file mode 100644 index 000000000..aa3a40161 --- /dev/null +++ b/src/de/dhbwstuttgart/syntaxtree/factory/Unify_FC_TTO_Builder.java @@ -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 fc = new Menge(); + private Menge classes = new Menge(); + + /* + 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(); + classes = new Menge(); + } +} diff --git a/src/de/dhbwstuttgart/syntaxtree/modifier/Abstract.java b/src/de/dhbwstuttgart/syntaxtree/modifier/Abstract.java index 71d891a04..11661bcd8 100755 --- a/src/de/dhbwstuttgart/syntaxtree/modifier/Abstract.java +++ b/src/de/dhbwstuttgart/syntaxtree/modifier/Abstract.java @@ -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"); + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/modifier/Final.java b/src/de/dhbwstuttgart/syntaxtree/modifier/Final.java index 95b2e5c61..03be2767c 100755 --- a/src/de/dhbwstuttgart/syntaxtree/modifier/Final.java +++ b/src/de/dhbwstuttgart/syntaxtree/modifier/Final.java @@ -1,6 +1,10 @@ // ino.module.Final.8586.package package de.dhbwstuttgart.syntaxtree.modifier; +import de.dhbwstuttgart.typeinference.JavaCodeResult; +import de.dhbwstuttgart.typeinference.ResultSet; + + // ino.class.Final.24022.description type=javadoc /** * Stellt den Modifier Final dar. @@ -22,5 +26,10 @@ public class Final extends Modifier } // ino.end + @Override + public JavaCodeResult printJavaCode(ResultSet resultSet) { + return new JavaCodeResult("final"); + } + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/modifier/InterfaceModifier.java b/src/de/dhbwstuttgart/syntaxtree/modifier/InterfaceModifier.java index 720faaa92..b6fd3ece1 100755 --- a/src/de/dhbwstuttgart/syntaxtree/modifier/InterfaceModifier.java +++ b/src/de/dhbwstuttgart/syntaxtree/modifier/InterfaceModifier.java @@ -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"); + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/modifier/Modifier.java b/src/de/dhbwstuttgart/syntaxtree/modifier/Modifier.java index 6cb5568c6..22bcda47d 100755 --- a/src/de/dhbwstuttgart/syntaxtree/modifier/Modifier.java +++ b/src/de/dhbwstuttgart/syntaxtree/modifier/Modifier.java @@ -1,6 +1,8 @@ // ino.module.Modifier.8587.package package de.dhbwstuttgart.syntaxtree.modifier; +import de.dhbwstuttgart.typeinference.JavaCodeResult; +import de.dhbwstuttgart.typeinference.ResultSet; // ino.end // ino.class.Modifier.24029.declaration @@ -18,5 +20,6 @@ public abstract class Modifier public abstract short getBitmask(); // ino.end + public abstract JavaCodeResult printJavaCode(ResultSet resultSet); } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/modifier/Modifiers.java b/src/de/dhbwstuttgart/syntaxtree/modifier/Modifiers.java index efed7fd94..92db05ed9 100755 --- a/src/de/dhbwstuttgart/syntaxtree/modifier/Modifiers.java +++ b/src/de/dhbwstuttgart/syntaxtree/modifier/Modifiers.java @@ -2,21 +2,129 @@ package de.dhbwstuttgart.syntaxtree.modifier; // ino.end +// ino.module.Modifiers.8588.import +import de.dhbwstuttgart.typeinference.Menge; + +import de.dhbwstuttgart.typeinference.JavaCodeResult; +import de.dhbwstuttgart.typeinference.ResultSet; +// ino.end + // ino.class.Modifiers.24035.description type=javadoc - -import java.util.ArrayList; -import java.util.List; - /** * Die Klasse beinhaltet die Liste der Access-Modifier fuer eine Klasse, * Methode usw. */ public class Modifiers { - protected List modifier = new ArrayList(); + protected Menge modifier = new Menge(); // ino.end + // ino.method.getModifiers.24041.definition + public Menge getModifiers() + // ino.end + // ino.method.getModifiers.24041.body + { + return this.modifier; + } + // ino.end + + // ino.method.setModifier.24044.definition + public void setModifier(Menge modifier) + // ino.end + // ino.method.setModifier.24044.body + { + if (modifier != null) this.modifier = modifier; + } + // ino.end + + // ino.method.addModifier.24047.defdescription type=javadoc + /** + * Fuegt den angegebenen Modifier zur Auflistung hinzu. + */ + // ino.end + // ino.method.addModifier.24047.definition + public void addModifier(Modifier mod) + // ino.end + // ino.method.addModifier.24047.body + { + modifier.addElement(mod); + } + // ino.end + + // ino.method.includesModifier.24050.defdescription type=javadoc + /** + * Gibt zurueck, ob der angegebene Modifier enthalten ist. + */ + // ino.end + // ino.method.includesModifier.24050.definition + public boolean includesModifier(Modifier mod) + // ino.end + // ino.method.includesModifier.24050.body + { + String class1 = mod.getClass().toString(); + String class2; + + for (int i=0; i getOperatorTypes() { + Hashtable types = new Hashtable(); + + 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 getReturnTypes(TypeAssumptions ass) { + HashMap 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)); + 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", "", 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(); + } + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/AndOp.java b/src/de/dhbwstuttgart/syntaxtree/operator/AndOp.java index 665c23912..0da0936d9 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/AndOp.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/AndOp.java @@ -1,9 +1,18 @@ // ino.module.AndOp.8595.package 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; // ino.class.AndOp.24101.declaration public class AndOp extends LogOp @@ -18,9 +27,14 @@ public class AndOp extends LogOp { super(offset,variableLength); } - // ino.end + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs, Binary operator) { + // TODO Auto-generated method stub + return null; + } + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/DivideOp.java b/src/de/dhbwstuttgart/syntaxtree/operator/DivideOp.java index bd2dd8fef..3d90a71df 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/DivideOp.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/DivideOp.java @@ -1,7 +1,9 @@ // ino.module.DivideOp.8596.package package de.dhbwstuttgart.syntaxtree.operator; // ino.end -// ino.module.DivideOp.8596.import +// ino.module.DivideOp.8596.import +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException; import org.apache.bcel.generic.ArithmeticInstruction; import org.apache.bcel.generic.DADD; @@ -30,6 +32,22 @@ public class DivideOp extends MulOp // ino.end // ino.method.DivideOp.24112.body { + super(offset,variableLength); } + // ino.end + + 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(); + } + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/EqualOp.java b/src/de/dhbwstuttgart/syntaxtree/operator/EqualOp.java index 04059c7c5..0b1bc8f23 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/EqualOp.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/EqualOp.java @@ -17,9 +17,14 @@ public class EqualOp extends RelOp // ino.end // ino.method.EqualOp.24122.body { + super(offset, variableLength); } // ino.end + @Override + BranchInstruction getOperator() { + return new IF_ICMPNE(null); + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/GreaterEquOp.java b/src/de/dhbwstuttgart/syntaxtree/operator/GreaterEquOp.java index 357f462b5..2c0f01a9b 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/GreaterEquOp.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/GreaterEquOp.java @@ -1,7 +1,8 @@ // ino.module.GreaterEquOp.8598.package package de.dhbwstuttgart.syntaxtree.operator; // ino.end -// ino.module.GreaterEquOp.8598.import +// ino.module.GreaterEquOp.8598.import +import de.dhbwstuttgart.typeinference.Menge; import org.apache.bcel.generic.BranchInstruction; import org.apache.bcel.generic.IF_ICMPLT; @@ -22,9 +23,14 @@ public class GreaterEquOp extends RelOp // ino.end // ino.method.GreaterEquOp.24138.body { - + super(offset,variableLength); } // ino.end + @Override + BranchInstruction getOperator() { + return new IF_ICMPLT(null); + } + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/GreaterOp.java b/src/de/dhbwstuttgart/syntaxtree/operator/GreaterOp.java index 446b870c2..0d7c4fcbf 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/GreaterOp.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/GreaterOp.java @@ -1,7 +1,9 @@ // ino.module.GreaterOp.8599.package package de.dhbwstuttgart.syntaxtree.operator; // ino.end -// ino.module.GreaterOp.8599.import +// ino.module.GreaterOp.8599.import +import de.dhbwstuttgart.typeinference.Menge; + import org.apache.bcel.generic.BranchInstruction; import org.apache.bcel.generic.IF_ICMPLE; import de.dhbwstuttgart.syntaxtree.statement.Binary; @@ -20,8 +22,14 @@ public class GreaterOp extends RelOp // ino.end // ino.method.GreaterOp.24151.body { + super(offset,variableLength); } // ino.end + @Override + BranchInstruction getOperator() { + return new IF_ICMPLE(null); + } + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/LessEquOp.java b/src/de/dhbwstuttgart/syntaxtree/operator/LessEquOp.java index 1f8d1ecd1..b284946ef 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/LessEquOp.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/LessEquOp.java @@ -1,7 +1,8 @@ // ino.module.LessEquOp.8600.package package de.dhbwstuttgart.syntaxtree.operator; // ino.end -// ino.module.LessEquOp.8600.import +// ino.module.LessEquOp.8600.import +import de.dhbwstuttgart.typeinference.Menge; import org.apache.bcel.generic.BranchInstruction; import org.apache.bcel.generic.IF_ICMPGT; @@ -21,9 +22,14 @@ public class LessEquOp extends RelOp // ino.end // ino.method.LessEquOp.24164.body { + super(offset,variableLength); } // ino.end + @Override + BranchInstruction getOperator() { + return new IF_ICMPGT(null); + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/LessOp.java b/src/de/dhbwstuttgart/syntaxtree/operator/LessOp.java index 18b507383..a1ba738ec 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/LessOp.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/LessOp.java @@ -1,7 +1,8 @@ // ino.module.LessOp.8601.package package de.dhbwstuttgart.syntaxtree.operator; // ino.end -// ino.module.LessOp.8601.import +// ino.module.LessOp.8601.import +import de.dhbwstuttgart.typeinference.Menge; import org.apache.bcel.generic.BranchInstruction; import org.apache.bcel.generic.IF_ICMPGE; import de.dhbwstuttgart.syntaxtree.statement.Binary; @@ -20,8 +21,14 @@ public class LessOp extends RelOp // ino.end // ino.method.LessOp.24177.body { + super(offset,variableLength); } // ino.end + @Override + BranchInstruction getOperator() { + return new IF_ICMPGE(null); + } + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/LogOp.java b/src/de/dhbwstuttgart/syntaxtree/operator/LogOp.java index 8af189968..765511436 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/LogOp.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/LogOp.java @@ -5,6 +5,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; + @@ -19,8 +33,28 @@ public abstract class LogOp extends Operator // ino.end // ino.method.LogOp.24190.body { + super(offset, variableLength); } // ino.end + + + @Override + protected Hashtable getOperatorTypes() { + Hashtable types = new Hashtable(); + + types.put(new RefType("java.lang.Boolean",this,-1), new RefType("java.lang.Boolean",this,-1)); + + return types; + } + + @Override + public HashMap getReturnTypes(TypeAssumptions ass) { + HashMap 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; + } + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/MinusOp.java b/src/de/dhbwstuttgart/syntaxtree/operator/MinusOp.java index 7032a59f2..5a342e99c 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/MinusOp.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/MinusOp.java @@ -1,7 +1,15 @@ // ino.module.MinusOp.8603.package package de.dhbwstuttgart.syntaxtree.operator; // ino.end -// ino.module.MinusOp.8603.impor +// ino.module.MinusOp.8603.import +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; + @@ -18,5 +26,9 @@ public class MinusOp extends AddOp super(offset,variableLength); } // ino.end + + ArithmeticInstruction getOperator(String returnType) { + return new ISUB(); + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/ModuloOp.java b/src/de/dhbwstuttgart/syntaxtree/operator/ModuloOp.java index 500397a70..4a13c6573 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/ModuloOp.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/ModuloOp.java @@ -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; @@ -18,8 +19,14 @@ public class ModuloOp extends MulOp // ino.end // ino.method.ModuloOp.24225.body { + super(offset,variableLength); } // ino.end + @Override + ArithmeticInstruction getOperator(String returnType) { + return new IREM(); + } + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/MulOp.java b/src/de/dhbwstuttgart/syntaxtree/operator/MulOp.java index e350d34bb..14d0948fc 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/MulOp.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/MulOp.java @@ -2,11 +2,123 @@ package de.dhbwstuttgart.syntaxtree.operator; // ino.end -// ino.module. +// ino.module.MulOp.8605.import +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; + // ino.class.MulOp.24231.declaration public abstract class MulOp extends Operator // ino.end // ino.class.MulOp.24231.body { + // ino.method.MulOp.24235.definition + public MulOp(int offset, int variableLength) + // ino.end + // ino.method.MulOp.24235.body + { + super(offset, variableLength); + } + // ino.end + + @Override + protected Hashtable getOperatorTypes() { + Hashtable types = new Hashtable(); + + + return types; + } + + @Override + public HashMap getReturnTypes(TypeAssumptions ass) { + HashMap 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(); + } + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/NotEqualOp.java b/src/de/dhbwstuttgart/syntaxtree/operator/NotEqualOp.java index 9ebf02b8c..37e22386c 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/NotEqualOp.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/NotEqualOp.java @@ -1,7 +1,18 @@ // ino.module.NotEqualOp.8606.package package de.dhbwstuttgart.syntaxtree.operator; // ino.end -// ino.module.Not +// ino.module.NotEqualOp.8606.import +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; + // ino.class.NotEqualOp.24241.declaration public class NotEqualOp extends RelOp @@ -13,7 +24,14 @@ public class NotEqualOp extends RelOp // ino.end // ino.method.NotEqualOp.24245.body { + super(offset,variableLength); } + // ino.end + + @Override + BranchInstruction getOperator() { + return new IF_ACMPEQ(null); + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/Operator.java b/src/de/dhbwstuttgart/syntaxtree/operator/Operator.java index d8aea90e9..b4ef10a16 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/Operator.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/Operator.java @@ -1,12 +1,105 @@ // ino.module.Operator.8607.package package de.dhbwstuttgart.syntaxtree.operator; // ino.end +// ino.module.Operator.8607.import +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 getOperatorTypes( ); + + + /** + * Liefert eine HashMap der Form: HashMap + * @param ass + * @return + */ + public abstract HashMap getReturnTypes(TypeAssumptions ass); + + public abstract InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs, Binary operator); + + @Override + public Menge 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; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/OrOp.java b/src/de/dhbwstuttgart/syntaxtree/operator/OrOp.java index fdfcf865e..457ff978e 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/OrOp.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/OrOp.java @@ -11,6 +11,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; // ino.class.OrOp.24282.declaration public class OrOp extends LogOp @@ -27,6 +31,46 @@ public class OrOp extends LogOp } // ino.end + @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; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/PlusOp.java b/src/de/dhbwstuttgart/syntaxtree/operator/PlusOp.java index 03ed693f2..099f1ab79 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/PlusOp.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/PlusOp.java @@ -1,7 +1,31 @@ // ino.module.PlusOp.8609.package package de.dhbwstuttgart.syntaxtree.operator; // ino.end -// ino.module.PlusOp.8609.import +// ino.module.PlusOp.8609.import +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; @@ -19,5 +43,19 @@ public class PlusOp extends AddOp super(offset,variableLength); } // ino.end + + 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(); + } + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/RelOp.java b/src/de/dhbwstuttgart/syntaxtree/operator/RelOp.java index e5d265d29..8325d6275 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/RelOp.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/RelOp.java @@ -2,11 +2,105 @@ package de.dhbwstuttgart.syntaxtree.operator; // ino.end +// ino.module.RelOp.8610.import +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; // ino.class.RelOp.24299.declaration public abstract class RelOp extends Operator // ino.end // ino.class.RelOp.24299.body { + // ino.method.RelOp.24303.definition + public RelOp(int offset, int variableLength) + // ino.end + // ino.method.RelOp.24303.body + { + super(offset, variableLength); + } + // ino.end + + + protected Hashtable getOperatorTypes() { + Hashtable types = new Hashtable(); + + 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 getReturnTypes(TypeAssumptions ass) { + HashMap 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(); } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/operator/TimesOp.java b/src/de/dhbwstuttgart/syntaxtree/operator/TimesOp.java index 0385c4169..a2b773199 100755 --- a/src/de/dhbwstuttgart/syntaxtree/operator/TimesOp.java +++ b/src/de/dhbwstuttgart/syntaxtree/operator/TimesOp.java @@ -2,7 +2,10 @@ package de.dhbwstuttgart.syntaxtree.operator; // ino.end -// ino.module.TimesOp.8611.import +// ino.module.TimesOp.8611.import +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; @@ -22,9 +25,23 @@ public class TimesOp extends MulOp // ino.end // ino.method.TimesOp.24316.body { + super(offset,variableLength); } // ino.end - + + 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(); + } + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/ArgumentList.java b/src/de/dhbwstuttgart/syntaxtree/statement/ArgumentList.java index 0f00d620c..02b7d8847 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/ArgumentList.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/ArgumentList.java @@ -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; + public Menge expr = new Menge(); + + 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 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 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; + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/Assign.java b/src/de/dhbwstuttgart/syntaxtree/statement/Assign.java index 8c045ba71..174095372 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/Assign.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/Assign.java @@ -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,6 +45,119 @@ 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; + } + + + + // ino.method.toString.24960.defdescription type=javadoc + /** + *
Author: Martin Pl�micke + * @return + */ + // ino.end + // ino.method.toString.24960.definition + public String toString() + // ino.end + // ino.method.toString.24960.body + { + if(getType() == null)return "(" + expr1.toString() + " = " + expr2.toString() + ")"; + return getType().toString() + "(" + expr1.toString() + " = " + expr2.toString() + ")"; + } + // ino.end + + + // ino.method.wandleRefTypeAttributes2GenericAttributes.24963.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.24963.body + { + } + // ino.end + +/* + @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 getChildren() { + Menge ret = new Menge(); + 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; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/Binary.java b/src/de/dhbwstuttgart/syntaxtree/statement/Binary.java index fb8dc637e..31526d946 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/Binary.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/Binary.java @@ -7,8 +7,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; // ino.class.Binary.24966.description type=line @@ -30,6 +42,168 @@ public class Binary extends BinaryExpr // ino.end + // ino.attribute.parserlog.24973.decldescription type=javadoc + /** + * Logger: log4j + */ + // ino.end + // ino.attribute.parserlog.24973.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end + // ino.attribute.expr1.24976.declaration + public Expr expr1; + // ino.end + // ino.attribute.op.24979.declaration + public Operator op; + // ino.end + // ino.attribute.expr2.24982.declaration + public Expr expr2; + // ino.end + + + // ino.method.set_Expr1.24988.definition + public void set_Expr1(Expr exp) + // ino.end + // ino.method.set_Expr1.24988.body + { + this.expr1=exp; + } + // ino.end + + + + // ino.method.set_Expr2.24991.definition + public void set_Expr2(Expr exp) + // ino.end + // ino.method.set_Expr2.24991.body + { + this.expr2=exp; + } + // ino.end + + + + // ino.method.set_Operator.24994.definition + public void set_Operator(Operator Op) + // ino.end + // ino.method.set_Operator.24994.body + { + this.op=Op; + } + // ino.end + + + + // ino.method.get_Name.24997.definition + public String get_Name() + // ino.end + // ino.method.get_Name.24997.body + { + return null; + } + // ino.end + + + + // ino.method.get_Operator.25000.definition + public Operator get_Operator() + // ino.end + // ino.method.get_Operator.25000.body + { + return op; + } + // ino.end + + + + // ino.method.get_Expr1.25003.definition + public Expr get_Expr1() + // ino.end + // ino.method.get_Expr1.25003.body + { + return expr1; + } + // ino.end + + + + // ino.method.get_Expr2.25006.definition + public Expr get_Expr2() + // ino.end + // ino.method.get_Expr2.25006.body + { + return expr2; + } + // ino.end + + + + + + // ino.method.wandleRefTypeAttributes2GenericAttributes.25027.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25027.body + { + } + + @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 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 getChildren() { + Menge ret = new Menge(); + 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); + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/BinaryExpr.java b/src/de/dhbwstuttgart/syntaxtree/statement/BinaryExpr.java index d0b2e156d..561803d36 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/BinaryExpr.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/BinaryExpr.java @@ -1,6 +1,8 @@ // ino.module.BinaryExpr.8624.package package de.dhbwstuttgart.syntaxtree.statement; +import de.dhbwstuttgart.typeinference.ConstraintsSet; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; // ino.class.BinaryExpr.25030.declaration @@ -14,7 +16,7 @@ public abstract class BinaryExpr extends Expr // ino.end // ino.method.BinaryExpr.25034.body { - super(null,variableLength); + super(offset,variableLength); } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/Block.java b/src/de/dhbwstuttgart/syntaxtree/statement/Block.java index 86c94bcf6..17bb91503 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/Block.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/Block.java @@ -2,7 +2,10 @@ package de.dhbwstuttgart.syntaxtree.statement; // ino.end // ino.module.Block.8625.import -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; @@ -12,6 +15,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; + @@ -25,15 +47,29 @@ public class Block extends Statement private ClassGen _cg; public Block(List statements, int offset) { - super(null, 0); - this.statements = statements; + super(offset); + this.statements = statements; } + // ino.attribute.parserlog.25044.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end - public List statements = new ArrayList<>(); + public List statements = new Menge(); + //private String sc_meth_ret_type; + // ino.attribute.inferencelog.25059.decldescription type=javadoc + /** + * Logger: log4j + */ + // ino.end + // ino.attribute.inferencelog.25059.declaration + protected static Logger inferencelog = Logger.getLogger("inference"); + // ino.end + protected static Logger typinferenceLog = Logger.getLogger("Typeinference"); + // ino.method.get_Statement.25065.definition @@ -50,6 +86,125 @@ public class Block extends Statement + // ino.method.toString.25083.defdescription type=javadoc + /** + *
Author: Martin Pl�micke + * @return + */ + // ino.end + // ino.method.toString.25083.definition + public String toString() + // ino.end + // ino.method.toString.25083.body + { + return this.type + " { " + statements.toString(); + } + // ino.end + + @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 getChildren() { + Menge ret = new Menge(); + 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; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/BoolLiteral.java b/src/de/dhbwstuttgart/syntaxtree/statement/BoolLiteral.java index 1b1f4fae2..8f96a203c 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/BoolLiteral.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/BoolLiteral.java @@ -9,6 +9,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; + @@ -19,14 +33,27 @@ public class BoolLiteral extends Literal { + + + // ino.attribute.Bool.25093.declaration private boolean Bool; + // ino.end + // ino.attribute.parserlog.25096.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end + // ino.method.BoolLiteral.25099.definition public BoolLiteral() // ino.end // ino.method.BoolLiteral.25099.body { - super(null,-1); + super(-1,-1); + // #JB# 20.04.2005 + // ########################################################### + this.setType(new RefType("java.lang.Boolean",this.getOffset())); + //this.setType(new Type("boolean")); + // ########################################################### } // ino.end @@ -64,10 +91,45 @@ public class BoolLiteral extends Literal { return null; } + // ino.end + + @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 getChildren() { + Menge ret = new Menge(); + 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; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/CastExpr.java b/src/de/dhbwstuttgart/syntaxtree/statement/CastExpr.java index 761a1b924..cb7d499d0 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/CastExpr.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/CastExpr.java @@ -5,10 +5,24 @@ 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; + + // ino.class.CastExpr.25126.declaration @@ -17,19 +31,24 @@ public class CastExpr extends Expr // ino.class.CastExpr.25126.body { // ino.method.CastExpr.25130.definition - public CastExpr(RefType castType, Expr expr, int offset) + public CastExpr(Type castType, Expr expr,int offset) // ino.end // ino.method.CastExpr.25130.body { - super(null, 0); + super(offset); + this.type = castType; } // ino.end - // ino.attribute.type.25133.decla + // ino.attribute.type.25133.declaration + private Type type; // ino.end // ino.attribute.expr.25136.declaration public Expr expr; // ino.end + // ino.attribute.parserlog.25139.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end @@ -44,7 +63,16 @@ public class CastExpr extends Expr // ino.end - + + // ino.method.set_Type.25148.definition + public void set_Type(Type ty) + // ino.end + // ino.method.set_Type.25148.body + { + this.type = ty; + } + // ino.end + // ino.method.set_Expr.25151.definition @@ -57,6 +85,46 @@ public class CastExpr extends Expr // ino.end + + + // ino.method.wandleRefTypeAttributes2GenericAttributes.25163.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25163.body + { + } + // ino.end + + + @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 getChildren() { + Menge ret = new Menge(); + ret.add(this.expr); + return ret; + } + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + // TODO Bytecode + throw new NotImplementedException(); + } + + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/CharLiteral.java b/src/de/dhbwstuttgart/syntaxtree/statement/CharLiteral.java index 3d2ea7e73..36eca1834 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/CharLiteral.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/CharLiteral.java @@ -4,6 +4,24 @@ package de.dhbwstuttgart.syntaxtree.statement; // ino.module.CharLiteral.8628.import 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; @@ -15,6 +33,10 @@ public class CharLiteral extends Literal { // ino.attribute.Char.25170.declaration private char Char; + // ino.end + // ino.attribute.parserlog.25173.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end // ino.method.CharLiteral.25176.definition @@ -22,7 +44,11 @@ public class CharLiteral extends Literal // ino.end // ino.method.CharLiteral.25176.body { - super(null,-1); + super(-1,-1); + // #JB# 20.04.2005 + // ########################################################### + this.setType(new RefType("Char",this,this.getOffset())); + //this.setType(new Type("char")); // ########################################################### } // ino.end @@ -58,6 +84,50 @@ public class CharLiteral extends Literal return null; } // ino.end + + @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 getChildren() { + Menge ret = new Menge(); + return ret; + } + + + + @Override + public void wandleRefTypeAttributes2GenericAttributes( + Menge paralist, + Menge genericMethodParameters) { + } + + + //Char-Getter fuer genByteCode + public char get_Char() + // ino.end + // ino.method.get_Int.25463.body + { + 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; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/DoubleLiteral.java b/src/de/dhbwstuttgart/syntaxtree/statement/DoubleLiteral.java index 137fcb035..d3fd8e552 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/DoubleLiteral.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/DoubleLiteral.java @@ -11,8 +11,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; @@ -24,14 +36,20 @@ public class DoubleLiteral extends Literal { // ino.attribute.Int.25451.declaration private double Double; + // ino.end + // ino.attribute.parserlog.25454.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end + // ino.method.IntLiteral.25457.definition public DoubleLiteral() // ino.end // ino.method.IntLiteral.25457.body { - super(null,-1); - + super(-1,-1); + + this.setType(new RefType("Double",this,this.getOffset())); } // ino.end @@ -75,6 +93,65 @@ public class DoubleLiteral extends Literal // ino.end + // ino.method.toString.25484.defdescription type=javadoc + /** + *
Author: Martin Pl�micke + * @return + */ + // ino.end + // ino.method.toString.25484.definition + public String toString() + // ino.end + // ino.method.toString.25484.body + { + return type.toString() + " " + Double; + } + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25487.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25487.body + { + } + // ino.end + + @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 getChildren() { + Menge ret = new Menge(); + 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; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/EmptyStmt.java b/src/de/dhbwstuttgart/syntaxtree/statement/EmptyStmt.java index 68397f30d..0eff5b0f2 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/EmptyStmt.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/EmptyStmt.java @@ -7,6 +7,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; @@ -21,12 +34,63 @@ public class EmptyStmt extends Statement // ino.end // ino.method.EmptyStmt.25207.body { - super(null,-1); + super(-1,-1); } // ino.end + // ino.attribute.parserlog.25210.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end + /* + // ino.method.sc_check.25213.definition + public void sc_check(Menge classlist, Hashtable ch, Hashtable bh, boolean ext, Hashtable parach, Hashtable parabh) + // ino.end + // ino.method.sc_check.25213.body + { + if(ext){ + parserlog.debug(" ---EmptyStmt---"); + } + } + // ino.end + */ + // ino.method.wandleRefTypeAttributes2GenericAttributes.25222.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25222.body + { + } + // ino.end + + + @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 getChildren() { + return new Menge(); + } + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + // TODO Bytecode + throw new NotImplementedException(); + } + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/Executeable.java b/src/de/dhbwstuttgart/syntaxtree/statement/Executeable.java index db6501fa9..7550f6c78 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/Executeable.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/Executeable.java @@ -2,18 +2,35 @@ package de.dhbwstuttgart.syntaxtree.statement; 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.syntaxtree.type.Type; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.Pair; +import de.dhbwstuttgart.typeinference.Typeable; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.unify.TypeUnify; -public abstract class Executeable extends SyntaxTreeNode +public abstract class Executeable extends SyntaxTreeNode implements Typeable { - private RefType type; + private Type type; - public Executeable(RefType type, int offset) { + public Executeable(Type type,int offset) { + super(offset); this.type = type; } + + public Type getType(){ + return type; + } + + public abstract InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs); //public abstract String getTypeInformation(); } diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/Expr.java b/src/de/dhbwstuttgart/syntaxtree/statement/Expr.java index 33b43e859..510d38f0a 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/Expr.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/Expr.java @@ -4,17 +4,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.Menge; +import de.dhbwstuttgart.syntaxtree.Class; +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.ConstraintsSet; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; +import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException; public abstract class Expr extends Executeable { - public Expr(RefType type, int offset) { + public Expr(Type type, int offset) { super(type, offset); } + 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); } diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/ExprStmt.java b/src/de/dhbwstuttgart/syntaxtree/statement/ExprStmt.java index ca7a2d637..51372c17c 100644 --- a/src/de/dhbwstuttgart/syntaxtree/statement/ExprStmt.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/ExprStmt.java @@ -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); } diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/FloatLiteral.java b/src/de/dhbwstuttgart/syntaxtree/statement/FloatLiteral.java index ec3637f88..3a2c5e150 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/FloatLiteral.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/FloatLiteral.java @@ -10,6 +10,20 @@ 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; + @@ -20,14 +34,20 @@ public class FloatLiteral extends Literal { // ino.attribute.Int.25451.declaration private float Float; + // ino.end + // ino.attribute.parserlog.25454.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end + // ino.method.IntLiteral.25457.definition public FloatLiteral() // ino.end // ino.method.IntLiteral.25457.body { - super(null,-1); - + super(-1,-1); + + this.setType(new RefType("Float",this,this.getOffset())); } // ino.end @@ -71,5 +91,54 @@ public class FloatLiteral extends Literal // ino.end + + // ino.method.toString.25484.defdescription type=javadoc + /** + *
Author: Martin Pl�micke + * @return + */ + // ino.end + // ino.method.toString.25484.definition + public String toString() + // ino.end + // ino.method.toString.25484.body + { + return type.toString() + " " + Float; + } + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25487.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25487.body + { + } + // ino.end + + @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 getChildren() { + Menge ret = new Menge(); + 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; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/ForStmt.java b/src/de/dhbwstuttgart/syntaxtree/statement/ForStmt.java index 3378b31b0..f1fe577fe 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/ForStmt.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/ForStmt.java @@ -3,7 +3,6 @@ package de.dhbwstuttgart.syntaxtree.statement; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; -import java.util.List; import org.apache.bcel.generic.BranchInstruction; import org.apache.bcel.generic.ClassGen; @@ -13,7 +12,28 @@ import org.apache.bcel.generic.InstructionHandle; import org.apache.bcel.generic.InstructionList; import org.apache.bcel.generic.NOP; +import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException; +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.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 ForStmt extends Statement { @@ -28,13 +48,113 @@ public class ForStmt extends Statement public ForStmt(int offset, int variableLength) { - super(null,variableLength); + super(offset,variableLength); } - void sc_check(List classname, Hashtable ch, Hashtable bh, boolean ext, Hashtable parach, Hashtable parabh) + void sc_check(Menge classname, Hashtable ch, Hashtable bh, boolean ext, Hashtable parach, Hashtable parabh) { + } + + public String toString() + { + return "FOR "; + } + + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + { + if(body_Loop_block!=null){ + body_Loop_block.wandleRefTypeAttributes2GenericAttributes(paralist,genericMethodParameters); + } + } + public void set_head_Initializer(Expr expr) { + head_Initializer = expr; + + } + + public void set_head_Condition(Expr expr) { + head_Condition = expr; + + } + + public void set_head_Loop_expr(Expr expr) { + head_Loop_expr = expr; + + } + + public void set_body_Loop_block(Statement statement) { + body_Loop_block = statement; + + } + + @Override + public ConstraintsSet TYPEStmt(TypeAssumptions assumptions) { + //TODO: TYPEStmt + ConstraintsSet ret = new ConstraintsSet(); + this.setType(TypePlaceholder.fresh(this)); + + 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 getChildren() { + Menge ret = new Menge(); + 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; + } } \ No newline at end of file diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/IfStmt.java b/src/de/dhbwstuttgart/syntaxtree/statement/IfStmt.java index c869849a1..dbf4a4fb7 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/IfStmt.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/IfStmt.java @@ -22,6 +22,30 @@ 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; + + // ino.class.IfStmt.25300.declaration @@ -34,7 +58,7 @@ public class IfStmt extends Statement // ino.end // ino.method.IfStmt.25304.body { - super(null,variableLength); + super(offset,variableLength); } // ino.end @@ -50,6 +74,9 @@ public class IfStmt extends Statement // ino.attribute.else_block.25316.declaration public Statement else_block; // ino.end + // ino.attribute.parserlog.25319.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end @@ -72,6 +99,101 @@ public class IfStmt extends Statement this.then_block = blk; } // ino.end + + + + // ino.method.set_Else_block.25328.definition + public void set_Else_block(Statement blk) + // ino.end + // ino.method.set_Else_block.25328.body + { + this.else_block = blk; + } + // ino.end + + // ino.method.wandleRefTypeAttributes2GenericAttributes.25349.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25349.body + { + if(then_block!=null){ + then_block.wandleRefTypeAttributes2GenericAttributes(paralist,genericMethodParameters); + } + if(else_block!=null){ + else_block.wandleRefTypeAttributes2GenericAttributes(paralist,genericMethodParameters); + } + + } + // ino.end + + @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 getChildren() { + Menge ret = new Menge(); + 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; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/InstVar.java b/src/de/dhbwstuttgart/syntaxtree/statement/InstVar.java index f0ef4f53d..43636f287 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/InstVar.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/InstVar.java @@ -9,6 +9,28 @@ 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; + @@ -20,17 +42,176 @@ public class InstVar extends Expr // ino.attribute.expr.25396.declaration private Expr expr; // ino.end + // ino.attribute.usedid.25399.declaration + private UsedId usedid; + // ino.end // ino.attribute.type.25402.declaration protected String type; //???? BRAUCHT MAN DEN??? // ino.end + // ino.attribute.parserlog.25405.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end + // ino.method.InstVar.25408.definition public InstVar(Expr e, String n, int offset) // ino.end // ino.method.InstVar.25408.body { - super(null,n.length()); + super(offset,n.length()); expr = e; + usedid = new UsedId(getOffset()); + usedid.set_Name(n); } + // ino.end + + // ino.method.InstVar.25411.definition + public InstVar(String n, String t, int offset) + // ino.end + // ino.method.InstVar.25411.body + { + super(offset,n.length()); + usedid = new UsedId(getOffset()); + usedid.set_Name(n); + type = t; + } + // ino.end + + // ino.method.InstVar.25414.defdescription type=javadoc + /** + * macht aus einem UsedId mit einem Menge von Strings eine InstVar + *
Author: Martin Pl�micke PL 05-08-17 + * @param ui + * @return + */ + // ino.end + // ino.method.InstVar.25414.definition + public InstVar(UsedId ui, int offset,int variableLength) + // ino.end + // ino.method.InstVar.25414.body + { + 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; + } + // ino.end + @Override + public void parserPostProcessing(SyntaxTreeNode parent) { + super.parserPostProcessing(parent); + if(this.getType()==null)this.set_Type(TypePlaceholder.fresh(this)); + } + + /* + // ino.method.sc_check.25417.definition + public void sc_check(Menge classname, Hashtable ch, Hashtable bh, boolean ext, Hashtable parach, Hashtable parabh) + // ino.end + // ino.method.sc_check.25417.body + { + 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); + } + } + // ino.end + */ + // ino.method.get_Name.25420.definition + public String get_Name() + // ino.end + // ino.method.get_Name.25420.body + { + return this.usedid.get_Name_1Element(); + } + // ino.end + + // ino.method.get_codegen_UsedId.25423.definition + public String get_codegen_UsedId() + // ino.end + // ino.method.get_codegen_UsedId.25423.body + { return usedid.get_codegen_UsedId(); } + // ino.end + + // ino.method.toString.25441.defdescription type=javadoc + /** + *
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 paralist, Menge 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 getChildren() { + Menge ret = new Menge(); + ret.add(this.expr); + return ret; + } + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + // TODO Bytecode + throw new NotImplementedException(); + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/InstanceOf.java b/src/de/dhbwstuttgart/syntaxtree/statement/InstanceOf.java index 6ffc3aab4..6c3a02782 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/InstanceOf.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/InstanceOf.java @@ -8,7 +8,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; @@ -26,6 +39,9 @@ public class InstanceOf extends BinaryExpr // ino.attribute.parserlog.25362.decldescription type=line // private boolean is_instance = false; // ino.end + // ino.attribute.parserlog.25362.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end // ino.method.InstanceOf.25365.definition @@ -35,6 +51,10 @@ public class InstanceOf extends BinaryExpr { super(offset,variableLength); // #JB# 20.04.2005 + // ########################################################### + this.setType(new RefType("Boolean",this,this.getOffset())); + //this.setType(new Type("boolean")); + // ########################################################### } // ino.end @@ -66,6 +86,41 @@ public class InstanceOf extends BinaryExpr } // ino.end + + // ino.method.wandleRefTypeAttributes2GenericAttributes.25389.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25389.body + { + } + // ino.end + + + @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 getChildren() { + Menge ret = new Menge(); + ret.add(this.expr); + return ret; + } + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + // TODO Bytecode + throw new NotImplementedException(); + } + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/IntLiteral.java b/src/de/dhbwstuttgart/syntaxtree/statement/IntLiteral.java index 319f732e6..c9bf7db54 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/IntLiteral.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/IntLiteral.java @@ -11,6 +11,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; @@ -23,14 +38,22 @@ public class IntLiteral extends Literal // ino.attribute.Int.25451.declaration private int Int; // ino.end + // ino.attribute.parserlog.25454.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end + // ino.method.IntLiteral.25457.definition public IntLiteral() // ino.end // ino.method.IntLiteral.25457.body { - super(null,-1); + super(-1,-1); // #JB# 20.04.2005 + // ########################################################### + this.setType(new RefType("Integer",this,this.getOffset())); + //this.setType(new Type("int")); + // ########################################################### } // ino.end @@ -73,5 +96,58 @@ public class IntLiteral extends Literal // ino.end + // ino.method.toString.25484.defdescription type=javadoc + /** + *
Author: Martin Pl�micke + * @return + */ + // ino.end + // ino.method.toString.25484.definition + public String toString() + // ino.end + // ino.method.toString.25484.body + { + return getType().toString() + " " + Int; + } + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25487.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25487.body + { + } + // ino.end + + @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 getChildren() { + Menge ret = new Menge(); + 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; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/LambdaExpression.java b/src/de/dhbwstuttgart/syntaxtree/statement/LambdaExpression.java index f0c45e2ed..c090958e1 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/LambdaExpression.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/LambdaExpression.java @@ -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,247 @@ 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 paralist, + Menge 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 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 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 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 paramTypes = new Menge(); + + 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 getChildren() { + Menge ret = new Menge(); + ret.add(this.method_body); + for(FormalParameter fp : this.params)ret.add(fp); + return ret; + } + + /* + private List crawlVariables(SyntaxTreeNode inStatements){ + List ret = new ArrayList<>(); + for(SyntaxTreeNode child : inStatements.getChildren()){ + ret.addAll(crawlVariables(child)); + } + 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 arguments = new ArrayList(); + 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; iAuthor: Martin Pl�micke + * @return + */ + // ino.end + // ino.method.toString.25534.definition + public String toString() + // ino.end + // ino.method.toString.25534.body + { + if(getType()==null)return usedid.toString(); + return usedid.toString() + ": " + getType().toString(); + } + // ino.end + + // ino.method.wandleRefTypeAttributes2GenericAttributes.25537.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25537.body + { + } + // ino.end + + + @Override + public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) { + ConstraintsSet ret = new ConstraintsSet(); + //gibt es eine Assumption für den die LocalOrFieldVar-Variablen, dann folgendes ausführen: + Type thisTypeAssumption = assumptions.getVarType(this.get_Name(), this.getParentClass()); + if(thisTypeAssumption == null){//Es ist keine Variable oder Feld + //Testen ob es ein Klassenname ist: + ClassAssumption cAss = assumptions.getClass(this.get_Name()); + if(cAss == null)throw new TypeinferenceException("Weder eine Variable noch eine Klasse "+this.get_Name()+" ist in den Assumptions nicht vorhanden",this); + + thisTypeAssumption = cAss.getAssumedClass().getType(); + this.set_Type(thisTypeAssumption); + this.isClassAccess = true; + }else{ + Type thisType = thisTypeAssumption.checkTYPE(assumptions, this); + this.setType(thisType); + //ret.add(new Constraint(thisTypeAssumption, this.getTypeVariable())); + //Rausfinden, ob es Feld oder Locale Variable ist: + for(FieldAssumption fAss : assumptions.getFieldVars(this.get_Name())){ + if(this.getParentClass().equals(fAss.getParentClass()))this.isFieldAccess = true; + }; + } + + return ret; + } + + public String getTypeInformation(){ + return this.getType()+" "+this.get_Name(); + } + + @Override + public JavaCodeResult printJavaCode(ResultSet resultSet) { + return new JavaCodeResult(this.get_Name()); + } + + @Override + public Menge getChildren() { + Menge ret = new Menge(); + return ret; + } + + @Override + public InstructionList genByteCode(ClassGenerator cg, TypeinferenceResultSet rs) { + InstructionList il = new InstructionList(); + if(this.isFieldAccess){ + il.append(new This(this).genByteCode(cg, rs)); + il.append(cg.getInstructionFactory().createFieldAccess(this.getParentClass().getName().toString(), this.get_Name(), this.getType().getBytecodeType(cg, rs), Constants.GETFIELD)); + }else{ + il.append(createLoad(cg, rs)); + } + + return il; + } + + public LocalVariableInstruction createLoad(ClassGenerator cg, TypeinferenceResultSet rs){ + Type type = this.getType(); + org.apache.bcel.generic.Type byteCodeType = type.getBytecodeType(cg, rs); + String name = this.get_Name(); + + return cg.getMethodGenerator().createLoad(byteCodeType, name); + } + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/LocalVarDecl.java b/src/de/dhbwstuttgart/syntaxtree/statement/LocalVarDecl.java index 4cbc3caba..a7e793b4c 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/LocalVarDecl.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/LocalVarDecl.java @@ -8,15 +8,35 @@ import java.util.Hashtable; import org.apache.bcel.generic.ClassGen; 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.Class; +import de.dhbwstuttgart.syntaxtree.ClassHelper; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import de.dhbwstuttgart.syntaxtree.misc.DeclId; +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.ResultSet; +import de.dhbwstuttgart.typeinference.TypeInsertable; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.assumptions.LocalVarAssumption; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; +import de.dhbwstuttgart.typeinference.exceptions.DebugException; +import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint; + + // ino.class.LocalVarDecl.25540.declaration -public class LocalVarDecl extends Statement +public class LocalVarDecl extends Statement implements TypeInsertable // ino.end // ino.class.LocalVarDecl.25540.body { @@ -25,12 +45,336 @@ public class LocalVarDecl extends Statement // ino.end // ino.method.LocalVarDecl.25545.body { - super(null,variableLength); + super(offset,variableLength); + } + // ino.end + + // ino.attribute.declid.25548.declaration + private Menge declid = new Menge(); + // ino.end + // ino.attribute.paralist.25554.declaration + private Menge paralist = null; + // ino.end + // ino.attribute.parahash.25557.declaration + private Hashtable parahash = null; + // ino.end + // ino.attribute.inferencelog.25560.declaration + protected static Logger inferencelog = Logger.getLogger("inference"); + // ino.end + // ino.attribute.parserlog.25563.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end + // ino.attribute.block.25566.declaration + public Block block; + // ino.end + + // ino.method.set_DeclId.25575.definition + public void set_DeclId(DeclId did) + // ino.end + // ino.method.set_DeclId.25575.body + { + this.declid.addElement(did); } // ino.end - public Block block; + // ino.method.get_Name.25578.definition + public String get_Name() + // ino.end + // ino.method.get_Name.25578.body + { + DeclId hilf; + hilf=declid.elementAt(0); + return hilf.get_Name(); + } + // ino.end + // ino.method.set_ParaList.25581.definition + public void set_ParaList(Menge pl) + // ino.end + // ino.method.set_ParaList.25581.body + { + this.paralist = pl; + } + // ino.end + + /* + // ino.method.check_anz.25590.definition + public void check_anz(Type type, Menge paralist, Menge classlist) + throws SCStatementException + // ino.end + // ino.method.check_anz.25590.body + { + boolean flag = false; + for(Enumeration e2 = classlist.elements();e2.hasMoreElements();){ + Class c = e2.nextElement(); + // System.out.println("vergleiche "+type.get_Type_()+" mit "+c.getName()); + if(c.getName().equals(type.getName())){ + // System.out.println("if(c.getName().equals(type.get_Type())){"); + if(c.get_ParaList().size()>0 && paralist!=null){ + + parserlog.debug("Type "+type.getName()+" in classlist gefunden!"); + parserlog.debug("Anzahl der localvar.paralist:"+ paralist.size()+" class.paralist: (soll) "+c.get_ParaList().size()); + if(paralist.size()==c.get_ParaList().size()){ + + for(Enumeration e3=paralist.elements();e3.hasMoreElements();){ + Type t = (Type)e3.nextElement(); + parserlog.debug("Type "+t.getName()+" wird gerade untersucht"); + + try + { + if ( t instanceof RefType ) + { + check_anz(t, ((RefType)t).get_ParaList(),classlist); + } + } + catch(SCStatementException ex) + { + throw ex; + } + } + flag = true; + parserlog.debug("flag gesetzt"); + break; + } + else{ + SCStatementException ex = new SCStatementException(); + SCExcept e = new SCExcept(); + e.set_error("Klasse "+c.getName()+" ist falsch parametrisiert!"); + e.set_function("complete_parahashtable() --> check_anz()"); + e.set_statement(type.getName().toString()); + ex.addException(e); + throw ex; + } + } + else if(c.get_ParaList().size()==0 && paralist!=null){ + SCStatementException ex = new SCStatementException(); + SCExcept e = new SCExcept(); + e.set_error("Klasse "+c.getName()+" ist nicht parametrisierbar!"); + e.set_function("complete_parahashtable() --> check_anz()"); + e.set_statement(type.getName().toString()); + ex.addException(e); + throw ex; + } + else if(paralist==null && c.get_ParaList().size()>0){ + parserlog.debug(paralist.toString()); + parserlog.debug(c.getName()+" "+c.get_ParaList().size()); + SCStatementException ex = new SCStatementException(); + SCExcept e = new SCExcept(); + e.set_error("Klasse "+c.getName()+" �berhaupt garnicht parametrisiert!"); + e.set_function("complete_parahashtable() --> check_anz()"); + e.set_statement(type.getName().toString()); + ex.addException(e); + throw ex; + + } + else{ + flag = true; + parserlog.debug(type.getName()+" nicht parametrisierbar"); + break; + } + } + } + if(!flag) + { + SCStatementException ex = new SCStatementException(); + SCExcept e = new SCExcept(); + if ( type instanceof RefType ) + { + e.set_error("Type " + type.getName()+ " falsche Parameter-Anzahl " + ((RefType)type).get_ParaList().size()); + } + e.set_function("complete_parahashtable() --> check_anz()"); + e.set_statement(type.getName().toString()); + ex.addException(e); + throw ex; + } + + } + // ino.end + */ + + public Menge getDeclidMenge() + // ino.end + // ino.method.getDeclidMenge.25596.body + { + return declid; + } + // ino.end + // ino.method.setDeclidMenge.25599.definition + public void setDeclidMenge(Menge declid) + // ino.end + // ino.method.setDeclidMenge.25599.body + { + this.declid = declid; + } // ino.end + // ino.method.getLineNumber.25602.defdescription type=javadoc + /** + *
Author: J�rg B�uerle + * @return + */ + // ino.end + // ino.method.getLineNumber.25602.definition + public int getLineNumber() + // ino.end + // ino.method.getLineNumber.25602.body + { + if(declid.size()<=0) + return MyCompiler.NO_LINENUMBER; + else{ + return declid.elementAt(0).getLineNumber(); + } + } + // ino.end + + // ino.method.getOffset.25605.defdescription type=javadoc + /** + *
Author: Thomas Hornberger + * @return + */ + // ino.end + // ino.method.getOffset.25605.definition + public int getOffset() + // ino.end + // ino.method.getOffset.25605.body + { + if(declid.size()<=0) + return MyCompiler.NO_LINENUMBER; + else{ + return declid.elementAt(0).getOffset(); + } + } + // ino.end + + + + // ino.method.getTypeLineNumber.25611.defdescription type=javadoc + /** + *
Author: J�rg B�uerle + * @return + */ + // ino.end + // ino.method.getTypeLineNumber.25611.definition + public int getTypeLineNumber() + // ino.end + // ino.method.getTypeLineNumber.25611.body + { + return this.getLineNumber(); + } + // ino.end + + + // ino.method.toString.25617.defdescription type=javadoc + /** + *
Author: Martin Pl�micke + * @return + */ + // ino.end + // ino.method.toString.25617.definition + public String toString() + // ino.end + // ino.method.toString.25617.body + { + if(this.getType() == null)return "no type " + declid.toString(); + return this.getType().toString() + " " + declid.toString(); + } + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25620.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25620.body + { + + Type fpType=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 pendantPara=ClassHelper.findGenericType(fpType,paralist,genericMethodParameters); + if(pendantPara!=null){ //Wenn generisch, dann modifizieren + setType(pendantPara); + } + + + } + // ino.end + + + /** + * @author Andreas Stadelmeier, a10023 + * Der Typ der Variablendeklaration wird den Assumptions angefügt. + * Bei einer Deklaration ohne Typangabe wird ein TypePlaceholder den Assumptions hinzugefügt. + */ + @Override + public ConstraintsSet TYPEStmt(TypeAssumptions assumptions) { + ConstraintsSet ret = new ConstraintsSet(); + if((this.getType() instanceof RefType)){ + Type replaceType = null; + replaceType = assumptions.checkType((RefType)this.getType(), this); + this.setType(replaceType); + } + assumptions.addAssumption(new LocalVarAssumption(this, this.getType())); //Bevor der Typ auf Void gesetzt wird. + //if(this.getType() == null)throw new DebugException("Parser Post Processing nicht aufgerufen"); + ret.add(ConstraintsSet.createSingleConstraint(this.getType().TYPE(assumptions, this), this.getType().TYPE(assumptions, this))); + //assumptions.remove(null); // falls Variable mit diesem Namen bereits vorhanden. + this.setReturnType(new Void(this,0)); //Return typ einer Variablendeklaration ist Void + return ret; + } + + @Override + public String getDescription(){ + if(this.getType() == null)return "no type " + declid.toString(); + if(this.getType() instanceof TypePlaceholder)return declid.toString(); + return this.getType().toString() + " " + declid.toString(); + } + + @Override + public void parserPostProcessing(SyntaxTreeNode parent) { + super.parserPostProcessing(parent); + if(this.getType()==null || this.getType() instanceof TypePlaceholder)this.setType(TypePlaceholder.fresh(this)); + } + + @Override + public String getTypeInformation(){ + String ret = "VarDeclaration "; + if(this.getType()!=null)ret+= this.getType().toString()+" "; + ret+=this.get_Name(); + return ret; + } + + @Override + public JavaCodeResult printJavaCode(ResultSet resultSet) { + JavaCodeResult ret = new JavaCodeResult(); + if(this.getType()!=null)ret.attach(getType().printJavaCode(resultSet)).attach(" "); + ret.attach(this.get_Name()+";"); + return ret;} + + @Override + public void setOffset(int offset) { + this.offset = offset; + } + + @Override + public String getIdentifier() { + return this.get_Name(); + } + + @Override + public Menge getChildren() { + Menge ret = new Menge(); + if(this.getType()!=null)ret.add(this.getType()); + return ret; + } + + @Override + public TypeInsertPoint createTypeInsertPoint(TypePlaceholder tph, + ResultSet resultSet) { + return new TypeInsertPoint(this, this, resultSet.getTypeEqualTo(tph),resultSet); + } + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + _cg.getMethodGenerator().getStoreIndex(get_Name()); + return new InstructionList(); + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/LongLiteral.java b/src/de/dhbwstuttgart/syntaxtree/statement/LongLiteral.java index 0cb71703f..8da5f1673 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/LongLiteral.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/LongLiteral.java @@ -9,6 +9,20 @@ import org.apache.bcel.generic.ConstantPoolGen; import org.apache.bcel.generic.InstructionList; 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; + @@ -20,6 +34,9 @@ public class LongLiteral extends Literal // ino.attribute.Int.25451.declaration private long Long; // ino.end + // ino.attribute.parserlog.25454.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end // ino.method.IntLiteral.25457.definition @@ -27,8 +44,10 @@ public class LongLiteral extends Literal // ino.end // ino.method.IntLiteral.25457.body { - super(null,-1); - + super(-1,-1); + + this.setType(new RefType("Long",this,this.getOffset())); + } // ino.end @@ -68,6 +87,54 @@ public class LongLiteral extends Literal { return null; } + + /** + *
Author: Martin Pl�micke + * @return + */ + // ino.end + // ino.method.toString.25484.definition + public String toString() + // ino.end + // ino.method.toString.25484.body + { + return getType().toString() + " " + Long; + } + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25487.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25487.body + { + } + // ino.end + @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 getChildren() { + Menge ret = new Menge(); + return ret; + } + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + ConstantPoolGen cp = _cg.getConstantPool(); + //InstructionFactory _factory = new InstructionFactory(cg, cp); + InstructionList il = new InstructionList(); + + cp.addLong(get_Long()); + il.append(new LDC2_W(cp.getSize()-1)); + return il; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java b/src/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java index 9a9f95de5..c47a44420 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java @@ -11,9 +11,28 @@ import org.apache.bcel.generic.InstructionFactory; import org.apache.bcel.generic.InstructionHandle; 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.Method; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import de.dhbwstuttgart.syntaxtree.misc.UsedId; +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.OderConstraint; +import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.UndConstraint; +import de.dhbwstuttgart.typeinference.assumptions.ClassAssumption; +import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; +import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException; + @@ -24,6 +43,8 @@ public class MethodCall extends Expr { public MethodCall(Receiver receiver, String methodName, ArgumentList argumentList, int offset){ this(offset, 0); + this.set_Receiver(receiver); + this.set_Name(methodName); this.set_ArgumentList(argumentList); } @@ -32,7 +53,7 @@ public class MethodCall extends Expr // ino.end // ino.method.MethodCall.25627.body { - super(null,variableLength); + super(offset,variableLength); } // ino.end @@ -43,8 +64,11 @@ public class MethodCall extends Expr private Receiver receiver; // ino.end // ino.attribute.arglist.25642.declaration - private ArgumentList arglist; + private ArgumentList arglist=new ArgumentList(); + // ino.attribute.parserlog.25663.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end // ino.method.set_ArgumentList.25666.definition public void set_ArgumentList(ArgumentList al) @@ -60,6 +84,7 @@ public class MethodCall extends Expr // ino.end // ino.method.getArgumentList.25669.body { + if(this.arglist==null)return this.arglist = new ArgumentList(); return this.arglist; } // ino.end @@ -71,7 +96,270 @@ public class MethodCall extends Expr { return receiver; } + // ino.end + + // ino.method.get_Name.25675.definition + public String get_Name() + // ino.end + // ino.method.get_Name.25675.body + { + return this.usedid.name.firstElement(); + } + // ino.end + + public void set_Name(String name){ + + this.usedid = new UsedId(name, 0); + } + + + // ino.method.set_Receiver.25693.definition + public void set_Receiver(Receiver rec) + // ino.end + // ino.method.set_Receiver.25693.body + { + receiver=rec; + } + // ino.end + + // ino.method.set_UsedId.25696.definition + public void set_UsedId(UsedId u) + // ino.end + // ino.method.set_UsedId.25696.body + { + usedid=u; + } + // ino.end + + // ino.method.set_Expr_Menge.25699.definition + public void set_Expr_Menge(Menge v) + // ino.end + // ino.method.set_Expr_Menge.25699.body + { + arglist.expr=v; + } + // ino.end + + // ino.method.add_Expr.25702.definition + public void add_Expr(Expr e) + // ino.end + // ino.method.add_Expr.25702.body + { + arglist.expr.addElement(e); + } + // ino.end + + + + // ino.method.toString.25738.defdescription type=javadoc + /** + *
Author: Martin Pl�micke + * @return + */ + // ino.end + // ino.method.toString.25738.definition + public String toString() + // ino.end + // ino.method.toString.25738.body + { + //return receiver/*.toString()*/ + " " + usedid.toString(); + return type + " (" + this.get_Receiver() + "." + this.get_Name() +"(" + this.getArgumentList() + "))"; + } + // ino.end + + // ino.method.wandleRefTypeAttributes2GenericAttributes.25741.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25741.body + { + } + // ino.end + + /** + * @author Andreas Stadelmeier, a10023 + * @return der Name der Methode, welcher dieser MethodCall aufruft. + */ + public String getName(){ + return this.usedid.toString(); + } + + /** + * @author AI10023 - Andreas Stadelmeier + * + * Mögliche Probleme: + * Wenn die Methode ohne Angabe eines Receivers im Quelltext steht: + * methodCall(param); -> (bedeutet:) this.methodCall(param); + * Parser möglicherweise anpassen (siehe JavaParser.jay Zeile 1858 ff) + */ + @Override + public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) { + //Hier der Ablauf für einen Methodenaufruf: + ConstraintsSet ret = new ConstraintsSet(); + //Der Return-Type des MEthodenaufrufs ist zunächst unbekannt: + this.setType(TypePlaceholder.fresh(this)); + //Berechne die Constraints des Receivers + if(receiver == null){ + receiver = new Receiver(new This(this)); + } + ret.add(receiver.get_Expr().TYPEExpr(assumptions)); + + //Berechne die Constraints der Argumente aus der Argumentlist (also der Parameter, welche der Funktion übergeben wurden) + if(this.arglist != null)for(Expr arg : this.arglist.expr){ + ret.add(arg.TYPEExpr(assumptions)); + } + + //Noch das Overloading-Constraint anhängen: + ret.add(overloading(assumptions)); + + /* + //Die Klasse für den Receiver setzen: Das ist für die Bytecodegenerierung notwendig. + ClassAssumption receiverClassAssumption = assumptions.getClassAssumptionFor(receiver.get_Expr().getType()); + de.dhbwstuttgart.syntaxtree.Class receiverCl = receiverClassAssumption.getAssumedClass(); + this.receiver.setClass(receiverCl); + */ + //Die Assumptions für den Receiver setzen: + this.receiver.setAssumptions(assumptions); + + return ret; + } + + /** + * Erstellt die Constraints für den eigentlichen Methodenaufruf. + * Sucht in den Assumptions nach passenden Methoden und erstellt ein OderConstraintSet. + * @param assumptions + * @return + */ + public ConstraintsSet overloading(TypeAssumptions assumptions){ + ConstraintsSet ret = new ConstraintsSet(); + //ret.add(new Overloading(assumptions, this, this.getType()).generateConsstraints()); + OderConstraint oCons = new OderConstraint(); + Menge methodAssumptions = assumptions.getMethodAssumptions(this.getName(), this.getArgumentList().size()); + if(methodAssumptions.size()==0)throw new TypeinferenceException("Eine Methode "+this.get_Name()+" ist in den Assumptions nicht vorhanden", this); + //Alle möglichen Methoden durchgehen: + for(MethodAssumption methodAssumption : methodAssumptions){ + //Constraint nicht erstellen, falls Rückgabetyp von vorne herein nicht übereinstimmt: + if(!(this.type instanceof TypePlaceholder) && !this.type.equals(methodAssumption.getAssumedType()))break; + oCons.addConstraint(constraintsFromMethodAssumption(methodAssumption, assumptions)); + } + ret.add(oCons); + return ret; + } + + /** + * Spezifikation: + * overloading determines for all possible overloadings and overridings + * of a method the constraints, where constraints itself forms + * the constraints from the receiver type, the argument types, the return + * type and a given type assumption for the method. If it is a + * method from a class, which is not the actual class (this), all type + * variables are replaced by fresh type variables (fresh), as different + * instances can occur. sargs determines all type assumptions of a + * method, where the argument types are supertypes of a minimal type + * assumption. + * + * @TODO: wenn es sich um eine Methode einer anderen Klasse handelt, müssen neue TPH vergeben werden und nicht die der Assumption verwendet werden. + * + * @return + */ + public UndConstraint constraintsFromMethodAssumption(MethodAssumption methodAssumption, TypeAssumptions assumptions){ + UndConstraint methodConstraint = new UndConstraint(); + //Ein Constraint für den ReturnType der Methode... + methodConstraint.addConstraint(methodAssumption.getAssumedType().TYPE(assumptions, this), this.getType().TYPE(assumptions, this)); + //Ein Constraint für die Parameter der Methode... + for(int i=0; i getChildren() { + Menge ret = new Menge(); + for(Expr e : this.arglist.expr){ + ret.add(e); + } + if(this.receiver!=null)ret.add(this.receiver.get_Expr()); + return ret; + } + + /* + @Override + public void parserPostProcessing(SyntaxTreeNode parent) { + super.parserPostProcessing(parent); + } + */ + + @Override + public InstructionList genByteCode(ClassGenerator cg, TypeinferenceResultSet rs) { + InstructionList il = new InstructionList(); + DHBWInstructionFactory _factory = cg.getInstructionFactory(); + + il.append(receiver.get_Expr().genByteCode(cg, rs)); + + //Herausfinden, ob eine Methode oder ein Interface aufgerufen wird: + Type receiverType = this.receiver.get_Expr().getType(); + de.dhbwstuttgart.syntaxtree.Class receiverClass = this.receiver.getReceiverClass(cg, rs); + short kind = 0; + if(receiverClass.isInterface()){ + kind = Const.INVOKEINTERFACE; + }else{//Ansonsten muss es eine Klasse sein: + kind = Const.INVOKEVIRTUAL; + } + + org.apache.bcel.generic.Type[] argumentTypen = org.apache.bcel.generic.Type.NO_ARGS; + if(this.getArgumentList() != null && this.getArgumentList().size()>0){ + argumentTypen = new org.apache.bcel.generic.Type[this.getArgumentList().size()]; + int i = 0; + for(Expr argument : this.arglist.expr){ + cg.getMethodGenerator().getStoreIndex(argument.get_Name()); + + argumentTypen[i] = argument.getType().getBytecodeType(cg, rs); + //Das Argument auf den Stack legen: + il.append(argument.genByteCode(cg, rs)); + i++; + } + } + + org.apache.bcel.generic.Type returnType = this.getType().getBytecodeType(cg, rs); + il.append(_factory.createInvoke( + receiver.get_Expr().getType().getBytecodeType(cg, rs).toString(), + //receiver.getReceiverClass(cg, rs).getBytecodeType(cg, rs).toString(), + this.get_Name(), returnType , argumentTypen, kind)); + return il; + } + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/NegativeExpr.java b/src/de/dhbwstuttgart/syntaxtree/statement/NegativeExpr.java index c3d48f8c6..62eab993f 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/NegativeExpr.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/NegativeExpr.java @@ -8,6 +8,25 @@ 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.type.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.type.RefType; +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.Pair; +import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; +import de.dhbwstuttgart.typeinference.unify.TypeUnify; + +import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException; + // ino.class.NegativeExpr.25744.declaration @@ -29,6 +48,9 @@ public class NegativeExpr extends UnaryExpr // ino.attribute.expr.25754.declaration public Expr expr; // ino.end + // ino.attribute.parserlog.25757.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end // ino.method.get_Name.25760.definition public String get_Name() @@ -57,5 +79,39 @@ public class NegativeExpr extends UnaryExpr } // ino.end + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25784.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25784.body + { + } + // ino.end + + @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 getChildren() { + Menge ret = new Menge(); + ret.add(this.expr); + return ret; + } + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + // TODO Bytecode + throw new NotImplementedException(); + } + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/NewArray.java b/src/de/dhbwstuttgart/syntaxtree/statement/NewArray.java index 5d8388ba0..a42570dec 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/NewArray.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/NewArray.java @@ -3,13 +3,24 @@ package de.dhbwstuttgart.syntaxtree.statement; // ino.end // ino.module.NewArray.8641.import import java.util.Hashtable; -import java.util.List; -import de.dhbwstuttgart.syntaxtree.type.RefType; 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.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; @@ -24,17 +35,110 @@ public class NewArray extends Expr // ino.end // ino.method.NewArray.25791.body { - super(null,variableLength); + super(offset,variableLength); } // ino.end // ino.attribute.type.25794.declaration - private RefType type; + private Type type; // ino.end // ino.attribute.expr.25797.declaration - public List expr; + public Menge expr = new Menge(); + // ino.end + // ino.attribute.parserlog.25800.declaration + protected static Logger parserlog = Logger.getLogger("parser"); // ino.end + + // ino.method.getType.25803.defdescription type=javadoc + /** + * Author: J�rg B�uerle
+ * @return Returns the type. + */ + // ino.end + // ino.method.getType.25803.definition + public Type getType() + // ino.end + // ino.method.getType.25803.body + { + return type; + } + // ino.end + + // ino.method.setType.25806.defdescription type=javadoc + /** + * Author: J�rg B�uerle
+ * @param type The type to set. + */ + // ino.end + // ino.method.setType.25806.definition + public void setType(Type type) + // ino.end + // ino.method.setType.25806.body + { + this.type = type; + } + // ino.end + + // ino.method.get_Name.25809.definition + public String get_Name() + // ino.end + // ino.method.get_Name.25809.body + { + return null; + } + // ino.end + /* + // ino.method.sc_check.25812.definition + public void sc_check(Menge classname, Hashtable bh, Hashtable ch,boolean ext, Hashtable parach, Hashtable parabh) + // ino.end + // ino.method.sc_check.25812.body + { + if(ext) + parserlog.debug(" ---NewArray---"); + } + // ino.end + */ + + + // ino.method.wandleRefTypeAttributes2GenericAttributes.25827.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25827.body + { + } + // ino.end + + @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 getChildren() { + Menge ret = new Menge(); + ret.addAll(this.expr); + return ret; + } + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + InstructionFactory _factory = new InstructionFactory(_cg, _cg.getConstantPool()); + InstructionList il = new InstructionList(); + + il.append(expr.elementAt(0).genByteCode(_cg, rs)); + il.append(_factory.createNewArray( org.apache.bcel.generic.Type.getType(getTypeName()), (short)1)); + + + return il; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/NewClass.java b/src/de/dhbwstuttgart/syntaxtree/statement/NewClass.java index 34ea35ebd..0f23a46ad 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/NewClass.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/NewClass.java @@ -13,7 +13,30 @@ import org.apache.bcel.generic.ClassGen; 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.logger.Logger; +import de.dhbwstuttgart.syntaxtree.Class; +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import de.dhbwstuttgart.syntaxtree.misc.UsedId; +import de.dhbwstuttgart.syntaxtree.type.FunN; +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.ResultSet; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.UndConstraint; +import de.dhbwstuttgart.typeinference.assumptions.ConstructorAssumption; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; +import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException; @@ -28,14 +51,17 @@ public class NewClass extends Expr // ino.end // ino.method.NewClass.25834.body { - super(null,variableLength); + super(offset,variableLength); } // ino.end // ino.attribute.arglist.25837.declaration private ArgumentList arglist; private boolean isStatement = false; - private List parameterList = new ArrayList<>(); + private List parameterList = new ArrayList<>(); + // ino.end + // ino.attribute.parserlog.25840.declaration + protected static Logger parserlog = Logger.getLogger("parser"); // ino.end @@ -48,6 +74,159 @@ public class NewClass extends Expr } // ino.end + // ino.method.get_Name.25846.definition + public String get_Name() + // ino.end + // ino.method.get_Name.25846.body + { + return this.usedid.get_Name_1Element(); + } + // ino.end + + // ino.method.set_UsedId.25849.definition + public void set_UsedId( UsedId t) + // ino.end + // ino.method.set_UsedId.25849.body + { + this.usedid = t; + } + // ino.end + + // ino.method.set_ArgumentList.25855.definition + public void set_ArgumentList(ArgumentList al) + // ino.end + // ino.method.set_ArgumentList.25855.body + { + this.arglist = al; + } + // ino.end + + // ino.method.toString.25867.defdescription type=javadoc + /** + *
Author: Martin Pl�micke + * @return + */ + // ino.end + // ino.method.toString.25867.definition + public String toString() + // ino.end + // ino.method.toString.25867.body + { + String ret = "NEW "; + Type thisType = getType(); + if(thisType != null)ret += thisType.toString(); + else ret += this.get_Name(); + return ret; + } + // ino.end + + // ino.method.wandleRefTypeAttributes2GenericAttributes.25870.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25870.body + { + } + // ino.end + + @Override + public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) { + ConstraintsSet ret = new ConstraintsSet(); + UndConstraint callConstraints = new UndConstraint(); + + int numArgs = 0; + if(this.arglist != null)numArgs = this.arglist.size(); + ConstructorAssumption cA = assumptions.getConstructorAssumption(this.get_Name(), numArgs); + if(cA == null)throw new TypeinferenceException("Der Konstruktor "+this.get_Name()+" mit "+numArgs+" Parametern ist nicht vorhanden.", this); + + for(int i=0; i it = this.arglist.expr.iterator(); + while(it.hasNext()){ + Expr arg = it.next(); + ret.attach(arg.printJavaCode(resultSet)); + if(it.hasNext())ret.attach(", "); + } + //ret = ret.substring(0, ret.length()-2); + } + ret.attach(")"); + + return ret; + } + @Override + public Menge getChildren() { + Menge ret = new Menge(); + if(this.arglist!=null)for(Expr e : this.arglist.expr){ + ret.add(e); + } + return ret; + } + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + InstructionList il = new InstructionList(); + //il.append(_cg.getInstructionFactory().createNew(get_Name())); + il.append(_cg.getInstructionFactory().createNew(this.getType().getBytecodeType(_cg, rs).toString())); + il.append(InstructionConstants.DUP); + + String signature = getType().getBytecodeSignature(_cg, rs); + String description = signature.substring(1, signature.length()-1); + + if(arglist!=null){ + il.append(arglist.generateBytecode(_cg, rs)); + il.append(_cg.getInstructionFactory().createInvoke(description, "", + org.apache.bcel.generic.Type.VOID, + this.arglist.getBytecodeTypeList(_cg, rs), Constants.INVOKESPECIAL)); + }else{ + il.append(_cg.getInstructionFactory().createInvoke(description, "", + org.apache.bcel.generic.Type.VOID, + new org.apache.bcel.generic.Type[]{}, Constants.INVOKESPECIAL)); + } + if(this.isStatement){ + il.append(InstructionConstants.POP); + } + return il; + } + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/NotExpr.java b/src/de/dhbwstuttgart/syntaxtree/statement/NotExpr.java index 13aec388a..46b4f4ea3 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/NotExpr.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/NotExpr.java @@ -8,9 +8,24 @@ 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.type.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.type.RefType; +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.OderConstraint; +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.unify.TypeUnify; +import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException; @@ -34,6 +49,10 @@ public class NotExpr extends UnaryExpr // ino.attribute.expr.25883.declaration public Expr expr; // ino.end + // ino.attribute.parserlog.25886.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end + // ino.method.get_Name.25892.definition @@ -72,5 +91,52 @@ public class NotExpr extends UnaryExpr } // ino.end +/* + public void if_codegen(ClassFile classfile, Code_attribute code, boolean sw) throws JVMCodeException { + if(expr instanceof NotExpr) if_codegen(classfile, code, !sw); + else { + expr.codegen(classfile, code); + not.if_codegen(classfile, code, sw); + } + } +*/ + + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25916.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25916.body + { + } + // ino.end + + @Override + public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) { + ConstraintsSet ret = new ConstraintsSet(); + OderConstraint constraint = new OderConstraint(); + constraint.addConstraint(this.getType().TYPE(assumptions, this), new RefType("Boolean",this,-1).TYPE(assumptions, this)); + ret.add(constraint); + return ret; + } + + @Override +public JavaCodeResult printJavaCode(ResultSet resultSet) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Menge getChildren() { + Menge ret = new Menge(); + ret.add(this.expr); + return ret; + } + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + // TODO Bytecode + throw new NotImplementedException(); + } + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/Null.java b/src/de/dhbwstuttgart/syntaxtree/statement/Null.java index 6229d2b5f..cf3c6b121 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/Null.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/Null.java @@ -9,6 +9,19 @@ 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.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.TypeAssumptions; @@ -18,14 +31,17 @@ public class Null extends Literal // ino.end // ino.class.Null.25919.body { - + + // ino.attribute.parserlog.25923.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end // ino.method.Null.25926.definition public Null() // ino.end // ino.method.Null.25926.body { - super(null,-1); + super(-1,-1); //this.setType(new Type("__NULL__",this,getOffset())); } // ino.end @@ -51,6 +67,41 @@ public class Null extends Literal // ino.end */ + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25944.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25944.body + { + } + // ino.end + + @Override + public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) { + this.setType(TypePlaceholder.fresh(this)); + return new ConstraintsSet(); + } + + @Override + public JavaCodeResult printJavaCode(ResultSet resultSet) { + return new JavaCodeResult("null"); + } + + @Override + public Menge getChildren() { + return new Menge(); + } + + @Override + public InstructionList genByteCode(ClassGenerator cg, TypeinferenceResultSet rs) { + InstructionFactory _factory = new InstructionFactory(cg, cg.getConstantPool()); + InstructionList il = new InstructionList(); + + il.append(InstructionConstants.ACONST_NULL); + + + return il; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/PositivExpr.java b/src/de/dhbwstuttgart/syntaxtree/statement/PositivExpr.java index 3bd482804..01a09b97d 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/PositivExpr.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/PositivExpr.java @@ -7,8 +7,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; @@ -32,6 +43,9 @@ public class PositivExpr extends UnaryExpr // ino.attribute.expr.25957.declaration public Expr expr; // ino.end + // ino.attribute.parserlog.25960.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end @@ -75,6 +89,39 @@ public class PositivExpr extends UnaryExpr // ino.end */ + // ino.method.wandleRefTypeAttributes2GenericAttributes.25984.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.25984.body + { + } + // ino.end + + + @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 getChildren() { + Menge ret = new Menge(); + ret.add(this.expr); + return ret; + } + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + // TODO Bytecode + throw new NotImplementedException(); + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/PostDecExpr.java b/src/de/dhbwstuttgart/syntaxtree/statement/PostDecExpr.java index 76dbc473d..94dfa98e1 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/PostDecExpr.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/PostDecExpr.java @@ -8,6 +8,18 @@ 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.type.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.typeinference.JavaCodeResult; +import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException; @@ -24,6 +36,9 @@ public class PostDecExpr extends UnaryExpr super(offset,variableLength); } // ino.end + // ino.attribute.parserlog.25997.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end @@ -45,5 +60,33 @@ public class PostDecExpr extends UnaryExpr } // ino.end + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.26018.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.26018.body + { + } + // ino.end + + @Override +public JavaCodeResult printJavaCode(ResultSet resultSet) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Menge getChildren() { + Menge ret = new Menge(); + ret.add(this.expr); + return ret; + } + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + // TODO Bytecode + throw new NotImplementedException(); + } + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/PostIncExpr.java b/src/de/dhbwstuttgart/syntaxtree/statement/PostIncExpr.java index c436e62df..891198de4 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/PostIncExpr.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/PostIncExpr.java @@ -11,7 +11,25 @@ import org.apache.bcel.generic.IINC; 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.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.syntaxtree.type.Void; +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.TypeAssumptions; +import de.dhbwstuttgart.typeinference.unify.TypeUnify; @@ -29,7 +47,11 @@ public class PostIncExpr extends UnaryExpr super(offset,variableLength); } // ino.end - + + // ino.attribute.parserlog.26031.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end + // ino.method.set_Expr.26034.definition @@ -50,6 +72,43 @@ public class PostIncExpr extends UnaryExpr } // ino.end + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.26052.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.26052.body + { + } + // ino.end + + @Override +public JavaCodeResult printJavaCode(ResultSet resultSet) { + JavaCodeResult ret = new JavaCodeResult(); + ret.attach(this.expr.printJavaCode(resultSet)); + ret.attach("++"); + return ret; + } + + @Override + public Menge getChildren() { + Menge ret = new Menge(); + ret.add(this.expr); + return ret; + } + + public static int counterPostInc = 0; + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + InstructionFactory _factory = new InstructionFactory(_cg, _cg.getConstantPool()); + InstructionList il = new InstructionList(); + counterPostInc++; + il.append(new IINC(counterPostInc,1)); + //Tests aufgrund fehlener TypInferenz-Funktionalit�t nicht m�glich + //Vermutlich muss der Counter noch angepasst werden, da nicht incrementierende Variablen nicht mitgez�hlt werden, und zu falschen aufrufen f�hren + //Gibt es einen Compiler-internen Variablenindex, der den Counter effektiver ersetzen k�nnte + return il; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/PreDecExpr.java b/src/de/dhbwstuttgart/syntaxtree/statement/PreDecExpr.java index 06eb6049f..a278d6666 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/PreDecExpr.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/PreDecExpr.java @@ -8,6 +8,23 @@ 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.type.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.type.RefType; +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.Pair; +import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; +import de.dhbwstuttgart.typeinference.unify.TypeUnify; +import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException; @@ -25,7 +42,11 @@ public class PreDecExpr extends UnaryExpr super(offset,variableLength); } // ino.end - + + // ino.attribute.parserlog.26065.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end + // ino.method.set_Expr.26068.definition @@ -45,6 +66,32 @@ public class PreDecExpr extends UnaryExpr } // ino.end + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.26086.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.26086.body + { + } + // ino.end + + @Override + public JavaCodeResult printJavaCode(ResultSet resultSet) { + // TODO Auto-generated method stub + return null; + } + @Override + public Menge getChildren() { + Menge ret = new Menge(); + ret.add(this.expr); + return ret; + } + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + // TODO Bytecode + throw new NotImplementedException(); + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/PreIncExpr.java b/src/de/dhbwstuttgart/syntaxtree/statement/PreIncExpr.java index e1f1bdf78..5c2000715 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/PreIncExpr.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/PreIncExpr.java @@ -8,8 +8,23 @@ 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.type.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.type.RefType; +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.Pair; +import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; +import de.dhbwstuttgart.typeinference.unify.TypeUnify; +import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException; @@ -27,6 +42,9 @@ public class PreIncExpr extends UnaryExpr super(offset,variableLength); } // ino.end + // ino.attribute.parserlog.26099.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end @@ -48,7 +66,34 @@ public class PreIncExpr extends UnaryExpr return null; } // ino.end + + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.26120.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.26120.body + { + } + // ino.end + + @Override +public JavaCodeResult printJavaCode(ResultSet resultSet) { + // TODO Auto-generated method stub + return null; + } + @Override + public Menge getChildren() { + Menge ret = new Menge(); + ret.add(this.expr); + return ret; + } + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + // TODO Bytecode + throw new NotImplementedException(); + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/Receiver.java b/src/de/dhbwstuttgart/syntaxtree/statement/Receiver.java index 95610c872..2b0dbb0da 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/Receiver.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/Receiver.java @@ -3,9 +3,18 @@ package de.dhbwstuttgart.syntaxtree.statement; // ino.end // ino.module.Receiver.8650.import import java.util.Hashtable; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.bytecode.ClassGenerator; +import de.dhbwstuttgart.logger.Logger; import de.dhbwstuttgart.syntaxtree.Class; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.JavaCodeResult; +import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.assumptions.ClassAssumption; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; +import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException; @@ -17,7 +26,12 @@ public class Receiver { // ino.attribute.expr.26126.declaration private Expr expr; + private TypeAssumptions typeAssumptions; // ino.end + // ino.attribute.parserlog.26129.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end + // ino.method.Receiver.26132.defdescription type=javadoc /** * Autor: J�rg B�uerle @@ -32,6 +46,82 @@ public class Receiver this.expr = expr; } // ino.end + + // ino.method.get_Type.26138.definition + public String get_Type() + // ino.end + // ino.method.get_Type.26138.body + { + return expr.getTypeName(); + } + // ino.end + + // ino.method.set_Expr.26141.definition + public void set_Expr(Expr express) + // ino.end + // ino.method.set_Expr.26141.body + { + expr=express; + } + // ino.end + + // ino.method.get_Expr.26144.definition + public Expr get_Expr() + // ino.end + // ino.method.get_Expr.26144.body + { + return expr; + } + // ino.end + + // ino.method.toString.26147.defdescription type=javadoc + /** + *
Author: Martin Pl�micke + * @return + */ + // ino.end + // ino.method.toString.26147.definition + public String toString() + // ino.end + // ino.method.toString.26147.body + { + return expr.toString(); + } + // ino.end + + /* + public void setClass(Class cl){ + this.receiverClass = cl; + } + */ + + public Class getReceiverClass(ClassGenerator cg, TypeinferenceResultSet rs){ + de.dhbwstuttgart.syntaxtree.type.Type receiverType = this.get_Expr().getType(); + if(receiverType instanceof TypePlaceholder){ + receiverType = rs.getTypeOfPlaceholder((TypePlaceholder)receiverType); + } + if(!(receiverType instanceof RefType)){ + throw new TypeinferenceException("Typ des Receivers nicht eindeutig",this.get_Expr()); + } + ClassAssumption receiverClassAssumption = typeAssumptions.getClassAssumptionFor((RefType)receiverType); + if(receiverClassAssumption == null) + throw new TypeinferenceException("Die Klasse für den Typ "+receiverType+" ist nicht in den Assumptions vorhanden", receiverType); + de.dhbwstuttgart.syntaxtree.Class receiverCl = receiverClassAssumption.getAssumedClass(); + return receiverCl; + } + + /** + * Setzt die TypeAssumptions für diesen Receiver. + * Das ist notwendig für die Bytecodegenerierung + * @param ass + */ + public void setAssumptions(TypeAssumptions ass){ + this.typeAssumptions = ass; + } + + public JavaCodeResult printJavaCode(ResultSet resultSet) { + return new JavaCodeResult().attach(this.get_Expr().printJavaCode(resultSet)); + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/Return.java b/src/de/dhbwstuttgart/syntaxtree/statement/Return.java index aabd042dc..a17a6714d 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/Return.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/Return.java @@ -9,8 +9,20 @@ import org.apache.bcel.generic.InstructionFactory; import org.apache.bcel.generic.InstructionList; import org.apache.bcel.generic.ClassGen; +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.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.TypeAssumptions; + @@ -24,12 +36,16 @@ public class Return extends Statement // ino.end // ino.method.Return.26154.body { - super(null,variableLength); + super(offset,variableLength); } // ino.end // ino.attribute.retexpr.26157.declaration public Expr retexpr; // ino.end + // ino.attribute.parserlog.26160.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end + // ino.method.set_ReturnExpr.26166.definition @@ -42,5 +58,86 @@ public class Return extends Statement } // ino.end + // ino.method.get_Type.26169.definition + public String get_Type() + // ino.end + // ino.method.get_Type.26169.body + { + return retexpr.getTypeName(); + } + // ino.end + + + // ino.method.toString.26178.definition + public String toString() + // ino.end + // ino.method.toString.26178.body + { + return type + " Return " + retexpr.toString(); + } + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.26181.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.26181.body + { + } + // ino.end + + @Override + public ConstraintsSet TYPEStmt(TypeAssumptions assumptions) { + ConstraintsSet ret = new ConstraintsSet(); + ret.add(this.retexpr.TYPEExpr(assumptions)); + //this.setTypeVariable(TypePlaceholder.fresh("Return Type")); + this.setType(TypePlaceholder.fresh(this)); + ret.add(ConstraintsSet.createSingleConstraint(retexpr.getType().TYPE(assumptions, this), this.getType().TYPE(assumptions, this))); + return ret; + } + + public int getTypeLineNumber() { + return 0; + } + + @Override + public String getTypeInformation(){ + String ret = this.getType()+" :: (Return "+this.retexpr.getTypeInformation()+")"; + return ret; + } + + @Override + public JavaCodeResult printJavaCode(ResultSet resultSet) { + JavaCodeResult ret = new JavaCodeResult("return "); + ret.attach(this.retexpr.printJavaCode(resultSet)); + return ret.attach(";"); + } + + @Override + public Menge getChildren() { + Menge ret = new Menge(); + ret.add(this.retexpr); + return ret; + } + + @Override + public void setReturnType(Type t){ + this.setType(t); + } + + @Override + public Type getReturnType(){ + return this.getType(); + } + + @Override + public InstructionList genByteCode(ClassGenerator cg, TypeinferenceResultSet rs) { + InstructionList il = retexpr.genByteCode(cg, rs); + + InstructionFactory _factory = new InstructionFactory(cg, cg.getConstantPool()); + + org.apache.bcel.generic.Type retType = this.getReturnType().getBytecodeType(cg, rs);//retexpr.getType().getBytecodeType(); + il.append(_factory.createReturn(retType )); + + return il; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/Statement.java b/src/de/dhbwstuttgart/syntaxtree/statement/Statement.java index 5f5bed744..f8103e0d5 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/Statement.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/Statement.java @@ -4,12 +4,26 @@ package de.dhbwstuttgart.syntaxtree.statement; import java.util.Enumeration; import java.util.Hashtable; -import de.dhbwstuttgart.syntaxtree.type.RefType; import org.apache.bcel.generic.ClassGen; import org.apache.bcel.generic.ConstantPoolGen; 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.core.IItemWithOffset; +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.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.ConstraintsSet; +import de.dhbwstuttgart.typeinference.JavaCodeResult; +import de.dhbwstuttgart.typeinference.Pair; +import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.Typeable; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; @@ -17,11 +31,41 @@ public abstract class Statement extends Executeable { - public Statement(RefType type, int offset) + public Statement(Type type,int offset) { super(type,offset); } - + + + /** + * @author AI10023 - Andreas Stadelmeier + * Implementierung des Java 8 - Typinferenzalgorithmus von Martin Plümicke + * Jedes Statement wird im Zuge des Algorithmus durch die TYPEExpr-Funktion angesprochen. + */ + public abstract ConstraintsSet TYPEStmt(TypeAssumptions assumptions); + + /** + * @author Andreas Stadelmeier, a10023 + * Sollte von jedem Statement überschrieben werden. + * Liefert Informationen zum Statment und dessen Typ. + * @return + */ + public String getTypeInformation(){ + return this.printJavaCode(new ResultSet(new Menge()))+" : "+this.getType().toString(); + } + + @Override + public String getDescription(){ + return this.printJavaCode(new ResultSet(new Menge())).toString(); + } + + public void setReturnType(Type t){ + } + + public Type getReturnType(){ + return new de.dhbwstuttgart.syntaxtree.type.Void(-1); + } + } \ No newline at end of file diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/StringLiteral.java b/src/de/dhbwstuttgart/syntaxtree/statement/StringLiteral.java index ecd28e54d..1c043363b 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/StringLiteral.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/StringLiteral.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.syntaxtree.statement; +import de.dhbwstuttgart.typeinference.Menge; @@ -17,19 +18,39 @@ import org.apache.bcel.generic.InstructionFactory; import org.apache.bcel.generic.InstructionList; import org.apache.bcel.generic.LDC; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.bytecode.ClassGenerator; +import de.dhbwstuttgart.logger.Logger; +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 StringLiteral extends Literal { private String string; + // ino.attribute.parserlog.26234.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end + // ino.method.StringLiteral.26237.definition public StringLiteral() // ino.end // ino.method.StringLiteral.26237.body { - super(null,-1); + super(-1,-1); // #JB# 20.04.2005 + // ########################################################### + this.setType(new RefType("java.lang.String",this,getOffset())); + //this.setType(new Type("String")); + // ########################################################### } // ino.end @@ -63,5 +84,60 @@ public class StringLiteral extends Literal } // ino.end + + // ino.method.wandleRefTypeAttributes2GenericAttributes.26258.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.26258.body + { + } + // ino.end + + @Override + public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) { + this.set_Type(assumptions.checkType(new RefType("String",this,0), this)); + return new ConstraintsSet(); + } + + @Override + public JavaCodeResult printJavaCode(ResultSet resultSet) { + return new JavaCodeResult("\""+this.string+"\""); + } + + @Override + public Menge getChildren() { + Menge ret = new Menge(); + return ret; + } + + @Override + public String toString(){ + return "\""+this.string+"\""; + } + + + public String get_String() + // ino.end + // ino.method.get_Name.26246.body + { + return string; + } + //public static int counterString = 0; + @Override + public InstructionList genByteCode(ClassGenerator cg, TypeinferenceResultSet rs) { + ConstantPoolGen cp = cg.getConstantPool(); + InstructionFactory _factory = new InstructionFactory(cg, cp); + InstructionList il = new InstructionList(); + //counterString++; + //il.append(_factory.ASTORE_1, _factory.createNew(string)); + cp.addString(get_String()); + il.append(new LDC(cp.getSize()-1)); + return il; + + } + + + + } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java b/src/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java index a338065e8..28cb0bb26 100644 --- a/src/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java @@ -8,7 +8,17 @@ import org.apache.bcel.generic.InstructionFactory; import org.apache.bcel.generic.InstructionHandle; import org.apache.bcel.generic.InstructionList; +import de.dhbwstuttgart.bytecode.ClassGenerator; +import de.dhbwstuttgart.syntaxtree.Constructor; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +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; +import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException; @@ -16,12 +26,69 @@ public class SuperCall extends ThisCall { public SuperCall(int offset,int variableLength) { - super(null,null,variableLength); + super(offset,variableLength); } public SuperCall(SyntaxTreeNode parent){ this(0,0); + this.parent = parent; } + + @Override + public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) { + throw new TypeinferenceException("super(...)-Aufruf kann nicht als Ausdruck verwendet werden",this); + } + /** + * This kann auch als Konstruktoraufruf in einem Konstruktor-Block vorkommen. + */ + @Override + public ConstraintsSet TYPEStmt(TypeAssumptions assumptions) { + String className = this.getParentClass().getSuperClass().getName().toString(); + ConstraintsSet ret = new ConstraintsSet(); + this.setType(new Void(this,this.getOffset())); + //Kontrollieren, dass sich this(...) in einem Konstruktor und dort als erstes Statement befindet: + SyntaxTreeNode p = this.getGTVDeclarationContext(); + if(p instanceof Constructor && + ((Constructor)p).get_Block().statements.firstElement().equals(this)){ + //Constraints generieren: + + if(this.arglist == null)this.arglist = new ArgumentList(); + + MethodCall constructorCall = new ConstructorCall(new Receiver(new This(this)), className, arglist, this.getOffset()); + constructorCall.parserPostProcessing(this); + ret.add(constructorCall.TYPEStmt(assumptions)); + return ret; + }else{ + //Ansonsten Fehler ausgeben: + throw new TypeinferenceException("super()-Aufruf hier nicht möglich", this); + } + } + + public String toString() + { + //return receiver/*.toString()*/ + " " + usedid.toString(); + return "(" + "super" +"(" + this.getArgumentList() + "))"; + } + + @Override + public JavaCodeResult printJavaCode(ResultSet resultSet) { + String argList = ""; + if(this.getArgumentList() != null)argList = this.getArgumentList().printJavaCode(resultSet).getJavaCode(); + return new JavaCodeResult("super("+argList+")"); + } + + @Override + public InstructionList genByteCode(ClassGenerator cg, TypeinferenceResultSet rs) { + InstructionFactory _factory = new InstructionFactory(cg, cg.getConstantPool()); + InstructionList il = new InstructionList(); + Type superClass = this.getParentClass().getSuperClass(); + //Instructionhandle dynamisch + InstructionHandle ih_0 = il.append(_factory.createLoad( org.apache.bcel.generic.Type.OBJECT, 0)); + il.append(_factory.createInvoke(superClass.getName().toString(), "", org.apache.bcel.generic.Type.VOID, org.apache.bcel.generic.Type.NO_ARGS, Constants.INVOKESPECIAL)); + //InstructionHandle ih_4 = il.append(_factory.createReturn( org.apache.bcel.generic.Type.VOID)); + + return il; + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/This.java b/src/de/dhbwstuttgart/syntaxtree/statement/This.java index 482aa4bbc..767e18f72 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/This.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/This.java @@ -11,9 +11,25 @@ import org.apache.bcel.generic.InstructionList; import org.apache.bcel.generic.MethodGen; import org.apache.bcel.generic.ObjectType; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.bytecode.ClassGenerator; +import de.dhbwstuttgart.logger.Logger; import de.dhbwstuttgart.syntaxtree.Class; import de.dhbwstuttgart.syntaxtree.Constructor; 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.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.ConstructorAssumption; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; +import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException; + + // ino.class.This.26261.declaration public class This extends Expr @@ -25,16 +41,114 @@ public class This extends Expr // ino.end // ino.method.This.26265.body { - super(null,variableLength); + super(offset,variableLength); } // ino.end public This(SyntaxTreeNode parent){ this(0,0); + this.parent = parent; } // ino.attribute.arglist.26268.declaration public ArgumentList arglist; // ino.end + + // ino.attribute.parserlog.26271.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end + + + // ino.method.set_ArgumentList.26274.definition + public void set_ArgumentList(ArgumentList al) + // ino.end + // ino.method.set_ArgumentList.26274.body + { + this.arglist = al; + } + // ino.end + + public ArgumentList getArgumentList() + { + return this.arglist; + } + + // ino.method.set_UsedId.26277.definition + public void set_UsedId(UsedId ui) + // ino.end + // ino.method.set_UsedId.26277.body + { + this.usedid = ui; + } + // ino.end + + /* + // ino.method.sc_check.26280.definition + public void sc_check(Menge classname, Hashtable ch, Hashtable bh, boolean ext, Hashtable parach, Hashtable parabh) + throws SCStatementException + // ino.end + // ino.method.sc_check.26280.body + { + if(ext) + parserlog.debug(" ---This---"); + } + // ino.end + */ + + // ino.method.get_Name.26286.definition + public String get_Name() + // ino.end + // ino.method.get_Name.26286.body + { return null; } + // ino.end + + + // ino.method.wandleRefTypeAttributes2GenericAttributes.26295.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.26295.body + { + } + // ino.end + + @Override + public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) { + ConstraintsSet ret = new ConstraintsSet(); + //this.set_Type(new); + //this.setType(assumptions.getThisValue());//Die Assumption für this als TypeVariable setzen. + this.setType(this.getParentClass().getType()); + return ret; + } + + @Override + public ConstraintsSet TYPEStmt(TypeAssumptions assumptions) { + throw new TypeinferenceException("this ist keine Anweisung", this); + } + + public String toString() + // ino.end + // ino.method.toString.25738.body + { + //return receiver/*.toString()*/ + " " + usedid.toString(); + return type + " (" + "this" +"(" + this.getArgumentList() + "))"; + } + + @Override + public JavaCodeResult printJavaCode(ResultSet resultSet) { + return new JavaCodeResult("this"); + } + + @Override + public Menge getChildren() { + Menge ret = new Menge(); + return ret; + } + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + InstructionList il = new InstructionList(); + il.append(InstructionFactory.createLoad( org.apache.bcel.generic.Type.OBJECT, 0)); + return il; + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java b/src/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java index a398cfb0d..c506386ea 100644 --- a/src/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java @@ -4,6 +4,14 @@ package de.dhbwstuttgart.syntaxtree.statement; // ino.module.This.8654.import import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +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.assumptions.ConstructorAssumption; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; +import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException; @@ -11,12 +19,66 @@ public class ThisCall extends MethodCall { public ThisCall(Receiver receiver, ArgumentList arglist, int offset) { - super(null, null, null, 0); + super(offset); - } + } public ArgumentList arglist; + + public void set_ArgumentList(ArgumentList al) + { + this.arglist = al; + } + + public ArgumentList getArgumentList() + { + return this.arglist; + } + + @Override + public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) { + throw new TypeinferenceException("this(...)-Aufruf kann nicht als Ausdruck verwendet werden",this); + } + /** + * This kann auch als Konstruktoraufruf in einem Konstruktor-Block vorkommen. + */ + @Override + public ConstraintsSet TYPEStmt(TypeAssumptions assumptions, Class parentClass) { + ConstraintsSet ret = new ConstraintsSet(); + this.setType(new Void(this,this.getOffset())); + //Kontrollieren, dass sich this(...) in einem Konstruktor und dort als erstes Statement befindet: + SyntaxTreeNode p = this.getGTVDeclarationContext(); + if(p instanceof Constructor && + ((Constructor)p).get_Block().statements.firstElement().equals(this)){ + //Constraints generieren: + ret.add(super.TYPEStmt(assumptions, parentClass)); + return ret; + }else{ + //Ansonsten Fehler ausgeben: + throw new TypeinferenceException("this()-Aufruf hier nicht möglich", this); + } + } + + @Override + public ConstraintsSet overloading(TypeAssumptions assumptions){ + ConstraintsSet ret = new ConstraintsSet(); + ConstructorAssumption cAss = assumptions.getConstructorAssumption(this.get_Name(), this.getArgumentList().size()); + if(cAss == null)throw new TypeinferenceException("Kein Konstruktor mit passender Parameteranzahl vorhanden",this); + + ret.add(constraintsFromMethodAssumption(cAss, assumptions)); + return ret; + } + + public String toString() + { + return "(" + "this" +"(" + this.getArgumentList() + "))"; + } + + @Override + public JavaCodeResult printJavaCode(ResultSet resultSet) { + return new JavaCodeResult("this("+this.getArgumentList().printJavaCode(resultSet)+")"); + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/UnaryExpr.java b/src/de/dhbwstuttgart/syntaxtree/statement/UnaryExpr.java index 8bc996f06..da6ac5b36 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/UnaryExpr.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/UnaryExpr.java @@ -1,7 +1,19 @@ // ino.module.UnaryExpr.8655.package package de.dhbwstuttgart.syntaxtree.statement; // ino.end -// ino.module.UnaryExpr.8655.import +// ino.module.UnaryExpr.8655.import +import de.dhbwstuttgart.typeinference.Menge; + +import org.apache.bcel.generic.InstructionList; + +import de.dhbwstuttgart.bytecode.ClassGenerator; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.ConstraintsSet; +import de.dhbwstuttgart.typeinference.OderConstraint; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.UndConstraint; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; @@ -14,5 +26,43 @@ public abstract class UnaryExpr extends MethodCall super(offset,variableLength); } + @Override + public InstructionList genByteCode(ClassGenerator cg, TypeinferenceResultSet rs) { + /** + * TODO + * Je nach Typisierung wird eine andere Methode aufgerufen + * Alle Parameter müssen in ihren primitiven Datentyp umgewandelt werden + * Der Bytecodegenerator muss anhand der ermittelten Typen den korrekten Bytecode produzieren + * Es werden nie Typen generiert, die nicht Containertypen von primitiven Datentypen sind. + * Das lassen die generierten Constraints nicht zu. + */ + return super.genByteCode(cg, rs); + } + + /* + @Override + public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) { + if(this.getType() == null)this.setType(TypePlaceholder.fresh(this)); + ConstraintsSet ret = new ConstraintsSet(); + OderConstraint oderConstraint = new OderConstraint(); + ret.add(this.expr.TYPEExpr(assumptions)); + for(RefType t : getNumericTypes()){ + UndConstraint undConstraint = new UndConstraint(); + undConstraint.addConstraint(this.getType().TYPE(assumptions, this), t.TYPE(assumptions, this)); + undConstraint.addConstraint(this.expr.getType().TYPE(assumptions, this), t.TYPE(assumptions, this)); + + oderConstraint.addConstraint(undConstraint); + } + ret.add(oderConstraint); + return ret; + } + + @Override + public ConstraintsSet TYPEStmt(TypeAssumptions assumptions) { + ConstraintsSet ret = this.TYPEExpr(assumptions); + this.setType(new de.dhbwstuttgart.syntaxtree.type.Void(this, -1).TYPE(assumptions, this)); + return ret; + } + */ } diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/WhileStmt.java b/src/de/dhbwstuttgart/syntaxtree/statement/WhileStmt.java index 7e806e048..820786805 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/WhileStmt.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/WhileStmt.java @@ -2,11 +2,9 @@ package de.dhbwstuttgart.syntaxtree.statement; // ino.end // ino.module.WhileStmt.8659.import -import java.sql.ResultSet; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; -import java.util.List; import org.apache.bcel.generic.BranchInstruction; import org.apache.bcel.generic.ClassGen; @@ -14,12 +12,27 @@ import org.apache.bcel.generic.DUP; import org.apache.bcel.generic.GOTO; import org.apache.bcel.generic.IFEQ; 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.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.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.UndConstraint; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; +import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException; +import de.dhbwstuttgart.typeinference.unify.TypeUnify; @@ -34,7 +47,7 @@ public class WhileStmt extends Statement // ino.end // ino.method.WhileStmt.26330.body { - super(null,variableLength); + super(offset,variableLength); } // ino.end @@ -44,7 +57,10 @@ public class WhileStmt extends Statement // ino.attribute.loop_block.26336.declaration public Statement loop_block; // ino.end - + + // ino.attribute.parserlog.26339.declaration + protected static Logger parserlog = Logger.getLogger("parser"); + // ino.end // ino.method.set_Expr.26342.definition public void set_Expr(Expr exp) @@ -78,8 +94,64 @@ public class WhileStmt extends Statement { return "WHILE " + loop_block.toString(); } + // ino.end + + // ino.method.wandleRefTypeAttributes2GenericAttributes.26363.definition + public void wandleRefTypeAttributes2GenericAttributes(Menge paralist, Menge genericMethodParameters) + // ino.end + // ino.method.wandleRefTypeAttributes2GenericAttributes.26363.body + { + if(loop_block!=null){ + loop_block.wandleRefTypeAttributes2GenericAttributes(paralist,genericMethodParameters); + } + + } + // ino.end + + @Override + public ConstraintsSet TYPEStmt(TypeAssumptions assumptions) { + ConstraintsSet ret = new ConstraintsSet(); + ret.add(expr.TYPEExpr(assumptions)); + UndConstraint exprMustBeBool = ConstraintsSet.createSingleConstraint(expr.getType().TYPE(assumptions, this), new RefType("Boolean",this, 0).TYPE(assumptions, this)); // while(expr){}; expr <. boolean + ret.add(exprMustBeBool); + ret.add(this.loop_block.TYPEStmt(assumptions)); + this.setType(loop_block.getType()); + return ret; + } + public int getTypeLineNumber() { + throw new NotImplementedException(); + } + @Override + public JavaCodeResult printJavaCode(ResultSet resultSet) { + return new JavaCodeResult().attach("while(").attach(this.expr.printJavaCode(resultSet)).attach(")").attach(this.loop_block.printJavaCode(resultSet)); + } + @Override + public Menge getChildren() { + Menge ret = new Menge(); + ret.add(this.expr); + ret.add(this.loop_block); + return ret; + } + + @Override + public InstructionList genByteCode(ClassGenerator _cg, TypeinferenceResultSet rs) { + //TOD: while Statement + InstructionList il = expr.genByteCode(_cg, rs); + + BranchInstruction ifeq = new IFEQ(null); + il.append(ifeq); + + il.append(loop_block.genByteCode(_cg, rs)); + + il.append(new GOTO(il.getStart())); + + ifeq.setTarget(il.append(new DUP())); + + + return il; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/type/ExtendsWildcardType.java b/src/de/dhbwstuttgart/syntaxtree/type/ExtendsWildcardType.java index 6a41a72dc..e6ee10440 100755 --- a/src/de/dhbwstuttgart/syntaxtree/type/ExtendsWildcardType.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/ExtendsWildcardType.java @@ -1,5 +1,11 @@ package de.dhbwstuttgart.syntaxtree.type; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typecheck.JavaClassName; +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import de.dhbwstuttgart.typeinference.JavaCodeResult; +import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; /** @@ -10,7 +16,7 @@ package de.dhbwstuttgart.syntaxtree.type; * */ -public class ExtendsWildcardType extends WildcardType{ +public class ExtendsWildcardType extends WildcardType implements ITypeContainer, IMatchable{ /** * Author: Arne Lüdtke
@@ -19,7 +25,137 @@ public class ExtendsWildcardType extends WildcardType{ public ExtendsWildcardType (int offset, RefType extendsType) { super(extendsType, offset); + this.name = new JavaClassName(this.toString()); + } + + public ExtendsWildcardType(ObjectType extendsType) { + this(extendsType.getOffset(),extendsType); } + /** + * Author: Arne Lüdtke
+ * Gibt den Typen in der Wildcard zurück. + * Beispiel: ? extends Integer. + * Integer wird zurückgegeben. + */ + public ObjectType get_ExtendsType() + { + return this.innerType; + } + + /** + * Author: Arne Lüdtke
+ * Gibt String Entsprechung zurück. + */ + public String toString() + { + return "? extends " + innerType.toString(); + } + + /** + * Author: Arne Lüdtke
+ * Gibt einen Klon der Wildcard zurück. + * Der Innere Typ wird auch geklont + */ + public ExtendsWildcardType clone() + { + //Hier ist unklar, ob der Extends Type auch geklont werden muss. + return new ExtendsWildcardType(getOffset(),innerType.clone()); + } + + /** + * Author: Arne Lüdtke
+ * Vergleicht mit einem anderen Objekt. + * @param obj - Object to compare. + */ + public boolean equals(Object obj) + { + if(obj instanceof ExtendsWildcardType) + { + return super.equals(obj); + } + else + { + return false; + } + } + + /** + * Author: Arne Lüdtke
+ * Das gleiche wie get_ExtendsType(). + * Überschreibt die Methode der Superklasse. + */ + public Type GetWildcardType() + { + return this.get_ExtendsType(); + } + + /** + * Author: Arne Lüdtke
+ * Setzt den Typ in der Wildcard + * @param T - Type to be set + */ + public void SetWildcardType(ObjectType T) + { + //if(T instanceof RefType) + this.innerType = (RefType)T; + } + + /** + * Author: Arne Lüdtke
+ * Das gleiche wie get_ExtendsType(). + * Implementiert ITypeContainer + */ + public ObjectType getContainedType() + { + return this.get_ExtendsType(); + } + + /** + * Author: Arne Lüdtke
+ * Gibt den Typen zurück, der bei einem match im Unify verwendet werden soll. + * Wird über IMatchable implementiert. + */ + public ObjectType getMatchType() + { + return this.get_ExtendsType(); + } + + @Override + public JavaCodeResult printJavaCode(ResultSet resultSet) { + return new JavaCodeResult("? extends "+this.innerType.printJavaCode(resultSet)); + } + + @Override + public Menge getInvolvedTypePlaceholder() { + Menge ret = super.getInvolvedTypePlaceholder(); + ret.addAll(this.innerType.getInvolvedTypePlaceholder()); + return ret; + } + + @Override + public void parserPostProcessing(SyntaxTreeNode parent) { + super.parserPostProcessing(parent); + this.innerType.parserPostProcessing(this); + } + + @Override + public Type TYPE(TypeAssumptions ass, SyntaxTreeNode parent) { + //Folgender TypeCast ist sicher. Wird ein ObjectType in einen ConstraintType umgewandelt und wieder zurück, kann kein Fehler auftreten. + this.innerType = (ObjectType) this.innerType.TYPE(ass, parent); + return super.TYPE(ass, parent); + } + + /* + @Override + public org.apache.bcel.generic.Type getBytecodeType(ClassGenerator cg) { + return new de.dhbwstuttgart.bytecode.WildcardType(this.innerType.get_Name(), "+"); + } + */ + + @Override + public String get_Name() { + return "? extends "+this.innerType.get_Name(); + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/type/FunN.java b/src/de/dhbwstuttgart/syntaxtree/type/FunN.java index 3005e89ff..897fe55c3 100755 --- a/src/de/dhbwstuttgart/syntaxtree/type/FunN.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/FunN.java @@ -4,7 +4,11 @@ package de.dhbwstuttgart.syntaxtree.type; import java.util.ArrayList; import java.util.List; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.bytecode.ClassGenerator; import de.dhbwstuttgart.typecheck.JavaClassName; +import de.dhbwstuttgart.syntaxtree.factory.NameGenerator; +import de.dhbwstuttgart.typeinference.exceptions.DebugException; /** * @see Spezifikation "Complete Typeinference in Java 8" von Martin Plümicke @@ -29,7 +33,11 @@ public class FunN extends RefType { * @return */ public FunN(RefType R, List T) { - super(null,0); + super("",0); + if(T==null || R == null)throw new NullPointerException(); + setT(T); + setR(R); + this.name = new JavaClassName("Fun"+T.size());//getName(); } /** @@ -42,5 +50,70 @@ public class FunN extends RefType { this.name = new JavaClassName("Fun"+list.size());//getName(); } */ + + /** + * Erstellt eine FunN: + * FunN + * R und T1 - TparameterCount werden mit GenericTypeVars besetzt. + * @param parameterCount + */ + public FunN(int parameterCount) { + super("",0); + if(parameterCount<0)throw new RuntimeException("Anzahl der Parameter muss >0 sein"); + List t = new ArrayList<>(); + for(int i=0;i t = new ArrayList<>(); + if(R!=null)t.add(R); + if(T!=null)t.addAll(T); + for(RefType type : t){ + if(type instanceof WildcardType){ + throw new DebugException("Der FunN-Typ darf keine Wildcards in den Parameter enthalten"); + } + } + this.parameter = t; + } + + protected void setT(List list){ + this.T = list; + calculateNewParalist(); + } + protected void setR(RefType R){ + this.R = R; + calculateNewParalist(); + } + + public String getBytecodeInvokeDynamicSignature(ClassGenerator cg, TypeinferenceResultSet rs) { + String ret = "("; + for(RefType t : T){ + ret+=t.getBytecodeType(cg, rs).getSignature(); + } + ret +=")"; + ret+= R.getBytecodeType(cg, rs).getSignature(); + return ret; + } + + public String getBytecodeInvokeDynamicSignatureUpperBound(ClassGenerator cg) { + String ret = "("; + for(RefType t : T){ + ret+=cg.getInstructionFactory().createObjectType().getSignature(); + } + ret +=")"; + ret += cg.getInstructionFactory().createObjectType().getSignature(); + return ret; + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/type/FunVoidN.java b/src/de/dhbwstuttgart/syntaxtree/type/FunVoidN.java index 1e767b986..edbb05cdd 100644 --- a/src/de/dhbwstuttgart/syntaxtree/type/FunVoidN.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/FunVoidN.java @@ -27,9 +27,20 @@ public class FunVoidN extends FunN { */ public FunVoidN(List T) { super(null,T); + this.setR(new Void(this, -1)); + this.name = new JavaClassName("FunVoid"+T.size()); } - + /** + * Erstellt eine FunVoidN: + * FunN + * T1 - TparameterCount werden mit TypePlaceholdern besetzt. + * @param parameterCount + */ + public FunVoidN(int parameterCount) { + super(parameterCount); + this.name = new JavaClassName("FunVoid"+T.size()); + } /** * Muss nach jeder Änderung von T oder R aufgerufen werden. diff --git a/src/de/dhbwstuttgart/syntaxtree/type/RefType.java b/src/de/dhbwstuttgart/syntaxtree/type/RefType.java index a16a18026..c2d1fcbd0 100755 --- a/src/de/dhbwstuttgart/syntaxtree/type/RefType.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/RefType.java @@ -3,10 +3,17 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.bytecode.ClassGenerator; import de.dhbwstuttgart.typecheck.JavaClassName; import de.dhbwstuttgart.syntaxtree.Class; import de.dhbwstuttgart.syntaxtree.SourceFile; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.typeinference.JavaCodeResult; +import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.TypeinferenceResults; public class RefType extends SyntaxTreeNode @@ -30,6 +37,7 @@ public class RefType extends SyntaxTreeNode public RefType(JavaClassName fullyQualifiedName, int offset) { + super(offset); this.name = (fullyQualifiedName); } @@ -59,6 +67,7 @@ public class RefType extends SyntaxTreeNode /** * Author: Jrg Buerle
+ * @param Object * @return */ public boolean equals(Object obj) @@ -95,5 +104,151 @@ public class RefType extends SyntaxTreeNode } } + public RefType clone() + { + if(this.getParaList() != null ) + { + List para = this.getParaList(); + List clonepara = new ArrayList<>(); + for(int i = 0; i< para.size(); i++) + { + clonepara.add(((RefType)para.get(i)).clone()); + } + RefType newRefType=new RefType(this.getName(), clonepara, getOffset()); + newRefType.IsArray = this.IsArray; + return newRefType; + } + else { + RefType newRefType = new RefType(this.getName(),getOffset()); + newRefType.IsArray = this.IsArray; + return newRefType; + } + } + + public String toString() + { + String primitiveFlagMarker=primitiveFlag?"*":""; + if(parameter==null) + { + return name+primitiveFlagMarker; + } + else + { + String para = new String(); + Iterator e=parameter.iterator(); + while(e.hasNext()) + { + RefType ty = e.next(); + String t = ty.toString(); + if(para.length() > 0) + para = para +", "+ t; + else para = " " + t; + } + String ret = name.toString(); + if(parameter.size()>0)ret += "<"+para + " >"; + return ret + primitiveFlagMarker;//name + "<"+para + " >" +primitiveFlagMarker; + } + } + + @Override + public JavaCodeResult printJavaCode(ResultSet resultSet) { + JavaCodeResult ret = new JavaCodeResult(this.name.toString()); + if(this.getParaList()!=null && this.getParaList().size()>0){ + ret .attach( "<" ); + Iterator it = this.getParaList().iterator(); + while(it.hasNext()){ + RefType t = it.next(); + ret .attach( t.printJavaCode(resultSet)); + if(it.hasNext())ret.attach(", "); + } + //ret = ret.substring(0,ret.length()-2); + ret .attach(">"); + } + return ret; + } + + public List getUnresolvedTPH(ResultSet resultSet) { + List ret = new ArrayList<>(); //super.getUnresolvedTPH(resultSet); + ret.addAll(this.printJavaCode(resultSet).getUnresolvedTPH()); + return ret; + } + + public List getInvolvedTypePlaceholder() { + List ret = new ArrayList<>(); //super.getInvolvedTypePlaceholder(); + if(this.parameter == null)return ret; + for(RefType param : this.parameter){ + ret.addAll(param.getInvolvedTypePlaceholder()); + } + return ret; + } + + @Override + public List getChildren() { + List ret = new ArrayList<>(); //super.getChildren(); + ret.addAll(this.getParaList()); + return ret; + } + + public org.apache.bcel.generic.Type getBytecodeType(ClassGenerator cg, TypeinferenceResultSet rs) { + org.apache.bcel.generic.ObjectType ret = new org.apache.bcel.generic.ObjectType(getCombinedType(cg, rs)); + if(this.IsArray){ + //Hier wird einfachhalber von einer Dimension ausgegangen. Arrays sind im Bytecode nur für main-Methode relevant + return new org.apache.bcel.generic.ArrayType(ret, 1); + }else{ + return ret; + } + } + + public String getBytecodeSignature(ClassGenerator cg, TypeinferenceResultSet rs) { + String combinedType = getCombinedType(cg, rs); + /* + + */ + String ret = new org.apache.bcel.generic.ObjectType(combinedType).getSignature(); + return ret; + } + + public String getCombinedType(ClassGenerator cg, TypeinferenceResultSet rs){ + //Bsp.: Ljava/util/Vector; + StringBuilder sb = new StringBuilder(); + String ret; + List newParams = new ArrayList<>(); + if(parameter != null && parameter.size() > 0){ + sb.append(getName().toString().replace(".", "%")); + sb.append("%%"); + for(RefType type: parameter){ + RefType newParameter; + if(type instanceof RefType){ + sb.append(((RefType) type).getCombinedType(cg, rs).replace(".", "%")); + newParameter = type; + }else if(type instanceof TypePlaceholder){ + //TODO: Die Methode sollte keinen String, sondern einen BytecodeType zurückgeben. + //Auf sämtlichen RefTypes und TPHs muss eine Konvertierungsmethode aufgerufen werden, diese + // kann dann TPH dem entsprechenden Typ aus dem TypeinferenceResult zuweisen + newParameter = rs.getTypeOfPlaceholder((TypePlaceholder)type); + sb.append(((TypePlaceholder) type).getBytecodeType(cg, rs).toString().replace(".", "%")); + }else if(type instanceof WildcardType){ + //TODO: unresolved! + return this.getName().toString(); + }else{ + newParameter = type; + sb.append(type.getBytecodeType(cg, rs).toString().replace(".", "%")); + } + newParams.add(newParameter); + sb.append("%"); + } + ret = sb.toString(); + }else{ + ret = sb.append(this.getName().toString()).toString(); + } + if(!ret.equals(getName().toString())){ + //getSuperWildcardTypes(); + RefType superClass = new RefType(this.getName(),newParams,this.getOffset()); + Class generatedClass = ASTFactory.createInterface(ret, superClass, null, null, new SourceFile()); + + cg.addExtraClass(generatedClass.genByteCode(new TypeinferenceResults()).getByteCode()); + } + return ret; + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/type/SuperWildcardType.java b/src/de/dhbwstuttgart/syntaxtree/type/SuperWildcardType.java index 20efd8e78..31bf03def 100755 --- a/src/de/dhbwstuttgart/syntaxtree/type/SuperWildcardType.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/SuperWildcardType.java @@ -1,5 +1,12 @@ package de.dhbwstuttgart.syntaxtree.type; +import de.dhbwstuttgart.bytecode.ClassGenerator; +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import de.dhbwstuttgart.typeinference.JavaCodeResult; +import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; + +import java.util.List; /** * Stellt eine Wildcard mit unterer Grenze dar. @@ -12,8 +19,7 @@ package de.dhbwstuttgart.syntaxtree.type; public class SuperWildcardType extends WildcardType{ public SuperWildcardType(RefType innerType){ - super(null, 0); - + this(innerType.getOffset(), innerType); } /** @@ -35,5 +41,105 @@ public class SuperWildcardType extends WildcardType{ { return this.innerType; } + + /** + * Author: Arne Lüdtke
+ * Gibt String Entsprechung zurück. + */ + public String toString() + { + return "? super " + innerType.toString(); + } + + /** + * Author: Arne Lüdtke
+ * Gibt einen Klon der Wildcard zurück. + * Der Innere Typ wird auch geklont + */ + public SuperWildcardType clone() + { + return new SuperWildcardType(getOffset(), innerType.clone()); + } + + /** + * Author: Arne Lüdtke
+ * Das gleiche wie get_innerType(). + * Überschreibt die Methode der Superklasse + */ + public RefType GetWildcardType() + { + return this.get_SuperType(); + } + + /** + * Author: Arne Lüdtke
+ * Setzt den Typ in der Wildcard + * @param T - Type to be set + */ + public void SetWildcardType(RefType T) + { + //if(T instanceof RefType) + this.innerType = (RefType)T; + } + + /** + * Author: Arne Lüdtke
+ * Das gleiche wie get_innerType(). + * Implementiert ITypeContainer + */ + public RefType getContainedType() + { + return this.get_SuperType(); + } + + /** + * Author: Arne Lüdtke
+ * Gibt den Typen zurück, der bei einem match im Unify verwendet werden soll. + * Wird über IMatchable implementiert. + */ + public RefType getMatchType() + { + return this.get_SuperType(); + } + + @Override + public JavaCodeResult printJavaCode(ResultSet result){ + return new JavaCodeResult("? super " + this.innerType.printJavaCode(result)); + } + + /** + * Author: Arne Lüdtke
+ * Vergleicht mit einem anderen Objekt. + * @param obj - Object to compare. + */ + public boolean equals(Object obj) + { + if(obj instanceof SuperWildcardType) + { + return super.equals(obj); + } + else + { + return false; + } + } + + @Override + public List getInvolvedTypePlaceholder() { + List ret = super.getInvolvedTypePlaceholder(); + ret.addAll(this.innerType.getInvolvedTypePlaceholder()); + return ret; + } + + @Override + public void parserPostProcessing(SyntaxTreeNode parent) { + super.parserPostProcessing(parent); + this.innerType.parserPostProcessing(this); + } + + @Override + public String getBytecodeSignature(ClassGenerator cg, TypeinferenceResultSet rs) { + return "-" + this.innerType.getBytecodeSignature(cg, rs); + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/type/TypePlaceholder.java b/src/de/dhbwstuttgart/syntaxtree/type/TypePlaceholder.java index 2b94095a8..3269b1e5e 100755 --- a/src/de/dhbwstuttgart/syntaxtree/type/TypePlaceholder.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/TypePlaceholder.java @@ -1,7 +1,20 @@ package de.dhbwstuttgart.syntaxtree.type; import java.util.Hashtable; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.logger.*; +import de.dhbwstuttgart.bytecode.ClassGenerator; +import de.dhbwstuttgart.bytecode.DHBWInstructionFactory; +import de.dhbwstuttgart.bytecode.TypePlaceholderType; +import de.dhbwstuttgart.typecheck.JavaClassName; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import de.dhbwstuttgart.syntaxtree.factory.NameGenerator; +import de.dhbwstuttgart.typeinference.JavaCodeResult; +import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.TypeInsertable; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint; /** * Repr�sentiert einen Typparameter f�r einen vom Programmierer nicht angegeben @@ -13,11 +26,16 @@ import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; */ public class TypePlaceholder extends RefType { + private static final Logger log = Logger.getLogger(TypePlaceholder.class.getName()); private static Hashtable m_TypePlaceholdersRegistry = new Hashtable(); private SyntaxTreeNode parent; + @Override + public Type TYPE(TypeAssumptions ass, SyntaxTreeNode parent) { + return this; + } /** * Privater Konstruktor - Eine TypePlaceholder-Variable wird �ber die @@ -27,7 +45,10 @@ public class TypePlaceholder extends RefType */ private TypePlaceholder(String typeName, SyntaxTreeNode parent) { - super(null, -1); + super(new JavaClassName(typeName), -1); + if(typeName == null)throw new NullPointerException(); + this.name = new JavaClassName(typeName); + if(parent != null)log.debug("Erstelle TPH "+typeName+" für SyntaxTreeNode: "+parent, Section.TYPEINFERENCE); } /** @@ -50,7 +71,13 @@ public class TypePlaceholder extends RefType */ public static TypePlaceholder fresh(String name, SyntaxTreeNode parent) { - return null; + TypePlaceholder typeVar = new TypePlaceholder(name, parent); + TypePlaceholder oldTPH = m_TypePlaceholdersRegistry.put(typeVar.getName().toString(), typeVar); + if(oldTPH != null){ + oldTPH.name = new JavaClassName(NameGenerator.makeNewName()); + m_TypePlaceholdersRegistry.put(oldTPH.getName().toString(), oldTPH); + } + return typeVar; } @@ -62,8 +89,9 @@ public class TypePlaceholder extends RefType * @return */ public static TypePlaceholder fresh(SyntaxTreeNode parent){ - - return null; + TypePlaceholder ret= new TypePlaceholder(NameGenerator.makeNewName(), parent); + m_TypePlaceholdersRegistry.put(ret.getName().toString(), ret); + return ret; } @@ -138,11 +166,126 @@ public class TypePlaceholder extends RefType //backdoorvars werden registiert, weil am Ende beim execute //auf den CSubstitution nicht registrierte Variablen zu //Exceptions fuehrt - TypePlaceholder typeVar = new TypePlaceholder(null, null); + TypePlaceholder typeVar = new TypePlaceholder(NameGenerator.makeNewName(), null); m_TypePlaceholdersRegistry.put(typeVar.getName().toString(), typeVar); return typeVar; //return new TypePlaceholder(makeNewName()); } + /** + * Backdoor-Hilfsfunktion, die f�r makeFC() und unify() + * ben�tigt wird, zum Erzeugen eines TypePlaceholders, der nicht in + * der zentralen Registry eingetragen wird. Die erzeugte Variablen ist somit v�llig + * losgel�st vom abstrakten Syntaxbaum.
Author: J�rg B�uerle + * @param name + * @return + */ + public static TypePlaceholder backdoorCreate(String name) + { + + //PL 05-08-22 SEHR GEFAEHRLICH + //backdoorvars werden registiert, weil am Ende beim execute + //auf den CSubstitution nicht registrierte Variablen zu + //Exceptions fuehrt + TypePlaceholder typeVar = new TypePlaceholder(name, null); + m_TypePlaceholdersRegistry.put(typeVar.getName().toString(), typeVar); + return typeVar; + + //return new TypePlaceholder(name); + } + + /////////////////////////////////////////////////////////////////// + // Ende Spezialfunktionen + /////////////////////////////////////////////////////////////////// + + private JavaCodeResult printJavaCodePr(ResultSet resultSet) { + RefType equalType = resultSet.getTypeEqualTo(this); + if(equalType == null || equalType.equals(this)){ + //Für den Fall das der TPH nicht aufgelöst werden konnte. + JavaCodeResult ret = new JavaCodeResult(this.getName().toString()); + //Jetzt muss eine nicht aufgelöste generische Variable dem JavaCodeResult-Set angefügt werden + ret.addUnresolvedTPH(this); + return ret; + } + + return equalType.printJavaCode(resultSet); + } + + public JavaCodeResult printJavaCode(ResultSet resultSet, boolean resolveTPHs){ + if(resolveTPHs)return printJavaCodePr(resultSet); + return new JavaCodeResult(this.get_Name()); + } + /** + * Berechnet die InsertPoints dieses TypePlaceholders. + * Alle an diesem TypePlaceholder registrierten ITypeReplacementListener werden darauf kontrolliert, + * ob sie von TypeInsertable erben. + * Diese ergeben zusammen mit den Informationen aus dem übergebenen ResultSet einen TypeInsertPoint. + * Mehrere TypeInsertPoint's ergeben ein TypeInsertSet. + * @param result Das ResultSet das den einzusetzenden Typ für diesen TPH enthält. + * @return + * @see TypeInsertPoint + */ + public Menge getTypeInsertPoints(ResultSet result) { + Menge ret = new Menge(); + if(this.parent instanceof TypeInsertable){ + TypeInsertPoint toAdd = ((TypeInsertable) parent).createTypeInsertPoint(this, result); + if(toAdd != null)ret.add(toAdd); + //ret.add(new TypeInsertPoint(this, (TypeInsertable)ti, result.getTypeEqualTo(this), result)); + } + return ret; + } + + @Override + public Menge getUnresolvedTPH(ResultSet resultSet) { + Menge ret = super.getUnresolvedTPH(resultSet); + Type t = resultSet.getTypeEqualTo(this); + if(t instanceof TypePlaceholder){ + ret.add((TypePlaceholder)t); + } + return ret; + } + + @Override + public org.apache.bcel.generic.Type getBytecodeType(ClassGenerator cg, TypeinferenceResultSet rs) { + Type resolvedType = rs.getTypeOfPlaceholder(this); + if(resolvedType instanceof TypePlaceholder){ + return DHBWInstructionFactory.createObjectType(); + } + return resolvedType.getBytecodeType(cg, rs); + } + + @Override + public String getBytecodeSignature(ClassGenerator cg, TypeinferenceResultSet rs) { + if(rs == null){ + System.out.println(""); + return null; + } + Type resolvedType = rs.getTypeOfPlaceholder(this); + if(resolvedType instanceof TypePlaceholder){ + cg.addUsedTPH((TypePlaceholder)resolvedType); + return new TypePlaceholderType((TypePlaceholder)resolvedType).getSignature(); + } + return resolvedType.getBytecodeSignature(cg, rs); + } + + @Override + public String getClassSignature(ClassGenerator cg, TypeinferenceResultSet rs) { + //Die Signaturen in der Klasse bauen sich für Generische Variabeln (also TPHs) folgendermaßen auf: "GVAR:SuperClass" + String ret = this.get_Name();//this.getBytecodeSignature(cg); + //ret = ret.substring(1, ret.length()-1) + ":"; //";" mit ":" ersetzen + ret+=":"; + Menge possibleTPHs = cg.getUsedTPH(); + possibleTPHs.remove(this); + //TODO: hier komplett überarbeiten. Wann wird ein TPH eine generische Variable, das sollte geklärt werden. + org.apache.bcel.generic.Type nearestType = null;//cg.getNearestUsedType(this, possibleTPHs); + //if(nearestType instanceof TypePlaceholderType){ //Handelt es sich um einen weiteren TPH als nächsten Typ, so ist es ein allgemeiner Typ und wir nehmen Object als Superklasse + if(nearestType == null){ + ret += cg.getInstructionFactory().createObjectType().getSignature(); + }else{ + ret += nearestType.getSignature(); + } + return ret; + } + } diff --git a/src/de/dhbwstuttgart/syntaxtree/type/WildcardType.java b/src/de/dhbwstuttgart/syntaxtree/type/WildcardType.java index 3cb00c92a..ed1fede7f 100755 --- a/src/de/dhbwstuttgart/syntaxtree/type/WildcardType.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/WildcardType.java @@ -1,5 +1,15 @@ package de.dhbwstuttgart.syntaxtree.type; +import de.dhbwstuttgart.bytecode.ClassGenerator; +import de.dhbwstuttgart.typecheck.JavaClassName; +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +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; + /** * Stellt eine Wildcard in Java dar. * z.B. void Test(? var){..} @@ -18,6 +28,7 @@ public abstract class WildcardType extends RefType{ public WildcardType(RefType innerType, int offset) { super(innerType.getName(), offset); + if(innerType instanceof WildcardType)throw new TypeinferenceException("Ein Wildcardtype kann keinen Wildcardtype als innerType besitzen",this); this.innerType = innerType; } @@ -40,4 +51,43 @@ public abstract class WildcardType extends RefType{ return null; } + + @Override + public JavaCodeResult printJavaCode(ResultSet resultSet) { + throw new NotImplementedException(); + } + + @Override + public RefType TYPE(TypeAssumptions ass, SyntaxTreeNode parent) { + this.innerType = innerType.TYPE(ass, this); + return this; + } + + public boolean equals(Object obj) + { + if(obj instanceof WildcardType) + { + return ((WildcardType)obj).GetWildcardType().equals(this.GetWildcardType()); + } + else + { + return false; + } + } + + @Override + public org.apache.bcel.generic.Type getBytecodeType(ClassGenerator cg, TypeinferenceResultSet rs) { + return this.innerType.getBytecodeType(cg, rs); + } + + @Override + public String getBytecodeSignature(ClassGenerator cg, TypeinferenceResultSet rs) { + return this.innerType.getBytecodeSignature(cg, rs); + } + + @Override + public JavaClassName getName() { + return new JavaClassName(this.get_Name()); + } + } diff --git a/src/de/dhbwstuttgart/typeinference/ByteCodeResult.java b/src/de/dhbwstuttgart/typeinference/ByteCodeResult.java new file mode 100644 index 000000000..8398b1c18 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/ByteCodeResult.java @@ -0,0 +1,63 @@ +package de.dhbwstuttgart.typeinference; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.bcel.generic.ClassGen; + +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.bytecode.ClassGenerator; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +public class ByteCodeResult{ + + private ClassGenerator byteCode; + //TODO: unresolvedTPHs entfernen. BROKEN! + private Menge unresolvedTPHs = new Menge(); + + public ByteCodeResult(ClassGenerator byteCode){ + this.byteCode = byteCode; + } + + public ClassGenerator getByteCode(){ + return byteCode; + } + + + public void addUnresolvedTPH(TypePlaceholder typePlaceholder) { + unresolvedTPHs.add(typePlaceholder); + } + + /** + * Liefert alle TPHs, welche in diesem ByteCodeResult nicht zu einem Typ aufgelöst wurden. + * Diese TPHs stehen dadurch im ByteCode als Variablennamen ohne zugeordnetem Typ. + * @return + */ + public Menge getUnresolvedTPH(){ + return unresolvedTPHs; + } + + @Override + public String toString(){ + return getByteCode().toString(); + } + + @Override + public boolean equals(Object obj){ + if(!(obj instanceof ByteCodeResult))return false; + ByteCodeResult equals = (ByteCodeResult)obj; + if(!equals.getByteCode().equals(this.getByteCode()))return false; + if(!equals.getUnresolvedTPH().equals(this.getUnresolvedTPH()))return false; + return true; + } + + /** + * Schreibt den Bytecode in die übergebene .class Datei + * @throws IOException + */ + public void writeClassToFile(File output) throws IOException{ + this.getByteCode().getJavaClass().dump(output); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/ConstraintsSet.java b/src/de/dhbwstuttgart/typeinference/ConstraintsSet.java new file mode 100755 index 000000000..dd4a2ff1b --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/ConstraintsSet.java @@ -0,0 +1,99 @@ +package de.dhbwstuttgart.typeinference; + +import java.util.Iterator; +import java.util.Set; +import java.util.Vector; +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.logger.*; +import de.dhbwstuttgart.typeinference.unify.Unifikationsalgorithmus; + +public class ConstraintsSet extends UndMenge implements Iterable{ + private static final Logger log = Logger.getLogger(ConstraintsSet.class.getName()); + private Menge constraintsSet; + + public ConstraintsSet(){ + constraintsSet = new Menge(); + } + + public void add(ConstraintsSet CSet){ + for(OderConstraint element : CSet) + add(element); + } + public void add(OderConstraint constraint){ + constraintsSet.add(constraint); + } + + @Override + public String toString(){ + String ret =""; + for(OderConstraint constraint : this){ + ret += constraint.toString()+"\n"; + } + return ret; + } + + public Iterator iterator() { + return constraintsSet.iterator(); + } + + /* + public void filterWrongConstraints(Unifier unify) { + + // * Das ConstraintsSet enthält nur OderConstraints, welche UND-Verknüpft sind. + // * Hier werden Constraints in den OderConstraints kontrolliert: + + for(OderConstraint constraint : this){ + constraint.filterWrongConstraints(unify); + } + } + +*/ + /** + * Nimmt alle UndConstraints und filtert mithilfe dieser die falschen Constraints aus den OderConstraints + * @param unifier + + public void unifyUndConstraints(Unifier unifier) { + Vector uCons = this.filterUndConstraints(); + Vector alleUndConstraints = new Vector<>(); + for(UndConstraint undConstraint : uCons){ + alleUndConstraints.addAll(undConstraint.getConstraintPairs()); + } + this.filterWrongConstraints( + (pairs)->{ + Set undConstraintsUndPairs = new Menge<>(); + undConstraintsUndPairs.addAll(pairs); + undConstraintsUndPairs.addAll(alleUndConstraints); + log.debug("Versuche Pairs auszusondern:\n"+pairs, Section.TYPEINFERENCE); + log.debug("Unifiziere:\n"+undConstraintsUndPairs, Section.TYPEINFERENCE); + Set> unifyResult = unifier.apply(undConstraintsUndPairs); + return unifyResult; + }); + } + */ + + public void add(UndConstraint singleConstraint) { + OderConstraint toAdd = new OderConstraint(); + toAdd.addConstraint(singleConstraint); + constraintsSet.add(toAdd); + } + + @Override + public Menge> getSet() { + return this.getOderConstraints(); + } + + public Menge getOderConstraints() { + return this.constraintsSet; + } + + public static UndConstraint createSingleConstraint(Type t1, Type t2){ + UndConstraint ret = new UndConstraint(); + ret.addConstraint(t1, t2); + return ret; + } + + public static UndConstraint createSingleConstraint(Pair pair) { + return createSingleConstraint(pair.TA1, pair.TA2); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/DeepCloneable.java b/src/de/dhbwstuttgart/typeinference/DeepCloneable.java new file mode 100644 index 000000000..c20b6493a --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/DeepCloneable.java @@ -0,0 +1,18 @@ +package de.dhbwstuttgart.typeinference; + +public interface DeepCloneable{ + public A deepClone(); +} + +/* +public class CloneableMenge extends Menge{ + + public CloneableMenge deepClone(){ + CloneableMenge ret = new CloneableMenge<>(); + for(A i : this){ + ret.add(i.deepClone()); + } + return ret; + } +} +*/ \ No newline at end of file diff --git a/src/de/dhbwstuttgart/typeinference/EinzelElement.java b/src/de/dhbwstuttgart/typeinference/EinzelElement.java new file mode 100644 index 000000000..60ae48fbd --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/EinzelElement.java @@ -0,0 +1,39 @@ +package de.dhbwstuttgart.typeinference; + +import java.util.Set; + +import de.dhbwstuttgart.typeinference.exceptions.*; + +public class EinzelElement implements KomplexeMenge{ + private A item; + + public EinzelElement(A element){ + item = element; + } + + public Menge> getSet(){ + Menge> ret = new Menge<>(); + ret.add(this); + return ret; + } + + @Override + public Set> cartesianProduct() { + Set> ret = new Menge<>(); + Menge i = new Menge(); + i.add(item); + ret.add(i); + return ret; + //throw new NotImplementedException(); + } + + @Override + public String toString(){ + return item.toString(); + } + + public A getItem(){ + return item; + } + +} \ No newline at end of file diff --git a/src/de/dhbwstuttgart/typeinference/FunNInterface.java b/src/de/dhbwstuttgart/typeinference/FunNInterface.java new file mode 100644 index 000000000..a74baf8d3 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/FunNInterface.java @@ -0,0 +1,97 @@ +package de.dhbwstuttgart.typeinference; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import de.dhbwstuttgart.syntaxtree.Class; +import de.dhbwstuttgart.syntaxtree.modifier.Modifiers; +import de.dhbwstuttgart.syntaxtree.type.FunN; +import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.typeinference.assumptions.ClassAssumption; +import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; + +/** + * Stellt das Interface FunN dar. + * @author janulrich + * + */ +public class FunNInterface extends Class{ +//TODO: Diese Klasse sollte eigentlich von Interface erben + //TODO: getType muss einen Typ mit der ParameterListe zurückliefern. + + //private Menge gtvparalist; + + /** + * Ein FunN-Interface enthält nur eine Methode (namens apply). Ist also ein Funktionales Interface. + * @param N - Die Anzahl der Parameter der apply-Methode. Beispiel N = 1 ergibt R apply(T1 par1); + */ + public FunNInterface(int N) { + super("Fun"+N, null, new Modifiers(), FunNInterface.makeParaList(N)); + /* + GenericTypeVar gtv; + Menge paralist = new Menge<>(); + gtv = new GenericTypeVar("R",this, 0); + this.gtvparalist = new Menge(); + paralist.add(gtv); + this.gtvparalist.add(gtv); + //paralist.add(TypePlaceholder.fresh()); + for(int i = 1; i<=N;i++){ + gtv=new GenericTypeVar("T"+i,this, 0); + paralist.add(gtv); + this.gtvparalist.add(gtv); + //paralist.add(TypePlaceholder.fresh()); + } + this.set_ParaList(paralist); + */ + } + + private static Menge makeParaList(int n) { + Menge ret = new Menge<>(); + ret.add("R"); + for(int i = 1; i<=n;i++){ + ret.add("T"+i); + } + return ret; + } + + /** + * @return Im Falle von einem FunN-Interface ist dies die apply-Methode + */ + @Override + public TypeAssumptions getPublicFieldAssumptions() { + //return super.getPublicFieldAssumptions(); + TypeAssumptions ret = new TypeAssumptions(); + ret.addAssumption(new MethodAssumption(this.getApplyFunction(), this)); + ret.addClassAssumption(new ClassAssumption(this)); + for(GenericTypeVar gtv : this.getGenericParameter())ret.addGenericVarAssumption(gtv); + return ret; + } + + /** + * Erstellt die nach Definition des Typinferenzalgorithmus von Martin Plümicke, in jedem FunN-Interface enthaltene apply-Methode + * @return + */ + private FunNMethod getApplyFunction(){ + return new FunNMethod(this.get_ParaList()); + //return new FunNMethod(this.get_ParaList().size()-1); + } + + @Override + public RefType getType() { + List paraList = this.get_ParaList(); + Iterator paraIter = paraList.iterator(); + Type R = paraIter.next(); + List paraListNew = new ArrayList<>(); + while(paraIter.hasNext()){ + paraListNew.add(paraIter.next()); + } + return new FunN(R, paraListNew); + } + + + +} diff --git a/src/de/dhbwstuttgart/typeinference/FunNMethod.java b/src/de/dhbwstuttgart/typeinference/FunNMethod.java new file mode 100755 index 000000000..6ac8011eb --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/FunNMethod.java @@ -0,0 +1,67 @@ +package de.dhbwstuttgart.typeinference; + +import de.dhbwstuttgart.typeinference.Menge; + +import de.dhbwstuttgart.syntaxtree.FormalParameter; + +import java.util.List; + +import de.dhbwstuttgart.syntaxtree.Class; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.misc.DeclId; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint; + +public class FunNMethod extends Method{ + /** + * + * @param N - Anzahl der Parameter (Beispiel: Fun2) + */ + public FunNMethod(List paralist){ + super(0); //Hat keinen Offset, da nur theoretisch gedachte Methode + int N = paralist.size(); //In der paraliste ist der erste Parameter der Rückgabetyp + this.setType(paralist.get(0)); + this.set_DeclId(new DeclId("apply")); + ParameterList pl = new ParameterList(); + Menge fpList = new Menge(); + for(int i = 1;i fpList = new Menge(); + for(int i = 1;i<=N;i++){ //Alle verbleibenden Elemente in der übergebenen paralist durchgehen. + DeclId paramName = new DeclId("T"+i); + FormalParameter parameter = new FormalParameter(paramName); + parameter.setType(TypePlaceholder.fresh(parameter)); + //parameter.set_DeclId(paramName); + fpList.add(parameter); + } + pl.formalparameter = fpList; + this.parameterlist = pl; + this.parserPostProcessing(new Class("Fun"+N, 0)); + } + */ + @Override + public TypeInsertPoint createTypeInsertPoint(TypePlaceholder tph, + ResultSet resultSet) { + return null; + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/FunVoidNInterface.java b/src/de/dhbwstuttgart/typeinference/FunVoidNInterface.java new file mode 100644 index 000000000..6a8edd996 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/FunVoidNInterface.java @@ -0,0 +1,59 @@ +package de.dhbwstuttgart.typeinference; + +import de.dhbwstuttgart.syntaxtree.Class; +import de.dhbwstuttgart.syntaxtree.modifier.Modifiers; +import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.typeinference.assumptions.ClassAssumption; +import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; + +/** + * Stellt das Interface FunVoidN dar. + * @author janulrich + * + */ +public class FunVoidNInterface extends Class{ +//TODO: Diese Klasse sollte eigentlich von Interface erben + //TODO: getType muss einen Typ mit der ParameterListe zurückliefern. + + //private Menge gtvparalist; + + /** + * Ein FunN-Interface enthält nur eine Methode (namens apply). Ist also ein Funktionales Interface. + * @param N - Die Anzahl der Parameter der apply-Methode. Beispiel N = 1 ergibt R apply(T1 par1); + */ + public FunVoidNInterface(int N) { + super("FunVoid"+N, null, new Modifiers(), FunVoidNInterface.makeParaList(N)); + } + + private static Menge makeParaList(int n) { + Menge ret = new Menge<>(); + for(int i = 1; i<=n;i++){ + ret.add("T"+i); + } + return ret; + } + + /** + * @return Im Falle von einem FunN-Interface ist dies die apply-Methode + */ + @Override + public TypeAssumptions getPublicFieldAssumptions() { + //return super.getPublicFieldAssumptions(); + TypeAssumptions ret = new TypeAssumptions(); + ret.addAssumption(new MethodAssumption(this.getApplyFunction(), this)); + ret.addClassAssumption(new ClassAssumption(this)); + for(GenericTypeVar gtv : this.getGenericParameter())ret.addGenericVarAssumption(gtv); + return ret; + } + + /** + * Erstellt die nach Definition des Typinferenzalgorithmus von Martin Plümicke, in jedem FunN-Interface enthaltene apply-Methode + * @return + */ + private FunVoidNMethod getApplyFunction(){ + return new FunVoidNMethod(this.get_ParaList(),this); + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/FunVoidNMethod.java b/src/de/dhbwstuttgart/typeinference/FunVoidNMethod.java new file mode 100644 index 000000000..41bf22426 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/FunVoidNMethod.java @@ -0,0 +1,64 @@ +package de.dhbwstuttgart.typeinference; + +import de.dhbwstuttgart.typeinference.Menge; +import java.util.List; +import de.dhbwstuttgart.syntaxtree.type.Void; + +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.Class; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.misc.DeclId; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint; + +public class FunVoidNMethod extends Method{ + /** + * + * @param N - Anzahl der Parameter (Beispiel: Fun2) + */ + public FunVoidNMethod(List paralist, Class parent){ + super(0); //Hat keinen Offset, da nur theoretisch gedachte Methode + int N = paralist.size(); + this.setType(new Void(this, -1)); + this.set_DeclId(new DeclId("apply")); + ParameterList pl = new ParameterList(); + Menge fpList = new Menge(); + for(int i = 0;i fpList = new Menge(); + for(int i = 1;i<=N;i++){ //Alle verbleibenden Elemente in der übergebenen paralist durchgehen. + DeclId paramName = new DeclId("T"+i); + FormalParameter parameter = new FormalParameter(paramName); + parameter.setType(TypePlaceholder.fresh(parameter)); + //parameter.set_DeclId(paramName); + fpList.add(parameter); + } + pl.formalparameter = fpList; + this.parameterlist = pl; + this.parserPostProcessing(new Class("Fun"+N, 0)); + } + */ + @Override + public TypeInsertPoint createTypeInsertPoint(TypePlaceholder tph, + ResultSet resultSet) { + return null; + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/GenericTypeInsertable.java b/src/de/dhbwstuttgart/typeinference/GenericTypeInsertable.java new file mode 100644 index 000000000..b6694ce1b --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/GenericTypeInsertable.java @@ -0,0 +1,12 @@ +package de.dhbwstuttgart.typeinference; + +/** + * Wird von Knoten im Syntaxbaum implementiert, welche ein Einsetzen von generischen Variablendeklarationen erlauben. + */ +public interface GenericTypeInsertable { + + public String getGenericVarDeclarationString(String genericVarDeclaration); + public int getGenericVarDeclarationOffset(); + + +} diff --git a/src/de/dhbwstuttgart/typeinference/JavaCodeResult.java b/src/de/dhbwstuttgart/typeinference/JavaCodeResult.java new file mode 100755 index 000000000..cbd881bfe --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/JavaCodeResult.java @@ -0,0 +1,64 @@ +package de.dhbwstuttgart.typeinference; + +import de.dhbwstuttgart.typeinference.Menge; + +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +public class JavaCodeResult{ + + private String javaCode = ""; + //TODO: unresolvedTPHs entfernen. BROKEN! + private Menge unresolvedTPHs = new Menge(); + + public JavaCodeResult(){ + + } + + public JavaCodeResult(String javaCode){ + this.javaCode += javaCode; + } + + public String getJavaCode(){ + return javaCode; + } + + public JavaCodeResult attach(JavaCodeResult javaCodeResult){ + this.javaCode += javaCodeResult.getJavaCode(); + //Alle TPH anfügen: + for(TypePlaceholder tph : javaCodeResult.getUnresolvedTPH())this.addUnresolvedTPH(tph); + return this; + } + + public JavaCodeResult attach(String javaCode){ + this.javaCode += javaCode; + return this; + } + + public void addUnresolvedTPH(TypePlaceholder typePlaceholder) { + unresolvedTPHs.add(typePlaceholder); + } + + /** + * Liefert alle TPHs, welche in diesem JavaCodeResult nicht zu einem Typ aufgelöst wurden. + * Diese TPHs stehen dadurch im JavaCode als Variablennamen ohne zugeordnetem Typ. + * @return + */ + public Menge getUnresolvedTPH(){ + return unresolvedTPHs; + } + + @Override + public String toString(){ + return getJavaCode(); + } + + @Override + public boolean equals(Object obj){ + if(!(obj instanceof JavaCodeResult))return false; + JavaCodeResult equals = (JavaCodeResult)obj; + if(!equals.getJavaCode().equals(this.getJavaCode()))return false; + if(!equals.getUnresolvedTPH().equals(this.getUnresolvedTPH()))return false; + return true; + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/KarthesischesProdukt.java b/src/de/dhbwstuttgart/typeinference/KarthesischesProdukt.java new file mode 100755 index 000000000..6272b7bed --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/KarthesischesProdukt.java @@ -0,0 +1,75 @@ +package de.dhbwstuttgart.typeinference; + + +public abstract class KarthesischesProdukt { + + public static Menge> berechneKarthesischesProdukt(Menge> m1){ + if(m1.size()==0)return m1; + if(m1.size()==1){ + Menge> ret = new Menge>(); + for(M o : m1.firstElement()){ + Menge v = new Menge(); + v.add(o); + ret.add(v); + } + return ret; + //return m1;//throw new TypinferenzException("m1 hat zu wenige Objekte für ein Karthesisches Produkt. Es müssen mindestens 2 sein."); + } + return berechneKarthesischesProdukt(m1, null); + } + + private static Menge> berechneKarthesischesProdukt(Menge> m1, Menge> result){ + if(m1.size()==0)return result; + if(result == null){ + result = new Menge>(); + result.add(new Menge()); + } + Menge o1 = m1.remove(0); + Menge> newResult = new Menge>(); + for(Menge o2 : result){ + Menge> xProd = karthesischesProdukt(o2,o1); + //System.out.println("karthesischesProdukt( "+o2+" , "+o1+" ) \n = "+xProd); + newResult.addAll(xProd); + //result.addAll(karthesischesProdukt(o1, o2)); + } + return berechneKarthesischesProdukt(m1, newResult); + /* + Menge> ret = null; + Iterator> it = m1.iterator(); + while(it.hasNext()){ + + } + if(m1.size()>1){ + ret = new Menge>(); + }else if(m1.size() == 1){ + ret = new Menge>(); + ret.addAll( karthesischesProdukt2(m1.firstElement(), m2) ); + }else{ + throw new TypinferenzException("Der übergebene Vektor m1 ist leer."); + } + + return ret;*/ + } + + private static Menge> karthesischesProdukt(Menge m1, Menge m2){ + Menge> ret = new Menge>(); + /* Wird dieser Teil nicht auskommentiert, so kann auch ein Karthesisches Produkt über eine Menge mit leeren Teilmengen erstellt werden + if(m2.size() == 0){//Sonderfall, m2 ist leer: + ret.add(m1); + return ret; //Die restliche Berechnungen können übersprungen werden. + } + */ + //for(M o1 : m1){ + for(M o2 : m2){ + Menge v1 = new Menge(); + //for(M o1 : m1)v1.add(o1); + v1.addAll(m1); + v1.add(o2); + //System.out.println("g: "+v1); + ret.add(v1); + } + //} + return ret; + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/KomplexeMenge.java b/src/de/dhbwstuttgart/typeinference/KomplexeMenge.java new file mode 100644 index 000000000..f72d991de --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/KomplexeMenge.java @@ -0,0 +1,8 @@ +package de.dhbwstuttgart.typeinference; + +import java.util.Set; + +public interface KomplexeMenge{ + Set> getSet(); + Set> cartesianProduct(); +} \ No newline at end of file diff --git a/src/de/dhbwstuttgart/typeinference/Menge.java b/src/de/dhbwstuttgart/typeinference/Menge.java new file mode 100644 index 000000000..6834552f4 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/Menge.java @@ -0,0 +1,29 @@ +package de.dhbwstuttgart.typeinference; + +import java.util.Set; +import java.util.Vector; + +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + + +public class Menge extends Vector implements Set{ + + public interface Equal{ + boolean equal(A a, A b); + } + + public boolean contains(A item, Equal eq) { + for(A test : this){ + if(eq.equal(item, test))return true; + } + return false; + } + + public A[] toArray(){ + A[] ret = (A[]) new Object[this.size()]; + for(int i = 0; i{ + private Set oderConstraintPairs; + + private final static Logger logger = Logger.getLogger(OderConstraint.class.getName()); + + /** + * Erstellt ein neues Oder Constraint und f�gt bereits ein Constraint hinzu. + * @param p1 + * @param p2 + + public OderConstraint(Pair p1, Pair p2){ + if(p1 == null || p2 == null)throw new NullPointerException(); + Pair constraintPair = new Pair(p1,p2); + oderConstraintPairs = new Menge(); + this.addConstraint(constraintPair); + } + */ + + public OderConstraint(){ + oderConstraintPairs = new Menge(); + } + + + /** + * Liefert alle in diesem OderConstraint enthaltene Constraints. Dabei gehen die Verkn�pfungen (Oder/Und) verloren. + * @return + */ + public Menge getConstraintPairs(){ + Menge ret = new Menge(); + for(UndConstraint oC : this.oderConstraintPairs){ + ret.addAll(oC.getConstraintPairs()); + } + return ret; + } + + /** + * F�gt ein Pair(p1, p2) dem Constraint hinzu + * @param p1 + * @param p2 + */ + public void addConstraint(Type p1, Type p2){ + addConstraint(new Pair(p1,p2)); + } + + /** + * Falls die Type des toAdd-Pairs nicht vom Typ RefType bzw. TypePlaceholder sind, so werden sie in einen RefType umgewandelt. + * @param toAdd + */ + public void addConstraint(Pair toAdd){ + UndConstraint uCons = new UndConstraint(); + uCons.addConstraint(toAdd); + oderConstraintPairs.add(uCons); + } + + @Override + public String toString(){ + String ret = "["; + for(UndConstraint p : this.getUndConstraints()){ + ret += p.toString()+ "| "; + } + return ret+"]"; + } + + public Set getUndConstraints() { + return this.oderConstraintPairs; + /* + Vector ret = new Vector(); + for(Pair p : this.getConstraintPairs()){ + ret.add(new UndConstraint(p.TA1,p.TA2)); + } + return ret; + */ + } + + public void addConstraint(UndConstraint constraint) { + oderConstraintPairs.add(constraint); + } + + /** + * Filtert die Constraints in diesem ODER-Verknüpften Constraint aus, + * welche keinen Sinn ergeben, also beim unifizieren scheitern. + * @param unifier - Wird für die Unifizierung benutzt + + void filterWrongConstraints(Unifier unifier) { + Set filteredConstraints = new Menge<>(); + for(UndConstraint cons : this.getUndConstraints()){ + Set> unifierResult = unifier.apply(cons.getConstraintPairs()); + if(!unifierResult.isEmpty()){ + filteredConstraints.add(cons); + }else{ + logger.debug("Ausgesondertes Constraint: "+cons, Section.TYPEINFERENCE); + } + } + this.oderConstraintPairs = filteredConstraints; + } + UndConstraint filterUndConstraints() { + if(this.oderConstraintPairs.size()==1){ + return this.oderConstraintPairs.firstElement(); + } + return null; + } + + */ + @Override + public Set> getSet() { + return this.oderConstraintPairs; + } + + +} diff --git a/src/de/dhbwstuttgart/typeinference/OderMenge.java b/src/de/dhbwstuttgart/typeinference/OderMenge.java new file mode 100644 index 000000000..d6083480e --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/OderMenge.java @@ -0,0 +1,37 @@ +package de.dhbwstuttgart.typeinference; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.unify.Unifikationsalgorithmus; + +public abstract class OderMenge implements KomplexeMenge{ + + public abstract Set> getSet(); + + @Override + public Set> cartesianProduct() { + Set> ret = new Menge<>(); + for(KomplexeMenge km : this.getSet()){ + ret.addAll(km.cartesianProduct()); + } + return ret; + } + + @Override + public String toString(){ + String ret = "["; + for(KomplexeMenge i : this.getSet()){ + ret += i.toString() + " | "; + } + return ret + "]"; + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/Pair.java b/src/de/dhbwstuttgart/typeinference/Pair.java new file mode 100755 index 000000000..5d5641f83 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/Pair.java @@ -0,0 +1,273 @@ +package de.dhbwstuttgart.typeinference; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +// ino.end +import de.dhbwstuttgart.syntaxtree.type.FreshWildcardType; +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.WildcardType; + + + +// Klasse, die ein Paar in der Menge Eq speichern kann +public class Pair implements Serializable, DeepCloneable +{ + public RefType TA1; + public RefType TA2; + + private PairOperator eOperator = PairOperator.SMALLER; + + public boolean bSubst; // speichert, ob die SUBST -Regel auf diese Paar + + public Pair( RefType TA1, RefType TA2 ) + { + // Konstruktor + //if(TA1 == null || TA2 == null)throw new NullPointerException(); + this.TA1 = TA1; + this.TA2 = TA2; + bSubst = false; + eOperator = PairOperator.SMALLER; + } + + public Pair( RefType TA1, RefType TA2, PairOperator eOp) + { + // Konstruktor + this(TA1,TA2); + this.eOperator = eOp; + } + // ino.end + + // ino.method.Pair.26561.definition + public Pair( RefType TA1, RefType TA2, PairOperator eOp, boolean bSubst ) + // ino.end + // ino.method.Pair.26561.body + { + // Konstruktor + this(TA1,TA2,eOp); + this.bSubst = bSubst; + } + // ino.end + + // ino.method.toString.26564.definition + public String toString() + // ino.end + // ino.method.toString.26564.body + { + // otth: Gibt ein Paar als String aus --> zum Debuggen und Vergleichen + String strElement1 = "NULL"; + String strElement2 = "NULL"; + String Operator = "<."; + + if( TA1 != null ) + strElement1 = TA1.toString(); + + if( TA2 != null ) + strElement2 = TA2.toString(); + + if(OperatorEqual()) + Operator = "="; + if(OperatorSmaller()) + Operator = "<."; + if(OperatorSmallerExtends()) + Operator = " v1=RT1.get_ParaList(); + List v2=RT2.get_ParaList(); + if(v1==null && v2==null){ + return true; + }else{ + if(v1==null && v2!=null || v1!=null && v2==null){ + return false; + }else{ + if(v1.size()!=v2.size()){ + return false; + }else{ + for(int i=0;i Stringvergleich + // TA1 == TA2 + return true; + }*/ + + }else if( TA1 instanceof TypePlaceholder && TA2 instanceof TypePlaceholder ) { + + if( TA1.getName().equals( TA2.getName() ) ) + { + // TA1 = TA2 + return true; + } + + } else if( TA1 instanceof GenericTypeVar && TA2 instanceof GenericTypeVar ) { + //eingefuegt PL 06-05-16 + if( TA1.getName().equals( TA2.getName() ) ) + { + // TA1 = TA2 + return true; + } + } else if(TA1 instanceof WildcardType && TA2 instanceof WildcardType) + { + return TA1.equals(TA2); + } + else if(TA1 instanceof FreshWildcardType && TA2 instanceof FreshWildcardType) + { + return TA1.equals(TA2); + } + + // Rest: Typen sind wohl verschieden + return false; + + + } + + public static RefType copyType( RefType T ) + { + // #JB# 22.05.2005 + // ########################################################### + return T.clone(); + // ########################################################### + + } + + /** + *
Author: J�rg B�uerle + * @param obj + * @return + */ + public boolean equals(Object obj) + { + boolean ret = true; + ret &= (obj instanceof Pair); + if(!ret)return ret; + ret &= ((Pair)obj).TA1.equals(this.TA1); + ret &= ((Pair)obj).TA2.equals(this.TA2); + return ret; + } + + /** + * Author: Arne Lüdtke
+ * Abfrage, ob Operator vom Typ Equal ist. + */ + public boolean OperatorEqual() + { + return eOperator == PairOperator.EQUALSDOT; + } + + /** + * Author: Arne Lüdtke
+ * Abfrage, ob Operator vom Typ Smaller ist. + */ + public boolean OperatorSmaller() + { + return eOperator == PairOperator.SMALLER; + } + + /** + * Author: Arne Lüdtke
+ * Abfrage, ob Operator vom Typ SmallerExtends ist. + */ + public boolean OperatorSmallerExtends() + { + return eOperator == PairOperator.SMALLERDOTWC; + } + + /** + * Author: Arne Lüdtke
+ * Gibt den Operator zurück. + */ + public PairOperator GetOperator() + { + return eOperator; + } + + + /** + * Author: Arne Lüdtke
+ * Erzeugt einen Klon des Paares. + */ + public Pair clone() + { + return this.copyPair(); + } + + /** + * Gibt eine Liste aller TypePlaceholder die in diesem Pair enthalten sind zurück. + * (Immer zwischen 0 und 2 Stück ;P) + * @return + */ + public Menge getTypePlaceholder() { + Menge ret = new Menge(); + if(this.TA1 instanceof TypePlaceholder)ret.add((TypePlaceholder)TA1); + if(this.TA2 instanceof TypePlaceholder)ret.add((TypePlaceholder)TA2); + return ret; + } + + /** + * @return Menge aus TA1 und TA2 + */ + public List getTypes(){ + List ret = new ArrayList<>(); + ret.add(this.TA1); + ret.add(this.TA2); + return ret; + } + + public Pair deepClone() { + /* + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(this); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bais); + return (Pair) ois.readObject(); + } catch (IOException e) { + return null; + } catch (ClassNotFoundException e) { + return null; + } + */ + return clone(); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/ResultSet.java b/src/de/dhbwstuttgart/typeinference/ResultSet.java new file mode 100755 index 000000000..87c3ecbd6 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/ResultSet.java @@ -0,0 +1,154 @@ +package de.dhbwstuttgart.typeinference; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.exceptions.DebugException; + +/** + * Im Grunde Sammlung von Pair s mit Equal-Operatoren. + * + * @author Andreas Stadelmeier, a10023 + * + */ +public class ResultSet implements Iterable { + + Menge resultPairs; + + public ResultSet(Menge resultSet){ + resultPairs = resultSet; + } + + /** + * Erstellt ein leeres ResultSet + */ + public ResultSet() { + this(new Menge()); + } + + public Menge getResultSet(){ + return resultPairs; + } + + /** + * Löst den übergebenen Typ auf. Rückgabetyp ist ein Reftype oder Void + * @param type + * @return + */ + public RefType getTypeEqualTo(RefType type) { + return getTypeEqualTo(type,null); + } + + /** + * Löst den übergebenen Typ auf. Rückgabetyp ist ein Reftype oder Void + * @param type + * @return + */ + public RefType getTypeEqualTo(RefType type, List ofType) { + RefType res = type; + Menge modifiedResultPairs = (Menge) resultPairs.clone(); + Ret r = findPairWithTypeEqualTo(type, modifiedResultPairs); + while(r.i != -1 && r.ret != null){ + res = r.ret; + if(ofType != null){ + if(res instanceof RefType)return res; + if(ofType.contains(res) && ! res.equals(type))return res; + } + modifiedResultPairs.remove(r.i); + r = findPairWithTypeEqualTo(res, modifiedResultPairs); + } + return res; + } + + class Ret{ + int i; + RefType ret; + private Ret(int i, RefType ret){ + this.i = i; + this.ret = ret; + } + } + + private Ret findPairWithTypeEqualTo(RefType type, Menge inResultPairs){ + for(int i = 0; i iterator() { + return this.getResultSet().iterator(); + } + + /** + * Durchsucht das ResultSet (die unifizierten Constraints des ResultSets) nach diesem Typ. Der Typ wird nicht aufgelöst. + * Es spielt keine Rolle in welchem Kontext der Typ im ResultSet auftaucht. + * @param tA1 + * @return true, falls der gesuchte Typ enthalten ist. + */ + public boolean contains(RefType tA1) { + for(Pair p : this){ + if(p.TA1.equals(tA1)||p.TA2.equals(tA1))return true; + } + return false; + } + + @Override + public String toString(){ + return this.getResultSet().toString(); + } + + @Override + public boolean equals(Object obj){ + return true; + } + + + /** + * Sammelt alle Constraints, welche mit den übergebenen TPH's in Verbindung stehen. + * Auch alle Constraints, welche wiederum mit den gesammelten Constraints in Verbindung stehen werden gesammelt. + * @return + */ + public Menge getConstraintsFor(Menge typePlaceholders) { + Menge ret = new Menge(); + Menge tphs = (Menge) typePlaceholders.clone(); + for(int i = 0;i getTypesInvolving(Menge unresolvedTPH) { + List ret = new ArrayList<>(); + for(Pair p : this.resultPairs){ + for(TypePlaceholder tph : unresolvedTPH){ + if(p.TA1.involves(tph))ret.add(p.TA1); + if(p.TA2.involves(tph))ret.add(p.TA2); + } + } + return ret; + } +} diff --git a/src/de/dhbwstuttgart/typeinference/TIPConstraints.java b/src/de/dhbwstuttgart/typeinference/TIPConstraints.java new file mode 100644 index 000000000..63756dd28 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/TIPConstraints.java @@ -0,0 +1,17 @@ +package de.dhbwstuttgart.typeinference; + +import de.dhbwstuttgart.typeinference.Menge; + +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +/** + * + * @author janulrich + * + */ +public class TIPConstraints { + + public TIPConstraints(Menge involvedTPHs){ + + } +} diff --git a/src/de/dhbwstuttgart/typeinference/TypeInsertable.java b/src/de/dhbwstuttgart/typeinference/TypeInsertable.java new file mode 100644 index 000000000..cba61fcea --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/TypeInsertable.java @@ -0,0 +1,22 @@ +package de.dhbwstuttgart.typeinference; + +import de.dhbwstuttgart.core.IItemWithOffset; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint; + +public interface TypeInsertable extends Typeable, IItemWithOffset { + + public int getOffset(); + public void setOffset(int offset); + public String getIdentifier(); + + /** + * Errechnet den TypeInsertPoint für das TypeInsertable. + * TypeInsertPoints sollten nur über diese Funktion erstellt werden. + * @param tph + * @param resultSet + * @return - kann auch null zurückgeben. + */ + public TypeInsertPoint createTypeInsertPoint(TypePlaceholder tph, ResultSet resultSet); + +} diff --git a/src/de/dhbwstuttgart/typeinference/Typeable.java b/src/de/dhbwstuttgart/typeinference/Typeable.java new file mode 100755 index 000000000..ad305b011 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/Typeable.java @@ -0,0 +1,14 @@ +package de.dhbwstuttgart.typeinference; + +import de.dhbwstuttgart.syntaxtree.type.Type; + +public interface Typeable { + /** + * @author Andreas Stadelmeier, a10023 + * Jede Expression und jedes Statement muss im Zuge des Typinferenzalgorithmus das Interfece Typable einbinden. + * Die Typen werden nur einmalig vom Parser gesetzt und können dann nur ausgelesen werden. + * Dadurch bleibt der Syntaxbaum immutable. + * @param typ Der Typ der Typable-Expression/Statement + */ + Type getType(); +} diff --git a/src/de/dhbwstuttgart/typeinference/TypeinferenceResultSet.java b/src/de/dhbwstuttgart/typeinference/TypeinferenceResultSet.java new file mode 100755 index 000000000..3059529cc --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/TypeinferenceResultSet.java @@ -0,0 +1,116 @@ +// ino.module.CTypeReconstructionResult.8689.package +package de.dhbwstuttgart.typeinference; +// ino.end + +// ino.module.CTypeReconstructionResult.8689.import +import java.util.Hashtable; +import java.util.Iterator; +import de.dhbwstuttgart.typeinference.Menge; + +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.assumptions.TypeAssumptions; +import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +// ino.class.CTypeReconstructionResult.27238.description type=javadoc +/** + * Diese Container-Klasse kapselt alle Ergebniswerte f�r eine m�gliche + * Typkombination einer Klasse und deren Methoden sowie lokalen Variablen. Eine + * Instanz dieser Klasse steht f�r genau eine m�gliche Typkombination.
+ * Objekte dieser Klasse werden vom Typrekonstruktionsalgorithmus �ber die + * Compiler-API zur�ckgegeben. + * @author J�rg B�uerle + * @version $Date: 2013/09/22 20:13:02 $ + */ +// ino.end +// ino.class.CTypeReconstructionResult.27238.declaration +public class TypeinferenceResultSet +{ + + /** + * Alle Constraints vor der Unifizierung. + * Dies ist nur eine Liste von Pair-Objekten (jedes Pair Objekt bildet dabei einen Constraint: Bsp.: TA <. TB) + */ + private Menge constraints; + /** + * Das unifizierte ConstaraintsSet + */ + private ResultSet unifiedConstraints; + private de.dhbwstuttgart.syntaxtree.Class ownerOfResultSet;//Jedes Resultset gilt immer nur für eine Klasse. Diese wird in dieser Variable gespeichert. + + // ino.method.CTypeReconstructionResult.27256.definition + public TypeinferenceResultSet(de.dhbwstuttgart.syntaxtree.Class inferedClass, Menge constraints, ResultSet unifiedConstraints) + // ino.end + // ino.method.CTypeReconstructionResult.27256.body + { + this.ownerOfResultSet = inferedClass; + this.constraints = constraints; + this.unifiedConstraints = unifiedConstraints; + } + // ino.end + + /** + * @author Andreas Stadelmeier, a10023 + * Anhand des Syntaxbaums errechnet der Typinferenzalgorithmus ein Set von Constraints. + * Diese Funktion ist nur für automatisierte Tests interessant. + * Zum abrufen der Unifizierten Constraints siehe getUnifiedConstraints() + * @return + */ + public Menge getConstraints() { + return this.constraints; + } + + /** + * @author Andreas Stadelmeier, a10023 + * Nach dem Durchführen des Interferenzalgorithmus von Lambda 8 entsteht für jede Lösung ein Set con Constraints. + * Diese Constraints haben bereits den Unify-Algorithmus durchlaufen und weißen die errechneten Typen den Typeplacholdern zu. + * @return Das fertige ConstraintsSet dieser CTypeRecunstructionResult + */ + public ResultSet getUnifiedConstraints() { + return unifiedConstraints; + } + + + /** + * Ermittelt den in diesem ResultSet für den TypePlaceholder tph zugewiesenen Wert. + * @author Andreas Stadelmeier, a10023 + */ + public Type getTypeOfPlaceholder(TypePlaceholder tph){ + return this.getTypeOfPlaceholder(tph,null); + } + public Type getTypeOfPlaceholder(TypePlaceholder tph, Menge ofType){ + return this.getUnifiedConstraints().getTypeEqualTo(tph, ofType); + } + + /** + * Jedes TypeReconstructionResultSet entstand bei der Typinferierung einer Klasse. + * @return Gibt die Klasse zurück der dieses ResultSet zugeordnet ist. + */ + public de.dhbwstuttgart.syntaxtree.Class getInterferedClass(){ + return this.ownerOfResultSet; + } + + @Override + public String toString(){ + return "Unified Constraints: "+this.unifiedConstraints.toString(); + } + + /** + * Berechnet alle möglichen Punkte zum Einsetzen eines Typs im Quelltext + * Dabei entstehen TypeInsertSets. Für jeden gesammelten TypeInsertPoint werden alle Abhängigkeiten berechnet. + * + * @return + */ + public TypeInsertSet getTypeInsertionPoints(){ + TypeInsertSet ret = new TypeInsertSet(this.unifiedConstraints); + + this.ownerOfResultSet.addTypeInsertPoints(ret,this.unifiedConstraints); + + return ret; + } +} +// ino.end diff --git a/src/de/dhbwstuttgart/typeinference/TypeinferenceResults.java b/src/de/dhbwstuttgart/typeinference/TypeinferenceResults.java new file mode 100644 index 000000000..d4f01d534 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/TypeinferenceResults.java @@ -0,0 +1,31 @@ +package de.dhbwstuttgart.typeinference; + +import java.util.List; + +import de.dhbwstuttgart.bytecode.ClassGenerator; +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; + +public class TypeinferenceResults { + + private List typeReconstructions; + + public TypeinferenceResults() { + typeReconstructions = new Menge<>(); + } + + public TypeinferenceResults(List typeReconstructions) { + this.typeReconstructions = typeReconstructions; + } + + public List getTypeReconstructions() { + return typeReconstructions; + } + + public List getTypeReconstructions(Method method, ClassGenerator cg) { + return typeReconstructions; + } +} \ No newline at end of file diff --git a/src/de/dhbwstuttgart/typeinference/UndConstraint.java b/src/de/dhbwstuttgart/typeinference/UndConstraint.java new file mode 100755 index 000000000..bb6914ee4 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/UndConstraint.java @@ -0,0 +1,86 @@ +package de.dhbwstuttgart.typeinference; + +import java.util.Collection; +import java.util.Set; +import java.util.Vector; + +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.typeinference.exceptions.DebugException; +import de.dhbwstuttgart.typeinference.unify.Unifikationsalgorithmus; + +/** + * Stellt ein Constraint dar, welches aus mehreren Constraint-Paaren besteht. Diese gelten alle stets gleichzeitig / sind per "Und" miteinander verknüpft. + * @author janulrich + * + */ +public class UndConstraint extends UndMenge { + + Menge> set = new Menge<>(); + + @Override + public Menge> getSet() { + return set; + } + + public Set getConstraintPairs() { + Set> ret = this.cartesianProduct(); + if(ret.size() != 1){ + //UndConstraints enthalten nur SingleConstraints, wodurch das Karthesische Produkt nur aus einem Element bestehen kann. + throw new DebugException("Fehler in ConstraintPairs-Bildung"); + } + return ret.iterator().next(); + } + + public void addConstraint(Type type, Type rT) { + Pair p = new Pair(type, rT); + addConstraint(p); + } + + public void addConstraint(Pair toAdd){ + this.set.add(new EinzelElement(toAdd)); + } + + @Override + public String toString() { + String ret = this.getConstraintPairs().toString(); + return ret; + } + + public Set> getPairs(){ + return set; + } + +/* + public UndConstraint(ConstraintType p1, ConstraintType p2) { + super(p1, p2); + } + + @Override + public Vector getUndConstraints() { + Vector ret = new Vector(); + ret.add(this); + return ret; + } + + @Override + public String toString(){ + //String ret = super.toString(); + //return ret.replace('|', ','); + String ret = "["; + for(Pair p : this.getConstraintPairs()){ + ret += p.toString()+ ", "; + } + return ret+"]"; + } + + @Override + void filterWrongConstraints(Unifier unifier) { + //In einem UndConstraint gibt es keine falschen Constraints + } + + @Override + UndConstraint filterUndConstraints(){ + return this; + } +*/ +} diff --git a/src/de/dhbwstuttgart/typeinference/UndMenge.java b/src/de/dhbwstuttgart/typeinference/UndMenge.java new file mode 100644 index 000000000..8782d70ac --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/UndMenge.java @@ -0,0 +1,43 @@ +package de.dhbwstuttgart.typeinference; + +import de.dhbwstuttgart.typeinference.unify.TypeUnify; +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; + +//import com.rits.cloning.Cloner; + +public abstract class UndMenge
implements KomplexeMenge{ + + public abstract Menge> getSet(); + + @Override + public Set> cartesianProduct() { + Set> ret = null; + for(KomplexeMenge km : this.getSet()){ + if(ret == null){ + ret = km.cartesianProduct(); + }else{ + Set> cartesianProduct = new Menge<>(); + for(Set r : ret)for(Set m : km.cartesianProduct()){ //Für jedes Element aus dem Karthesischen Produkt: + Set undElement = new Menge(); + undElement.addAll(r); + undElement.addAll(m); + cartesianProduct.add(undElement); + } + ret = cartesianProduct; + } + } + if(ret == null)return new Menge<>(); + return ret; + } + + public String toString(){ + String ret = "["; + for(KomplexeMenge item : this.getSet()){ + ret += item.toString() + " , "; + } + return ret + "]"; + } +} + diff --git a/src/de/dhbwstuttgart/typeinference/UnifyConstraintsSet.java b/src/de/dhbwstuttgart/typeinference/UnifyConstraintsSet.java new file mode 100644 index 000000000..b19a0197e --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/UnifyConstraintsSet.java @@ -0,0 +1,96 @@ +package de.dhbwstuttgart.typeinference; + +import java.util.Iterator; +import java.util.Set; +import java.util.Vector; +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.*; +import de.dhbwstuttgart.typeinference.unify.Unifikationsalgorithmus; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +public class UnifyConstraintsSet extends UndMenge implements Iterable{ + private static final Logger log = Logger.getLogger(UnifyConstraintsSet.class.getName()); + private Menge constraintsSet; + + public UnifyConstraintsSet(){ + constraintsSet = new Menge(); + } + + public void add(UnifyConstraintsSet CSet){ + for(UnifyOderConstraint element : CSet) + add(element); + } + public void add(UnifyOderConstraint constraint){ + constraintsSet.add(constraint); + } + + @Override + public String toString(){ + String ret =""; + for(UnifyOderConstraint constraint : this){ + ret += constraint.toString()+"\n"; + } + return ret; + } + + public Iterator iterator() { + return constraintsSet.iterator(); + } + + public void filterWrongConstraints(Unifikationsalgorithmus unify) { + /* + * Das ConstraintsSet enthält nur OderConstraints, welche UND-Verknüpft sind. + * Hier werden Constraints in den OderConstraints kontrolliert: + */ + for(UnifyOderConstraint constraint : this){ + constraint.filterWrongConstraints(unify); + } + } + + /** + * Nimmt alle UndConstraints und filtert mithilfe dieser die falschen Constraints aus den OderConstraints + * @param unifier + */ + public void unifyUndConstraints(Unifikationsalgorithmus unifier) { + Vector uCons = this.filterUndConstraints(); + Vector alleUndConstraints = new Vector<>(); + for(UnifyUndConstraint undConstraint : uCons){ + alleUndConstraints.addAll(undConstraint.getConstraintPairs()); + } + this.filterWrongConstraints( + (pairs)->{ + Set undConstraintsUndPairs = new Menge<>(); + undConstraintsUndPairs.addAll(pairs); + undConstraintsUndPairs.addAll(alleUndConstraints); + log.debug("Versuche Pairs auszusondern:\n"+pairs, Section.TYPEINFERENCE); + log.debug("Unifiziere:\n"+undConstraintsUndPairs, Section.TYPEINFERENCE); + Set> unifyResult = unifier.apply(undConstraintsUndPairs); + return unifyResult; + }); + } + + /** + * Aus dem ConstraintsSet [ u1, u2, ... (OderConstraint), ... uN ] werden alle + * UndConstraints, welche sich nicht innerhalb eines OderConstraints befinden, herausgefiltert + * @return [u1, ... , uN] + */ + private Vector filterUndConstraints() { + Vector ret = new Vector<>(); + for(UnifyOderConstraint con : constraintsSet){ + UnifyUndConstraint filtered = con.filterUndConstraints(); + if(filtered != null)ret.add(filtered); + } + return ret; + } + + public void add(UnifyUndConstraint singleConstraint) { + UnifyOderConstraint toAdd = new UnifyOderConstraint(); + toAdd.addConstraint(singleConstraint); + constraintsSet.add(toAdd); + } + + @Override + public Menge> getSet() { + return this.constraintsSet; + } +} diff --git a/src/de/dhbwstuttgart/typeinference/UnifyOderConstraint.java b/src/de/dhbwstuttgart/typeinference/UnifyOderConstraint.java new file mode 100644 index 000000000..4955ea931 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/UnifyOderConstraint.java @@ -0,0 +1,112 @@ +package de.dhbwstuttgart.typeinference; + +import java.util.Set; +import java.util.Vector; + +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.unify.Unifikationsalgorithmus; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +public class UnifyOderConstraint extends OderMenge{ + private Set oderConstraintPairs; + + private final static Logger logger = Logger.getLogger(UnifyOderConstraint.class.getName()); + + /** + * Erstellt ein neues Oder Constraint und f�gt bereits ein Constraint hinzu. + * @param p1 + * @param p2 + + public OderConstraint(Pair p1, Pair p2){ + if(p1 == null || p2 == null)throw new NullPointerException(); + Pair constraintPair = new Pair(p1,p2); + oderConstraintPairs = new Menge(); + this.addConstraint(constraintPair); + } + */ + + public UnifyOderConstraint(){ + oderConstraintPairs = new Menge(); + } + + + /** + * Liefert alle in diesem OderConstraint enthaltene Constraints. Dabei gehen die Verkn�pfungen (Oder/Und) verloren. + * @return + */ + public Menge getConstraintPairs(){ + Menge ret = new Menge(); + for(UnifyUndConstraint oC : this.oderConstraintPairs){ + ret.addAll(oC.getConstraintPairs()); + } + return ret; + } + + /** + * Falls die Type des toAdd-Pairs nicht vom Typ RefType bzw. TypePlaceholder sind, so werden sie in einen RefType umgewandelt. + * @param toAdd + */ + public void addConstraint(UnifyPair toAdd){ + oderConstraintPairs.add(new UnifySingleConstraint(toAdd)); + } + + @Override + public String toString(){ + String ret = "["; + for(UnifyUndConstraint p : this.getUndConstraints()){ + ret += p.toString()+ "| "; + } + return ret+"]"; + } + + public Set getUndConstraints() { + return this.oderConstraintPairs; + /* + Vector ret = new Vector(); + for(Pair p : this.getConstraintPairs()){ + ret.add(new UndConstraint(p.TA1,p.TA2)); + } + return ret; + */ + } + + public void addConstraint(UnifyUndConstraint constraint) { + oderConstraintPairs.add(constraint); + } + + /** + * Filtert die Constraints in diesem ODER-Verknüpften Constraint aus, + * welche keinen Sinn ergeben, also beim unifizieren scheitern. + * @param unifier - Wird für die Unifizierung benutzt + */ + void filterWrongConstraints(Unifikationsalgorithmus unifier) { + Set filteredConstraints = new Menge<>(); + for(UnifyUndConstraint cons : this.getUndConstraints()){ + Set> unifierResult = unifier.apply(cons.getConstraintPairs()); + if(!unifierResult.isEmpty()){ + filteredConstraints.add(cons); + }else{ + logger.debug("Ausgesondertes Constraint: "+cons, Section.TYPEINFERENCE); + } + } + this.oderConstraintPairs = filteredConstraints; + } + + UnifyUndConstraint filterUndConstraints() { + if(this.oderConstraintPairs.size()==1){ + return this.oderConstraintPairs.iterator().next(); + } + return null; + } + + @Override + public Set> getSet() { + return this.oderConstraintPairs; + } + + +} diff --git a/src/de/dhbwstuttgart/typeinference/UnifySingleConstraint.java b/src/de/dhbwstuttgart/typeinference/UnifySingleConstraint.java new file mode 100644 index 000000000..2860d32fa --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/UnifySingleConstraint.java @@ -0,0 +1,50 @@ +package de.dhbwstuttgart.typeinference; + +import java.util.Vector; + +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.exceptions.DebugException; +import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + + +public class UnifySingleConstraint extends UnifyUndConstraint{ + + private UnifyPair constraintPair; //entspricht θ condition θ' + + @Override + public Menge> getSet() { + Menge> ret = new Menge<>(); + ret.add(new EinzelElement<>(constraintPair)); + return ret; + } + + public UnifySingleConstraint(UnifyPair toAdd) { + this.addConstraint(toAdd); + } + + public UnifyPair getPair(){ + return constraintPair; + } + + @Override //Methode überschreiben, damit immer nur ein Vector mit nur einem Element zurückgeliefert wird. + public Menge getConstraintPairs(){ + Menge ret = new Menge<>(); + ret.add(constraintPair); + return ret; + } + + public void addConstraint(UnifyPair toAdd){ + if(constraintPair != null)throw new DebugException("Ein Constraint darf nur aus einem ConstraintPair bestehen. Das hinzufügen von "+ toAdd + " ist nicht möglich."); + + constraintPair = toAdd; + } + + @Override + public String toString(){ + return constraintPair.toString(); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/UnifyUndConstraint.java b/src/de/dhbwstuttgart/typeinference/UnifyUndConstraint.java new file mode 100644 index 000000000..f1ed05489 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/UnifyUndConstraint.java @@ -0,0 +1,45 @@ +package de.dhbwstuttgart.typeinference; + +import java.util.Collection; +import java.util.Set; +import java.util.Vector; + +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.typeinference.exceptions.DebugException; +import de.dhbwstuttgart.typeinference.unify.Unifikationsalgorithmus; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +/** + * Stellt ein Constraint dar, welches aus mehreren Constraint-Paaren besteht. Diese gelten alle stets gleichzeitig / sind per "Und" miteinander verknüpft. + * @author janulrich + * + */ +public class UnifyUndConstraint extends UndMenge { + + Menge> set = new Menge<>(); + + @Override + public Menge> getSet() { + return set; + } + + public Set getConstraintPairs() { + Set> ret = this.cartesianProduct(); + if(ret.size() != 1){ + //UndConstraints enthalten nur SingleConstraints, wodurch das Karthesische Produkt nur aus einem Element bestehen kann. + throw new DebugException("Fehler in ConstraintPairs-Bildung"); + } + return ret.iterator().next(); + } + + @Override + public String toString() { + String ret = this.getConstraintPairs().toString(); + return ret; + } + + public void add(UnifyPair pair){ + set.add(new EinzelElement<>(pair)); + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/Assumption.java b/src/de/dhbwstuttgart/typeinference/assumptions/Assumption.java new file mode 100644 index 000000000..db64c33cf --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/assumptions/Assumption.java @@ -0,0 +1,29 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import de.dhbwstuttgart.typecheck.JavaClassName; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.typeinference.TypeInsertable; + +public class Assumption { + + private TypeInsertable typable; + + /** + * Wird dieser Konstruktor benutzt müssen alle Methoden der Klasse Assumption überschrieben werden. + */ + protected Assumption(){ + } + + public Assumption(TypeInsertable ass){ + this.typable = ass; + } + + public Type getAssumedType() { + return this.typable.getType(); + } + + public JavaClassName getIdentifier(){ + return new JavaClassName(typable.getIdentifier()); + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/ClassAssumption.java b/src/de/dhbwstuttgart/typeinference/assumptions/ClassAssumption.java new file mode 100644 index 000000000..785a049f9 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/assumptions/ClassAssumption.java @@ -0,0 +1,32 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import de.dhbwstuttgart.syntaxtree.Class; +/** + * Nicht wirklich eine Assumption. + * Wird benutzt um Typen von Variablen zu verifizieren. + * @author janulrich + * + */ +public class ClassAssumption{ + + private Class classType; + + public ClassAssumption(Class cls){ + this.classType = cls; + } + + public Class getAssumedClass(){ + return classType; + } + + public String toString(){ + return this.classType.getName().toString(); + } + + public boolean equals(Object obj){ + if(!(obj instanceof ClassAssumption))return false; + ClassAssumption equals = (ClassAssumption)obj; + if(!equals.classType.equals(this.classType))return false; + return true; + } +} diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/ConstructorAssumption.java b/src/de/dhbwstuttgart/typeinference/assumptions/ConstructorAssumption.java new file mode 100644 index 000000000..a3f72a464 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/assumptions/ConstructorAssumption.java @@ -0,0 +1,47 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import java.util.Iterator; + +import de.dhbwstuttgart.syntaxtree.Class; +import de.dhbwstuttgart.syntaxtree.Field; +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.syntaxtree.type.Void; +import de.dhbwstuttgart.typeinference.exceptions.DebugException; +import de.dhbwstuttgart.syntaxtree.type.*; + +public class ConstructorAssumption extends MethodAssumption{ + + public ConstructorAssumption(Method assumedMethod, Class parentClass) { + super(assumedMethod, parentClass); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof ConstructorAssumption))return false; + return super.equals(obj); + } + + @Override + public Type getAssumedType() { + return new Void(this.method.getOffset()); + //throw new DebugException("Eine ConstructorAssumption hat keinen Typ bzw. er ist nicht relevant"); + //return this.getMethod().getParentClass().getType(); + } + + @Override + public String toString(){ + String ret = "ConstructorAssumption: "; + ret += this.getMethodName()+"("; + Iterator it = this.getMethod().parameterlist.formalparameter.iterator(); + while(it.hasNext()){ + FormalParameter fp = it.next(); + ret+=fp.toString(); + if(it.hasNext())ret += ","; + } + ret+=")"; + return ret; + } +} diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java b/src/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java new file mode 100644 index 000000000..1530e95f6 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java @@ -0,0 +1,41 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import de.dhbwstuttgart.typecheck.JavaClassName; +import de.dhbwstuttgart.syntaxtree.Class; +import de.dhbwstuttgart.syntaxtree.Field; +import de.dhbwstuttgart.syntaxtree.type.Type; + +public class FieldAssumption extends Assumption { + + private Class parentClass; + private Field field; + + public FieldAssumption(Field fieldVar, Class inClass){ + super(fieldVar); + this.parentClass = inClass; + this.field = fieldVar; + } + + public Class getParentClass() { + return this.parentClass; + } + + public JavaClassName getIdentifier(){ + return new JavaClassName(this.field.getIdentifier()); + } + + @Override + public String toString(){ + return "FieldAssumption: "+this.field.getType()+" "+this.getIdentifier(); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof FieldAssumption))return false; + FieldAssumption equals = (FieldAssumption)obj; + if(!equals.field.equals(this.field))return false; + if(!equals.parentClass.equals(this.parentClass))return false; + return true; + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/GenericVarAssumption.java b/src/de/dhbwstuttgart/typeinference/assumptions/GenericVarAssumption.java new file mode 100644 index 000000000..687725344 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/assumptions/GenericVarAssumption.java @@ -0,0 +1,28 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import de.dhbwstuttgart.typecheck.JavaClassName; +import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.type.Type; + +public class GenericVarAssumption extends Assumption{ + + private GenericTypeVar genericVar; + + public GenericVarAssumption(GenericTypeVar genericVar){ + super(); + this.genericVar = genericVar; + } + + public GenericTypeVar getAssumedType() { + return genericVar;//new RefType(this.getIdentifier(), -1); + } + + public JavaClassName getIdentifier(){ + return genericVar.getName(); + } + + public String toString(){ + return this.getIdentifier() +"::"+this.getAssumedType(); + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/LocalVarAssumption.java b/src/de/dhbwstuttgart/typeinference/assumptions/LocalVarAssumption.java new file mode 100644 index 000000000..11530f64b --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/assumptions/LocalVarAssumption.java @@ -0,0 +1,21 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl; +import de.dhbwstuttgart.syntaxtree.type.Type; + +public class LocalVarAssumption extends Assumption { + private LocalVarDecl localVar; + private Type type; + + public LocalVarAssumption(LocalVarDecl localVar, Type declaredType){ + super(localVar); + this.localVar = localVar; + this.type = declaredType; + } + + @Override + public Type getAssumedType() { + return this.type; + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java b/src/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java new file mode 100644 index 000000000..88c887738 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java @@ -0,0 +1,74 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import java.util.Iterator; + +import de.dhbwstuttgart.syntaxtree.Class; +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.type.Type; + +public class MethodAssumption extends FieldAssumption { + + protected Method method; + private Class parentClass; + + public MethodAssumption(Method assumedMethod, Class parentClass){ + super(assumedMethod, parentClass); + this.method = assumedMethod; + this.parentClass = parentClass; + } + + public String getMethodName() { + return this.method.get_Name(); + } + + public int getParaCount(){ + return this.method.getParameterCount(); + } + + protected Method getMethod(){ + return method; + } + + /** + * Liefert den Typ des i-ten Parameters dieser Method-Assumption + * @param i + * @return + */ + public Type getParameterType(int i) { + Type ret = this.method.getParameterList().getParameterAt(i).getType(); + return ret; + } + + public Type getParentClassType() { + return this.parentClass.getType(); + } + + + public String toString(){ + String ret = "MethodAssumption: "; + ret += this.method.getType().toString()+" "; + ret += this.method.get_Name().toString()+"("; + Iterator it = this.method.parameterlist.formalparameter.iterator(); + while(it.hasNext()){ + FormalParameter fp = it.next(); + ret+=fp.toString(); + if(it.hasNext())ret += ","; + } + ret+=")"; + return ret; + } + + @Override + public boolean equals(Object obj){ + if(!(obj instanceof MethodAssumption))return false; + MethodAssumption equals = (MethodAssumption)obj; + if(equals.method==null)return false; + if(equals.parentClass==null)return false; + if(!(equals.method.equals(this.method)))return false; + if(!(equals.parentClass.equals(this.parentClass)))return false; + + return true; + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/ParameterAssumption.java b/src/de/dhbwstuttgart/typeinference/assumptions/ParameterAssumption.java new file mode 100644 index 000000000..7c5c8b84f --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/assumptions/ParameterAssumption.java @@ -0,0 +1,15 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import de.dhbwstuttgart.syntaxtree.FormalParameter; + +/** + * ParameterAssumptions repräsentieren die Methodenparameter innerhalb des Rumpfes einer Methode. + * + * @author janulrich + * + */ +public class ParameterAssumption extends Assumption { + public ParameterAssumption(FormalParameter parameter){ + super(parameter); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/TypeAssumptions.java b/src/de/dhbwstuttgart/typeinference/assumptions/TypeAssumptions.java new file mode 100755 index 000000000..65bb44d88 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/assumptions/TypeAssumptions.java @@ -0,0 +1,302 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import de.dhbwstuttgart.typeinference.Menge; + +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.typecheck.JavaClassName; +import de.dhbwstuttgart.syntaxtree.Class; +import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.Type; + +/** + * Eine Sammlung von TypeAssumptions. + * Jede Expression und jedes Statement erhält beim Aufrufen ihrer TYPE-Methode ein AssumptionSet mit den Assumptions ihrer Umgebung als Parameter übergeben. + * @author janulrich + * + * Es gibt verschiedene Assumptions: + * 1. Methoden Assumptions + * 2. Konstruktor Assumptions + * 3. Lokale Variablen Assumptions + * 4. Feldvariablen Assumptions + * + */ +public class TypeAssumptions { + + private static final Logger log = Logger.getLogger( TypeAssumptions.class.getName() ); + + //private static CTypeAssumptionSet globalAssumptions = new CTypeAssumptionSet(); + private JavaClassName thisClassName; + + + private Menge methodAssumptions = new Menge(); + private Menge constructorAssumptions = new Menge(); + private Menge fieldAssumptions = new Menge(); + private Menge localVarAssumptions = new Menge(); + private Menge parameterAssumptions = new Menge(); + private Menge genericVarAssumptions = new Menge(); + private Menge classAssumptions = new Menge(); + + /** + * Dieser Konstruktor setzt bei der Initialisierung auch den Wert von "this" + * @param klassenname - Wert für "this" + */ + public TypeAssumptions(){ + //this.thisClassName = klassenname; + } + + public TypeAssumptions(JavaClassName thisClassName){ + this(); + this.thisClassName = thisClassName; + } + + /** + * Liefert alle bekannten öffentlichen Feldern mit dem Namen withName. Dabei werden alle bekannten Klassen durchsucht. + * @param withName + * @return + */ + public Menge getFieldVars(String withName){ + Menge ret = new Menge(); + for(FieldAssumption fa : this.fieldAssumptions){ + if(fa.getIdentifier().equals(withName))ret.add(fa); + } + return ret; + } + + /** + * Liefert den Typ einer Feldvariable der Klasse inClass + * @param withName + * @param inClass + * @return null, falls die Klasse kein zugängliches Feld enthält + */ + public Type getTypeOfFieldVar(String withName, Class inClass){ + for(FieldAssumption fa : this.getFieldVars(withName)){ + if(fa.getParentClass().equals(inClass))return fa.getAssumedType(); + } + //throw new TypeinferenceException("Das Feld "+withName+" ist in der Klasse "+inClass.getName()+" nicht vorhanden."); + return null; + } + + /** + * Sucht nach Assumptions zu einer Methode mit dem Namen methodName und parameterCount Parametern. + * @param methodName + * @param i Die Parameter, welche die Methode verarbeiten soll + * @return Alle Methoden in den Assumptions, welche eine Parameterliste der Länge der übergebenen Parameterliste (parameter) verarbeiten können. + */ + public Menge getMethodAssumptions(String methodName, int parameterCount){ + Menge ret = new Menge(); + for(MethodAssumption ass : this.methodAssumptions){ + if(ass.getMethodName().equals(methodName) && ass.getParaCount() == parameterCount){ + ret.add(ass); + } + } + + //TODO: Dieser Teil mit der Generierung von FunN-Methoden kann raus, da die FunNInterfaces sich in den Basic-Assumptions befinden sollten. + //Falls es sich um die apply-Methode eines FunN-Interface handelt: + //if(methodName.equals("apply")){ //Ein Workaround für den Typinferenzalgorithmus TODO: Das hier rausnehmen. + //CMethodTypeAssumption funNAssumption = new FunN(parameterCount).toCMethodTypeAssumption(); + // MethodAssumption funNAssumption = new MethodAssumption(new FunNMethod(parameterCount), new FunNInterface(parameter)); + // ret.add(funNAssumption); + //} + //if(ret.size()==0)throw new TypeinferenceException("Eine Methode "+methodName+" ist in den Assumptions nicht vorhanden"); + return ret; + } + + + /** + * Durchsucht die Assumptions des aktuellen Gültigkeitsbereichs (lokale Variablen und Felder der aktuellen Klasse) nach einem Eintrag für den übergebenen Variablennamen. + * In den Assumptions wird dann in der Reihenfolge LocalVarAssumptions, FieldAssumption nach dem übergebenen Variablennamen gesucht. + * @param variableName - der Identifier der gesuchten Variablen + * @param inScope - Sucht auch die Felder der übergebenen Klasse ab. Hier kann auch null übergeben werden, dann werden nur die Lokalen Variablen dieser TypeAssumption durchsucht. + * @return - Der Typ für diesen Identifier, oder null, falls kein Typ vorliegt. + */ + public Type getVarType(String variableName, Class inScope){ + //Zuerst die Parameter durchsuchen + for(ParameterAssumption ass : this.parameterAssumptions){//this.getParameterAssumptions(null)){ + if(ass.getIdentifier().equals(variableName))return ass.getAssumedType(); + } + //Dann die lokalen Variablen + for(LocalVarAssumption ass : this.localVarAssumptions){ + if(ass.getIdentifier().equals(variableName))return ass.getAssumedType(); + } + //Ebenso wie die Generischen Variablen: + for(GenericVarAssumption ass : this.genericVarAssumptions){ + if(ass.getIdentifier().equals(variableName))return ass.getAssumedType(); + } + + //und zuletzt die Felder der Klasse in dessen Namensraum sich dieses AssumptionSet befindet. + if(inScope!=null){ + for(FieldAssumption ass : this.getAssumptionsFor(inScope.getName())){ + if(ass.getIdentifier().equals(variableName) && ass instanceof FieldAssumption)return ass.getAssumedType(); + } + } + //Wird keine Assumption gefunden, muss ein Fehler vorliegen: + //throw new TypeinferenceException("Eine Variable "+variableName+" ist in den Assumptions nicht vorhanden", inScope); + return null; + } + + /** + * Sucht nach MethodAssumptions einer bestimmten Klasse mit einem bestimmten Namen. + * @param className + * @param methodName + * @param parameterCount + * @return + */ + public Menge getMethodAssumptions(JavaClassName className, String methodName){ + Menge ret = new Menge(); + for(FieldAssumption ass : this.getAssumptionsFor(className)){ + //System.out.println(ass.getIdentifier()); + if(ass.getIdentifier().equals(methodName) && ass instanceof MethodAssumption)ret.add((MethodAssumption)ass); + } + //if(ret.size()==0)throw new TypinferenzException("Eine Methode "+methodName+" ist in den Assumptions nicht vorhanden"); + return ret; + } + + /** + * Liefert alle Assumptions, außer die der lokalen Variablen, welche einer bestimmten Klasse zugeordnet sind. + * @param className + * @return + */ + private Menge getAssumptionsFor(JavaClassName className) { + Menge ret = new Menge(); + for(Assumption a : this.getAllAssumptions()){ + if(a instanceof FieldAssumption){ + FieldAssumption fA = (FieldAssumption) a; + if(fA.getParentClass().getName().equals(className))ret.add(fA); + } + } + return ret; + } + + + private Menge getAllAssumptions(){ + Menge ret = new Menge(); + for(Assumption f : this.localVarAssumptions)ret.add(f); + for(Assumption f : this.methodAssumptions)ret.add(f); + for(Assumption f : this.fieldAssumptions)ret.add(f); + for(Assumption f : this.parameterAssumptions)ret.add(f); + for(Assumption f : this.constructorAssumptions)ret.add(f); + for(Assumption f : this.genericVarAssumptions)ret.add(f); + return ret; + } + + public void addAssumption(Assumption ass){ + if(ass instanceof ConstructorAssumption){ + if(!this.constructorAssumptions.contains(ass))this.constructorAssumptions.add((ConstructorAssumption)ass);//this.constructorAssumptions.add((ConstructorAssumption)ass); + return; + } + if(ass instanceof MethodAssumption){ + if(!this.methodAssumptions.contains(ass))this.methodAssumptions.add((MethodAssumption)ass);//this.methodAssumptions.add((MethodAssumption)ass);// + return; + } + if(ass instanceof LocalVarAssumption)if(!this.localVarAssumptions.contains(ass))this.localVarAssumptions.add((LocalVarAssumption)ass);//this.localVarAssumptions.add((LocalVarAssumption)ass);// + if(ass instanceof ParameterAssumption)if(!this.parameterAssumptions.contains(ass))this.parameterAssumptions.add((ParameterAssumption)ass);//this.parameterAssumptions.add((ParameterAssumption)ass); + if(ass instanceof FieldAssumption)if(!this.fieldAssumptions.contains(ass))this.fieldAssumptions.add((FieldAssumption)ass);//this.fieldAssumptions.add((FieldAssumption)ass); + if(ass instanceof GenericVarAssumption)if(!this.genericVarAssumptions.contains(ass))this.genericVarAssumptions.add((GenericVarAssumption)ass); + + } + + private void addAllAssumptions(Menge assumptions){ + for(Assumption ass : assumptions){ + this.addAssumption(ass); + } + } + + public TypeAssumptions add(TypeAssumptions assumptions){ + //for(MethodAssumption ass : assumptions.methodAssumptions){ + // if(!this.methodAssumptions.contains(ass))this.methodAssumptions.add(ass); + //} + //this.methodAssumptions.addAll(assumptions.methodAssumptions); + //this.fieldAssumptions.addAll(assumptions.fieldAssumptions); + //this.localVarAssumptions.addAll(assumptions.localVarAssumptions); + //this.parameterAssumptions.addAll(assumptions.parameterAssumptions); + //this.constructorAssumptions.addAll(assumptions.constructorAssumptions); + this.addAllAssumptions(assumptions.getAllAssumptions()); + this.classAssumptions.addAll(assumptions.classAssumptions); + return this; + } + + + @Override + public TypeAssumptions clone(){ + TypeAssumptions ret = new TypeAssumptions(); + ret.add(this); + return ret; + } + + @Override + public String toString(){ + String ret = "this: "+this.thisClassName+"\n"; + ret += "Method Assumptions:\n" + this.methodAssumptions.toString() + "\n"; + ret += "FieldVar Assumptions:\n" + this.fieldAssumptions.toString() + "\n"; + ret += "LocalVar Assumptions:\n" + this.localVarAssumptions.toString() + "\n"; + ret += "Parameter Assumptions:\n" + this.parameterAssumptions.toString() + "\n"; + ret += "Generic Var Assumptions:\n" + this.genericVarAssumptions.toString() + "\n"; + ret += "Konstruktor Assumptions:\n" + this.constructorAssumptions.toString() + "\n"; + ret += "Class Assumptions:\n" + this.classAssumptions.toString() + "\n"; + //return assumptions.toString(); + return ret; + } + + /** + * Fügt eine TypAssumption an. + * Dadurch wird ein Pool von Typen aufgebaut, welche überhaupt erlaubt sind. + * Wird genutzt um vom Parser eingelesene Typen auf ihre Korrektheit zu kontrollieren. + * @param classAssumption + */ + public void addClassAssumption(ClassAssumption classAssumption) { + if(!this.classAssumptions.contains(classAssumption))//throw new TypinferenzException("Die Klasse "+classAssumption.getAssumedClass().getName()+" wurde bereits deklariert"); + this.classAssumptions.add(classAssumption); + } + + /** + * + * @return Null, falls kein Konstruktor vorhanden. + */ + public ConstructorAssumption getConstructorAssumption(String className, int paramCount) { + for(ConstructorAssumption ca : this.constructorAssumptions){ + log.debug("Durchsuche Assumptions: "+ca.getIdentifier().toString() +" -Anzahl Parameter: "+ ca.getParaCount(), Section.TYPEINFERENCE); + if(ca.getParaCount()==paramCount && ca.getIdentifier().equals(className))return ca; + } + return null; + } + + /** + * Fügt eine Generische Typvariablen den Assumptions hinzu + * @param genericTypeVar + */ + public void addGenericVarAssumption( + GenericTypeVar genericTypeVar) { + this.genericVarAssumptions.add(new GenericVarAssumption(genericTypeVar)); + } + + public Menge getClassAssumptions() { + return this.classAssumptions; + } + + public ClassAssumption getClassAssumptionFor(RefType t){ + return this.getClass(t.get_Name()); + } + + public ClassAssumption getClass(String withName){ + for(ClassAssumption cA : this.getClassAssumptions()){ + RefType classType = cA.getAssumedClass().getType(); + if(classType.getName().equals(withName))return cA; + } + return null; + } + + /** + * Prüft einen Typ auf das vorhandensein in den BasicAssumptions. + * Dabei werden alle Konstruktoren nach diesem Typ durchsucht. Denn jede Klasse hat einen Konstruktor und der muss in den TypeAssumptions vorhanden sein. + * @param t + * @return + + public Type validateType(Type t){ + return null; + } + */ + +} + diff --git a/src/de/dhbwstuttgart/typeinference/exceptions/DebugException.java b/src/de/dhbwstuttgart/typeinference/exceptions/DebugException.java new file mode 100644 index 000000000..1f2e2775c --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/exceptions/DebugException.java @@ -0,0 +1,8 @@ +package de.dhbwstuttgart.typeinference.exceptions; + +public class DebugException extends RuntimeException { + + public DebugException(String message) { + System.err.print(message); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/exceptions/NotImplementedException.java b/src/de/dhbwstuttgart/typeinference/exceptions/NotImplementedException.java new file mode 100644 index 000000000..bf7e77797 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/exceptions/NotImplementedException.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.typeinference.exceptions; + +public class NotImplementedException extends RuntimeException { + + public NotImplementedException() { + } + + public NotImplementedException(String string) { + super(string); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/exceptions/ParserError.java b/src/de/dhbwstuttgart/typeinference/exceptions/ParserError.java new file mode 100644 index 000000000..535c576af --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/exceptions/ParserError.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.typeinference.exceptions; + +import de.dhbwstuttgart.parser.JavaParser.yyException; + + +public class ParserError extends TypeinferenceException{ + + public ParserError(yyException exc){ + super(exc.getMessage(), exc.token.getOffset()); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/exceptions/TypeinferenceException.java b/src/de/dhbwstuttgart/typeinference/exceptions/TypeinferenceException.java new file mode 100755 index 000000000..feaa287cc --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/exceptions/TypeinferenceException.java @@ -0,0 +1,46 @@ +package de.dhbwstuttgart.typeinference.exceptions; + +import de.dhbwstuttgart.core.IItemWithOffset; +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; + +/** + * Eine RuntimeException, welche bei einem Fehler während des Typinferenzalgorithmus ausgelöst wird. + * Dies wird zum Beispiel durch Programmierfehler in der Java-Eingabedatei ausgelöst. + * @author Andreas Stadelmeier, a10023 + * + */ +//TODO: Diese Klasse muss von Exception erben +public class TypeinferenceException extends RuntimeException { + + /** + * Das Offset im Quelltext bei dem das Problem aufgetaucht ist + */ + private int offset; + private String message; + + public TypeinferenceException(String message, SyntaxTreeNode problemSource) + { + super(message); + this.message=message; + if(problemSource == null)throw new DebugException("TypinferenzException ohne Offset: "+this.message); + this.offset=problemSource.getOffset(); + } + + public TypeinferenceException(String message, int offset){ + this.message=message; + this.offset = offset; + } + + /** + * + * @return Der Offset an dem im Quellcode der Fehler aufgetreten ist. + */ + public int getOffset(){ + return offset; + } + + public String getMessage(){ + return this.message; + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/typedeployment/GenericTypeInsertPoint.java b/src/de/dhbwstuttgart/typeinference/typedeployment/GenericTypeInsertPoint.java new file mode 100644 index 000000000..f1be21c47 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/typedeployment/GenericTypeInsertPoint.java @@ -0,0 +1,265 @@ +package de.dhbwstuttgart.typeinference.typedeployment; + +import java.util.Iterator; +import de.dhbwstuttgart.typeinference.Menge; + +import de.dhbwstuttgart.core.IItemWithOffset; +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.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.GenericTypeInsertable; +import de.dhbwstuttgart.typeinference.JavaCodeResult; +import de.dhbwstuttgart.typeinference.Pair; +import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.TypeInsertable; +import de.dhbwstuttgart.typeinference.exceptions.DebugException; + +/** + * Ein InsertPoint für Generische Variablen + * Wird beim Einsetzen eines TIP generiert. + * Steht für die Einsetzung aller Generischen Variablendeklarationen zugehörig zu einem Punkt in der SourceFile. + * @author janulrich + * + */ +public class GenericTypeInsertPoint extends SourcePatchPoint { + + + private GenericVarPatch patch; + private GenericTypeInsertable genericInsertPoint; + + public GenericTypeInsertPoint(GenericTypeInsertable syntaxTreeNode, + GenericVarPatch gtv ,ResultSet resultSet) { + this.resultSet = resultSet; + this.patch = gtv; + this.genericInsertPoint = syntaxTreeNode; + } + + /** + * Der TypeInsertString wird im Falle des GTIP von dem zugehörigen SyntaxTreeNode generiert. + * @return + */ + public String getTypeInsertString() { + String genericVar = this.patch.getInsertString(this.resultSet); + if(genericVar.length()==0)return ""; + return this.genericInsertPoint.getGenericVarDeclarationString(genericVar)+" "; + } + + @Override + public boolean equals(Object obj){ + if(obj instanceof GenericTypeInsertPoint)return super.equals(obj); + return false; + } + + @Override + public int compareTo(SourcePatchPoint arg0) { + int ret = super.compareTo(arg0); + if(ret == 0)ret = -666;//Hack der dazu führt, dass GTIP vor anderen InsertTypes eingesetzt werden. + return ret; + } + + @Override + public JavaCodeResult patch(String fileContent, int additionalOffset) { + JavaCodeResult ret = new JavaCodeResult(fileContent.substring(0, this.getOffset()+additionalOffset)); + JavaCodeResult mitte = new JavaCodeResult(this.getTypeInsertString()).attach(fileContent.substring(this.getOffset()+additionalOffset)); + ret.attach(mitte); + return ret; + } + + @Override + public int getOffset() { + return genericInsertPoint.getGenericVarDeclarationOffset(); + } + + @Override + public int getInsertLength() { + return this.getTypeInsertString().length(); + } + + @Override + public String toString(){ + return "GVIP: "+this.getTypeInsertString(); + } +} + +/** + * Eine Hilfsklasse zur Einsetzung einer Generischen Variable. + * @author janulrich + * + */ +class GenericVarPatch { + + private Menge genericVarExtendDeclarations = new Menge(); + private Menge genericVarDeclarations = new Menge(); + private Menge usedTPHs; + + /** + * Fügt eine generische Variable in Form eines Pairs an. + * @param p + */ + public void add(Pair p){ + GenericVarExtendsDeclarationPatch toAdd = new GenericVarExtendsDeclarationPatch(p); + boolean mussDeklariertWerden = true; + for(GenericVarDeclarationPatch patch : genericVarDeclarations){ + if(patch.genericVar.equals(p.TA2)){ + mussDeklariertWerden = false; + break; + } + } + if(!this.genericVarExtendDeclarations.contains(toAdd))this.genericVarExtendDeclarations.add(toAdd); + if(mussDeklariertWerden && p.TA2 instanceof TypePlaceholder)this.add((TypePlaceholder)p.TA2); + } + + public String getInsertString(ResultSet rs){ + //Alle Generische Einsetzungen verwerfen, welche nicht benötigt werden: + /* + * Dies geht mit der momentanen Variante nur für die genericVarDeclarations. + * Es kann passieren, dass bei den genericVarExtendDeclarations extend-Verknüpfungen enthalten sind, + * welche nicht im eingesetzten Typ auftauchen, aber dennoch notwendig sind. + */ + Menge tmpGenVars = new Menge<>(); + for(GenericVarDeclarationPatch gv : this.genericVarDeclarations){ + if(this.usedTPHs.contains(gv.genericVar)){ + tmpGenVars.add(gv); + } + } + this.genericVarDeclarations = tmpGenVars; + + //Hier sollten TPHs nicht aufgelöst sondern in Generische Variablen umgewandelt werden: + String ret = ""; + Iterator it1 = this.genericVarDeclarations.iterator(); + boolean bereitsVorhanden = false; + while(it1.hasNext()){ + bereitsVorhanden = false; + GenericVarDeclarationPatch p = it1.next(); + //Kontrollieren, ob GenericVar bereits von den Extends Declarations definiert wird: + for(GenericVarExtendsDeclarationPatch pe : this.genericVarExtendDeclarations){ + if(pe.definesGenericVar(p.genericVar)){ + bereitsVorhanden = true; + } + } + if(bereitsVorhanden == false){ + ret += p.getInsertString(rs); + if(it1.hasNext())ret += ", "; + } + } + if(this.genericVarExtendDeclarations.size()>0 && bereitsVorhanden == false)ret+=", "; + Iterator it2 = this.genericVarExtendDeclarations.iterator(); + while(it2.hasNext()){ + GenericVarExtendsDeclarationPatch p = it2.next(); + ret += p.getInsertString(rs); + if(it2.hasNext())ret += ", "; + } + return ret; + } + + public void add(TypePlaceholder tph) { + GenericVarDeclarationPatch toAdd = new GenericVarDeclarationPatch(tph); + if(!this.genericVarDeclarations.contains(toAdd))this.genericVarDeclarations.add(toAdd); + } + + public void addTPHs(Menge TPHs) { + for(TypePlaceholder tph: TPHs)this.add(tph); + } + + public void addPairs(Menge pairs) { + for(Pair pair : pairs)this.add(pair); + } + + public void removeUnusedTPHs(Menge usedTPHs) { + this.usedTPHs = usedTPHs; + return; + + } + + /* + for(TypePlaceholder tph : usedTPHs){ + //Zuerst alle extends Typen kontrollieren und entfernen: + for(GenericVarExtendsDeclarationPatch p : this.genericVarExtendDeclarations){ + if(p.definesGenericVar(tph))return; + } + } + */ +} + + +/** + * Eine Hilfsklasse zur Einsetzung einer Generischen Variable mit extend Bedingung. + * @author janulrich + * + */ +class GenericVarExtendsDeclarationPatch { + + private Pair genericPair; + + /** + * Kontrolliert ob der T1 mit tph übereinstimmt im Constraint: T1 extends T2 + * @param tph + * @return + */ + public boolean definesGenericVar(TypePlaceholder tph){ + if(genericPair.TA1.equals(tph))return true; + return false; + } + + public GenericVarExtendsDeclarationPatch(Pair p) { + this.genericPair = p; + } + + public String getInsertString(ResultSet resultSet){ + String ret = ""; + if(this.genericPair != null){ + ret += this.genericPair.TA1.printJavaCode(resultSet, false); + ret += " extends "; + ret += this.genericPair.TA2.printJavaCode(resultSet, false); + } + return ret; + } + + @Override + public boolean equals(Object o){ + if(!(o instanceof GenericVarExtendsDeclarationPatch))return false; + if(!(this.genericPair.equals(((GenericVarExtendsDeclarationPatch)o).genericPair)))return false; + return true; + } + + public String toString(){ + return this.genericPair.toString(); + } +} + +/** + * Eine Hilfsklasse zur Einsetzung einer Generischen Variable. + * @author janulrich + * + */ +class GenericVarDeclarationPatch { + + TypePlaceholder genericVar; + + public GenericVarDeclarationPatch(TypePlaceholder p) { + this.genericVar = p; + } + + public String getInsertString(ResultSet resultSet){ + String ret = ""; + if(this.genericVar != null){ + //ret += this.genericPair.printJavaCode(resultSet); + ret += this.genericVar.getName().toString(); + } + return ret; + } + + @Override + public boolean equals(Object o){ + if(!(o instanceof GenericVarDeclarationPatch))return false; + if(!(this.genericVar.equals(((GenericVarDeclarationPatch)o).genericVar)))return false; + return true; + } + + @Override + public String toString(){ + return genericVar.toString(); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/typedeployment/SourcePatchPoint.java b/src/de/dhbwstuttgart/typeinference/typedeployment/SourcePatchPoint.java new file mode 100644 index 000000000..75c69b019 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/typedeployment/SourcePatchPoint.java @@ -0,0 +1,22 @@ +package de.dhbwstuttgart.typeinference.typedeployment; + +import de.dhbwstuttgart.typeinference.JavaCodeResult; +import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.TypeInsertable; + +public abstract class SourcePatchPoint implements Comparable{ + protected ResultSet resultSet; + public abstract int getOffset(); + public ResultSet getResultSet() { + return resultSet; + } + + @Override + public int compareTo(SourcePatchPoint arg0) { + return new Integer(this.getOffset()).compareTo(new Integer(arg0.getOffset())); + } + public abstract JavaCodeResult patch(String fileContent, int additionalOffset); + + public abstract int getInsertLength(); + +} diff --git a/src/de/dhbwstuttgart/typeinference/typedeployment/TypeInsertPoint.java b/src/de/dhbwstuttgart/typeinference/typedeployment/TypeInsertPoint.java new file mode 100644 index 000000000..6540249be --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/typedeployment/TypeInsertPoint.java @@ -0,0 +1,125 @@ +package de.dhbwstuttgart.typeinference.typedeployment; + +import de.dhbwstuttgart.typeinference.Menge; + +import de.dhbwstuttgart.core.IItemWithOffset; +import de.dhbwstuttgart.syntaxtree.Class; +import de.dhbwstuttgart.syntaxtree.Field; +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.typeinference.GenericTypeInsertable; +import de.dhbwstuttgart.typeinference.JavaCodeResult; +import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.TypeInsertable; +import de.dhbwstuttgart.typeinference.exceptions.DebugException; + +/** + * Stellt eine Einsetzungsmöglichkeit für einen Typ an einem (Typeable)Punkt im Syntaxbaum dar. + * Mehrere TypeInsertPoint's werden in einem TypInsertSet zusammengefasst. + * @author janulrich + * + */ +public class TypeInsertPoint extends SourcePatchPoint { + + public Type type; + private TypeInsertable point; + private SyntaxTreeNode node; + + /** + * Dieser Konstruktor erstellt einen TypInsertPoint + * @param insertPoint + * @param insertNode - muss das gleiche sein wie "insertPoint" + * @param insertType - der einzusetzende Typ + * @param resultSet + * @param generics - die generischen Parameter des einzusetzenden Typs + */ + public TypeInsertPoint(TypeInsertable insertPoint, SyntaxTreeNode insertNode, Type insertType, ResultSet resultSet){ + this.point = insertPoint; + this.type = insertType; + this.resultSet = resultSet; + this.node = insertNode; + } + + /** + * Setzt den Typ dieses TypeInsertPoint in den übergebenen Quelltext ein. + * @param fileContent - der Quelltext + * @param additionalOffset - Falls mehrere Typen in einen Quellcode eingesetzet werden muss die Verschiebung der Offsets mit einbezogen werden. + * @return + */ + public JavaCodeResult patch(String fileContent, int additionalOffset) { + String anfang = fileContent.substring(0, this.getInsertPoint().getOffset()+additionalOffset); + JavaCodeResult mitte = this.getTypeInsertString(); + String ende = fileContent.substring(this.getInsertPoint().getOffset()+additionalOffset); + return new JavaCodeResult(anfang).attach(mitte).attach(ende); + } + + public int getInsertLength() { + return this.getTypeInsertString().toString().length(); + } + + /** + * + * @return Der Offset des TypeInsertPoints in dem geparsten Source für dessen Klasse er erstellt wurde. + */ + public int getOffset(){ + return this.getInsertPoint().getOffset(); + } + + protected Type getInsertType(){ + return this.type; + } + + /** + * Die Zeichenkette die durch diesen TypeInsertPoint eingesetzt wird. (Der Typ als String) + * @return + */ + public JavaCodeResult getTypeInsertString(){ + JavaCodeResult ret = this.getInsertType().printJavaCode(this.resultSet).attach(" "); + return ret; + } + + /** + * @return - Der Punkt (Knoten) im Syntaxbaum, für den dieser TypeInsertPoint gilt. + */ + public IItemWithOffset getInsertPoint(){ + return this.point; + } + + public SyntaxTreeNode getInsertNode(){ + return this.node; + } + + @Override + public boolean equals(Object obj){ + if(! (obj instanceof TypeInsertPoint))return false; + TypeInsertPoint equals = (TypeInsertPoint) obj; + if(!(equals.getInsertPoint().equals(this.getInsertPoint())))return false; + if(!(equals.getResultSet().equals(this.getResultSet())))return false; + if(!(equals.getInsertType().equals(this.getInsertType())))return false; + + return true; + } + + + + public GenericTypeInsertable getGenericTypeVarInsertNode() { + SyntaxTreeNode ret = (SyntaxTreeNode)this.getTIP(); + while(!(ret instanceof Field || ret instanceof Class)){ + ret = ret.getParent(); + if(ret == null){ + throw new DebugException(this.getInsertPoint().toString()+" hat kein Feld oder Klasse als Elternelement"); + } + } + return (GenericTypeInsertable) ret; + } + + private TypeInsertable getTIP() { + return this.point; + } + + @Override + public String toString(){ + return "TIP: "+this.type; + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/typedeployment/TypeInsertSet.java b/src/de/dhbwstuttgart/typeinference/typedeployment/TypeInsertSet.java new file mode 100644 index 000000000..2e02352f5 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/typedeployment/TypeInsertSet.java @@ -0,0 +1,264 @@ +package de.dhbwstuttgart.typeinference.typedeployment; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import de.dhbwstuttgart.typeinference.Menge; + +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.core.IItemWithOffset; +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.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.JavaCodeResult; +import de.dhbwstuttgart.typeinference.Pair; +import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.TypeInsertable; + +/** + * Bündelt ein Set von TypeInsertPoints, welche zu einem TypeInferenceResultSet gehören. + * Das TypeInsertSet löst zudem Abhängigkeiten auf. Wird eine Generische Variable eingesetzt, + * müssen alle mit ihr in Verbindung stehenden Typen ebenfalls eingesetzt werden. + * @author janulrich + * + */ +public class TypeInsertSet { + //Logger: + protected Logger typinferenzLog = Logger.getLogger("Typeinference"); + + public Menge points = new Menge(); + private ResultSet resultSet; + + public TypeInsertSet(ResultSet resultSet) { + this.resultSet = resultSet; + } + + /** + * Fügt einen TypeInsertPoint dem TypeInsertSet hinzu. + * @param typeInsertPoint + * @return + */ + public void add(TypeInsertPoint typeInsertPoint) { + if( typeInsertPoint!=null && ! this.points.contains(typeInsertPoint)){ //Nur falls typeInsertPoint noch nicht im Set vorhanden ist: + points.add(typeInsertPoint); + } + } + + /** + * Fügt nur einen einzelnen TypeInsertPoint in fileContent ein. + * @param tip + * @param fileContent + * @return + */ + public String insertType(TypeInsertPoint tip, String fileContent){ + TypePatchJob tpj = new TypePatchJob(); + this.insertType(tip, tpj); + return tpj.run(fileContent); + } + + /** + * Fügt einen einzelnen TypeInsertPoint einem TypePatchJob hinzu + * @param tip + * @param tpj + */ + private void insertType(TypeInsertPoint tip, TypePatchJob tpj){ + /* + * Ablauf: + * 1. Alle TypePlaceholder im einzusetzenden Typ ermitteln. + * 2. Alle Constraints die mit diesen TPHs zusammenhängen ermitteln (Das kann möglicherweise wegfallen) + * 3. Alle TPHs, aus Schritt 1 und 2 zusammenfügen. + * 4. Kontrollieren, welche TPHs in dem InsertKontext noch nicht bekannt sind. + * 5. Alle Unbekannten TPHs herausfiltern (von den Pairs nur TA2) + * 6. Alle unbekannten TPHs + Pairs als GenericTypeInsertPoint deklarieren. + */ + GenericVarPatch gPatch = new GenericVarPatch();//Set der Einzusetzenden generischen Variablendeklarationen + //Schritt 1: + Menge involvedTPHs = tip.getInsertType().getInvolvedTypePlaceholder();//.getInvolvedTypePlaceholder(); + + //Schritt 2: + Menge pairs = new Menge<>(); + for(Pair pair : this.resultSet.getConstraintsFor(involvedTPHs)){ + //gPatch.add(pair); //Schritt 6 (Teil 2) + pairs.add(pair); + } + + //Schritt 3: + Menge allTPHs = new Menge<>(); + for(TypePlaceholder tph : involvedTPHs){ + if(!allTPHs.contains(tph)){ + allTPHs.add(tph); + } + } + for(Pair pair : pairs) + for(TypePlaceholder tph : pair.getTypePlaceholder()){ + if(!allTPHs.contains(tph)){ + allTPHs.add(tph); + } + } + //TODO: Schritt 4 (Es wird nicht kontrolliert, ob der TPH in dem Kontext schon bekannt ist) + + + /* + // und Schritt 5: (Es werden nur die TPHs übernommen, welche noch nicht in den involvedTPHs vorkommen) + for(Pair pair : pairs)for(Type t : pair.getTypes())for(TypePlaceholder tph : t.getInvolvedTypePlaceholder()){ + if(!allTPHs.contains(tph)){ + allTPHs.add(tph); + } + } + */ + + gPatch.addPairs(pairs); + gPatch.addTPHs(allTPHs); + + /* + //TODO: Nur die TPH aus den Paaren entnehmen und Generische Variablen bilden + //Kontrollieren ob alle in den Paaren vorhandenen Generischen Variablen in dem Bereich vorkommen: + for(Pair pair : pairs){ + if(! tip.getInsertNode().seesType(pair.TA2)){ + for(TypePlaceholder tph : pair.getTypePlaceholder()){ + if(! pairsDeclareTPH(pairs, tph)){ + gPatch.add(tph); + } + } + } + } + */ + + //Nur Generische Variablen einsetzen, welche auch verwendet werden: + gPatch.removeUnusedTPHs(tip.getInsertType().getInvolvedTypePlaceholder()); + + GenericTypeInsertPoint gip = new GenericTypeInsertPoint(tip.getGenericTypeVarInsertNode(), gPatch, resultSet); + typinferenzLog.debug("Erstellter GenericTypeInsertPoint: "+gip, Section.TYPEINFERENCE); + tpj.add(tip); + tpj.add(gip); + } + + private boolean pairsDeclareTPH(Menge ps, TypePlaceholder tph){ + for(Pair p : ps){ + if(p.TA1.equals(tph))return true; + } + return false; + } + + /** + * Fügt alle Typen dieses TypeInsertSets in den übergebenen Quellcode ein + * @param fileContent + * @return + */ + @Deprecated + public String insertAllTypes(String fileContent) { + TypePatchJob tpj = new TypePatchJob(); + for(TypeInsertPoint tip : this.points){ + this.insertType(tip, tpj); + } + return tpj.run(fileContent); + } + + /** + * + * @param node + * @return - null, falls kein InsertPoint für node vorhanden. + */ + public TypeInsertPoint getInsertPointFor(TypeInsertable node){ + for(TypeInsertPoint point : points){ + if(point.getInsertPoint().equals(node))return point; + } + return null; + } + + @Override + public boolean equals(Object obj){ + if(! (obj instanceof TypeInsertSet))return false; + TypeInsertSet equals = (TypeInsertSet) obj; + if(points.size()!=equals.points.size())return false; + + for(TypeInsertPoint point : points){ + //Jeder TypeInsertPoint muss auch in equals vorkommen: + if(!equals.points.contains(point)) + return false; + //... aber nicht öfter als 1x : + if(equals.points.lastIndexOf(point)!=equals.points.indexOf(point))return false; + } + return true; + } + + /** + * Fügt TypeInsertPoints an + * @param insertPoints + */ + public void add(Menge insertPoints) { + for(TypeInsertPoint p : insertPoints){ + this.add(p); + } + } + + @Override + public String toString(){ + return this.points.toString(); + } + +} + +/** + * Stellt eine Reihe von TypeInsertions dar + */ +class TypePatchJob{ + private Menge points = new Menge<>(); + void add(SourcePatchPoint tip){ + points.add(tip); + } + String run(String fileContent){ + //sortieren (nach dem Offset der InsertPoints): + Collections.sort(points); + int additionalOffset = 0; + for(SourcePatchPoint p : points){ + //Zuerst den Typ einsetzen + JavaCodeResult insertCode = p.patch(fileContent, additionalOffset); + fileContent = insertCode.toString(); + //Dann Additional Offset korrigieren: + additionalOffset += p.getInsertLength(); + } + return fileContent; + } +} + +class TypedJavaSource{ + public TypedJavaSource(String source, int offset){ + + } + + public void addInsert(GenericVarInsert genericVar, int offset){ + + } + + public void addInsert(VarInsert var, int offset){ + + } +} + +class VarInsert{ + public VarInsert(String var){ + + } +} + +class GenericVarInsert{ + public GenericVarInsert(String varName){ + + } +} + +class GenericVarExtendsInsert extends GenericVarInsert{ + public GenericVarExtendsInsert(String varName, String extendsVarName){ + super(varName); + } +} + +class GenericVarSuperInsert extends GenericVarInsert{ + public GenericVarSuperInsert(String varName, String superVarName){ + super(varName); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/GuavaSetOperations.java b/src/de/dhbwstuttgart/typeinference/unify/GuavaSetOperations.java new file mode 100644 index 000000000..b51fb648f --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/GuavaSetOperations.java @@ -0,0 +1,23 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.List; +import java.util.Set; + +import com.google.common.collect.Sets; + +import de.dhbwstuttgart.typeinference.unify.interfaces.ISetOperations; + +/** + * Implements set operations using google guava. + * @author DH10STF + * + */ +public class GuavaSetOperations implements ISetOperations { + + @Override + public Set> cartesianProduct(List> sets) { + // Wraps the call to google guava + return Sets.cartesianProduct(sets); + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/Mapping.java b/src/de/dhbwstuttgart/typeinference/unify/Mapping.java new file mode 100644 index 000000000..b6ec1e34f --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/Mapping.java @@ -0,0 +1,72 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.Pair; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; + +public class Mapping { + + private HashMap backwardMap = new HashMap<>(); + private HashMap forwardMap = new HashMap<>(); + private Set irreversible = new HashSet<>(); + + public Mapping(Set types) { + for(de.dhbwstuttgart.syntaxtree.type.Type t : types) { + } + } + + public de.dhbwstuttgart.typeinference.unify.model.UnifyType map(de.dhbwstuttgart.syntaxtree.type.Type type) { + return forwardMap.get(type); + } + + public de.dhbwstuttgart.typeinference.unify.model.UnifyPair map(de.dhbwstuttgart.typeinference.Pair pair) { + return new de.dhbwstuttgart.typeinference.unify.model.UnifyPair(forwardMap.get(pair.TA1), forwardMap.get(pair.TA2), mapOp(pair.GetOperator())); + } + + public Set mapTypeSet(Set types) { + return types.stream().map(this::map).collect(Collectors.toCollection(HashSet::new)); + } + + public Set mapPairSet(Set pairs) { + return pairs.stream().map(this::map).collect(Collectors.toCollection(HashSet::new)); + } + + public Optional unmap(de.dhbwstuttgart.typeinference.unify.model.UnifyType type) { + return irreversible.contains(type) ? Optional.of(backwardMap.get(type)) : Optional.empty(); + } + + public Optional unmap(de.dhbwstuttgart.typeinference.unify.model.UnifyPair mpair) { + de.dhbwstuttgart.typeinference.unify.model.UnifyType lhs = mpair.getLhsType(); + de.dhbwstuttgart.typeinference.unify.model.UnifyType rhs = mpair.getRhsType(); + + if(irreversible.contains(lhs) || irreversible.contains(rhs)) + return Optional.empty(); + return Optional.of(new Pair(backwardMap.get(lhs), backwardMap.get(rhs), unmapOp(mpair.getPairOp()))); + } + + public Optional> unmapTypeSet(Set types) { + Set result = types.stream().map(this::unmap).filter(x -> x.isPresent()).map(x -> x.get()).collect(Collectors.toCollection(HashSet::new)); + return result.size() == types.size() ? Optional.of(result) : Optional.empty(); + } + + public Optional> unmapPairSet(Set pairs) { + Set result = pairs.stream().map(this::unmap).filter(x -> x.isPresent()).map(x -> x.get()).collect(Collectors.toCollection(HashSet::new)); + return result.size() == pairs.size() ? Optional.of(result) : Optional.empty(); + } + + private PairOperator mapOp(PairOperator op) { + //TODO: Methode kann entfernt werden: + return op; + } + + private PairOperator unmapOp(PairOperator op) { + //TODO: Methode kann entfernt werden: + return op; + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java b/src/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java new file mode 100644 index 000000000..1c75ea99e --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java @@ -0,0 +1,107 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.TypeParams; +import de.dhbwstuttgart.typeinference.unify.model.Unifier; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; + +/** + * Implementation of the Martelli-Montanari unification algorithm. + * @author Florian Steurer + */ +public class MartelliMontanariUnify implements IUnify { + + @Override + public Optional unify(Set terms) { + // Sets with less than 2 terms are trivially unified + if(terms.size() < 2) + return Optional.of(Unifier.identity()); + + // For the the set of terms {t1,...,tn}, + // build a list of equations {(t1 = t2), (t2 = t3), (t3 = t4), ....} + ArrayList termsList = new ArrayList(); + Iterator iter = terms.iterator(); + UnifyType prev = iter.next(); + while(iter.hasNext()) { + UnifyType next = iter.next(); + termsList.add(new UnifyPair(prev, next, PairOperator.EQUALSDOT)); + prev = next; + } + + // Start with the identity unifier. Substitutions will be added later. + Unifier mgu = Unifier.identity(); + + // Apply rules while possible + int idx = 0; + while(idx < termsList.size()) { + UnifyPair pair = termsList.get(idx); + UnifyType rhsType = pair.getRhsType(); + UnifyType lhsType = pair.getLhsType(); + TypeParams rhsTypeParams = rhsType.getTypeParams(); + TypeParams lhsTypeParams = lhsType.getTypeParams(); + + // REDUCE - Rule + if(!(rhsType instanceof PlaceholderType) && !(lhsType instanceof PlaceholderType)) { + Set result = new HashSet<>(); + + // f<...> = g<...> with f != g are not unifiable + if(!rhsType.getName().equals(lhsType.getName())) + return Optional.empty(); // conflict + // f = f are not unifiable + if(rhsTypeParams.size() != lhsTypeParams.size()) + return Optional.empty(); // conflict + // f = g is not unifiable (cannot be f = f because erase rule would have been applied) + //if(rhsTypeParams.size() == 0) + //return Optional.empty(); + + // Unpack the arguments + for(int i = 0; i < rhsTypeParams.size(); i++) + result.add(new UnifyPair(rhsTypeParams.get(i), lhsTypeParams.get(i), PairOperator.EQUALSDOT)); + + termsList.remove(idx); + termsList.addAll(result); + continue; + } + + // DELETE - Rule + if(pair.getRhsType().equals(pair.getLhsType())) { + termsList.remove(idx); + continue; + } + + // SWAP - Rule + if(!(lhsType instanceof PlaceholderType) && (rhsType instanceof PlaceholderType)) { + termsList.remove(idx); + termsList.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT)); + continue; + } + + // OCCURS-CHECK + if(pair.getLhsType() instanceof PlaceholderType + && pair.getRhsType().getTypeParams().occurs((PlaceholderType) pair.getLhsType())) + return Optional.empty(); + + // SUBST - Rule + if(lhsType instanceof PlaceholderType) { + mgu.add((PlaceholderType) lhsType, rhsType); + termsList = termsList.stream().map(mgu::apply).collect(Collectors.toCollection(ArrayList::new)); + idx = idx+1 == termsList.size() ? 0 : idx+1; + continue; + } + + idx++; + } + + return Optional.of(mgu); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java b/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java new file mode 100644 index 000000000..85f7a6d0e --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java @@ -0,0 +1,833 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Optional; +import java.util.Queue; +import java.util.Set; +import java.util.Stack; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.exceptions.DebugException; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet; +import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +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.Unifier; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; +import de.dhbwstuttgart.typeinference.unify.model.WildcardType; + +/** + * Implementation of the type inference rules. + * @author Florian Steurer + * + */ +public class RuleSet implements IRuleSet{ + + @Override + public Optional reduceUp(UnifyPair pair) { + // Check if reduce up is applicable + if(pair.getPairOp() != PairOperator.SMALLERDOT) + return Optional.empty(); + + UnifyType rhsType = pair.getRhsType(); + if(!(rhsType instanceof SuperType)) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + if(!(lhsType instanceof ReferenceType) && !(lhsType instanceof PlaceholderType)) + return Optional.empty(); + + // Rule is applicable, unpack the SuperType + return Optional.of(new UnifyPair(lhsType, ((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT)); + } + + @Override + public Optional reduceLow(UnifyPair pair) { + // Check if rule is applicable + if(pair.getPairOp() != PairOperator.SMALLERDOT) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + if(!(lhsType instanceof ExtendsType)) + return Optional.empty(); + + UnifyType rhsType = pair.getRhsType(); + if(!(rhsType instanceof ReferenceType) && !(rhsType instanceof PlaceholderType)) + return Optional.empty(); + + // Rule is applicable, unpack the ExtendsType + return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), rhsType, PairOperator.SMALLERDOT)); + } + + @Override + public Optional reduceUpLow(UnifyPair pair) { + // Check if rule is applicable + if(pair.getPairOp() != PairOperator.SMALLERDOT) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + if(!(lhsType instanceof ExtendsType)) + return Optional.empty(); + + UnifyType rhsType = pair.getRhsType(); + if(!(rhsType instanceof SuperType)) + return Optional.empty(); + + // Rule is applicable, unpack both sides + return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(),((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT)); + } + + @Override + public Optional> reduceExt(UnifyPair pair, IFiniteClosure fc) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType x = pair.getLhsType(); + UnifyType sTypeX; + + if(x instanceof ReferenceType) + sTypeX = x; + else if(x instanceof ExtendsType) + sTypeX = ((ExtendsType) x).getExtendedType(); + else + return Optional.empty(); + + UnifyType extY = pair.getRhsType(); + + if(!(extY instanceof ExtendsType)) + return Optional.empty(); + + if(x.getTypeParams().empty() || extY.getTypeParams().size() != x.getTypeParams().size()) + return Optional.empty(); + + UnifyType xFromFc = fc.getLeftHandedType(sTypeX.getName()).orElse(null); + + if(xFromFc == null || !xFromFc.getTypeParams().arePlaceholders()) + return Optional.empty(); + + if(x instanceof ExtendsType) + xFromFc = new ExtendsType(xFromFc); + + UnifyType extYFromFc = fc.grArg(xFromFc).stream().filter(t -> t.getName().equals(extY.getName())).filter(t -> t.getTypeParams().arePlaceholders()).findAny().orElse(null); + + if(extYFromFc == null || extYFromFc.getTypeParams() != xFromFc.getTypeParams()) + return Optional.empty(); + + TypeParams extYParams = extY.getTypeParams(); + TypeParams xParams = x.getTypeParams(); + + int[] pi = pi(xParams, extYParams); + + if(pi.length == 0) + return Optional.empty(); + + Set result = new HashSet<>(); + + for(int rhsIdx = 0; rhsIdx < extYParams.size(); rhsIdx++) + result.add(new UnifyPair(xParams.get(pi[rhsIdx]), extYParams.get(rhsIdx), PairOperator.SMALLERDOTWC)); + + return Optional.of(result); + } + + @Override + public Optional> reduceSup(UnifyPair pair, IFiniteClosure fc) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType x = pair.getLhsType(); + UnifyType sTypeX; + + if(x instanceof ReferenceType) + sTypeX = x; + else if(x instanceof SuperType) + sTypeX = ((SuperType) x).getSuperedType(); + else + return Optional.empty(); + + UnifyType supY = pair.getRhsType(); + + if(!(supY instanceof SuperType)) + return Optional.empty(); + + if(x.getTypeParams().empty() || supY.getTypeParams().size() != x.getTypeParams().size()) + return Optional.empty(); + + UnifyType xFromFc = fc.getLeftHandedType(sTypeX.getName()).orElse(null); + + if(xFromFc == null || !xFromFc.getTypeParams().arePlaceholders()) + return Optional.empty(); + + if(x instanceof SuperType) + xFromFc = new SuperType(xFromFc); + + UnifyType supYFromFc = fc.grArg(xFromFc).stream().filter(t -> t.getName().equals(supY.getName())).filter(t -> t.getTypeParams().arePlaceholders()).findAny().orElse(null); + + if(supYFromFc == null || supYFromFc.getTypeParams() != xFromFc.getTypeParams()) + return Optional.empty(); + + TypeParams supYParams = supY.getTypeParams(); + TypeParams xParams = x.getTypeParams(); + Set result = new HashSet<>(); + + int[] pi = pi(xParams, supYParams); + + if(pi.length == 0) + return Optional.empty(); + + for(int rhsIdx = 0; rhsIdx < supYParams.size(); rhsIdx++) + result.add(new UnifyPair(supYParams.get(rhsIdx), xParams.get(pi[rhsIdx]), PairOperator.SMALLERDOTWC)); + + return Optional.of(result); + } + + @Override + public Optional> reduceEq(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + if(lhsType instanceof PlaceholderType || lhsType.getTypeParams().empty()) + return Optional.empty(); + + UnifyType rhsType = pair.getRhsType(); + + if(!rhsType.getName().equals(lhsType.getName())) + return Optional.empty(); + + if(rhsType instanceof PlaceholderType || lhsType instanceof PlaceholderType || rhsType.getTypeParams().empty()) + return Optional.empty(); + + if(rhsType.getTypeParams().size() != lhsType.getTypeParams().size()) + return Optional.empty(); + + // Keine Permutation wie im Paper nötig + Set result = new HashSet<>(); + TypeParams lhsTypeParams = lhsType.getTypeParams(); + TypeParams rhsTypeParams = rhsType.getTypeParams(); + + for(int i = 0; i < lhsTypeParams.size(); i++) + result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT)); + + return Optional.of(result); + } + + @Override + public Optional> reduce1(UnifyPair pair, IFiniteClosure fc) { + if(pair.getPairOp() != PairOperator.SMALLERDOT) + return Optional.empty(); + + UnifyType c = pair.getLhsType(); + if(!(c instanceof ReferenceType)) + return Optional.empty(); + + UnifyType d = pair.getRhsType(); + if(!(d instanceof ReferenceType)) + return Optional.empty(); + + ReferenceType lhsSType = (ReferenceType) c; + ReferenceType rhsSType = (ReferenceType) d; + + if(lhsSType.getTypeParams().empty() || lhsSType.getTypeParams().size() != rhsSType.getTypeParams().size()) + return Optional.empty(); + + UnifyType cFromFc = fc.getLeftHandedType(c.getName()).orElse(null); + + if(cFromFc == null || !cFromFc.getTypeParams().arePlaceholders()) + return Optional.empty(); + + UnifyType dFromFc = fc.getAncestors(cFromFc).stream().filter(x -> x.getName().equals(d.getName())).findAny().orElse(null); + + if(dFromFc == null || !dFromFc.getTypeParams().arePlaceholders() || dFromFc.getTypeParams().size() != cFromFc.getTypeParams().size()) + return Optional.empty(); + + int[] pi = pi(cFromFc.getTypeParams(), dFromFc.getTypeParams()); + + if(pi.length == 0) + return Optional.empty(); + + TypeParams rhsTypeParams = d.getTypeParams(); + TypeParams lhsTypeParams = c.getTypeParams(); + Set result = new HashSet<>(); + + for(int rhsIdx = 0; rhsIdx < rhsTypeParams.size(); rhsIdx++) + result.add(new UnifyPair(lhsTypeParams.get(pi[rhsIdx]), rhsTypeParams.get(rhsIdx), PairOperator.SMALLERDOTWC)); + + return Optional.of(result); + } + + @Override + public Optional> reduce2(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.EQUALSDOT) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + ReferenceType lhsSType; + + if(lhsType instanceof ReferenceType) + lhsSType = (ReferenceType) lhsType; + else if(lhsType instanceof WildcardType) { + UnifyType lhsSTypeRaw = ((WildcardType) lhsType).getWildcardedType(); + if(lhsSTypeRaw instanceof ReferenceType) + lhsSType = (ReferenceType) lhsSTypeRaw; + else + return Optional.empty(); + } + else + return Optional.empty(); + + if(lhsSType.getTypeParams().empty()) + return Optional.empty(); + + UnifyType rhsType = pair.getRhsType(); + ReferenceType rhsSType; + + if(rhsType instanceof ReferenceType) + rhsSType = (ReferenceType) rhsType; + else if(rhsType instanceof WildcardType) { + UnifyType rhsSTypeRaw = ((WildcardType) rhsType).getWildcardedType(); + if(rhsSTypeRaw instanceof ReferenceType) + rhsSType = (ReferenceType) rhsSTypeRaw; + else + return Optional.empty(); + } + else + return Optional.empty(); + + if(!rhsSType.getName().equals(lhsSType.getName())) + return Optional.empty(); + + if(!(lhsSType.getTypeParams().size()==rhsSType.getTypeParams().size()))throw new DebugException("Fehler in Unifizierung"); + //if(rhsSType.getTypeParams().size() != lhsSType.getTypeParams().size()) + // return Optional.empty(); + + Set result = new HashSet<>(); + + TypeParams rhsTypeParams = rhsSType.getTypeParams(); + TypeParams lhsTypeParams = lhsSType.getTypeParams(); + for(int i = 0; i < rhsTypeParams.size(); i++) + result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT)); + + return Optional.of(result); + } + + @Override + public boolean erase1(UnifyPair pair, IFiniteClosure fc) { + if(pair.getPairOp() != PairOperator.SMALLERDOT) + return false; + + UnifyType lhsType = pair.getLhsType(); + if(!(lhsType instanceof ReferenceType) && !(lhsType instanceof PlaceholderType)) + return false; + + UnifyType rhsType = pair.getRhsType(); + if(!(rhsType instanceof ReferenceType) && !(rhsType instanceof PlaceholderType)) + return false; + + return fc.greater(lhsType).contains(rhsType); + } + + @Override + public boolean erase2(UnifyPair pair, IFiniteClosure fc) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return false; + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + + return fc.grArg(lhsType).contains(rhsType); + } + + @Override + public boolean erase3(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.EQUALSDOT) + return false; + + return pair.getLhsType().equals(pair.getRhsType()); + } + + @Override + public Optional swap(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.EQUALSDOT) + return Optional.empty(); + + if(pair.getLhsType() instanceof PlaceholderType) + return Optional.empty(); + + if(!(pair.getRhsType() instanceof PlaceholderType)) + return Optional.empty(); + + return Optional.of(new UnifyPair(pair.getRhsType(), pair.getLhsType(), PairOperator.EQUALSDOT)); + } + + @Override + public Optional adapt(UnifyPair pair, IFiniteClosure fc) { + if(pair.getPairOp() != PairOperator.SMALLERDOT) + return Optional.empty(); + + UnifyType typeD = pair.getLhsType(); + if(!(typeD instanceof ReferenceType)) + return Optional.empty(); + + UnifyType typeDs = pair.getRhsType(); + if(!(typeDs instanceof ReferenceType)) + return Optional.empty(); + + /*if(typeD.getTypeParams().size() == 0 || typeDs.getTypeParams().size() == 0) + return Optional.empty();*/ + + if(typeD.getName().equals(typeDs.getName())) + return Optional.empty(); + + + Optional opt = fc.getLeftHandedType(typeD.getName()); + if(!opt.isPresent()) + return Optional.empty(); + + // The generic Version of Type D (D) + UnifyType typeDgen = opt.get(); + + // Actually greater+ because the types are ensured to have different names + Set greater = fc.getAncestors(typeDgen); + opt = greater.stream().filter(x -> x.getName().equals(typeDs.getName())).findAny(); + + if(!opt.isPresent()) + return Optional.empty(); + + UnifyType newLhs = opt.get(); + + TypeParams typeDParams = typeD.getTypeParams(); + TypeParams typeDgenParams = typeDgen.getTypeParams(); + + Unifier unif = Unifier.identity(); + for(int i = 0; i < typeDParams.size(); i++) + unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i)); + + return Optional.of(new UnifyPair(unif.apply(newLhs), typeDs, PairOperator.SMALLERDOT)); + } + + @Override + public Optional adaptExt(UnifyPair pair, IFiniteClosure fc) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType typeD = pair.getLhsType(); + if(!(typeD instanceof ReferenceType) && !(typeD instanceof ExtendsType)) + return Optional.empty(); + + UnifyType typeExtDs = pair.getRhsType(); + if(!(typeExtDs instanceof ExtendsType)) + return Optional.empty(); + + if(typeD.getTypeParams().size() == 0 || typeExtDs.getTypeParams().size() == 0) + return Optional.empty(); + + UnifyType typeDgen; + if(typeD instanceof ReferenceType) + typeDgen = fc.getLeftHandedType(typeD.getName()).orElse(null); + else { + Optional opt = fc.getLeftHandedType(((ExtendsType) typeD).getExtendedType().getName()); + typeDgen = opt.isPresent() ? new ExtendsType(opt.get()) : null; + } + + if(typeDgen == null) + return Optional.empty(); + + Set grArg = fc.grArg(typeDgen); + + Optional opt = grArg.stream().filter(x -> x.getName().equals(typeExtDs.getName())).findAny(); + + if(!opt.isPresent()) + return Optional.empty(); + + UnifyType newLhs = ((ExtendsType) opt.get()).getExtendedType(); + + TypeParams typeDParams = typeD.getTypeParams(); + TypeParams typeDgenParams = typeDgen.getTypeParams(); + + Unifier unif = new Unifier((PlaceholderType) typeDgenParams.get(0), typeDParams.get(0)); + for(int i = 1; i < typeDParams.size(); i++) + unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i)); + + return Optional.of(new UnifyPair(unif.apply(newLhs), typeExtDs, PairOperator.SMALLERDOTWC)); + } + + @Override + public Optional adaptSup(UnifyPair pair, IFiniteClosure fc) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType typeDs = pair.getLhsType(); + if(!(typeDs instanceof ReferenceType) && !(typeDs instanceof SuperType)) + return Optional.empty(); + + UnifyType typeSupD = pair.getRhsType(); + if(!(typeSupD instanceof SuperType)) + return Optional.empty(); + + if(typeDs.getTypeParams().size() == 0 || typeSupD.getTypeParams().size() == 0) + return Optional.empty(); + + + Optional opt = fc.getLeftHandedType(((SuperType) typeSupD).getSuperedType().getName()); + + if(!opt.isPresent()) + return Optional.empty(); + + UnifyType typeDgen = opt.get(); + UnifyType typeSupDgen = new SuperType(typeDgen); + + // Use of smArg instead of grArg because + // a in grArg(b) => b in smArg(a) + Set smArg = fc.smArg(typeSupDgen); + opt = smArg.stream().filter(x -> x.getName().equals(typeDs.getName())).findAny(); + + if(!opt.isPresent()) + return Optional.empty(); + + // New RHS + UnifyType newRhs = null; + if(typeDs instanceof ReferenceType) + newRhs = new ExtendsType(typeDs); + else + newRhs = new ExtendsType(((SuperType) typeDs).getSuperedType()); + + // New LHS + UnifyType newLhs = opt.get(); + TypeParams typeDParams = typeSupD.getTypeParams(); + TypeParams typeSupDsgenParams = typeSupDgen.getTypeParams(); + + Unifier unif = new Unifier((PlaceholderType) typeSupDsgenParams.get(0), typeDParams.get(0)); + for(int i = 1; i < typeDParams.size(); i++) + unif.add((PlaceholderType) typeSupDsgenParams.get(i), typeDParams.get(i)); + + return Optional.of(new UnifyPair(unif.apply(newLhs), newRhs, PairOperator.SMALLERDOTWC)); + } + + /** + * Finds the permutation pi of the type arguments of two types based on the finite closure + * @param C The type which arguments are permuted + * @param D The other type + * @return An array containing the values of pi for every type argument of C or an empty array if the search failed. + */ + private int[] pi(TypeParams cArgs, TypeParams dArgs) { + if(!(cArgs.size()==dArgs.size()))throw new DebugException("Fehler in Unifizierung"); + + int[] permutation = new int[dArgs.size()]; + + boolean succ = true; + for (int dArgIdx = 0; dArgIdx < dArgs.size() && succ; dArgIdx++) { + UnifyType dArg = dArgs.get(dArgIdx); + succ = false; + for (int pi = 0; pi < cArgs.size(); pi++) + if (cArgs.get(pi).getName().equals(dArg.getName())) { + permutation[dArgIdx] = pi; + succ = true; + break; + } + } + + return succ ? permutation : new int[0]; + } + + @Override + public Optional> subst(Set pairs) { + HashMap typeMap = new HashMap<>(); + + Stack occuringTypes = new Stack<>(); + + for(UnifyPair pair : pairs) { + occuringTypes.push(pair.getLhsType()); + occuringTypes.push(pair.getRhsType()); + } + + while(!occuringTypes.isEmpty()) { + UnifyType t1 = occuringTypes.pop(); + if(!typeMap.containsKey(t1)) + typeMap.put(t1, 0); + typeMap.put(t1, typeMap.get(t1)+1); + + if(t1 instanceof ExtendsType) + occuringTypes.push(((ExtendsType) t1).getExtendedType()); + if(t1 instanceof SuperType) + occuringTypes.push(((SuperType) t1).getSuperedType()); + else + t1.getTypeParams().forEach(x -> occuringTypes.push(x)); + } + + Queue result1 = new LinkedList(pairs); + ArrayList result = new ArrayList(); + boolean applied = false; + + while(!result1.isEmpty()) { + UnifyPair pair = result1.poll(); + PlaceholderType lhsType = null; + UnifyType rhsType; + + if(pair.getPairOp() == PairOperator.EQUALSDOT + && pair.getLhsType() instanceof PlaceholderType) + lhsType = (PlaceholderType) pair.getLhsType(); + if(lhsType != null + && !((rhsType = pair.getRhsType()) instanceof PlaceholderType) + && typeMap.get(lhsType) > 1 // The type occurs in more pairs in the set than just the recent pair. + && !rhsType.getTypeParams().occurs(lhsType)) { + Unifier uni = new Unifier(lhsType, rhsType); + result = result.stream().map(uni::apply).collect(Collectors.toCollection(ArrayList::new)); + result1 = result1.stream().map(uni::apply).collect(Collectors.toCollection(LinkedList::new)); + applied = true; + } + + result.add(pair); + } + + return applied ? Optional.of(new HashSet<>(result)) : Optional.empty(); + } + + @Override + public Optional reduceWildcardLow(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof ExtendsType) || !(rhsType instanceof ExtendsType)) + return Optional.empty(); + + return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT)); + } + + @Override + public Optional reduceWildcardLowRight(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof ReferenceType) || !(rhsType instanceof ExtendsType)) + return Optional.empty(); + + return Optional.of(new UnifyPair(lhsType, ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT)); + } + + @Override + public Optional reduceWildcardUp(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof SuperType) || !(rhsType instanceof SuperType)) + return Optional.empty(); + + return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), ((SuperType) lhsType).getSuperedType(), PairOperator.SMALLERDOT)); + } + + @Override + public Optional reduceWildcardUpRight(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof ReferenceType) || !(rhsType instanceof SuperType)) + return Optional.empty(); + + return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), lhsType, PairOperator.SMALLERDOTWC)); + } + + @Override + public Optional reduceWildcardLowUp(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof ExtendsType) || !(rhsType instanceof SuperType)) + return Optional.empty(); + + return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), ((SuperType) rhsType).getSuperedType(), PairOperator.EQUALSDOT)); + } + + @Override + public Optional reduceWildcardUpLow(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof SuperType) || !(rhsType instanceof ExtendsType)) + return Optional.empty(); + + return Optional.of(new UnifyPair(((SuperType) lhsType).getSuperedType(), ((ExtendsType) rhsType).getExtendedType(), PairOperator.EQUALSDOT)); + } + + @Override + public Optional reduceWildcardLeft(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType rhsType = pair.getRhsType(); + if(!(rhsType instanceof ReferenceType)) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + + if(lhsType instanceof WildcardType) + return Optional.of(new UnifyPair(((WildcardType) lhsType).getWildcardedType(), rhsType, PairOperator.EQUALSDOT)); + + return Optional.empty(); + } + + @Override + public Optional> reduceFunN(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOT) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + + if(!(lhsType instanceof FunNType) || !(rhsType instanceof FunNType)) + return Optional.empty(); + + FunNType funNLhsType = (FunNType) lhsType; + FunNType funNRhsType = (FunNType) rhsType; + + if(funNLhsType.getN() != funNRhsType.getN()) + return Optional.empty(); + + Set result = new HashSet(); + + result.add(new UnifyPair(funNLhsType.getTypeParams().get(0), funNRhsType.getTypeParams().get(0), PairOperator.SMALLERDOT)); + for(int i = 1; i < funNLhsType.getTypeParams().size(); i++) + result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT)); + + return Optional.of(result); + } + + @Override + public Optional> greaterFunN(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOT) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + + if(!(lhsType instanceof FunNType) || !(rhsType instanceof PlaceholderType)) + return Optional.empty(); + + FunNType funNLhsType = (FunNType) lhsType; + + Set result = new HashSet(); + + UnifyType[] freshPlaceholders = new UnifyType[funNLhsType.getTypeParams().size()]; + for(int i = 0; i < freshPlaceholders.length; i++) + freshPlaceholders[i] = PlaceholderType.freshPlaceholder(); + + result.add(new UnifyPair(funNLhsType.getTypeParams().get(0), freshPlaceholders[0], PairOperator.SMALLERDOT)); + for(int i = 1; i < funNLhsType.getTypeParams().size(); i++) + result.add(new UnifyPair(freshPlaceholders[i], funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT)); + result.add(new UnifyPair(rhsType, funNLhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT)); + + return Optional.of(result); + } + + @Override + public Optional> smallerFunN(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOT) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + + if(!(lhsType instanceof PlaceholderType) || !(rhsType instanceof FunNType)) + return Optional.empty(); + + FunNType funNRhsType = (FunNType) rhsType; + + Set result = new HashSet(); + + UnifyType[] freshPlaceholders = new UnifyType[funNRhsType.getTypeParams().size()]; + for(int i = 0; i < freshPlaceholders.length; i++) + freshPlaceholders[i] = PlaceholderType.freshPlaceholder(); + + result.add(new UnifyPair(freshPlaceholders[0], funNRhsType.getTypeParams().get(0), PairOperator.SMALLERDOT)); + for(int i = 1; i < funNRhsType.getTypeParams().size(); i++) + result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), freshPlaceholders[i], PairOperator.SMALLERDOT)); + result.add(new UnifyPair(lhsType, funNRhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT)); + + return Optional.of(result); + } + + @Override + public Optional reduceTph(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof PlaceholderType) || !(rhsType instanceof ReferenceType)) + return Optional.empty(); + + return Optional.of(new UnifyPair(lhsType, rhsType, PairOperator.EQUALSDOT)); + } + + @Override + public Optional> reduceTphExt(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof ExtendsType) || !(rhsType instanceof PlaceholderType)) + return Optional.empty(); + + UnifyType extendedType = ((ExtendsType)lhsType).getExtendedType(); + + boolean isGen = extendedType instanceof PlaceholderType && !((PlaceholderType) extendedType).isGenerated(); + + Set result = new HashSet<>(); + if(isGen) + result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT)); + else { + UnifyType freshTph = PlaceholderType.freshPlaceholder(); + result.add(new UnifyPair(rhsType, new ExtendsType(freshTph), PairOperator.EQUALSDOT)); + result.add(new UnifyPair(extendedType, freshTph, PairOperator.SMALLERDOT)); + } + + return Optional.of(result); + } + + @Override + public Optional> reduceTphSup(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof SuperType) || !(rhsType instanceof PlaceholderType)) + return Optional.empty(); + + UnifyType superedType = ((SuperType)lhsType).getSuperedType(); + + boolean isGen = superedType instanceof PlaceholderType && !((PlaceholderType) superedType).isGenerated(); + + Set result = new HashSet<>(); + if(isGen) + result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT)); + else { + UnifyType freshTph = PlaceholderType.freshPlaceholder(); + result.add(new UnifyPair(rhsType, new SuperType(freshTph), PairOperator.EQUALSDOT)); + result.add(new UnifyPair(freshTph, superedType, PairOperator.SMALLERDOT)); + } + + return Optional.of(result); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/TypeUnify.java b/src/de/dhbwstuttgart/typeinference/unify/TypeUnify.java new file mode 100644 index 000000000..f457fbb8f --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/TypeUnify.java @@ -0,0 +1,24 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.Set; +import java.util.concurrent.ForkJoinPool; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +public class TypeUnify { + public Set> unify(Set eq, IFiniteClosure fc) { + TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, true); + ForkJoinPool pool = new ForkJoinPool(); + pool.invoke(unifyTask); + Set> res = unifyTask.join(); + return res; + } + + public Set> unifySequential(Set eq, IFiniteClosure fc) { + TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, false); + Set> res = unifyTask.compute(); + return res; + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java b/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java new file mode 100644 index 000000000..be67ea09f --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java @@ -0,0 +1,626 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.RecursiveTask; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet; +import de.dhbwstuttgart.typeinference.unify.interfaces.ISetOperations; +import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; +import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.SuperType; +import de.dhbwstuttgart.typeinference.unify.model.TypeParams; +import de.dhbwstuttgart.typeinference.unify.model.Unifier; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; + + +/** + * Implementation of the type unification algorithm + * @author Florian Steurer + */ +public class TypeUnifyTask extends RecursiveTask>> { + + private static final long serialVersionUID = 1L; + + /** + * The implementation of setOps that will be used during the unification + */ + protected ISetOperations setOps = new GuavaSetOperations(); + + /** + * The implementation of the standard unify that will be used during the unification + */ + protected IUnify stdUnify = new MartelliMontanariUnify(); + + /** + * The implementation of the rules that will be used during the unification. + */ + protected IRuleSet rules = new RuleSet(); + + protected Set eq; + + protected IFiniteClosure fc; + + protected boolean parallel; + + public TypeUnifyTask(Set eq, IFiniteClosure fc, boolean parallel) { + this.eq = eq; + this.fc = fc; + this.parallel = parallel; + } + + @Override + protected Set> compute() { + return unify(eq, fc, parallel); + } + + /** + * Computes all principal type unifiers for a set of constraints. + * @param eq The set of constraints + * @param fc The finite closure + * @return The set of all principal type unifiers + */ + protected Set> unify(Set eq, IFiniteClosure fc, boolean parallel) { + /* + * Step 1: Repeated application of reduce, adapt, erase, swap + */ + Set eq0 = applyTypeUnificationRules(eq, fc); + + /* + * Step 2 and 3: Create a subset eq1s of pairs where both sides are TPH and eq2s of the other pairs + */ + Set eq1s = new HashSet<>(); + Set eq2s = new HashSet<>(); + splitEq(eq0, eq1s, eq2s); + + /* + * Step 4: Create possible typings + * + * "Manche Autoren identifizieren die Paare (a, (b,c)) und ((a,b),c) + * mit dem geordneten Tripel (a,b,c), wodurch das kartesische Produkt auch assoziativ wird." - Wikipedia + */ + + // There are up to 10 toplevel set. 8 of 10 are the result of the + // cartesian product of the sets created by pattern matching. + List>> topLevelSets = new ArrayList<>(); + + if(eq1s.size() != 0) { // Do not add empty sets or the cartesian product will always be empty. + Set> wrap = new HashSet<>(); + wrap.add(eq1s); + topLevelSets.add(wrap); // Add Eq1' + } + + // Add the set of [a =. Theta | (a=. Theta) in Eq2'] + Set bufferSet = eq2s.stream() + .filter(x -> x.getPairOp() == PairOperator.EQUALSDOT && x.getLhsType() instanceof PlaceholderType) + .collect(Collectors.toSet()); + + if(bufferSet.size() != 0) { // Do not add empty sets or the cartesian product will always be empty. + Set> wrap = new HashSet<>(); + wrap.add(bufferSet); + topLevelSets.add(wrap); + eq2s.removeAll(bufferSet); + } + + // Sets that originate from pair pattern matching + // Sets of the "second level" + Set undefinedPairs = new HashSet<>(); + Set>>> secondLevelSets = calculatePairSets(eq2s, fc, undefinedPairs); + + // If pairs occured that did not match one of the cartesian product cases, + // those pairs are contradictory and the unification is impossible. + if(!undefinedPairs.isEmpty()) + return new HashSet<>(); + + /* Up to here, no cartesian products are calculated. + * filters for pairs and sets can be applied here */ + + // Sub cartesian products of the second level (pattern matched) sets + // "the big (x)" + for(Set>> secondLevelSet : secondLevelSets) { + List>> secondLevelSetList = new ArrayList<>(secondLevelSet); + Set>> cartResult = setOps.cartesianProduct(secondLevelSetList); + + // Flatten and add to top level sets + Set> flat = new HashSet<>(); + for(List> s : cartResult) { + Set flat1 = new HashSet<>(); + for(Set s1 : s) + flat1.addAll(s1); + flat.add(flat1); + } + topLevelSets.add(flat); + } + + // Cartesian product over all (up to 10) top level sets + Set>> eqPrimeSet = setOps.cartesianProduct(topLevelSets) + .stream().map(x -> new HashSet<>(x)) + .collect(Collectors.toCollection(HashSet::new)); + //System.out.println(result); + + Set> eqPrimePrimeSet = new HashSet<>(); + + Set forks = new HashSet<>(); + for(Set> setToFlatten : eqPrimeSet) { + // Flatten the cartesian product + Set eqPrime = new HashSet<>(); + setToFlatten.stream().forEach(x -> eqPrime.addAll(x)); + + /* + * Step 5: Substitution + */ + Optional> eqPrimePrime = rules.subst(eqPrime); + + + /* + * Step 6 a) Restart (fork) for pairs where subst was applied + */ + if(parallel) { + if (eqPrime.equals(eq)) + eqPrimePrimeSet.add(eqPrime); + else if(eqPrimePrime.isPresent()) { + TypeUnifyTask fork = new TypeUnifyTask(eqPrimePrime.get(), fc, true); + forks.add(fork); + fork.fork(); + } + else { + TypeUnifyTask fork = new TypeUnifyTask(eqPrime, fc, true); + forks.add(fork); + fork.fork(); + } + } + else { // sequentiell (Step 6b is included) + if (eqPrime.equals(eq)) + eqPrimePrimeSet.add(eqPrime); + else if(eqPrimePrime.isPresent()) + eqPrimePrimeSet.addAll(unify(eqPrimePrime.get(), fc, false)); + else + eqPrimePrimeSet.addAll(unify(eqPrime, fc, false)); + } + } + + /* + * Step 6 b) Build the union over everything. + */ + + if(parallel) + for(TypeUnifyTask fork : forks) + eqPrimePrimeSet.addAll(fork.join()); + + /* + * Step 7: Filter empty sets; + */ + return eqPrimePrimeSet.stream().filter(x -> isSolvedForm(x)).collect(Collectors.toCollection(HashSet::new)); + + } + + /** + * Checks whether a set of pairs is in solved form. + * @param eqPrimePrime The set of pair + * @return True if in solved form, false otherwise. + */ + protected boolean isSolvedForm(Set eqPrimePrime) { + for(UnifyPair pair : eqPrimePrime) { + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + + if(!(lhsType instanceof PlaceholderType)) + return false; + + // If operator is not equals, both sides must be placeholders + if(pair.getPairOp() != PairOperator.EQUALSDOT && !(rhsType instanceof PlaceholderType)) + return false; + } + return true; + } + + /** + * Repeatedly applies type unification rules to a set of equations. + * This is step one of the unification algorithm. + * @return The set of pairs that results from repeated application of the inference rules. + */ + protected Set applyTypeUnificationRules(Set eq, IFiniteClosure fc) { + + /* + * Rule Application Strategy: + * + * 1. Swap all pairs and erase all erasable pairs + * 2. Apply all possible rules to a single pair, then move it to the result set. + * Iterating over pairs first, then iterating over rules prevents the application + * of rules to a "finished" pair over and over. + * 2.1 Apply all rules repeatedly except for erase rules. If + * the application of a rule creates new pairs, check immediately + * against the erase rules. + */ + + + LinkedHashSet targetSet = new LinkedHashSet(); + LinkedList eqQueue = new LinkedList<>(); + + /* + * Swap all pairs and erase all erasable pairs + */ + eq.forEach(x -> swapAddOrErase(x, fc, eqQueue)); + + /* + * Apply rules until the queue is empty + */ + while(!eqQueue.isEmpty()) { + UnifyPair pair = eqQueue.pollFirst(); + + // ReduceUp, ReduceLow, ReduceUpLow + Optional opt = rules.reduceUpLow(pair); + opt = opt.isPresent() ? opt : rules.reduceLow(pair); + opt = opt.isPresent() ? opt : rules.reduceUp(pair); + opt = opt.isPresent() ? opt : rules.reduceWildcardLow(pair); + opt = opt.isPresent() ? opt : rules.reduceWildcardLowRight(pair); + opt = opt.isPresent() ? opt : rules.reduceWildcardUp(pair); + opt = opt.isPresent() ? opt : rules.reduceWildcardUpRight(pair); + opt = opt.isPresent() ? opt : rules.reduceWildcardLowUp(pair); + opt = opt.isPresent() ? opt : rules.reduceWildcardUpLow(pair); + opt = opt.isPresent() ? opt : rules.reduceWildcardLeft(pair); + + // Reduce TPH + opt = opt.isPresent() ? opt : rules.reduceTph(pair); + + // One of the rules has been applied + if(opt.isPresent()) { + swapAddOrErase(opt.get(), fc, eqQueue); + continue; + } + + // Reduce1, Reduce2, ReduceExt, ReduceSup, ReduceEq + Optional> optSet = rules.reduce1(pair, fc); + optSet = optSet.isPresent() ? optSet : rules.reduce2(pair); + optSet = optSet.isPresent() ? optSet : rules.reduceExt(pair, fc); + optSet = optSet.isPresent() ? optSet : rules.reduceSup(pair, fc); + optSet = optSet.isPresent() ? optSet : rules.reduceEq(pair); + + // ReduceTphExt, ReduceTphSup + optSet = optSet.isPresent() ? optSet : rules.reduceTphExt(pair); + optSet = optSet.isPresent() ? optSet : rules.reduceTphSup(pair); + + + // FunN Rules + optSet = optSet.isPresent() ? optSet : rules.reduceFunN(pair); + optSet = optSet.isPresent() ? optSet : rules.greaterFunN(pair); + optSet = optSet.isPresent() ? optSet : rules.smallerFunN(pair); + + // One of the rules has been applied + if(optSet.isPresent()) { + optSet.get().forEach(x -> swapAddOrErase(x, fc, eqQueue)); + continue; + } + + // Adapt, AdaptExt, AdaptSup + opt = rules.adapt(pair, fc); + opt = opt.isPresent() ? opt : rules.adaptExt(pair, fc); + opt = opt.isPresent() ? opt : rules.adaptSup(pair, fc); + + // One of the rules has been applied + if(opt.isPresent()) { + swapAddOrErase(opt.get(), fc, eqQueue); + continue; + } + + // None of the rules has been applied + targetSet.add(pair); + } + + return targetSet; + } + + /** + * Applies the rule swap to a pair if possible. Then adds the pair to the set if no erase rule applies. + * If an erase rule applies, the pair is not added (erased). + * @param pair The pair to swap and add or erase. + * @param collection The collection to which the pairs are added. + */ + protected void swapAddOrErase(UnifyPair pair, IFiniteClosure fc, Collection collection) { + Optional opt = rules.swap(pair); + UnifyPair pair2 = opt.isPresent() ? opt.get() : pair; + + if(rules.erase1(pair2, fc) || rules.erase3(pair2) || rules.erase2(pair2, fc)) + return; + + collection.add(pair2); + } + + /** + * Splits the equation eq into a set eq1s where both terms are type variables, + * and a set eq2s where one of both terms is not a type variable. + * @param eq Set of pairs to be splitted. + * @param eq1s Subset of eq where both terms are type variables. + * @param eq2s eq/eq1s. + */ + protected void splitEq(Set eq, Set eq1s, Set eq2s) { + for(UnifyPair pair : eq) + if(pair.getLhsType() instanceof PlaceholderType && pair.getRhsType() instanceof PlaceholderType) + eq1s.add(pair); + else + eq2s.add(pair); + } + + /** + * Creates sets of pairs specified in the fourth step. Does not calculate cartesian products. + * @param undefined All pairs that did not match one of the 8 cases are added to this set. + * @return The set of the eight cases (without empty sets). Each case is a set, containing sets generated + * from the pairs that matched the case. Each generated set contains singleton sets or sets with few elements + * (as in case 1 where sigma is added to the innermost set). + */ + protected Set>>> calculatePairSets(Set eq2s, IFiniteClosure fc, Set undefined) { + List>>> result = new ArrayList<>(8); + + // Init all 8 cases + for(int i = 0; i < 8; i++) + result.add(new HashSet<>()); + + for(UnifyPair pair : eq2s) { + PairOperator pairOp = pair.getPairOp(); + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + + // Case 1: (a <. Theta') + if(pairOp == PairOperator.SMALLERDOT && lhsType instanceof PlaceholderType) + result.get(0).add(unifyCase1((PlaceholderType) pair.getLhsType(), pair.getRhsType(), fc)); + + // Case 2: (a <.? ? ext Theta') + else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof ExtendsType) + result.get(1).add(unifyCase2((PlaceholderType) pair.getLhsType(), (ExtendsType) pair.getRhsType(), fc)); + + // Case 3: (a <.? ? sup Theta') + else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof SuperType) + result.get(2).add(unifyCase3((PlaceholderType) lhsType, (SuperType) rhsType, fc)); + + // Case 4 was replaced by an inference rule + // Case 4: (a <.? Theta') + //else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType) + // result.get(3).add(unifyCase4((PlaceholderType) lhsType, rhsType, fc)); + + // Case 5: (Theta <. a) + else if(pairOp == PairOperator.SMALLERDOT && rhsType instanceof PlaceholderType) + result.get(4).add(unifyCase5(lhsType, (PlaceholderType) rhsType, fc)); + + // Case 6 was replaced by an inference rule. + // Case 6: (? ext Theta <.? a) + //else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof ExtendsType && rhsType instanceof PlaceholderType) + // result.get(5).add(unifyCase6((ExtendsType) lhsType, (PlaceholderType) rhsType, fc)); + + // Case 7 was replaced by an inference rule + // Case 7: (? sup Theta <.? a) + //else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof SuperType && rhsType instanceof PlaceholderType) + // result.get(6).add(unifyCase7((SuperType) lhsType, (PlaceholderType) rhsType, fc)); + + // Case 8: (Theta <.? a) + else if(pairOp == PairOperator.SMALLERDOTWC && rhsType instanceof PlaceholderType) + result.get(7).add(unifyCase8(lhsType, (PlaceholderType) rhsType, fc)); + // Case unknown: If a pair fits no other case, then the type unification has failed. + // Through application of the rules, every pair should have one of the above forms. + // Pairs that do not have one of the aboves form are contradictory. + else { + // If a pair is not defined, the unificiation will fail, so the loop can be stopped here. + undefined.add(pair); + break; + } + } + + // Filter empty sets or sets that only contain an empty set. + return result.stream().map(x -> x.stream().filter(y -> y.size() > 0).collect(Collectors.toCollection(HashSet::new))) + .filter(x -> x.size() > 0).collect(Collectors.toCollection(HashSet::new)); + } + + /** + * Cartesian product Case 1: (a <. Theta') + */ + protected Set> unifyCase1(PlaceholderType a, UnifyType thetaPrime, IFiniteClosure fc) { + Set> result = new HashSet<>(); + + boolean allGen = thetaPrime.getTypeParams().size() > 0; + for(UnifyType t : thetaPrime.getTypeParams()) + if(!(t instanceof PlaceholderType) || !((PlaceholderType) t).isGenerated()) { + allGen = false; + break; + } + + Set cs = fc.getAllTypesByName(thetaPrime.getName()); + cs.add(thetaPrime); + + for(UnifyType c : cs) { + Set thetaQs = fc.getChildren(c).stream().collect(Collectors.toCollection(HashSet::new)); + //thetaQs.add(thetaPrime); + Set thetaQPrimes = new HashSet<>(); + TypeParams cParams = c.getTypeParams(); + if(cParams.size() == 0) + thetaQPrimes.add(c); + else { + ArrayList> candidateParams = new ArrayList<>(); + + for(UnifyType param : cParams) + candidateParams.add(fc.grArg(param)); + + for(TypeParams tp : permuteParams(candidateParams)) + thetaQPrimes.add(c.setTypeParams(tp)); + } + + for(UnifyType tqp : thetaQPrimes) { + Optional opt = stdUnify.unify(tqp, thetaPrime); + if (!opt.isPresent()) + continue; + + Unifier unifier = opt.get(); + unifier.swapPlaceholderSubstitutions(thetaPrime.getTypeParams()); + Set substitutionSet = new HashSet<>(); + for (Entry sigma : unifier) + substitutionSet.add(new UnifyPair(sigma.getKey(), sigma.getValue(), PairOperator.EQUALSDOT)); + + List freshTphs = new ArrayList<>(); + for (UnifyType tq : thetaQs) { + Set smaller = fc.smaller(unifier.apply(tq)); + for(UnifyType theta : smaller) { + Set resultPrime = new HashSet<>(); + + for(int i = 0; !allGen && i < theta.getTypeParams().size(); i++) { + if(freshTphs.size()-1 < i) + freshTphs.add(PlaceholderType.freshPlaceholder()); + resultPrime.add(new UnifyPair(freshTphs.get(i), theta.getTypeParams().get(i), PairOperator.SMALLERDOTWC)); + } + + if(allGen) + resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT)); + else + resultPrime.add(new UnifyPair(a, theta.setTypeParams(new TypeParams(freshTphs.toArray(new UnifyType[0]))), PairOperator.EQUALSDOT)); + resultPrime.addAll(substitutionSet); + result.add(resultPrime); + } + } + + } + } + + return result; + } + + /** + * Cartesian Product Case 2: (a <.? ? ext Theta') + */ + private Set> unifyCase2(PlaceholderType a, ExtendsType extThetaPrime, IFiniteClosure fc) { + Set> result = new HashSet<>(); + + UnifyType aPrime = PlaceholderType.freshPlaceholder(); + UnifyType extAPrime = new ExtendsType(aPrime); + UnifyType thetaPrime = extThetaPrime.getExtendedType(); + Set resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(a, thetaPrime, PairOperator.SMALLERDOT)); + result.add(resultPrime); + + resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(a, extAPrime, PairOperator.EQUALSDOT)); + resultPrime.add(new UnifyPair(aPrime, thetaPrime, PairOperator.SMALLERDOT)); + result.add(resultPrime); + return result; + } + + /** + * Cartesian Product Case 3: (a <.? ? sup Theta') + */ + private Set> unifyCase3(PlaceholderType a, SuperType subThetaPrime, IFiniteClosure fc) { + Set> result = new HashSet<>(); + + UnifyType aPrime = PlaceholderType.freshPlaceholder(); + UnifyType supAPrime = new SuperType(aPrime); + UnifyType thetaPrime = subThetaPrime.getSuperedType(); + Set resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(thetaPrime, a, PairOperator.SMALLERDOT)); + result.add(resultPrime); + + resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(a, supAPrime, PairOperator.EQUALSDOT)); + resultPrime.add(new UnifyPair(thetaPrime, aPrime, PairOperator.SMALLERDOT)); + result.add(resultPrime); + + return result; + } + + /** + * Cartesian Product Case 5: (Theta <. a) + */ + private Set> unifyCase5(UnifyType theta, PlaceholderType a, IFiniteClosure fc) { + Set> result = new HashSet<>(); + + boolean allGen = theta.getTypeParams().size() > 0; + for(UnifyType t : theta.getTypeParams()) + if(!(t instanceof PlaceholderType) || !((PlaceholderType) t).isGenerated()) { + allGen = false; + break; + } + + for(UnifyType thetaS : fc.greater(theta)) { + Set resultPrime = new HashSet<>(); + + UnifyType[] freshTphs = new UnifyType[thetaS.getTypeParams().size()]; + for(int i = 0; !allGen && i < freshTphs.length; i++) { + freshTphs[i] = PlaceholderType.freshPlaceholder(); + resultPrime.add(new UnifyPair(thetaS.getTypeParams().get(i), freshTphs[i], PairOperator.SMALLERDOTWC)); + } + + if(allGen) + resultPrime.add(new UnifyPair(a, thetaS, PairOperator.EQUALSDOT)); + else + resultPrime.add(new UnifyPair(a, thetaS.setTypeParams(new TypeParams(freshTphs)), PairOperator.EQUALSDOT)); + result.add(resultPrime); + } + + return result; + } + + /** + * Cartesian Product Case 8: (Theta <.? a) + */ + private Set> unifyCase8(UnifyType theta, PlaceholderType a, IFiniteClosure fc) { + Set> result = new HashSet<>(); + //for(UnifyType thetaS : fc.grArg(theta)) { + Set resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT)); + result.add(resultPrime); + + UnifyType freshTph = PlaceholderType.freshPlaceholder(); + resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(a, new ExtendsType(freshTph), PairOperator.EQUALSDOT)); + resultPrime.add(new UnifyPair(theta, freshTph, PairOperator.SMALLERDOT)); + result.add(resultPrime); + + resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(a, new SuperType(freshTph), PairOperator.EQUALSDOT)); + resultPrime.add(new UnifyPair(freshTph, theta, PairOperator.SMALLERDOT)); + result.add(resultPrime); + //} + + return result; + } + + /** + * Takes a set of candidates for each position and computes all possible permutations. + * @param candidates The length of the list determines the number of type params. Each set + * contains the candidates for the corresponding position. + */ + protected Set permuteParams(ArrayList> candidates) { + Set result = new HashSet<>(); + permuteParams(candidates, 0, result, new UnifyType[candidates.size()]); + return result; + } + + /** + * Takes a set of candidates for each position and computes all possible permutations. + * @param candidates The length of the list determines the number of type params. Each set + * contains the candidates for the corresponding position. + * @param idx Idx for the current permutatiton. + * @param result Set of all permutations found so far + * @param current The permutation of type params that is currently explored + */ + private void permuteParams(ArrayList> candidates, int idx, Set result, UnifyType[] current) { + if(candidates.size() == idx) { + result.add(new TypeParams(Arrays.copyOf(current, current.length))); + return; + } + + Set localCandidates = candidates.get(idx); + + for(UnifyType t : localCandidates) { + current[idx] = t; + permuteParams(candidates, idx+1, result, current); + } + } +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/Unifikationsalgorithmus.java b/src/de/dhbwstuttgart/typeinference/unify/Unifikationsalgorithmus.java new file mode 100644 index 000000000..39c25e57d --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/Unifikationsalgorithmus.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +public interface Unifikationsalgorithmus { + + public Set> apply (Set E); + +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java new file mode 100644 index 000000000..dcb6c4d1d --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java @@ -0,0 +1,64 @@ +package de.dhbwstuttgart.typeinference.unify.interfaces; + +import java.util.Optional; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +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.UnifyType; + +/** + * + * @author Florian Steurer + */ +public interface IFiniteClosure { + + /** + * Returns all types of the finite closure that are subtypes of the argument. + * @return The set of subtypes of the argument. + */ + public Set smaller(UnifyType type); + + /** + * Returns all types of the finite closure that are supertypes of the argument. + * @return The set of supertypes of the argument. + */ + public Set greater(UnifyType type); + + /** + * Wo passt Type rein? + * @param type + * @return + */ + public Set grArg(UnifyType type); + + /** + * Was passt in Type rein? + * @param type + * @return + */ + public Set smArg(UnifyType type); + + public Set grArg(ReferenceType type); + public Set smArg(ReferenceType type); + + public Set grArg(ExtendsType type); + public Set smArg(ExtendsType type); + + public Set grArg(SuperType type); + public Set smArg(SuperType type); + + public Set grArg(PlaceholderType type); + public Set smArg(PlaceholderType type); + + public Set grArg(FunNType type); + public Set smArg(FunNType type); + + public Optional getLeftHandedType(String typeName); + public Set getAncestors(UnifyType t); + public Set getChildren(UnifyType t); + public Set getAllTypesByName(String typeName); +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java new file mode 100644 index 000000000..62c9649f2 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java @@ -0,0 +1,90 @@ +package de.dhbwstuttgart.typeinference.unify.interfaces; + +import java.util.Optional; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +/** + * Contains the inference rules that are applied to the set Eq. + * @author Florian Steurer + */ +public interface IRuleSet { + + public Optional reduceUp(UnifyPair pair); + public Optional reduceLow(UnifyPair pair); + public Optional reduceUpLow(UnifyPair pair); + public Optional> reduceExt(UnifyPair pair, IFiniteClosure fc); + public Optional> reduceSup(UnifyPair pair, IFiniteClosure fc); + public Optional> reduceEq(UnifyPair pair); + public Optional> reduce1(UnifyPair pair, IFiniteClosure fc); + public Optional> reduce2(UnifyPair pair); + + /* + * Missing Reduce-Rules for Wildcards + */ + public Optional reduceWildcardLow(UnifyPair pair); + public Optional reduceWildcardLowRight(UnifyPair pair); + public Optional reduceWildcardUp(UnifyPair pair); + public Optional reduceWildcardUpRight(UnifyPair pair); + public Optional reduceWildcardLowUp(UnifyPair pair); + public Optional reduceWildcardUpLow(UnifyPair pair); + public Optional reduceWildcardLeft(UnifyPair pair); + + /* + * Additional Rules which replace cases of the cartesian product + */ + + /** + * Rule that replaces the fourth case of the cartesian product where (a <.? Theta) + */ + public Optional reduceTph(UnifyPair pair); + + /** + * Rule that replaces the sixth case of the cartesian product where (? ext Theta <.? a) + */ + public Optional> reduceTphExt(UnifyPair pair); + + /** + * Rule that replaces the fourth case of the cartesian product where (? sup Theta <.? a) + */ + public Optional> reduceTphSup(UnifyPair pair); + + /* + * FunN Rules + */ + public Optional> reduceFunN(UnifyPair pair); + public Optional> greaterFunN(UnifyPair pair); + public Optional> smallerFunN(UnifyPair pair); + + /** + * Checks whether the erase1-Rule applies to the pair. + * @return True if the pair is erasable, false otherwise. + */ + public boolean erase1(UnifyPair pair, IFiniteClosure fc); + + /** + * Checks whether the erase2-Rule applies to the pair. + * @return True if the pair is erasable, false otherwise. + */ + public boolean erase2(UnifyPair pair, IFiniteClosure fc); + + /** + * Checks whether the erase3-Rule applies to the pair. + * @return True if the pair is erasable, false otherwise. + */ + public boolean erase3(UnifyPair pair); + + public Optional swap(UnifyPair pair); + + public Optional adapt(UnifyPair pair, IFiniteClosure fc); + public Optional adaptExt(UnifyPair pair, IFiniteClosure fc); + public Optional adaptSup(UnifyPair pair, IFiniteClosure fc); + + /** + * Applies the subst-Rule to a set of pairs (usually Eq'). + * @param pairs The set of pairs where the subst rule should apply. + * @return An optional of the modified set, if there were any substitutions. An empty optional if there were no substitutions. + */ + public Optional> subst(Set pairs); +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/interfaces/ISetOperations.java b/src/de/dhbwstuttgart/typeinference/unify/interfaces/ISetOperations.java new file mode 100644 index 000000000..4a98aaba3 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/interfaces/ISetOperations.java @@ -0,0 +1,16 @@ +package de.dhbwstuttgart.typeinference.unify.interfaces; + +import java.util.List; +import java.util.Set; + +/** + * Contains operations on sets. + * @author Florian Steurer + */ +public interface ISetOperations { + /** + * Calculates the cartesian product of the sets. + * @return The cartesian product + */ + Set> cartesianProduct(List> sets); +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IUnify.java b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IUnify.java new file mode 100644 index 000000000..524608f5c --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IUnify.java @@ -0,0 +1,35 @@ +package de.dhbwstuttgart.typeinference.unify.interfaces; + +import java.util.Arrays; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; +import de.dhbwstuttgart.typeinference.unify.model.Unifier; + +/** + * Standard unification algorithm (e.g. Robinson, Paterson-Wegman, Martelli-Montanari) + * @author Florian Steurer + */ +public interface IUnify { + + /** + * Finds the most general unifier sigma of the set {t1,...,tn} so that + * sigma(t1) = sigma(t2) = ... = sigma(tn). + * @param terms The set of terms to be unified + * @return An optional of the most general unifier if it exists or an empty optional if there is no unifier. + */ + public Optional unify(Set terms); + + /** + * Finds the most general unifier sigma of the set {t1,...,tn} so that + * sigma(t1) = sigma(t2) = ... = sigma(tn). + * @param terms The set of terms to be unified + * @return An optional of the most general unifier if it exists or an empty optional if there is no unifier. + */ + default public Optional unify(UnifyType... terms) { + return unify(Arrays.stream(terms).collect(Collectors.toSet())); + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/ExtendsType.java b/src/de/dhbwstuttgart/typeinference/unify/model/ExtendsType.java new file mode 100644 index 000000000..33f32e07b --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/ExtendsType.java @@ -0,0 +1,87 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; + +/** + * An extends wildcard type "? extends T". + */ +public final class ExtendsType extends WildcardType { + + /** + * Creates a new extends wildcard type. + * @param extendedType The extended type e.g. Integer in "? extends Integer" + */ + public ExtendsType(UnifyType extendedType) { + super("? extends " + extendedType.getName(), extendedType); + } + + /** + * The extended type e.g. Integer in "? extends Integer" + */ + public UnifyType getExtendedType() { + return wildcardedType; + } + + /** + * Sets the type parameters of the wildcarded type and returns a new extendstype that extends that type. + */ + @Override + public UnifyType setTypeParams(TypeParams newTp) { + UnifyType newType = wildcardedType.setTypeParams(newTp); + if(newType == wildcardedType) + return this; // Reduced the amount of objects created + return new ExtendsType(wildcardedType.setTypeParams(newTp)); + } + + @Override + Set smArg(IFiniteClosure fc) { + return fc.smArg(this); + } + + @Override + Set grArg(IFiniteClosure fc) { + return fc.grArg(this); + } + + @Override + UnifyType apply(Unifier unif) { + UnifyType newType = wildcardedType.apply(unif); + if(newType.hashCode() == wildcardedType.hashCode() && newType.equals(wildcardedType)) + return this; // Reduced the amount of objects created + return new ExtendsType(newType); + } + + @Override + public int hashCode() { + /* + * It is important that the prime that is added is different to the prime added in hashCode() of SuperType. + * Otherwise ? extends T and ? super T have the same hashCode() for every Type T. + */ + return wildcardedType.hashCode() + 229; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof ExtendsType)) + return false; + + if(obj.hashCode() != this.hashCode()) + return false; + + ExtendsType other = (ExtendsType) obj; + + + return other.getWildcardedType().equals(wildcardedType); + } + + @Override + public String toString() { + return "? extends " + wildcardedType; + } + + +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java b/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java new file mode 100644 index 000000000..9ace0e515 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java @@ -0,0 +1,413 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.unify.MartelliMontanariUnify; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; + +/** + * The finite closure for the type unification + * @author Florian Steurer + */ +public class FiniteClosure implements IFiniteClosure { + + /** + * A map that maps every type to the node in the inheritance graph that contains that type. + */ + private HashMap> inheritanceGraph; + + /** + * A map that maps every typename to the nodes of the inheritance graph that contain a type with that name. + */ + private HashMap>> strInheritanceGraph; + + /** + * The initial pairs of that define the inheritance tree + */ + private Set pairs; + + /** + * Creates a new instance using the inheritance tree defined in the pairs. + */ + public FiniteClosure(Set pairs) { + this.pairs = new HashSet<>(pairs); + inheritanceGraph = new HashMap>(); + + // Build the transitive closure of the inheritance tree + for(UnifyPair pair : pairs) { + if(pair.getPairOp() != PairOperator.SMALLER) + continue; + + // Add nodes if not already in the graph + if(!inheritanceGraph.containsKey(pair.getLhsType())) + inheritanceGraph.put(pair.getLhsType(), new Node(pair.getLhsType())); + if(!inheritanceGraph.containsKey(pair.getRhsType())) + inheritanceGraph.put(pair.getRhsType(), new Node(pair.getRhsType())); + + Node childNode = inheritanceGraph.get(pair.getLhsType()); + Node parentNode = inheritanceGraph.get(pair.getRhsType()); + + // Add edge + parentNode.addDescendant(childNode); + + // Add edges to build the transitive closure + parentNode.getPredecessors().stream().forEach(x -> x.addDescendant(childNode)); + childNode.getDescendants().stream().forEach(x -> x.addPredecessor(parentNode)); + } + + // Build the alternative representation with strings as keys + strInheritanceGraph = new HashMap<>(); + for(UnifyType key : inheritanceGraph.keySet()) { + if(!strInheritanceGraph.containsKey(key.getName())) + strInheritanceGraph.put(key.getName(), new HashSet<>()); + + strInheritanceGraph.get(key.getName()).add(inheritanceGraph.get(key)); + } + } + + /** + * Returns all types of the finite closure that are subtypes of the argument. + * @return The set of subtypes of the argument. + */ + @Override + public Set smaller(UnifyType type) { + if(type instanceof FunNType) + return computeSmallerFunN((FunNType) type); + + Set ts = new HashSet<>(); + ts.add(type); + return computeSmaller(ts); + } + + /** + * Computes the smaller functions for every type except FunNTypes. + */ + private Set computeSmaller(Set types) { + HashSet result = new HashSet<>(); + + IUnify unify = new MartelliMontanariUnify(); + + for(UnifyType t : types) { + + // if T = T' then T <* T' + result.add(t); + + // if C<...> <* C<...> then ... (third case in definition of <*) + if(t.getTypeParams().size() > 0) { + ArrayList> paramCandidates = new ArrayList<>(); + for (int i = 0; i < t.getTypeParams().size(); i++) + paramCandidates.add(smArg(t.getTypeParams().get(i))); + permuteParams(paramCandidates).forEach(x -> result.add(t.setTypeParams(x))); + } + + if(!strInheritanceGraph.containsKey(t.getName())) + continue; + + // if T <* T' then sigma(T) <* sigma(T') + Set> candidates = strInheritanceGraph.get(t.getName()); + for(Node candidate : candidates) { + UnifyType theta2 = candidate.getContent(); + Optional optSigma = unify.unify(theta2, t); + if(!optSigma.isPresent()) + continue; + + Unifier sigma = optSigma.get(); + sigma.swapPlaceholderSubstitutions(t.getTypeParams()); + + Set theta1Set = candidate.getContentOfDescendants(); + + for(UnifyType theta1 : theta1Set) + result.add(theta1.apply(sigma)); + } + } + + if(result.equals(types)) + return result; + return computeSmaller(result); + } + + /** + * Computes the smaller-Function for FunNTypes. + */ + private Set computeSmallerFunN(FunNType type) { + Set result = new HashSet<>(); + + // if T = T' then T <=* T' + result.add(type); + + // Because real function types are implicitly variant + // it is enough to permute the params with the values of greater / smaller. + ArrayList> paramCandidates = new ArrayList<>(); + paramCandidates.add(smaller(type.getTypeParams().get(0))); + for (int i = 1; i < type.getTypeParams().size(); i++) + paramCandidates.add(greater(type.getTypeParams().get(i))); + + permuteParams(paramCandidates).forEach(x -> result.add(type.setTypeParams(x))); + return result; + } + + /** + * Returns all types of the finite closure that are supertypes of the argument. + * @return The set of supertypes of the argument. + */ + @Override + public Set greater(UnifyType type) { + if(type instanceof FunNType) + return computeGreaterFunN((FunNType) type); + + Set ts = new HashSet<>(); + ts.add(type); + return computeGreater(ts); + } + + /** + * Computes the greater function for all types except function types. + */ + protected Set computeGreater(Set types) { + HashSet result = new HashSet<>(); + + IUnify unify = new MartelliMontanariUnify(); + + for(UnifyType t : types) { + + // if T = T' then T <=* T' + result.add(t); + + // if C<...> <* C<...> then ... (third case in definition of <*) + if(t.getTypeParams().size() > 0) { + ArrayList> paramCandidates = new ArrayList<>(); + for (int i = 0; i < t.getTypeParams().size(); i++) + paramCandidates.add(grArg(t.getTypeParams().get(i))); + permuteParams(paramCandidates).forEach(x -> result.add(t.setTypeParams(x))); + } + + if(!strInheritanceGraph.containsKey(t.getName())) + continue; + + // if T <* T' then sigma(T) <* sigma(T') + Set> candidates = strInheritanceGraph.get(t.getName()); + for(Node candidate : candidates) { + UnifyType theta1 = candidate.getContent(); + Optional optSigma = unify.unify(theta1, t); + if(!optSigma.isPresent()) + continue; + + Unifier sigma = optSigma.get(); + sigma.swapPlaceholderSubstitutionsReverse(theta1.getTypeParams()); + + Set theta2Set = candidate.getContentOfPredecessors(); + + for(UnifyType theta2 : theta2Set) + result.add(theta2.apply(sigma)); + } + + } + + if(result.equals(types)) + return result; + return computeGreater(result); + } + + /** + * Computes the greater function for FunN-Types + */ + protected Set computeGreaterFunN(FunNType type) { + Set result = new HashSet<>(); + + // if T = T' then T <=* T' + result.add(type); + + // Because real function types are implicitly variant + // it is enough to permute the params with the values of greater / smaller. + ArrayList> paramCandidates = new ArrayList<>(); + paramCandidates.add(greater(type.getTypeParams().get(0))); + for (int i = 1; i < type.getTypeParams().size(); i++) + paramCandidates.add(smaller(type.getTypeParams().get(i))); + permuteParams(paramCandidates).forEach(x -> result.add(type.setTypeParams(x))); + return result; + } + + + @Override + public Set grArg(UnifyType type) { + return type.grArg(this); + } + + @Override + public Set grArg(ReferenceType type) { + Set result = new HashSet(); + result.add(type); + smaller(type).forEach(x -> result.add(new SuperType(x))); + greater(type).forEach(x -> result.add(new ExtendsType(x))); + return result; + } + + @Override + public Set grArg(FunNType type) { + Set result = new HashSet(); + result.add(type); + smaller(type).forEach(x -> result.add(new SuperType(x))); + greater(type).forEach(x -> result.add(new ExtendsType(x))); + return result; + } + + @Override + public Set grArg(ExtendsType type) { + Set result = new HashSet(); + result.add(type); + UnifyType t = type.getExtendedType(); + greater(t).forEach(x -> result.add(new ExtendsType(x))); + return result; + } + + @Override + public Set grArg(SuperType type) { + Set result = new HashSet(); + result.add(type); + UnifyType t = type.getSuperedType(); + smaller(t).forEach(x -> result.add(new SuperType(x))); + return result; + } + + @Override + public Set grArg(PlaceholderType type) { + HashSet result = new HashSet<>(); + result.add(type); + return result; + } + + @Override + public Set smArg(UnifyType type) { + return type.smArg(this); + } + + @Override + public Set smArg(ReferenceType type) { + Set result = new HashSet(); + result.add(type); + return result; + } + + @Override + public Set smArg(FunNType type) { + Set result = new HashSet(); + result.add(type); + return result; + } + + @Override + public Set smArg(ExtendsType type) { + Set result = new HashSet(); + result.add(type); + UnifyType t = type.getExtendedType(); + result.add(t); + smaller(t).forEach(x -> { + result.add(new ExtendsType(x)); + result.add(x); + }); + return result; + } + + + @Override + public Set smArg(SuperType type) { + Set result = new HashSet(); + result.add(type); + UnifyType t = type.getSuperedType(); + result.add(t); + greater(t).forEach(x -> { + result.add(new SuperType(x)); + result.add(x); + }); + return result; + } + + @Override + public Set smArg(PlaceholderType type) { + HashSet result = new HashSet<>(); + result.add(type); + return result; + } + + @Override + public Set getAllTypesByName(String typeName) { + if(!strInheritanceGraph.containsKey(typeName)) + return new HashSet<>(); + return strInheritanceGraph.get(typeName).stream().map(x -> x.getContent()).collect(Collectors.toCollection(HashSet::new)); + } + + @Override + public Optional getLeftHandedType(String typeName) { + if(!strInheritanceGraph.containsKey(typeName)) + return Optional.empty(); + + for(UnifyPair pair : pairs) + if(pair.getLhsType().getName().equals(typeName)) + return Optional.of(pair.getLhsType()); + + return Optional.empty(); + } + + @Override + public Set getAncestors(UnifyType t) { + if(!inheritanceGraph.containsKey(t)) + return new HashSet<>(); + Set result = inheritanceGraph.get(t).getContentOfPredecessors(); + result.add(t); + return result; + } + + @Override + public Set getChildren(UnifyType t) { + if(!inheritanceGraph.containsKey(t)) + return new HashSet<>(); + Set result = inheritanceGraph.get(t).getContentOfDescendants(); + result.add(t); + return result; + } + + /** + * Takes a set of candidates for each position and computes all possible permutations. + * @param candidates The length of the list determines the number of type params. Each set + * contains the candidates for the corresponding position. + */ + protected Set permuteParams(ArrayList> candidates) { + Set result = new HashSet<>(); + permuteParams(candidates, 0, result, new UnifyType[candidates.size()]); + return result; + } + + /** + * Takes a set of candidates for each position and computes all possible permutations. + * @param candidates The length of the list determines the number of type params. Each set + * contains the candidates for the corresponding position. + * @param idx Idx for the current permutatiton. + * @param result Set of all permutations found so far + * @param current The permutation of type params that is currently explored + */ + protected void permuteParams(ArrayList> candidates, int idx, Set result, UnifyType[] current) { + if(candidates.size() == idx) { + result.add(new TypeParams(Arrays.copyOf(current, current.length))); + return; + } + + Set localCandidates = candidates.get(idx); + + for(UnifyType t : localCandidates) { + current[idx] = t; + permuteParams(candidates, idx+1, result, current); + } + } + + @Override + public String toString(){ + return this.inheritanceGraph.toString(); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/FunNType.java b/src/de/dhbwstuttgart/typeinference/unify/model/FunNType.java new file mode 100644 index 000000000..cf2c86ae5 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/FunNType.java @@ -0,0 +1,88 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; + +/** + * A real function type in java. + * @author Florian Steurer + */ +public class FunNType extends UnifyType { + + /** + * Creates a FunN-Type with the specified TypeParameters. + */ + protected FunNType(TypeParams p) { + super("Fun"+(p.size()-1), p); + } + + /** + * Creates a new FunNType. + * @param tp The parameters of the type. + * @return A FunNType. + * @throws IllegalArgumentException is thrown when there are to few type parameters or there are wildcard-types. + */ + public static FunNType getFunNType(TypeParams tp) throws IllegalArgumentException { + if(tp.size() == 0) + throw new IllegalArgumentException("FunNTypes need at least one type parameter"); + for(UnifyType t : tp) + if(t instanceof WildcardType) + throw new IllegalArgumentException("Invalid TypeParams for a FunNType: " + tp); + return new FunNType(tp); + } + + /** + * Returns the degree of the function type, e.g. 2 for FunN. + */ + public int getN() { + return typeParams.size()-1; + } + + @Override + public UnifyType setTypeParams(TypeParams newTp) { + if(newTp.hashCode() == typeParams.hashCode() && newTp.equals(typeParams)) + return this; + return getFunNType(newTp); + } + + @Override + Set smArg(IFiniteClosure fc) { + return fc.smArg(this); + } + + @Override + Set grArg(IFiniteClosure fc) { + return fc.grArg(this); + } + + @Override + UnifyType apply(Unifier unif) { + // TODO this bypasses the validation of the type parameters. + // Wildcard types can be unified into FunNTypes. + TypeParams newParams = typeParams.apply(unif); + if(newParams.hashCode() == typeParams.hashCode() && newParams.equals(typeParams)) + return this; + + return new FunNType(newParams); + } + + @Override + public int hashCode() { + return 181 + typeParams.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof FunNType)) + return false; + + if(obj.hashCode() != this.hashCode()) + return false; + + FunNType other = (FunNType) obj; + + return other.getTypeParams().equals(typeParams); + } + +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/Node.java b/src/de/dhbwstuttgart/typeinference/unify/model/Node.java new file mode 100644 index 000000000..d24b68253 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/Node.java @@ -0,0 +1,99 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * A node of a directed graph. + * @author Florian Steurer + * + * @param The type of the content of the node. + */ +class Node { + + /** + * The content of the node. + */ + private T content; + + /** + * The set of predecessors + */ + private HashSet> predecessors = new HashSet<>(); + + /** + * The set of descendants + */ + private HashSet> descendants = new HashSet<>(); + + /** + * Creates a node containing the specified content. + */ + public Node(T content) { + this.content = content; + } + + /** + * Adds a directed edge from this node to the descendant (this -> descendant) + */ + public void addDescendant(Node descendant) { + if(descendants.contains(descendant)) + return; + + descendants.add(descendant); + descendant.addPredecessor(this); + } + + /** + * Adds a directed edge from the predecessor to this node (predecessor -> this) + */ + public void addPredecessor(Node predecessor) { + if(predecessors.contains(predecessor)) + return; + + predecessors.add(predecessor); + predecessor.addDescendant(this); + } + + /** + * The content of this node. + */ + public T getContent() { + return content; + } + + /** + * Returns all predecessors (nodes that have a directed edge to this node) + */ + public Set> getPredecessors() { + return predecessors; + } + + /** + * Returns all descendants. All nodes M, where there is a edge from this node to the node M. + * @return + */ + public Set> getDescendants() { + return descendants; + } + + /** + * Retrieves the content of all descendants. + */ + public Set getContentOfDescendants() { + return descendants.stream().map(x -> x.getContent()).collect(Collectors.toSet()); + } + + /** + * Retrieves the content of all predecessors. + */ + public Set getContentOfPredecessors() { + return predecessors.stream().map(x -> x.getContent()).collect(Collectors.toSet()); + } + + @Override + public String toString() { + return "Node(" + content.toString() + ")"; + } +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/PairOperator.java b/src/de/dhbwstuttgart/typeinference/unify/model/PairOperator.java new file mode 100644 index 000000000..fd18f6c02 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/PairOperator.java @@ -0,0 +1,42 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +/** + * Operators of pairs of the unification. + * @author Florian Steurer + */ +public enum PairOperator { + /** + * The smaller operator (T < P) is used to express a subtyping relation between + * T and P for example in the finite closure. It is necessarily true. + */ + SMALLER, + + /** + * The smallerdot operator (T <. P) is used to express a subtyping relation between + * of T and P in a CONSTRAINT during the unification. It is not necessarily true. + */ + SMALLERDOT, + + /** + * The smallerdot operator for arguments (T <.? P) is used to express that + * T is an element of smArg(P) (or P is an element of grArg(T)) in a CONSTRAINT + * during the unification. It is not necessarily true. + */ + SMALLERDOTWC, + + /** + * The equalsdot operator (T =. P) is used to express that two types during the unification + * should be equal. It is not necessarily true. + */ + EQUALSDOT; + + @Override + public String toString() { + switch (this) { + case SMALLER: return "<"; + case SMALLERDOT: return "<."; + case SMALLERDOTWC: return "<.?"; + default: return "=."; // EQUALSDOT + } + } +} \ No newline at end of file diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/PlaceholderType.java b/src/de/dhbwstuttgart/typeinference/unify/model/PlaceholderType.java new file mode 100644 index 000000000..e9268d0d5 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/PlaceholderType.java @@ -0,0 +1,119 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Random; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; + +/** + * An unbounded placeholder type. + * @author Florian Steurer + */ +public final class PlaceholderType extends UnifyType{ + + /** + * Static list containing the names of all existing placeholders. + * Used for generating fresh placeholders. + */ + protected static final HashSet EXISTING_PLACEHOLDERS = new HashSet(); + + /** + * Prefix of auto-generated placeholder names. + */ + protected static String nextName = "gen_"; + + /** + * Random number generator used to generate fresh placeholder name. + */ + protected static Random rnd = new Random(43558747548978L); + + /** + * True if this object was auto-generated, false if this object was user-generated. + */ + private final boolean IsGenerated; + + /** + * Creates a new placeholder type with the specified name. + */ + public PlaceholderType(String name) { + super(name, new TypeParams()); + EXISTING_PLACEHOLDERS.add(name); // Add to list of existing placeholder names + IsGenerated = false; // This type is user generated + } + + /** + * Creates a new placeholdertype + * @param isGenerated true if this placeholder is auto-generated, false if it is user-generated. + */ + protected PlaceholderType(String name, boolean isGenerated) { + super(name, new TypeParams()); + EXISTING_PLACEHOLDERS.add(name); // Add to list of existing placeholder names + IsGenerated = isGenerated; + } + + /** + * Creates a fresh placeholder type with a name that does so far not exist. + * A user could later instantiate a type using the same name that is equivalent to this type. + * @return A fresh placeholder type. + */ + public static PlaceholderType freshPlaceholder() { + String name = nextName + (char) (rnd.nextInt(22) + 97); // Returns random char between 'a' and 'z' + // Add random chars while the name is in use. + while(EXISTING_PLACEHOLDERS.contains(name)); + name += (char) (rnd.nextInt(22) + 97); // Returns random char between 'a' and 'z' + return new PlaceholderType(name, true); + } + + /** + * True if this placeholder is auto-generated, false if it is user-generated. + */ + public boolean isGenerated() { + return IsGenerated; + } + + @Override + Set smArg(IFiniteClosure fc) { + return fc.smArg(this); + } + + @Override + Set grArg(IFiniteClosure fc) { + return fc.grArg(this); + } + + @Override + public UnifyType setTypeParams(TypeParams newTp) { + return this; // Placeholders never have params. + } + + @Override + public int hashCode() { + return typeName.hashCode(); + } + + @Override + UnifyType apply(Unifier unif) { + if(unif.hasSubstitute(this)) + return unif.getSubstitute(this); + return this; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof PlaceholderType)) + return false; + + return ((PlaceholderType) obj).getName().equals(typeName); + } + + + @Override + public Collection getInvolvedPlaceholderTypes() { + ArrayList ret = new ArrayList<>(); + ret.add(this); + return ret; + } +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java b/src/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java new file mode 100644 index 000000000..02ab38a02 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java @@ -0,0 +1,76 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; + +/** + * A reference type e.q. Integer or List. + * @author Florian Steurer + * + */ +public final class ReferenceType extends UnifyType { + + /** + * The buffered hashCode + */ + private final int hashCode; + + public ReferenceType(String name, UnifyType... params) { + super(name, new TypeParams(params)); + hashCode = 31 + 17 * typeName.hashCode() + 17 * typeParams.hashCode(); + } + + public ReferenceType(String name, TypeParams params) { + super(name, params); + hashCode = 31 + 17 * typeName.hashCode() + 17 * typeParams.hashCode(); + } + + @Override + Set smArg(IFiniteClosure fc) { + return fc.smArg(this); + } + + @Override + Set grArg(IFiniteClosure fc) { + return fc.grArg(this); + } + + @Override + UnifyType apply(Unifier unif) { + TypeParams newParams = typeParams.apply(unif); + + if(newParams.hashCode() == typeParams.hashCode() && newParams.equals(typeParams)) + return this; + + return new ReferenceType(typeName, newParams); + } + + @Override + public UnifyType setTypeParams(TypeParams newTp) { + if(newTp.hashCode() == typeParams.hashCode() && newTp.equals(typeParams)) + return this; // reduced the amount of objects created + return new ReferenceType(typeName, newTp); + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof ReferenceType)) + return false; + + if(obj.hashCode() != this.hashCode()) + return false; + + ReferenceType other = (ReferenceType) obj; + + if(!other.getName().equals(typeName)) + return false; + + return other.getTypeParams().equals(typeParams); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/SuperType.java b/src/de/dhbwstuttgart/typeinference/unify/model/SuperType.java new file mode 100644 index 000000000..4f78602f5 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/SuperType.java @@ -0,0 +1,82 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; + +/** + * A super wildcard type e.g. ? super Integer. + * @author Florian Steurer + */ +public final class SuperType extends WildcardType { + + /** + * Creates a new instance "? extends superedType" + * @param superedType The type that is supered e.g. Integer in "? super Integer" + */ + public SuperType(UnifyType superedType) { + super("? super " + superedType.getName(), superedType); + } + + /** + * The type that is supered e.g. Integer in "? super Integer" + */ + public UnifyType getSuperedType() { + return wildcardedType; + } + + @Override + public String toString() { + return "? super " + wildcardedType; + } + + /** + * Sets the type parameters of the wildcarded type and returns a new supertype that supers that type. + */ + @Override + public UnifyType setTypeParams(TypeParams newTp) { + UnifyType newType = wildcardedType.setTypeParams(newTp); + if(newType == wildcardedType) + return this; // Reduced the amount of objects created + return new SuperType(wildcardedType.setTypeParams(newTp)); + } + + @Override + Set smArg(IFiniteClosure fc) { + return fc.smArg(this); + } + + @Override + Set grArg(IFiniteClosure fc) { + return fc.grArg(this); + } + + @Override + UnifyType apply(Unifier unif) { + UnifyType newType = wildcardedType.apply(unif); + if(newType.hashCode() == wildcardedType.hashCode() && newType.equals(wildcardedType)) + return this; // Reduced the amount of objects created + return new SuperType(newType); + } + + @Override + public int hashCode() { + /* + * It is important that the prime that is added is different to the prime added in hashCode() of ExtendsType. + * Otherwise ? extends T and ? super T have the same hashCode() for every Type T. + */ + return wildcardedType.hashCode() + 3917; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof SuperType)) + return false; + + if(obj.hashCode() != this.hashCode()) + return false; + + SuperType other = (SuperType) obj; + return other.getSuperedType().equals(wildcardedType); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java b/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java new file mode 100644 index 000000000..31469ac46 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java @@ -0,0 +1,182 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; + +import de.dhbwstuttgart.typeinference.Menge; + +/** + * The generic or non-generic parameters of a type e.g. for List + * @author Florian Steurer + */ +public final class TypeParams implements Iterable{ + /** + * The array which backs the type parameters. + */ + private final UnifyType[] typeParams; + + /** + * Hashcode calculation is expensive and must be cached. + */ + private final int hashCode; + + /** + * Creates a new set of type parameters. + * @param types The type parameters. + */ + public TypeParams(Menge types){ + typeParams = new UnifyType[types.size()]; + for(int i=0;i x instanceof PlaceholderType); + } + + /** + * Returns the number of the type parameters in this object. + * @return number of type parameters, always positive (including 0). + */ + public int size() { + return typeParams.length; + } + + /** + * Returns true if this object has size() of zero, false otherwise. + */ + public boolean empty() { + return typeParams.length == 0; + } + + /** + * Applies a unifier to every parameter in this object. + * @param unif The applied unifier. + * @return A new type parameter object, where the unifier was applied to every parameter. + */ + public TypeParams apply(Unifier unif) { + UnifyType[] newParams = new UnifyType[typeParams.length]; + + // If true, a type was modified and a new typeparams object has to be created. + // Otherwise it is enough to return this object, since it is immutable + // This reduced the needed TypeParams-Instances for the lambda14-Test from + // 130.000 to 30.000 without a decrease in speed. + boolean isNew = false; + + for(int i = 0; i < typeParams.length; i++) { + UnifyType newType = typeParams[i].apply(unif); + newParams[i] = newType; + if(!isNew && (newType.hashCode() != typeParams[i].hashCode() || !newType.equals(typeParams[i]))) + isNew = true; + } + + if(!isNew) + return this; + return new TypeParams(newParams); + } + + /** + * True if the PlaceholderType t is a parameter of this object, or if any parameter + * contains t (arbitrary depth of recursion), false otherwise. + */ + public boolean occurs(PlaceholderType t) { + for(UnifyType p : typeParams) + if(p instanceof PlaceholderType) + if(p.equals(t)) + return true; + else + if(p.getTypeParams().occurs(t)) + return true; + return false; + } + + /** + * Returns the i-th parameter of this object. + * @throws ArrayOutOfBoundsException if i > this.size()-1. + */ + public UnifyType get(int i) { + return typeParams[i]; + } + + /** + * Sets the the type t as the i-th parameter and returns a new object + * that equals this object, except for the i-th type. + * @throws ArrayOutOfBoundsException if i > this.size()-1. + */ + public TypeParams set(UnifyType t, int idx) { + // Reduce the creation of new objects for less memory + // Reduced the needed instances of TypeParams in the lambda14-Test from + // 150.000 to 130.000 + if(t.hashCode() == typeParams[idx].hashCode() && t.equals(typeParams[idx])) + return this; + UnifyType[] newparams = Arrays.copyOf(typeParams, typeParams.length); + newparams[idx] = t; + return new TypeParams(newparams); + } + + @Override + public Iterator iterator() { + return Arrays.stream(typeParams).iterator(); + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof TypeParams)) + return false; + + if(obj.hashCode() != this.hashCode()) + return false; + + TypeParams other = (TypeParams) obj; + + if(other.size() != this.size()) + return false; + + for(int i = 0; i < this.size(); i++) + if(!(this.get(i).equals(other.get(i)))) + return false; + + return true; + } + + @Override + public String toString() { + String res = ""; + for(UnifyType t : typeParams) + res += t + ","; + return "<" + res.substring(0, res.length()-1) + ">"; + } + + public Collection getInvolvedPlaceholderTypes() { + ArrayList ret = new ArrayList<>(); + for(UnifyType t : typeParams){ + ret.addAll(t.getInvolvedPlaceholderTypes()); + } + return ret; + } +} + diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java b/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java new file mode 100644 index 000000000..2dd7c83f8 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java @@ -0,0 +1,142 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.function.Function; + +/** + * A set of substitutions (s -> t) that is an applicable function to types and pairs. + * @author Florian Steurer + */ +public class Unifier implements Function, Iterable> { + + /** + * The set of substitutions that unify a type-term + */ + private HashMap substitutions = new HashMap<>(); + + /** + * Creates a new instance with a single substitution (source -> target). + * @param The type that is replaced + * @param The type that replaces + */ + public Unifier(PlaceholderType source, UnifyType target) { + substitutions.put(source, target); + } + + /** + * Identity function as an "unifier". + */ + protected Unifier() { + + } + + /** + * Creates an unifier that is the identity function (thus has no substitutions). + */ + public static Unifier identity() { + return new Unifier(); + } + + /** + * Adds a substitution to the unifier from (source -> target) + * @param The type that is replaced + * @param The type that replaces + */ + public void add(PlaceholderType source, UnifyType target) { + Unifier tempU = new Unifier(source, target); + // Every new substitution must be applied to previously added substitutions + // otherwise the unifier needs to be applied multiple times to unify two terms + for(PlaceholderType pt : substitutions.keySet()) + substitutions.put(pt, substitutions.get(pt).apply(tempU)); + substitutions.put(source, target); + } + + @Override + public UnifyType apply(UnifyType t) { + return t.apply(this); + } + + /** + * Applies the unifier to the two terms of the pair. + * @return A new pair where the left and right-hand side are applied + */ + public UnifyPair apply(UnifyPair p) { + return new UnifyPair(this.apply(p.getLhsType()), this.apply(p.getRhsType()), p.getPairOp()); + } + + /** + * True if the typevariable t will be substituted if the unifier is applied. + * false otherwise. + */ + public boolean hasSubstitute(PlaceholderType t) { + return substitutions.containsKey(t); + } + + /** + * Returns the type that will replace the typevariable t if the unifier is applied. + */ + public UnifyType getSubstitute(PlaceholderType t) { + return substitutions.get(t); + } + + /** + * The number of substitutions in the unifier. If zero, this is the identity function. + */ + public int size() { + return substitutions.size(); + } + + /** + * Garantuees that if there is a substitutions (a -> b) in this unifier, + * a is not an element of the targetParams. Substitutions that do not + * satisfy this condition, are swapped. + */ + public void swapPlaceholderSubstitutions(Iterable targetParams) { + for(UnifyType tph : targetParams) { + if(!(tph instanceof PlaceholderType)) + continue; + // Swap a substitutions (a -> b) if a is an element of the target params. + if(substitutions.containsKey(tph)) { + if((substitutions.get(tph) instanceof PlaceholderType)) { + PlaceholderType newLhs = (PlaceholderType) substitutions.get(tph); + substitutions.remove(tph); + substitutions.put(newLhs, tph); + } + } + } + } + + public void swapPlaceholderSubstitutionsReverse(Iterable sourceParams) { + for(UnifyType tph : sourceParams) { + if(!(tph instanceof PlaceholderType)) + continue; + if(substitutions.containsValue(tph)) { + UnifyType key = substitutions.values().stream().filter(x -> x.equals(tph)).findAny().get(); + if(key instanceof PlaceholderType) { + PlaceholderType newLhs = (PlaceholderType) tph; + substitutions.remove(key); + substitutions.put(newLhs, key); + } + } + } + } + + @Override + public String toString() { + String result = "{ "; + for(Entry entry : substitutions.entrySet()) + result += "(" + entry.getKey() + " -> " + entry.getValue() + "), "; + if(!substitutions.isEmpty()) + result = result.substring(0, result.length()-2); + result += " }"; + return result; + } + + @Override + public Iterator> iterator() { + return substitutions.entrySet().iterator(); + } +} + diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java b/src/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java new file mode 100644 index 000000000..988f9b7a0 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java @@ -0,0 +1,99 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * A pair which contains two types and an operator, e.q. (Integer <. a). + * @author Florian Steurer + */ +public class UnifyPair { + + /** + * The type on the left hand side of the pair. + */ + private final UnifyType lhs; + + /** + * The type on the right hand side of the pair. + */ + private final UnifyType rhs; + + /** + * The operator that determines the relation between the left and right hand side type. + */ + private PairOperator pairOp; + + private final int hashCode; + + /** + * Creates a new instance of the pair. + * @param lhs The type on the left hand side of the pair. + * @param rhs The type on the right hand side of the pair. + * @param op The operator that determines the relation between the left and right hand side type. + */ + public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op) { + this.lhs = lhs; + this.rhs = rhs; + pairOp = op; + + // Caching hashcode + hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode(); + } + + /** + * Returns the type on the left hand side of the pair. + */ + public UnifyType getLhsType() { + return lhs; + } + + /** + * Returns the type on the right hand side of the pair. + */ + public UnifyType getRhsType() { + return rhs; + } + + /** + * Returns the operator that determines the relation between the left and right hand side type. + */ + public PairOperator getPairOp() { + return pairOp; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof UnifyPair)) + return false; + + if(obj.hashCode() != this.hashCode()) + return false; + + UnifyPair other = (UnifyPair) obj; + + return other.getPairOp() == pairOp + && other.getLhsType().equals(lhs) + && other.getRhsType().equals(rhs); + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public String toString() { + return "(" + lhs + " " + pairOp + " " + rhs + ")"; + } + + public List getInvolvedPlaceholderTypes() { + ArrayList ret = new ArrayList<>(); + ret.addAll(lhs.getInvolvedPlaceholderTypes()); + ret.addAll(rhs.getInvolvedPlaceholderTypes()); + return ret; + } +} + + diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java b/src/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java new file mode 100644 index 000000000..567181984 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java @@ -0,0 +1,99 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; + +/** + * Represents a java type. + * @author Florian Steurer + */ +public abstract class UnifyType { + + /** + * The name of the type e.q. "Integer", "? extends Integer" or "List" for (List) + */ + protected final String typeName; + + /** + * The type parameters of the type. + */ + protected final TypeParams typeParams; + + /** + * Creates a new instance + * @param name Name of the type (e.q. List for List, Integer or ? extends Integer) + * @param typeParams Parameters of the type (e.q. for List) + */ + protected UnifyType(String name, TypeParams p) { + typeName = name; + typeParams = p; + } + + /** + * Returns the name of the type. + * @return The name e.q. List for List, Integer or ? extends Integer + */ + public String getName() { + return typeName; + } + + /** + * The parameters of the type. + * @return Parameters of the type, e.q. for List. + */ + public TypeParams getTypeParams() { + return typeParams; + } + + /** + * Returns a new type that equals this type except for the type parameters. + * @param newTp The type params of the new type. + * @return A new type object. + */ + public abstract UnifyType setTypeParams(TypeParams newTp); + + /** + * Implementation of the visitor-pattern. Returns the set of smArg + * by calling the most specific overload in the FC. + * @param fc The FC that is called. + * @return The set that is smArg(this) + */ + abstract Set smArg(IFiniteClosure fc); + + /** + * Implementation of the visitor-pattern. Returns the set of grArg + * by calling the most specific overload in the FC. + * @param fc The FC that is called. + * @return The set that is grArg(this) + */ + abstract Set grArg(IFiniteClosure fc); + + /** + * Applies a unifier to this object. + * @param unif The unifier + * @return A UnifyType, that may or may not be a new object, that has its subtypes substituted. + */ + abstract UnifyType apply(Unifier unif); + + @Override + public String toString() { + String params = ""; + if(typeParams.size() != 0) { + for(UnifyType param : typeParams) + params += param.toString() + ","; + params = "<" + params.substring(0, params.length()-1) + ">"; + } + + return typeName + params; + } + + public Collection getInvolvedPlaceholderTypes() { + ArrayList ret = new ArrayList<>(); + ret.addAll(typeParams.getInvolvedPlaceholderTypes()); + return ret; + } +} \ No newline at end of file diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/WildcardType.java b/src/de/dhbwstuttgart/typeinference/unify/model/WildcardType.java new file mode 100644 index 000000000..2bc514601 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/WildcardType.java @@ -0,0 +1,67 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * A wildcard type that is either a ExtendsType or a SuperType. + * @author Florian Steurer + */ +public abstract class WildcardType extends UnifyType { + + /** + * The wildcarded type, e.q. Integer for ? extends Integer. Never a wildcard type itself. + */ + protected UnifyType wildcardedType; + + /** + * Creates a new instance. + * @param name The name of the type, e.q. ? extends Integer + * @param wildcardedType The wildcarded type, e.q. Integer for ? extends Integer. Never a wildcard type itself. + */ + protected WildcardType(String name, UnifyType wildcardedType) { + super(name, wildcardedType.getTypeParams()); + this.wildcardedType = wildcardedType; + } + + /** + * Returns the wildcarded type, e.q. Integer for ? extends Integer. + * @return The wildcarded type. Never a wildcard type itself. + */ + public UnifyType getWildcardedType() { + return wildcardedType; + } + + /** + * Returns the type parameters of the WILDCARDED TYPE. + */ + @Override + public TypeParams getTypeParams() { + return wildcardedType.getTypeParams(); + } + + @Override + public int hashCode() { + return wildcardedType.hashCode() + getName().hashCode() + 17; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof WildcardType)) + return false; + + if(obj.hashCode() != this.hashCode()) + return false; + + WildcardType other = (WildcardType) obj; + return other.getWildcardedType().equals(wildcardedType); + } + + + @Override + public Collection getInvolvedPlaceholderTypes() { + ArrayList ret = new ArrayList<>(); + ret.addAll(wildcardedType.getInvolvedPlaceholderTypes()); + return ret; + } +} diff --git a/test/KomplexeMenge/KarthesischesProduktTest.java b/test/KomplexeMenge/KarthesischesProduktTest.java new file mode 100644 index 000000000..89979df8e --- /dev/null +++ b/test/KomplexeMenge/KarthesischesProduktTest.java @@ -0,0 +1,129 @@ +package KomplexeMenge; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import de.dhbwstuttgart.typeinference.EinzelElement; +import de.dhbwstuttgart.typeinference.KomplexeMenge; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.OderMenge; +import de.dhbwstuttgart.typeinference.UndMenge; + +class TestOderMenge extends OderMenge{ + Menge set = new Menge<>(); + + @Override + public Menge> getSet() { + return set; + } + + public void addItem(String string) { + TestUndMenge toAdd = new TestUndMenge(); + toAdd.addItem(string); + set.add(toAdd); + } + public void addItems(TestUndMenge undMenge) { + set.add(undMenge); + } +} + +class TestUndMenge extends UndMenge{ + Menge> set = new Menge<>(); + + @Override + public Menge> getSet() { + return set; + } + public void addItem(String string) { + set.add(new EinzelElement(string)); + } + + public void addItems(KomplexeMenge oderMenge) { + set.add(oderMenge); + } +} + +public class KarthesischesProduktTest { + + + @Test + public void test() { + TestOderMenge oM1 = new TestOderMenge(); + TestOderMenge oM2 = new TestOderMenge(); + TestUndMenge oM3 = new TestUndMenge(); + oM1.addItem("Menge 1, Item 1"); + oM1.addItem("Menge 1, Item 2"); + oM2.addItem("Menge 2, Item 1"); + oM2.addItem("Menge 2, Item 2"); + oM3.addItems(oM1); + oM3.addItems(oM2); + System.out.println(oM3.cartesianProduct()); + assertTrue(oM3.cartesianProduct().size()==4); + } + + @Test + public void test2(){ + TestUndMenge oM1 = new TestUndMenge(); + TestUndMenge oM2 = new TestUndMenge(); + TestUndMenge oM3 = new TestUndMenge(); + oM1.addItem("Menge 1, Item 1"); + oM1.addItem("Menge 1, Item 2"); + oM2.addItem("Menge 2, Item 1"); + oM2.addItem("Menge 2, Item 2"); + oM3.addItems(oM1); + oM3.addItems(oM2); + System.out.println("undMenge:"+oM3.cartesianProduct()); + assertTrue(oM3.cartesianProduct().size()==1); + } + + @Test + public void test3(){ + TestOderMenge oM1 = new TestOderMenge(); + TestUndMenge oM2 = new TestUndMenge(); + TestUndMenge oM3 = new TestUndMenge(); + oM1.addItem("Menge 1, Item 1"); + oM1.addItem("Menge 1, Item 2"); + oM2.addItem("Menge 2, Item 1"); + oM2.addItem("Menge 2, Item 2"); + oM3.addItems(oM1); + oM3.addItems(oM2); + //System.out.println("undMenge:"+oM3.cartesianProduct()); + assertTrue(oM3.cartesianProduct().size()==2); + } + + @Test + public void test4(){ + TestOderMenge oM1 = new TestOderMenge(); + TestUndMenge oM2 = new TestUndMenge(); + TestUndMenge oM3 = new TestUndMenge(); + oM2.addItem("Menge 2, Item 1"); + oM2.addItem("Menge 2, Item 2"); + oM3.addItems(oM1); + oM3.addItems(oM2); + //System.out.println("undMenge:"+oM3.cartesianProduct()); + assertTrue(oM3.cartesianProduct().size()==0); + } + + @Test + public void test5(){ + TestOderMenge oM1 = new TestOderMenge(); + TestUndMenge oM2 = new TestUndMenge(); + TestUndMenge oM3 = new TestUndMenge(); + oM3.addItems(oM1); + oM3.addItems(oM2); + //System.out.println("undMenge:"+oM3.cartesianProduct()); + assertTrue(oM3.cartesianProduct().size()==0); + } + + @Test + public void test6(){ + TestOderMenge oM1 = new TestOderMenge(); + TestOderMenge oM2 = new TestOderMenge(); + TestUndMenge oM3 = new TestUndMenge(); + oM3.addItems(oM1); + oM3.addItems(oM2); + //System.out.println("undMenge:"+oM3.cartesianProduct()); + assertTrue(oM3.cartesianProduct().size()==0); + } +} diff --git a/test/KomplexeMenge/KeineDoppeltenVerweise.java b/test/KomplexeMenge/KeineDoppeltenVerweise.java new file mode 100644 index 000000000..606783f88 --- /dev/null +++ b/test/KomplexeMenge/KeineDoppeltenVerweise.java @@ -0,0 +1,107 @@ +package KomplexeMenge; + +import static org.junit.Assert.*; + +import java.util.Set; +import java.util.Vector; + +import org.junit.Test; + +import de.dhbwstuttgart.typeinference.EinzelElement; +import de.dhbwstuttgart.typeinference.KomplexeMenge; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.OderMenge; +import de.dhbwstuttgart.typeinference.UndMenge; + +class TestKlasse { + static int identifier = 0; + public String name; + int id; + + TestKlasse(String name){ + this.name = name; + id = 0; + } + + public String toString(){ + return name+" #"+id; + } +} + +class TestKlasseOderMenge extends OderMenge{ + Menge set = new Menge<>(); + + @Override + public Menge> getSet() { + return set; + } + + public void addItem(TestKlasse string) { + TestKlasseUndMenge toAdd = new TestKlasseUndMenge(); + toAdd.addItem(string); + set.add(toAdd); + } + public void addItems(TestKlasseUndMenge undMenge) { + set.add(undMenge); + } +} + +class TestKlasseUndMenge extends UndMenge{ + Menge> set = new Menge<>(); + + @Override + public Menge> getSet() { + return set; + } + public void addItem(TestKlasse string) { + set.add(new EinzelElement(string)); + } + + public void addItems(KomplexeMenge oderMenge) { + set.add(oderMenge); + } +} + +/** + * @Depreciated + * Tests möglicherweise obsolet + */ +public class KeineDoppeltenVerweise { + + @Test + public void test() { + TestKlasseOderMenge oM1 = new TestKlasseOderMenge(); + TestKlasseOderMenge oM2 = new TestKlasseOderMenge(); + TestKlasseUndMenge oM3 = new TestKlasseUndMenge(); + oM1.addItem(new TestKlasse("Menge 1, Item 1")); + oM1.addItem(new TestKlasse("Menge 1, Item 2")); + oM2.addItem(new TestKlasse("Menge 2, Item 1")); + oM2.addItem(new TestKlasse("Menge 2, Item 2")); + oM3.addItems(oM1); + oM3.addItems(oM2); + Set> cP = oM3.cartesianProduct(); + System.out.println(cP); + cP.iterator().next().iterator().next().name="neu"; + System.out.println(cP); + //check(cP); //TODO Muss neu implementiert werden + } + + private void check(Menge> cP){ + Menge allElements = new Menge<>(); + for(Vector v : cP)for(A i : v){ + Object o = containsRef(allElements, i); + if(o!=null){ + fail("Ein Verweis ist im Karthesischen Produkt doppelt vorhanden: "+o+" == "+i); + }else{ + allElements.add(i); + } + } + } + + private Object containsRef(Menge v, Object i){ + for(Object o : v){ + if(i == o)return o; + } + return null; + } +} diff --git a/test/bytecode/ASTBytecodeTest.java b/test/bytecode/ASTBytecodeTest.java new file mode 100644 index 000000000..f170b49fc --- /dev/null +++ b/test/bytecode/ASTBytecodeTest.java @@ -0,0 +1,90 @@ +package bytecode; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +import org.apache.bcel.classfile.JavaClass; + +import de.dhbwstuttgart.bytecode.ClassGenerator; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.ResultSet; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.TypeinferenceResults; + +public abstract class ASTBytecodeTest { + protected Class getClassToTest(){ + Class classToTest = null; + try { + ClassLoader classLoader = getClassLoader(); + + classToTest = classLoader.loadClass(getTestName()); + + + } catch (Exception e) { + throw new RuntimeException(e); + } + + return classToTest; + } + + protected ClassLoader getClassLoader() throws Exception{ + File file = new File(getRootDirectory()); + URL url = file.toURL(); + URL[] urls = new URL[]{url}; + + return new URLClassLoader(urls); + } + + public ASTBytecodeTest(){ + LoggerConfiguration logConfig = new LoggerConfiguration().setOutput(Section.PARSER, System.out); + MyCompilerAPI compiler = MyCompiler.getAPI(logConfig); + try { + TypeinferenceResults results = getResults(); + Menge sourceFiles = new Menge<>(); + sourceFiles.add(getSourceFile()); + + Menge bytecode = compiler.generateBytecode(sourceFiles, results); + + ByteCodeResult result = bytecode.firstElement(); + + String rootDirectory = getRootDirectory(); + + JavaClass javaClass = result.getByteCode().getJavaClass(); + javaClass.dump(new File(rootDirectory+javaClass.getClassName()+".class")); + + for(ClassGenerator cg: result.getByteCode().getExtraClasses().values()){ + JavaClass jc = cg.getJavaClass(); + jc.dump(new File(rootDirectory+jc.getClassName()+".class")); + } + + }catch(Exception e){ + throw new RuntimeException(e); + } + } + + public SourceFile getSourceFile() { + return new SourceFile(); + } + + public TypeinferenceResults getResults() { + Menge results = new Menge<>(); + results.add(new TypeinferenceResultSet(getSourceFile().KlassenVektor.get(0), new Menge(), new ResultSet())); + + return new TypeinferenceResults(results); + } + + public String getRootDirectory() { + return System.getProperty("user.dir")+"/test/bytecode/"; + } + + public String getTestName() { + return "No Testname defined!"; + } +} diff --git a/test/bytecode/Assign.jav b/test/bytecode/Assign.jav new file mode 100644 index 000000000..02fb4b6ee --- /dev/null +++ b/test/bytecode/Assign.jav @@ -0,0 +1,10 @@ +class Assign{ + +void method() { +a; +a = 20; +b; +b=59; +} + +} \ No newline at end of file diff --git a/test/bytecode/AssignTest.java b/test/bytecode/AssignTest.java new file mode 100644 index 000000000..03a328651 --- /dev/null +++ b/test/bytecode/AssignTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class AssignTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Assign"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/Binary.jav b/test/bytecode/Binary.jav new file mode 100644 index 000000000..3ea073fb3 --- /dev/null +++ b/test/bytecode/Binary.jav @@ -0,0 +1,10 @@ +class Binary{ + +void method() { +a; +a = 20; +b; +b=59 + a; +} + +} \ No newline at end of file diff --git a/test/bytecode/Binary2.jav b/test/bytecode/Binary2.jav new file mode 100644 index 000000000..e89672ac1 --- /dev/null +++ b/test/bytecode/Binary2.jav @@ -0,0 +1,8 @@ + +class Binary2 { + + Integer m(Integer x) { return x + x; } + + Boolean m(Boolean x) {return x || x; } + +} \ No newline at end of file diff --git a/test/bytecode/BinaryTest.java b/test/bytecode/BinaryTest.java new file mode 100644 index 000000000..3e73a2eaf --- /dev/null +++ b/test/bytecode/BinaryTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class BinaryTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Binary"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/BinaryTest2.java b/test/bytecode/BinaryTest2.java new file mode 100644 index 000000000..5ea335142 --- /dev/null +++ b/test/bytecode/BinaryTest2.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class BinaryTest2 extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Binary2"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/BoolLit.jav b/test/bytecode/BoolLit.jav new file mode 100644 index 000000000..1fa4ac311 --- /dev/null +++ b/test/bytecode/BoolLit.jav @@ -0,0 +1,7 @@ +class BoolLit{ + +void method() { b; b = false; } + + + +} \ No newline at end of file diff --git a/test/bytecode/BoolLitTest.java b/test/bytecode/BoolLitTest.java new file mode 100644 index 000000000..be459e8d8 --- /dev/null +++ b/test/bytecode/BoolLitTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class BoolLitTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "BoolLit"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/CharLitTest.java b/test/bytecode/CharLitTest.java new file mode 100644 index 000000000..87b35013c --- /dev/null +++ b/test/bytecode/CharLitTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class CharLitTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "CharLit"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/Condition.jav b/test/bytecode/Condition.jav new file mode 100644 index 000000000..4f68e8ab0 --- /dev/null +++ b/test/bytecode/Condition.jav @@ -0,0 +1,7 @@ +class Condition{ + + Boolean method() { + return 0 == 1; + } + +} \ No newline at end of file diff --git a/test/bytecode/ConditionTest.java b/test/bytecode/ConditionTest.java new file mode 100644 index 000000000..dfbbadf92 --- /dev/null +++ b/test/bytecode/ConditionTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class ConditionTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Condition"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/EmptyClass.jav b/test/bytecode/EmptyClass.jav new file mode 100644 index 000000000..381162fa4 --- /dev/null +++ b/test/bytecode/EmptyClass.jav @@ -0,0 +1,7 @@ +class EmptyClass{ + + + + + +} \ No newline at end of file diff --git a/test/bytecode/EmptyClassTest.java b/test/bytecode/EmptyClassTest.java new file mode 100644 index 000000000..6050dd37f --- /dev/null +++ b/test/bytecode/EmptyClassTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class EmptyClassTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "EmptyClass"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/FieldDeclaration.jav b/test/bytecode/FieldDeclaration.jav new file mode 100644 index 000000000..14d4f9bd7 --- /dev/null +++ b/test/bytecode/FieldDeclaration.jav @@ -0,0 +1,8 @@ +class FieldDeclaration{ + Integer integer = 20; + FieldDeclaration field = methode(); + + FieldDeclaration methode(){ + return this; + } +} \ No newline at end of file diff --git a/test/bytecode/FieldDeclarationTest.java b/test/bytecode/FieldDeclarationTest.java new file mode 100644 index 000000000..ea6b80622 --- /dev/null +++ b/test/bytecode/FieldDeclarationTest.java @@ -0,0 +1,21 @@ +package bytecode; + +import org.junit.Test; + +public class FieldDeclarationTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "FieldDeclaration"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/ForTest.jav b/test/bytecode/ForTest.jav new file mode 100644 index 000000000..d2723cf4c --- /dev/null +++ b/test/bytecode/ForTest.jav @@ -0,0 +1,7 @@ +class ForTest{ + void method(){ + for(Integer i = 0; i < 10 ; i = i + 1){ + + } + } +} \ No newline at end of file diff --git a/test/bytecode/ForTest.java b/test/bytecode/ForTest.java new file mode 100644 index 000000000..d34b2a631 --- /dev/null +++ b/test/bytecode/ForTest.java @@ -0,0 +1,22 @@ +package bytecode; + +import org.junit.Ignore; +import org.junit.Test; + +public class ForTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "ForTest"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/Fun0.java b/test/bytecode/Fun0.java new file mode 100644 index 000000000..da05fdb13 --- /dev/null +++ b/test/bytecode/Fun0.java @@ -0,0 +1,3 @@ +interface Fun0{ + A apply(); +} diff --git a/test/bytecode/Id.jav b/test/bytecode/Id.jav new file mode 100644 index 000000000..ceebc1f77 --- /dev/null +++ b/test/bytecode/Id.jav @@ -0,0 +1,5 @@ +class Id{ + +Fun1 method() { return (x)-> x; } + +} \ No newline at end of file diff --git a/test/bytecode/IdTest.java b/test/bytecode/IdTest.java new file mode 100644 index 000000000..e7185ca54 --- /dev/null +++ b/test/bytecode/IdTest.java @@ -0,0 +1,21 @@ +package bytecode; + +import org.junit.Test; + +public class IdTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Id"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/Identity.jav b/test/bytecode/Identity.jav new file mode 100644 index 000000000..4524c60b5 --- /dev/null +++ b/test/bytecode/Identity.jav @@ -0,0 +1,7 @@ +class Identity{ +op = (x)->x; + +m(){ + op.apply(1); + } +} \ No newline at end of file diff --git a/test/bytecode/IdentityField.jav b/test/bytecode/IdentityField.jav new file mode 100644 index 000000000..8063d0b30 --- /dev/null +++ b/test/bytecode/IdentityField.jav @@ -0,0 +1,3 @@ +class IdentityField { + Fun1 op = (x) -> x; +} \ No newline at end of file diff --git a/test/bytecode/IdentityFieldTest.java b/test/bytecode/IdentityFieldTest.java new file mode 100644 index 000000000..2a6e7ecd6 --- /dev/null +++ b/test/bytecode/IdentityFieldTest.java @@ -0,0 +1,21 @@ +package bytecode; + +import org.junit.Test; + +public class IdentityFieldTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "IdentityField"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/IdentityTest.java b/test/bytecode/IdentityTest.java new file mode 100644 index 000000000..2aa2563e4 --- /dev/null +++ b/test/bytecode/IdentityTest.java @@ -0,0 +1,21 @@ +package bytecode; + +import org.junit.Test; + +public class IdentityTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Identity"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/IfElseIfStatement.jav b/test/bytecode/IfElseIfStatement.jav new file mode 100644 index 000000000..caf9d524a --- /dev/null +++ b/test/bytecode/IfElseIfStatement.jav @@ -0,0 +1,12 @@ +class IfElseIfStatement{ + method(flag){ + if(flag){ + return 0; + }else if(flag){ + return 1; + }else{ + return 2; + } + } + +} \ No newline at end of file diff --git a/test/bytecode/IfElseIfStatementTest.java b/test/bytecode/IfElseIfStatementTest.java new file mode 100644 index 000000000..6e60d3a64 --- /dev/null +++ b/test/bytecode/IfElseIfStatementTest.java @@ -0,0 +1,21 @@ +package bytecode; + +import org.junit.Test; + +public class IfElseIfStatementTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "IfElseIfStatement"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/IfElseStatement.jav b/test/bytecode/IfElseStatement.jav new file mode 100644 index 000000000..aa57a9ecd --- /dev/null +++ b/test/bytecode/IfElseStatement.jav @@ -0,0 +1,9 @@ +class IfElseStatement{ + Integer method(Boolean flag){ + if(flag){ + return 0; + }else{ + return 1; + } + } +} \ No newline at end of file diff --git a/test/bytecode/IfElseStatementTest.java b/test/bytecode/IfElseStatementTest.java new file mode 100644 index 000000000..3209b8d1e --- /dev/null +++ b/test/bytecode/IfElseStatementTest.java @@ -0,0 +1,21 @@ +package bytecode; + +import org.junit.Test; + +public class IfElseStatementTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "IfElseStatement"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/IfStatement.jav b/test/bytecode/IfStatement.jav new file mode 100644 index 000000000..d9fdb16c3 --- /dev/null +++ b/test/bytecode/IfStatement.jav @@ -0,0 +1,7 @@ +class IfStatement{ + method(flag){ + if(flag){ + + } + } +} \ No newline at end of file diff --git a/test/bytecode/IfStatementTest.java b/test/bytecode/IfStatementTest.java new file mode 100644 index 000000000..baa8b9064 --- /dev/null +++ b/test/bytecode/IfStatementTest.java @@ -0,0 +1,21 @@ +package bytecode; + +import org.junit.Test; + +public class IfStatementTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "IfStatement"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/LambdaExpr.jav b/test/bytecode/LambdaExpr.jav new file mode 100644 index 000000000..3339ec0e2 --- /dev/null +++ b/test/bytecode/LambdaExpr.jav @@ -0,0 +1,9 @@ +class LambdaExpr { + + method() { + + lambda; + lambda = (Integer a) -> a; + return lambda; + } +} \ No newline at end of file diff --git a/test/bytecode/LambdaExpr2.jav b/test/bytecode/LambdaExpr2.jav new file mode 100644 index 000000000..39e6cfd51 --- /dev/null +++ b/test/bytecode/LambdaExpr2.jav @@ -0,0 +1,8 @@ +class LambdaExpr2 { + + op = ()->method(); + + method() { + return 2; + } +} \ No newline at end of file diff --git a/test/bytecode/LambdaExpr2Test.java b/test/bytecode/LambdaExpr2Test.java new file mode 100644 index 000000000..ac85b8d05 --- /dev/null +++ b/test/bytecode/LambdaExpr2Test.java @@ -0,0 +1,40 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Ignore; +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class LambdaExpr2Test extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "LambdaExpr"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/LambdaExprTest.java b/test/bytecode/LambdaExprTest.java new file mode 100644 index 000000000..c6b8e0f5e --- /dev/null +++ b/test/bytecode/LambdaExprTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class LambdaExprTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "LambdaExpr"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/LambdaRunnable.jav b/test/bytecode/LambdaRunnable.jav new file mode 100644 index 000000000..eb2c69c1a --- /dev/null +++ b/test/bytecode/LambdaRunnable.jav @@ -0,0 +1,7 @@ +class LambdaRunnable { + + op = ()->method(); + + void method() { + } +} \ No newline at end of file diff --git a/test/bytecode/LambdaRunnableTest.java b/test/bytecode/LambdaRunnableTest.java new file mode 100644 index 000000000..c2d3a4bd4 --- /dev/null +++ b/test/bytecode/LambdaRunnableTest.java @@ -0,0 +1,40 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Ignore; +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class LambdaRunnableTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "LambdaRunnable"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/Main.jav b/test/bytecode/Main.jav new file mode 100644 index 000000000..3e87c03e8 --- /dev/null +++ b/test/bytecode/Main.jav @@ -0,0 +1,6 @@ +class Main{ + +public static void main(String[] args){ +} + +} \ No newline at end of file diff --git a/test/bytecode/MainTest.java b/test/bytecode/MainTest.java new file mode 100644 index 000000000..97abece42 --- /dev/null +++ b/test/bytecode/MainTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class MainTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Main"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/Matrix_lambda.jav b/test/bytecode/Matrix_lambda.jav new file mode 100644 index 000000000..f531d2ba2 --- /dev/null +++ b/test/bytecode/Matrix_lambda.jav @@ -0,0 +1,5 @@ +import java.util.Vector; + +class Matrix_lambda extends Vector> { + op = (Matrix m) -> (f) -> f.apply(this, m); +} \ No newline at end of file diff --git a/test/bytecode/Matrix_lambda2.jav b/test/bytecode/Matrix_lambda2.jav new file mode 100644 index 000000000..667e02e29 --- /dev/null +++ b/test/bytecode/Matrix_lambda2.jav @@ -0,0 +1,4 @@ + +class Matrix_lambda2 { + op = (f) -> f.apply(2); +} \ No newline at end of file diff --git a/test/bytecode/Matrix_lambda3.jav b/test/bytecode/Matrix_lambda3.jav new file mode 100644 index 000000000..f0341cdc6 --- /dev/null +++ b/test/bytecode/Matrix_lambda3.jav @@ -0,0 +1,4 @@ + +class Matrix_lambda3 { + op = (f) -> f.apply(); +} \ No newline at end of file diff --git a/test/bytecode/Matrix_lambdaTest.java b/test/bytecode/Matrix_lambdaTest.java new file mode 100644 index 000000000..5d8b4e39d --- /dev/null +++ b/test/bytecode/Matrix_lambdaTest.java @@ -0,0 +1,21 @@ +package bytecode; + +import org.junit.Test; + +public class Matrix_lambdaTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Matrix_lambda"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/Matrix_lambdaTest2.java b/test/bytecode/Matrix_lambdaTest2.java new file mode 100644 index 000000000..374802a3c --- /dev/null +++ b/test/bytecode/Matrix_lambdaTest2.java @@ -0,0 +1,21 @@ +package bytecode; + +import org.junit.Test; + +public class Matrix_lambdaTest2 extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Matrix_lambda2"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/Matrix_lambdaTest3.java b/test/bytecode/Matrix_lambdaTest3.java new file mode 100644 index 000000000..6addc9fd9 --- /dev/null +++ b/test/bytecode/Matrix_lambdaTest3.java @@ -0,0 +1,21 @@ +package bytecode; + +import org.junit.Test; + +public class Matrix_lambdaTest3 extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Matrix_lambda3"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/MethodAndVariable.jav b/test/bytecode/MethodAndVariable.jav new file mode 100644 index 000000000..2ae7002ed --- /dev/null +++ b/test/bytecode/MethodAndVariable.jav @@ -0,0 +1,18 @@ +class MethodAndVariable{ + public Integer method(Integer parameter){ + Integer lokaleVariable; + lokaleVariable = 2; + + Integer lokaleVariable2; + lokaleVariable2 = method2(lokaleVariable); + + return parameter+lokaleVariable2; + } + + public Integer method2(Integer parameter){ + Integer lokaleVariable; + lokaleVariable = 2; + + return parameter+lokaleVariable; + } +} \ No newline at end of file diff --git a/test/bytecode/MethodCall.jav b/test/bytecode/MethodCall.jav new file mode 100644 index 000000000..1ae031d53 --- /dev/null +++ b/test/bytecode/MethodCall.jav @@ -0,0 +1,9 @@ +class MethodCall{ + +void method() { +method2(); +} + +void method2(){} + +} \ No newline at end of file diff --git a/test/bytecode/MethodCallTest.java b/test/bytecode/MethodCallTest.java new file mode 100644 index 000000000..c5bfa3522 --- /dev/null +++ b/test/bytecode/MethodCallTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class MethodCallTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "MethodCall"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/MethodEmpty.jav b/test/bytecode/MethodEmpty.jav new file mode 100644 index 000000000..e2c5d97a0 --- /dev/null +++ b/test/bytecode/MethodEmpty.jav @@ -0,0 +1,7 @@ +class MethodEmpty{ + + +void method() { } + + +} \ No newline at end of file diff --git a/test/bytecode/MethodEmpty.java b/test/bytecode/MethodEmpty.java new file mode 100644 index 000000000..ce72531be --- /dev/null +++ b/test/bytecode/MethodEmpty.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class MethodEmpty extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "MethodEmpty"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/MethodEmptyRetType.jav b/test/bytecode/MethodEmptyRetType.jav new file mode 100644 index 000000000..84dbc7098 --- /dev/null +++ b/test/bytecode/MethodEmptyRetType.jav @@ -0,0 +1,7 @@ +class MethodEmptyRetType{ + + +Object method() { return null; } + + +} \ No newline at end of file diff --git a/test/bytecode/MethodEmptyRetType.java b/test/bytecode/MethodEmptyRetType.java new file mode 100644 index 000000000..82f8848be --- /dev/null +++ b/test/bytecode/MethodEmptyRetType.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class MethodEmptyRetType extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "MethodEmptyRetType"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/MethodsAndVariableTest.java b/test/bytecode/MethodsAndVariableTest.java new file mode 100644 index 000000000..8e0fd808f --- /dev/null +++ b/test/bytecode/MethodsAndVariableTest.java @@ -0,0 +1,26 @@ +package bytecode; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + + +public class MethodsAndVariableTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "MethodAndVariable"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/MultiClass.jav b/test/bytecode/MultiClass.jav new file mode 100644 index 000000000..11114b32a --- /dev/null +++ b/test/bytecode/MultiClass.jav @@ -0,0 +1,5 @@ +class MultiClass{ +} + +class MultiClass2{ +} \ No newline at end of file diff --git a/test/bytecode/MultiClassTest.java b/test/bytecode/MultiClassTest.java new file mode 100644 index 000000000..54b51f47a --- /dev/null +++ b/test/bytecode/MultiClassTest.java @@ -0,0 +1,49 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class MultiClassTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "MultiClass"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } + + @Test + public void testConstruct2() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName+2); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/NewArray.jav b/test/bytecode/NewArray.jav new file mode 100644 index 000000000..ff311c25d --- /dev/null +++ b/test/bytecode/NewArray.jav @@ -0,0 +1,11 @@ +class NewArray{ + +void method() { +a; +a = new Integer[2]; +a = {1,2}; +} + + + +} \ No newline at end of file diff --git a/test/bytecode/NewClass.jav b/test/bytecode/NewClass.jav new file mode 100644 index 000000000..6343c9d0c --- /dev/null +++ b/test/bytecode/NewClass.jav @@ -0,0 +1,7 @@ +class NewClass{ + String method() { + String a; + a = new String(); + return a; + } +} \ No newline at end of file diff --git a/test/bytecode/NewClassTest.java b/test/bytecode/NewClassTest.java new file mode 100644 index 000000000..5757d32d5 --- /dev/null +++ b/test/bytecode/NewClassTest.java @@ -0,0 +1,61 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URL; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class NewClassTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "NewClass"; + } + + @Test + public void testInit() throws Exception { + ClassLoader cl = getClassLoader(); + + cl.loadClass(testName).newInstance(); + } + + @Test + public void testMethod() throws Exception { + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + File file = new File(rootDirectory); + URL url = file.toURL(); + URL[] urls = new URL[]{url}; + + + Class[] params = new Class[0]; + + Method method = cls.getDeclaredMethod("method", params); + Object returnValue = method.invoke(obj); + assertTrue(returnValue instanceof String); + }catch(Exception e){ + throw new RuntimeException(e); + } + } +} diff --git a/test/bytecode/NewStatement.jav b/test/bytecode/NewStatement.jav new file mode 100644 index 000000000..c654c1161 --- /dev/null +++ b/test/bytecode/NewStatement.jav @@ -0,0 +1,10 @@ +class NewStatement{ +public NewStatement(Integer i){} +public NewStatement(String i){} +method() { + NewStatement n; + n = new NewStatement("hallo"); + n = new NewStatement(1); +} + +} \ No newline at end of file diff --git a/test/bytecode/NewStatementTest.java b/test/bytecode/NewStatementTest.java new file mode 100644 index 000000000..6f930699c --- /dev/null +++ b/test/bytecode/NewStatementTest.java @@ -0,0 +1,42 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class NewStatementTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "NewStatement"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/OL.jav b/test/bytecode/OL.jav new file mode 100755 index 000000000..5c102f6a7 --- /dev/null +++ b/test/bytecode/OL.jav @@ -0,0 +1,16 @@ +class OL { + + m(Integer x) { return x + x; } + + m(Boolean x) {return x || x; } +} + +class Main { + + main(x) { + ol; + ol = new OL(); + return ol.m(x); + } + +} diff --git a/test/bytecode/OLTest.java b/test/bytecode/OLTest.java new file mode 100644 index 000000000..e8cdd5ee7 --- /dev/null +++ b/test/bytecode/OLTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class OLTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "OL"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/Parameter.jav b/test/bytecode/Parameter.jav new file mode 100644 index 000000000..185176792 --- /dev/null +++ b/test/bytecode/Parameter.jav @@ -0,0 +1,3 @@ +class Parameter{ + public String param; +} \ No newline at end of file diff --git a/test/bytecode/ParameterTest.java b/test/bytecode/ParameterTest.java new file mode 100644 index 000000000..09993db35 --- /dev/null +++ b/test/bytecode/ParameterTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class ParameterTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Parameter"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/PostDecrement.jav b/test/bytecode/PostDecrement.jav new file mode 100644 index 000000000..7622014f5 --- /dev/null +++ b/test/bytecode/PostDecrement.jav @@ -0,0 +1,6 @@ +class PostIncrement{ + +void method() {a; a = 20; a--;} + + +} \ No newline at end of file diff --git a/test/bytecode/PostDecrement.java b/test/bytecode/PostDecrement.java new file mode 100644 index 000000000..6ab8bbf37 --- /dev/null +++ b/test/bytecode/PostDecrement.java @@ -0,0 +1,40 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Ignore; +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class PostDecrement extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "PostDecrement"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/PostIncrement.jav b/test/bytecode/PostIncrement.jav new file mode 100644 index 000000000..463546c40 --- /dev/null +++ b/test/bytecode/PostIncrement.jav @@ -0,0 +1,6 @@ +class PostIncrement{ + +void method() {a; a = 20; a++;} + + +} \ No newline at end of file diff --git a/test/bytecode/PostIncrement.java b/test/bytecode/PostIncrement.java new file mode 100644 index 000000000..83f189dc8 --- /dev/null +++ b/test/bytecode/PostIncrement.java @@ -0,0 +1,40 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Ignore; +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class PostIncrement extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "PostIncrement"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/Return.jav b/test/bytecode/Return.jav new file mode 100644 index 000000000..7486dc494 --- /dev/null +++ b/test/bytecode/Return.jav @@ -0,0 +1,8 @@ +class Return{ + +Integer method() { + return 6; + } + + +} \ No newline at end of file diff --git a/test/bytecode/ReturnTest.java b/test/bytecode/ReturnTest.java new file mode 100644 index 000000000..cad56bfad --- /dev/null +++ b/test/bytecode/ReturnTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class ReturnTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Return"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/Runnable.jav b/test/bytecode/Runnable.jav new file mode 100644 index 000000000..bcd3a42ae --- /dev/null +++ b/test/bytecode/Runnable.jav @@ -0,0 +1,5 @@ +class Runnable{ + +Fun0 method() { return ()-> this; } + +} \ No newline at end of file diff --git a/test/bytecode/RunnableTest.java b/test/bytecode/RunnableTest.java new file mode 100644 index 000000000..82b6abc8f --- /dev/null +++ b/test/bytecode/RunnableTest.java @@ -0,0 +1,21 @@ +package bytecode; + +import org.junit.Test; + +public class RunnableTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Runnable"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/SingleClassTester.java b/test/bytecode/SingleClassTester.java new file mode 100644 index 000000000..07564f552 --- /dev/null +++ b/test/bytecode/SingleClassTester.java @@ -0,0 +1,73 @@ +package bytecode; + +import java.io.File; +import java.io.IOException; +import java.util.Map; + +import org.apache.bcel.classfile.JavaClass; + +import com.google.common.io.Files; + +import junit.framework.TestCase; +import de.dhbwstuttgart.bytecode.ClassGenerator; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.logger.Timewatch; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResults; + +public class SingleClassTester { + + public static void compileToBytecode(String inputFile, String outputDirectory){ + LoggerConfiguration logConfig = new LoggerConfiguration().setOutput(Section.PARSER, System.out); + MyCompilerAPI compiler = MyCompiler.getAPI(logConfig); + try { + SourceFile sf = compiler.parse(new File(inputFile)); + + Menge sourceFiles = new Menge<>(); + sourceFiles.add(sf); + + TypeinferenceResults results = new TypeinferenceResults(compiler.typeReconstruction(sourceFiles)); + + Menge bytecode = compiler.generateBytecode(sourceFiles, results); + //System.out.println(bytecode); + + for(ByteCodeResult result: bytecode){ + JavaClass javaClass = result.getByteCode().getJavaClass(); + javaClass.dump(new File(outputDirectory+javaClass.getClassName()+".class")); + ///* + for(ClassGenerator cg: result.getByteCode().getExtraClasses().values()){ + JavaClass jc = cg.getJavaClass(); + jc.dump(new File(outputDirectory+jc.getClassName()+".class")); + } + //*/ + Logger.getLogger("SingleClassTester").error(result.getByteCode().getJavaClass().toString(), Section.CODEGEN); + } + + + } catch (IOException | yyException e) { + Logger.getLogger("SingleClassTester").error(e.toString(), Section.CODEGEN); + e.printStackTrace(); + TestCase.fail(); + }finally{ + writeLog(inputFile+".log"); + } + } + + private static void writeLog(String toFile){ + String log = Logger.getWholeLog()+"\n"; + log+=Timewatch.getTimewatch().dumpTimeData(); + try { + Files.write(log.getBytes(),new File(toFile)); + } catch (IOException e) { + e.printStackTrace(); + TestCase.fail(); + } + } +} diff --git a/test/bytecode/SourceFileBytecodeTest.java b/test/bytecode/SourceFileBytecodeTest.java new file mode 100644 index 000000000..d975c0c1d --- /dev/null +++ b/test/bytecode/SourceFileBytecodeTest.java @@ -0,0 +1,74 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; + +import junit.framework.TestCase; + +import org.junit.BeforeClass; +import org.junit.Test; + +public abstract class SourceFileBytecodeTest extends TestCase{ + public String rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + public String testFile; + public String outputDirectory; + + protected String testName; + + public SourceFileBytecodeTest(){ + super("Bytecode Test"); + init(); + + if(testName != null){ + + testFile = testName+".jav"; + outputDirectory = ""; + + SingleClassTester.compileToBytecode(rootDirectory+testFile, rootDirectory+outputDirectory); + System.out.println("Test"); + }else{ + throw new RuntimeException("rootDirectory, testFile or outputFile is null."); + } + } + + protected abstract void init(); + + protected Class getClassToTest(){ + Class classToTest = null; + try { + ClassLoader classLoader = getClassLoader(); + + classToTest = classLoader.loadClass(testName); + + + } catch (Exception e) { + throw new RuntimeException(e); + } + + return classToTest; + } + + protected ClassLoader getClassLoader() throws Exception{ + File file = new File(rootDirectory); + URL url = file.toURL(); + URL[] urls = new URL[]{url}; + + return new URLClassLoader(urls); + } + + protected void testMethod(String methodName) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{ + Class testClass = getClassToTest(); + for(Method m : testClass.getMethods()){ + if(m.getName().equals(methodName)){ + m.invoke(testClass, new Object[0]); + } + } + } +} diff --git a/test/bytecode/StringLitTest.jav b/test/bytecode/StringLitTest.jav new file mode 100644 index 000000000..a063d123e --- /dev/null +++ b/test/bytecode/StringLitTest.jav @@ -0,0 +1,7 @@ +class StringLitTest{ + + +void method() { s; s = "abcdefg"; t; t ="jfowehfowh"; } + + +} \ No newline at end of file diff --git a/test/bytecode/StringLitTest.java b/test/bytecode/StringLitTest.java new file mode 100644 index 000000000..690968e48 --- /dev/null +++ b/test/bytecode/StringLitTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class StringLitTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "StringLitTest"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/SystemOutPrintln.jav b/test/bytecode/SystemOutPrintln.jav new file mode 100644 index 000000000..c9f7ba39b --- /dev/null +++ b/test/bytecode/SystemOutPrintln.jav @@ -0,0 +1,7 @@ +import java.lang.System; + +class SystemOutPrintln{ + void method() { + System.out.println("Hello World"); + } +} \ No newline at end of file diff --git a/test/bytecode/SystemOutPrintlnTest.java b/test/bytecode/SystemOutPrintlnTest.java new file mode 100644 index 000000000..39db74e3f --- /dev/null +++ b/test/bytecode/SystemOutPrintlnTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class SystemOutPrintlnTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "SystemOutPrintln"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/Test.java b/test/bytecode/Test.java new file mode 100644 index 000000000..0cd36a625 --- /dev/null +++ b/test/bytecode/Test.java @@ -0,0 +1,6 @@ +class Test{ + public static void main(String[] args){ + System.out.println(new Main().main(true)); + new LambdaExpr().method(); +} +} diff --git a/test/bytecode/UninitializedVariable.jav b/test/bytecode/UninitializedVariable.jav new file mode 100644 index 000000000..0854d0a90 --- /dev/null +++ b/test/bytecode/UninitializedVariable.jav @@ -0,0 +1,15 @@ +import java.util.Vector; + +class UninitializedVariable{ + + Integer method(Integer v) { + return v; + } + + public static void main(String[] args) { + UninitializedVariable ol; + ol = new UninitializedVariable(); + Integer v; + ol.method(v); + } +} \ No newline at end of file diff --git a/test/bytecode/UninitializedVariableTest.java b/test/bytecode/UninitializedVariableTest.java new file mode 100644 index 000000000..838d97083 --- /dev/null +++ b/test/bytecode/UninitializedVariableTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTester; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.ByteCodeResult; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class UninitializedVariableTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "UninitializedVariable"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/Variable.jav b/test/bytecode/Variable.jav new file mode 100644 index 000000000..ef9de3312 --- /dev/null +++ b/test/bytecode/Variable.jav @@ -0,0 +1,8 @@ +class Variable{ + public Integer method(Integer parameter){ + Integer lokaleVariable; + lokaleVariable = 2; + + return parameter+lokaleVariable; + } +} \ No newline at end of file diff --git a/test/bytecode/VariableMultimethods.jav b/test/bytecode/VariableMultimethods.jav new file mode 100644 index 000000000..ad5520f49 --- /dev/null +++ b/test/bytecode/VariableMultimethods.jav @@ -0,0 +1,14 @@ +class VariableMultimethods{ + public Integer method(Integer z, Integer x, Integer y){ + return x+y+z; + } + + public Integer method(Integer x, Integer y){ + return x+y; + } + + public Integer method(Integer y){ + return y; + } + +} \ No newline at end of file diff --git a/test/bytecode/VariableMultimethodsTest.java b/test/bytecode/VariableMultimethodsTest.java new file mode 100644 index 000000000..2990e25be --- /dev/null +++ b/test/bytecode/VariableMultimethodsTest.java @@ -0,0 +1,98 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Test; + +import org.junit.Ignore; + +import bytecode.SourceFileBytecodeTest; + + +public class VariableMultimethodsTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "VariableMultimethods"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } + + @Test + public void testOneArgument() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Integer y = 1; + + Class[] params = new Class[]{ + y.getClass() + }; + + Method method = cls.getDeclaredMethod("method", params); + Integer returnValue = (Integer) method.invoke(obj, y); + assertEquals(new Integer(1), returnValue); + } + + @Test + public void testTwoArgument() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Integer x = 1; + Integer y = 2; + + Class[] params = new Class[]{ + x.getClass(), + y.getClass() + }; + + Method method = cls.getDeclaredMethod("method", params); + Integer returnValue = (Integer) method.invoke(obj, x, y); + assertEquals(new Integer(3), returnValue); + } + + @Test + public void testThreeArgument() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Integer z = 1; + Integer x = 2; + Integer y = 4; + + Class[] params = new Class[]{ + z.getClass(), + x.getClass(), + y.getClass() + }; + + Method method = cls.getDeclaredMethod("method", params); + Integer returnValue = (Integer) method.invoke(obj, z, x, y); + assertEquals(new Integer(7), returnValue); + } +} diff --git a/test/bytecode/VariableTest.java b/test/bytecode/VariableTest.java new file mode 100644 index 000000000..de3875663 --- /dev/null +++ b/test/bytecode/VariableTest.java @@ -0,0 +1,35 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Test; + +import org.junit.Ignore; + +import bytecode.SourceFileBytecodeTest; + + +public class VariableTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Variable"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/WhileTest.jav b/test/bytecode/WhileTest.jav new file mode 100644 index 000000000..903020d5b --- /dev/null +++ b/test/bytecode/WhileTest.jav @@ -0,0 +1,10 @@ +class WhileTest{ + + void method(){ + Integer i; + i = 1; + while(i < 10){ + i = i + 1; + } + } +} \ No newline at end of file diff --git a/test/bytecode/WhileTest.java b/test/bytecode/WhileTest.java new file mode 100644 index 000000000..025f4d30e --- /dev/null +++ b/test/bytecode/WhileTest.java @@ -0,0 +1,26 @@ +package bytecode; + +import org.junit.Test; +import org.junit.runners.Suite; + +public class WhileTest extends SourceFileBytecodeTest{ + + public WhileTest(){ + super(); + } + + @Override + protected void init() { + testName = "WhileTest"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + assertTrue(true); + } +} \ No newline at end of file diff --git a/test/bytecode/asdf.java b/test/bytecode/asdf.java new file mode 100644 index 000000000..efdb9dc88 --- /dev/null +++ b/test/bytecode/asdf.java @@ -0,0 +1,8 @@ +class ASDFTest{ + +public static void main(String[] args){ + VariableMultimethods test = new VariableMultimethods(); + System.out.println(test.method(test.method(1,2),test.method(3),0)); +} + +} diff --git a/test/bytecode/lambda/Simple.jav b/test/bytecode/lambda/Simple.jav new file mode 100644 index 000000000..d29da619c --- /dev/null +++ b/test/bytecode/lambda/Simple.jav @@ -0,0 +1,8 @@ +class Simple{ + +op = (i)->i; + +public void main(){ + op.apply(1); +} +} \ No newline at end of file diff --git a/test/bytecode/lambda/SimpleTest.java b/test/bytecode/lambda/SimpleTest.java new file mode 100644 index 000000000..9ca780378 --- /dev/null +++ b/test/bytecode/lambda/SimpleTest.java @@ -0,0 +1,19 @@ +package bytecode.lambda; + +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class SimpleTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Simple"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/lambda/"; + } + + @Test + public void testConstruct() throws Exception{ + this.testMethod("main"); + assertTrue(true); + } +} diff --git a/test/bytecode/lambda/Test.java b/test/bytecode/lambda/Test.java new file mode 100644 index 000000000..70efddea1 --- /dev/null +++ b/test/bytecode/lambda/Test.java @@ -0,0 +1,5 @@ +class Test{ + public static void main(String[] args){ + new Simple().main(); +} +} diff --git a/test/bytecode/lambda/TestInterface.java b/test/bytecode/lambda/TestInterface.java new file mode 100644 index 000000000..5b92f6c9b --- /dev/null +++ b/test/bytecode/lambda/TestInterface.java @@ -0,0 +1 @@ +interface TestInterface extends Fun1{} diff --git a/test/bytecode/operators/AddDoubleOperator.jav b/test/bytecode/operators/AddDoubleOperator.jav new file mode 100644 index 000000000..2ed1848cb --- /dev/null +++ b/test/bytecode/operators/AddDoubleOperator.jav @@ -0,0 +1,5 @@ +class AddDoubleOperator{ + Double method(Double x, Double y){ + return x + y; + } +} \ No newline at end of file diff --git a/test/bytecode/operators/AddDoubleOperatorTest.java b/test/bytecode/operators/AddDoubleOperatorTest.java new file mode 100644 index 000000000..5461b1726 --- /dev/null +++ b/test/bytecode/operators/AddDoubleOperatorTest.java @@ -0,0 +1,53 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Ignore; +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class AddDoubleOperatorTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "AddDoubleOperator"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } + + @Test + public void testTwoDoubles() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Double x = new Double(1); + Double y = new Double(2); + + Class[] params = new Class[]{ + x.getClass(), + y.getClass(), + }; + + Method method = cls.getDeclaredMethod("method", params); + Double returnValue = (Double) method.invoke(obj, x, y); + assertEquals(new Double(3.0), returnValue); + } +} diff --git a/test/bytecode/operators/AddFloatOperator.jav b/test/bytecode/operators/AddFloatOperator.jav new file mode 100644 index 000000000..b7968498d --- /dev/null +++ b/test/bytecode/operators/AddFloatOperator.jav @@ -0,0 +1,5 @@ +class AddFloatOperator{ + Float method(Float x, Float y){ + return x + y; + } +} \ No newline at end of file diff --git a/test/bytecode/operators/AddFloatOperatorTest.java b/test/bytecode/operators/AddFloatOperatorTest.java new file mode 100644 index 000000000..205c48564 --- /dev/null +++ b/test/bytecode/operators/AddFloatOperatorTest.java @@ -0,0 +1,53 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Ignore; +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class AddFloatOperatorTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "AddFloatOperator"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } + + @Test + public void testTwoFloats() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Float x = new Float(1.0); + Float y = new Float(2.0); + + Class[] params = new Class[]{ + x.getClass(), + y.getClass(), + }; + + Method method = cls.getDeclaredMethod("method", params); + Float returnValue = (Float) method.invoke(obj, x, y); + assertEquals(new Float(3.0), returnValue); + } +} diff --git a/test/bytecode/operators/AddIntegerOperator.jav b/test/bytecode/operators/AddIntegerOperator.jav new file mode 100644 index 000000000..7a1ee0b34 --- /dev/null +++ b/test/bytecode/operators/AddIntegerOperator.jav @@ -0,0 +1,5 @@ +class AddIntegerOperator{ + Integer method(Integer x, Integer y){ + return x + y; + } +} \ No newline at end of file diff --git a/test/bytecode/operators/AddIntegerOperatorTest.java b/test/bytecode/operators/AddIntegerOperatorTest.java new file mode 100644 index 000000000..a012307d8 --- /dev/null +++ b/test/bytecode/operators/AddIntegerOperatorTest.java @@ -0,0 +1,53 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Ignore; +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class AddIntegerOperatorTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "AddIntegerOperator"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } + + @Test + public void testTwoIntegers() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Integer x = new Integer(1); + Integer y = new Integer(2); + + Class[] params = new Class[]{ + x.getClass(), + y.getClass(), + }; + + Method method = cls.getDeclaredMethod("method", params); + Integer returnValue = (Integer) method.invoke(obj, x, y); + assertEquals(new Integer(3), returnValue); + } +} diff --git a/test/bytecode/operators/AddLongOperator.jav b/test/bytecode/operators/AddLongOperator.jav new file mode 100644 index 000000000..86cba0834 --- /dev/null +++ b/test/bytecode/operators/AddLongOperator.jav @@ -0,0 +1,5 @@ +class AddLongOperator{ + Long method(Long x, Long y){ + return x + y; + } +} \ No newline at end of file diff --git a/test/bytecode/operators/AddLongOperatorTest.java b/test/bytecode/operators/AddLongOperatorTest.java new file mode 100644 index 000000000..7dc791f39 --- /dev/null +++ b/test/bytecode/operators/AddLongOperatorTest.java @@ -0,0 +1,53 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Ignore; +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class AddLongOperatorTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "AddLongOperator"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } + + @Test + public void testTwoLongs() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Long x = new Long(1); + Long y = new Long(2); + + Class[] params = new Class[]{ + x.getClass(), + y.getClass(), + }; + + Method method = cls.getDeclaredMethod("method", params); + Long returnValue = (Long) method.invoke(obj, x, y); + assertEquals(new Long(3), returnValue); + } +} diff --git a/test/bytecode/operators/AddOperator.jav b/test/bytecode/operators/AddOperator.jav new file mode 100644 index 000000000..8eec40b39 --- /dev/null +++ b/test/bytecode/operators/AddOperator.jav @@ -0,0 +1,5 @@ +class AddOperator{ + method(x){ + return x + x; + } +} \ No newline at end of file diff --git a/test/bytecode/operators/AddOperatorTest.java b/test/bytecode/operators/AddOperatorTest.java new file mode 100644 index 000000000..3f6230386 --- /dev/null +++ b/test/bytecode/operators/AddOperatorTest.java @@ -0,0 +1,108 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Ignore; +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class AddOperatorTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "AddOperator"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } + + @Test + public void testTwoIntegers() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Integer x = new Integer(1); + + Class[] params = new Class[]{ + x.getClass() + }; + + Method method = cls.getDeclaredMethod("method", params); + Integer returnValue = (Integer) method.invoke(obj, x); + assertEquals(new Integer(2), returnValue); + } + + @Test + public void testTwoDoubles() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Double x = new Double(1.0); + + Class[] params = new Class[]{ + x.getClass() + }; + + Method method = cls.getDeclaredMethod("method", params); + Double returnValue = (Double) method.invoke(obj, x); + assertEquals(new Double(2.0), returnValue); + } + + @Test + public void testTwoFloats() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Float x = new Float(1.0); + + Class[] params = new Class[]{ + x.getClass() + }; + + Method method = cls.getDeclaredMethod("method", params); + Float returnValue = (Float) method.invoke(obj, x); + assertEquals(new Float(2.0), returnValue); + } + + @Test + public void testTwoLongs() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Long x = new Long(1); + + Class[] params = new Class[]{ + x.getClass() + }; + + Method method = cls.getDeclaredMethod("method", params); + Long returnValue = (Long) method.invoke(obj, x); + assertEquals(new Long(3), returnValue); + } +} diff --git a/test/bytecode/operators/DivOperator.jav b/test/bytecode/operators/DivOperator.jav new file mode 100644 index 000000000..d23c04baa --- /dev/null +++ b/test/bytecode/operators/DivOperator.jav @@ -0,0 +1,5 @@ +class DivOperator{ + method(x, y){ + return x / y; + } +} \ No newline at end of file diff --git a/test/bytecode/operators/DivOperatorTest.java b/test/bytecode/operators/DivOperatorTest.java new file mode 100644 index 000000000..6b7db4e08 --- /dev/null +++ b/test/bytecode/operators/DivOperatorTest.java @@ -0,0 +1,53 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Ignore; +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class DivOperatorTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "DivOperator"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } + + @Test + public void testTwoIntegers() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Integer x = new Integer(1); + Integer y = new Integer(2); + + Class[] params = new Class[]{ + x.getClass(), + y.getClass(), + }; + + Method method = cls.getDeclaredMethod("method", params); + Integer returnValue = (Integer) method.invoke(obj, x, y); + assertEquals(new Integer(0), returnValue); + } +} diff --git a/test/bytecode/operators/EqualOperator.jav b/test/bytecode/operators/EqualOperator.jav new file mode 100644 index 000000000..a51b512a4 --- /dev/null +++ b/test/bytecode/operators/EqualOperator.jav @@ -0,0 +1,5 @@ +class EqualOperator{ + Boolean method(Integer x, Integer y){ + return x == y; + } +} \ No newline at end of file diff --git a/test/bytecode/operators/EqualOperatorTest.java b/test/bytecode/operators/EqualOperatorTest.java new file mode 100644 index 000000000..46720335a --- /dev/null +++ b/test/bytecode/operators/EqualOperatorTest.java @@ -0,0 +1,30 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.lang.reflect.Method; +import org.junit.Test; +import bytecode.SourceFileBytecodeTest; + +public class EqualOperatorTest extends RelOperatorTest{ + @Override + protected void init() { + testName = "EqualOperator"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/"; + } + + @Override + protected Boolean getTest1x2ReturnValue() { + return new Boolean(false); + } + + @Override + protected Boolean getTest2x2ReturnValue() { + return new Boolean(true); + } + + @Override + protected Boolean getTest2x1ReturnValue() { + return new Boolean(false); + } +} diff --git a/test/bytecode/operators/GreaterEqualOperator.jav b/test/bytecode/operators/GreaterEqualOperator.jav new file mode 100644 index 000000000..798891f98 --- /dev/null +++ b/test/bytecode/operators/GreaterEqualOperator.jav @@ -0,0 +1,5 @@ +class GreaterEqualOperator{ + Boolean method(Integer x, Integer y){ + return x >= y; + } +} \ No newline at end of file diff --git a/test/bytecode/operators/GreaterEqualOperatorTest.java b/test/bytecode/operators/GreaterEqualOperatorTest.java new file mode 100644 index 000000000..41834e73d --- /dev/null +++ b/test/bytecode/operators/GreaterEqualOperatorTest.java @@ -0,0 +1,30 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.lang.reflect.Method; +import org.junit.Test; +import bytecode.SourceFileBytecodeTest; + +public class GreaterEqualOperatorTest extends RelOperatorTest{ + @Override + protected void init() { + testName = "GreaterEqualOperator"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/"; + } + + @Override + protected Boolean getTest1x2ReturnValue() { + return new Boolean(false); + } + + @Override + protected Boolean getTest2x2ReturnValue() { + return new Boolean(true); + } + + @Override + protected Boolean getTest2x1ReturnValue() { + return new Boolean(true); + } +} diff --git a/test/bytecode/operators/GreaterOperator.jav b/test/bytecode/operators/GreaterOperator.jav new file mode 100644 index 000000000..f2c28682e --- /dev/null +++ b/test/bytecode/operators/GreaterOperator.jav @@ -0,0 +1,5 @@ +class GreaterOperator{ + Boolean method(Integer x, Integer y){ + return x > y; + } +} \ No newline at end of file diff --git a/test/bytecode/operators/GreaterOperatorTest.java b/test/bytecode/operators/GreaterOperatorTest.java new file mode 100644 index 000000000..7a5624618 --- /dev/null +++ b/test/bytecode/operators/GreaterOperatorTest.java @@ -0,0 +1,30 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.lang.reflect.Method; +import org.junit.Test; +import bytecode.SourceFileBytecodeTest; + +public class GreaterOperatorTest extends RelOperatorTest{ + @Override + protected void init() { + testName = "GreaterOperator"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/"; + } + + @Override + protected Boolean getTest1x2ReturnValue() { + return new Boolean(false); + } + + @Override + protected Boolean getTest2x2ReturnValue() { + return new Boolean(false); + } + + @Override + protected Boolean getTest2x1ReturnValue() { + return new Boolean(true); + } +} diff --git a/test/bytecode/operators/ModuloOperator.jav b/test/bytecode/operators/ModuloOperator.jav new file mode 100644 index 000000000..6a17f28ef --- /dev/null +++ b/test/bytecode/operators/ModuloOperator.jav @@ -0,0 +1,5 @@ +class ModuloOperator{ + Integer method(Integer x, Integer y){ + return x % y; + } +} \ No newline at end of file diff --git a/test/bytecode/operators/ModuloOperatorTest.java b/test/bytecode/operators/ModuloOperatorTest.java new file mode 100644 index 000000000..5c0c600fe --- /dev/null +++ b/test/bytecode/operators/ModuloOperatorTest.java @@ -0,0 +1,53 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Ignore; +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class ModuloOperatorTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "ModuloOperator"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } + + @Test + public void testTwoIntegers() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Integer x = new Integer(1); + Integer y = new Integer(2); + + Class[] params = new Class[]{ + x.getClass(), + y.getClass(), + }; + + Method method = cls.getDeclaredMethod("method", params); + Integer returnValue = (Integer) method.invoke(obj, x, y); + assertEquals(new Integer(1), returnValue); + } +} diff --git a/test/bytecode/operators/MulOperator.jav b/test/bytecode/operators/MulOperator.jav new file mode 100644 index 000000000..8efd6349f --- /dev/null +++ b/test/bytecode/operators/MulOperator.jav @@ -0,0 +1,5 @@ +class MulOperator{ + method(x, y){ + return x * y; + } +} \ No newline at end of file diff --git a/test/bytecode/operators/MulOperatorTest.java b/test/bytecode/operators/MulOperatorTest.java new file mode 100644 index 000000000..2c6630210 --- /dev/null +++ b/test/bytecode/operators/MulOperatorTest.java @@ -0,0 +1,53 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Ignore; +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class MulOperatorTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "MulOperator"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } + + @Test + public void testTwoIntegers() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Integer x = new Integer(1); + Integer y = new Integer(2); + + Class[] params = new Class[]{ + x.getClass(), + y.getClass(), + }; + + Method method = cls.getDeclaredMethod("method", params); + Integer returnValue = (Integer) method.invoke(obj, x, y); + assertEquals(new Integer(2), returnValue); + } +} diff --git a/test/bytecode/operators/NotEqualOperator.jav b/test/bytecode/operators/NotEqualOperator.jav new file mode 100644 index 000000000..68c8a1681 --- /dev/null +++ b/test/bytecode/operators/NotEqualOperator.jav @@ -0,0 +1,5 @@ +class NotEqualOperator{ + Boolean method(Integer x, Integer y){ + return x != y; + } +} \ No newline at end of file diff --git a/test/bytecode/operators/NotEqualOperatorTest.java b/test/bytecode/operators/NotEqualOperatorTest.java new file mode 100644 index 000000000..89b2d871d --- /dev/null +++ b/test/bytecode/operators/NotEqualOperatorTest.java @@ -0,0 +1,30 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.lang.reflect.Method; +import org.junit.Test; +import bytecode.SourceFileBytecodeTest; + +public class NotEqualOperatorTest extends RelOperatorTest{ + @Override + protected void init() { + testName = "NotEqualOperator"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/"; + } + + @Override + protected Boolean getTest1x2ReturnValue() { + return new Boolean(true); + } + + @Override + protected Boolean getTest2x2ReturnValue() { + return new Boolean(false); + } + + @Override + protected Boolean getTest2x1ReturnValue() { + return new Boolean(true); + } +} diff --git a/test/bytecode/operators/OrOperator.jav b/test/bytecode/operators/OrOperator.jav new file mode 100644 index 000000000..c10a96e25 --- /dev/null +++ b/test/bytecode/operators/OrOperator.jav @@ -0,0 +1,5 @@ +class OrOperator{ + Boolean method(Boolean x, Boolean y){ + return x || y; + } +} \ No newline at end of file diff --git a/test/bytecode/operators/OrOperatorTest.java b/test/bytecode/operators/OrOperatorTest.java new file mode 100644 index 000000000..8d8faaa96 --- /dev/null +++ b/test/bytecode/operators/OrOperatorTest.java @@ -0,0 +1,32 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Ignore; +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class OrOperatorTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "OrOperator"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/operators/RelOperatorTest.java b/test/bytecode/operators/RelOperatorTest.java new file mode 100644 index 000000000..59f3ded7d --- /dev/null +++ b/test/bytecode/operators/RelOperatorTest.java @@ -0,0 +1,86 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.lang.reflect.Method; +import org.junit.Test; +import bytecode.SourceFileBytecodeTest; + +public abstract class RelOperatorTest extends SourceFileBytecodeTest{ + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } + + @Test + public void test1x2() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Integer x = new Integer(1); + Integer y = new Integer(2); + + Class[] params = new Class[]{ + x.getClass(), + y.getClass(), + }; + + Method method = cls.getDeclaredMethod("method", params); + Boolean returnValue = (Boolean) method.invoke(obj, x, y); + assertEquals(getTest1x2ReturnValue(), returnValue); + } + + @Test + public void test2x2() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Integer x = new Integer(2); + Integer y = new Integer(2); + + Class[] params = new Class[]{ + x.getClass(), + y.getClass(), + }; + + Method method = cls.getDeclaredMethod("method", params); + Boolean returnValue = (Boolean) method.invoke(obj, x, y); + assertEquals(getTest2x2ReturnValue(), returnValue); + } + + @Test + public void test2x1() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Integer x = new Integer(2); + Integer y = new Integer(2); + + Class[] params = new Class[]{ + x.getClass(), + y.getClass(), + }; + + Method method = cls.getDeclaredMethod("method", params); + Boolean returnValue = (Boolean) method.invoke(obj, x, y); + assertEquals(getTest2x1ReturnValue(), returnValue); + } + + protected abstract Boolean getTest1x2ReturnValue(); + protected abstract Boolean getTest2x2ReturnValue(); + protected abstract Boolean getTest2x1ReturnValue(); +} diff --git a/test/bytecode/operators/SmallerEqualOperator.jav b/test/bytecode/operators/SmallerEqualOperator.jav new file mode 100644 index 000000000..b0448dbac --- /dev/null +++ b/test/bytecode/operators/SmallerEqualOperator.jav @@ -0,0 +1,5 @@ +class SmallerEqualOperator{ + Boolean method(Integer x, Integer y){ + return x <= y; + } +} \ No newline at end of file diff --git a/test/bytecode/operators/SmallerEqualOperatorTest.java b/test/bytecode/operators/SmallerEqualOperatorTest.java new file mode 100644 index 000000000..d4da5f6f7 --- /dev/null +++ b/test/bytecode/operators/SmallerEqualOperatorTest.java @@ -0,0 +1,30 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.lang.reflect.Method; +import org.junit.Test; +import bytecode.SourceFileBytecodeTest; + +public class SmallerEqualOperatorTest extends RelOperatorTest{ + @Override + protected void init() { + testName = "SmallerEqual"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/"; + } + + @Override + protected Boolean getTest1x2ReturnValue() { + return new Boolean(true); + } + + @Override + protected Boolean getTest2x2ReturnValue() { + return new Boolean(true); + } + + @Override + protected Boolean getTest2x1ReturnValue() { + return new Boolean(false); + } +} diff --git a/test/bytecode/operators/SmallerOperator.jav b/test/bytecode/operators/SmallerOperator.jav new file mode 100644 index 000000000..5ddc8c911 --- /dev/null +++ b/test/bytecode/operators/SmallerOperator.jav @@ -0,0 +1,5 @@ +class SmallerOperator{ + Boolean method(Integer x, Integer y){ + return x < y; + } +} \ No newline at end of file diff --git a/test/bytecode/operators/SmallerOperatorTest.java b/test/bytecode/operators/SmallerOperatorTest.java new file mode 100644 index 000000000..2609b70f6 --- /dev/null +++ b/test/bytecode/operators/SmallerOperatorTest.java @@ -0,0 +1,30 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.lang.reflect.Method; +import org.junit.Test; +import bytecode.SourceFileBytecodeTest; + +public class SmallerOperatorTest extends RelOperatorTest{ + @Override + protected void init() { + testName = "Smaller"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/"; + } + + @Override + protected Boolean getTest1x2ReturnValue() { + return new Boolean(true); + } + + @Override + protected Boolean getTest2x2ReturnValue() { + return new Boolean(false); + } + + @Override + protected Boolean getTest2x1ReturnValue() { + return new Boolean(false); + } +} diff --git a/test/bytecode/operators/SubOperator.jav b/test/bytecode/operators/SubOperator.jav new file mode 100644 index 000000000..1c5915221 --- /dev/null +++ b/test/bytecode/operators/SubOperator.jav @@ -0,0 +1,5 @@ +class SubOperator{ + Integer method(Integer x, Integer y){ + return x - y; + } +} \ No newline at end of file diff --git a/test/bytecode/operators/SubOperatorTest.java b/test/bytecode/operators/SubOperatorTest.java new file mode 100644 index 000000000..a9b3294fd --- /dev/null +++ b/test/bytecode/operators/SubOperatorTest.java @@ -0,0 +1,53 @@ +package bytecode.operators; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Ignore; +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class SubOperatorTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "SubOperator"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/operators/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } + + @Test + public void testTwoIntegers() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Integer x = new Integer(1); + Integer y = new Integer(2); + + Class[] params = new Class[]{ + x.getClass(), + y.getClass(), + }; + + Method method = cls.getDeclaredMethod("method", params); + Integer returnValue = (Integer) method.invoke(obj, x, y); + assertEquals(new Integer(-1), returnValue); + } +} diff --git a/test/bytecode/stackmaptable/IfStatement.jav b/test/bytecode/stackmaptable/IfStatement.jav new file mode 100644 index 000000000..1451af170 --- /dev/null +++ b/test/bytecode/stackmaptable/IfStatement.jav @@ -0,0 +1,10 @@ +class IfStatement{ + Integer methode(Boolean b){ + if(b){ + return 1; + }else{ + return 2; + } + } + +} \ No newline at end of file diff --git a/test/bytecode/stackmaptable/IfStatementTest.java b/test/bytecode/stackmaptable/IfStatementTest.java new file mode 100644 index 000000000..7c10e42b9 --- /dev/null +++ b/test/bytecode/stackmaptable/IfStatementTest.java @@ -0,0 +1,24 @@ +package bytecode.stackmaptable; + +import org.junit.Test; + +import bytecode.SingleClassTester; +import bytecode.SourceFileBytecodeTest; + +public class IfStatementTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "IfStatement"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/stackmaptable/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/stackmaptable/StackMapTableGenTests.java b/test/bytecode/stackmaptable/StackMapTableGenTests.java new file mode 100644 index 000000000..f100c5c16 --- /dev/null +++ b/test/bytecode/stackmaptable/StackMapTableGenTests.java @@ -0,0 +1,66 @@ +package bytecode.stackmaptable; + +import junit.framework.TestCase; +import org.apache.bcel.Repository; +import org.apache.bcel.classfile.*; +import org.apache.bcel.generic.ConstantPoolGen; +import org.apache.bcel.generic.MethodGen; +import org.apache.bcel.generic.StackMapTableGen; + +import java.util.List; + +public class StackMapTableGenTests extends TestCase { + + public static class StackMapTableTest { + public void method1(){} + + Integer method2(Boolean b){ + if(b){ + return 1; + }else{ + return 2; + } + } + + public static void staticMethod1(){ + int a = 1; + int b = 2; + while(true){ + a = b; + } + } + + } + + private MethodGen getMethod(Class cls, String name) throws ClassNotFoundException { + JavaClass jc = Repository.lookupClass(cls); + ConstantPoolGen cp = new ConstantPoolGen(jc.getConstantPool()); + for (Method method : jc.getMethods()) { + if (method.getName().equals(name)) { + return new MethodGen(method, jc.getClassName(), cp); + } + } + + fail("Method " + name + " not found in class " + cls); + return null; + } + + public void testFrameSplittingTrivial() throws Exception{ + MethodGen mg = getMethod(StackMapTableTest.class, "method1"); + StackMapTableGen sg = new StackMapTableGen(mg,mg.getConstantPool()); + List blocks = sg.splitIntoBlocks(mg.getInstructionList(), mg.getConstantPool()); + assertTrue(blocks.size() == 1); //There is only one frame, because the method1 is empty + } + + public void testStaticMethods() throws Exception{ + MethodGen mg = getMethod(StackMapTableTest.class, "staticMethod1"); + StackMapTableGen sg = new StackMapTableGen(mg,mg.getConstantPool()); + try{ + StackMap stackMap = sg.getStackMap(); + assertTrue(stackMap.getStackMap().length > 0); + }catch(Exception e){ + e.printStackTrace(); + } + } + +} diff --git a/test/bytecode/stackmaptable/Test.java b/test/bytecode/stackmaptable/Test.java new file mode 100644 index 000000000..442df6039 --- /dev/null +++ b/test/bytecode/stackmaptable/Test.java @@ -0,0 +1,6 @@ +class Test{ + public static void main(String[] args){ + System.out.println(new IfStatement().methode(true)); + System.out.println(new IfStatement().methode(false)); + } +} diff --git a/test/bytecode/types/AutoOverloading.jav b/test/bytecode/types/AutoOverloading.jav new file mode 100644 index 000000000..8d97f7055 --- /dev/null +++ b/test/bytecode/types/AutoOverloading.jav @@ -0,0 +1,20 @@ +class AutoOverloading{ + + method2(String p){ + return p; + } + + method2(Integer p){ + return p; + } + + + method(p){ + return method2(p); + } + + public static void main(String[] args){ + System.out.println(methode("hallo")); + System.out.println(methode(2)); + } +} \ No newline at end of file diff --git a/test/bytecode/types/AutoOverloadingMultiResults.jav b/test/bytecode/types/AutoOverloadingMultiResults.jav new file mode 100644 index 000000000..d5c0f23ff --- /dev/null +++ b/test/bytecode/types/AutoOverloadingMultiResults.jav @@ -0,0 +1,8 @@ +import java.util.Vector; + +class AutoOverloadingMultiResults{ + void method(Integer a) { + b; + b = 1; + } +} \ No newline at end of file diff --git a/test/bytecode/types/AutoOverloadingMultiResultsTest.java b/test/bytecode/types/AutoOverloadingMultiResultsTest.java new file mode 100644 index 000000000..ce34f3f71 --- /dev/null +++ b/test/bytecode/types/AutoOverloadingMultiResultsTest.java @@ -0,0 +1,35 @@ +package bytecode.types; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Test; + +import org.junit.Ignore; + +import bytecode.SourceFileBytecodeTest; + + +public class AutoOverloadingMultiResultsTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "AutoOverloadingMultiResults"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/types/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/types/AutoOverloadingTest.java b/test/bytecode/types/AutoOverloadingTest.java new file mode 100644 index 000000000..ddc8da0ad --- /dev/null +++ b/test/bytecode/types/AutoOverloadingTest.java @@ -0,0 +1,84 @@ +package bytecode.types; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class AutoOverloadingTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "AutoOverloading"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/types/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } + + @Test + public void testString() { + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + File file = new File(rootDirectory); + URL url = file.toURL(); + URL[] urls = new URL[]{url}; + + Class string = classLoader.loadClass("java.lang.String"); + + Class[] params = new Class[1]; + params[0] = string; + + Method method = cls.getDeclaredMethod("method", params); + method.invoke(obj, string.newInstance()); + assertTrue(true); + }catch(Exception e){ + throw new RuntimeException(e); + } + } + + @Test + public void testInteger() { + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + File file = new File(rootDirectory); + URL url = file.toURL(); + URL[] urls = new URL[]{url}; + + Integer integer = new Integer(123); + + Class[] params = new Class[1]; + params[0] = integer.getClass(); + + Method method = cls.getDeclaredMethod("method", params); + method.invoke(obj, integer); + assertTrue(true); + }catch(Exception e){ + throw new RuntimeException(e); + } + } +} diff --git a/test/bytecode/types/AutoOverloadingVector.jav b/test/bytecode/types/AutoOverloadingVector.jav new file mode 100644 index 000000000..eb65ae4ce --- /dev/null +++ b/test/bytecode/types/AutoOverloadingVector.jav @@ -0,0 +1,14 @@ +import java.util.Vector; + +class AutoOverloadingVector{ + method2(p){ + method(p); + } + + method(Vector p){ + } + + method(Vector p){ + } + +} \ No newline at end of file diff --git a/test/bytecode/types/AutoOverloadingVectorTest.java b/test/bytecode/types/AutoOverloadingVectorTest.java new file mode 100644 index 000000000..8dfe1d70e --- /dev/null +++ b/test/bytecode/types/AutoOverloadingVectorTest.java @@ -0,0 +1,84 @@ +package bytecode.types; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class AutoOverloadingVectorTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "AutoOverloadingVector"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/types/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } + + @Test + public void testString() { + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + File file = new File(rootDirectory); + URL url = file.toURL(); + URL[] urls = new URL[]{url}; + + Class string = classLoader.loadClass("java%util%Vector%%java%lang%String%"); + + Class[] params = new Class[1]; + params[0] = string; + + Method method = cls.getDeclaredMethod("method2", params); + method.invoke(obj, string.newInstance()); + assertTrue(true); + }catch(Exception e){ + throw new RuntimeException(e); + } + } + + @Test + public void testInteger() { + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + File file = new File(rootDirectory); + URL url = file.toURL(); + URL[] urls = new URL[]{url}; + + Class integer = classLoader.loadClass("java%util%Vector%%java%lang%Integer%"); + + Class[] params = new Class[1]; + params[0] = integer; + + Method method = cls.getDeclaredMethod("method2", params); + method.invoke(obj, integer.newInstance()); + assertTrue(true); + }catch(Exception e){ + throw new RuntimeException(e); + } + } +} diff --git a/test/bytecode/types/ExtendsObjectTest.java b/test/bytecode/types/ExtendsObjectTest.java new file mode 100644 index 000000000..1bd04bb74 --- /dev/null +++ b/test/bytecode/types/ExtendsObjectTest.java @@ -0,0 +1,72 @@ +package bytecode.types; + +import static org.junit.Assert.*; + +import java.lang.reflect.Constructor; + +import org.junit.BeforeClass; +import org.junit.Test; + +import bytecode.ASTBytecodeTest; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; + + +public class ExtendsObjectTest extends ASTBytecodeTest{ + public SourceFile getSourceFile(){ + /* + class ExtendsObject extends Object{ + + } + */ + SourceFile sourceFile = new SourceFile(); + de.dhbwstuttgart.syntaxtree.Class classToTest = ASTFactory.createClass(getTestName(), null, null, null, sourceFile); + sourceFile.addElement(classToTest); + return sourceFile; + } + + @Test + public void testConstruct(){ + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(getTestName()); + + Object obj = cls.newInstance(); + + Constructor method = cls.getConstructor(new Class[]{}); + method.newInstance(); + assertTrue(true); + }catch(Exception e){ + e.printStackTrace(); + fail(); + } + } + + @Test + public void testSupertype(){ + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(getTestName()); + + assertEquals("java.lang.Object", cls.getSuperclass().getName()); + }catch(Exception e){ + e.printStackTrace(); + fail(); + } + } + + @Override + public String getRootDirectory() { + return super.getRootDirectory()+"types/"; + } + + + + @Override + public String getTestName() { + return "ExtendsObjectTest"; + } + +} diff --git a/test/bytecode/types/ExtendsType.jav b/test/bytecode/types/ExtendsType.jav new file mode 100644 index 000000000..8bd50b6fc --- /dev/null +++ b/test/bytecode/types/ExtendsType.jav @@ -0,0 +1,13 @@ +import java.util.Vector; + +class ExtendsType{ + Vector integerVector; + + void method() { + method(integerVector); + } + + void method(Vector v) { + + } +} \ No newline at end of file diff --git a/test/bytecode/types/ExtendsVectorStringTest.java b/test/bytecode/types/ExtendsVectorStringTest.java new file mode 100644 index 000000000..c106fbeec --- /dev/null +++ b/test/bytecode/types/ExtendsVectorStringTest.java @@ -0,0 +1,92 @@ +package bytecode.types; + +import static org.junit.Assert.*; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.Vector; + +import org.junit.BeforeClass; +import org.junit.Test; + +import bytecode.ASTBytecodeTest; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.typeinference.Menge; + + +public class ExtendsVectorStringTest extends ASTBytecodeTest{ + + public SourceFile getSourceFile(){ + /* + import java.util.Vector; + + class ExtendsVector extends Vector{ + + } + */ + SourceFile sourceFile = new SourceFile(); + + Menge parameter = new Menge<>(); + parameter.add(new RefType("java.lang.String", sourceFile, 0)); + + de.dhbwstuttgart.syntaxtree.Class classToTest = ASTFactory.createClass(getTestName(), new RefType("java.util.Vector", parameter, sourceFile, 0), null, null, sourceFile); + sourceFile.addElement(classToTest); + + return sourceFile; + } + + @Test + public void testSupertype(){ + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(getTestName()); + + assertEquals("java.util.Vector", cls.getSuperclass().getName()); + }catch(Exception e){ + e.printStackTrace(); + fail(); + } + } + + @Test + public void testParameter(){ + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(getTestName()); + + Object obj = cls.newInstance(); + + Class objectClass = classLoader.loadClass("java.lang.String"); + + Class[] params = new Class[1]; + params[0] = objectClass; + + Method method = cls.getDeclaredMethod("add", params); + method.invoke(obj, objectClass.newInstance()); + }catch(Exception e){ + throw new RuntimeException(e); + } + } + + @Override + public String getRootDirectory() { + return super.getRootDirectory()+"types/"; + } + + + + @Override + public String getTestName() { + return "ExtendsVectorString"; + } + + class StringVector extends Vector{ + + } + +} diff --git a/test/bytecode/types/ExtendsVectorTest.java b/test/bytecode/types/ExtendsVectorTest.java new file mode 100644 index 000000000..3856dbb3e --- /dev/null +++ b/test/bytecode/types/ExtendsVectorTest.java @@ -0,0 +1,59 @@ +package bytecode.types; + +import static org.junit.Assert.*; + +import java.lang.reflect.Constructor; + +import org.junit.BeforeClass; +import org.junit.Test; + +import bytecode.ASTBytecodeTest; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.syntaxtree.type.RefType; + + +public class ExtendsVectorTest extends ASTBytecodeTest{ + public SourceFile getSourceFile(){ + /* + import java.util.Vector; + + class ExtendsVector extends Vector{ + + } + */ + SourceFile sourceFile = new SourceFile(); + + de.dhbwstuttgart.syntaxtree.Class classToTest = ASTFactory.createClass(getTestName(), new RefType("java.util.Vector", sourceFile, 0), null, null, sourceFile); + sourceFile.addElement(classToTest); + + return sourceFile; + } + + @Test + public void testSupertype(){ + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(getTestName()); + + assertEquals("java.util.Vector", cls.getSuperclass().getName()); + }catch(Exception e){ + e.printStackTrace(); + fail(); + } + } + + @Override + public String getRootDirectory() { + return super.getRootDirectory()+"types/"; + } + + + + @Override + public String getTestName() { + return "ExtendsVector"; + } + +} diff --git a/test/bytecode/types/MethodWithTypedVector.jav b/test/bytecode/types/MethodWithTypedVector.jav new file mode 100644 index 000000000..35261e96f --- /dev/null +++ b/test/bytecode/types/MethodWithTypedVector.jav @@ -0,0 +1,11 @@ +import java.util.Vector; + +class MethodWithTypedVector{ + public void method(Vector v) { + + } + + public void method(Vector v) { + + } +} \ No newline at end of file diff --git a/test/bytecode/types/MethodWithTypedVectorTest.java b/test/bytecode/types/MethodWithTypedVectorTest.java new file mode 100644 index 000000000..f8ae8fe3b --- /dev/null +++ b/test/bytecode/types/MethodWithTypedVectorTest.java @@ -0,0 +1,45 @@ +package bytecode.types; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Stack; +import java.util.Vector; + +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.Section; + +public class MethodWithTypedVectorTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "MethodWithTypedVector"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/types/"; + } + + @Test + public void test() { + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Class stringVector = classLoader.loadClass("java%util%Vector%%java%lang%String%"); + + Class[] params = new Class[1]; + params[0] = stringVector; + + Method method = cls.getDeclaredMethod("method", params); + method.invoke(obj, stringVector.newInstance()); + }catch(Exception e){ + throw new RuntimeException(e); + } + } +} diff --git a/test/bytecode/types/MethodWithUntypedVector.jav b/test/bytecode/types/MethodWithUntypedVector.jav new file mode 100644 index 000000000..fead39817 --- /dev/null +++ b/test/bytecode/types/MethodWithUntypedVector.jav @@ -0,0 +1,7 @@ +import java.util.Vector; + +class MethodWithUntypedVector{ + public void method(Vector v) { + + } +} \ No newline at end of file diff --git a/test/bytecode/types/MethodWithUntypedVectorTest.java b/test/bytecode/types/MethodWithUntypedVectorTest.java new file mode 100644 index 000000000..bb0a75775 --- /dev/null +++ b/test/bytecode/types/MethodWithUntypedVectorTest.java @@ -0,0 +1,68 @@ +package bytecode.types; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Stack; +import java.util.Vector; + +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.Section; + +public class MethodWithUntypedVectorTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "MethodWithUntypedVector"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/types/"; + } + + @Test + public void testObjectVector() { + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + File file = new File(rootDirectory); + URL url = file.toURL(); + URL[] urls = new URL[]{url}; + + Object object = new Object(); + + Class[] params = new Class[1]; + params[0] = object.getClass(); + + Method method = cls.getDeclaredMethod("method", params); + method.invoke(obj, object); + }catch(Exception e){ + throw new RuntimeException(e); + } + } + + @Test + public void testGenericClass() { + try{ + ClassLoader classLoader = getClassLoader(); + + Class untypedVectorTest = classLoader.loadClass(testName); + + Class stringVector = classLoader.loadClass("java%util%Vector%%java%lang%Object%"); + + Class[] params = new Class[1]; + params[0] = stringVector; + + Method method = untypedVectorTest.getDeclaredMethod("method", params); + method.invoke(untypedVectorTest.newInstance(), stringVector.newInstance()); + }catch(Exception e){ + throw new RuntimeException(e); + } + } +} diff --git a/test/bytecode/types/MultiExtends.jav b/test/bytecode/types/MultiExtends.jav new file mode 100644 index 000000000..d4ada054d --- /dev/null +++ b/test/bytecode/types/MultiExtends.jav @@ -0,0 +1,11 @@ +import java.util.Vector; + +class MultiExtends{ + Integer method(Vector a){ + return method2(a); + } + + Integer method2(Vector b){ + return 1; + } +} \ No newline at end of file diff --git a/test/bytecode/types/MultiExtendsTest.java b/test/bytecode/types/MultiExtendsTest.java new file mode 100644 index 000000000..066ad1ff7 --- /dev/null +++ b/test/bytecode/types/MultiExtendsTest.java @@ -0,0 +1,35 @@ +package bytecode.types; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Test; + +import org.junit.Ignore; + +import bytecode.SourceFileBytecodeTest; + + +public class MultiExtendsTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "MultiExtends"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/types/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/types/NewStatement.jav b/test/bytecode/types/NewStatement.jav new file mode 100644 index 000000000..9a8128367 --- /dev/null +++ b/test/bytecode/types/NewStatement.jav @@ -0,0 +1,10 @@ +import java.util.Vector; + +class NewStatement{ + + void methode(){ + Vector vi; + vi = new Vector(); + } + +} diff --git a/test/bytecode/types/NewStatementTest.java b/test/bytecode/types/NewStatementTest.java new file mode 100644 index 000000000..c63548b66 --- /dev/null +++ b/test/bytecode/types/NewStatementTest.java @@ -0,0 +1,32 @@ +package bytecode.types; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class NewStatementTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "NewStatement"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/types/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/bytecode/types/OL.jav b/test/bytecode/types/OL.jav new file mode 100644 index 000000000..080a25420 --- /dev/null +++ b/test/bytecode/types/OL.jav @@ -0,0 +1,18 @@ +class OL { + + m(x) { return x + x; } + + m(Boolean x) { return x; } +} + + + +class Main { + + main(x) { + ol; + ol = new OL(); + return ol.m(x); + } + +} \ No newline at end of file diff --git a/test/bytecode/types/OLTest.java b/test/bytecode/types/OLTest.java new file mode 100644 index 000000000..7f3263048 --- /dev/null +++ b/test/bytecode/types/OLTest.java @@ -0,0 +1,101 @@ +package bytecode.types; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class OLTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "OL"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/types/"; + } + + + @Test + public void testInteger() { + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + File file = new File(rootDirectory); + URL url = file.toURL(); + URL[] urls = new URL[]{url}; + + Integer integer = new Integer(1); + + Class[] params = new Class[1]; + params[0] = integer.getClass(); + + Method method = cls.getDeclaredMethod("m", params); + method.invoke(obj, integer); + assertTrue(true); + }catch(Exception e){ + throw new RuntimeException(e); + } + } + + @Test + public void testString() { + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + File file = new File(rootDirectory); + URL url = file.toURL(); + URL[] urls = new URL[]{url}; + + String string = "foo"; + + Class[] params = new Class[1]; + params[0] = string.getClass(); + + Method method = cls.getDeclaredMethod("m", params); + method.invoke(obj, string); + assertTrue(true); + }catch(Exception e){ + throw new RuntimeException(e); + } + } + + @Test + public void testBoolen() { + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + File file = new File(rootDirectory); + URL url = file.toURL(); + URL[] urls = new URL[]{url}; + + Boolean bool = new Boolean(true); + + Class[] params = new Class[1]; + params[0] = bool.getClass(); + + Method method = cls.getDeclaredMethod("m", params); + method.invoke(obj, bool); + assertTrue(true); + }catch(Exception e){ + throw new RuntimeException(e); + } + } + +} diff --git a/test/bytecode/types/Overloading.jav b/test/bytecode/types/Overloading.jav new file mode 100644 index 000000000..66a2ad814 --- /dev/null +++ b/test/bytecode/types/Overloading.jav @@ -0,0 +1,21 @@ +import java.util.Vector; + +class Overloading{ + + void method(Vector v) { + + } + + void method(Vector v) { + + } + + main(String[] args) { + ol; + ol = new Overloading(); + v; + v = new Vector (); + ol.method(v); + } + +} \ No newline at end of file diff --git a/test/bytecode/types/Overloading2.jav b/test/bytecode/types/Overloading2.jav new file mode 100644 index 000000000..86961c954 --- /dev/null +++ b/test/bytecode/types/Overloading2.jav @@ -0,0 +1,18 @@ +import java.util.Vector; + +class Overloading2{ + + String method(Vector v) { + return v; + } + + Integer method(Vector v) { + return v; + } + + public static void main(String[] args){ + Overloading2 t; + t = new Overloading2(); + t.method(new Vector()); + } +} \ No newline at end of file diff --git a/test/bytecode/types/Overloading2Test.java b/test/bytecode/types/Overloading2Test.java new file mode 100644 index 000000000..aed1c45d7 --- /dev/null +++ b/test/bytecode/types/Overloading2Test.java @@ -0,0 +1,71 @@ +package bytecode.types; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class Overloading2Test extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Overloading2"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/types/"; + } + + + @Test + public void testString() { + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + File file = new File(rootDirectory); + URL url = file.toURL(); + URL[] urls = new URL[]{url}; + + Class stringVector = classLoader.loadClass("java%util%Vector%%java%lang%String%"); + + Class[] params = new Class[1]; + params[0] = stringVector; + + Method method = cls.getDeclaredMethod("method", params); + method.invoke(obj, stringVector.newInstance()); + assertTrue(true); + }catch(Exception e){ + throw new RuntimeException(e); + } + } + + @Test + public void testInteger() { + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Class integerVector = classLoader.loadClass("java%util%Vector%%java%lang%Integer%"); + + Class[] params = new Class[1]; + params[0] = integerVector; + + Method method = cls.getDeclaredMethod("method", params); + method.invoke(obj, integerVector.newInstance()); + assertTrue(true); + }catch(Exception e){ + throw new RuntimeException(e); + } + } + +} diff --git a/test/bytecode/types/OverloadingReplace.jav b/test/bytecode/types/OverloadingReplace.jav new file mode 100644 index 000000000..70763fa0d --- /dev/null +++ b/test/bytecode/types/OverloadingReplace.jav @@ -0,0 +1,18 @@ +import java.util.Vector; + +class OverloadingReplace{ + +Vector test; + + void method(){ + method(test); + } + + void method(Vector v) { + + } + + void method(Vector v) { + + } +} \ No newline at end of file diff --git a/test/bytecode/types/OverloadingTest.java b/test/bytecode/types/OverloadingTest.java new file mode 100644 index 000000000..ea5d15688 --- /dev/null +++ b/test/bytecode/types/OverloadingTest.java @@ -0,0 +1,71 @@ +package bytecode.types; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.Test; + +import bytecode.SourceFileBytecodeTest; + +public class OverloadingTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "Overloading"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/types/"; + } + + + @Test + public void testString() { + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + File file = new File(rootDirectory); + URL url = file.toURL(); + URL[] urls = new URL[]{url}; + + Class stringVector = classLoader.loadClass("java%util%Vector%%java%lang%String%"); + + Class[] params = new Class[1]; + params[0] = stringVector; + + Method method = cls.getDeclaredMethod("method", params); + method.invoke(obj, stringVector.newInstance()); + assertTrue(true); + }catch(Exception e){ + throw new RuntimeException(e); + } + } + + @Test + public void testInteger() { + try{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + + Class integerVector = classLoader.loadClass("java%util%Vector%%java%lang%Integer%"); + + Class[] params = new Class[1]; + params[0] = integerVector; + + Method method = cls.getDeclaredMethod("method", params); + method.invoke(obj, integerVector.newInstance()); + assertTrue(true); + }catch(Exception e){ + throw new RuntimeException(e); + } + } + +} diff --git a/test/bytecode/types/SuperType.jav b/test/bytecode/types/SuperType.jav new file mode 100644 index 000000000..f029c2d08 --- /dev/null +++ b/test/bytecode/types/SuperType.jav @@ -0,0 +1,13 @@ +import java.util.Vector; + +class SuperType{ + Vector numberVector; + + void method() { + method(numberVector); + } + + void method(Vector v) { + + } +} \ No newline at end of file diff --git a/test/bytecode/types/WildcardTest.jav b/test/bytecode/types/WildcardTest.jav new file mode 100644 index 000000000..647d7b668 --- /dev/null +++ b/test/bytecode/types/WildcardTest.jav @@ -0,0 +1,11 @@ +import java.util.Vector; + +class WildcardTest{ + void lower(Vector v) { + + } + + void upper(Vector v) { + + } +} \ No newline at end of file diff --git a/test/bytecode/types/WildcardTest.java b/test/bytecode/types/WildcardTest.java new file mode 100644 index 000000000..44df73a95 --- /dev/null +++ b/test/bytecode/types/WildcardTest.java @@ -0,0 +1,28 @@ +package bytecode.types; + +import static org.junit.Assert.*; + + +import org.junit.Test; + + +import bytecode.SourceFileBytecodeTest; + + +public class WildcardTest extends SourceFileBytecodeTest{ + @Override + protected void init() { + testName = "WildcardTest"; + rootDirectory = System.getProperty("user.dir")+"/test/bytecode/types/"; + } + + @Test + public void testConstruct() throws Exception{ + ClassLoader classLoader = getClassLoader(); + + Class cls = classLoader.loadClass(testName); + + Object obj = cls.newInstance(); + assertTrue(true); + } +} diff --git a/test/parser/GeneralParserTest.java b/test/parser/GeneralParserTest.java index e225c68ed..59f8a07bb 100644 --- a/test/parser/GeneralParserTest.java +++ b/test/parser/GeneralParserTest.java @@ -8,9 +8,10 @@ import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.typeinference.Menge; import junit.framework.TestCase; import org.junit.Test; @@ -30,19 +31,19 @@ public class GeneralParserTest{ @Test public void run(){ + LoggerConfiguration config = new LoggerConfiguration(); + config.setOutput(Section.PARSER, System.out); - List filenames = new ArrayList(); + Menge filenames = new Menge(); filenames.add("FieldInitializationTest.jav"); filenames.add("ImportTest.jav"); filenames.add("BoundedParameter.jav"); filenames.add("GenericFieldVarTest.jav"); filenames.add("FieldVarTest.jav"); - //MyCompilerAPI compiler = MyCompiler.getAPI(config); + MyCompilerAPI compiler = MyCompiler.getAPI(config); try{ - for(String filename : filenames) { - //compiler.parse(new File(rootDirectory + filename)); - //TODO: Test ANTLR Parser - } + for(String filename : filenames) + compiler.parse(new File(rootDirectory + filename)); }catch(Exception exc){ exc.printStackTrace(); fail(); diff --git a/test/plugindevelopment/InsertSingleTypeTest.java b/test/plugindevelopment/InsertSingleTypeTest.java new file mode 100644 index 000000000..916f45fcf --- /dev/null +++ b/test/plugindevelopment/InsertSingleTypeTest.java @@ -0,0 +1,66 @@ +package plugindevelopment; + +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; + +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; +import junit.framework.TestCase; + +public class InsertSingleTypeTest { + private static final String testFile = "SingleTypeInsertTest.jav"; + + @Test + public void test1(){ + TypeinferenceResultSet res = test(testFile); + TypeInsertPoint p = res.getTypeInsertionPoints().points.firstElement(); + try { + System.out.println(res.getTypeInsertionPoints().insertType(p, this.getFileContent(rootDirectory + testFile))); + } catch (IOException e) { + TestCase.fail(); + e.printStackTrace(); + } + } + + static final String rootDirectory = System.getProperty("user.dir")+"/test/plugindevelopment/"; + + public static TypeinferenceResultSet test(String sourceFileToInfere){ + + String inferedSource = ""; + MyCompilerAPI compiler = MyCompiler.getAPI(new LoggerConfiguration().setOutput(Section.TYPEINFERENCE, System.out)); + try { + SourceFile parsed = compiler.parse(new File(rootDirectory + sourceFileToInfere));Menge sourceFiles = new Menge<>(); + sourceFiles.add(parsed); + Menge results = compiler.typeReconstruction(sourceFiles); + TestCase.assertTrue("Es darf nicht mehr als eine L�sungsm�glichkeit geben und nicht "+results.size(), results.size()==1); + return results.firstElement(); + } catch (IOException | yyException e) { + e.printStackTrace(); + TestCase.fail(); + return null; + } + } + + //Source: https://stackoverflow.com/questions/326390/how-to-create-a-java-string-from-the-contents-of-a-file + //PS: ben�tigt Java 7 + public static String getFileContent(String path)throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return StandardCharsets.UTF_8.decode(ByteBuffer.wrap(encoded)).toString(); + } +} diff --git a/test/plugindevelopment/MartinTestCases/AchimTest1.jav b/test/plugindevelopment/MartinTestCases/AchimTest1.jav new file mode 100755 index 000000000..35d7739d5 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/AchimTest1.jav @@ -0,0 +1,9 @@ +class Test{ + test(){ + return 1; + } + test2(){ + i; + i = test(); + } +} diff --git a/test/plugindevelopment/MartinTestCases/BoundedType.jav b/test/plugindevelopment/MartinTestCases/BoundedType.jav new file mode 100755 index 000000000..ca33735a7 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/BoundedType.jav @@ -0,0 +1,12 @@ +class BoundedType { + + m(T x) { + return x; + } + + m1(x) { + T y; + x = y; + return y; + } +} \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/BoundedType1.jav b/test/plugindevelopment/MartinTestCases/BoundedType1.jav new file mode 100755 index 000000000..f56a643e0 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/BoundedType1.jav @@ -0,0 +1,16 @@ +interface BB { } +interface AA extends BB { + AAm(BB x); + } + +interface RR extends BB { + } + +class BoundedType1 { + + + m1(AA a) { + T1 b; + a.AAm(b); + } +} \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/BoundedType2.jav b/test/plugindevelopment/MartinTestCases/BoundedType2.jav new file mode 100755 index 000000000..ccb0d6a2f --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/BoundedType2.jav @@ -0,0 +1,15 @@ +class BoundedType { + m(T x) { + r; + r=x; + return r; + } + m1(b) { return b; } + +} + +class Id { + BoundedType bb; + m(x) { return bb.m1(x); } + } + \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/Id.jav b/test/plugindevelopment/MartinTestCases/Id.jav new file mode 100644 index 000000000..d2293b4b8 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/Id.jav @@ -0,0 +1,3 @@ +class Id { + Fun1 op = (x) -> x; + } \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/MatrixVectorMul.jav b/test/plugindevelopment/MartinTestCases/MatrixVectorMul.jav new file mode 100644 index 000000000..50bad19aa --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/MatrixVectorMul.jav @@ -0,0 +1,14 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class Matrix extends Menge> { + + mvmul(Menge v) { + i; + ele; + v.add(1); + while (i < v.size()) { + + ele = 5 + v.elementAt(i); + } + } +} diff --git a/test/plugindevelopment/MartinTestCases/MatrixWhile.jav b/test/plugindevelopment/MartinTestCases/MatrixWhile.jav new file mode 100644 index 000000000..7096ba0c6 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/MatrixWhile.jav @@ -0,0 +1,43 @@ +class Matrix extends Menge> { + + Matrix mul_rec(Matrix m) { + v1; + v1 = new Menge(); + v2; + v2 = new Menge(); + i; + i = 0; + while(i < m.size()) { + v; + v = m.elementAt(i); + v2.addElement(v.remove(v.size()-1)); + i++; + } + Matrix ret; + if (m.elementAt(0).size() > 0) { + ret = this.mul_rec(m); + } + else { + ret = new Matrix(); + i = 0; + while (i < this.size()) { + ret.addElement(new Menge()); + i++; + } + } + i = 0; + while (i < this.size()) { + int erg = 0; + j; + j = 0; + while (j < v2.size()) { + erg = erg + this.elementAt(i).elementAt(j).intValue() + * v2.elementAt(j).intValue(); + j++; + } + ret.elementAt(i).addElement(erg); + i++; + } + return ret; + } +} \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/Matrix_lambda.jav b/test/plugindevelopment/MartinTestCases/Matrix_lambda.jav new file mode 100644 index 000000000..a505aea9d --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/Matrix_lambda.jav @@ -0,0 +1,5 @@ +import java.util.Vector; + +class Matrix { + op = (m) -> (f) -> f.apply(m); +} \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/MethodId.jav b/test/plugindevelopment/MartinTestCases/MethodId.jav new file mode 100644 index 000000000..f8f44dec3 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/MethodId.jav @@ -0,0 +1,6 @@ +class MethodId { + + US m (UR x) { + return x; + } + } \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/MethodIntegerUse.jav b/test/plugindevelopment/MartinTestCases/MethodIntegerUse.jav new file mode 100644 index 000000000..11f2c06bc --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/MethodIntegerUse.jav @@ -0,0 +1,8 @@ +class MethodIntegerUse { + Fun1 op = (x) -> m(x); + + + Integer m (Integer x) { + return x; + } + } \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/MethodUse.jav b/test/plugindevelopment/MartinTestCases/MethodUse.jav new file mode 100644 index 000000000..1349b7ff7 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/MethodUse.jav @@ -0,0 +1,8 @@ +class MethodUse { + Fun1 op = (x) -> m(x); + + + AP m (AO x) { + return x; + } + } \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/OL.jav b/test/plugindevelopment/MartinTestCases/OL.jav new file mode 100755 index 000000000..66e95aeb3 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/OL.jav @@ -0,0 +1,16 @@ +class OL { + + Integer m(Integer x) { return x + x; } + + Boolean m(Boolean x) {return x || x; } +} + +class Main { + + main(x) { + ol; + ol = new OL(); + return ol.m(x); + } + +} diff --git a/test/plugindevelopment/MartinTestCases/OL2.jav b/test/plugindevelopment/MartinTestCases/OL2.jav new file mode 100755 index 000000000..87b63a44e --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/OL2.jav @@ -0,0 +1,19 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class OL2 { + + Integer m(Integer x) { return x + x; } + + Boolean m(Boolean x) {return x || x; } +} + +class Main { + + main(x) { + ol; + ol = new OL2(); + y; + y.add(ol.m(x)); + } + +} diff --git a/test/plugindevelopment/MartinTestCases/OL3.jav b/test/plugindevelopment/MartinTestCases/OL3.jav new file mode 100644 index 000000000..0ccd6da1b --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/OL3.jav @@ -0,0 +1,9 @@ +class Test{ + String main(){ + return m(()->{return "Test";}); + } + String m(p){ + return p.apply(); + } + void m(p){} +} diff --git a/test/plugindevelopment/MartinTestCases/Plus1.jav b/test/plugindevelopment/MartinTestCases/Plus1.jav new file mode 100644 index 000000000..6b0ca749a --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/Plus1.jav @@ -0,0 +1,3 @@ +class Plus1 { + Fun1 op = (x) -> x+1; + } \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/Plus1_Float_Double.jav b/test/plugindevelopment/MartinTestCases/Plus1_Float_Double.jav new file mode 100644 index 000000000..5291001cd --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/Plus1_Float_Double.jav @@ -0,0 +1,3 @@ +class Plus1_Float_Double { + op = (x) -> x + 1.0; + } \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/Probleme b/test/plugindevelopment/MartinTestCases/Probleme new file mode 100755 index 000000000..f4ebc5a23 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/Probleme @@ -0,0 +1,41 @@ +- Sequenz-Diagramme fuer TR-Algorithmen +- In der GUI werden bei der Auswahl bei Typisierungen mehrerer Klassen immer nur die Typisierung der einzelnen Klasse angepasst (Use-Rase ZweiKlassen.jav) +- Bound bleiben in der GUI erhalten auch wenn durch Auswahl die Bounds gar nicht mehr existieren (Use-Rase BoundedType2.jav) +- Parameter gehen nicht Matrix Use-Rase +- gleiche TypePlaceHolder in unterschiedlichen Intersections werden durch unterschiedliche GentypeVars ersetzt (BoundedType2.jav) +- Mail von Juergen, welche Usecases machen ihm Probleme? +- UsedId bei bei "extends" in RefType bzw. bei "implements" in Menge umwandeln. (siehe mail an Timo) +- Roundtrip fuer den Innovator einbauen erledigt 06-06 +- Schnittstelle mit syntaktischen Angaben fuer den Konstantenpool wird bei unbeboxten Typen nicht richtig erzeugt +- Boxing und Unboxing geht noch nicht bei allen primitiven Typen und Operatoren +-------------------------------------------------------------------------------------------------- +- makeFC testen durch Verschiebung von TyploseVaribale yu GentypeVar + sind Probleme entstanden PL 06-03-16 +- Alle UseCases noch mit Vervielfachung testen +- Codeerzeugung: called_method +- Returntyp void UsecaseThree_pl.jav ERLEDIGT Fehler in Void.java 05-07-31 +- Parameter in Typen: Werden die �berhaupt betrachtet? UsecaseTwo_pl.jav +- Die Argumente bei UsedId Konstruktion f�r die Parameter in dem Attribut paralist von Typen + sind immer GenericTypeVars, k�nnten aber auch Typen wie Integer als RefTypes sein. + In der Methode wandleGeneric2RefType (MyCompiler) werden nur die GenericTypeVars + der Superklassen-Deklarationen angepasst. Hier muessten alle expliziten Typdeklarationen + im gesamten abstrakten Syntaxbaum angepasst werden. Koennte ueber eine Registry + und die Listener realisiert werden. ERLEDIGT SourceFile.java 05-07-31 +- getypte Variablen werden nicht richtig gesetzt UsecaseFive_pl.jav ERLEDIGT JavaParser.jay 05-07-30 + +- UNIFY funktioniert nicht mit GenericTypeVars UsecaseOne_pl.jav +- Einschränkungen bei TRMAPP von noch einbauen. +- a.b wird als Expression nicht in InstVar umgewandelt, sondern bleibt LocalOrFieldVar mit UsedId UsecaseNine_pl.jav + wird inzwischen bei zwei Identifieren umgewandelt. Mit mehr testen +- In Usecase UsecaseNine_pl.jav wird der Parameter bei der Klasse bei b nicht bestimmt. +- Braucht man das Field type vom Typ String in InstVar.java? +- in Assign stimmt der Typ von Assign nicht (Beispiel Matrix1.jav in bajo) +- unifyAndregister in allen Subklassen von ExprStmt durch register ersetzen. erledigt 05-08-21 +- Class.java: m_MethodIntersectionTypes wird in CTypeReconstructionResult nicht richtig gestetzt. + Beispiel Matrix.jav in bajo1_usecases +- clone in alle Subklassen von CTypeAssumption ueberpruefen. +- Was ist der Unterschied zwischen RefType.clone() und Pair.copyType +- in instanceSmaller neuhinzugekommene GENTYPEVARS durch typlose Vars ersetzen. +- EST95A anschauen. Insbesondere: Wann ist this View und wann GView? + siehe SubtypeingTest this wird immer dynamisch angepasst. Auch in + der Theorie aendern \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/SMatrix.jav b/test/plugindevelopment/MartinTestCases/SMatrix.jav new file mode 100755 index 000000000..bbb6bb5f7 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/SMatrix.jav @@ -0,0 +1,11 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class Matrix extends Menge> { + + mul(){ + Menge> ret1; + Menge ret; + return ret; + } + +} diff --git a/test/plugindevelopment/MartinTestCases/Simple.jav b/test/plugindevelopment/MartinTestCases/Simple.jav new file mode 100755 index 000000000..312e8a885 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/Simple.jav @@ -0,0 +1,10 @@ +class Simple { + + simple(a) { + return 1; + } + + main(a) { + return a; + } +} \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/Tester.java b/test/plugindevelopment/MartinTestCases/Tester.java new file mode 100644 index 000000000..d739fd496 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/Tester.java @@ -0,0 +1,101 @@ +package plugindevelopment.MartinTestCases; + +import java.io.File; +import java.io.IOException; + +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; +import plugindevelopment.TypeInsertTester; +import plugindevelopment.TypeInsertTests.MultipleTypesInsertTester; +import junit.framework.TestCase; + +public class Tester extends TypeInsertTester{ + + public final static String rootDirectory = System.getProperty("user.dir")+"/test/plugindevelopment/MartinTestCases/"; + + public static void test(String sourceFileToInfere, Menge mustContain){ + String gesamterSrc = ""; + String inferedSource = ""; + MyCompilerAPI compiler = MyCompiler.getAPI(new LoggerConfiguration().setOutput(Section.TYPEINFERENCE, System.out)); + try { + SourceFile parsed = compiler.parse(new File(rootDirectory + sourceFileToInfere)); + Menge sourceFiles = new Menge<>(); + sourceFiles.add(parsed); + Menge results = compiler.typeReconstruction(sourceFiles); + //TestCase.assertTrue("Es darf nicht mehr als eine L�sungsm�glichkeit geben und nicht "+results.size(), results.size()==1); + for(TypeinferenceResultSet result : results){ + TypeInsertSet point = result.getTypeInsertionPoints(); + //TestCase.assertTrue("Es muss mindestens ein TypeInsertSet vorhanden sein", points.size()>0); + + //TestCase.assertTrue("Es muss mindestens ein TypeInsertPoint vorhanden sein", point.points.size()>0); + if(point.points.size()>0){ + inferedSource = point.insertAllTypes(TypeInsertTester.getFileContent(rootDirectory + sourceFileToInfere)); + System.out.println(inferedSource); + gesamterSrc += inferedSource; + } + + } + + } catch (IOException | yyException e) { + e.printStackTrace(); + TestCase.fail(); + } + for(String containString : mustContain){ + TestCase.assertTrue("\""+containString+"\" muss in den inferierten L�sungen vorkommen",gesamterSrc.contains(containString)); + } + } + + @Test + public void runTests(){ + Menge testFiles = new Menge(); + //testFiles.add("OL3.jav"); + testFiles.add("Plus1_Float_Double.jav"); + ///* + testFiles.add("AchimTest1.jav"); + //testFiles.add("MatrixWhile.jav"); + //testFiles.add("BoundedType1.jav"); + testFiles.add("BoundedType2.jav"); + testFiles.add("BoundedType.jav"); + + testFiles.add("OL2.jav"); + testFiles.add("OL.jav"); + testFiles.add("Simple.jav"); + testFiles.add("SMatrix.jav"); + testFiles.add("UnifyTest1.jav"); + testFiles.add("UsecaseEight_pl.jav"); + testFiles.add("UsecaseFive_pl.jav"); + testFiles.add("UsecaseFour_pl.jav"); + testFiles.add("Usecase_MUBTest1.jav"); + testFiles.add("Usecase_MUBTest2.jav"); + testFiles.add("Usecase_MUBTest3.jav"); + testFiles.add("Usecase_MUBTest4.jav"); + testFiles.add("Usecase_MUBTest5.jav"); + testFiles.add("Usecase_MUBTest6.jav"); + testFiles.add("Usecase_MUBTest.jav"); + testFiles.add("UsecaseNine_pl.jav"); + testFiles.add("UsecaseOne_pl.jav"); + testFiles.add("UsecaseSeven_pl.jav"); + testFiles.add("UsecaseSix_pl.jav"); + testFiles.add("UsecaseTen_pl.jav"); + testFiles.add("UsecaseThree_pl.jav"); + testFiles.add("UsecaseThree_pl.orig.jav"); + testFiles.add("UsecaseTwo_pl.jav"); + testFiles.add("ZweiKlassen.jav"); + //*/ + for(String file : testFiles){ + System.out.println("Testfile: "+file); + Tester.test(file, new Menge()); + } + } + +} diff --git a/test/plugindevelopment/MartinTestCases/UnifyTest1.jav b/test/plugindevelopment/MartinTestCases/UnifyTest1.jav new file mode 100755 index 000000000..810baa61d --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/UnifyTest1.jav @@ -0,0 +1,11 @@ +import de.dhbwstuttgart.typeinference.Menge; +import java.util.Stack; + + +class Test { + public getValue(a){ + String x; + a.add(x); + } + +} diff --git a/test/plugindevelopment/MartinTestCases/UsecaseEight_pl.jav b/test/plugindevelopment/MartinTestCases/UsecaseEight_pl.jav new file mode 100755 index 000000000..f2395352f --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/UsecaseEight_pl.jav @@ -0,0 +1,10 @@ +class UsecaseEight_pl { + + foo1() { + a; + b; + a = b.foo1(); + return 1; + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/UsecaseFive_pl.jav b/test/plugindevelopment/MartinTestCases/UsecaseFive_pl.jav new file mode 100755 index 000000000..b66225536 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/UsecaseFive_pl.jav @@ -0,0 +1,11 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class UsecaseFive_pl { + + foo() { + Menge c; + c = new Menge() ; + return c; + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/UsecaseFour_pl.jav b/test/plugindevelopment/MartinTestCases/UsecaseFour_pl.jav new file mode 100755 index 000000000..415318d4f --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/UsecaseFour_pl.jav @@ -0,0 +1,9 @@ +class UsecaseFour_pl { + + foo() { + c; + c = new Menge() ; + return c; + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/UsecaseNine_pl.jav b/test/plugindevelopment/MartinTestCases/UsecaseNine_pl.jav new file mode 100755 index 000000000..979b2baad --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/UsecaseNine_pl.jav @@ -0,0 +1,12 @@ +class UsecaseNine_pl { + + Integer c; + + foo1() { + a; + b; + a = b.c; + return 1; + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/UsecaseOne_pl.jav b/test/plugindevelopment/MartinTestCases/UsecaseOne_pl.jav new file mode 100755 index 000000000..5156ae484 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/UsecaseOne_pl.jav @@ -0,0 +1,20 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class UsecaseOne_pl { + + A x; + + foo(bar){ + bar = true; + return 1; + } +/* + foo1(a) { + c; + c = new Menge(); + b; + b = new UsecaseOne_pl(); + return c.addElement(a); + } +*/ +} diff --git a/test/plugindevelopment/MartinTestCases/UsecaseSeven_pl.jav b/test/plugindevelopment/MartinTestCases/UsecaseSeven_pl.jav new file mode 100755 index 000000000..5744f550e --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/UsecaseSeven_pl.jav @@ -0,0 +1,18 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class UsecaseSeven_pl { + + foo(bar){ + bar = true; + return 1; + } + + foo1(a) { + c; + c = new Menge(); + b; + b = new UsecaseSeven_pl(); + return c.addElement(a); + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/UsecaseSix_pl.jav b/test/plugindevelopment/MartinTestCases/UsecaseSix_pl.jav new file mode 100755 index 000000000..45c140af8 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/UsecaseSix_pl.jav @@ -0,0 +1,5 @@ +class uuu {} +class vvv {} +class UsecaseSix_pl extends Menge> { + +} \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/UsecaseTen_pl.jav b/test/plugindevelopment/MartinTestCases/UsecaseTen_pl.jav new file mode 100755 index 000000000..ab5b8d005 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/UsecaseTen_pl.jav @@ -0,0 +1,14 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class UsecaseTen_pl { + + Menge c; + + foo1() { + a; + b; + a = b.c.elementAt(1); + return b; + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/UsecaseThree_pl.jav b/test/plugindevelopment/MartinTestCases/UsecaseThree_pl.jav new file mode 100755 index 000000000..b03518144 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/UsecaseThree_pl.jav @@ -0,0 +1,9 @@ +class UsecaseThree_pl { + + foo() { + c; + c = new Menge(); + return c; + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/UsecaseThree_pl.orig.jav b/test/plugindevelopment/MartinTestCases/UsecaseThree_pl.orig.jav new file mode 100755 index 000000000..aecefabd1 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/UsecaseThree_pl.orig.jav @@ -0,0 +1,11 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class UsecaseThree_pl_org { + + Menge foo() { + Menge c; + c = new Menge(); + return c; + } + +} diff --git a/test/plugindevelopment/MartinTestCases/UsecaseTwo_pl.jav b/test/plugindevelopment/MartinTestCases/UsecaseTwo_pl.jav new file mode 100755 index 000000000..8fbb75e16 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/UsecaseTwo_pl.jav @@ -0,0 +1,11 @@ +class UsecaseTwo_pl { + + foo() { + d; + d = new UsecaseTwo_pl (); + e; + e = d.foo(); + return d; + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/Usecase_MUBTest.jav b/test/plugindevelopment/MartinTestCases/Usecase_MUBTest.jav new file mode 100755 index 000000000..bda38eb28 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/Usecase_MUBTest.jav @@ -0,0 +1,12 @@ +class A { } + +class B extends A { + f(Boolean x) { + if (x) { + return new B(); } + else { + return new A(); } + } +} + +class C extends B> {} diff --git a/test/plugindevelopment/MartinTestCases/Usecase_MUBTest1.jav b/test/plugindevelopment/MartinTestCases/Usecase_MUBTest1.jav new file mode 100755 index 000000000..cfe0e30e8 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/Usecase_MUBTest1.jav @@ -0,0 +1,17 @@ + + +class A { } + +class B extends A { + f(Boolean x) { + if (x) { + return new B(); } + else { + return new A(); } + } +} + +class C extends B> {} + + + diff --git a/test/plugindevelopment/MartinTestCases/Usecase_MUBTest2.jav b/test/plugindevelopment/MartinTestCases/Usecase_MUBTest2.jav new file mode 100755 index 000000000..08e66aed6 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/Usecase_MUBTest2.jav @@ -0,0 +1,13 @@ +class A { } + +class B extends A { + f(x) { + a; + if (x) { + return new C(); } + else { + return a; } + } +} + +class C extends B> {} diff --git a/test/plugindevelopment/MartinTestCases/Usecase_MUBTest3.jav b/test/plugindevelopment/MartinTestCases/Usecase_MUBTest3.jav new file mode 100755 index 000000000..fc7a33cd3 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/Usecase_MUBTest3.jav @@ -0,0 +1,14 @@ +class A { } + +class B extends A { + f(x) { + a; + b; + if (x) { + return a; } + else { + return b; } + } +} + +class C extends B> {} diff --git a/test/plugindevelopment/MartinTestCases/Usecase_MUBTest4.jav b/test/plugindevelopment/MartinTestCases/Usecase_MUBTest4.jav new file mode 100755 index 000000000..0325a6008 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/Usecase_MUBTest4.jav @@ -0,0 +1,12 @@ +class A { } + +class B extends A { + f(Boolean x) { + if (x) { + return new B(); } + else { + return new C(); } + } +} + +class C extends B> {} diff --git a/test/plugindevelopment/MartinTestCases/Usecase_MUBTest5.jav b/test/plugindevelopment/MartinTestCases/Usecase_MUBTest5.jav new file mode 100755 index 000000000..c1b2b19b6 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/Usecase_MUBTest5.jav @@ -0,0 +1,12 @@ +class A { } + +class B extends A { + f(Boolean x) { + if (x) { + return new B(); } + else { + return new C(); } + } +} + +class C extends B> {} diff --git a/test/plugindevelopment/MartinTestCases/Usecase_MUBTest6.jav b/test/plugindevelopment/MartinTestCases/Usecase_MUBTest6.jav new file mode 100755 index 000000000..2d494563d --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/Usecase_MUBTest6.jav @@ -0,0 +1,9 @@ +class Test2 { + public meth(){ + if(true) { + return(1); + }else{ + return(2); + } + } +} diff --git a/test/plugindevelopment/MartinTestCases/ZweiKlassen.jav b/test/plugindevelopment/MartinTestCases/ZweiKlassen.jav new file mode 100755 index 000000000..e74b9b9fe --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/ZweiKlassen.jav @@ -0,0 +1,17 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class ZweiKlassen { + + foo() { + c; + c = new Menge() ; + return c; + } + +} + +class X { + ZweiKlassen bb; + + foo2() { return bb.foo();} +} \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/Fehler Report b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/Fehler Report new file mode 100644 index 000000000..246508723 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/Fehler Report @@ -0,0 +1,37 @@ +Allgemeine Probleme: + +- Argument von lambda-Aussdrücken hat falsche Typvar: Könnte das darin liegen, + dass die Typvar auch in der abstrakten Syntax gelöscht wird? + +- unnötige constraints entfernen + +- Textmarker werden, beim speichern nicht gelöscht, es wird einfach der neue + Text hinzugefügt + +Dateien: + +- Id.jav: funktioniert + +- Matrix_lambda.jav: es bleiben TPH im Typ stehen. + TPH IM müsste irgend Supertyp von Matrix (this) sein. + +- MethodId.jav: funktioniert; + +- MethodIntegerUse.jav: funktioniert; + +- MethodUse.jav: funktioniert; + +- OL.jav: + * java.lang.Float funktioniert als Return-Typ nicht: Parseerror + * wenn man beim ersten m einen Typ auswählt wird der vom zweiten m eingetragen + warum? + In der zweiten Klasse kann man nach dem eintragen nichts mehr auswählen + * Wenn man in der zweiten Klassen einen Typ auswählt kann man in der ersten + nichts mehr auswählen. Was wird eigetragen? + +- Plus1_Float_Double.jav: Syntax-Error und Nullpointer-Exception + +- Plus1.jav: funktioniert; Frage: gibt es keinen anderen Typ mit +1? + + + diff --git a/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/Id.jav b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/Id.jav new file mode 100644 index 000000000..d2293b4b8 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/Id.jav @@ -0,0 +1,3 @@ +class Id { + Fun1 op = (x) -> x; + } \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/MatrixVectorMul.jav b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/MatrixVectorMul.jav new file mode 100644 index 000000000..50bad19aa --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/MatrixVectorMul.jav @@ -0,0 +1,14 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class Matrix extends Menge> { + + mvmul(Menge v) { + i; + ele; + v.add(1); + while (i < v.size()) { + + ele = 5 + v.elementAt(i); + } + } +} diff --git a/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/Matrix_lambda.jav b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/Matrix_lambda.jav new file mode 100644 index 000000000..51150cc17 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/Matrix_lambda.jav @@ -0,0 +1,5 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class Matrix extends Menge> { + Fun1>, Matrix> op = (Matrix m) -> (f) -> f.apply(this, m); +} \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/MethodId.jav b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/MethodId.jav new file mode 100644 index 000000000..f8f44dec3 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/MethodId.jav @@ -0,0 +1,6 @@ +class MethodId { + + US m (UR x) { + return x; + } + } \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/MethodIntegerUse.jav b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/MethodIntegerUse.jav new file mode 100644 index 000000000..11f2c06bc --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/MethodIntegerUse.jav @@ -0,0 +1,8 @@ +class MethodIntegerUse { + Fun1 op = (x) -> m(x); + + + Integer m (Integer x) { + return x; + } + } \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/MethodUse.jav b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/MethodUse.jav new file mode 100644 index 000000000..1349b7ff7 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/MethodUse.jav @@ -0,0 +1,8 @@ +class MethodUse { + Fun1 op = (x) -> m(x); + + + AP m (AO x) { + return x; + } + } \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/OL.jav b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/OL.jav new file mode 100644 index 000000000..65b5f88f3 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/OL.jav @@ -0,0 +1,19 @@ + +class OL { + + java.lang.Float m(java.lang.Float x) { return x + x; } + + java.lang.Boolean m(java.lang.Boolean x) {return x || x; } +} + + + +class Main { + + main(x) { + ol; + ol = new OL(); + return ol.m(x); + } + +} diff --git a/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/Plus1.jav b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/Plus1.jav new file mode 100644 index 000000000..6b0ca749a --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/Plus1.jav @@ -0,0 +1,3 @@ +class Plus1 { + Fun1 op = (x) -> x+1; + } \ No newline at end of file diff --git a/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/Plus1_Float_Double.jav b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/Plus1_Float_Double.jav new file mode 100644 index 000000000..75c3baad7 --- /dev/null +++ b/test/plugindevelopment/MartinTestCases/jav/Lambda_usecases/Plus1_Float_Double.jav @@ -0,0 +1,3 @@ +class Plus1_Float_Double { + op = (x) -> x+1.0; + } \ No newline at end of file diff --git a/test/plugindevelopment/MethodTypeInsertTest.jav b/test/plugindevelopment/MethodTypeInsertTest.jav new file mode 100644 index 000000000..03b20bc8f --- /dev/null +++ b/test/plugindevelopment/MethodTypeInsertTest.jav @@ -0,0 +1,6 @@ + +class VariableTypeInsertTest{ + methode(){ + return "String"; + } +} diff --git a/test/plugindevelopment/MethodTypeInsertTest.java b/test/plugindevelopment/MethodTypeInsertTest.java new file mode 100644 index 000000000..cf9c5aef0 --- /dev/null +++ b/test/plugindevelopment/MethodTypeInsertTest.java @@ -0,0 +1,16 @@ +package plugindevelopment; + +import org.junit.Test; + +public class MethodTypeInsertTest { + + + private static final String TEST_FILE = "MethodTypeInsertTest.jav"; + private static final String SOLUTION_FILE = "MethodTypeInsertTestSolution.jav"; + + @Test + public void run(){ + TypeInsertTester.test(this.TEST_FILE, this.SOLUTION_FILE); + } + +} diff --git a/test/plugindevelopment/MethodTypeInsertTestSolution.jav b/test/plugindevelopment/MethodTypeInsertTestSolution.jav new file mode 100644 index 000000000..4246f9536 --- /dev/null +++ b/test/plugindevelopment/MethodTypeInsertTestSolution.jav @@ -0,0 +1,6 @@ + +class VariableTypeInsertTest{ + String methode(){ + return "String"; + } +} diff --git a/test/plugindevelopment/ParameterInsertTest.java b/test/plugindevelopment/ParameterInsertTest.java new file mode 100644 index 000000000..63b108196 --- /dev/null +++ b/test/plugindevelopment/ParameterInsertTest.java @@ -0,0 +1,13 @@ +package plugindevelopment; + +import org.junit.Test; + +public class ParameterInsertTest { + private static final String TEST_FILE = "ParameterTypeInsertTest.jav"; + private static final String SOLUTION_FILE = "ParameterTypeInsertTestSolution.jav"; + + @Test + public void run(){ + TypeInsertTester.test(this.TEST_FILE, this.SOLUTION_FILE); + } +} diff --git a/test/plugindevelopment/ParameterTypeInsertTest.jav b/test/plugindevelopment/ParameterTypeInsertTest.jav new file mode 100644 index 000000000..9a2405af3 --- /dev/null +++ b/test/plugindevelopment/ParameterTypeInsertTest.jav @@ -0,0 +1,7 @@ + +class VariableTypeInsertTest{ + String var; + void methode(test){ + var = test; + } +} diff --git a/test/plugindevelopment/ParameterTypeInsertTestSolution.jav b/test/plugindevelopment/ParameterTypeInsertTestSolution.jav new file mode 100644 index 000000000..4a53daa8f --- /dev/null +++ b/test/plugindevelopment/ParameterTypeInsertTestSolution.jav @@ -0,0 +1,7 @@ + +class VariableTypeInsertTest{ + String var; + void methode(java.lang.String test){ + var = test; + } +} diff --git a/test/plugindevelopment/SingleTypeInsertTest.jav b/test/plugindevelopment/SingleTypeInsertTest.jav new file mode 100644 index 000000000..8039f8972 --- /dev/null +++ b/test/plugindevelopment/SingleTypeInsertTest.jav @@ -0,0 +1,3 @@ +class Test{ +var; +} \ No newline at end of file diff --git a/test/plugindevelopment/SyntaxTreeTests.java b/test/plugindevelopment/SyntaxTreeTests.java new file mode 100644 index 000000000..099661636 --- /dev/null +++ b/test/plugindevelopment/SyntaxTreeTests.java @@ -0,0 +1,7 @@ +package plugindevelopment; + +public class SyntaxTreeTests { + + //TODO: Hier tests für getChildren anfügen. + +} diff --git a/test/plugindevelopment/TypeInsertSetEqualTest.jav b/test/plugindevelopment/TypeInsertSetEqualTest.jav new file mode 100644 index 000000000..b07d5db44 --- /dev/null +++ b/test/plugindevelopment/TypeInsertSetEqualTest.jav @@ -0,0 +1,10 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class ImportTest{ +Menge var; +var2; +methode(){ + var.add(var2); +} + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTester.java b/test/plugindevelopment/TypeInsertTester.java new file mode 100755 index 000000000..6737c6a36 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTester.java @@ -0,0 +1,79 @@ +package plugindevelopment; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; + +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.typeinference.Menge; + +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; +import junit.framework.TestCase; + + +public class TypeInsertTester{ + + //private static Logger inferencelog = Logger.getLogger(TypeInsertTester.class.getName()); + private static LoggerConfiguration logConfig = new LoggerConfiguration(); + static{ + { + logConfig.setOutput(Section.TYPEINFERENCE, System.out); + /* + // Ausgabeoptionen fuer die Logger + ConsoleAppender logAppender = new ConsoleAppender(new SimpleLayout()); + logAppender.setTarget("System.out"); + logAppender.activateOptions(); + inferencelog.addAppender(logAppender); //Bei den Tests wird der Log auch in System.out geschrieben. + */ + } + } + static final String rootDirectory = System.getProperty("user.dir")+"/test/plugindevelopment/"; + + public static void test(String sourceFileToInfere, String solutionFile){ + String inferedSource = ""; + MyCompilerAPI compiler = MyCompiler.getAPI(logConfig); + try { + SourceFile parsed = compiler.parse(new File(rootDirectory + sourceFileToInfere)); + Menge sourceFiles = new Menge<>(); + sourceFiles.add(parsed); + Menge results = compiler.typeReconstruction(sourceFiles); + TestCase.assertTrue("Es darf nicht mehr als eine Lösungsmöglichkeit geben und nicht "+results.size(), results.size()==1); + for(TypeinferenceResultSet result : results){ + TypeInsertSet point = result.getTypeInsertionPoints(); + //TestCase.assertTrue("Es muss mindestens ein TypeInsertSet vorhanden sein", points.size()>0); + if(point.points.size()>0){ + inferedSource = point.insertAllTypes(getFileContent(rootDirectory + sourceFileToInfere)); + String solutionSource = getFileContent(rootDirectory + solutionFile); + System.out.println("\nInferierter Source:\n"+inferedSource); + TestCase.assertTrue("Nicht das erwartete Ergebnis", inferedSource.equals(solutionSource)); + } + } + + } catch (IOException | yyException e) { + e.printStackTrace(); + TestCase.fail(); + } + } + + //Source: https://stackoverflow.com/questions/326390/how-to-create-a-java-string-from-the-contents-of-a-file + //PS: benötigt Java 7 + public static String getFileContent(String path)throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return StandardCharsets.UTF_8.decode(ByteBuffer.wrap(encoded)).toString(); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/.LambdaTest2_3.jav.log.swp b/test/plugindevelopment/TypeInsertTests/.LambdaTest2_3.jav.log.swp new file mode 100644 index 000000000..457a36417 Binary files /dev/null and b/test/plugindevelopment/TypeInsertTests/.LambdaTest2_3.jav.log.swp differ diff --git a/test/plugindevelopment/TypeInsertTests/Add.jav b/test/plugindevelopment/TypeInsertTests/Add.jav new file mode 100644 index 000000000..4e7599b34 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/Add.jav @@ -0,0 +1,8 @@ +import java.util.Vector; + +class Matrix extends Vector> { + + mvmul(Vector v) { + return v.size() + 5; + } +} diff --git a/test/plugindevelopment/TypeInsertTests/Add.java b/test/plugindevelopment/TypeInsertTests/Add.java new file mode 100644 index 000000000..2aaf7b0fe --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/Add.java @@ -0,0 +1,19 @@ +package plugindevelopment.TypeInsertTests; + +import java.util.ArrayList; +import java.util.List; +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class Add { + private static final String TEST_FILE = "Add.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("TestIfStmt var"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + ArrayList l = new ArrayList(); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/Analysis.txt b/test/plugindevelopment/TypeInsertTests/Analysis.txt new file mode 100644 index 000000000..c6c27a756 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/Analysis.txt @@ -0,0 +1,3 @@ +LambdaTest5: +* Zeit ohne Unify-Filterung: 729601 +* Zeit mit Unify-Filterung: 95235 diff --git a/test/plugindevelopment/TypeInsertTests/BoundedGenericTest.jav b/test/plugindevelopment/TypeInsertTests/BoundedGenericTest.jav new file mode 100755 index 000000000..2fbcc715a --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/BoundedGenericTest.jav @@ -0,0 +1,6 @@ +class BoundedGenericTest{ + var = "test"; + methode(){ + return var; + } +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/BoundedGenericsTest.java b/test/plugindevelopment/TypeInsertTests/BoundedGenericsTest.java new file mode 100644 index 000000000..ae1d0f92f --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/BoundedGenericsTest.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class BoundedGenericsTest { + private static final String TEST_FILE = "BoundedGenericTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("java.lang.String var"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/ConstructorTest.jav b/test/plugindevelopment/TypeInsertTests/ConstructorTest.jav new file mode 100644 index 000000000..b92a7a3be --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/ConstructorTest.jav @@ -0,0 +1,9 @@ +import java.util.Vector; + +class Matrix{ + + Matrix(){ + var; + var = "test"; + } +} diff --git a/test/plugindevelopment/TypeInsertTests/ConstructorTest.java b/test/plugindevelopment/TypeInsertTests/ConstructorTest.java new file mode 100644 index 000000000..eb9004fb5 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/ConstructorTest.java @@ -0,0 +1,22 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; + +public class ConstructorTest { + + private static final String TEST_FILE = "ConstructorTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //Logger.setStandardConfiguration(new LoggerConfiguration().setOutput(Section.TYPEINFERENCE, System.out)); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/FunNInsertTest.jav b/test/plugindevelopment/TypeInsertTests/FunNInsertTest.jav new file mode 100644 index 000000000..fe76739d7 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/FunNInsertTest.jav @@ -0,0 +1,15 @@ +class FunNInsertTest{ + + Object1 var1; + Object2 var2; + Object3 var3; + op = (a) -> (b) -> (c) -> { + var1 = a; + var2 = b; + var3 = c; + }; +} + +class Object1{} +class Object2{} +class Object3{} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/FunNInsertTest.java b/test/plugindevelopment/TypeInsertTests/FunNInsertTest.java new file mode 100644 index 000000000..3ea54b4f7 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/FunNInsertTest.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class FunNInsertTest { + + private static final String TEST_FILE = "FunNInsertTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("Fun1, Object2>, Object1> op"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/FunVoid.jav b/test/plugindevelopment/TypeInsertTests/FunVoid.jav new file mode 100644 index 000000000..2503977f2 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/FunVoid.jav @@ -0,0 +1,5 @@ + +class FunTest{ + + funVoid = ()->{}; +} diff --git a/test/plugindevelopment/TypeInsertTests/FunVoid.java b/test/plugindevelopment/TypeInsertTests/FunVoid.java new file mode 100644 index 000000000..017b6b9fd --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/FunVoid.java @@ -0,0 +1,19 @@ +package plugindevelopment.TypeInsertTests; + +import java.util.ArrayList; +import java.util.List; +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class FunVoid { + private static final String TEST_FILE = "FunVoid.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("TestIfStmt var"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + ArrayList l = new ArrayList(); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/GenTypeTest.jav b/test/plugindevelopment/TypeInsertTests/GenTypeTest.jav new file mode 100644 index 000000000..36b7de8d4 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenTypeTest.jav @@ -0,0 +1,4 @@ +class Test{ + A a; + b = a; +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/GenTypeTest.java b/test/plugindevelopment/TypeInsertTests/GenTypeTest.java new file mode 100644 index 000000000..19e75bd73 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenTypeTest.java @@ -0,0 +1,19 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class GenTypeTest { + + private static final String TEST_FILE = "GenTypeTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + + mustContain.add("A b"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/GenericParaListInsertTest.jav b/test/plugindevelopment/TypeInsertTests/GenericParaListInsertTest.jav new file mode 100644 index 000000000..ed362c9d4 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenericParaListInsertTest.jav @@ -0,0 +1,3 @@ +class GenericParaListInsertTest{ + A methode(a){return a;} +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/GenericParaListInsertTest.java b/test/plugindevelopment/TypeInsertTests/GenericParaListInsertTest.java new file mode 100644 index 000000000..c9919058b --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenericParaListInsertTest.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class GenericParaListInsertTest { + private static final String TEST_FILE = "GenericParaListInsertTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("<"); //Es muss eine Parameterliste generiert werden. + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/GenericParaListInsertTest2.jav b/test/plugindevelopment/TypeInsertTests/GenericParaListInsertTest2.jav new file mode 100644 index 000000000..d42042c9d --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenericParaListInsertTest2.jav @@ -0,0 +1,3 @@ +class GenericParaListInsertTest{ + A methode(a){return a;} +} diff --git a/test/plugindevelopment/TypeInsertTests/GenericParaListInsertTest2.java b/test/plugindevelopment/TypeInsertTests/GenericParaListInsertTest2.java new file mode 100644 index 000000000..d428731dc --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenericParaListInsertTest2.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class GenericParaListInsertTest2 { + private static final String TEST_FILE = "GenericParaListInsertTest2.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("<"); //Es muss eine Parameterliste generiert werden. + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/GenericTypeVarTest.jav b/test/plugindevelopment/TypeInsertTests/GenericTypeVarTest.jav new file mode 100644 index 000000000..772f649b2 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenericTypeVarTest.jav @@ -0,0 +1,11 @@ +class GTVTest{ +GTVTest2 var; + +methode(){ + return var.var2; +} +} + +class GTVTest2{ + GTV2 var2; +} diff --git a/test/plugindevelopment/TypeInsertTests/GenericTypeVarTest.java b/test/plugindevelopment/TypeInsertTests/GenericTypeVarTest.java new file mode 100644 index 000000000..626270021 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenericTypeVarTest.java @@ -0,0 +1,23 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; + +public class GenericTypeVarTest { + + private static final String TEST_FILE = "GenericTypeVarTest.jav"; + + @Test + public void run(){ + Logger.setStandardConfiguration(new LoggerConfiguration().setOutput(Section.ASSUMPTIONS, System.out)); + Menge mustContain = new Menge(); + mustContain.add("String methode"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/GenericTypeVarTest2.jav b/test/plugindevelopment/TypeInsertTests/GenericTypeVarTest2.jav new file mode 100644 index 000000000..c1fd0e508 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenericTypeVarTest2.jav @@ -0,0 +1,14 @@ +class GTVTest{ +GTVTest2 var; + +methode(){ + var2; + return var.test(var2); +} +} + +class GTVTest2{ + test(GTV2 param){ + return param; + } +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/GenericTypeVarTest2.java b/test/plugindevelopment/TypeInsertTests/GenericTypeVarTest2.java new file mode 100644 index 000000000..10aad9ab4 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenericTypeVarTest2.java @@ -0,0 +1,29 @@ +package plugindevelopment.TypeInsertTests; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.PrintStream; + +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class GenericTypeVarTest2 { + + private static final String TEST_FILE2 = "GenericTypeVarTest2.jav"; + private static final String LOGFILE = "GenericTypeVarTest2.log"; + + + @Test + public void run2() throws FileNotFoundException{ + Menge mustContain = new Menge(); + mustContain.add("String var2"); + File logFile = new File(MultipleTypesInsertTester.rootDirectory+this.LOGFILE); + LoggerConfiguration lConf = new LoggerConfiguration(); + + lConf.setOutput(Section.TYPEINFERENCE, new PrintStream(logFile)); + MultipleTypesInsertTester.test(TEST_FILE2, mustContain, lConf); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/GenericVarInsertTest.jav b/test/plugindevelopment/TypeInsertTests/GenericVarInsertTest.jav new file mode 100644 index 000000000..3f552dbca --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenericVarInsertTest.jav @@ -0,0 +1,3 @@ +class GenericVarInsertTest{ + op = (m) -> (f) -> f; +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/GenericVarInsertTest.java b/test/plugindevelopment/TypeInsertTests/GenericVarInsertTest.java new file mode 100644 index 000000000..04e2910ab --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenericVarInsertTest.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class GenericVarInsertTest { + private static final String TEST_FILE = "GenericVarInsertTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("Fun1, Object2>, Object1> op"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/GenericVarTest.jav b/test/plugindevelopment/TypeInsertTests/GenericVarTest.jav new file mode 100644 index 000000000..1f3d9f46d --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenericVarTest.jav @@ -0,0 +1,5 @@ +import java.util.Vector; + +class WildcardTest extends Vector{ + Fun1> op = (f) -> f.apply(this); +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/GenericVarTest.java b/test/plugindevelopment/TypeInsertTests/GenericVarTest.java new file mode 100644 index 000000000..576bf0c9d --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenericVarTest.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class GenericVarTest { + private static final String TEST_FILE = "GenericVarTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("Fun1, Object2>, Object1> op"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/GenericVarTest2.jav b/test/plugindevelopment/TypeInsertTests/GenericVarTest2.jav new file mode 100644 index 000000000..2aef0758a --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenericVarTest2.jav @@ -0,0 +1,15 @@ +class GenericTest{ + A method(){ + return null; + } +} + +class GenericTest2{ + + GenericTest var = new GenericTest(); + + method2(){ + return var.method(); + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/GenericVarTest2.java b/test/plugindevelopment/TypeInsertTests/GenericVarTest2.java new file mode 100644 index 000000000..ddf5ee67f --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenericVarTest2.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class GenericVarTest2 { + private static final String TEST_FILE = "GenericVarTest2.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("Fun1, Object2>, Object1> op"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/GenericVarTest3.jav b/test/plugindevelopment/TypeInsertTests/GenericVarTest3.jav new file mode 100755 index 000000000..5d6654be9 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenericVarTest3.jav @@ -0,0 +1,8 @@ +class GenericTest{ + A method(){ + A x; + Integer integer; + integer = x; + return x; + } +} diff --git a/test/plugindevelopment/TypeInsertTests/GenericVarTest3.java b/test/plugindevelopment/TypeInsertTests/GenericVarTest3.java new file mode 100644 index 000000000..e8cbfc1f9 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/GenericVarTest3.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class GenericVarTest3 { + private static final String TEST_FILE = "GenericVarTest3.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("Fun1, Object2>, Object1> op"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/Id.jav b/test/plugindevelopment/TypeInsertTests/Id.jav new file mode 100644 index 000000000..91d9acef8 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/Id.jav @@ -0,0 +1,8 @@ + +class Id { + op = (x) -> x; + +m(){ + op.apply(1); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/Id.java b/test/plugindevelopment/TypeInsertTests/Id.java new file mode 100644 index 000000000..797886be5 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/Id.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class Id { + private static final String TEST_FILE = "Id.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("TestIfStmt var"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/ImportSubClassTest.jav b/test/plugindevelopment/TypeInsertTests/ImportSubClassTest.jav new file mode 100644 index 000000000..92ee5482e --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/ImportSubClassTest.jav @@ -0,0 +1,13 @@ +import java.util.ArrayList; +import java.util.List; +import de.dhbwstuttgart.typeinference.Menge; + +class ImportSubClassTest{ +methode(){ +Menge var1; +ArrayList var2; +var3; +var3 = var1; +var3 = var2; +} +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/ImportSubClassTest.java b/test/plugindevelopment/TypeInsertTests/ImportSubClassTest.java new file mode 100644 index 000000000..f33f31601 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/ImportSubClassTest.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class ImportSubClassTest { + private static final String TEST_FILE = "ImportSubClassTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("TestIfStmt var"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/ImportTest.jav b/test/plugindevelopment/TypeInsertTests/ImportTest.jav new file mode 100755 index 000000000..7e761863c --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/ImportTest.jav @@ -0,0 +1,10 @@ +import java.util.Vector; + +class ImportTest{ +Vector var; + +methode(var2){ + var.add(var2); +} + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/ImportTest.java b/test/plugindevelopment/TypeInsertTests/ImportTest.java new file mode 100644 index 000000000..f7e6ec961 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/ImportTest.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class ImportTest { + + private static final String TEST_FILE = "ImportTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("String var2"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/ImportTest2.jav b/test/plugindevelopment/TypeInsertTests/ImportTest2.jav new file mode 100755 index 000000000..10075ef94 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/ImportTest2.jav @@ -0,0 +1,10 @@ +import java.util.Vector; + +class ImportTest{ + +void methode(a){ + var; + var.add(a); +} + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/ImportTest2.java b/test/plugindevelopment/TypeInsertTests/ImportTest2.java new file mode 100644 index 000000000..be3d09ff7 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/ImportTest2.java @@ -0,0 +1,17 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class ImportTest2 { + + private static final String TEST_FILE = "ImportTest2.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/IntTest.jav b/test/plugindevelopment/TypeInsertTests/IntTest.jav new file mode 100755 index 000000000..7a2471f2d --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/IntTest.jav @@ -0,0 +1,6 @@ +class IntTest{ + int methode(){ + var; + return var; + } +} diff --git a/test/plugindevelopment/TypeInsertTests/IntTest.java b/test/plugindevelopment/TypeInsertTests/IntTest.java new file mode 100644 index 000000000..4a2e2814e --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/IntTest.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class IntTest { + + private static final String TEST_FILE = "IntTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("Integer var"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest1.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest1.jav new file mode 100644 index 000000000..690e6c9a8 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest1.jav @@ -0,0 +1,11 @@ + +class LambdaTest{ + +String var; + +op = () -> (f) -> { + f.apply(this,var); + return var; +}; + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest1.java b/test/plugindevelopment/TypeInsertTests/LambdaTest1.java new file mode 100644 index 000000000..e6d6a5afe --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest1.java @@ -0,0 +1,20 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest1 { + + private static final String TEST_FILE = "LambdaTest1.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + + mustContain.add("Fun0<"); + mustContain.add("java.lang.String>>> op"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest10.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest10.jav new file mode 100755 index 000000000..a056762d8 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest10.jav @@ -0,0 +1,7 @@ +class Test{ + + CT methode(m){ +return m; +} + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest10.java b/test/plugindevelopment/TypeInsertTests/LambdaTest10.java new file mode 100644 index 000000000..c0f17fed6 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest10.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest10 { + + private static final String TEST_FILE = "LambdaTest10.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest11.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest11.jav new file mode 100755 index 000000000..a2cd93578 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest11.jav @@ -0,0 +1,7 @@ +class Test{ + + CT methode(m){ +return m; +} + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest11.java b/test/plugindevelopment/TypeInsertTests/LambdaTest11.java new file mode 100644 index 000000000..99a4e09ad --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest11.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest11 { + private static final String TEST_FILE = "LambdaTest11.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest12.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest12.jav new file mode 100644 index 000000000..923f0a208 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest12.jav @@ -0,0 +1,9 @@ +class Test { + + A m; + +CT methode(){ +return m; +} + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest12.java b/test/plugindevelopment/TypeInsertTests/LambdaTest12.java new file mode 100644 index 000000000..33b04b42a --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest12.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest12 { + private static final String TEST_FILE = "LambdaTest12.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest13.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest13.jav new file mode 100644 index 000000000..e11264c8c --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest13.jav @@ -0,0 +1,5 @@ +class Matrix{ + op(m){ + return (f) -> f.apply(m,this); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest13.java b/test/plugindevelopment/TypeInsertTests/LambdaTest13.java new file mode 100644 index 000000000..44748a7b2 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest13.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest13 { + private static final String TEST_FILE = "LambdaTest13.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest14.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest14.jav new file mode 100644 index 000000000..3e4edfeda --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest14.jav @@ -0,0 +1,5 @@ +class Matrix{ + op(B m){ + return (f) -> f.apply(m,this); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest14.java b/test/plugindevelopment/TypeInsertTests/LambdaTest14.java new file mode 100644 index 000000000..4087a1eea --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest14.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest14 { + private static final String TEST_FILE = "LambdaTest14.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest15.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest15.jav new file mode 100644 index 000000000..ef93085f2 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest15.jav @@ -0,0 +1,7 @@ +class ConstructorTest1{ + +ConstructorTest1(){ +var; +var = 1; +} +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest15.java b/test/plugindevelopment/TypeInsertTests/LambdaTest15.java new file mode 100644 index 000000000..981107a47 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest15.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest15 { + private static final String TEST_FILE = "LambdaTest15.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest16.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest16.jav new file mode 100644 index 000000000..bc58f522c --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest16.jav @@ -0,0 +1,3 @@ +class Matrix2{ + Fun1>, DF> op = (m)->(f)->{return f.apply(this,m);}; + } diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest16.java b/test/plugindevelopment/TypeInsertTests/LambdaTest16.java new file mode 100644 index 000000000..c5ad8ca16 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest16.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest16 { + private static final String TEST_FILE = "LambdaTest16.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest17.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest17.jav new file mode 100644 index 000000000..a211b625d --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest17.jav @@ -0,0 +1,10 @@ +class ConstructorTest1{} + +class ConstructorTest2{ + + void method(){ + var; + var = new ConstructorTest1(); + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest17.java b/test/plugindevelopment/TypeInsertTests/LambdaTest17.java new file mode 100644 index 000000000..2e185fc40 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest17.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest17 { + private static final String TEST_FILE = "LambdaTest17.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest18.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest18.jav new file mode 100644 index 000000000..142aa2918 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest18.jav @@ -0,0 +1,8 @@ + +class Test{ +java.lang.Integer var; +var2 = var; +void methode(){ +var = 1; +} +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest18.java b/test/plugindevelopment/TypeInsertTests/LambdaTest18.java new file mode 100644 index 000000000..26b37ddcc --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest18.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest18 { + private static final String TEST_FILE = "LambdaTest18.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("java.lang.Integer var2"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest19.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest19.jav new file mode 100644 index 000000000..32bf4fced --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest19.jav @@ -0,0 +1,14 @@ + +class TestIfStmt { + +methode(){ + var; + if(true){ + var=this; + }else{ + var=this; + } + return 1; +} + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest19.java b/test/plugindevelopment/TypeInsertTests/LambdaTest19.java new file mode 100644 index 000000000..8cdbe3622 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest19.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest19 { + private static final String TEST_FILE = "LambdaTest19.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("TestIfStmt var"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest2.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest2.jav new file mode 100755 index 000000000..206a10b5c --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest2.jav @@ -0,0 +1,5 @@ +class LambdaTest{ + +Fun1, B>>, B> op = (m) -> (f) -> f.apply(this,m); + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest2.java b/test/plugindevelopment/TypeInsertTests/LambdaTest2.java new file mode 100755 index 000000000..c1c118700 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest2.java @@ -0,0 +1,23 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; + +public class LambdaTest2 { + + private static final String TEST_FILE = "LambdaTest2.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("S m"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain, + new LoggerConfiguration().setOutput(Section.ASSUMPTIONS, System.out)); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest20.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest20.jav new file mode 100644 index 000000000..79053b872 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest20.jav @@ -0,0 +1,11 @@ + +class WhileTest{ + + var; + public method(){ + while(true){ + var = "String"; + } + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest20.java b/test/plugindevelopment/TypeInsertTests/LambdaTest20.java new file mode 100644 index 000000000..afc303613 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest20.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest20 { + private static final String TEST_FILE = "LambdaTest21.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("TestIfStmt var"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest21.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest21.jav new file mode 100644 index 000000000..f510f0be7 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest21.jav @@ -0,0 +1,9 @@ + +class Test{ + +void methode(){ + var; + var.toString(); +} + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest22.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest22.jav new file mode 100644 index 000000000..397e890e2 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest22.jav @@ -0,0 +1,35 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class Matrix extends Menge> { + + Matrix mul(m){ + ret; + ret = new Matrix(); + i; + i = 0; + while(i < this.size()) { + v1; + v2; + v1 = this.elementAt(i); + v2 = new Menge(); + j; + j = 0; + while(j < v1.size()) { + erg; + erg = 0; + k; + k = 0; + while(k < v1.size()) { + erg = erg + v1.elementAt(k).intValue() * m.elementAt(k).elementAt(j).intValue(); + k++; + } + v2.addElement(new Integer(erg)); + j++; + } + ret.addElement(v2); + i++; + } + return ret; + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest23.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest23.jav new file mode 100644 index 000000000..4bc270c4b --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest23.jav @@ -0,0 +1,12 @@ +import java.util.Vector; + +class Matrix extends Vector> { + + void mul(m){ + v1; + v1 = this.elementAt(1); + erg; + erg = v1.elementAt(1); + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest23.java b/test/plugindevelopment/TypeInsertTests/LambdaTest23.java new file mode 100644 index 000000000..03d2d755d --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest23.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest23 { + private static final String TEST_FILE = "LambdaTest23.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("de.dhbwstuttgart.typeinference.Menge v1;"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest24.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest24.jav new file mode 100644 index 000000000..ede3dbe6f --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest24.jav @@ -0,0 +1,10 @@ +class Overloading_in_Method { + + ff (x) { + op; + op = (m) -> (f) -> f.apply(m); + return op; + } + + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest24.java b/test/plugindevelopment/TypeInsertTests/LambdaTest24.java new file mode 100644 index 000000000..d1a2f209a --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest24.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest24 { + private static final String TEST_FILE = "LambdaTest24.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("Fun1"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest25.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest25.jav new file mode 100644 index 000000000..a499b2bdd --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest25.jav @@ -0,0 +1,8 @@ +import java.util.Vector; + +class ImportGeneric { + + m (Vector x) { + return x.elementAt(1); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest25.java b/test/plugindevelopment/TypeInsertTests/LambdaTest25.java new file mode 100644 index 000000000..8dbeb3fb7 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest25.java @@ -0,0 +1,19 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest25 { + private static final String TEST_FILE = "LambdaTest25.jav"; + + @Test + public void run(){ + //de.dhbwstuttgart.logger.Logger.setStandardConfiguration(Logger.getConfiguration().setOutput(Section.TYPEINFERENCE, System.out)); + Menge mustContain = new Menge(); + mustContain.add("Integer m"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest26.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest26.jav new file mode 100644 index 000000000..a59e9ef3c --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest26.jav @@ -0,0 +1,12 @@ +class Test { + + String var; + + A m (A x) { + return x; + } + + m2(){ + return m(var); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest26.java b/test/plugindevelopment/TypeInsertTests/LambdaTest26.java new file mode 100644 index 000000000..fdca0e67f --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest26.java @@ -0,0 +1,25 @@ +package plugindevelopment.TypeInsertTests; + +import java.io.File; +import java.io.IOException; + +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +import com.google.common.io.Files; + +public class LambdaTest26 { + + private static final String TEST_FILE = "LambdaTest26.jav"; + + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest27.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest27.jav new file mode 100644 index 000000000..cf52b258f --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest27.jav @@ -0,0 +1,17 @@ +class Klasse{ +main(String argument){ +var; +var.methode(argument); +return var.methode(argument); +} +} +class Klasse1{ +String methode(String arg){ +return arg; +} +} +class Klasse2{ +Integer methode(Integer arg){ +return arg; +} +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest27.java b/test/plugindevelopment/TypeInsertTests/LambdaTest27.java new file mode 100644 index 000000000..bd8d41ab9 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest27.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest27 { + + private static final String TEST_FILE = "LambdaTest27.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest28.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest28.jav new file mode 100644 index 000000000..c91288ab4 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest28.jav @@ -0,0 +1,11 @@ +class Klasse{ + main(param){ + return param.methode(); + } +} + +class Klasse1{ + A methode(){ + return null; + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest28.java b/test/plugindevelopment/TypeInsertTests/LambdaTest28.java new file mode 100644 index 000000000..ae9353a9a --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest28.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest28 { + + private static final String TEST_FILE = "LambdaTest28.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest29.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest29.jav new file mode 100644 index 000000000..c297d4dff --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest29.jav @@ -0,0 +1,3 @@ +class LambdaTest29{ + lambda = (f)->f.apply(); +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest29.java b/test/plugindevelopment/TypeInsertTests/LambdaTest29.java new file mode 100644 index 000000000..d832d75d4 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest29.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest29 { + + private static final String TEST_FILE = "LambdaTest29.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest2_2.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest2_2.jav new file mode 100644 index 000000000..898bc03d6 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest2_2.jav @@ -0,0 +1,5 @@ +class LambdaTest{ + +op = (m) -> (f) -> f.apply(this,m); + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest2_2.java b/test/plugindevelopment/TypeInsertTests/LambdaTest2_2.java new file mode 100644 index 000000000..b0ae1d8b8 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest2_2.java @@ -0,0 +1,23 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; + +public class LambdaTest2_2 { + + private static final String TEST_FILE = "LambdaTest2_2.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("S m"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain, + new LoggerConfiguration().setOutput(Section.ASSUMPTIONS, System.out)); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest2_3.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest2_3.jav new file mode 100644 index 000000000..fdb3d7b00 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest2_3.jav @@ -0,0 +1,5 @@ +class LambdaTest{ + +op = (m) -> (f) -> {f.apply(this,m); return this;}; + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest2_3.java b/test/plugindevelopment/TypeInsertTests/LambdaTest2_3.java new file mode 100644 index 000000000..e7cfc2ca0 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest2_3.java @@ -0,0 +1,23 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; + +public class LambdaTest2_3 { + + private static final String TEST_FILE = "LambdaTest2_3.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("S m"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain, + new LoggerConfiguration().setOutput(Section.ASSUMPTIONS, System.out)); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest3.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest3.jav new file mode 100644 index 000000000..3500832b9 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest3.jav @@ -0,0 +1,7 @@ +class LambdaTest{ + void methode(){ + var; + Fun0 op; + op = () -> {return var;}; + } +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest3.java b/test/plugindevelopment/TypeInsertTests/LambdaTest3.java new file mode 100644 index 000000000..e48ed6c3a --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest3.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest3 { + + private static final String TEST_FILE = "LambdaTest3.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("String var"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest4.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest4.jav new file mode 100755 index 000000000..681715f96 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest4.jav @@ -0,0 +1,9 @@ +class LambdaTest{ + +Fun1 op = (var) -> { + var2; + var2 = var; + return var; + }; + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest4.java b/test/plugindevelopment/TypeInsertTests/LambdaTest4.java new file mode 100755 index 000000000..55d463674 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest4.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest4 { + + private static final String TEST_FILE = "LambdaTest4.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("String var2;"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest5.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest5.jav new file mode 100755 index 000000000..8baed3b31 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest5.jav @@ -0,0 +1,5 @@ +class LambdaTest{ + +Fun1 op = (var) -> {return var;}; + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest5.java b/test/plugindevelopment/TypeInsertTests/LambdaTest5.java new file mode 100644 index 000000000..1dfcbad3b --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest5.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest5 { + + private static final String TEST_FILE = "LambdaTest5.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A var"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest6.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest6.jav new file mode 100644 index 000000000..ba1d552ab --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest6.jav @@ -0,0 +1,3 @@ +class Matrix{ + op = (m) -> (f) -> f.apply(this, m); +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest6.java b/test/plugindevelopment/TypeInsertTests/LambdaTest6.java new file mode 100644 index 000000000..34b8d322b --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest6.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest6 { + + private static final String TEST_FILE = "LambdaTest6.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A var"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest7.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest7.jav new file mode 100644 index 000000000..760677873 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest7.jav @@ -0,0 +1,3 @@ +class Test7{ + void testMethode(a){} +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest7.java b/test/plugindevelopment/TypeInsertTests/LambdaTest7.java new file mode 100644 index 000000000..ded681d0e --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest7.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest7 { + + private static final String TEST_FILE = "LambdaTest7.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest8.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest8.jav new file mode 100644 index 000000000..0df204987 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest8.jav @@ -0,0 +1,3 @@ +class Plus1 { + op = (x) -> x+1; + } \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest8.java b/test/plugindevelopment/TypeInsertTests/LambdaTest8.java new file mode 100644 index 000000000..db910e573 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest8.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest8 { + + private static final String TEST_FILE = "LambdaTest8.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest9.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest9.jav new file mode 100644 index 000000000..cb1643634 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest9.jav @@ -0,0 +1,6 @@ +class MethodId { + + m (x) { + return x; + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest9.java b/test/plugindevelopment/TypeInsertTests/LambdaTest9.java new file mode 100644 index 000000000..6baa2fa12 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest9.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class LambdaTest9 { + + private static final String TEST_FILE = "LambdaTest9.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LargeSourceCodeTests/LambdaTest22.java b/test/plugindevelopment/TypeInsertTests/LargeSourceCodeTests/LambdaTest22.java new file mode 100755 index 000000000..69b51979f --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LargeSourceCodeTests/LambdaTest22.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests.LargeSourceCodeTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTests.MultipleTypesInsertTester; + +public class LambdaTest22 { + private static final String TEST_FILE = "LambdaTest22.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("Matrix ret"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LargeSourceCodeTests/LambdaTest2_2.java b/test/plugindevelopment/TypeInsertTests/LargeSourceCodeTests/LambdaTest2_2.java new file mode 100644 index 000000000..662846f19 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LargeSourceCodeTests/LambdaTest2_2.java @@ -0,0 +1,26 @@ +package plugindevelopment.TypeInsertTests.LargeSourceCodeTests; + +import de.dhbwstuttgart.typeinference.Menge; +import plugindevelopment.TypeInsertTests.MultipleTypesInsertTester; + +import org.junit.Test; + +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; + +public class LambdaTest2_2 { + + private static final String TEST_FILE = "LambdaTest2_2.jav"; + + @Test + public void run(){ + //Logger.getConfiguration().setOutput(Section.ASSUMPTIONS, System.out); + LoggerConfiguration logConfig = new LoggerConfiguration(); + logConfig.setOutput(Section.ASSUMPTIONS, System.out); + Menge mustContain = new Menge(); + //mustContain.add("S m"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain, logConfig); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LargeSourceCodeTests/Matrix.java b/test/plugindevelopment/TypeInsertTests/LargeSourceCodeTests/Matrix.java new file mode 100755 index 000000000..8db48ec7a --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LargeSourceCodeTests/Matrix.java @@ -0,0 +1,21 @@ +package plugindevelopment.TypeInsertTests.LargeSourceCodeTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTests.MultipleTypesInsertTester; +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; + +public class Matrix { + private static final String TEST_FILE = "Matrix.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("TestIfStmt var"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LargeSourceCodeTests/TypedMatrixSimpleTest.java b/test/plugindevelopment/TypeInsertTests/LargeSourceCodeTests/TypedMatrixSimpleTest.java new file mode 100755 index 000000000..5eeb7887e --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LargeSourceCodeTests/TypedMatrixSimpleTest.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests.LargeSourceCodeTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTests.MultipleTypesInsertTester; + +public class TypedMatrixSimpleTest { + private static final String TEST_FILE = "TypedMatrixSimpleTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("Integer i;"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LargeSourceCodeTests/TypedMatrixTest.java b/test/plugindevelopment/TypeInsertTests/LargeSourceCodeTests/TypedMatrixTest.java new file mode 100755 index 000000000..e6ea571ea --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LargeSourceCodeTests/TypedMatrixTest.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests.LargeSourceCodeTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +import plugindevelopment.TypeInsertTests.MultipleTypesInsertTester; + +public class TypedMatrixTest { + private static final String TEST_FILE = "TypedMatrixTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("Integer erg;"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/Matrix.jav b/test/plugindevelopment/TypeInsertTests/Matrix.jav new file mode 100644 index 000000000..b71f5c1fa --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/Matrix.jav @@ -0,0 +1,35 @@ +import java.util.Vector; + +class Matrix extends Vector> { + + mul(m){ + ret; + ret = new Matrix(); + i; + i = 0; + while(true) { + v1; + v2; + v1 = this.elementAt(i); + v2 = new Menge(); + j; + j = 0; + while(true) { + erg; + erg = 0; + k; + k = 0; + while(true) { + erg = erg + v1.elementAt(k).intValue() * m.elementAt(k).elementAt(j).intValue(); + k++; + } + v2.addElement(new Integer(erg)); + j++; + } + ret.addElement(v2); + i++; + } + return ret; + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/Matrix_simple.jav b/test/plugindevelopment/TypeInsertTests/Matrix_simple.jav new file mode 100644 index 000000000..5aa6ee451 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/Matrix_simple.jav @@ -0,0 +1,14 @@ +import java.util.Vector; + +class Matrix extends Vector> { + + mvmul(Vector v) { + i; + ele; + v.add(1); + while (i < v.size()) { + + ele = 5 + v.elementAt(i); + } + } +} diff --git a/test/plugindevelopment/TypeInsertTests/Matrix_simple.java b/test/plugindevelopment/TypeInsertTests/Matrix_simple.java new file mode 100644 index 000000000..94d6019cc --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/Matrix_simple.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class Matrix_simple { + private static final String TEST_FILE = "Matrix_simple.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("TestIfStmt var"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/MultipleTypesInsertTester.java b/test/plugindevelopment/TypeInsertTests/MultipleTypesInsertTester.java new file mode 100755 index 000000000..77e1c27bf --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/MultipleTypesInsertTester.java @@ -0,0 +1,125 @@ +package plugindevelopment.TypeInsertTests; + +import java.io.File; +import java.io.IOException; + +import com.google.common.io.Files; + +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.logger.SectionLogger; +import de.dhbwstuttgart.logger.Timewatch; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; +import plugindevelopment.TypeInsertTester; +import junit.framework.TestCase; + +public class MultipleTypesInsertTester extends TypeInsertTester{ + + public final static String rootDirectory = System.getProperty("user.dir")+"/test/plugindevelopment/TypeInsertTests/"; + + static LoggerConfiguration logConfig = new LoggerConfiguration(); + static{ + logConfig.setOutput(Section.TYPEINFERENCE, System.out); + } + + public MultipleTypesInsertTester(){ + //Output von TYPEINFERENCE auf die Console setzen: + //Logger.getConfiguration().setOutput(Section.TYPEINFERENCE, System.out); + } + + public static void test(String sourceFileToInfere, Menge mustContain, LoggerConfiguration additionalConfig){ + logConfig.mergeConfiguration(additionalConfig); + MultipleTypesInsertTester.test(sourceFileToInfere, mustContain); + } + + public static void test(String sourceFileToInfere, Menge mustContain){ + String gesamterSrc = ""; + String inferedSource = ""; + SectionLogger log = Logger.getSectionLogger(MultipleTypesInsertTester.class.getName(), Section.TYPEINFERENCE); + + MyCompilerAPI compiler = MyCompiler.getAPI(logConfig); + try { + SourceFile parsedFile = compiler.parse(new File(rootDirectory + sourceFileToInfere)); + Menge parsedFiles = new Menge<>(); + parsedFiles.add(parsedFile); + Menge results = compiler.typeReconstruction(parsedFiles); + System.out.println("Typinferenz ausgeführt!"); + //TestCase.assertTrue("Es darf nicht mehr als eine Lösungsmöglichkeit geben und nicht "+results.size(), results.size()==1); + for(TypeinferenceResultSet result : results){ + TypeInsertSet point = result.getTypeInsertionPoints(); + //TestCase.assertTrue("Es muss mindestens ein TypeInsertSet vorhanden sein", points.size()>0); + + //TestCase.assertTrue("Es muss mindestens ein TypeInsertPoint vorhanden sein", point.points.size()>0); + if(point.points.size()>0){ + inferedSource = point.insertAllTypes(TypeInsertTester.getFileContent(rootDirectory + sourceFileToInfere)); + log.debug(inferedSource); + gesamterSrc += inferedSource; + } + + } + + } catch (IOException | yyException e) { + e.printStackTrace(); + TestCase.fail(); + }finally{ + writeLog(sourceFileToInfere+".log"); + } + for(String containString : mustContain){ + TestCase.assertTrue("\""+containString+"\" muss in den inferierten Lösungen vorkommen",gesamterSrc.contains(containString)); + } + } + + public static void testSingleInsert(String sourceFileToInfere, Menge mustContain){ + String gesamterSrc = ""; + String inferedSource = ""; + MyCompilerAPI compiler = MyCompiler.getAPI(logConfig); + try { + Menge parsedSource = new Menge<>(); + parsedSource.add(compiler.parse(new File(rootDirectory + sourceFileToInfere))); + Menge results = compiler.typeReconstruction(parsedSource); + //TestCase.assertTrue("Es darf nicht mehr als eine Lösungsmöglichkeit geben und nicht "+results.size(), results.size()==1); + for(TypeinferenceResultSet result : results){ + TypeInsertSet point = result.getTypeInsertionPoints(); + //TestCase.assertTrue("Es muss mindestens ein TypeInsertSet vorhanden sein", points.size()>0); + + //TestCase.assertTrue("Es muss mindestens ein TypeInsertPoint vorhanden sein", point.points.size()>0); + if(point.points.size()>0){ + for(TypeInsertPoint tip : point.points){ + System.out.println("Setze " + tip + " ein:"); + inferedSource = point.insertType(tip, TypeInsertTester.getFileContent(rootDirectory + sourceFileToInfere)); + System.out.println(inferedSource); + gesamterSrc += inferedSource; + } + } + } + } catch (IOException | yyException e) { + e.printStackTrace(); + TestCase.fail(); + }finally{ + writeLog(sourceFileToInfere+".log"); + } + for(String containString : mustContain){ + TestCase.assertTrue("\""+containString+"\" muss in den inferierten Lösungen vorkommen",gesamterSrc.contains(containString)); + } + + } + + private static void writeLog(String toFile){ + String log = Logger.getWholeLog()+"\n"; + log+=Timewatch.getTimewatch().dumpTimeData(); + try { + Files.write(log.getBytes(),new File(rootDirectory+toFile)); + } catch (IOException e) { + e.printStackTrace(); + TestCase.fail(); + } + } +} diff --git a/test/plugindevelopment/TypeInsertTests/MutlitpleTestCases.java b/test/plugindevelopment/TypeInsertTests/MutlitpleTestCases.java new file mode 100644 index 000000000..5c26ee994 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/MutlitpleTestCases.java @@ -0,0 +1,26 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class MutlitpleTestCases { + + private static final String TEST_FILE = "Test1.jav"; + private static final String TEST_FILE2 = "Test2.jav"; + + + @Test + public void test1(){ + Menge mustContain = new Menge(); + mustContain.add("OverloadingTest testMethode"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + + @Test + public void test2(){ + Menge mustContain = new Menge(); + MultipleTypesInsertTester.test(this.TEST_FILE2, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/OL.jav b/test/plugindevelopment/TypeInsertTests/OL.jav new file mode 100755 index 000000000..66e95aeb3 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OL.jav @@ -0,0 +1,16 @@ +class OL { + + Integer m(Integer x) { return x + x; } + + Boolean m(Boolean x) {return x || x; } +} + +class Main { + + main(x) { + ol; + ol = new OL(); + return ol.m(x); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/OL.java b/test/plugindevelopment/TypeInsertTests/OL.java new file mode 100644 index 000000000..40b857471 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OL.java @@ -0,0 +1,17 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class OL { + private static final String TEST_FILE = "OL.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("Integer main"); + mustContain.add("Boolean main"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/OperatorTest.jav b/test/plugindevelopment/TypeInsertTests/OperatorTest.jav new file mode 100644 index 000000000..1f97f6dab --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OperatorTest.jav @@ -0,0 +1,5 @@ +class RelOpTest{ + i = 1 + 1; + j = 1 * 1; + k = 1 / 0; +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/OperatorTest.java b/test/plugindevelopment/TypeInsertTests/OperatorTest.java new file mode 100644 index 000000000..6437c66f5 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OperatorTest.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class OperatorTest { + private static final String TEST_FILE = "OperatorTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("Integer i"); + mustContain.add("Integer j"); + mustContain.add("Integer k"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/OverloadingExample.jav b/test/plugindevelopment/TypeInsertTests/OverloadingExample.jav new file mode 100644 index 000000000..5ac198d8b --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OverloadingExample.jav @@ -0,0 +1,13 @@ +class Example { + test(){ + variable1; + variable2; + variable1 = this; + variable2 = variable1.intValue(); + return variable1.intValue(); + } + + int intValue(){ + return 1; + } +} diff --git a/test/plugindevelopment/TypeInsertTests/OverloadingExample.java b/test/plugindevelopment/TypeInsertTests/OverloadingExample.java new file mode 100644 index 000000000..27a6c6287 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OverloadingExample.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class OverloadingExample { + private static final String TEST_FILE = "OverloadingExample.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("Example variable"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/OverloadingInMethod.jav b/test/plugindevelopment/TypeInsertTests/OverloadingInMethod.jav new file mode 100644 index 000000000..fb1da409b --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OverloadingInMethod.jav @@ -0,0 +1,9 @@ +class OverloadingInMethod{ + + m () { + op; + op = (m) -> (f) -> f.apply(m); + return op; + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/OverloadingInMethod.java b/test/plugindevelopment/TypeInsertTests/OverloadingInMethod.java new file mode 100644 index 000000000..e243cc1db --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OverloadingInMethod.java @@ -0,0 +1,19 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class OverloadingInMethod { + + private static final String TEST_FILE = "OverloadingInMethod.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + + //mustContain.add("Fun0>> op"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/OverloadingInMethod2.jav b/test/plugindevelopment/TypeInsertTests/OverloadingInMethod2.jav new file mode 100755 index 000000000..4dc931782 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OverloadingInMethod2.jav @@ -0,0 +1,10 @@ + +class OverloadingInMethod2{ + + Fun1>, ? super C> m () { + Fun1>, ? super C> op; + op = (m) -> (f) -> f.apply(m); + return op; + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/OverloadingInMethod2.java b/test/plugindevelopment/TypeInsertTests/OverloadingInMethod2.java new file mode 100644 index 000000000..dc911c2b1 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OverloadingInMethod2.java @@ -0,0 +1,21 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class OverloadingInMethod2 { + + private static final String TEST_FILE = "OverloadingInMethod2.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + + //mustContain.add("Fun0>> op"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain, new LoggerConfiguration().setOutput(Section.UNIFY, System.out)); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/OverloadingInMethod2Simple.jav b/test/plugindevelopment/TypeInsertTests/OverloadingInMethod2Simple.jav new file mode 100755 index 000000000..36ec2c052 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OverloadingInMethod2Simple.jav @@ -0,0 +1,10 @@ +class OverloadingInMethod2{ + + + Integer m () { + Fun1 op; + op = (m) -> (f) -> f.apply(m); + return 1; + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/OverloadingInMethod2Simple.java b/test/plugindevelopment/TypeInsertTests/OverloadingInMethod2Simple.java new file mode 100755 index 000000000..5472ee824 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OverloadingInMethod2Simple.java @@ -0,0 +1,19 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class OverloadingInMethod2Simple { + + private static final String TEST_FILE = "OverloadingInMethod2Simple.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + + //mustContain.add("Fun0>> op"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/OverloadingInsertTest.jav b/test/plugindevelopment/TypeInsertTests/OverloadingInsertTest.jav new file mode 100755 index 000000000..aa0aaf421 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OverloadingInsertTest.jav @@ -0,0 +1,17 @@ +class OverloadingInsertTest{ + + overload(){ + return this; + } +} + +class Overloading2{ + + methode(var2){ + return var2.overload(); + } + + overload(){ + return this; + } +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/OverloadingInsertTest.java b/test/plugindevelopment/TypeInsertTests/OverloadingInsertTest.java new file mode 100644 index 000000000..843284b42 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OverloadingInsertTest.java @@ -0,0 +1,33 @@ +package plugindevelopment.TypeInsertTests; + +import java.io.File; +import java.io.IOException; +import de.dhbwstuttgart.typeinference.Menge; + +import junit.framework.TestCase; + +import org.junit.Test; + +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; +import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; + +public class OverloadingInsertTest { + private static final String TEST_FILE = "OverloadingInsertTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("Overloading2 methode"); + mustContain.add("Overloading2 overload"); + mustContain.add("Overloading2 var2"); + mustContain.add("OverloadingInsertTest methode"); + mustContain.add("OverloadingInsertTest overload"); + mustContain.add("OverloadingInsertTest var2"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + + +} diff --git a/test/plugindevelopment/TypeInsertTests/OverloadingRecursive.jav b/test/plugindevelopment/TypeInsertTests/OverloadingRecursive.jav new file mode 100644 index 000000000..70829c746 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OverloadingRecursive.jav @@ -0,0 +1,8 @@ +class OverloadingRecursive{ + + + m (f) { + f.apply(f); + } +} + diff --git a/test/plugindevelopment/TypeInsertTests/OverloadingRecursive.java b/test/plugindevelopment/TypeInsertTests/OverloadingRecursive.java new file mode 100644 index 000000000..0236a37f9 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OverloadingRecursive.java @@ -0,0 +1,19 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class OverloadingRecursive { + + private static final String TEST_FILE = "OverloadingRecursive.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + + //mustContain.add("Fun0>> op"); + //Untypisierbar + //MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/OverloadingVector.jav b/test/plugindevelopment/TypeInsertTests/OverloadingVector.jav new file mode 100755 index 000000000..e3146d36a --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OverloadingVector.jav @@ -0,0 +1,21 @@ +import java.util.Vector; + +class OverloadingVector{ + + void method(Vector v) { + + } + + void method(Vector v) { + + } + + main(String args) { + ol; + ol = new OverloadingVector(); + v; + v = new Vector (); + ol.method(v); + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/OverloadingVectorTest.java b/test/plugindevelopment/TypeInsertTests/OverloadingVectorTest.java new file mode 100644 index 000000000..c96b852ac --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/OverloadingVectorTest.java @@ -0,0 +1,15 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class OverloadingVectorTest { + private static final String TEST_FILE = "OverloadingVector.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/Recursive.jav b/test/plugindevelopment/TypeInsertTests/Recursive.jav new file mode 100644 index 000000000..0f689a498 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/Recursive.jav @@ -0,0 +1,13 @@ +class Recursive{ + +var = "test"; + +methode1(a){ + return methode2(a); +} + +String methode2(b){ + return methode1(var); +} + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/Recursive2.jav b/test/plugindevelopment/TypeInsertTests/Recursive2.jav new file mode 100644 index 000000000..7585b500e --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/Recursive2.jav @@ -0,0 +1,15 @@ +class Recursive{ + +Test var; + +Test methode1(a){ + return methode2(a); +} + +Test methode2(b){ + return methode1(var); +} + +} + +class Test{} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/RelOpTest.jav b/test/plugindevelopment/TypeInsertTests/RelOpTest.jav new file mode 100644 index 000000000..a481747d5 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/RelOpTest.jav @@ -0,0 +1,3 @@ +class RelOpTest{ + i = 1 < 1; +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/RelOpTest.java b/test/plugindevelopment/TypeInsertTests/RelOpTest.java new file mode 100644 index 000000000..ed068679d --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/RelOpTest.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class RelOpTest { + private static final String TEST_FILE = "RelOpTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + mustContain.add("Boolean i"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/ReursiveTest.java b/test/plugindevelopment/TypeInsertTests/ReursiveTest.java new file mode 100644 index 000000000..4af879a05 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/ReursiveTest.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class ReursiveTest { + + private static final String TEST_FILE = "Recursive.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/ReursiveTest2.java b/test/plugindevelopment/TypeInsertTests/ReursiveTest2.java new file mode 100644 index 000000000..a68e19fc4 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/ReursiveTest2.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class ReursiveTest2 { + + private static final String TEST_FILE = "Recursive2.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("A a"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/SuperTest.jav b/test/plugindevelopment/TypeInsertTests/SuperTest.jav new file mode 100644 index 000000000..96fd427ec --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/SuperTest.jav @@ -0,0 +1,12 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class Klasse1{ + Klasse1(var){} +} + +class Klass2 extends Klasse1{ + + Klass2(){ + super(this); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/SuperTest.java b/test/plugindevelopment/TypeInsertTests/SuperTest.java new file mode 100644 index 000000000..025ef614a --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/SuperTest.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class SuperTest { + + private static final String TEST_FILE = "SuperTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/Test1.jav b/test/plugindevelopment/TypeInsertTests/Test1.jav new file mode 100644 index 000000000..4f7f56612 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/Test1.jav @@ -0,0 +1,25 @@ +class OverloadingTest{ + + OverloadingTest var; + + + clone(){ + return this; + } + + testMethode(var2){ + var.clone(); + return var.clone(); + } + +} + +class OverloadingTest2{ + + String var = "test"; + + OverloadingTest2 clone(){ + return this; + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/Test2.jav b/test/plugindevelopment/TypeInsertTests/Test2.jav new file mode 100644 index 000000000..4114c341f --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/Test2.jav @@ -0,0 +1,4 @@ + +public class Matrix{ + op = (m) -> (f) -> f.apply(this, m); +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/ThisTest.jav b/test/plugindevelopment/TypeInsertTests/ThisTest.jav new file mode 100644 index 000000000..89383e3d1 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/ThisTest.jav @@ -0,0 +1,12 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class Matrix{ + + Matrix(){ + this("test"); + } + + Matrix(var){ + + } +} diff --git a/test/plugindevelopment/TypeInsertTests/ThisTest.java b/test/plugindevelopment/TypeInsertTests/ThisTest.java new file mode 100644 index 000000000..5a64a0698 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/ThisTest.java @@ -0,0 +1,20 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class ThisTest { + + private static final String TEST_FILE = "ThisTest.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain, new LoggerConfiguration().setOutput(Section.UNIFY, System.out)); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/TypedMatrixSimpleTest.jav b/test/plugindevelopment/TypeInsertTests/TypedMatrixSimpleTest.jav new file mode 100644 index 000000000..62e2994f3 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/TypedMatrixSimpleTest.jav @@ -0,0 +1,24 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class Matrix extends Menge> { + + Matrix mul(Matrix m){ + Matrix ret; + ret = new Matrix(); + i; + i = 0; + while(i < this.size()) { + Menge v1; + Menge v2; + v1 = this.elementAt(i); + v2 = new Menge(); + Integer j; + j = 0; + + ret.addElement(v2); + i++; + } + return ret; + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/TypedMatrixTest.jav b/test/plugindevelopment/TypeInsertTests/TypedMatrixTest.jav new file mode 100644 index 000000000..a660b2e4a --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/TypedMatrixTest.jav @@ -0,0 +1,35 @@ +import de.dhbwstuttgart.typeinference.Menge; + +class Matrix extends Menge> { + + Matrix mul(Matrix m){ + Matrix ret; + ret = new Matrix(); + Integer i; + i = 0; + while(i < this.size()) { + Menge v1; + Menge v2; + v1 = this.elementAt(i); + v2 = new Menge(); + Integer j; + j = 0; + while(j < this.size()) { + Integer erg; + erg = 0; + Integer k; + k = 0; + while(k < v1.size()) { + erg = erg + v1.elementAt(k).intValue() * m.elementAt(k).elementAt(j).intValue(); + k++; + } + v2.addElement(new Integer(erg)); + j++; + } + ret.addElement(v2); + i++; + } + return ret; + } + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/UnifyPaper.jav b/test/plugindevelopment/TypeInsertTests/UnifyPaper.jav new file mode 100644 index 000000000..023053777 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/UnifyPaper.jav @@ -0,0 +1,13 @@ + + +class Klasse1 { + void methode(){ + var; + var = this; + var = new Klasse2(); + } +} + +class Klasse2 extends Klasse1{ + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/UnifyPaper.java b/test/plugindevelopment/TypeInsertTests/UnifyPaper.java new file mode 100644 index 000000000..9f963c5f1 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/UnifyPaper.java @@ -0,0 +1,19 @@ +package plugindevelopment.TypeInsertTests; + +import java.util.ArrayList; +import java.util.List; +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class UnifyPaper { + private static final String TEST_FILE = "UnifyPaper.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("TestIfStmt var"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + ArrayList l = new ArrayList(); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/UnifyPaper2.jav b/test/plugindevelopment/TypeInsertTests/UnifyPaper2.jav new file mode 100644 index 000000000..ced65a23d --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/UnifyPaper2.jav @@ -0,0 +1,13 @@ +import java.util.Vector; + +class Klasse1 { + void methode(){ + var; + var = new Vector(); + var = new Vector(); + } +} + +class Klasse2 extends Klasse1{ + +} diff --git a/test/plugindevelopment/TypeInsertTests/UnifyPaper2.java b/test/plugindevelopment/TypeInsertTests/UnifyPaper2.java new file mode 100644 index 000000000..0c1f13381 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/UnifyPaper2.java @@ -0,0 +1,19 @@ +package plugindevelopment.TypeInsertTests; + +import java.util.ArrayList; +import java.util.List; +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class UnifyPaper2 { + private static final String TEST_FILE = "UnifyPaper2.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + //mustContain.add("TestIfStmt var"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + ArrayList l = new ArrayList(); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/WildcardTestForLambda.jav b/test/plugindevelopment/TypeInsertTests/WildcardTestForLambda.jav new file mode 100644 index 000000000..c5e8292d8 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/WildcardTestForLambda.jav @@ -0,0 +1,7 @@ +class LambdaTest{ + +methode(){ + return (Integer i)-> i; +} + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/WildcardTestForLambda.java b/test/plugindevelopment/TypeInsertTests/WildcardTestForLambda.java new file mode 100644 index 000000000..ed056925e --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/WildcardTestForLambda.java @@ -0,0 +1,19 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class WildcardTestForLambda { + + private static final String TEST_FILE = "WildcardTestForLambda.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + + //mustContain.add("Fun0>> op"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/WildcardTestForLambda2.jav b/test/plugindevelopment/TypeInsertTests/WildcardTestForLambda2.jav new file mode 100644 index 000000000..adae1646d --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/WildcardTestForLambda2.jav @@ -0,0 +1,5 @@ +class LambdaTest{ + +op = (f) -> f.apply(this); + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/WildcardTestForLambda2.java b/test/plugindevelopment/TypeInsertTests/WildcardTestForLambda2.java new file mode 100644 index 000000000..78028983a --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/WildcardTestForLambda2.java @@ -0,0 +1,19 @@ +package plugindevelopment.TypeInsertTests; + +import de.dhbwstuttgart.typeinference.Menge; + +import org.junit.Test; + +public class WildcardTestForLambda2 { + + private static final String TEST_FILE = "WildcardTestForLambda2.jav"; + + @Test + public void run(){ + Menge mustContain = new Menge(); + + //mustContain.add("Fun0>> op"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/VariableTypeInsertTest.jav b/test/plugindevelopment/VariableTypeInsertTest.jav new file mode 100644 index 000000000..228c7fc12 --- /dev/null +++ b/test/plugindevelopment/VariableTypeInsertTest.jav @@ -0,0 +1,4 @@ + +class VariableTypeInsertTest{ + var = "test"; +} diff --git a/test/plugindevelopment/VariableTypeInsertTest.java b/test/plugindevelopment/VariableTypeInsertTest.java new file mode 100644 index 000000000..f59bcf2ee --- /dev/null +++ b/test/plugindevelopment/VariableTypeInsertTest.java @@ -0,0 +1,15 @@ +package plugindevelopment; + +import org.junit.Test; + +public class VariableTypeInsertTest { + + private static final String TEST_FILE = "VariableTypeInsertTest.jav"; + private static final String SOLUTION_FILE = "VariableTypeInsertTestSolution.jav"; + + @Test + public void run(){ + TypeInsertTester.test(this.TEST_FILE, this.SOLUTION_FILE); + } + +} diff --git a/test/plugindevelopment/VariableTypeInsertTestSolution.jav b/test/plugindevelopment/VariableTypeInsertTestSolution.jav new file mode 100644 index 000000000..626e53454 --- /dev/null +++ b/test/plugindevelopment/VariableTypeInsertTestSolution.jav @@ -0,0 +1,4 @@ + +class VariableTypeInsertTest{ + String var = "test"; +} diff --git a/test/syntaxTree/NodeEqualTest.jav b/test/syntaxTree/NodeEqualTest.jav new file mode 100644 index 000000000..15cbdba50 --- /dev/null +++ b/test/syntaxTree/NodeEqualTest.jav @@ -0,0 +1,9 @@ +class NodeEqualTest { + String var1; + void methode1(){ + var1 = "String"; + } + String methode2(String test){ + return test; + } +} \ No newline at end of file diff --git a/test/syntaxTree/NodeEqualTest.java b/test/syntaxTree/NodeEqualTest.java new file mode 100644 index 000000000..1082379de --- /dev/null +++ b/test/syntaxTree/NodeEqualTest.java @@ -0,0 +1,59 @@ +package syntaxTree; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; + +import org.junit.Test; + +import de.dhbwstuttgart.core.MyCompiler; +import de.dhbwstuttgart.core.MyCompilerAPI; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; +import de.dhbwstuttgart.parser.JavaParser.yyException; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import junit.framework.TestCase; + +public class NodeEqualTest extends TestCase{ + private static final String rootDirectory = System.getProperty("user.dir")+"/test/syntaxTree/"; + private static final String testFile = "NodeEqualTest.jav"; + + @Test + public void test(){ + LoggerConfiguration logConfig = new LoggerConfiguration(); + logConfig.setOutput(Section.TYPEINFERENCE, System.out); + MyCompilerAPI compiler = MyCompiler.getAPI(logConfig); + MyCompilerAPI compiler2 = MyCompiler.getAPI(logConfig); + SourceFile tree = null; + SourceFile tree2 = null; + try { + tree = compiler.parse(new File(rootDirectory + testFile)); + tree2 = compiler2.parse(new File(rootDirectory + testFile)); + } catch (IOException | yyException e) { + e.printStackTrace(); + fail(); + } + recursivlyCheckEqual(tree, tree2); + } + + private void recursivlyCheckEqual(SyntaxTreeNode node1, SyntaxTreeNode node2){ + for(SyntaxTreeNode n1 : node1.getChildren()){ + int matches = 0; + for(SyntaxTreeNode n2 : node2.getChildren()){ + if(n2.equals(n1)){ + System.out.println(n2 + " == "+n1); + matches++; + this.recursivlyCheckEqual(n1, n2); + }else{ + System.out.println(n2 + " != "+ n1); + } + } + System.out.println(""); + assertTrue("Nur eines der Children darf gleich sein, nicht "+matches, matches == 1 && node2.getChildren().size()>0); + } + } + + + +} diff --git a/test/unify/FiniteClosureBuilder.java b/test/unify/FiniteClosureBuilder.java new file mode 100644 index 000000000..8b8b5f733 --- /dev/null +++ b/test/unify/FiniteClosureBuilder.java @@ -0,0 +1,83 @@ +package unify; + +import java.util.HashSet; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; + +public class FiniteClosureBuilder { + + private Set pairs = new HashSet<>(); + + public void add(UnifyType sub, UnifyType sup) { + pairs.add(new UnifyPair(sub, sup, PairOperator.SMALLER)); + } + + public IFiniteClosure getFiniteClosure() { + return new FiniteClosure(pairs); + } + + public void clear() { + pairs = new HashSet<>(); + } + + public IFiniteClosure getCollectionExample() { + TypeFactory tf = new TypeFactory(); + + /* Collection */ + + UnifyType collection = tf.getSimpleType("Collection"); + UnifyType set = tf.getSimpleType("Set", "T"); + //Type sortedSet = tf.getSimpleType("SortedSet", "T"); Sorted set bei den Unit-Tests vergessen + // nachträgliches einfügen zu aufwendig + UnifyType TreeSet = tf.getSimpleType("TreeSet", "T"); + UnifyType hashSet = tf.getSimpleType("HashSet", "T"); + UnifyType linkedHashSet = tf.getSimpleType("LinkedHashSet", "T"); + UnifyType queue = tf.getSimpleType("Queue", "T"); + UnifyType deque = tf.getSimpleType("Deque", "T"); + UnifyType linkedList = tf.getSimpleType("LinkedList", "T"); + UnifyType list = tf.getSimpleType("List", "T"); + UnifyType vector = tf.getSimpleType("Vector", "T"); + UnifyType stack = tf.getSimpleType("Stack", "T"); + UnifyType arrayList = tf.getSimpleType("ArrayList", "T"); + + add(set, collection); + //add(sortedSet, set); + add(TreeSet, set); + add(hashSet, set); + add(linkedHashSet, set); + + add(queue, collection); + add(deque, queue); + add(linkedList, deque); + add(list, collection); + add(linkedList, list); + add(vector, list); + add(arrayList, list); + add(stack, vector); + + /* Map */ + UnifyType map = tf.getSimpleType("Map", "K", "V"); + UnifyType sortedMap = tf.getSimpleType("SortedMap", "K", "V"); + UnifyType navigableMap = tf.getSimpleType("NavigableMap", "K", "V"); + UnifyType treeMap = tf.getSimpleType("TreeMap", "K", "V"); + UnifyType hashMap = tf.getSimpleType("HashMap", "K", "V"); + UnifyType hashtable = tf.getSimpleType("Hashtable", "K", "V"); + UnifyType linkedHashMap = tf.getSimpleType("LinkedHashMap", "K", "V"); + + add(sortedMap, map); + add(hashMap, map); + add(hashtable, map); + add(navigableMap, sortedMap); + add(treeMap, navigableMap); + add(linkedHashMap, hashMap); + + IFiniteClosure fc = getFiniteClosure(); + clear(); + return fc; + } +} diff --git a/test/unify/FiniteClosureTest.java b/test/unify/FiniteClosureTest.java new file mode 100644 index 000000000..b58b92987 --- /dev/null +++ b/test/unify/FiniteClosureTest.java @@ -0,0 +1,692 @@ +package unify; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +import org.junit.Assert; +import org.junit.Test; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; + +public class FiniteClosureTest { + + @Test + public void testSmaller() { + TypeFactory tf = new TypeFactory(); + + UnifyType integer = tf.getSimpleType("Integer"); + UnifyType number = tf.getSimpleType("Number"); + + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + fcb.add(integer, number); + fcb.add(tf.getSimpleType("MyMap", "T"), tf.getSimpleType("HashMap", tf.getSimpleType("Integer"))); + fcb.add(tf.getSimpleType("HashMap", "T"), tf.getSimpleType("Collection")); + IFiniteClosure fc = fcb.getCollectionExample(); + + /* + * Test Case 1: + * + * smaller(Set) = { HashSet, Set, LinkedHashSet } + */ + + UnifyType setInt = tf.getSimpleType("Set", integer); + UnifyType hashSetInt = tf.getSimpleType("HashSet", integer); + UnifyType treeSetInt = tf.getSimpleType("TreeSet", integer); + UnifyType linkedHashSetInt = tf.getSimpleType("LinkedHashSet", integer); + + Set expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + setInt, hashSetInt, linkedHashSetInt, treeSetInt, + }).collect(Collectors.toSet())); + + Assert.assertEquals(expectedResult, fc.smaller(setInt)); + + /* + * Test Case 2: + * + * smaller(Set) = + * { HashSet, Set, TreeSet, LinkedHashSet, + * HashSet, Set, TreeSet, LinkedHashSet } + */ + + UnifyType extInt = tf.getExtendsType(integer); + UnifyType hashSetExtInt = tf.getSimpleType("HashSet", extInt); + UnifyType treeSetExtInt = tf.getSimpleType("TreeSet", extInt); + UnifyType linkedHashSetExtInt = tf.getSimpleType("LinkedHashSet", extInt); + UnifyType setExtInt = tf.getSimpleType("Set", extInt); + + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + setInt, hashSetInt, linkedHashSetInt, treeSetInt, + hashSetExtInt, treeSetExtInt, linkedHashSetExtInt, setExtInt, + }).collect(Collectors.toSet())); + + Assert.assertEquals(expectedResult, fc.smaller(setExtInt)); + + /* + * Test Case 3: + * + * smaller(Set) = + * { HashSet, Set, TreeSet, LinkedHashSet, + * HashSet, Set, TreeSet, LinkedHashSet, + * HashSet, Set, TreeSet, LinkedHashSet + * HashSet } + */ + + UnifyType hashSetNum = tf.getSimpleType("HashSet", number); + UnifyType treeSetNum = tf.getSimpleType("TreeSet", number); + UnifyType linkedHashSetNum = tf.getSimpleType("LinkedHashSet", number); + UnifyType setNum = tf.getSimpleType("Set", number); + + UnifyType extNum = tf.getExtendsType(number); + UnifyType hashSetExtNum = tf.getSimpleType("HashSet", extNum); + UnifyType treeSetExtNum = tf.getSimpleType("TreeSet", extNum); + UnifyType linkedHashSetExtNum = tf.getSimpleType("LinkedHashSet", extNum); + UnifyType setExtNum = tf.getSimpleType("Set", extNum); + + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + setInt, hashSetInt, linkedHashSetInt, treeSetInt, + setNum, hashSetNum, linkedHashSetNum, treeSetNum, + setExtInt, hashSetExtInt, linkedHashSetExtInt, treeSetExtInt, + setExtNum, hashSetExtNum, linkedHashSetExtNum, treeSetExtNum + }).collect(Collectors.toSet())); + + Assert.assertEquals(expectedResult, fc.smaller(setExtNum)); + + /* + * Test Case 4: + * smaller(Set) = + * { HashSet, Set, TreeSet, LinkedHashSet } + */ + + UnifyType t = tf.getPlaceholderType("T"); + UnifyType setT = tf.getSimpleType("Set", t); + UnifyType hashSetT = tf.getSimpleType("HashSet", t); + UnifyType treeSetT = tf.getSimpleType("TreeSet", t); + UnifyType linkedHashSetT = tf.getSimpleType("LinkedHashSet", t); + + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + setT, hashSetT, treeSetT, linkedHashSetT + }).collect(Collectors.toSet())); + + Assert.assertEquals(expectedResult, fc.smaller(setT)); + + /* + * Test Case 5 + * + * smaller(Set = + * { Set, HashSet, TreeSet, LinkedHashSet, + * Set, HashSet, TreeSet, LinkedHashSet, + * Set, HashSet, TreeSet, LinkedHashSet } + */ + + UnifyType superNum = tf.getSuperType(number); + UnifyType superInt = tf.getSuperType(integer); + + UnifyType setSupInt = tf.getSimpleType("Set", superInt); + UnifyType hashSetSupInt = tf.getSimpleType("HashSet", superInt); + UnifyType linkedHashSetSupInt = tf.getSimpleType("LinkedHashSet", superInt); + UnifyType treeSetSupInt = tf.getSimpleType("TreeSet", superInt); + UnifyType setSupNum = tf.getSimpleType("Set", superNum); + UnifyType hashSetSupNum = tf.getSimpleType("HashSet", superNum); + UnifyType linkedHashSetSupNum = tf.getSimpleType("LinkedHashSet", superNum); + UnifyType treeSetSupNum = tf.getSimpleType("TreeSet", superNum); + + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + setSupInt, hashSetSupInt, linkedHashSetSupInt, treeSetSupInt, + setSupNum, hashSetSupNum, linkedHashSetSupNum, treeSetSupNum, + setInt, hashSetInt, linkedHashSetInt, treeSetInt, + setNum, hashSetNum, linkedHashSetNum, treeSetNum + }).collect(Collectors.toSet())); + + Assert.assertEquals(expectedResult, fc.smaller(setSupInt)); + + /* + * Test Case 6: + * TODO probleme wenn Set weil T auch in der Klassendeklaration class Set verwendet wird. + * smaller(Set, Set, TreeSet, LinkedHashSet, + * HashSet, Set, TreeSet, LinkedHashSet } + * + */ + UnifyType t1 = tf.getPlaceholderType("T1"); + UnifyType extT1 = tf.getExtendsType(t1); + UnifyType setExtT1 = tf.getSimpleType("Set", extT1); + UnifyType hashSetExtT1 = tf.getSimpleType("HashSet", extT1); + UnifyType treeSetExtT1 = tf.getSimpleType("TreeSet", extT1); + UnifyType linkedHashSetExtT1 = tf.getSimpleType("LinkedHashSet", extT1); + UnifyType setT1 = tf.getSimpleType("Set", t1); + UnifyType hashSetT1 = tf.getSimpleType("HashSet", t1); + UnifyType treeSetT1 = tf.getSimpleType("TreeSet", t1); + UnifyType linkedHashSetT1 = tf.getSimpleType("LinkedHashSet", t1); + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + setT1, hashSetT1, treeSetT1, linkedHashSetT1, + setExtT1, hashSetExtT1, treeSetExtT1, linkedHashSetExtT1 + }).collect(Collectors.toSet())); + + //System.out.println(fc.smaller(setExtT1)); + Assert.assertEquals(expectedResult, fc.smaller(setExtT1)); + + /* + * Test Case 7: + * + * smaller(Set) = + * { HashSet, Set, TreeSet, LinkedHashSet, + * HashSet, Set, TreeSet, LinkedHashSet } + */ + + UnifyType notInFc = tf.getSimpleType("notInFC"); + UnifyType setNotInFc = tf.getSimpleType("Set", notInFc); + UnifyType hashSetNotInFc = tf.getSimpleType("HashSet", notInFc); + UnifyType treeSetNotInFc = tf.getSimpleType("TreeSet", notInFc); + UnifyType linkedHashSetNotInFc = tf.getSimpleType("LinkedHashSet", notInFc); + UnifyType hashSetExtNotInFc = tf.getSimpleType("HashSet", notInFc); + UnifyType treeSetExtNotInFc = tf.getSimpleType("TreeSet", notInFc); + UnifyType linkedHashSetExtNotInFc = tf.getSimpleType("LinkedHashSet", notInFc); + UnifyType setExtNotInFc = tf.getSimpleType("Set", notInFc); + + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + setNotInFc, hashSetNotInFc, treeSetNotInFc, linkedHashSetNotInFc, + setExtNotInFc, hashSetExtNotInFc, treeSetExtNotInFc, linkedHashSetExtNotInFc + }).collect(Collectors.toSet())); + + Assert.assertEquals(expectedResult, fc.smaller(setNotInFc)); + + /* + * Test Case 8: + * + * smaller(Set) = + * { Set, HashSet, LinkedHashSet, TreeSet, + * Set, HashSet, LinkedHashSet, TreeSet } + */ + + UnifyType superNotInFc = tf.getSuperType(notInFc); + UnifyType setSuperNotInFc = tf.getSimpleType("Set", superNotInFc); + UnifyType hashSetSuperNotInFc = tf.getSimpleType("HashSet", superNotInFc); + UnifyType treeSetSuperNotInFc = tf.getSimpleType("TreeSet", superNotInFc); + UnifyType linkedHashSetSuperNotInFc = tf.getSimpleType("LinkedHashSet", superNotInFc); + + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + setNotInFc, hashSetNotInFc, treeSetNotInFc, linkedHashSetNotInFc, + setSuperNotInFc, hashSetSuperNotInFc, treeSetSuperNotInFc, linkedHashSetSuperNotInFc + }).collect(Collectors.toSet())); + + Assert.assertEquals(expectedResult, fc.smaller(setSuperNotInFc)); + + /* + * Test Case 8: + * + * smaller(NotInFc) = + * { NotInFc, NotInFc, NotInFc, NotInFc } + */ + + UnifyType notInFcExtNumber = tf.getSimpleType("NotInFc", extNum); + UnifyType notInFcInteger = tf.getSimpleType("NotInFc", integer); + UnifyType notInFcNumber = tf.getSimpleType("NotInFc", number); + UnifyType notInFcExtInt = tf.getSimpleType("NotInFc", extInt); + + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + notInFcExtNumber, notInFcInteger, notInFcNumber, notInFcExtInt + }).collect(Collectors.toSet())); + + Assert.assertEquals(expectedResult, fc.smaller(notInFcExtNumber)); + + /* + * Test Case 9: + * + * smaller(NotInFc = + * { NotInFc, NotInFc } + */ + + UnifyType alsoNotInFc = tf.getSimpleType("AlsoNotInFc"); + UnifyType notInFcAlsoNotInFc = tf.getSimpleType("NotInFc", alsoNotInFc); + UnifyType notInFcSupAlsoNotInFc = tf.getSimpleType("NotInFc", tf.getSuperType(alsoNotInFc)); + + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + notInFcAlsoNotInFc, notInFcSupAlsoNotInFc + }).collect(Collectors.toSet())); + + Set actual = fc.smaller(notInFcSupAlsoNotInFc); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 10: + * + * smaller(TreeMap) = + * { TreeMap, TreeMap, TreeMap, TreeMap + * TreeMap, TreeMap, TreeMap, TreeMap, + * TreeMap, TreeMap, TreeMap + * TreeMap, TreeMap, TreeMap, TreeMap } + */ + + UnifyType treeMapExtNumSupInt = tf.getSimpleType("TreeMap", extNum, superInt); + + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + treeMapExtNumSupInt, tf.getSimpleType("TreeMap", extNum, superNum), tf.getSimpleType("TreeMap", extNum, integer), tf.getSimpleType("TreeMap", extNum, number), + tf.getSimpleType("TreeMap", number, superInt), tf.getSimpleType("TreeMap", number, superNum), tf.getSimpleType("TreeMap", number, integer), tf.getSimpleType("TreeMap", number, number), + tf.getSimpleType("TreeMap", integer, superInt), tf.getSimpleType("TreeMap", integer, superNum), tf.getSimpleType("TreeMap", integer, integer), tf.getSimpleType("TreeMap", integer, number), + tf.getSimpleType("TreeMap", extInt, superInt), tf.getSimpleType("TreeMap", extInt, superNum), tf.getSimpleType("TreeMap", extInt, integer), tf.getSimpleType("TreeMap", extInt, number) + }).collect(Collectors.toSet())); + + actual = fc.smaller(treeMapExtNumSupInt); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 11: + * + * smaller(SortedMap) = { SortedMap, NavigableMap, TreeMap } + */ + + UnifyType sortedMapNumberT = tf.getSimpleType("SortedMap", number, t); + UnifyType navigableMapNumberT = tf.getSimpleType("NavigableMap", number, t); + UnifyType treeMapNumberT = tf.getSimpleType("TreeMap", number, t); + + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + sortedMapNumberT, navigableMapNumberT, treeMapNumberT + }).collect(Collectors.toSet())); + + actual = fc.smaller(sortedMapNumberT); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 12: + * + * MyMap <* TreeMap> + * + * smaller(TreeMap) = { TreeMap>, MyMap } + */ + + fcb = new FiniteClosureBuilder(); + UnifyType k = tf.getPlaceholderType("K"); + UnifyType myMap = tf.getSimpleType("MyMap", k); + fcb.add(myMap, tf.getSimpleType("TreeMap", k, tf.getSimpleType("List", k))); + fcb.add(integer, number); + fc = fcb.getCollectionExample(); + + UnifyType treeMapNumberListNumber = tf.getSimpleType("TreeMap", number, tf.getSimpleType("List", number)); + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + treeMapNumberListNumber, + tf.getSimpleType("MyMap", number) + }).collect(Collectors.toSet())); + + actual = fc.smaller(treeMapNumberListNumber); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 13: + * + * MyMap <* TreeMap> + * + * smaller(TreeMap) = + * { TreeMap, List>, + * TreeMap>, + * TreeMap>, + * TreeMap>, + * MyMap } + */ + + UnifyType listInteger = tf.getSimpleType("List", integer); + UnifyType treeMapExtNumberListInteger = tf.getSimpleType("TreeMap", extNum, listInteger); + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + treeMapExtNumberListInteger, + tf.getSimpleType("TreeMap", extInt, listInteger), + tf.getSimpleType("TreeMap", number, listInteger), + tf.getSimpleType("TreeMap", integer, listInteger), + tf.getSimpleType("MyMap", integer) + }).collect(Collectors.toSet())); + + actual = fc.smaller(treeMapExtNumberListInteger); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 14 + * + * MyMap <* TreeMap> + * + * smaller(TreeMap) = + * { TreeMap, List>, + * TreeMap>, + * TreeMap>, + * TreeMap>, + * MyMap + * MyMap + * MyMap + * MyMap + */ + + UnifyType listExtNum = tf.getSimpleType("List", extNum); + UnifyType treeMapExtNumListExtNum = tf.getSimpleType("TreeMap", extNum, listExtNum); + UnifyType myMapInt = tf.getSimpleType("MyMap", integer); + UnifyType myMapNumber = tf.getSimpleType("MyMap", number); + UnifyType myMapExtInt = tf.getSimpleType("MyMap", extInt); + UnifyType myMapExtNum = tf.getSimpleType("MyMap", extNum); + + actual = fc.smaller(treeMapExtNumListExtNum); + + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + tf.getSimpleType("TreeMap", extNum, listExtNum), + tf.getSimpleType("TreeMap", extInt, listExtNum), + tf.getSimpleType("TreeMap", number, listExtNum), + tf.getSimpleType("TreeMap", integer, listExtNum), + myMapInt, myMapNumber, myMapExtInt, myMapExtNum + }).collect(Collectors.toSet())); + + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 15: + * + * MyMap <* TreeMap> + * + * smaller(NavigableSet>) = + * { Permutationen der List, + * Permutationen der List in TreeSets, + * MyMap und MyMap + * } + */ + + UnifyType navSet = tf.getSimpleType("NavigableMap", extInt, tf.getExtendsType(tf.getSimpleType("List", extInt))); + + actual = fc.smaller(navSet); + + Assert.assertEquals(82, actual.size()); + Assert.assertTrue(actual.contains(myMapExtInt)); + Assert.assertTrue(actual.contains(myMapInt)); + + /* + * Test Case 16: + * + * smaller(FunN) = + * { FunN, FunN, + * FunN, FunN, + * FunN, FunN, + * FunN, FunN } + */ + + UnifyType object = tf.getSimpleType("Object"); + + fcb = new FiniteClosureBuilder(); + fcb.add(integer, number); + fcb.add(number, object); + fc = fcb.getCollectionExample(); + + UnifyType funNNumber = tf.getFunNType(number, number, number); + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + tf.getFunNType(number, number, number), tf.getFunNType(number, object, number), + tf.getFunNType(number, number, object), tf.getFunNType(number, object, object), + tf.getFunNType(integer, number, number), tf.getFunNType(integer, object, number), + tf.getFunNType(integer, number, object), tf.getFunNType(integer, object, object), + }).collect(Collectors.toSet())); + + actual = fc.smaller(funNNumber); + //System.out.println(actual); + Assert.assertEquals(expectedResult, actual); + + } + + @Test + public void testGreater() { + TypeFactory tf = new TypeFactory(); + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + UnifyType k = tf.getPlaceholderType("K"); + UnifyType integer = tf.getSimpleType("Integer"); + UnifyType number = tf.getSimpleType("Number"); + UnifyType myMap = tf.getSimpleType("MyMap", k); + UnifyType myIntMap = tf.getSimpleType("MyIntMap"); + UnifyType collection = tf.getSimpleType("Collection"); + UnifyType sortedSet =tf.getSimpleType("SortedSet", "T"); + UnifyType extInt = tf.getExtendsType(integer); + UnifyType extNum = tf.getExtendsType(number); + UnifyType supInt = tf.getSuperType(integer); + UnifyType supNum = tf.getSuperType(number); + fcb.add(myMap, tf.getSimpleType("Map", k, tf.getSimpleType("List", k))); + fcb.add(myIntMap, tf.getSimpleType("MyMap", integer)); + fcb.add(sortedSet, tf.getSimpleType("Set", "T")); // sortedSet < Set missing in collection example + fcb.add(integer, number); + IFiniteClosure fc = fcb.getCollectionExample(); + + /* + * Test Case 1: + * + * greater(SortedSet) = + * { SortedSet, Set, Collection + * SortedSet, SortedSet, SortedSet, + * Set, Set, Set } + */ + + UnifyType sortedSetInteger = tf.getSimpleType("SortedSet", integer); + Set expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + sortedSetInteger, tf.getSimpleType("Set", integer), collection, + tf.getSimpleType("SortedSet", extInt), tf.getSimpleType("SortedSet", supInt), + tf.getSimpleType("SortedSet", extNum), tf.getSimpleType("Set", extInt), + tf.getSimpleType("Set", supInt), tf.getSimpleType("Set", extNum) + }).collect(Collectors.toSet())); + + Set actual = fc.greater(sortedSetInteger); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 2: + * + * greater(SortedSet) = + * { SortedSet, SortedSet, + * Set, Set, Collection } + */ + + UnifyType sortedSetExtInt = tf.getSimpleType("SortedSet", extInt); + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + sortedSetExtInt, tf.getSimpleType("SortedSet", extNum), collection, + tf.getSimpleType("Set", extInt), tf.getSimpleType("Set", extNum) + }).collect(Collectors.toSet())); + + actual = fc.greater(sortedSetExtInt); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 3: + * + * TODO hier extends und super? (siehe test case 4 bei smaller) + * greater(SortedSet) = + * { SortedSet, SortedSet, SortedSet, + * Set, Set, Set, Collection } + */ + + /* + * Test Case 4: + * + * greater(SortedSet) = + * { SortedSet, SortedSet + * Set, Set, Collection } + */ + + UnifyType sortedSetSupNum = tf.getSimpleType("SortedSet", supNum); + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + sortedSetSupNum, tf.getSimpleType("SortedSet", supInt), collection, + tf.getSimpleType("Set", supNum), tf.getSimpleType("Set", supInt) + }).collect(Collectors.toSet())); + + actual = fc.greater(sortedSetSupNum); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 5: + * + * TODO nicht unifizierbar bei T wenn Set deklariert wurde. Können die beiden T's verschieden sein? + * greater(SortedSet) = + * { SortedSet, Set, Collection } + */ + + UnifyType extT = tf.getExtendsType(tf.getPlaceholderType("T1")); + UnifyType sortedSetExtT = tf.getSimpleType("SortedSet", extT); + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + sortedSetExtT, tf.getSimpleType("Set", extT), collection, + }).collect(Collectors.toSet())); + + actual = fc.greater(sortedSetExtT); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 6: + * + * greater(SortedSet) = + * { SortedSet, SortedSet, SortedSet, + * Set, Set, Set, Collection } + */ + + UnifyType notInFc = tf.getSimpleType("NotInFc"); + UnifyType extNotInFc = tf.getExtendsType(notInFc); + UnifyType supNotInFc = tf.getSuperType(notInFc); + UnifyType sortedSetNotInFc= tf.getSimpleType("SortedSet", notInFc); + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + sortedSetNotInFc, tf.getSimpleType("SortedSet", extNotInFc), tf.getSimpleType("SortedSet", supNotInFc), + tf.getSimpleType("Set", notInFc), tf.getSimpleType("Set", extNotInFc), tf.getSimpleType("Set", supNotInFc), + collection + }).collect(Collectors.toSet())); + + actual = fc.greater(sortedSetNotInFc); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 7: + * + * greater(SortedSet, Set, Collection } + */ + + UnifyType sortedSetSupNotInFc= tf.getSimpleType("SortedSet", supNotInFc); + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + sortedSetSupNotInFc, tf.getSimpleType("Set", supNotInFc), collection + }).collect(Collectors.toSet())); + + actual = fc.greater(sortedSetSupNotInFc); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 8: + * + * greater(NotInFc) = + * { NotInFc, NotInFc, NotInFC, + * NotInFc } + */ + + UnifyType notInFcInteger = tf.getSimpleType("NotInFc", integer); + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + notInFcInteger, tf.getSimpleType("NotInFc", supInt), + tf.getSimpleType("NotInFc", extInt), tf.getSimpleType("NotInFc", extNum) + }).collect(Collectors.toSet())); + + actual = fc.greater(notInFcInteger); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 9: + * greater(NotInFc) = + * { NotInFc, NotInFc } + */ + + UnifyType notInFcAlsoNotInFc = tf.getSimpleType("NotInFc", tf.getSimpleType("AlsoNotInFc")); + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + notInFcAlsoNotInFc, tf.getSimpleType("NotInFc", tf.getExtendsType(tf.getSimpleType("AlsoNotInFc"))), + tf.getSimpleType("NotInFc", tf.getSuperType(tf.getSimpleType("AlsoNotInFc"))) + }).collect(Collectors.toSet())); + + actual = fc.greater(notInFcAlsoNotInFc); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 10: + * greater(Map) = + * { Map, Map, + * Map, Map, + * Map, Map, + * Map, Map } + */ + + UnifyType mapExtIntInt = tf.getSimpleType("Map", extInt, integer); + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + mapExtIntInt, tf.getSimpleType("Map", extInt, extInt), + tf.getSimpleType("Map", extInt, supInt), tf.getSimpleType("Map", extInt, extNum), + tf.getSimpleType("Map", extNum, integer), tf.getSimpleType("Map", extNum, extInt), + tf.getSimpleType("Map", extNum, supInt), tf.getSimpleType("Map", extNum, extNum) + }).collect(Collectors.toSet())); + + actual = fc.greater(mapExtIntInt); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 11: + * + * MyIntMap < MyMap + * MyMap < Map> + * + * greater(MyIntMap) = + * { MyMap, MyMap, MyMap, MyMap, + * Map, Map, List, + * Map, List, Map, MyIntMap } + */ + + UnifyType listInteger = tf.getSimpleType("List", integer); + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + myIntMap, tf.getSimpleType("MyMap", integer), tf.getSimpleType("MyMap", extInt), + tf.getSimpleType("MyMap", extNum), tf.getSimpleType("MyMap", supInt), + tf.getSimpleType("Map", integer, listInteger), tf.getSimpleType("Map", extInt, listInteger), + tf.getSimpleType("MyMap", extNum, listInteger), tf.getSimpleType("MyMap", supInt, listInteger) + }).collect(Collectors.toSet())); + + actual = fc.greater(myIntMap); + //Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 12: + * + * MyIntMap < MyMap + * MyMap < Map> + * + * TODO + * D d = null; + * A> a = null; + * a = d; ist nicht möglich! + * + * greater(MyMap) = + * { MyMap, MyMap, + * Map>, + * Map, List> } + */ + + /* + * Test Case 13: + * + * greater(SortedMap, ? super List>) = + * + */ + + /* + * Test Case 14: + * + * greater(FunN) = + * { FunN, FunN, + * FunN, FunN, + * FunN, FunN, + * FunN, FunN } + */ + + UnifyType object = tf.getSimpleType("Object"); + + fcb = new FiniteClosureBuilder(); + fcb.add(integer, number); + fcb.add(number, object); + fc = fcb.getCollectionExample(); + + UnifyType funNNumber = tf.getFunNType(number, number, number); + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + tf.getFunNType(number, number, number), tf.getFunNType(number, integer, number), + tf.getFunNType(number, number, integer), tf.getFunNType(number, integer, integer), + tf.getFunNType(object, number, number), tf.getFunNType(object, integer, number), + tf.getFunNType(object, number, integer), tf.getFunNType(object, integer, integer) + }).collect(Collectors.toSet())); + + actual = fc.greater(funNNumber); + Assert.assertEquals(expectedResult, actual); + } +} diff --git a/test/unify/GenerateFiniteClosure.java b/test/unify/GenerateFiniteClosure.java new file mode 100644 index 000000000..42a5e8623 --- /dev/null +++ b/test/unify/GenerateFiniteClosure.java @@ -0,0 +1,51 @@ +package unify; + +import static org.junit.Assert.*; + +import java.util.Set; + +import org.junit.Test; + +import de.dhbwstuttgart.syntaxtree.ImportDeclarations; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; +import de.dhbwstuttgart.syntaxtree.misc.UsedId; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.typeinference.Menge; +import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; +import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; + +public class GenerateFiniteClosure{ + + private TypeAssumptions generateAssumptionsFromImport(String importClass){ + SourceFile sf = new SourceFile(); + ImportDeclarations imports = new ImportDeclarations(); + imports.add(new UsedId(importClass,0)); + TypeAssumptions ass = sf.makeBasicAssumptionsFromJRE(imports, true); + return ass; + } + + @Test + public void generateTypeAssumptions(){ + Menge imports = new Menge<>(); + imports.add("java.util.Vector"); + imports.add("java.lang.Boolean"); + imports.add("java.util.ArrayList"); + + for(String importClass : imports){ + TypeAssumptions ass = generateAssumptionsFromImport(importClass); + assertTrue(ass.getClassAssumptionFor(new RefType(importClass,null,0))!=null); + } + } + + @Test + public void test() { + String importClass = "java.util.Vector"; + TypeAssumptions ass = generateAssumptionsFromImport(importClass); + FiniteClosure fc = UnifyTypeFactory.generateFC(ass); + Set test = fc.getAllTypesByName(importClass); + assertTrue(test.size()>0); + } + +} diff --git a/test/unify/RuleSetTest.java b/test/unify/RuleSetTest.java new file mode 100644 index 000000000..0679bda26 --- /dev/null +++ b/test/unify/RuleSetTest.java @@ -0,0 +1,696 @@ +package unify; + + +import java.util.Optional; +import java.util.Set; + +import junit.framework.Assert; + +import org.junit.Test; + +import de.dhbwstuttgart.typeinference.unify.RuleSet; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet; +import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; +import de.dhbwstuttgart.typeinference.unify.model.SuperType; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; + + +public class RuleSetTest { + + @Test + public void testReduceUp() { + IRuleSet rules = new RuleSet(); + TypeFactory tf = new TypeFactory(); + + /* + * Positive Tests + */ + + UnifyPair reduce1 = new UnifyPair(tf.getSimpleType("type"), tf.getSuperType(tf.getSimpleType("type")), PairOperator.SMALLERDOT); + UnifyPair reduce2 = new UnifyPair(tf.getPlaceholderType("T"), tf.getSuperType(tf.getSimpleType("type")), PairOperator.SMALLERDOT); + + UnifyPair expected1 = new UnifyPair(tf.getSimpleType("type"), tf.getSimpleType("type"), PairOperator.SMALLERDOT); + UnifyPair expected2 = new UnifyPair(tf.getPlaceholderType("T"), tf.getSimpleType("type"), PairOperator.SMALLERDOT); + + Optional opt1 = rules.reduceUp(reduce1); + Optional opt2 = rules.reduceUp(reduce2); + + Assert.assertTrue(opt1.isPresent()); + Assert.assertTrue(opt2.isPresent()); + Assert.assertEquals(opt1.get(), expected1); + Assert.assertEquals(opt2.get(), expected2); + + /* + * Negative Tests + */ + + UnifyPair noreduce1 = new UnifyPair(tf.getSuperType(tf.getSimpleType("type")), tf.getSuperType(tf.getSimpleType("type")), PairOperator.SMALLERDOT); + UnifyPair noreduce2 = new UnifyPair(tf.getPlaceholderType("T"), tf.getSimpleType("type"), PairOperator.SMALLERDOT); + UnifyPair noreduce3 = new UnifyPair(tf.getPlaceholderType("T"), tf.getExtendsType(tf.getSimpleType("type")), PairOperator.SMALLERDOT); + UnifyPair noreduce4 = new UnifyPair(tf.getPlaceholderType("T"), tf.getSuperType(tf.getSimpleType("type")), PairOperator.EQUALSDOT); + + Assert.assertFalse(rules.reduceUp(noreduce1).isPresent()); + Assert.assertFalse(rules.reduceUp(noreduce2).isPresent()); + Assert.assertFalse(rules.reduceUp(noreduce3).isPresent()); + Assert.assertFalse(rules.reduceUp(noreduce4).isPresent()); + } + + @Test + public void testReduceLow() { + IRuleSet rules = new RuleSet(); + TypeFactory tf = new TypeFactory(); + + /* + * Positive Tests + */ + UnifyPair reduce1 = new UnifyPair(tf.getExtendsType(tf.getSimpleType("type")), tf.getSimpleType("type"), PairOperator.SMALLERDOT); + UnifyPair reduce2 = new UnifyPair(tf.getExtendsType(tf.getSimpleType("type")), tf.getPlaceholderType("T"), PairOperator.SMALLERDOT); + + UnifyPair expected1 = new UnifyPair(tf.getSimpleType("type"), tf.getSimpleType("type"), PairOperator.SMALLERDOT); + UnifyPair expected2 = new UnifyPair(tf.getSimpleType("type"), tf.getPlaceholderType("T"), PairOperator.SMALLERDOT); + + Optional opt1 = rules.reduceLow(reduce1); + Optional opt2 = rules.reduceLow(reduce2); + + Assert.assertTrue(opt1.isPresent()); + Assert.assertTrue(opt2.isPresent()); + Assert.assertEquals(opt1.get(), expected1); + Assert.assertEquals(opt2.get(), expected2); + + /* + * Negative Tests + */ + UnifyPair noreduce1 = new UnifyPair(tf.getExtendsType(tf.getSimpleType("type")), tf.getExtendsType(tf.getSimpleType("type")), PairOperator.SMALLERDOT); + UnifyPair noreduce2 = new UnifyPair(tf.getPlaceholderType("T"), tf.getSimpleType("type"), PairOperator.SMALLERDOT); + UnifyPair noreduce3 = new UnifyPair(tf.getSuperType(tf.getPlaceholderType("T")), tf.getSimpleType("type"), PairOperator.SMALLERDOT); + UnifyPair noreduce4 = new UnifyPair(tf.getExtendsType(tf.getPlaceholderType("T")), tf.getSimpleType("type"), PairOperator.EQUALSDOT); + + Assert.assertFalse(rules.reduceLow(noreduce1).isPresent()); + Assert.assertFalse(rules.reduceLow(noreduce2).isPresent()); + Assert.assertFalse(rules.reduceLow(noreduce3).isPresent()); + Assert.assertFalse(rules.reduceLow(noreduce4).isPresent()); + } + + @Test + public void testReduceUpLow() { + IRuleSet rules = new RuleSet(); + TypeFactory tf = new TypeFactory(); + + /* + * Positive Tests + */ + UnifyPair reduce1 = new UnifyPair(tf.getExtendsType(tf.getSimpleType("type")), tf.getSuperType(tf.getSimpleType("type")), PairOperator.SMALLERDOT); + UnifyPair reduce2 = new UnifyPair(tf.getExtendsType(tf.getSimpleType("type")), tf.getSuperType(tf.getPlaceholderType("T")), PairOperator.SMALLERDOT); + + UnifyPair expected1 = new UnifyPair(tf.getSimpleType("type"), tf.getSimpleType("type"), PairOperator.SMALLERDOT); + UnifyPair expected2 = new UnifyPair(tf.getSimpleType("type"), tf.getPlaceholderType("T"), PairOperator.SMALLERDOT); + + Optional opt1 = rules.reduceUpLow(reduce1); + Optional opt2 = rules.reduceUpLow(reduce2); + + Assert.assertTrue(opt1.isPresent()); + Assert.assertTrue(opt2.isPresent()); + Assert.assertEquals(opt1.get(), expected1); + Assert.assertEquals(opt2.get(), expected2); + + /* + * Negative Tests + */ + UnifyPair noreduce1 = new UnifyPair(tf.getExtendsType(tf.getSimpleType("type")), tf.getExtendsType(tf.getSimpleType("type")), PairOperator.SMALLERDOT); + UnifyPair noreduce2 = new UnifyPair(tf.getSuperType(tf.getPlaceholderType("T")), tf.getExtendsType(tf.getSimpleType("type")), PairOperator.SMALLERDOT); + UnifyPair noreduce3 = new UnifyPair(tf.getSuperType(tf.getPlaceholderType("T")), tf.getSimpleType("type"), PairOperator.SMALLERDOT); + UnifyPair noreduce4 = new UnifyPair(tf.getExtendsType(tf.getPlaceholderType("T")), tf.getSimpleType("type"), PairOperator.EQUALSDOT); + + Assert.assertFalse(rules.reduceUpLow(noreduce1).isPresent()); + Assert.assertFalse(rules.reduceUpLow(noreduce2).isPresent()); + Assert.assertFalse(rules.reduceUpLow(noreduce3).isPresent()); + Assert.assertFalse(rules.reduceUpLow(noreduce4).isPresent()); + } + + @Test + public void testReduce1() { + TypeFactory tf = new TypeFactory(); + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + + /* + * Positive Tests + */ + + // C + ReferenceType c1 = tf.getSimpleType("C", "T1", "T2", "T3", "T4"); + // D + ReferenceType d1 = tf.getSimpleType("D", "T4", "T1", "T2", "T3"); + ReferenceType buffer = tf.getSimpleType("Buffer"); + + //C + ReferenceType c2 = tf.getSimpleType("C", tf.getSimpleType("Int"), tf.getExtendsType(tf.getSimpleType("Double")), tf.getPlaceholderType("M"), tf.getPlaceholderType("N")); + //D, Number, Double, N> + ReferenceType d2 = tf.getSimpleType("D", tf.getSuperType(tf.getSimpleType("HashSet", "Int")), tf.getSimpleType("Number"), tf.getSimpleType("Double"), tf.getPlaceholderType("N")); + + // C<...> < buffer < D<...> + fcb.add(c1, buffer); + fcb.add(buffer, d1); + + IRuleSet rules = new RuleSet(); + IFiniteClosure fc = fcb.getFiniteClosure(); + UnifyPair pair = new UnifyPair(c2, d2, PairOperator.SMALLERDOT); + + System.out.println("------ Reduce1 ------"); + Optional> res = rules.reduce1(pair, fc); + System.out.println(res); + + pair = new UnifyPair(c2, c2, PairOperator.SMALLERDOT); + res = rules.reduce1(pair, fc); + System.out.println(res); + + /* + * Negative Tests + */ + + // Case 1: D <. C and C <* D + pair = new UnifyPair(d2, c2, PairOperator.SMALLERDOT); + Assert.assertFalse(rules.reduce1(pair, fc).isPresent()); + + // Case 2: D =. C + pair = new UnifyPair(c2, d2, PairOperator.EQUALSDOT); + Assert.assertFalse(rules.reduce1(pair, fc).isPresent()); + + // Case 3: C <. D and !(C <* D) + fcb.clear(); + fc = fcb.getFiniteClosure(); + rules = new RuleSet(); + pair = new UnifyPair(c1, d1, PairOperator.SMALLERDOT); + Assert.assertFalse(rules.reduce1(pair, fc).isPresent()); + } + + @Test + public void testReduce2() { + TypeFactory tf = new TypeFactory(); + IRuleSet rules = new RuleSet(); + + /* + * Positive Tests + */ + System.out.println("----- Reduce2 ------"); + + // C + ReferenceType c1 = tf.getSimpleType("C", tf.getPlaceholderType("T1"), tf.getSimpleType("SType1"), tf.getExtendsType(tf.getSimpleType("SType1"))); + // C + ReferenceType c2 = tf.getSimpleType("C", tf.getPlaceholderType("T2"), tf.getSimpleType("SType2"), tf.getExtendsType(tf.getSimpleType("SType2"))); + + UnifyPair pair1 = new UnifyPair(c1, c2, PairOperator.EQUALSDOT); + UnifyPair pair2 = new UnifyPair(tf.getExtendsType(c1), tf.getExtendsType(c2), PairOperator.EQUALSDOT); + UnifyPair pair3 = new UnifyPair(tf.getSuperType(c1), tf.getSuperType(c2), PairOperator.EQUALSDOT); + + Optional> opt1 = rules.reduce2(pair1); + System.out.println(opt1); + + Optional> opt2 = rules.reduce2(pair2); + System.out.println(opt2); + + Optional> opt3 = rules.reduce2(pair3); + System.out.println(opt3); + + + /* + * Negative Tests + */ + + ReferenceType d1 = tf.getSimpleType("D", tf.getPlaceholderType("T2"), tf.getSimpleType("SType2"), tf.getExtendsType(tf.getSimpleType("SType2"))); + pair1 = new UnifyPair(d1, c1, PairOperator.EQUALSDOT); // Case 1: D =. C + pair2 = new UnifyPair(tf.getExtendsType(c1), c2, PairOperator.EQUALSDOT); // Case 2: ? extends C =. C + pair3 = new UnifyPair(tf.getExtendsType(c1), tf.getSuperType(c2), PairOperator.EQUALSDOT); // Case 3: ? extends C =. ? super C + UnifyPair pair4 = new UnifyPair(c1, c2, PairOperator.SMALLERDOT); // Case 4: C <. C + + Assert.assertFalse(rules.reduceEq(pair1).isPresent()); + Assert.assertFalse(rules.reduceEq(pair2).isPresent()); + Assert.assertFalse(rules.reduceEq(pair3).isPresent()); + Assert.assertFalse(rules.reduceEq(pair4).isPresent()); + } + + @Test + public void testReduceExt() { + TypeFactory tf = new TypeFactory(); + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + + /* + * Positive Tests + */ + + // X + ReferenceType x1 = tf.getSimpleType("X", "T1", "T2", "T3", "T4"); + // Y + ReferenceType y1 = tf.getSimpleType("Y", "T4", "T1", "T2", "T3"); + ReferenceType buffer = tf.getSimpleType("Buffer"); + + //X + ReferenceType x2 = tf.getSimpleType("X", tf.getSimpleType("Int"), tf.getExtendsType(tf.getSimpleType("Double")), tf.getPlaceholderType("M"), tf.getPlaceholderType("N")); + //? extends Y, Number, Double, N> + ExtendsType extY1 = tf.getExtendsType(tf.getSimpleType("Y", tf.getSuperType(tf.getSimpleType("HashSet", "Int")), tf.getSimpleType("Number"), tf.getSimpleType("Double"), tf.getPlaceholderType("N"))); + + // Y<...> < buffer < X<...> + fcb.add(x1, buffer); + fcb.add(buffer, y1); + + IRuleSet rules = new RuleSet(); + IFiniteClosure fc = fcb.getFiniteClosure(); + UnifyPair pair1 = new UnifyPair(x2, extY1, PairOperator.SMALLERDOTWC); + UnifyPair pair2 = new UnifyPair(tf.getExtendsType(x2), extY1, PairOperator.SMALLERDOTWC); + UnifyPair pair3 = new UnifyPair(extY1, extY1, PairOperator.SMALLERDOTWC); + + System.out.println("------ ReduceExt ------"); + Optional> opt1 = rules.reduceExt(pair1, fc); + System.out.println(opt1); + + Optional> opt2 = rules.reduceExt(pair2, fc); + System.out.println(opt2); + + Optional> opt3 = rules.reduceExt(pair3, fc); + System.out.println(opt3); + + /* + * Negative Tests + */ + + // Case 1: X <.? Y + pair1 = new UnifyPair(x2, extY1.getExtendedType(), PairOperator.SMALLERDOTWC); + Assert.assertFalse(rules.reduceExt(pair1, fc).isPresent()); + + // Case 2: X =. ? super Y + pair2 = new UnifyPair(x2, extY1, PairOperator.EQUALSDOT); + Assert.assertFalse(rules.reduceExt(pair2, fc).isPresent()); + + // Case 3: ? extends Y <.? ? extends X + pair3 = new UnifyPair(extY1, tf.getExtendsType(x2), PairOperator.SMALLERDOTWC); + Assert.assertFalse(rules.reduceExt(pair3, fc).isPresent()); + + // Case 4: X <. ? extends Y and ? extends Y not in grArg(X) + fcb.clear(); + rules = new RuleSet(); + fc = fcb.getFiniteClosure(); + pair1 = new UnifyPair(x2, extY1, PairOperator.SMALLERDOTWC); + Assert.assertFalse(rules.reduceExt(pair1, fc).isPresent()); + } + + @Test + public void testReduceSup() { + TypeFactory tf = new TypeFactory(); + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + + /* + * Positive Tests + */ + + // X + ReferenceType x1 = tf.getSimpleType("X", "T1", "T2", "T3", "T4"); + // Y + ReferenceType y1 = tf.getSimpleType("Y", "T4", "T1", "T2", "T3"); + ReferenceType buffer = tf.getSimpleType("Buffer"); + + //X + ReferenceType x2 = tf.getSimpleType("X", tf.getSimpleType("Int"), tf.getExtendsType(tf.getSimpleType("Double")), tf.getPlaceholderType("M"), tf.getPlaceholderType("N")); + //? super Y, Number, Double, N> + SuperType supY1 = tf.getSuperType(tf.getSimpleType("Y", tf.getSuperType(tf.getSimpleType("HashSet", "Int")), tf.getSimpleType("Number"), tf.getSimpleType("Double"), tf.getPlaceholderType("N"))); + + // Y<...> < buffer < X<...> + fcb.add(y1, buffer); + fcb.add(buffer, x1); + + IRuleSet rules = new RuleSet(); + IFiniteClosure fc = fcb.getFiniteClosure(); + UnifyPair pair1 = new UnifyPair(x2, supY1, PairOperator.SMALLERDOTWC); + UnifyPair pair2 = new UnifyPair(tf.getSuperType(x2), supY1, PairOperator.SMALLERDOTWC); + UnifyPair pair3 = new UnifyPair(supY1, supY1, PairOperator.SMALLERDOTWC); + + System.out.println("------ ReduceSup ------"); + Optional> opt1 = rules.reduceSup(pair1, fc); + System.out.println(opt1); + + Optional> opt2 = rules.reduceSup(pair2, fc); + System.out.println(opt2); + + Optional> opt3 = rules.reduceSup(pair3, fc); + System.out.println(opt3); + + /* + * Negative Tests + */ + + // Case 1: X <.? Y + pair1 = new UnifyPair(x2, supY1.getSuperedType(), PairOperator.SMALLERDOTWC); + Assert.assertFalse(rules.reduceSup(pair1, fc).isPresent()); + + // Case 2: X =. ? super Y + pair2 = new UnifyPair(x2, supY1, PairOperator.EQUALSDOT); + Assert.assertFalse(rules.reduceSup(pair2, fc).isPresent()); + + // Case 3: ? super Y <.? ? super X + pair3 = new UnifyPair(supY1, tf.getSuperType(x2), PairOperator.SMALLERDOTWC); + Assert.assertFalse(rules.reduceSup(pair3, fc).isPresent()); + + // Case 4: X <. ? super Y and ? super Y not in grArg(X) + fcb.clear(); + rules = new RuleSet(); + fc = fcb.getFiniteClosure(); + pair1 = new UnifyPair(x2, supY1, PairOperator.SMALLERDOTWC); + Assert.assertFalse(rules.reduceSup(pair1, fc).isPresent()); + } + + @Test + public void testReduceEq() { + TypeFactory tf = new TypeFactory(); + IRuleSet rules = new RuleSet(); + + /* + * Positive Tests + */ + System.out.println("----- ReduceEq ------"); + + // C + ReferenceType c1 = tf.getSimpleType("C", tf.getPlaceholderType("T1"), tf.getSimpleType("SType1"), tf.getExtendsType(tf.getSimpleType("SType1"))); + // C + ReferenceType c2 = tf.getSimpleType("C", tf.getPlaceholderType("T2"), tf.getSimpleType("SType2"), tf.getExtendsType(tf.getSimpleType("SType2"))); + + UnifyPair pair = new UnifyPair(c1, c2, PairOperator.SMALLERDOTWC); + Optional> res = rules.reduceEq(pair); + System.out.println(res); + + /* + * Negative Tests + */ + + // Case 1: D <.? C + ReferenceType d1 = tf.getSimpleType("D", tf.getPlaceholderType("T2"), tf.getSimpleType("SType2"), tf.getExtendsType(tf.getSimpleType("SType2"))); + pair = new UnifyPair(d1, c1, PairOperator.SMALLERDOTWC); + Assert.assertFalse(rules.reduceEq(pair).isPresent()); + + // Case 2: C <. C + pair = new UnifyPair(c1, c2, PairOperator.SMALLERDOT); + Assert.assertFalse(rules.reduceEq(pair).isPresent()); + } + + @Test + public void testErase1() { + TypeFactory tf = new TypeFactory(); + IRuleSet rules = new RuleSet(); + IFiniteClosure fc = new FiniteClosureBuilder().getCollectionExample(); + + /* + * Positive Tests + */ + UnifyPair erase1 = new UnifyPair(tf.getSimpleType("List", "T"), tf.getSimpleType("Collection"), PairOperator.SMALLERDOT); + UnifyPair erase2 = new UnifyPair(tf.getSimpleType("HashSet", "T"), tf.getSimpleType("Collection"), PairOperator.SMALLERDOT); + UnifyPair erase3 = new UnifyPair(tf.getSimpleType("List", "T"), tf.getSimpleType("List", "T"), PairOperator.SMALLERDOT); + + Assert.assertTrue(rules.erase1(erase1, fc)); + Assert.assertTrue(rules.erase1(erase2, fc)); + Assert.assertTrue(rules.erase1(erase3, fc)); + + /* + * Negative Tests + */ + UnifyPair noerase1 = new UnifyPair(tf.getSimpleType("Collection"), tf.getSimpleType("List", "T"), PairOperator.SMALLERDOT); + UnifyPair noerase2 = new UnifyPair(tf.getSimpleType("List", "T"), tf.getSimpleType("Collection"), PairOperator.EQUALSDOT); + UnifyPair noerase3 = new UnifyPair(tf.getSimpleType("List", "T"), tf.getSimpleType("Collection"), PairOperator.SMALLERDOTWC); + + Assert.assertFalse(rules.erase1(noerase1, fc)); + Assert.assertFalse(rules.erase1(noerase2, fc)); + Assert.assertFalse(rules.erase1(noerase3, fc)); + } + + @Test + public void testErase2() { + TypeFactory tf = new TypeFactory(); + IRuleSet rules = new RuleSet(); + IFiniteClosure fc = new FiniteClosureBuilder().getCollectionExample(); + + /* + * Positive Tests + */ + UnifyPair erase1 = new UnifyPair(tf.getSimpleType("List", "T"), tf.getExtendsType(tf.getSimpleType("Collection")), PairOperator.SMALLERDOTWC); + UnifyPair erase2 = new UnifyPair(tf.getSimpleType("Collection"), tf.getSuperType(tf.getSimpleType("HashSet", "T")), PairOperator.SMALLERDOTWC); + UnifyPair erase3 = new UnifyPair(tf.getSimpleType("List", "T"), tf.getSimpleType("List", "T"), PairOperator.SMALLERDOTWC); + UnifyPair erase4 = new UnifyPair(tf.getExtendsType(tf.getSimpleType("LinkedList", "T")), tf.getExtendsType(tf.getSimpleType("List", "T")), PairOperator.SMALLERDOTWC); + UnifyPair erase5 = new UnifyPair(tf.getSuperType(tf.getSimpleType("List", "T")), tf.getSuperType(tf.getSimpleType("Stack", "T")), PairOperator.SMALLERDOTWC); + + + Assert.assertTrue(rules.erase2(erase1, fc)); + Assert.assertTrue(rules.erase2(erase2, fc)); + Assert.assertTrue(rules.erase2(erase3, fc)); + Assert.assertTrue(rules.erase2(erase4, fc)); + Assert.assertTrue(rules.erase2(erase5, fc)); + + /* + * Negative Tests + */ + UnifyPair noerase1 = new UnifyPair(tf.getSimpleType("Collection"), tf.getSimpleType("List", "T"), PairOperator.SMALLERDOTWC); + UnifyPair noerase2 = new UnifyPair(tf.getSuperType(tf.getSimpleType("List", "T")), tf.getSimpleType("ArrayList", "T"), PairOperator.SMALLERDOTWC); + UnifyPair noerase3 = new UnifyPair(tf.getExtendsType(tf.getSimpleType("List", "T")), tf.getSuperType(tf.getSimpleType("List", "T")), PairOperator.SMALLERDOTWC); + UnifyPair noerase4 = new UnifyPair(tf.getSimpleType("List", "T"), tf.getSimpleType("List", "T"), PairOperator.SMALLERDOT); + + Assert.assertFalse(rules.erase2(noerase1, fc)); + Assert.assertFalse(rules.erase2(noerase2, fc)); + Assert.assertFalse(rules.erase2(noerase3, fc)); + Assert.assertFalse(rules.erase2(noerase4, fc)); + } + + @Test + public void testErase3() { + TypeFactory tf = new TypeFactory(); + IRuleSet rules = new RuleSet(); + + /* + * Positive Tests + */ + UnifyPair erase1 = new UnifyPair(tf.getSimpleType("List", "T"), tf.getSimpleType("List", "T"), PairOperator.EQUALSDOT); + UnifyPair erase2 = new UnifyPair(tf.getPlaceholderType("W"), tf.getPlaceholderType("W"), PairOperator.EQUALSDOT); + + Assert.assertTrue(rules.erase3(erase1)); + Assert.assertTrue(rules.erase3(erase2)); + + /* + * Negative Tests + */ + UnifyPair noerase1 = new UnifyPair(tf.getSimpleType("Collection"), tf.getSimpleType("List", "T"), PairOperator.EQUALSDOT); + UnifyPair noerase2 = new UnifyPair(tf.getSimpleType("List", "T"), tf.getSimpleType("List", "T"), PairOperator.SMALLERDOT); + + Assert.assertFalse(rules.erase3(noerase1)); + Assert.assertFalse(rules.erase3(noerase2)); + } + + @Test + public void testSwap() { + TypeFactory tf = new TypeFactory(); + IRuleSet rules = new RuleSet(); + + /* + * Positive Tests + */ + UnifyPair swap1 = new UnifyPair(tf.getExtendsType(tf.getSimpleType("MyClass")), tf.getPlaceholderType("P"), PairOperator.EQUALSDOT); + UnifyPair swap2 = new UnifyPair(tf.getSimpleType("MyClass"), tf.getPlaceholderType("X"), PairOperator.EQUALSDOT); + + UnifyPair expected1 = new UnifyPair(tf.getPlaceholderType("P"), tf.getExtendsType(tf.getSimpleType("MyClass")), PairOperator.EQUALSDOT); + UnifyPair expected2 = new UnifyPair(tf.getPlaceholderType("X"), tf.getSimpleType("MyClass"), PairOperator.EQUALSDOT); + + Optional opt1 = rules.swap(swap1); + Optional opt2 = rules.swap(swap2); + + // swap((? extends MyClass =. P)) = (P =. MyClass) + Assert.assertEquals(opt1.get(), expected1); + + // swap((MyClass =. X)) = (X =. MyClass) + Assert.assertEquals(opt2.get(), expected2); + + /* + * Negative Tests + */ + UnifyPair noswap1 = new UnifyPair(tf.getPlaceholderType("Z"), tf.getPlaceholderType("X"), PairOperator.EQUALSDOT); + UnifyPair noswap2 = new UnifyPair(tf.getSimpleType("MyClass"), tf.getExtendsType(tf.getPlaceholderType("X")), PairOperator.EQUALSDOT); + UnifyPair noswap3 = new UnifyPair( tf.getPlaceholderType("X"), tf.getSimpleType("MyClass"), PairOperator.EQUALSDOT); + UnifyPair noswap4 = new UnifyPair(tf.getSimpleType("MyClass"), tf.getPlaceholderType("X"), PairOperator.SMALLERDOT); + + opt1 = rules.swap(noswap1); + opt2 = rules.swap(noswap2); + Optional opt3 = rules.swap(noswap3); + Optional opt4 = rules.swap(noswap4); + + Assert.assertFalse(opt1.isPresent()); + Assert.assertFalse(opt2.isPresent()); + Assert.assertFalse(opt3.isPresent()); + Assert.assertFalse(opt4.isPresent()); + } + + @Test + public void testAdapt() { + TypeFactory tf = new TypeFactory(); + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + + ReferenceType t1 = tf.getSimpleType("Type1", "T", "U"); + ReferenceType t2 = tf.getSimpleType("Type2", "T"); + ReferenceType t3 = tf.getSimpleType("Type3", tf.getPlaceholderType("T"), tf.getSimpleType("Integer")); + + fcb.add(t1, t2); + fcb.add(t2, t3); + + IRuleSet rules = new RuleSet(); + IFiniteClosure fc = fcb.getFiniteClosure(); + + /* + * Positive Tests + */ + + ReferenceType c1 = tf.getSimpleType("Type1", "String", "Double"); + ReferenceType c2 = tf.getSimpleType("Type2", "Object"); + ReferenceType c3 = tf.getSimpleType("Type3", "Object", "Number"); + + UnifyPair pair1 = new UnifyPair(c1, c2, PairOperator.SMALLERDOT); + UnifyPair pair2 = new UnifyPair(c2, c3, PairOperator.SMALLERDOT); + UnifyPair pair3 = new UnifyPair(c1, c3, PairOperator.SMALLERDOT); + + System.out.println("------ Adapt ------"); + System.out.println(rules.adapt(pair1, fc)); + System.out.println(rules.adapt(pair2, fc)); + System.out.println(rules.adapt(pair3, fc)); + + /* + * Negative Tests + */ + + UnifyPair noAdapt1 = new UnifyPair(c2, c1, PairOperator.SMALLERDOT); + UnifyPair noAdapt2 = new UnifyPair(c1, c1, PairOperator.SMALLERDOT); + UnifyPair noAdapt3 = new UnifyPair(c1, c2, PairOperator.SMALLERDOTWC); + + Assert.assertFalse(rules.adapt(noAdapt1, fc).isPresent()); + Assert.assertFalse(rules.adapt(noAdapt2, fc).isPresent()); + Assert.assertFalse(rules.adapt(noAdapt3, fc).isPresent()); + } + + @Test + public void testAdaptExt() { + TypeFactory tf = new TypeFactory(); + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + + ReferenceType t1 = tf.getSimpleType("Type1", "T", "U"); + ReferenceType t2 = tf.getSimpleType("Type2", "T"); + ReferenceType t3 = tf.getSimpleType("Type3", tf.getPlaceholderType("T"), tf.getSimpleType("Integer")); + ReferenceType t32 = tf.getSimpleType("Type3", "T", "U"); + ReferenceType t4 = tf.getSimpleType("Object"); + + fcb.add(t1, t2); + fcb.add(t2, t3); + fcb.add(t32, t4); + + IRuleSet rules = new RuleSet(); + IFiniteClosure fc = fcb.getFiniteClosure(); + + /* + * Positive Tests + */ + + ReferenceType c1 = tf.getSimpleType("Type1", "String", "Double"); + ReferenceType c2 = tf.getSimpleType("Type2", "Object"); + ReferenceType c3 = tf.getSimpleType("Type3", "Object", "Number"); + ExtendsType extc1 = new ExtendsType(c1); + ExtendsType extc2 = new ExtendsType(c2); + ExtendsType extc3 = new ExtendsType(c3); + + UnifyPair pair1 = new UnifyPair(c1, extc2, PairOperator.SMALLERDOTWC); + UnifyPair pair2 = new UnifyPair(c2, extc3, PairOperator.SMALLERDOTWC); + UnifyPair pair3 = new UnifyPair(c1, extc3, PairOperator.SMALLERDOTWC); + UnifyPair pair4 = new UnifyPair(extc1, extc2, PairOperator.SMALLERDOTWC); + UnifyPair pair5 = new UnifyPair(extc2, extc3, PairOperator.SMALLERDOTWC); + UnifyPair pair6 = new UnifyPair(extc1, extc3, PairOperator.SMALLERDOTWC); + UnifyPair pair7 = new UnifyPair(extc1, extc1, PairOperator.SMALLERDOTWC); + + System.out.println("------ AdaptExt ------"); + System.out.println(rules.adaptExt(pair1, fc)); + System.out.println(rules.adaptExt(pair2, fc)); + System.out.println(rules.adaptExt(pair3, fc)); + System.out.println(rules.adaptExt(pair4, fc)); + System.out.println(rules.adaptExt(pair5, fc)); + System.out.println(rules.adaptExt(pair6, fc)); + System.out.println(rules.adaptExt(pair7, fc)); + + /* + * Negative Tests + */ + + UnifyPair noAdapt1 = new UnifyPair(extc2, extc1, PairOperator.SMALLERDOTWC); + UnifyPair noAdapt2 = new UnifyPair(extc1, c2, PairOperator.SMALLERDOTWC); + UnifyPair noAdapt3 = new UnifyPair(tf.getSuperType(c1), extc2, PairOperator.SMALLERDOTWC); + UnifyPair noAdapt4 = new UnifyPair(extc3, extc1, PairOperator.SMALLERDOTWC); + UnifyPair noAdapt5 = new UnifyPair(c1, extc2, PairOperator.SMALLERDOT); + + Assert.assertFalse(rules.adaptExt(noAdapt1, fc).isPresent()); + Assert.assertFalse(rules.adaptExt(noAdapt2, fc).isPresent()); + Assert.assertFalse(rules.adaptExt(noAdapt3, fc).isPresent()); + Assert.assertFalse(rules.adaptExt(noAdapt4, fc).isPresent()); + Assert.assertFalse(rules.adaptExt(noAdapt5, fc).isPresent()); + } + + @Test + public void testAdaptSup() { + TypeFactory tf = new TypeFactory(); + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + + ReferenceType t1 = tf.getSimpleType("Type1", "T", "U"); + ReferenceType t2 = tf.getSimpleType("Type2", "T"); + ReferenceType t3 = tf.getSimpleType("Type3", tf.getPlaceholderType("T"), tf.getSimpleType("Integer")); + ReferenceType t32 = tf.getSimpleType("Type3", "T", "U"); + ReferenceType t4 = tf.getSimpleType("Object"); + + fcb.add(t1, t2); + fcb.add(t2, t3); + fcb.add(t32, t4); + + IRuleSet rules = new RuleSet(); + IFiniteClosure fc = fcb.getFiniteClosure(); + + /* + * Positive Tests + */ + + ReferenceType c1 = tf.getSimpleType("Type1", "String", "Double"); + ReferenceType c2 = tf.getSimpleType("Type2", "Object"); + ReferenceType c3 = tf.getSimpleType("Type3", "Object", "Number"); + SuperType supc1 = new SuperType(c1); + SuperType supc2 = new SuperType(c2); + SuperType supc3 = new SuperType(c3); + + UnifyPair pair1 = new UnifyPair(c2, supc1, PairOperator.SMALLERDOTWC); + UnifyPair pair2 = new UnifyPair(c3, supc2, PairOperator.SMALLERDOTWC); + UnifyPair pair3 = new UnifyPair(c3, supc1, PairOperator.SMALLERDOTWC); + UnifyPair pair4 = new UnifyPair(supc2, supc1, PairOperator.SMALLERDOTWC); + UnifyPair pair5 = new UnifyPair(supc3, supc2, PairOperator.SMALLERDOTWC); + UnifyPair pair6 = new UnifyPair(supc3, supc1, PairOperator.SMALLERDOTWC); + UnifyPair pair7 = new UnifyPair(supc1, supc1, PairOperator.SMALLERDOTWC); + + System.out.println("------ AdaptSup ------"); + System.out.println(rules.adaptSup(pair1, fc)); + System.out.println(rules.adaptSup(pair2, fc)); + System.out.println(rules.adaptSup(pair3, fc)); + System.out.println(rules.adaptSup(pair4, fc)); + System.out.println(rules.adaptSup(pair5, fc)); + System.out.println(rules.adaptSup(pair6, fc)); + System.out.println(rules.adaptSup(pair7, fc)); + + /* + * Negative Tests + */ + + UnifyPair noAdapt1 = new UnifyPair(supc2, supc1, PairOperator.SMALLERDOTWC); + UnifyPair noAdapt2 = new UnifyPair(supc1, c2, PairOperator.SMALLERDOTWC); + UnifyPair noAdapt3 = new UnifyPair(tf.getExtendsType(c1), supc2, PairOperator.SMALLERDOTWC); + UnifyPair noAdapt4 = new UnifyPair(supc3, supc1, PairOperator.SMALLERDOTWC); + UnifyPair noAdapt5 = new UnifyPair(c1, supc2, PairOperator.SMALLERDOT); + + Assert.assertFalse(rules.adaptExt(noAdapt1, fc).isPresent()); + Assert.assertFalse(rules.adaptExt(noAdapt2, fc).isPresent()); + Assert.assertFalse(rules.adaptExt(noAdapt3, fc).isPresent()); + Assert.assertFalse(rules.adaptExt(noAdapt4, fc).isPresent()); + Assert.assertFalse(rules.adaptExt(noAdapt5, fc).isPresent()); + } +} diff --git a/test/unify/StandardUnifyTest.java b/test/unify/StandardUnifyTest.java new file mode 100644 index 000000000..83f8abe1d --- /dev/null +++ b/test/unify/StandardUnifyTest.java @@ -0,0 +1,63 @@ +package unify; + +import java.util.HashSet; +import java.util.Set; + +import junit.framework.Assert; + +import org.junit.Test; + +import de.dhbwstuttgart.typeinference.unify.MartelliMontanariUnify; +import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; + +public class StandardUnifyTest { + + @Test + public void testUnify() { + IUnify unify = new MartelliMontanariUnify(); + TypeFactory tf = new TypeFactory(); + + /* + * Positive Tests + */ + + UnifyType x = tf.getPlaceholderType("x"); + UnifyType y = tf.getPlaceholderType("y"); + UnifyType f = tf.getSimpleType("f", x); + + // {f = y} + Set terms = new HashSet(); + + System.out.println(unify.unify(f, y).get()); + + // {f,x> = f} + UnifyType g = tf.getSimpleType("g", "x"); + UnifyType f1 = tf.getSimpleType("f", g, x); + UnifyType a = tf.getExtendsType(tf.getPlaceholderType("a")); + UnifyType f2 = tf.getSimpleType("f", y, a); + + terms = new HashSet<>(); + + System.out.println(unify.unify(f1, f2).get()); + + /* + * Negative Tests + */ + + // {f(x) =. x} + f = tf.getSimpleType("f", x); + Assert.assertFalse(unify.unify(f, x).isPresent()); + + // {f(x) =. f(x,y)} + f1 = tf.getSimpleType("f", "x"); + f2 = tf.getSimpleType("f", "x", "y"); + Assert.assertFalse(unify.unify(f1, f2).isPresent()); + + // {f(x) =. g(x)} + f1 = tf.getSimpleType("f", "x"); + f2 = tf.getSimpleType("g", "x"); + Assert.assertFalse(unify.unify(f1, f2).isPresent()); + } +} diff --git a/test/unify/TypeFactory.java b/test/unify/TypeFactory.java new file mode 100644 index 000000000..881222c81 --- /dev/null +++ b/test/unify/TypeFactory.java @@ -0,0 +1,44 @@ +package unify; + +import java.util.Arrays; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +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 TypeFactory { + + public ExtendsType getExtendsType(UnifyType extendedType) { + return new ExtendsType(extendedType); + } + + public SuperType getSuperType(UnifyType superedType) { + return new SuperType(superedType); + } + + public ReferenceType getSimpleType(String name) { + return new ReferenceType(name); + } + + public ReferenceType getSimpleType(String name, UnifyType... typeParams) { + return new ReferenceType(name, typeParams); + } + + public ReferenceType getSimpleType(String name, String... typeParams) { + return new ReferenceType(name, Arrays.stream(typeParams).map(x -> getPlaceholderType(x)).collect(Collectors.toList()).toArray(new UnifyType[0])); + } + + public PlaceholderType getPlaceholderType(String name) { + return new PlaceholderType(name); + } + + public FunNType getFunNType(UnifyType... typeParams) { + return FunNType.getFunNType(new TypeParams(typeParams)); + } + +} diff --git a/test/unify/UnifyTest.java b/test/unify/UnifyTest.java new file mode 100644 index 000000000..2ee542f00 --- /dev/null +++ b/test/unify/UnifyTest.java @@ -0,0 +1,1054 @@ +package unify; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +import org.junit.Test; + +import de.dhbwstuttgart.typeinference.unify.TypeUnify; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; +import de.dhbwstuttgart.typeinference.unify.model.TypeParams; +import junit.framework.Assert; + +public class UnifyTest { + + /** + * Testing the unification for cases with (n)one pair and without generics. + */ + @Test + public void unifyTestTrivial() { + /* + * INIT + */ + + TypeFactory tf = new TypeFactory(); + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + + UnifyType number = tf.getSimpleType("Number"); + UnifyType object = tf.getSimpleType("Object"); + UnifyType integer = tf.getSimpleType("Integer"); + UnifyType doubl = tf.getSimpleType("Double"); + + fcb.add(number, object); + fcb.add(integer, number); + fcb.add(doubl, number); + + IFiniteClosure fc = fcb.getCollectionExample(); + + /* + * Test 1: + * + * unify({ }) = { } + */ + + Set eq = new HashSet(); + Set> expected = new HashSet<>(); + expected.add(new HashSet<>()); + Set> actual = new TypeUnify().unifySequential(eq, fc); + Assert.assertEquals(expected, actual); + + /* + * Test 2: + * + * (a <. Number) + */ + + UnifyType tphA = tf.getPlaceholderType("a"); + eq = new HashSet<>(); + eq.add(new UnifyPair(tphA, number, PairOperator.SMALLERDOT)); + + expected = new HashSet<>(); + addAsSet(expected, new UnifyPair(tphA, number, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, integer, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, doubl, PairOperator.EQUALSDOT)); + + actual = new TypeUnify().unifySequential(eq, fc); + + Assert.assertEquals(expected, actual); + + /* + * Test 3: + * + * (Integer <. a) + */ + + eq = new HashSet<>(); + eq.add(new UnifyPair(integer, tphA, PairOperator.SMALLERDOT)); + + expected = new HashSet<>(); + addAsSet(expected, new UnifyPair(tphA, integer, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, number, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, object, PairOperator.EQUALSDOT)); + + actual = new TypeUnify().unifySequential(eq, fc); + + Assert.assertEquals(expected, actual); + + + /* + * Test 4: + * + * (a <.? Number) + */ + + eq = new HashSet<>(); + eq.add(new UnifyPair(tphA, number, PairOperator.SMALLERDOTWC)); + + expected = new HashSet<>(); + addAsSet(expected, new UnifyPair(tphA, number, PairOperator.EQUALSDOT)); + + actual = new TypeUnify().unifySequential(eq, fc); + + Assert.assertEquals(expected, actual); + + /* + * Test 5: + * + * (a <.? ? super Integer) + */ + + UnifyType supInteger = tf.getSuperType(integer); + UnifyType supNumber = tf.getSuperType(number); + UnifyType supObject = tf.getSuperType(object); + eq = new HashSet<>(); + eq.add(new UnifyPair(tphA, supInteger, PairOperator.SMALLERDOTWC)); + + expected = new HashSet<>(); + addAsSet(expected, new UnifyPair(tphA, integer, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, number, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, object, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, supInteger, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, supNumber, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, supObject, PairOperator.EQUALSDOT)); + + actual = new TypeUnify().unifySequential(eq, fc); + System.out.println("? super Integer"); + System.out.println(actual); + actual = filterGeneratedTPHsMultiple(actual); + + Assert.assertEquals(expected, actual); + + /* + * Test 6: + * + * (Number <.? a) + * + */ + + eq = new HashSet<>(); + UnifyType extNumber = tf.getExtendsType(number); + UnifyType extObject = tf.getExtendsType(object); + UnifyType supDouble = tf.getSuperType(doubl); + eq.add(new UnifyPair(number, tphA, PairOperator.SMALLERDOTWC)); + + expected = new HashSet<>(); + addAsSet(expected, new UnifyPair(tphA, number, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, extNumber, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, extObject, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, supInteger, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, supDouble, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, supNumber, PairOperator.EQUALSDOT)); + + actual = new TypeUnify().unifySequential(eq, fc); + actual = filterGeneratedTPHsMultiple(actual); + + Assert.assertEquals(expected, actual); + + /* + * Test 7: + * + * (? extends Number <.? a) + */ + + eq = new HashSet<>(); + eq.add(new UnifyPair(extNumber, tphA, PairOperator.SMALLERDOTWC)); + + expected = new HashSet<>(); + addAsSet(expected, new UnifyPair(tphA, extNumber, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, extObject, PairOperator.EQUALSDOT)); + + actual = new TypeUnify().unifySequential(eq, fc); + actual = filterGeneratedTPHsMultiple(actual); + Assert.assertEquals(expected, actual); + + + /* + * Test 8: + * + * (a <.? ? extends Number) + */ + + UnifyType extInteger = tf.getExtendsType(integer); + UnifyType extDouble = tf.getExtendsType(doubl); + + eq = new HashSet<>(); + eq.add(new UnifyPair(tphA, extNumber, PairOperator.SMALLERDOTWC)); + + expected = new HashSet<>(); + addAsSet(expected, new UnifyPair(tphA, extNumber, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, extInteger, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, extDouble, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, doubl, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, integer, PairOperator.EQUALSDOT)); + addAsSet(expected, new UnifyPair(tphA, number, PairOperator.EQUALSDOT)); + + actual = new TypeUnify().unifySequential(eq, fc); + actual = filterGeneratedTPHsMultiple(actual); + + Assert.assertEquals(expected, actual); + + /* + * Test 8: + * + * (Integer <. Number) + */ + + eq = new HashSet<>(); + eq.add(new UnifyPair(integer, number, PairOperator.SMALLERDOT)); + + expected = new HashSet<>(); + expected.add(new HashSet<>()); + + actual = new TypeUnify().unifySequential(eq, fc); + + Assert.assertEquals(expected, actual); + + /* + * Test 9: + * + * (Integer <.? Number) + */ + + eq = new HashSet<>(); + eq.add(new UnifyPair(integer, number, PairOperator.SMALLERDOTWC)); + + expected = new HashSet<>(); + + actual = new TypeUnify().unifySequential(eq, fc); + + Assert.assertEquals(expected, actual); + + /* + * Test 10: + * + * (a <. b) + */ + + UnifyType tphB = tf.getPlaceholderType("b"); + eq = new HashSet<>(); + eq.add(new UnifyPair(tphA, tphB, PairOperator.SMALLERDOT)); + + expected = new HashSet<>(); + addAsSet(expected, new UnifyPair(tphA, tphB, PairOperator.SMALLERDOT)); + + actual = new TypeUnify().unifySequential(eq, fc); + + Assert.assertEquals(expected, actual); + + /* + * Test 11: + * + * (a <.? b) + */ + + eq = new HashSet<>(); + eq.add(new UnifyPair(tphA, tphB, PairOperator.SMALLERDOTWC)); + + expected = new HashSet<>(); + addAsSet(expected, new UnifyPair(tphA, tphB, PairOperator.SMALLERDOTWC)); + + actual = new TypeUnify().unifySequential(eq, fc); + + Assert.assertEquals(expected, actual); + + /* + * Test 12: + * + * (void <. void) + */ + + eq = new HashSet<>(); + eq.add(new UnifyPair(tphA, tf.getSimpleType("void"), PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tf.getSimpleType("void"), tphA, PairOperator.SMALLERDOT)); + + expected = new HashSet<>(); + addAsSet(expected, new UnifyPair(tphA, tf.getSimpleType("void"), PairOperator.EQUALSDOT)); + + //Test funktioniert momentan auch ohne ein "void" in der Finite Closure + //fcb.add(tf.getSimpleType("void"), tf.getSimpleType("Object")); + + IFiniteClosure voidFC = fcb.getFiniteClosure(); + + actual = new TypeUnify().unifySequential(eq, fc); + + Assert.assertEquals(expected, actual); + } + + @Test + public void unifyTestSimple() { + /* + * INIT + */ + TypeFactory tf = new TypeFactory(); + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + + UnifyType number = tf.getSimpleType("Number"); + UnifyType object = tf.getSimpleType("Object"); + UnifyType integer = tf.getSimpleType("Integer"); + UnifyType doubl = tf.getSimpleType("Double"); + + //fcb.add(number, object); + fcb.add(integer, number); + //fcb.add(doubl, number); + + IFiniteClosure fc = fcb.getCollectionExample(); + + /* + * Test 1: + * + * (Vector <. Vector) + * (List <. List) + * + * Expected: + * {(b = Number), (a = Number)}, {(b = Number), (a = Integer)}, {(b = Number), (a = Integer)} + * (b = Integer), + */ + + UnifyType tphA = tf.getPlaceholderType("a"); + UnifyType tphB = tf.getPlaceholderType("b"); + UnifyType extB = tf.getExtendsType(tphB); + UnifyType extNum = tf.getExtendsType(number); + + Set eq = new HashSet(); + eq.add(new UnifyPair(tf.getSimpleType("Vector", tphA), tf.getSimpleType("Vector", extB), PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tf.getSimpleType("List", tphB), tf.getSimpleType("List", extNum), PairOperator.SMALLERDOT)); + + Set> expected = new HashSet<>(); + Set> actual = new TypeUnify().unifySequential(eq, fc); + + //System.out.println(actual); + //Assert.assertEquals(actual, expected); + + + /* + * Test 2: + * + * Vector <. List + * + */ + + UnifyType extA = tf.getExtendsType(tphA); + + eq = new HashSet(); + eq.add(new UnifyPair(tf.getSimpleType("Vector", extA), tf.getSimpleType("Vector", extNum), PairOperator.SMALLERDOT)); + + expected = new HashSet<>(); + actual = new TypeUnify().unifySequential(eq, fc); + + //System.out.println(actual); + //Assert.assertEquals(actual, expected); + + /* + * Test 3: + * + * Vector <. List + * + */ + + eq = new HashSet(); + eq.add(new UnifyPair(tf.getSimpleType("Vector", extNum), tf.getSimpleType("Vector", extA), PairOperator.SMALLERDOT)); + + expected = new HashSet<>(); + actual = new TypeUnify().unifySequential(eq, fc); + + System.out.println(actual); + //Assert.assertEquals(actual, expected); + + /* + * Test 4: + * + * LinkedList <. Deque <. Queue <. Collection + * + * Vector <. List + * List <. AbstractList + * ? extends Number <.? b + */ + + eq = new HashSet(); + eq.add(new UnifyPair(tf.getSimpleType("LinkedList", number), tf.getSimpleType("Deque", tphA), PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tf.getSimpleType("Deque", tphA), tf.getSimpleType("Queue", tphB), PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(extNum, tphB, PairOperator.SMALLERDOTWC)); + + expected = new HashSet<>(); + actual = new TypeUnify().unifySequential(eq, fc); + + //System.out.println(actual); + //Assert.assertEquals(actual, expected); + } + + /** + * These are tests that specifically test cases where the old unify algorithm was incomplete. + */ + @Test + public void unifyTestExtension() { + /* + * INIT + */ + TypeFactory tf = new TypeFactory(); + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + + UnifyType number = tf.getSimpleType("Number"); + UnifyType object = tf.getSimpleType("Object"); + UnifyType integer = tf.getSimpleType("Integer"); + UnifyType doubl = tf.getSimpleType("Double"); + UnifyType mygeneric = tf.getSimpleType("MyGeneric", "T"); + + + fcb.add(mygeneric, object); + fcb.add(integer, number); + //fcb.add(doubl, number); + + IFiniteClosure fc = fcb.getCollectionExample(); + + + /* + * Test 1: + * This is a Test for the extension of case 1 in the cartesian product of step 4. + * + * (a <. Vector) + * (List <. List) + * + * Expected: + * (b = Integer), (a = Vector) + * (b = ? extends Integer), (a = Vector), + * (b = ? extends Integer), (a = Vector), + * (b = ? super Integer), (a = Vector) + * (b = ? super Integer), (a = Vector) + * (b = ? super Integer), (a = Vector) + * (b = ? super Integer), (a = Vector) + * (b = ? extends Number), (a = Vector) + * (b = ? extends Number), (a = Vector) + * (b = ? extends Number), (a = Vector) + * (b = ? extends Number), (a = Vector) + */ + + UnifyType tphA = tf.getPlaceholderType("a"); + UnifyType tphB = tf.getPlaceholderType("b"); + UnifyType extB = tf.getExtendsType(tphB); + UnifyType extNum = tf.getExtendsType(number); + + Set eq = new HashSet(); + eq.add(new UnifyPair(tphA, tf.getSimpleType("Stack", tphB), PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tf.getSimpleType("List", integer), tf.getSimpleType("List", tphB), PairOperator.SMALLERDOT)); + + Set> expected = new HashSet<>(); + Set> actual = new TypeUnify().unifySequential(eq, fc); + + System.out.println(actual); + //Assert.assertEquals(actual, expected); + + /* + * Test 2: + * + * This is a test for th extension of case 2 of the cartesian product of step 4. + * + * (a <.? ? ext b) + * (b =. Number) + */ + + eq = new HashSet<>(); + eq.add(new UnifyPair(tphA, extB, PairOperator.SMALLERDOTWC)); + eq.add(new UnifyPair(tphB, number, PairOperator.EQUALSDOT)); + + expected = new HashSet<>(); + + actual = new TypeUnify().unifySequential(eq, fc); + + System.out.println("Case 2"); + System.out.println(actual); + + /* + * Test 3: + * This is a test for the extension of case 3 of the cartesian product of step 4. + * + * (a <.? ? sup b) + * (b = Number) + */ + + UnifyType supB = tf.getSuperType(tphB); + eq = new HashSet<>(); + eq.add(new UnifyPair(tphA, supB, PairOperator.SMALLERDOTWC)); + eq.add(new UnifyPair(tphB, number, PairOperator.EQUALSDOT)); + + expected = new HashSet<>(); + + actual = new TypeUnify().unifySequential(eq, fc); + + + System.out.println("Case 3"); + System.out.println(actual); + //Assert.assertEquals(expected, actual); + + /* + * Case 4 has no extension + */ + + /* + * Test 5: + * This is a test for the extension of case 5 of the cartesian product of step 4. + * + * Vector <. a + * b =. Number + */ + + eq = new HashSet<>(); + eq.add(new UnifyPair(tf.getSimpleType("HashSet", tphB), tphA, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tphB, number, PairOperator.EQUALSDOT)); + + expected = new HashSet<>(); + + actual = new TypeUnify().unifySequential(eq, fc); + + System.out.println(actual); + //Assert.assertEquals(expected, actual); + + /* + * Test 6: + * This is a test for the extension of case 6 of the cartesian product of step 4. + * + * ? extends b <.? a + * b =. Integer + */ + + eq = new HashSet<>(); + eq.add(new UnifyPair(extB, tphA, PairOperator.SMALLERDOTWC)); + eq.add(new UnifyPair(tphB, integer, PairOperator.EQUALSDOT)); + + expected = new HashSet<>(); + + actual = new TypeUnify().unifySequential(eq, fc); + + System.out.println(actual); + //Assert.assertEquals(expected, actual); + + /* + * Test 7: + * This is a test for the extension of case 7 of the cartesian product of step 4. + * + * ? sup b <.? a + * b =. Number + */ + + eq = new HashSet<>(); + eq.add(new UnifyPair(supB, tphA, PairOperator.SMALLERDOTWC)); + eq.add(new UnifyPair(tphB, number, PairOperator.EQUALSDOT)); + + expected = new HashSet<>(); + + actual = new TypeUnify().unifySequential(eq, fc); + + System.out.println("Case 7"); + System.out.println(actual); + //Assert.assertEquals(expected, actual); + + + /* + * Test 8: + * This is a test for the extension of case 8 of the cartesian product of step 4. + * + * MyGeneric <.? a + * b =. Integer + */ + + eq = new HashSet<>(); + eq.add(new UnifyPair(tf.getSimpleType("MyGeneric", extB), tphA, PairOperator.SMALLERDOTWC)); + eq.add(new UnifyPair(tphB, number, PairOperator.EQUALSDOT)); + + expected = new HashSet<>(); + + actual = new TypeUnify().unifySequential(eq, fc); + + System.out.println("Case 8:"); + System.out.println(actual); + //Assert.assertEquals(expected, actual); + + } + + @Test + public void unifyTestComplex() { + /* + * INIT + */ + TypeFactory tf = new TypeFactory(); + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + + UnifyType tphT = tf.getPlaceholderType("T"); + UnifyType vector = tf.getSimpleType("Vector", tphT); + UnifyType number = tf.getSimpleType("Number"); + UnifyType integer = tf.getSimpleType("Integer"); + UnifyType object = tf.getSimpleType("Object"); + UnifyType matrix = tf.getSimpleType("Matrix"); + UnifyType vectorvectorint = tf.getSimpleType("Vector", tf.getSimpleType("Vector", integer)); + + + fcb.add(integer, number); + fcb.add(matrix, vectorvectorint); + fcb.add(vector, object); + + IFiniteClosure fc = fcb.getFiniteClosure(); + + Set eq = new HashSet(); + eq.add(new UnifyPair(tf.getSimpleType("Matrix"), tf.getSimpleType("Vector", tf.getPlaceholderType("a")), PairOperator.SMALLERDOT)); + + Set> expected = new HashSet<>(); + Set> actual = new TypeUnify().unifySequential(eq, fc); + + System.out.println("Test Matrix:"); + System.out.println(actual); + } + + @Test + public void unifyTestVoid() { + /* + * Constraints Set mit "void" Typen + * T1 < Integer + * Integer < Integer + * T1 < T2 + * T3 < Bool + * void < T4 + * OL < Object + * void < void + * ol < T5 + * T5 < ol + */ + TypeFactory tf = new TypeFactory(); + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + + UnifyType tphT1 = tf.getPlaceholderType("T1"); + UnifyType tphT2 = tf.getPlaceholderType("T2"); + UnifyType tphT3 = tf.getPlaceholderType("T3"); + UnifyType tphT4 = tf.getPlaceholderType("T4"); + UnifyType tphT5 = tf.getPlaceholderType("T5"); + + UnifyType integer = tf.getSimpleType("java.lang.Integer"); + UnifyType voidType = tf.getSimpleType("void"); + UnifyType bool = tf.getSimpleType("java.lang.Boolean"); + UnifyType object = tf.getSimpleType("Object"); + UnifyType main = tf.getSimpleType("Main"); + UnifyType ol = tf.getSimpleType("OL"); + + fcb.add(integer, object); + fcb.add(main, object); + fcb.add(bool, object); + fcb.add(voidType, voidType); + fcb.add(ol, object); + + IFiniteClosure fc = fcb.getFiniteClosure(); + + Set eq = new HashSet(); + eq.add(new UnifyPair(tphT1, integer, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(integer, integer, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tphT1, tphT2, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tphT2, integer, PairOperator.SMALLERDOT)); + + eq.add(new UnifyPair(tphT3, bool, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(voidType, tphT4, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(ol, object, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(voidType, voidType, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(ol, tphT5, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tphT5, ol, PairOperator.SMALLERDOT)); + + Set> expected = new HashSet<>(); + Set solution = new HashSet(); + solution.add(new UnifyPair(tphT3, bool, PairOperator.EQUALSDOT)); + solution.add(new UnifyPair(tphT5, ol, PairOperator.EQUALSDOT)); + solution.add(new UnifyPair(tphT2, integer, PairOperator.EQUALSDOT)); + solution.add(new UnifyPair(tphT1, integer, PairOperator.EQUALSDOT)); + solution.add(new UnifyPair(tphT4, voidType, PairOperator.EQUALSDOT)); + expected.add(solution); + + + Set> actual = new TypeUnify().unifySequential(eq, fc); + + System.out.println("Test Void:"); + System.out.println(actual); + + Assert.assertEquals(expected, actual); + } + +// @Test +// public void unifyTestMatrixSimple() { +//// [(C <. C), +//// (D <. D), +//// (java.lang.Boolean <. PC), +//// (java.lang.Integer <. E1), +//// (java.util.Vector <. java.util.Vector), +//// (java.lang.Integer <. PD), +//// (java.util.Vector <. java.util.Vector), +//// (PE <. java.lang.Boolean), +//// (C <. java.lang.Integer), +//// (PD <. java.lang.Integer), +//// (PE <. java.lang.Boolean), +//// (E2 <. PF), +//// (C <. java.lang.Integer), +//// (java.util.Vector <. java.util.Vector), +//// (PG <. java.lang.Double), +//// (java.lang.Integer <. java.lang.Double), +//// (PF <. java.lang.Double), +//// (PG <. D), +//// (D <. PH), +//// (void <. B), +//// (void <. PI), +//// (Matrix <. java.util.Vector), +//// (void <. void)] +// +// TypeFactory tf = new TypeFactory(); +// FiniteClosureBuilder fcb = new FiniteClosureBuilder(); +// +// UnifyType tphC = tf.getPlaceholderType("C"); +// UnifyType tphD = tf.getPlaceholderType("D"); +// UnifyType tphPC = tf.getPlaceholderType("PC"); +// UnifyType tphE1 = tf.getPlaceholderType("E1"); +// UnifyType tphPD = tf.getPlaceholderType("PD"); +// UnifyType tphE3 = tf.getPlaceholderType("E3"); +// UnifyType tphPE = tf.getPlaceholderType("PE"); +// UnifyType tphE2 = tf.getPlaceholderType("E2"); +// UnifyType tphPG = tf.getPlaceholderType("PG"); +// UnifyType tphPF = tf.getPlaceholderType("PF"); +// UnifyType tphPH = tf.getPlaceholderType("PH"); +// UnifyType tphPI = tf.getPlaceholderType("PI"); +// UnifyType tphE4 = tf.getPlaceholderType("E4"); +// UnifyType tphB = tf.getPlaceholderType("B"); +// +// UnifyType integer = tf.getSimpleType("java.lang.Integer"); +// UnifyType voidType = tf.getSimpleType("void"); +// UnifyType bool = tf.getSimpleType("java.lang.Boolean"); +// UnifyType object = tf.getSimpleType("java.lang.Object"); +// UnifyType doubl = tf.getSimpleType("java.lang.Double"); +// UnifyType number = tf.getSimpleType("java.lang.Number"); +// +// fcb.add(integer, number); +// fcb.add(bool, object); +// fcb.add(doubl, number); +// fcb.add(number, object); +// fcb.add(voidType, voidType); +// +// IFiniteClosure fc = fcb.getFiniteClosure(); +// +// Set eq = new HashSet(); +// eq.add(new UnifyPair(tphC, tphC, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(tphD, tphD, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(bool, tphPC, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(integer, tphE1, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(tf.getSimpleType("Vector", integer), tf.getSimpleType("Vector", tphE1), PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(integer, tphPD, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(tf.getSimpleType("Vector", integer), tf.getSimpleType("Vector", tphE3), PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(tphPE, bool, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(tphC, integer, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(tphPD, integer, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(tphPE, bool, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(tphE2, tphPF, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(tphC, integer, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(tf.getSimpleType("Vector", integer), tf.getSimpleType("Vector", tphE2), PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(tphPG, doubl, PairOperator.SMALLERDOT)); +// //eq.add(new UnifyPair(integer, doubl, PairOperator.SMALLERDOT)); KEIN WUNDER INFERIERT DAS NICHT +// eq.add(new UnifyPair(tphPF, doubl, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(tphPG, tphD, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(tphD, tphPH, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(voidType, tphB, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(voidType, tphPI, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(tf.getSimpleType("Matrix"), tphPI, PairOperator.SMALLERDOT)); +// eq.add(new UnifyPair(voidType, tphPI, PairOperator.SMALLERDOT)); +// +// Set> expected = new HashSet<>(); +// +// Set> actual = unify(eq, fc); +// +// System.out.println("Test Void:"); +// System.out.println(actual); +// +// //Assert.assertEquals(expected, actual); +// } + + @Test + public void unifyTestLambda6() { +// [(D <. D), +// (R455538610 <. ND), +// (Matrix <. T1455538610), +// (C <. T2455538610), +// (B <. Fun2), +// (ND <. NE), +// (Fun1 <. NC), +// (NC <. NF), +// (Fun1 <. NB), +// (NB <. D), +// (void <. NG), +// (Matrix <. java.lang.Object), +// (void <. void)] + + TypeFactory tf = new TypeFactory(); + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + + UnifyType tphD = tf.getPlaceholderType("D"); + UnifyType tphND = tf.getPlaceholderType("ND"); + UnifyType tphR4 = tf.getPlaceholderType("R4"); + UnifyType tphT1 = tf.getPlaceholderType("T1"); + UnifyType tphT2 = tf.getPlaceholderType("T2"); + UnifyType tphC = tf.getPlaceholderType("C"); + UnifyType tphNE = tf.getPlaceholderType("NE"); + UnifyType tphNC = tf.getPlaceholderType("NC"); + UnifyType tphB = tf.getPlaceholderType("B"); + UnifyType tphNF = tf.getPlaceholderType("NF"); + UnifyType tphNB = tf.getPlaceholderType("NB"); + UnifyType tphNG = tf.getPlaceholderType("NG"); + + UnifyType voidType = tf.getSimpleType("void"); + UnifyType object = tf.getSimpleType("java.lang.Object"); + UnifyType matrix = tf.getSimpleType("java.lang.Matrix"); + + UnifyType r = tf.getPlaceholderType("R"); + UnifyType t1 = tf.getPlaceholderType("T1"); + UnifyType t2 = tf.getPlaceholderType("T2"); + UnifyType fun1 = FunNType.getFunNType(new TypeParams(r, t1)); + UnifyType fun2 = FunNType.getFunNType(new TypeParams(r, t1, t2)); + + fcb.add(matrix, object); + fcb.add(voidType, voidType); + + IFiniteClosure fc = fcb.getFiniteClosure(); + + Set eq = new HashSet(); + eq.add(new UnifyPair(tphD, tphD, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tphR4, tphND, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(matrix, tphT1, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tphC, tphT2, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tphB, FunNType.getFunNType(new TypeParams(tphR4, tphT1, tphT2)), PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tphND, tphNE, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(FunNType.getFunNType(new TypeParams(tphNE, tphB)), tphNC, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tphNC, tphNF, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(FunNType.getFunNType(new TypeParams(tphNF, tphC)), tphNB, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tphNB, tphD, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(voidType, tphNG, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(matrix, object, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(voidType, voidType, PairOperator.SMALLERDOT)); + + Set> expected = new HashSet<>(); + + Set> actual = new TypeUnify().unifySequential(eq, fc); + + System.out.println("Test Lambda6:"); + System.out.println(actual); + + //Assert.assertEquals(expected, actual); + } + + @Test + public void unifyTestVector(){ + /* + * Vector < T1 + * T1 < Vector + */ + TypeFactory tf = new TypeFactory(); + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + + UnifyType tphT1 = tf.getPlaceholderType("T1"); + UnifyType tphT2 = tf.getPlaceholderType("T2"); + + UnifyType gtv = tf.getSimpleType("gtv"); + UnifyType vector = tf.getSimpleType("Vector", gtv); + UnifyType vectorT2 = tf.getSimpleType("Vector", tphT2); + + UnifyType string = tf.getSimpleType("String"); + UnifyType vectorString = tf.getSimpleType("Vector", string); + + fcb.add(vector, tf.getSimpleType("java.lang.Object")); + + IFiniteClosure fc = fcb.getFiniteClosure(); + + Set eq = new HashSet(); + eq.add(new UnifyPair(vectorT2, tphT1, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tphT1, vectorString, PairOperator.SMALLERDOT)); + + Set> actual = new TypeUnify().unifySequential(eq, fc); + + System.out.println("Test OverloadingVector:"); + System.out.println(actual + "\n"); + } + + @Test + public void unifyTestOverloading(){ + /* + * Constraints Set mit "void" Typen + * OL < T1 + * T1 < T1 + * T1 < T2 + * T1 < OL + */ + TypeFactory tf = new TypeFactory(); + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + + UnifyType tphT1 = tf.getPlaceholderType("T1"); + UnifyType tphT2 = tf.getPlaceholderType("T2"); + + UnifyType integer = tf.getSimpleType("java.lang.Integer"); + UnifyType voidType = tf.getSimpleType("void"); + UnifyType bool = tf.getSimpleType("java.lang.Boolean"); + UnifyType object = tf.getSimpleType("Object"); + UnifyType main = tf.getSimpleType("Main"); + UnifyType ol = tf.getSimpleType("OL"); + + fcb.add(integer, object); + fcb.add(main, object); + fcb.add(bool, object); + fcb.add(voidType, voidType); + fcb.add(ol, object); + + IFiniteClosure fc = fcb.getFiniteClosure(); + + Set eq = new HashSet(); + eq.add(new UnifyPair(ol, tphT1, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tphT1, tphT1, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tphT1, tphT2, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tphT1, ol, PairOperator.SMALLERDOT)); + + Set expectedSolution = new HashSet(); + expectedSolution.add(new UnifyPair(tphT1, ol, PairOperator.EQUALSDOT)); + + + Set> actual = new TypeUnify().unifySequential(eq, fc); + + System.out.println("Test Overloading:"); + System.out.println(actual); + + for(Set actualSolution : actual){ + Assert.assertTrue(actualSolution.containsAll(expectedSolution)); + } + } + + @Test + public void unifyTestSubclasses() { + /* + * TPH1 < Integer + * Integer < Integer + * TPH1 < TPH2 + * TPH2 < Integer + * + * Einzige korrekte Lösung: + * TPH1 = Integer, TPH2 = Integer + */ + TypeFactory tf = new TypeFactory(); + FiniteClosureBuilder fcb = new FiniteClosureBuilder(); + + UnifyType tphT1 = tf.getPlaceholderType("T1"); + UnifyType tphT2 = tf.getPlaceholderType("T2"); + UnifyType tphT3 = tf.getPlaceholderType("T3"); + + UnifyType integer = tf.getSimpleType("java.lang.Integer"); + UnifyType bool = tf.getSimpleType("java.lang.Boolean"); + UnifyType object = tf.getSimpleType("java.lang.Object"); + UnifyType main = tf.getSimpleType("Main"); + + fcb.add(integer, object); + fcb.add(main, object); + fcb.add(bool, object); + + IFiniteClosure fc = fcb.getFiniteClosure(); + + Set eq = new HashSet(); + eq.add(new UnifyPair(tphT1, integer, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(integer, integer, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tphT1, tphT2, PairOperator.SMALLERDOT)); + eq.add(new UnifyPair(tphT2, integer, PairOperator.SMALLERDOT)); + + Set> expected = new HashSet<>(); + Set solution = new HashSet(); + solution.add(new UnifyPair(tphT1, integer, PairOperator.EQUALSDOT)); + solution.add(new UnifyPair(tphT2, integer, PairOperator.EQUALSDOT)); + expected.add(solution); + + Set> actual = new TypeUnify().unifySequential(eq, fc); + + System.out.println("Test Subclass:"); + System.out.println(actual); + + Assert.assertEquals(expected, actual); + } + + @Test + public void applyTypeUnificationRulesTest() { + + } + + @Test + public void calculatePairSetsTest() { + + } + +// @Test +// public void permuteParamsTest() { +// TypeFactory tf = new TypeFactory(); +// ArrayList> candidates = new ArrayList<>(); +// +// UnifyType p11 = tf.getPlaceholderType("p11"); +// UnifyType p12 = tf.getExtendsType(tf.getSimpleType("p12")); +// UnifyType p13 = tf.getSimpleType("p13"); +// UnifyType p21 = tf.getPlaceholderType("p21"); +// UnifyType p22 = tf.getPlaceholderType("p22"); +// UnifyType p31 = tf.getSimpleType("p31", "T"); +// +// Set p1 = new HashSet<>(); +// p1.add(p11); +// p1.add(p12); +// p1.add(p13); +// +// Set p2 = new HashSet<>(); +// p2.add(p21); +// p2.add(p22); +// +// Set p3 = new HashSet<>(); +// p3.add(p31); +// +// candidates.add(p1); +// candidates.add(p2); +// candidates.add(p3); +// +// +// /* +// * Expected Result: +// * { | x in { p11, p12, p13}, y in { p21, p22 }, z in { p31 }} +// */ +// Set expected = Arrays.stream(new TypeParams[] { +// new TypeParams(p11, p21, p31), +// new TypeParams(p11, p22, p31), +// new TypeParams(p12, p21, p31), +// new TypeParams(p12, p22, p31), +// new TypeParams(p13, p21, p31), +// new TypeParams(p13, p22, p31) +// }).collect(Collectors.toSet()); +// +// Set actual = permuteParams(candidates); +// +// Assert.assertEquals(expected, actual); +// } + + private Set> filterGeneratedTPHsMultiple(Set> set) { + return set.stream().map(x -> filterGeneratedTPHs(x)).collect(Collectors.toSet()); + } + + private Set filterGeneratedTPHs(Set set) { + return set.stream().filter(x -> !((x.getRhsType() instanceof PlaceholderType) && ((PlaceholderType) x.getRhsType()).isGenerated())). + filter(x -> !((x.getLhsType() instanceof PlaceholderType) && ((PlaceholderType) x.getLhsType()).isGenerated())).collect(Collectors.toSet()); + } + + private void addAsSet(Set> addTo, UnifyPair... mPairs) { + addTo.add(new HashSet<>(Arrays.stream(mPairs).collect(Collectors.toSet()))); + } +} diff --git a/test/unify/UnifyTypeFactoryTest.java b/test/unify/UnifyTypeFactoryTest.java new file mode 100644 index 000000000..a7f984b8c --- /dev/null +++ b/test/unify/UnifyTypeFactoryTest.java @@ -0,0 +1,155 @@ +package unify; + +import static org.junit.Assert.*; + +import java.util.Set; + +import org.junit.Test; + +import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.FunN; +import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.ConstraintsSet; +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.unify.model.UnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; + + +public class UnifyTypeFactoryTest { + private static TypeFactory tf = new TypeFactory(); + + @Test + public void convertUnifyTypes(){ + //UnifyType ut = + } + + @Test + public void convertConstraintSet(){ + ConstraintsSet cons = new ConstraintsSet(); + OderConstraint oCons = new OderConstraint(); + UndConstraint uCons = new UndConstraint(); + uCons.addConstraint(getSimpleRefType(), getSimpleRefType()); + oCons.addConstraint(uCons); + oCons.addConstraint(ConstraintsSet.createSingleConstraint(getPair())); + cons.add(oCons); + + checkConvertConstraintsSet(cons); + } + + @Test + public void convertMPair() { + UnifyPair mp1 = getSimpleMPair(); + checkConvertMPair(mp1); + + TypePlaceholder tph1 = TypePlaceholder.fresh(new NullSyntaxTreeNode()); + TypePlaceholder tph2 = TypePlaceholder.fresh(new NullSyntaxTreeNode()); + + UnifyPair mp2 = new UnifyPair(getSimpleType(), tf.getPlaceholderType(tph1.getName().toString()), PairOperator.SMALLERDOT); + checkConvertMPair(mp2); + + UnifyPair mp3 = new UnifyPair(tf.getSuperType(getSimpleType()), getSimpleType(), PairOperator.SMALLERDOT); + checkConvertMPair(mp3); + + UnifyPair mp4 = new UnifyPair(tf.getPlaceholderType(tph2.getName().toString()), tf.getPlaceholderType(tph1.getName().toString()), PairOperator.SMALLERDOT); + checkConvertMPair(mp4); + + ReferenceType typeWithParams = tf.getSimpleType("Test", getSimpleType()); + ReferenceType typeWithTPHParams = tf.getSimpleType("Test", tf.getPlaceholderType("Test")); + UnifyPair mp5 = new UnifyPair(typeWithTPHParams, typeWithParams, PairOperator.SMALLERDOT); + checkConvertMPair(mp5); + } + + @Test + public void convertPair(){ + TypePlaceholder tph1 = TypePlaceholder.fresh(new NullSyntaxTreeNode()); + TypePlaceholder tph2 = TypePlaceholder.fresh(new NullSyntaxTreeNode()); + + Pair p1 = new Pair(getSimpleRefType(), getSimpleRefType()); + checkConvertPair(p1); + + Pair p2 = new Pair(tph1, tph2); + checkConvertPair(p1); + + ExtendsWildcardType ext = new ExtendsWildcardType(getSimpleRefType()); + SuperWildcardType sup = new SuperWildcardType(getSimpleRefType()); + Pair p3 = new Pair(ext, sup); + checkConvertPair(p1); + + GenericTypeVar gt = new GenericTypeVar("A", new NullSyntaxTreeNode(), 0); + de.dhbwstuttgart.syntaxtree.type.Void voidType = new de.dhbwstuttgart.syntaxtree.type.Void(new NullSyntaxTreeNode(), 0); + Pair p4 = new Pair(gt, voidType); + checkConvertPair(p1); + + Pair p5 = new Pair(new FunN(getSimpleRefType(), new Menge<>()), tph1); + checkConvertPair(p5); + } + + // Hilfsfunktionen: + + private static void checkConvertConstraintsSet(ConstraintsSet cons){ + Set> check = cons.cartesianProduct(); + + UnifyConstraintsSet converted = UnifyTypeFactory.convert(cons); + Set> cartesianProductOfConverted = converted.cartesianProduct(); + + assertTrue(cartesianProductOfConverted.size()==check.size()); + assertTrue(cartesianProductOfConverted.iterator().next().size()==check.iterator().next().size()); + + Set> controlSet = new Menge<>(); + for(Set pairs : cartesianProductOfConverted){ + Set tmpSet = new Menge<>(); + for(UnifyPair mp : pairs){ + Pair p = checkConvertMPair(mp); + tmpSet.add(p); + } + controlSet.add(tmpSet); + } + assertTrue(controlSet.equals(check)); + } + + private static UnifyPair checkConvertPair(Pair p){ + System.out.println("Checking Pair: "+p); + UnifyPair mp = UnifyTypeFactory.convert(p); + assertTrue(p.TA1.get_Name().equals(mp.getLhsType().getName())); + assertTrue(p.TA2.get_Name().equals(mp.getRhsType().getName())); + return mp; + } + + private static Pair checkConvertMPair(UnifyPair mp){ + System.out.println("Checking Pair: "+mp); + Pair p = UnifyTypeFactory.convert(mp); + assertTrue(p.TA1.get_Name().equals(mp.getLhsType().getName())); + assertTrue(p.TA2.get_Name().equals(mp.getRhsType().getName())); + return p; + } + + private static ReferenceType getSimpleType(){ + return tf.getSimpleType("String"); + } + + private static UnifyPair getSimpleMPair(){ + UnifyType lt = tf.getSimpleType("String"); + UnifyType rt = tf.getSimpleType("String"); + UnifyPair ret = new UnifyPair(lt, rt, PairOperator.SMALLERDOT); + return ret; + } + + private static Pair getPair(){ + return new Pair(getSimpleRefType(),getSimpleRefType()); + } + + private static RefType getSimpleRefType(){ + NullSyntaxTreeNode nullNode = new NullSyntaxTreeNode(); + return new RefType("java.lang.String",nullNode,nullNode.getOffset()); + } +}