diff --git a/pom.xml b/pom.xml index 6b0f2fba5..9cce2d998 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,11 @@ antlr4 4.7 + + commons-io + commons-io + 2.6 + com.google.guava guava diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java index 425582ad2..f1994c204 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -1,6 +1,5 @@ package de.dhbwstuttgart.bytecode; -import java.awt.List; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -10,6 +9,9 @@ import org.objectweb.asm.ClassWriter; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.signature.SignatureVisitor; +import org.objectweb.asm.signature.SignatureWriter; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.syntaxtree.*; @@ -18,37 +20,54 @@ import de.dhbwstuttgart.syntaxtree.statement.literal.Null; import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.result.ResultSet; public class BytecodeGen implements ASTVisitor { ClassWriter cw =new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS); -// String methDesc; String type; String className; + private boolean isInterface; + private ResultSet resultSet; + private int indexOfFirstParam = 0; // stores parameter, local vars and the next index on the local variable table, which use for aload_i, astore_i,... - HashMap paramsAndLocals;// = new HashMap<>(); + HashMap paramsAndLocals = new HashMap<>(); + // stores generics and their bounds of class + HashMap genericsAndBounds = new HashMap<>(); + // stores generics and their bounds of method + HashMap genericsAndBoundsMethod = new HashMap<>(); + + HashMap methodParamsAndTypes = new HashMap<>(); byte[] bytecode; HashMap classFiles; - public BytecodeGen(HashMap classFiles) { + public BytecodeGen(HashMap classFiles, ResultSet resultSet) { this.classFiles = classFiles; - paramsAndLocals = new HashMap<>(); + this.resultSet = resultSet; } @Override public void visit(SourceFile sourceFile) { for(ClassOrInterface cl : sourceFile.getClasses()) { - BytecodeGen classGen = new BytecodeGen(classFiles); + BytecodeGen classGen = new BytecodeGen(classFiles, resultSet); cl.accept(classGen); + System.out.println("In CLASS: "+(cl.getClassName().toString())); classGen.writeClass(cl.getClassName().toString()); } } - + + /** + * Associates the bytecode of the class that was build with the classWriter {@link #cw} + * with the class name in the map {@link #classFiles} + * + * @param name name of the class with which the the bytecode is to be associated + */ private void writeClass(String name) { bytecode = cw.toByteArray(); classFiles.put(name, bytecode); @@ -58,12 +77,30 @@ public class BytecodeGen implements ASTVisitor { public HashMap getClassFiles() { return classFiles; } + + @Override public void visit(ClassOrInterface classOrInterface) { className = classOrInterface.getClassName().toString(); - // access flages?? - cw.visit(Opcodes.V1_8, classOrInterface.getModifiers()+Opcodes.ACC_SUPER, classOrInterface.getClassName().toString() - , null, classOrInterface.getSuperClass().toString(), null); + + isInterface = (classOrInterface.getModifiers()&512)==512; + System.out.println("IS Interface = "+"modifiers= "+classOrInterface.getModifiers()+" ->"+(classOrInterface.getModifiers()&512) + isInterface); + + int acc = isInterface?classOrInterface.getModifiers()+Opcodes.ACC_ABSTRACT:classOrInterface.getModifiers()+Opcodes.ACC_SUPER; + String sig = null; + /* if class has generics then creates signature + * Signature looks like: + * Superclass + */ + if(classOrInterface.getGenerics().iterator().hasNext()) { + Signature signature = new Signature(classOrInterface, genericsAndBounds); + + System.out.println(signature.toString()); + sig = signature.toString(); + } + // needs implemented Interfaces? + cw.visit(Opcodes.V1_8, acc, classOrInterface.getClassName().toString() + , sig, classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()), null); // for each field in the class for(Field f : classOrInterface.getFieldDecl()) { @@ -81,40 +118,100 @@ public class BytecodeGen implements ASTVisitor { } cw.visitSource(classOrInterface.getClassName().toString()+".jav", null); } - + @Override public void visit(Constructor field) { - Descriptor desc = new Descriptor(field); - MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", desc.getDesc(), null, null); + field.getParameterList().accept(this); + + String desc = null; + boolean hasGen = false; + for(String paramName : methodParamsAndTypes.keySet()) { + genericsAndBounds.containsKey(paramName); + hasGen = true; + } + String sig = null; + if(hasGen) { + System.out.println("IM IN CONST HAS Gens"); + Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes); + sig = signature.toString(); + System.out.println(sig); + } + NormalConstructor constructor = new NormalConstructor(field,genericsAndBounds,hasGen); + desc = constructor.accept(new DescriptorToString(resultSet)); + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", desc, sig, null); mv.visitCode(); System.out.println("-----Constructor-----"); - BytecodeGenMethod gen = new BytecodeGenMethod(className,field, mv,paramsAndLocals,desc.getDesc(),cw); - - mv.visitInsn(Opcodes.RETURN); + BytecodeGenMethod gen = new BytecodeGenMethod(className,resultSet,field, mv,paramsAndLocals,cw, + genericsAndBoundsMethod,genericsAndBounds,isInterface); + if(!field.getParameterList().iterator().hasNext()) { + mv.visitInsn(Opcodes.RETURN); + } mv.visitMaxs(0, 0); mv.visitEnd(); } @Override public void visit(Method method) { + // TODO: check if the method is static => if static then the first param will be stored in pos 0 + // else it will be stored in pos 1 and this will be stored in pos 0 method.getParameterList().accept(this); - Descriptor methDesc = new Descriptor(method); + + String methDesc = null; + + // Method getModifiers() ? + int acc = isInterface?Opcodes.ACC_ABSTRACT:0; + System.out.println("-----Method-----"); - MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, method.getName(), methDesc.getDesc(), null, null); + + boolean hasGenInParameterList = genericsAndBounds.containsKey(method.getReturnType().acceptTV(new TypeToDescriptor())); + if(!hasGenInParameterList) { + for(String paramName : methodParamsAndTypes.keySet()) { + if(genericsAndBounds.containsKey(paramName)) { + hasGenInParameterList = true; + break; + } + } + } + String sig = null; + boolean hasGen = method.getGenerics().iterator().hasNext() || hasGenInParameterList; + // Wenn ReturnType has Generics?? Fun1<...> wie testet man das generic hat?? + System.out.println(method.getReturnType().acceptTV(new TypeToString())); +// if(method.getReturnType().acceptTV(new TypeToString()).equals("TPH")) { +// Signature signature = new Signature(method, genericsAndBoundsMethod, methodParamsAndTypes,resultSet); +// sig = signature.toString(); +// System.out.println(sig); +// } + /* if method has generics, create signature */ + if(hasGen) { + // resultset hier zum testen + Signature signature = new Signature(method, genericsAndBoundsMethod, methodParamsAndTypes,resultSet); + sig = signature.toString(); + System.out.println(sig); + + } + + NormalMethod meth = new NormalMethod(method,genericsAndBounds,genericsAndBoundsMethod,hasGen); + methDesc = meth.accept(new DescriptorToString(resultSet)); + System.out.println("methDesc" + methDesc); + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC+acc, method.getName(), methDesc, sig, null); + mv.visitCode(); - BytecodeGenMethod gen = new BytecodeGenMethod(className,method, mv,paramsAndLocals,methDesc.getDesc(),cw); + BytecodeGenMethod gen = new BytecodeGenMethod(className,resultSet,method, mv,paramsAndLocals,cw,genericsAndBounds,genericsAndBounds,isInterface); mv.visitMaxs(0, 0); mv.visitEnd(); } @Override public void visit(ParameterList formalParameters) { + paramsAndLocals = new HashMap<>(); + methodParamsAndTypes = new HashMap<>(); Iterator itr = formalParameters.iterator(); int i = 1; while(itr.hasNext()) { FormalParameter fp = itr.next(); paramsAndLocals.put(fp.getName(), i); + methodParamsAndTypes.put(fp.getName(), fp.getType()); fp.accept(this); i++; } diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index d92ebfc36..5368cf936 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -1,12 +1,12 @@ package de.dhbwstuttgart.bytecode; -import java.io.PrintStream; import java.lang.invoke.CallSite; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import java.security.GeneralSecurityException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import de.dhbwstuttgart.syntaxtree.statement.*; import org.objectweb.asm.ClassWriter; @@ -16,60 +16,95 @@ import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.FormalParameter; import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.statement.literal.Literal; import de.dhbwstuttgart.syntaxtree.statement.literal.Null; +import de.dhbwstuttgart.syntaxtree.type.FunN; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.result.ResultSet; public class BytecodeGenMethod implements StatementVisitor{ private Method m; private MethodVisitor mv; private HashMap paramsAndLocals = new HashMap<>(); - private String desc; private String className; private int lamCounter; private ClassWriter cw; + private ResultSet resultSet; + private boolean isInterface; + HashMap genericsAndBoundsMethod; + private HashMap genericsAndBounds; //for tests ** private String fieldName; private String fieldDesc; private Expression rightSideTemp; private String where; + private boolean isRightSideALambda = false; + private KindOfLambda kindOfLambda; - public BytecodeGenMethod(String className, Method m, MethodVisitor mv, HashMap paramsAndLocals, - String desc, ClassWriter cw) { + private ArrayList varsFunInterface; + + public BytecodeGenMethod(String className,ResultSet resultSet, Method m, MethodVisitor mv, + HashMap paramsAndLocals, ClassWriter cw, + HashMap genericsAndBoundsMethod, HashMap genericsAndBounds, boolean isInterface) { - this.where = "NORMAL METHOD"; + this.where = "<<<<<< NORMAL METHOD >>>>>>"; this.className = className; + this.resultSet = resultSet; this.m = m; this.mv = mv; this.paramsAndLocals = paramsAndLocals; - this.desc = desc; this.cw = cw; + this.genericsAndBoundsMethod = genericsAndBoundsMethod; + this.genericsAndBounds = genericsAndBounds; + this.isInterface = isInterface; this.lamCounter = -1; - this.m.block.accept(this); + this.varsFunInterface = new ArrayList<>(); + System.out.println("PARAMS = "+this.paramsAndLocals.size()); + + if(!isInterface) + this.m.block.accept(this); + +// System.out.println("PARAMS = "+this.paramsAndLocals.size()); +// for(int i = 0; i paramsAndLocals, String desc) { - System.out.println("++++++IN LAMBDA -------"); - - this.where = "&&&&&&&& LAMBDA METHOD"; + public BytecodeGenMethod(LambdaExpression lambdaExpression,ResultSet resultSet ,MethodVisitor mv, + int indexOfFirstParamLam, boolean isInterface) { + System.out.println("\t\t++++++IN LAMBDA -------"); + this.where = "<<<<<< LAMBDA METHOD >>>>>>"; + this.resultSet = resultSet; this.mv = mv; - this.paramsAndLocals = paramsAndLocals; - this.desc = desc; - + this.isInterface = isInterface; this.lamCounter = -1; - + this.varsFunInterface = new ArrayList<>(); + + Iterator itr = lambdaExpression.params.iterator(); + int i = indexOfFirstParamLam; + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + this.paramsAndLocals.put(fp.getName(), i); + i++; + } lambdaExpression.methodBody.accept(this); } + private String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { +// return resultSet.resolveType(type).resolvedType.toString().replace(".", "/"); + return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor()); + } + + @Override public void visit(Block block) { for(Statement stmt : block.getStatements()) { @@ -85,26 +120,35 @@ public class BytecodeGenMethod implements StatementVisitor{ superCall.receiver.accept(this); superCall.arglist.accept(this); // mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", superCall.name, desc,false); - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), superCall.name, desc,false); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), superCall.name, "()V",isInterface); } // ?? @Override public void visit(LocalVar localVar) { - System.out.println("in Local Var"); + System.out.println("in Local Var: " + localVar.name); + mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name)); } // ?? @Override public void visit(LocalVarDecl localVarDecl) { // Integer i; - paramsAndLocals.put(localVarDecl.getName(), paramsAndLocals.size()+1); - System.out.println("In localVarDecl"); +// paramsAndLocals.put(localVarDecl.getName(), paramsAndLocals.size()+1); + System.out.println("In localVarDecl :: "+localVarDecl.getName()); } @Override public void visit(Assign assign) { System.out.println("Assign : \nright = "+assign.rightSide + "\nLeft = " + assign.lefSide); + // if the right side is a lambda => the left side must be a functional interface + if(assign.rightSide.getClass().equals(LambdaExpression.class)) { + isRightSideALambda = true; + }else { + isRightSideALambda = false; + } + + System.out.println("\t isRight Side lambda: " + isRightSideALambda); if(assign.lefSide.getClass().equals(AssignToField.class)) { // load_0, ldc or .. then putfield this.rightSideTemp = assign.rightSide; @@ -113,44 +157,71 @@ public class BytecodeGenMethod implements StatementVisitor{ assign.rightSide.accept(this); assign.lefSide.accept(this); } - - - } @Override public void visit(Binary binary) { - System.out.println("++ In Binary: "); + System.out.println("\t++ In Binary: "); } @Override public void visit(LambdaExpression lambdaExpression) { System.out.println("\n++ In Lambda: "); this.lamCounter++; + + System.out.println("Lam Hs Gens: " + lambdaExpression.getGenerics().iterator().hasNext()); + System.out.println("Lam Hs Gens: " + lambdaExpression.getReturnType().acceptTV(new TypeToString())); + Lambda lam = new Lambda(lambdaExpression); + String lamDesc = lam.accept(new DescriptorToString(resultSet)); //Call site, which, when invoked, returns an instance of the functional interface to which //the lambda is being converted MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class); + Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", mt.toMethodDescriptorString(), false); String methodName = "lambda$new$" + this.lamCounter; +// String typeErasure = "(Ljava/lang/Object;)Ljava/lang/Object;"; // Type erasure - Type arg1 = Type.getMethodType("()V"); +// Type arg1 = Type.getMethodType(typeErasure); + Type arg1 = Type.getMethodType(lamDesc); // real Type - Type arg3 = Type.getMethodType("()V"); - Handle arg2 = new Handle(Opcodes.H_INVOKESTATIC, this.className, methodName, - arg3.toString(),false); - mv.visitInvokeDynamicInsn("run", "()Ljava/lang/Runnable;", bootstrap, - arg1, arg2,arg3); - - MethodVisitor mvLambdaBody = cw.visitMethod(Opcodes.ACC_PRIVATE+ Opcodes.ACC_STATIC + Opcodes.ACC_SYNTHETIC, - methodName, arg3.toString(), null, null); -// new BytecodeGenLambda(lambdaExpression, mvLambdaBody); + Type arg3 = Type.getMethodType(lamDesc); + + int staticOrSpecial=0; + int staticOrInstance=0; + int indexOfFirstParamLam = 0; + this.kindOfLambda = new KindOfLambda(lambdaExpression); + + if(kindOfLambda.isInstanceCapturingLambda()) { + mv.visitVarInsn(Opcodes.ALOAD, 0); + staticOrSpecial = Opcodes.H_INVOKESPECIAL; + indexOfFirstParamLam = 1; + }else { + staticOrSpecial = Opcodes.H_INVOKESTATIC; + staticOrInstance = Opcodes.ACC_STATIC; + } + + // first check if capturing lambda then invokestatic or invokespecial + Handle arg2 = new Handle(staticOrSpecial, this.className, methodName, + arg3.toString(),false); + // Descriptor of functional interface methode + SamMethod samMethod = new SamMethod(kindOfLambda.getArgumentList(), lambdaExpression.getType()); + // Desc: (this/nothing)TargetType + String fiMethodDesc = samMethod.accept(new DescriptorToString(resultSet)); + mv.visitInvokeDynamicInsn("apply", fiMethodDesc, bootstrap, + arg1, arg2,arg3); + + MethodVisitor mvLambdaBody = cw.visitMethod(Opcodes.ACC_PRIVATE+ staticOrInstance + Opcodes.ACC_SYNTHETIC, + methodName, arg3.toString(), null, null); + + new BytecodeGenMethod(lambdaExpression,this.resultSet,mvLambdaBody,indexOfFirstParamLam,isInterface); - new BytecodeGenMethod(lambdaExpression, mvLambdaBody, new HashMap<>(), arg3.toString()); mvLambdaBody.visitMaxs(0, 0); mvLambdaBody.visitEnd(); + cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup", "java/lang/invoke/MethodHandles", "Lookup", + Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL); } @Override @@ -170,12 +241,13 @@ public class BytecodeGenMethod implements StatementVisitor{ System.out.println("in fieldVar " + fieldVar.fieldVarName + " ** receiver: "+fieldVar.receiver); fieldName = fieldVar.fieldVarName; - fieldDesc = fieldVar.getType().toString(); + fieldDesc = "L"+getResolvedType(fieldVar.getType())+";"; fieldVar.receiver.accept(this); // test (if) if(!fieldVar.receiver.getClass().equals(StaticClassName.class)) { - mv.visitFieldInsn(Opcodes.GETFIELD,fieldVar.getType().toString(),fieldName ,fieldDesc); + mv.visitFieldInsn(Opcodes.GETFIELD,getResolvedType(fieldVar.receiver.getType()), + fieldName ,fieldDesc); } // mv.visitFieldInsn(Opcodes.GETSTATIC, fieldVar.receiver.getType().toString().replace(".", "/"), @@ -202,7 +274,7 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(MethodCall methodCall) { System.out.println(" In Methodcall: (" +methodCall.name+")" ); - System.out.print(" Method-Receiver: "); + System.out.print("\t\tMethod-Receiver: "); if(methodCall.receiver instanceof ExpressionReceiver){ System.out.print(((ExpressionReceiver) methodCall.receiver).expr + "\n"); }else{ @@ -212,20 +284,31 @@ public class BytecodeGenMethod implements StatementVisitor{ methodCall.receiver.accept(this); methodCall.arglist.accept(this); - Descriptor mDesc = new Descriptor(methodCall.arglist, methodCall.getType()); + MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), + genericsAndBoundsMethod,genericsAndBounds); + String mDesc = method.accept(new DescriptorToString(resultSet)); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, methodCall.receiver.getType().toString(), - methodCall.name, mDesc.getDesc(), false); - // test - if(!methodCall.getType().toString().equals("V")) { - mv.visitInsn(Opcodes.POP); + System.out.println("is Vars empty: "+varsFunInterface.isEmpty()); + + // is methodCall.receiver functional Interface)? + if(varsFunInterface.contains(methodCall.receiver.getType())) { + mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()), + methodCall.name, mDesc, false); + }else { + System.out.println("mDesc = " + mDesc); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, getResolvedType(methodCall.receiver.getType()), + methodCall.name, mDesc, isInterface); } + // test +// if(!methodCall.getType().toString().equals("V")) { +// mv.visitInsn(Opcodes.POP); +// } } @Override public void visit(NewClass methodCall) { System.out.println("In NewClass: "); - System.out.println("name: " + methodCall.name + " *** " + "Receiver: " + methodCall.receiver); + System.out.println("\t\tname: " + methodCall.name + " *** " + "Receiver: " + methodCall.receiver); mv.visitTypeInsn(Opcodes.NEW, methodCall.name.replace(".", "/")); mv.visitInsn(Opcodes.DUP); @@ -233,11 +316,11 @@ public class BytecodeGenMethod implements StatementVisitor{ methodCall.arglist.accept(this); String d = "("; for(Expression e : methodCall.arglist.getArguments()) { - d = d + "L"+e.getType().toString().replace(".", "/") + ";"; + d = d + "L"+getResolvedType(e.getType()) + ";"; } d += ")V"; - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, methodCall.name.replace(".", "/"), "", d, false); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, methodCall.name.replace(".", "/"), "", d, isInterface); } @Override @@ -255,6 +338,7 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(Return aReturn) { + aReturn.retexpr.accept(this); mv.visitInsn(Opcodes.ARETURN); } @@ -268,7 +352,7 @@ public class BytecodeGenMethod implements StatementVisitor{ System.out.println("In StaticClassName: "); // mv.visitMethodInsn(Opcodes.INVOKESTATIC, staticClassName.getType().toString().replace(".", "/"), // staticClassName.toString(), staticClassName.getType().toString(), false); - mv.visitFieldInsn(Opcodes.GETSTATIC, staticClassName.getType().toString().replace(".", "/"), + mv.visitFieldInsn(Opcodes.GETSTATIC, getResolvedType(staticClassName.getType()), fieldName, fieldDesc); } @@ -308,30 +392,41 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(Literal literal) { // value? - mv.visitLdcInsn(literal.getType().toString()); + mv.visitLdcInsn(getResolvedType(literal.getType())); } @Override public void visit(ArgumentList argumentList) { + System.out.println("in ArgumentList: "); for(Expression al : argumentList.getArguments()) { al.accept(this); } + System.out.println("out from Argumentlist"); } @Override public void visit(AssignToField assignLeftSide) { +// temporäre Lösung für testen, bis ich weiss wie man funktionale +// interfaces erkennt + if(isRightSideALambda) + varsFunInterface.add(assignLeftSide.field.getType()); // Loads the an object reference from the local variable // array slot onto the top of the operand stack. assignLeftSide.field.receiver.accept(this); this.rightSideTemp.accept(this); - mv.visitFieldInsn(Opcodes.PUTFIELD, assignLeftSide.field.receiver.getType().toString(), - assignLeftSide.field.fieldVarName, assignLeftSide.field.getType().toString()); + mv.visitFieldInsn(Opcodes.PUTFIELD, getResolvedType(assignLeftSide.field.receiver.getType()), + assignLeftSide.field.fieldVarName, getResolvedType(assignLeftSide.field.getType())); } @Override public void visit(AssignToLocal assignLeftSide) { + System.out.println("In Assign To Local: "); + if(isRightSideALambda) + varsFunInterface.add(assignLeftSide.localVar.getType()); paramsAndLocals.put(assignLeftSide.localVar.name, paramsAndLocals.size()+1); mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.size()); + // Debug::: + } } diff --git a/src/de/dhbwstuttgart/bytecode/Descriptor.java b/src/de/dhbwstuttgart/bytecode/Descriptor.java deleted file mode 100644 index 41f7ab5db..000000000 --- a/src/de/dhbwstuttgart/bytecode/Descriptor.java +++ /dev/null @@ -1,54 +0,0 @@ -package de.dhbwstuttgart.bytecode; - -import java.awt.List; -import java.util.Iterator; - -import de.dhbwstuttgart.syntaxtree.Constructor; -import de.dhbwstuttgart.syntaxtree.FormalParameter; -import de.dhbwstuttgart.syntaxtree.Method; -import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; -import de.dhbwstuttgart.syntaxtree.statement.Expression; -import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; - -public class Descriptor { - String desc; - - public Descriptor(Method method) { - desc = "("; - Iterator itr = method.getParameterList().iterator(); - while(itr.hasNext()) { - FormalParameter fp = itr.next(); - desc = desc + "L"+fp.getType().toString().replace(".", "/") + ";"; - } - if(method.getReturnType().toString().equals("void")){ - desc = desc + ")V"; - }else { - desc = desc + ")" + "L"+method.getReturnType().toString().replace(".", "/")+";"; - } - - } - - public Descriptor(Constructor constructor) { - desc = "("; - Iterator itr = constructor.getParameterList().iterator(); - while(itr.hasNext()) { - FormalParameter fp = itr.next(); - desc = desc + "L"+fp.getType().toString().replace(".", "/") + ";"; - } - desc = desc + ")V"; - } - - public Descriptor(ArgumentList argList, RefTypeOrTPHOrWildcardOrGeneric returnType) { - desc = "("; - for(Expression e : argList.getArguments()) { - desc = desc + "L"+e.getType().toString().replace(".", "/") + ";"; - } - desc = desc + ")"+returnType.toString(); - - } - - public String getDesc() { - return this.desc; - } - -} diff --git a/src/de/dhbwstuttgart/bytecode/DescriptorToString.java b/src/de/dhbwstuttgart/bytecode/DescriptorToString.java new file mode 100644 index 000000000..481dbc5de --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/DescriptorToString.java @@ -0,0 +1,146 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.Iterator; + +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +public class DescriptorToString implements DescriptorVisitor{ + ResultSet resultSet; + + public DescriptorToString(ResultSet resultSet) { + this.resultSet = resultSet; + } + + private String addReturnType(String desc, RefTypeOrTPHOrWildcardOrGeneric returnType, ResultSet resultSet) { + if(resultSet.resolveType(returnType).resolvedType.toString().equals("void")){ + desc = desc + ")V"; + }else { + desc = desc + ")" + "L"+resultSet.resolveType(returnType).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + return desc; + } + + @Override + public String visit(NormalMethod method) { + + String desc = "("; + Iterator itr = method.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + if(method.hasGen()) { + String fpDesc = fp.getType().acceptTV(new TypeToDescriptor()); + if(method.getGenericsAndBoundsMethod().containsKey(fpDesc)) { + desc += "L"+method.getGenericsAndBoundsMethod().get(fpDesc)+ ";"; + }else if(method.getGenericsAndBounds().containsKey(fpDesc)){ + desc += "L"+method.getGenericsAndBounds().get(fpDesc)+ ";"; + }else { + desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + }else { + desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + } + + if(resultSet.resolveType(method.getReturnType()).resolvedType.toString().equals("void")) { + desc += ")V"; + }else { + if(method.hasGen()) { + String ret = method.getReturnType().acceptTV(new TypeToDescriptor()); + if(method.getGenericsAndBoundsMethod().containsKey(ret)) { + desc += ")L"+method.getGenericsAndBoundsMethod().get(ret)+ ";"; + }else if(method.getGenericsAndBounds().containsKey(ret)){ + desc += ")L"+method.getGenericsAndBounds().get(ret)+ ";"; + }else { + desc += ")" + "L"+resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + }else { + desc += ")" + "L"+resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + } +// desc = addReturnType(desc,method.getReturnType(), resultSet); + return desc; + } + + @Override + public String visit(NormalConstructor constructor) { + String desc = "("; + Iterator itr = constructor.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + if(constructor.hasGen()) { + System.out.println("Cons has Gens"); + String fpDesc = fp.getType().acceptTV(new TypeToDescriptor()); + System.out.println(fpDesc); + if(constructor.getGenericsAndBounds().containsKey(fpDesc)){ + desc += "L"+constructor.getGenericsAndBounds().get(fpDesc)+ ";"; + }else { + desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + }else { + System.out.println("Cons has NOT Gens"); + desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + } + desc = desc + ")V"; + return desc; + } + + @Override + public String visit(Lambda lambdaExpression) { + String desc = "("; + Iterator itr = lambdaExpression.getParams().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + desc = desc + "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()) + ";"; + } + System.out.println("LamReturnType: "+lambdaExpression.getReturnType().acceptTV(new TypeToString())); + desc = addReturnType(desc, lambdaExpression.getReturnType(), resultSet); + return desc; + } + + @Override + public String visit(SamMethod samMethod) { + String desc = "("; + Iterator itr = samMethod.getArgumentList().iterator(); + while(itr.hasNext()) { + RefTypeOrTPHOrWildcardOrGeneric rt = itr.next(); + desc = desc + "L"+resultSet.resolveType(rt).resolvedType.acceptTV(new TypeToDescriptor())+";"; + } + desc = desc + ")"+"L"+resultSet.resolveType(samMethod.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+";"; + return desc; + } + + @Override + public String visit(MethodFromMethodCall methodFromMethodCall) { + String desc = "("; + for(Expression e : methodFromMethodCall.getArgList().getArguments()) { + String d = e.getType().acceptTV(new TypeToDescriptor()); + if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(d)) { + desc += "L"+methodFromMethodCall.getGenericsAndBoundsMethod().get(d)+ ";"; + }else if(methodFromMethodCall.getGenericsAndBounds().containsKey(d)) { + desc += "L"+methodFromMethodCall.getGenericsAndBounds().get(d)+ ";"; + }else { + desc += "L"+resultSet.resolveType(e.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + } + + if(resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.toString().equals("void")) { + desc += ")V"; + }else { + String ret = resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); + if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(ret)) { + desc += ")L"+methodFromMethodCall.getGenericsAndBoundsMethod().get(ret)+ ";"; + }else if(methodFromMethodCall.getGenericsAndBounds().containsKey(ret)){ + desc += ")L"+methodFromMethodCall.getGenericsAndBounds().get(ret)+ ";"; + }else { + desc += ")" + "L"+resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + } +// desc = addReturnType(desc, methodFromMethodCall.getReturnType(), resultSet); + return desc; + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/DescriptorVisitor.java b/src/de/dhbwstuttgart/bytecode/DescriptorVisitor.java new file mode 100644 index 000000000..63198828f --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/DescriptorVisitor.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.bytecode; + +public interface DescriptorVisitor { + public String visit(NormalMethod method); + public String visit(NormalConstructor constructor); + public String visit(Lambda lambdaExpression); + public String visit(SamMethod samMethod); + public String visit(MethodFromMethodCall methodFromMethodCall); +} diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenLambda.java b/src/de/dhbwstuttgart/bytecode/KindOfLambda.java similarity index 75% rename from src/de/dhbwstuttgart/bytecode/BytecodeGenLambda.java rename to src/de/dhbwstuttgart/bytecode/KindOfLambda.java index 679a13654..36a28ce6f 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenLambda.java +++ b/src/de/dhbwstuttgart/bytecode/KindOfLambda.java @@ -1,24 +1,33 @@ package de.dhbwstuttgart.bytecode; import de.dhbwstuttgart.syntaxtree.statement.*; -import org.objectweb.asm.MethodVisitor; + +import java.util.ArrayList; +import java.util.List; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.statement.literal.Literal; import de.dhbwstuttgart.syntaxtree.statement.literal.Null; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; -public class BytecodeGenLambda implements StatementVisitor{ - private LambdaExpression lambdaExpression; - private MethodVisitor mv; +public class KindOfLambda implements StatementVisitor{ + private boolean isInstanceCapturingLambda = false; + private List argumentList = new ArrayList<>(); - public BytecodeGenLambda(LambdaExpression lambdaExpression, MethodVisitor mv) { - this.lambdaExpression = lambdaExpression; - this.mv = mv; - + public KindOfLambda(LambdaExpression lambdaExpression) { + lambdaExpression.methodBody.accept(this); } - + + public boolean isInstanceCapturingLambda() { + return this.isInstanceCapturingLambda; + } + + public List getArgumentList() { + return argumentList; + } + @Override public void visit(ArgumentList argumentList) { // TODO Auto-generated method stub @@ -27,14 +36,12 @@ public class BytecodeGenLambda implements StatementVisitor{ @Override public void visit(LambdaExpression lambdaExpression) { - // TODO Auto-generated method stub } @Override public void visit(Assign assign) { - // TODO Auto-generated method stub - + assign.rightSide.accept(this); } @Override @@ -45,8 +52,9 @@ public class BytecodeGenLambda implements StatementVisitor{ @Override public void visit(Block block) { - // TODO Auto-generated method stub - + for(Statement stmt : block.getStatements()) { + stmt.accept(this); + } } @Override @@ -63,8 +71,7 @@ public class BytecodeGenLambda implements StatementVisitor{ @Override public void visit(FieldVar fieldVar) { - // TODO Auto-generated method stub - + fieldVar.receiver.accept(this); } @Override @@ -99,8 +106,7 @@ public class BytecodeGenLambda implements StatementVisitor{ @Override public void visit(MethodCall methodCall) { - // TODO Auto-generated method stub - + methodCall.receiver.accept(this); } @Override @@ -117,14 +123,12 @@ public class BytecodeGenLambda implements StatementVisitor{ @Override public void visit(ExpressionReceiver receiver) { - // TODO Auto-generated method stub - + receiver.expr.accept(this); } @Override public void visit(Return aReturn) { - // TODO Auto-generated method stub - + aReturn.retexpr.accept(this); } @Override @@ -147,8 +151,8 @@ public class BytecodeGenLambda implements StatementVisitor{ @Override public void visit(This aThis) { - // TODO Auto-generated method stub - + this.isInstanceCapturingLambda = true; + this.argumentList.add(aThis.getType()); } @Override diff --git a/src/de/dhbwstuttgart/bytecode/Lambda.java b/src/de/dhbwstuttgart/bytecode/Lambda.java new file mode 100644 index 000000000..283b73934 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/Lambda.java @@ -0,0 +1,25 @@ +package de.dhbwstuttgart.bytecode; + +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class Lambda { + private LambdaExpression lambdaExpression; + + public Lambda(LambdaExpression lambdaExpression) { + this.lambdaExpression = lambdaExpression; + } + + public ParameterList getParams() { + return lambdaExpression.params; + } + + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return lambdaExpression.getReturnType(); + } + + public String accept(DescriptorVisitor descVisitor) { + return descVisitor.visit(this); + } +} diff --git a/src/de/dhbwstuttgart/bytecode/MethodFromMethodCall.java b/src/de/dhbwstuttgart/bytecode/MethodFromMethodCall.java new file mode 100644 index 000000000..330b0666d --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/MethodFromMethodCall.java @@ -0,0 +1,41 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.HashMap; + +import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class MethodFromMethodCall { + private ArgumentList argList; + private RefTypeOrTPHOrWildcardOrGeneric returnType; + private HashMap genericsAndBoundsMethod; + private HashMap genericsAndBounds; + + public MethodFromMethodCall(ArgumentList argList,RefTypeOrTPHOrWildcardOrGeneric returnType, + HashMap genericsAndBoundsMethod,HashMap genericsAndBounds) { + this.argList = argList; + this.returnType = returnType; + this.genericsAndBoundsMethod = genericsAndBoundsMethod; + this.genericsAndBounds = genericsAndBounds; + } + + public ArgumentList getArgList() { + return argList; + } + + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return returnType; + } + + public HashMap getGenericsAndBoundsMethod(){ + return genericsAndBoundsMethod; + } + + public HashMap getGenericsAndBounds(){ + return genericsAndBounds; + } + + public String accept(DescriptorVisitor descVisitor) { + return descVisitor.visit(this); + } +} diff --git a/src/de/dhbwstuttgart/bytecode/NormalConstructor.java b/src/de/dhbwstuttgart/bytecode/NormalConstructor.java new file mode 100644 index 000000000..d2174fd45 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/NormalConstructor.java @@ -0,0 +1,39 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.HashMap; + +import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.ParameterList; + +public class NormalConstructor { + private Constructor constructor; + private HashMap genericsAndBounds; + private boolean hasGenerics; + + public NormalConstructor(Constructor constructor, boolean hasGenerics) { + this.constructor = constructor; + this.hasGenerics = hasGenerics; + } + + public NormalConstructor(Constructor constructor, HashMap genericsAndBounds, boolean hasGenerics) { + this.constructor = constructor; + this.genericsAndBounds = genericsAndBounds; + this.hasGenerics = hasGenerics; + } + + public HashMap getGenericsAndBounds() { + return genericsAndBounds; + } + + public boolean hasGen() { + return hasGenerics; + } + + public ParameterList getParameterList() { + return constructor.getParameterList(); + } + + public String accept(DescriptorVisitor descVisitor) { + return descVisitor.visit(this); + } +} diff --git a/src/de/dhbwstuttgart/bytecode/NormalMethod.java b/src/de/dhbwstuttgart/bytecode/NormalMethod.java new file mode 100644 index 000000000..16e84cc53 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/NormalMethod.java @@ -0,0 +1,55 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.HashMap; + +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class NormalMethod { + private Method method; + private HashMap genericsAndBounds; + private HashMap genericsAndBoundsMethod; + private boolean hasGenerics; + + public NormalMethod(Method method, boolean hasGenerics) { + this.method = method; + this.hasGenerics = hasGenerics; + } + + public NormalMethod(Method method, HashMap genericsAndBounds, + HashMap genericsAndBoundsMethod,boolean hasGenerics) { + this.method = method; + this.genericsAndBounds = genericsAndBounds; + this.genericsAndBoundsMethod = genericsAndBoundsMethod; + this.hasGenerics = hasGenerics; + } + + public Method getMethod() { + return method; + } + + public ParameterList getParameterList() { + return method.getParameterList(); + } + + public HashMap getGenericsAndBounds(){ + return genericsAndBounds; + } + + public HashMap getGenericsAndBoundsMethod(){ + return genericsAndBoundsMethod; + } + + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return method.getReturnType(); + } + + public boolean hasGen() { + return this.hasGenerics; + } + + public String accept(DescriptorVisitor descVisitor) { + return descVisitor.visit(this); + } +} diff --git a/src/de/dhbwstuttgart/bytecode/SamMethod.java b/src/de/dhbwstuttgart/bytecode/SamMethod.java new file mode 100644 index 000000000..9cf039a2f --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/SamMethod.java @@ -0,0 +1,31 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.List; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class SamMethod { + private List argumentList; + private RefTypeOrTPHOrWildcardOrGeneric returnType; + + public SamMethod(List argumentList, RefTypeOrTPHOrWildcardOrGeneric returnType) { + this.argumentList = argumentList; + this.returnType = returnType; + } + + public List getArgumentList() { + return argumentList; + } + + + + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return returnType; + } + + + + public String accept(DescriptorVisitor descVisitor) { + return descVisitor.visit(this); + } +} diff --git a/src/de/dhbwstuttgart/bytecode/Signature.java b/src/de/dhbwstuttgart/bytecode/Signature.java new file mode 100644 index 000000000..362429a35 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/Signature.java @@ -0,0 +1,155 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.HashMap; +import java.util.Iterator; + +import org.objectweb.asm.signature.SignatureVisitor; +import org.objectweb.asm.signature.SignatureWriter; + +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +public class Signature { + private ClassOrInterface classOrInterface; + private HashMap genericsAndBounds; + private HashMap genericsAndBoundsMethod; + private SignatureWriter sw; + private Constructor constructor; + private Method method; + private HashMap methodParamsAndTypes; + private ResultSet resultSet; + + public Signature(ClassOrInterface classOrInterface, HashMap genericsAndBounds) { + this.classOrInterface = classOrInterface; + this.genericsAndBounds = genericsAndBounds; + sw = new SignatureWriter(); + createSignatureForClassOrInterface(); + } + + public Signature(Constructor constructor, HashMap genericsAndBounds, HashMap methodParamsAndTypes) { + this.constructor = constructor; + this.genericsAndBounds = genericsAndBounds; + this.methodParamsAndTypes = methodParamsAndTypes; + sw = new SignatureWriter(); + createSignatureForConsOrMethod(this.constructor,true); + } + + public Signature(Method method, HashMap genericsAndBoundsMethod, + HashMap methodParamsAndTypes, ResultSet resultSet) { + this.method = method; + this.genericsAndBoundsMethod = genericsAndBoundsMethod; + this.methodParamsAndTypes = methodParamsAndTypes; + this.resultSet = resultSet; + sw = new SignatureWriter(); + createSignatureForConsOrMethod(this.method,false); + } + + /** + * Creates signature for a method or constructor with @see {@link SignatureWriter} + * Signature looks like: + * (params L.. OR T.. Or basistape)ReturnType + * + * @param method method or constructor + * @param isConstructor true if constructor + */ + private void createSignatureForConsOrMethod(Method method, boolean isConstructor) { + Iterator itr = method.getGenerics().iterator(); + // visits all formal type parameter and visits their bounds + while(itr.hasNext()) { + GenericTypeVar g = itr.next(); + getBoundsOfTypeVar(g,genericsAndBoundsMethod); + } + // visits each method-parameter to create the signature + for(String paramName : methodParamsAndTypes.keySet()) { + RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName); + // parameter type deswegen ist true + doVisitParamsOrReturn(t,true); + } + if(isConstructor) { + sw.visitReturnType().visitBaseType('V'); + }else { + RefTypeOrTPHOrWildcardOrGeneric returnType = method.getReturnType(); + // return type deswegen ist false + doVisitParamsOrReturn(returnType, false); + } +// sw.visitEnd(); + } + /** + * Visits parameter type or return type with {@link SignatureVisitor} to create + * the method signature + * @param t type of parameter or return type + * @param isParameterType true if t is type of parameter + */ + private void doVisitParamsOrReturn(RefTypeOrTPHOrWildcardOrGeneric t, boolean isParameterType) { + String type = t.acceptTV(new TypeToString()); + SignatureVisitor sv; + if(isParameterType) { + sv = sw.visitParameterType(); + } + else { + sv = sw.visitReturnType(); + } + switch (type) { + case "RT": + sv.visitClassType(t.acceptTV(new TypeToDescriptor())); + break; + case "GRT": + GenericRefType g = (GenericRefType) t; + sv.visitTypeVariable(g.getParsedName()); + break; + case "TPH": + System.out.println(resultSet.resolveType(t).resolvedType.acceptTV(new TypeToDescriptor())); +// sv.visitInterface().visitClassType(resultSet.resolveType(t).resolvedType.acceptTV(new TypeToDescriptor())+";"); + + break; + default: + if(!isParameterType) + sv.visitBaseType('V'); + break; + } + } + /** + * Creates signature for class or interface with {@link SignatureWriter} + * Signature looks like: + * superclass + */ + private void createSignatureForClassOrInterface() { + Iterator itr = classOrInterface.getGenerics().iterator(); + + while(itr.hasNext()) { + GenericTypeVar g = itr.next(); + getBoundsOfTypeVar(g,genericsAndBounds); + } + + sw.visitSuperclass().visitClassType(classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()));; + sw.visitEnd(); + } + /** + * Get bounds of type variable + * @param g type variable + * @param genAndBounds + */ + private void getBoundsOfTypeVar(GenericTypeVar g, HashMap genAndBounds) { + sw.visitFormalTypeParameter(g.getParsedName()); + + Iterator bItr = g.getBounds().iterator(); + while(bItr.hasNext()) { + RefTypeOrTPHOrWildcardOrGeneric b =bItr.next(); + String boundDesc = b.acceptTV(new TypeToDescriptor()); + // Ensure that <...> extends java.lang.Object OR ... + sw.visitClassBound().visitClassType(boundDesc); + genAndBounds.put(g.getParsedName(), boundDesc); + } + sw.visitClassBound().visitEnd(); + } + + public String toString() { + return sw.toString(); + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/TypeToDescriptor.java b/src/de/dhbwstuttgart/bytecode/TypeToDescriptor.java new file mode 100644 index 000000000..5271e63d6 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/TypeToDescriptor.java @@ -0,0 +1,37 @@ +package de.dhbwstuttgart.bytecode; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.syntaxtree.type.TypeVisitor; + +public class TypeToDescriptor implements TypeVisitor{ + + @Override + public String visit(RefType refType) { + return refType.getName().toString().replace(".", "/"); + } + + @Override + public String visit(SuperWildcardType superWildcardType) { + throw new NotImplementedException(); + } + + @Override + public String visit(TypePlaceholder typePlaceholder) { + return typePlaceholder.toString().replace(".", "/"); + } + + @Override + public String visit(ExtendsWildcardType extendsWildcardType) { + throw new NotImplementedException(); + } + + @Override + public String visit(GenericRefType genericRefType) { + return genericRefType.getParsedName().replace(".", "/"); + } +} \ No newline at end of file diff --git a/src/de/dhbwstuttgart/bytecode/TypeToString.java b/src/de/dhbwstuttgart/bytecode/TypeToString.java new file mode 100644 index 000000000..86d4124a3 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/TypeToString.java @@ -0,0 +1,38 @@ +package de.dhbwstuttgart.bytecode; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.syntaxtree.type.TypeVisitor; + +public class TypeToString implements TypeVisitor{ + + @Override + public String visit(RefType refType) { + return "RT"; + } + + @Override + public String visit(SuperWildcardType superWildcardType) { + throw new NotImplementedException(); + } + + @Override + public String visit(TypePlaceholder typePlaceholder) { + return "TPH"; + } + + @Override + public String visit(ExtendsWildcardType extendsWildcardType) { + throw new NotImplementedException(); + } + + @Override + public String visit(GenericRefType genericRefType) { + return "GRT"; + } + +} diff --git a/src/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/de/dhbwstuttgart/core/JavaTXCompiler.java index adc160fcd..86666a49f 100644 --- a/src/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -29,7 +29,7 @@ import java.util.stream.Collectors; public class JavaTXCompiler { - final CompilationEnvironment environment; + final CompilationEnvironment environment; public final Map sourceFiles = new HashMap<>(); public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException { @@ -38,55 +38,85 @@ public class JavaTXCompiler { public JavaTXCompiler(List sources) throws IOException, ClassNotFoundException { environment = new CompilationEnvironment(sources); - for(File s : sources){ - sourceFiles.put(s,parse(s)); + for (File s : sources) { + sourceFiles.put(s, parse(s)); } } - public List typeInference() throws ClassNotFoundException { + public ConstraintSet getConstraints() throws ClassNotFoundException { List allClasses = new ArrayList<>();//environment.getAllAvailableClasses(); - for(SourceFile sf : sourceFiles.values()){ + for (SourceFile sf : sourceFiles.values()) { allClasses.addAll(sf.getClasses()); } List importedClasses = new ArrayList<>(); //Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC - for(File forSourceFile : sourceFiles.keySet()) - for(JavaClassName name : sourceFiles.get(forSourceFile).getImports()){ + for (File forSourceFile : sourceFiles.keySet()) + for (JavaClassName name : sourceFiles.get(forSourceFile).getImports()) { + //TODO: Hier werden imports von eigenen (.jav) Klassen nicht beachtet ClassOrInterface importedClass = ASTFactory.createClass( ClassLoader.getSystemClassLoader().loadClass(name.toString())); importedClasses.add(importedClass); } allClasses.addAll(importedClasses); - FiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses); - final ConstraintSet cons = new TYPE(sourceFiles.values(), allClasses).getConstraints(); + return new TYPE(sourceFiles.values(), allClasses).getConstraints(); + } + + public List getAvailableClasses(SourceFile forSourceFile) throws ClassNotFoundException { + List allClasses = new ArrayList<>();//environment.getAllAvailableClasses(); + for (SourceFile sf : sourceFiles.values()) { + allClasses.addAll(sf.getClasses()); + } + List importedClasses = new ArrayList<>(); + for (JavaClassName name : forSourceFile.getImports()) { + //TODO: Hier werden imports von eigenen (.jav) Klassen nicht beachtet + ClassOrInterface importedClass = ASTFactory.createClass( + ClassLoader.getSystemClassLoader().loadClass(name.toString())); + importedClasses.add(importedClass); + allClasses.addAll(importedClasses); + } + return allClasses; + } + + public List typeInference() throws ClassNotFoundException { + List allClasses = new ArrayList<>();//environment.getAllAvailableClasses(); + //Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC + for(SourceFile sf : this.sourceFiles.values()) { + //allClasses.addAll(getAvailableClasses(sf)); + allClasses.addAll(sf.getClasses()); + } + + final ConstraintSet cons = getConstraints(); + + FiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses); + System.out.println(finiteClosure); ConstraintSet unifyCons = UnifyTypeFactory.convert(cons); TypeUnify unify = new TypeUnify(); Set> results = new HashSet<>(); - for(List> xCons : unifyCons.cartesianProduct()){ + for (List> xCons : unifyCons.cartesianProduct()) { Set xConsSet = new HashSet<>(); - for(Constraint constraint : xCons){ + for (Constraint constraint : xCons) { xConsSet.addAll(constraint); } - //System.out.println(xConsSet); + System.out.println(xConsSet); Set> result = unify.unify(xConsSet, finiteClosure); - //System.out.println("RESULT: " + result); + System.out.println("RESULT: " + result); results.addAll(result); } return results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, generateTPHMap(cons))))).collect(Collectors.toList()); - } + } - private Map generateTPHMap(ConstraintSet constraints){ + private Map generateTPHMap(ConstraintSet constraints) { HashMap ret = new HashMap<>(); - constraints.map((Pair p)->{ - if(p.TA1 instanceof TypePlaceholder){ - ret.put(((TypePlaceholder)p.TA1).getName(), (TypePlaceholder) p.TA1); + constraints.map((Pair p) -> { + if (p.TA1 instanceof TypePlaceholder) { + ret.put(((TypePlaceholder) p.TA1).getName(), (TypePlaceholder) p.TA1); } - if(p.TA2 instanceof TypePlaceholder){ - ret.put(((TypePlaceholder)p.TA2).getName(), (TypePlaceholder) p.TA2); + if (p.TA2 instanceof TypePlaceholder) { + ret.put(((TypePlaceholder) p.TA2).getName(), (TypePlaceholder) p.TA2); } return null; }); @@ -96,8 +126,8 @@ public class JavaTXCompiler { private SourceFile parse(File sourceFile) throws IOException, java.lang.ClassNotFoundException { CompilationUnitContext tree = JavaTXParser.parse(sourceFile); SyntaxTreeGenerator generator = new SyntaxTreeGenerator(environment.getRegistry(sourceFile), new GenericsRegistry(null)); - SourceFile ret = generator.convert(tree); + SourceFile ret = generator.convert(tree, environment.packageCrawler); return ret; } - -} + +} \ No newline at end of file diff --git a/src/de/dhbwstuttgart/environment/CompilationEnvironment.java b/src/de/dhbwstuttgart/environment/CompilationEnvironment.java index 46a60139e..7044da6b6 100644 --- a/src/de/dhbwstuttgart/environment/CompilationEnvironment.java +++ b/src/de/dhbwstuttgart/environment/CompilationEnvironment.java @@ -5,10 +5,7 @@ import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; +import java.util.*; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.SourceFile; @@ -35,6 +32,7 @@ import de.dhbwstuttgart.parser.scope.JavaClassRegistry; public class CompilationEnvironment { private final List librarys; private final List sourceFiles; + public final PackageCrawler packageCrawler; /** * Imitiert die Environment beim Aufruf des JavaCompilers auf einer Menge von java-Dateien @@ -52,12 +50,22 @@ public class CompilationEnvironment { } } this.sourceFiles = sourceFiles; + this.packageCrawler = new PackageCrawler(librarys); } public JavaClassRegistry getRegistry(File forSourceFile) throws ClassNotFoundException, IOException { - List allNames; + Map allNames; CompilationUnitContext tree = JavaTXParser.parse(forSourceFile); - allNames = GatherNames.getNames(tree, new PackageCrawler(librarys)); + allNames = GatherNames.getNames(tree, packageCrawler); return new JavaClassRegistry(allNames); } + + public List getAllAvailableClasses() { + List ret = new ArrayList<>(); + for(Class c : new PackageCrawler(librarys).getAllAvailableClasses()){ + ret.add(ASTFactory.createClass(c)); + } + return ret; + } + } diff --git a/src/de/dhbwstuttgart/environment/PackageCrawler.java b/src/de/dhbwstuttgart/environment/PackageCrawler.java index 47b581284..7c63a0b6d 100644 --- a/src/de/dhbwstuttgart/environment/PackageCrawler.java +++ b/src/de/dhbwstuttgart/environment/PackageCrawler.java @@ -1,10 +1,7 @@ package de.dhbwstuttgart.environment; import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Set; +import java.util.*; import org.reflections.Reflections; import org.reflections.scanners.ResourcesScanner; @@ -56,14 +53,24 @@ public class PackageCrawler { return classes; } - public List getClassNames(String packageName){ - List nameList = new ArrayList(); + public Set> getAllAvailableClasses(){ + Reflections reflections = new Reflections(new ConfigurationBuilder() + .setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner()) + .setUrls(urls)); + + Set> classes = reflections.getSubTypesOf(Object.class); + + return classes; + } + + public Map getClassNames(String packageName){ + Map nameList = new HashMap<>(); Set> classes = getClassesInPackage(packageName); if(packageName.equals("java.lang") && ! classes.contains(Object.class)) { classes.add(Object.class); } for(Class c : classes){ - nameList.add(c.getName()); + nameList.put(c.getName(), c.getTypeParameters().length); } return nameList; } diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java new file mode 100644 index 000000000..cbca13ce6 --- /dev/null +++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java @@ -0,0 +1,148 @@ +package de.dhbwstuttgart.parser.SyntaxTreeGenerator; + +import de.dhbwstuttgart.exceptions.DebugException; +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; +import de.dhbwstuttgart.syntaxtree.type.*; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import de.dhbwstuttgart.typeinference.unify.model.*; + +import java.util.*; + +public class FCGenerator { + /** + * Baut die FiniteClosure aus availableClasses. + * Klassen welche nicht in availableClasses vorkommen werden im Java Classpath nachgeschlagen. + * + * @param availableClasses - Alle geparsten Klassen + */ + public static Set toFC(Collection availableClasses) throws ClassNotFoundException { + HashSet pairs = new HashSet<>(); + for(ClassOrInterface cly : availableClasses){ + pairs.addAll(getSuperTypes(cly, availableClasses)); + } + System.out.println(pairs); + return pairs; + } + + /** + * Bildet eine Kette vom übergebenen Typ bis hin zum höchsten bekannten Typ + * Als Generics werden TPHs benutzt, welche der Unifikationsalgorithmus korrekt interpretieren muss. + * Die verwendeten TPHs werden in der Kette nach oben gereicht, so erhält der selbe GTV immer den selben TPH + * @param forType + * @return + */ + private static List getSuperTypes(ClassOrInterface forType, Collection availableClasses) throws ClassNotFoundException { + return getSuperTypes(forType, availableClasses, new HashMap<>()); + } + + //TODO: implements Interface auch als superklassen beachten + private static List getSuperTypes(ClassOrInterface forType, Collection availableClasses, HashMap gtvs) throws ClassNotFoundException { + List params = new ArrayList<>(); + //Die GTVs, die in forType hinzukommen: + HashMap newGTVs = new HashMap<>(); + //Generics mit gleichem Namen müssen den selben TPH bekommen + for(GenericTypeVar gtv : forType.getGenerics()){ + if(!gtvs.containsKey(gtv.getParsedName())){ + gtvs.put(gtv.getParsedName(), PlaceholderType.freshPlaceholder()); + newGTVs.put(gtv.getParsedName(), PlaceholderType.freshPlaceholder()); + } + params.add(gtvs.get(gtv.getParsedName())); + } + + Optional hasSuperclass = availableClasses.stream().filter(cl -> forType.getSuperClass().getName().equals(cl.getClassName())).findAny(); + ClassOrInterface superClass; + if(!hasSuperclass.isPresent()) //Wenn es die Klasse in den available Klasses nicht gibt wird sie im Classpath gesucht. Ansonsten Exception + { + superClass = ASTFactory.createClass(ClassLoader.getSystemClassLoader().loadClass(forType.getSuperClass().getName().toString())); + }else{ + superClass = hasSuperclass.get(); + } + /* + Die Parameter der superklasse müssen jetzt nach den Angaben in der Subklasse + modifiziert werden + Beispie: Matrix extends Vector> + Den ersten Parameter mit Vector austauschen und dort alle Generics zu den Typplaceholdern in gtvs austauschen + */ + //Hier vermerken, welche Typen im der Superklasse ausgetauscht werden müssen + Iterator itGenParams = superClass.getGenerics().iterator(); + Iterator itSetParams = forType.getSuperClass().getParaList().iterator(); + while(itGenParams.hasNext()){ + RefTypeOrTPHOrWildcardOrGeneric setType = itSetParams.next(); + //In diesem Typ die GTVs durch TPHs und Einsetzungen austauschen: + UnifyType setSetType = setType.acceptTV(new TypeExchanger(gtvs)); + newGTVs.put(itGenParams.next().getParsedName(), setSetType); + } + + UnifyType superType = forType.getSuperClass().acceptTV(new TypeExchanger(newGTVs)); + + TypeParams paramList = new TypeParams(params); + UnifyType t1 = new ReferenceType(forType.getClassName().toString(), paramList); + UnifyType t2 = superType; + + UnifyPair ret = UnifyTypeFactory.generateSmallerPair(t1, t2); + + List superTypes; + //Rekursiver Aufruf. Abbruchbedingung ist Object als Superklasse: + if(superClass.getClassName().equals(ASTFactory.createObjectClass().getClassName())){ + superTypes = Arrays.asList(UnifyTypeFactory.generateSmallerPair(UnifyTypeFactory.convert(ASTFactory.createObjectType()), UnifyTypeFactory.convert(ASTFactory.createObjectType()))); + }else{ + superTypes = getSuperTypes(superClass, availableClasses, newGTVs); + } + + List retList = new ArrayList<>(); + retList.add(ret); + retList.addAll(superTypes); + + return retList; + } + + /** + * Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus. + */ + private static class TypeExchanger implements TypeVisitor{ + + private final HashMap gtvs; + + TypeExchanger(HashMap gtvs){ + this.gtvs = gtvs; + } + + @Override + public UnifyType visit(RefType refType) { + List params = new ArrayList<>(); + for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){ + params.add(param.acceptTV(this)); + } + TypeParams paramList = new TypeParams(params); + UnifyType ret = new ReferenceType(refType.getName().toString(), paramList); + return ret; + } + + @Override + public UnifyType visit(SuperWildcardType superWildcardType) { + throw new DebugException("Dieser Fall darf nicht auftreten"); + } + + @Override + public UnifyType visit(TypePlaceholder typePlaceholder) { + throw new DebugException("Dieser Fall darf nicht auftreten"); + } + + @Override + public UnifyType visit(ExtendsWildcardType extendsWildcardType) { + throw new DebugException("Dieser Fall darf nicht auftreten"); + } + + @Override + public UnifyType visit(GenericRefType genericRefType) { + if(! gtvs.containsKey(genericRefType.getParsedName())) + throw new DebugException("Dieser Fall darf nicht auftreten"); + return gtvs.get(genericRefType.getParsedName()); + } + + } +} diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java index 830f9d374..3d9d7aca4 100644 --- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java +++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java @@ -1,10 +1,12 @@ package de.dhbwstuttgart.parser.SyntaxTreeGenerator; +import de.dhbwstuttgart.environment.PackageCrawler; import de.dhbwstuttgart.exceptions.NotImplementedException; import java.lang.ClassNotFoundException; import de.dhbwstuttgart.exceptions.TypeinferenceException; import de.dhbwstuttgart.parser.antlr.Java8Parser; +import de.dhbwstuttgart.parser.scope.GatherNames; import de.dhbwstuttgart.parser.scope.GenericsRegistry; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.parser.scope.JavaClassRegistry; @@ -17,9 +19,8 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import java.lang.reflect.Modifier; import java.sql.Ref; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; +import java.util.*; +import java.util.stream.Collectors; //import jdk.internal.dynalink.support.TypeConverterFactory; import org.antlr.v4.runtime.CommonToken; @@ -30,7 +31,7 @@ public class SyntaxTreeGenerator{ private JavaClassRegistry reg; private final GenericsRegistry globalGenerics; private String pkgName = ""; - List imports = new ArrayList(); + Set imports = new HashSet(); List fieldInitializations = new ArrayList<>(); @@ -71,56 +72,10 @@ public class SyntaxTreeGenerator{ return ret; } - public void setImports(Java8Parser.CompilationUnitContext ctx) throws ClassNotFoundException { - List newImports = new ArrayList(); - for(Java8Parser.ImportDeclarationContext importDeclCtx : ctx.importDeclaration()){ - if(importDeclCtx.singleTypeImportDeclaration() != null){ - newImports.add(convertSingleTypeImportDeclaration(importDeclCtx.singleTypeImportDeclaration())); - } - else if(importDeclCtx.typeImportOnDemandDeclaration() != null){ - newImports.addAll(convertTypeImportOnDemandDeclaration(importDeclCtx.typeImportOnDemandDeclaration())); - } - else if(importDeclCtx.singleStaticImportDeclaration() != null){ - newImports.add(convertSingleStaticImportDeclaration(importDeclCtx.singleStaticImportDeclaration())); - } - else{ - newImports.addAll(convertStaticImportOnDemandDeclaration(importDeclCtx.staticImportOnDemandDeclaration())); - } - } - this.imports.addAll(newImports); - } - - private JavaClassName convertSingleTypeImportDeclaration(Java8Parser.SingleTypeImportDeclarationContext ctx) throws ClassNotFoundException{ - String typeName = convertTypeName(ctx.typeName()); - JavaClassName ret = reg.getName(typeName); - return ret; - } - - private List convertTypeImportOnDemandDeclaration(Java8Parser.TypeImportOnDemandDeclarationContext ctx){ - return reg.getAllFromPackage(ctx.packageOrTypeName().getText()); - } - - private JavaClassName convertSingleStaticImportDeclaration(Java8Parser.SingleStaticImportDeclarationContext ctx){ - throw new NotImplementedException(); - } - - private List convertStaticImportOnDemandDeclaration(Java8Parser.StaticImportOnDemandDeclarationContext ctx){ - return reg.getAllFromPackage(ctx.typeName().getText()); - } - - private String getPackageFromClass(String cls){ - String ret = ""; - String[] parts = cls.split("\\."); - for(int i = 0; i < parts.length - 1; i++){ - ret = ret + "." + parts[i]; - } - ret = ret.substring(1); - return ret; - } - - public SourceFile convert(Java8Parser.CompilationUnitContext ctx) throws ClassNotFoundException{ + public SourceFile convert(Java8Parser.CompilationUnitContext ctx, PackageCrawler packageCrawler) throws ClassNotFoundException{ List classes = new ArrayList<>(); - this.setImports(ctx); + Map imports = GatherNames.getImports(ctx, packageCrawler); + this.imports = imports.keySet().stream().map(name -> reg.getName(name)).collect(Collectors.toSet()); for(Java8Parser.TypeDeclarationContext typeDecl : ctx.typeDeclaration()){ ClassOrInterface newClass; if(typeDecl.classDeclaration() != null){ @@ -184,9 +139,9 @@ public class SyntaxTreeGenerator{ block = stmtGen.convert(body.block()); } if(parentClass.equals(new JavaClassName(name))){ - return new Constructor(modifiers, name, retType, modifiers, parameterList, block, gtvDeclarations, header.getStart(), fieldInitializations, superClass); + return new Constructor(modifiers, name, retType, parameterList, block, gtvDeclarations, header.getStart(), fieldInitializations); }else{ - return new Method(modifiers, name, retType, modifiers, parameterList,block, gtvDeclarations, header.getStart()); + return new Method(modifiers, name, retType, parameterList,block, gtvDeclarations, header.getStart()); } } @@ -222,7 +177,7 @@ public class SyntaxTreeGenerator{ if(ctx.superclass() != null){ superClass = convert(ctx.superclass()); }else{ - superClass = ASTFactory.createObjectClass().getType(); + superClass = new RefType(ASTFactory.createObjectClass().getClassName(), ctx.getStart()); } List fielddecl = convertFields(ctx.classBody(), generics); List methods = convertMethods(ctx.classBody(), name, superClass, generics); @@ -266,10 +221,9 @@ public class SyntaxTreeGenerator{ */ private Constructor generateStandardConstructor(String className, JavaClassName parentClass, RefType superClass, GenericDeclarationList classGenerics, Token offset){ RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset); - int modifiers = 0; ParameterList params = new ParameterList(new ArrayList<>(), offset); Block block = new Block(new ArrayList<>(), offset); - return new Constructor(Modifier.PUBLIC, className, classType, modifiers, params, block, classGenerics, offset, fieldInitializations, superClass); + return new Constructor(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset, fieldInitializations); } private RefType convert(Java8Parser.SuperclassContext superclass) { @@ -424,6 +378,8 @@ public class SyntaxTreeGenerator{ modifiers += newModifier; } } + if(!Modifier.isInterface(modifiers))modifiers += Modifier.INTERFACE; + JavaClassName name = reg.getName(ctx.Identifier().getText()); GenericsRegistry generics = createGenerics(ctx.typeParameters(), name, "", reg, new GenericsRegistry(globalGenerics)); @@ -434,7 +390,7 @@ public class SyntaxTreeGenerator{ }else{ genericParams = createEmptyGenericDeclarationList(ctx.Identifier()); } - RefType superClass = ASTFactory.createObjectClass().getType(); + RefType superClass = ASTFactory.createObjectType(); List fields = convertFields(ctx.interfaceBody()); List methods = convertMethods(ctx.interfaceBody(), name, superClass, generics); diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java index c60ae3224..d54b682a1 100644 --- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java +++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java @@ -14,6 +14,7 @@ import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import org.antlr.v4.runtime.Token; import java.util.ArrayList; @@ -42,7 +43,7 @@ public class TypeGenerator { throw new NotImplementedException(); }else if(unannTypeContext.unannReferenceType().unannArrayType()!=null){ - System.out.println(unannTypeContext.getText()); + //System.out.println(unannTypeContext.getText()); throw new NotImplementedException(); }else if(unannTypeContext.unannReferenceType().unannTypeVariable()!=null){ @@ -77,7 +78,7 @@ public class TypeGenerator { public static List convert(Java8Parser.TypeBoundContext typeBoundContext, JavaClassRegistry reg, GenericsRegistry generics) { List ret = new ArrayList<>(); if(typeBoundContext == null){ - ret.add(ASTFactory.createObjectClass().getType()); + ret.add(ASTFactory.createObjectType()); return ret; } if(typeBoundContext.typeVariable() != null){ @@ -131,7 +132,11 @@ public class TypeGenerator { } } if(typeArguments == null){ - return new RefType(reg.getName(name), offset); + List params = new ArrayList<>(); + for(int i = 0; i getNames(Java8Parser.CompilationUnitContext ctx, PackageCrawler packages) throws ClassNotFoundException{ - List ret = new ArrayList<>(); + public static Map getNames(Java8Parser.CompilationUnitContext ctx, PackageCrawler packages) throws ClassNotFoundException{ + Map ret = new HashMap<>(); String pkgName = getPackageName(ctx); String nameString = ""; for (Java8Parser.TypeDeclarationContext typeDecl : ctx.typeDeclaration()){ @@ -26,6 +28,8 @@ public class GatherNames { else{ nameString = typeDecl.interfaceDeclaration().normalInterfaceDeclaration().Identifier().toString(); } + int numGenerics = typeDecl.interfaceDeclaration().normalInterfaceDeclaration().typeParameters()!=null? + typeDecl.interfaceDeclaration().normalInterfaceDeclaration().typeParameters().typeParameterList().typeParameter().size():0; //Die Generic TypeParameter Definitionen Nicht! an die JavaClassName-Registry anfügen: /* //Diese gelängen dadurch in den globalen Scope, was sie schließlich nicht sind if(typeDecl.classDeclaration().normalClassDeclaration().typeParameters() != null){ @@ -34,7 +38,7 @@ public class GatherNames { } } */ - ret.add(nameString); + ret.put(nameString, numGenerics); } } else{ @@ -53,30 +57,36 @@ public class GatherNames { } } */ - ret.add(nameString); + int numGenerics = typeDecl.classDeclaration().normalClassDeclaration().typeParameters()!=null? + typeDecl.classDeclaration().normalClassDeclaration().typeParameters().typeParameterList().typeParameter().size():0; + + ret.put(nameString, numGenerics); } } } - ret.addAll(getImports(ctx, packages)); + ret.putAll(getImports(ctx, packages)); return ret; } - private static List getImports(Java8Parser.CompilationUnitContext ctx, PackageCrawler packages) throws ClassNotFoundException { - List ret = new ArrayList(); - ret.addAll(packages.getClassNames("java.lang")); - for(Java8Parser.ImportDeclarationContext importDeclCtx : ctx.importDeclaration()){ + public static Map getImports(Java8Parser.CompilationUnitContext ctx, PackageCrawler packages) throws ClassNotFoundException { + Map ret = new HashMap<>(); + ClassLoader classLoader = ClassLoader.getSystemClassLoader(); + ret.putAll(packages.getClassNames("java.lang")); + for(Java8Parser.ImportDeclarationContext importDeclCtx : ctx.importDeclaration()){ if(importDeclCtx.singleTypeImportDeclaration() != null){ - ret.add(importDeclCtx.singleTypeImportDeclaration().typeName().getText()); + Class cl = classLoader.loadClass(importDeclCtx.singleTypeImportDeclaration().typeName().getText()); + ret.put(cl.getName(), cl.getTypeParameters().length); } else if(importDeclCtx.typeImportOnDemandDeclaration() != null){ - ret.addAll(packages.getClassNames(importDeclCtx.typeImportOnDemandDeclaration().packageOrTypeName().getText())); + ret.putAll(packages.getClassNames(importDeclCtx.typeImportOnDemandDeclaration().packageOrTypeName().getText())); } else if(importDeclCtx.singleStaticImportDeclaration() != null){ - ret.add(importDeclCtx.singleStaticImportDeclaration().typeName().getText()+"."+importDeclCtx.singleStaticImportDeclaration().Identifier().getText()); - } + Class cl = classLoader.loadClass(importDeclCtx.singleStaticImportDeclaration().typeName().getText()+"."+importDeclCtx.singleStaticImportDeclaration().Identifier().getText()); + ret.put(cl.getName(), cl.getTypeParameters().length); + } else{ - ret.addAll(packages.getClassNames(importDeclCtx.staticImportOnDemandDeclaration().typeName().getText())); + ret.putAll(packages.getClassNames(importDeclCtx.staticImportOnDemandDeclaration().typeName().getText())); } } return ret; diff --git a/src/de/dhbwstuttgart/parser/scope/GenericTypeName.java b/src/de/dhbwstuttgart/parser/scope/GenericTypeName.java index 0cee932f7..c5355ebd8 100644 --- a/src/de/dhbwstuttgart/parser/scope/GenericTypeName.java +++ b/src/de/dhbwstuttgart/parser/scope/GenericTypeName.java @@ -19,4 +19,8 @@ public class GenericTypeName extends JavaClassName { + DELIMITER + methodName + DELIMITER + super.toString(); } + + public JavaClassName getParentClass() { + return parentClass; + } } diff --git a/src/de/dhbwstuttgart/parser/scope/JavaClassName.java b/src/de/dhbwstuttgart/parser/scope/JavaClassName.java index a20ce2e7e..b87ff719a 100644 --- a/src/de/dhbwstuttgart/parser/scope/JavaClassName.java +++ b/src/de/dhbwstuttgart/parser/scope/JavaClassName.java @@ -49,8 +49,10 @@ public class JavaClassName { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); + /* result = prime * result + ((packageName == null) ? 0 : packageName.hashCode()); //PackageName does not infect hashCode + */ return result; } diff --git a/src/de/dhbwstuttgart/parser/scope/JavaClassRegistry.java b/src/de/dhbwstuttgart/parser/scope/JavaClassRegistry.java index a0cfacbf4..d9ab804c8 100644 --- a/src/de/dhbwstuttgart/parser/scope/JavaClassRegistry.java +++ b/src/de/dhbwstuttgart/parser/scope/JavaClassRegistry.java @@ -8,20 +8,16 @@ import java.util.*; * Speichert die Klassen f�r einen bestimmten Projektscope */ public class JavaClassRegistry { - final List existingClasses = new ArrayList<>(); + final Map existingClasses = new HashMap<>(); - public JavaClassRegistry(List initialNames){ - for(String name : initialNames){ - existingClasses.add(new JavaClassName(name)); + public JavaClassRegistry(Map initialNames){ + for(String name : initialNames.keySet()){ + existingClasses.put(new JavaClassName(name), initialNames.get(name)); } } - - public void add(String className){ - existingClasses.add(new JavaClassName(className)); - } public JavaClassName getName(String className) { - for(JavaClassName name : existingClasses){ + for(JavaClassName name : existingClasses.keySet()){ if(name.equals(new JavaClassName(className)))return name; } throw new NotImplementedException(); @@ -34,7 +30,7 @@ public class JavaClassRegistry { public List getAllFromPackage(String packageName) { List ret = new ArrayList<>(); - for(JavaClassName className : this.existingClasses){ + for(JavaClassName className : this.existingClasses.keySet()){ JavaClassName toCompare = new JavaClassName(packageName + "." + JavaClassName.stripClassName(className.toString())); if(toCompare.toString().equals(className.toString())){ ret.add(className); @@ -44,6 +40,10 @@ public class JavaClassRegistry { } public boolean contains(String whole) { - return existingClasses.contains(new JavaClassName(whole)); + return existingClasses.containsKey(new JavaClassName(whole)); + } + + public int getNumberOfGenerics(String name) { + return existingClasses.get(new JavaClassName(name)); } } diff --git a/src/de/dhbwstuttgart/sat/CNF/CNF.java b/src/de/dhbwstuttgart/sat/CNF/CNF.java new file mode 100644 index 000000000..e5d9b3d0e --- /dev/null +++ b/src/de/dhbwstuttgart/sat/CNF/CNF.java @@ -0,0 +1,8 @@ +package de.dhbwstuttgart.sat.CNF; + +public class CNF { + /* + Baut die CNF Datei. + Hier muss man überlegen, in welchem Form die Constraints gebaut werden + */ +} diff --git a/src/de/dhbwstuttgart/sat/CNF/Writer.java b/src/de/dhbwstuttgart/sat/CNF/Writer.java new file mode 100644 index 000000000..c366686a8 --- /dev/null +++ b/src/de/dhbwstuttgart/sat/CNF/Writer.java @@ -0,0 +1,12 @@ +package de.dhbwstuttgart.sat.CNF; + +import java.io.*; + +/** + * Schreibt CNFs in eine Datei im DIMACS CNF Format + */ +public class Writer { + public Writer(FileWriter output){ + + } +} diff --git a/src/de/dhbwstuttgart/sat/asp/Clingo.java b/src/de/dhbwstuttgart/sat/asp/Clingo.java new file mode 100644 index 000000000..85f6dc569 --- /dev/null +++ b/src/de/dhbwstuttgart/sat/asp/Clingo.java @@ -0,0 +1,46 @@ +package de.dhbwstuttgart.sat.asp; + + +import org.apache.commons.io.IOUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class Clingo { + private final List input; + private static final List programFiles = new ArrayList<>(); + static{ + programFiles.add(new File("/home/janulrich/Sync/HiwiJob/ResearchPapers/MasterarbeitStadelmeier/asp/unifyWithoutWildcards/basis.lp")); + programFiles.add(new File("/home/janulrich/Sync/HiwiJob/ResearchPapers/MasterarbeitStadelmeier/asp/unifyWithoutWildcards/subst.lp")); + programFiles.add(new File("/home/janulrich/Sync/HiwiJob/ResearchPapers/MasterarbeitStadelmeier/asp/unifyWithoutWildcards/reduce1.lp")); + programFiles.add(new File("/home/janulrich/Sync/HiwiJob/ResearchPapers/MasterarbeitStadelmeier/asp/unifyWithoutWildcards/reduce2.lp")); + programFiles.add(new File("/home/janulrich/Sync/HiwiJob/ResearchPapers/MasterarbeitStadelmeier/asp/unifyWithoutWildcards/unify.lp")); + } + + public Clingo(List inputFiles){ + this.input = inputFiles; + } + + public String runClingo() throws IOException, InterruptedException { + String pathToClingo = + "/home/janulrich/Sync/HiwiJob/ResearchPapers/MasterarbeitStadelmeier/asp/clingo-5.2.1-linux-x86_64/clingo"; + List commands = new ArrayList<>(); + commands.add(pathToClingo); + commands.add("--outf=2"); //use JSON-Output + for(File file : input){ + commands.add(file.getPath()); + } + commands.addAll(programFiles.stream().map(f->f.getPath()).collect(Collectors.toList())); + Process clingo = new ProcessBuilder( commands.toArray(new String[0])).start(); + InputStream output = clingo.getInputStream(); + clingo.waitFor(); + String result = IOUtils.toString(output, StandardCharsets.UTF_8); + return result; + } +} diff --git a/src/de/dhbwstuttgart/sat/asp/model/ASPRule.java b/src/de/dhbwstuttgart/sat/asp/model/ASPRule.java new file mode 100644 index 000000000..412375474 --- /dev/null +++ b/src/de/dhbwstuttgart/sat/asp/model/ASPRule.java @@ -0,0 +1,24 @@ +package de.dhbwstuttgart.sat.asp.model; + +public enum ASPRule { + ASP_GENERIC_TYPE_NAME("genericType"), + ASP_PAIR_EQUALS_NAME("equals"), + ASP_PAIR_SMALLER_NAME("smaller"), + ASP_PAIR_SMALLER_DOT_NAME("smallerDot"), + ASP_PARAMLIST_NAME("param"), + ASP_PARAMLISTNUMERATION_NAME("paramNum"), + ASP_PARAMLIST_END_POINTER("null"), + ASP_TYPE("type") + ; + + private final String text; + + private ASPRule(final String text) { + this.text = text; + } + + @Override + public String toString() { + return text; + } +} diff --git a/src/de/dhbwstuttgart/sat/asp/parser/ASPParser.java b/src/de/dhbwstuttgart/sat/asp/parser/ASPParser.java new file mode 100644 index 000000000..c7be7dbc7 --- /dev/null +++ b/src/de/dhbwstuttgart/sat/asp/parser/ASPParser.java @@ -0,0 +1,17 @@ +package de.dhbwstuttgart.sat.asp.parser; + +import de.dhbwstuttgart.typeinference.result.ResultPair; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import java.util.HashSet; +import java.util.Set; + +public class ASPParser { + ResultSet parse(String result){ + Set ret = new HashSet<>(); + for(String pair : result.split(",")){ + + } + return new ResultSet(ret); + } +} \ No newline at end of file diff --git a/src/de/dhbwstuttgart/sat/asp/parser/model/ParsedASPStatement.java b/src/de/dhbwstuttgart/sat/asp/parser/model/ParsedASPStatement.java new file mode 100644 index 000000000..614bddb01 --- /dev/null +++ b/src/de/dhbwstuttgart/sat/asp/parser/model/ParsedASPStatement.java @@ -0,0 +1,7 @@ +package de.dhbwstuttgart.sat.asp.parser.model; + +public class ParsedASPStatement { + public ParsedASPStatement(String statement){ + + } +} diff --git a/src/de/dhbwstuttgart/sat/asp/writer/ASPGenerator.java b/src/de/dhbwstuttgart/sat/asp/writer/ASPGenerator.java new file mode 100644 index 000000000..002e3c7f6 --- /dev/null +++ b/src/de/dhbwstuttgart/sat/asp/writer/ASPGenerator.java @@ -0,0 +1,111 @@ +package de.dhbwstuttgart.sat.asp.writer; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.sat.asp.writer.model.*; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; +import de.dhbwstuttgart.syntaxtree.type.*; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.constraints.Pair; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class ASPGenerator { + ASPWriter writer = new ASPWriter(); + private final String asp; + + public ASPGenerator(ConstraintSet constraints, Collection fcClasses){ + List> constraints1 = constraints.cartesianProduct().iterator().next(); + List constraintPairs = new ArrayList<>(); + for(Constraint constraint : constraints1){ + System.out.println(UnifyTypeFactory.convert(constraint)); + constraintPairs.addAll(constraint); + } + asp = toASP(constraintPairs, fcClasses); + } + + public String getASP(){ + return asp; + } + + private String toASP(List constraintSet, Collection fcClasses){ + TypeConverter converter = new TypeConverter(); + for(ClassOrInterface cl : fcClasses){ + ASPType superClass = cl.getSuperClass().acceptTV(converter); + ASPPairSmaller fcEntry = new ASPPairSmaller(convert(cl), superClass); + writer.add(new ASPStatement(fcEntry.toASP())); + } + for(Pair cons : constraintSet){ + writer.add(new ASPStatement(convert(cons).toASP())); + } + + return writer.getASPFile(); + } + + private ASPPair convert(Pair pair){ + TypeConverter converter = new TypeConverter(); + ASPType ls = pair.TA1.acceptTV(converter); + ASPType rs = pair.TA2.acceptTV(converter); + if(pair.OperatorEqual()){ + return new ASPPairEquals(ls, rs); + }else if(pair.OperatorSmallerDot()){ + return new ASPPairSmallerDot(ls, rs); + }else throw new NotImplementedException(); + } + + private ASPType convert(ClassOrInterface cl){ + List paramList = new ArrayList<>(); + for(GenericTypeVar gtv : cl.getGenerics()){ + paramList.add(new ASPGenericType(toConstant(gtv.getName()))); + } + ASPParameterList params = new ASPParameterList(paramList, writer); + return new ASPRefType(toConstant(cl.getClassName()), params); + } + + public static String toConstant(JavaClassName name){ + return toConstant(name.toString().replace(".", "_")); + } + + public static String toConstant(String name){ + return "c" + name.toString().replace(".", "_"); + } + + private class TypeConverter implements TypeVisitor{ + + @Override + public ASPType visit(RefType type) { + List paramList = new ArrayList<>(); + for(RefTypeOrTPHOrWildcardOrGeneric gtv : type.getParaList()){ + paramList.add(gtv.acceptTV(this)); + } + ASPParameterList params = new ASPParameterList(paramList, writer); + return new ASPRefType(toConstant(type.getName()), params); + } + + @Override + public ASPType visit(SuperWildcardType superWildcardType) { + throw new NotImplementedException(); + } + + @Override + public ASPType visit(TypePlaceholder typePlaceholder) { + return new ASPTypeVar(toConstant(typePlaceholder.getName())); + } + + @Override + public ASPType visit(ExtendsWildcardType extendsWildcardType) { + throw new NotImplementedException(); + } + + @Override + public ASPType visit(GenericRefType genericRefType) { + return new ASPRefType(toConstant(genericRefType.getName()), + new ASPParameterList(new ArrayList<>(), writer)); + } + } +} diff --git a/src/de/dhbwstuttgart/sat/asp/writer/ASPWriter.java b/src/de/dhbwstuttgart/sat/asp/writer/ASPWriter.java new file mode 100644 index 000000000..450950d99 --- /dev/null +++ b/src/de/dhbwstuttgart/sat/asp/writer/ASPWriter.java @@ -0,0 +1,22 @@ +package de.dhbwstuttgart.sat.asp.writer; + +import de.dhbwstuttgart.sat.asp.writer.model.ASPStatement; + +import java.util.HashSet; + +public class ASPWriter { + + private HashSet content = new HashSet<>(); + + public void add(ASPStatement stmt){ + content.add(stmt); + } + + public String getASPFile(){ + String ret = ""; + for(ASPStatement statement : content){ + ret += statement.getASP() + ".\n"; + } + return ret; + } +} diff --git a/src/de/dhbwstuttgart/sat/asp/writer/model/ASPGenericType.java b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPGenericType.java new file mode 100644 index 000000000..57619edf6 --- /dev/null +++ b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPGenericType.java @@ -0,0 +1,15 @@ +package de.dhbwstuttgart.sat.asp.writer.model; + +import de.dhbwstuttgart.sat.asp.model.ASPRule; + +public class ASPGenericType implements ASPType{ + private final String name; + + public ASPGenericType(String name){ + this.name = name; + } + + public String toString(){ + return ASPRule.ASP_GENERIC_TYPE_NAME + "(" + name + ")"; + } +} diff --git a/src/de/dhbwstuttgart/sat/asp/writer/model/ASPPair.java b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPPair.java new file mode 100644 index 000000000..662f995c7 --- /dev/null +++ b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPPair.java @@ -0,0 +1,21 @@ +package de.dhbwstuttgart.sat.asp.writer.model; + +public abstract class ASPPair { + public final ASPType leftSide; + public final ASPType rightSide; + + public ASPPair(ASPType ls, ASPType rs){ + this.leftSide = ls; + this.rightSide = rs; + } + + public String toASP(){ + return this.getRuleName() + "(" + leftSide + ","+ rightSide + ")"; + } + + public String toString(){ + return toASP(); + } + + protected abstract String getRuleName(); +} diff --git a/src/de/dhbwstuttgart/sat/asp/writer/model/ASPPairEquals.java b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPPairEquals.java new file mode 100644 index 000000000..8806f2ce2 --- /dev/null +++ b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPPairEquals.java @@ -0,0 +1,14 @@ +package de.dhbwstuttgart.sat.asp.writer.model; + +import de.dhbwstuttgart.sat.asp.model.ASPRule; + +public class ASPPairEquals extends ASPPair{ + public ASPPairEquals(ASPType ls, ASPType rs){ + super(ls, rs); + } + + @Override + protected String getRuleName() { + return ASPRule.ASP_PAIR_EQUALS_NAME.toString(); + } +} diff --git a/src/de/dhbwstuttgart/sat/asp/writer/model/ASPPairSmaller.java b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPPairSmaller.java new file mode 100644 index 000000000..f57170f62 --- /dev/null +++ b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPPairSmaller.java @@ -0,0 +1,16 @@ +package de.dhbwstuttgart.sat.asp.writer.model; + +import de.dhbwstuttgart.sat.asp.model.ASPRule; + +import java.util.Map; + +public class ASPPairSmaller extends ASPPair{ + public ASPPairSmaller(ASPType ls, ASPType rs){ + super(ls, rs); + } + + @Override + protected String getRuleName() { + return ASPRule.ASP_PAIR_SMALLER_NAME.toString(); + } +} \ No newline at end of file diff --git a/src/de/dhbwstuttgart/sat/asp/writer/model/ASPPairSmallerDot.java b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPPairSmallerDot.java new file mode 100644 index 000000000..e8482bfc8 --- /dev/null +++ b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPPairSmallerDot.java @@ -0,0 +1,14 @@ +package de.dhbwstuttgart.sat.asp.writer.model; + +import de.dhbwstuttgart.sat.asp.model.ASPRule; + +public class ASPPairSmallerDot extends ASPPair{ + public ASPPairSmallerDot(ASPType ls, ASPType rs){ + super(ls, rs); + } + + @Override + protected String getRuleName() { + return ASPRule.ASP_PAIR_SMALLER_DOT_NAME.toString(); + } +} diff --git a/src/de/dhbwstuttgart/sat/asp/writer/model/ASPParameterList.java b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPParameterList.java new file mode 100644 index 000000000..3c176e49d --- /dev/null +++ b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPParameterList.java @@ -0,0 +1,45 @@ +package de.dhbwstuttgart.sat.asp.writer.model; + +import de.dhbwstuttgart.sat.asp.model.ASPRule; +import de.dhbwstuttgart.sat.asp.writer.ASPGenerator; +import de.dhbwstuttgart.sat.asp.writer.ASPWriter; +import de.dhbwstuttgart.syntaxtree.factory.NameGenerator; + +import java.util.Iterator; +import java.util.List; + +public class ASPParameterList { + public final String name; + private final List types; + + public ASPParameterList(List types, ASPWriter writer){ + int paramNum = 0; + this.types = types; + if(types.size() == 0){ + name = ASPRule.ASP_PARAMLIST_END_POINTER.toString(); + }else{ + name = newName(); + String nextPointer = name; + Iterator it = types.iterator(); + while(it.hasNext()){ + ASPType t = it.next(); + String param = nextPointer + "," + t.toString() + ","; + nextPointer = newName(); + if(! it.hasNext())nextPointer = ASPRule.ASP_PARAMLIST_END_POINTER.toString(); + param += nextPointer; + writer.add(new ASPStatement(ASPRule.ASP_PARAMLIST_NAME + "(" + param + ")")); + writer.add(new ASPStatement(ASPRule.ASP_PARAMLISTNUMERATION_NAME + "(" + name + "," +t + "," + paramNum + ")")); + paramNum++; + //paramDefinitions.add(new ASPStatement(ASP_PARAMLIST_NAME + "(" + param + ")")); + } + } + } + + private String newName() { + return ASPGenerator.toConstant(NameGenerator.makeNewName()); + } + + public String toString(){ + return name; + } +} diff --git a/src/de/dhbwstuttgart/sat/asp/writer/model/ASPRefType.java b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPRefType.java new file mode 100644 index 000000000..6491ff33c --- /dev/null +++ b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPRefType.java @@ -0,0 +1,21 @@ +package de.dhbwstuttgart.sat.asp.writer.model; + +import de.dhbwstuttgart.sat.asp.model.ASPRule; + +public class ASPRefType implements ASPType { + private final ASPParameterList params; + private final String name; + + public ASPRefType(String name, ASPParameterList params){ + this.name = name; + this.params = params; + } + + public ASPParameterList getParams() { + return params; + } + + public String toString(){ + return ASPRule.ASP_TYPE + "(" + name +"," + params.name + ")"; + } +} diff --git a/src/de/dhbwstuttgart/sat/asp/writer/model/ASPStatement.java b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPStatement.java new file mode 100644 index 000000000..76bb63e8d --- /dev/null +++ b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPStatement.java @@ -0,0 +1,27 @@ +package de.dhbwstuttgart.sat.asp.writer.model; + +public class ASPStatement { + private final String stmt; + public ASPStatement(String stmt) { + this.stmt = stmt; + } + + public String toString(){ + return stmt; + } + + @Override + public int hashCode() { + return stmt.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(obj instanceof ASPStatement)return stmt.equals(((ASPStatement) obj).stmt); + return false; + } + + public String getASP() { + return stmt; + } +} diff --git a/src/de/dhbwstuttgart/sat/asp/writer/model/ASPType.java b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPType.java new file mode 100644 index 000000000..da6942181 --- /dev/null +++ b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPType.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.sat.asp.writer.model; + +public interface ASPType { +} diff --git a/src/de/dhbwstuttgart/sat/asp/writer/model/ASPTypeVar.java b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPTypeVar.java new file mode 100644 index 000000000..4b07d30b4 --- /dev/null +++ b/src/de/dhbwstuttgart/sat/asp/writer/model/ASPTypeVar.java @@ -0,0 +1,14 @@ +package de.dhbwstuttgart.sat.asp.writer.model; + +public class ASPTypeVar implements ASPType{ + private final String name; + + public ASPTypeVar(String name){ + this.name = name; + } + + @Override + public String toString() { + return "typeVar("+ name +")"; + } +} diff --git a/src/de/dhbwstuttgart/syntaxtree/ASTVisitor.java b/src/de/dhbwstuttgart/syntaxtree/ASTVisitor.java index 9d3a7f6d3..cecbc6cbc 100644 --- a/src/de/dhbwstuttgart/syntaxtree/ASTVisitor.java +++ b/src/de/dhbwstuttgart/syntaxtree/ASTVisitor.java @@ -6,6 +6,8 @@ import de.dhbwstuttgart.syntaxtree.statement.literal.Null; import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.typeinference.constraints.Constraint; +import java.lang.reflect.Type; + public interface ASTVisitor extends StatementVisitor{ void visit(SourceFile sourceFile); diff --git a/src/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java b/src/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java index 50b4b470b..8a66629bf 100644 --- a/src/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java +++ b/src/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java @@ -37,7 +37,7 @@ public abstract class AbstractASTWalker implements ASTVisitor{ @Override public void visit(FormalParameter formalParameter) { - formalParameter.getType().accept(this); + formalParameter.getType().accept((ASTVisitor) this); } @Override @@ -61,7 +61,7 @@ public abstract class AbstractASTWalker implements ASTVisitor{ } private void visitMethod(Method method){ - method.getType().accept(this); + method.getReturnType().accept(this); method.getParameterList().accept(this); if(method.block != null) method.block.accept(this); @@ -105,7 +105,6 @@ public abstract class AbstractASTWalker implements ASTVisitor{ @Override public void visit(TypePlaceholder typePlaceholder) { - } @Override @@ -115,7 +114,6 @@ public abstract class AbstractASTWalker implements ASTVisitor{ @Override public void visit(GenericRefType genericRefType) { - } @Override diff --git a/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java b/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java index 540bc9939..5d5fc3e2c 100644 --- a/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java +++ b/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java @@ -60,10 +60,12 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{ return this.methods; } + /* public RefType getType() { return generateTypeOfClass(this.getClassName(), this.getGenerics(), this.getOffset()); } - + */ + //TODO: Das hier ist ein Problem. Je nach Kontext wird hier ein anderer Typ benötigt public static RefType generateTypeOfClass(JavaClassName name, GenericDeclarationList genericsOfClass ,Token offset){ //Hier wird immer ein generischer Typ generiert, also mit Type placeholdern List params = new ArrayList<>(); @@ -74,6 +76,10 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{ return new RefType(name, params, offset); } + /** + * Die Superklasse im Kontext dieser ClassOrInterface + * Das bedeutet, dass generische Variablen als GenericRefTypes dargestellt sind + */ public RefType getSuperClass() { return superClass; } diff --git a/src/de/dhbwstuttgart/syntaxtree/Constructor.java b/src/de/dhbwstuttgart/syntaxtree/Constructor.java index 2fdfb04e9..a99692bb8 100644 --- a/src/de/dhbwstuttgart/syntaxtree/Constructor.java +++ b/src/de/dhbwstuttgart/syntaxtree/Constructor.java @@ -14,9 +14,9 @@ public class Constructor extends Method { //TODO: Constructor braucht ein super-Statement - public Constructor(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, int modifiers, ParameterList parameterList, Block codeInsideConstructor, - GenericDeclarationList gtvDeclarations, Token offset, List fieldInitializations, RefType superClass) { - super(modifier, name, returnType, modifiers, parameterList, prepareBlock(codeInsideConstructor,fieldInitializations, superClass), gtvDeclarations, offset); + public Constructor(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block codeInsideConstructor, + GenericDeclarationList gtvDeclarations, Token offset, List fieldInitializations) { + super(modifier, name, returnType, parameterList, prepareBlock(codeInsideConstructor,fieldInitializations), gtvDeclarations, offset); } @@ -25,7 +25,7 @@ public class Constructor extends Method { * welche die Felder der zugehörigen Klasse dieses * Konstruktor initialisieren */ - protected static Block prepareBlock(Block constructorBlock, List fieldInitializations, RefType superClass){ + protected static Block prepareBlock(Block constructorBlock, List fieldInitializations){ List statements = constructorBlock.getStatements(); statements.add(0, new SuperCall(constructorBlock.getOffset())); return new Block(statements, constructorBlock.getOffset()); diff --git a/src/de/dhbwstuttgart/syntaxtree/Field.java b/src/de/dhbwstuttgart/syntaxtree/Field.java index 421f0ff33..8a4230e3c 100644 --- a/src/de/dhbwstuttgart/syntaxtree/Field.java +++ b/src/de/dhbwstuttgart/syntaxtree/Field.java @@ -6,7 +6,8 @@ import org.antlr.v4.runtime.Token; import java.util.ArrayList; public class Field extends SyntaxTreeNode implements TypeScope{ - + + public final int modifier; private String name; private RefTypeOrTPHOrWildcardOrGeneric type; @@ -14,6 +15,7 @@ public class Field extends SyntaxTreeNode implements TypeScope{ super(offset); this.name = name; this.type = type; + this.modifier = modifier; } public String getName(){ diff --git a/src/de/dhbwstuttgart/syntaxtree/GenericTypeVar.java b/src/de/dhbwstuttgart/syntaxtree/GenericTypeVar.java index c43fe068f..02042ca32 100644 --- a/src/de/dhbwstuttgart/syntaxtree/GenericTypeVar.java +++ b/src/de/dhbwstuttgart/syntaxtree/GenericTypeVar.java @@ -1,6 +1,7 @@ package de.dhbwstuttgart.syntaxtree; import de.dhbwstuttgart.parser.scope.GenericTypeName; +import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import org.antlr.v4.runtime.Token; @@ -53,6 +54,14 @@ public class GenericTypeVar extends SyntaxTreeNode return name; } + public String getParsedName(){ + return name.toString(); + } + + public JavaClassName definingClass(){ + return name.getParentClass(); + } + @Override public void accept(ASTVisitor visitor) { visitor.visit(this); diff --git a/src/de/dhbwstuttgart/syntaxtree/Method.java b/src/de/dhbwstuttgart/syntaxtree/Method.java index 3686fb4ee..99cd3f91c 100644 --- a/src/de/dhbwstuttgart/syntaxtree/Method.java +++ b/src/de/dhbwstuttgart/syntaxtree/Method.java @@ -22,16 +22,22 @@ import de.dhbwstuttgart.syntaxtree.statement.Block; * @author janulrich * */ -public class Method extends Field implements IItemWithOffset +public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope { public final Block block; + public final int modifier; + public final String name; private ParameterList parameterlist = new ParameterList(new ArrayList<>(), new NullToken()); private ExceptionList exceptionlist; private GenericDeclarationList generics; + private final RefTypeOrTPHOrWildcardOrGeneric returnType; - public Method(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, int modifiers, ParameterList parameterList, Block block, + public Method(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block block, GenericDeclarationList gtvDeclarations, Token offset) { - super(name, returnType, modifiers, offset); + super(offset); + this.name = name; + this.modifier = modifier; + this.returnType = returnType; this.parameterlist = parameterList; this.block = block; this.generics = gtvDeclarations; @@ -47,11 +53,20 @@ public class Method extends Field implements IItemWithOffset @Override public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { - return this.getType(); + return this.returnType; } @Override public void accept(ASTVisitor visitor) { visitor.visit(this); } + + @Override + public Token getOffset() { + return null; + } + + public String getName() { + return name; + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/SourceFile.java b/src/de/dhbwstuttgart/syntaxtree/SourceFile.java index 439a3a8c1..945ee5d8c 100644 --- a/src/de/dhbwstuttgart/syntaxtree/SourceFile.java +++ b/src/de/dhbwstuttgart/syntaxtree/SourceFile.java @@ -13,13 +13,13 @@ public class SourceFile extends SyntaxTreeNode{ private String pkgName; public final List KlassenVektor; - public final List imports; + public final Set imports; /** * Die SourceFile repräsntiert eine zu einem Syntaxbaum eingelesene Java-Datei. * SourceFile stellt dabei den Wurzelknoten des Syntaxbaumes dar. */ - public SourceFile(String pkgName, List classDefinitions, List imports){ + public SourceFile(String pkgName, List classDefinitions, Set imports){ super(new NullToken()); this.KlassenVektor = classDefinitions; this.pkgName = pkgName; @@ -31,7 +31,7 @@ public class SourceFile extends SyntaxTreeNode{ } // Get imports (to test implementation) - public List getImports(){ + public Set getImports(){ return this.imports; } diff --git a/src/de/dhbwstuttgart/syntaxtree/TypeScope.java b/src/de/dhbwstuttgart/syntaxtree/TypeScope.java index 3631eb2ec..f651648bf 100644 --- a/src/de/dhbwstuttgart/syntaxtree/TypeScope.java +++ b/src/de/dhbwstuttgart/syntaxtree/TypeScope.java @@ -2,6 +2,8 @@ package de.dhbwstuttgart.syntaxtree; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import java.util.Collection; + public interface TypeScope { Iterable getGenerics(); diff --git a/src/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java b/src/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java index b3f628a7c..6acb4214d 100644 --- a/src/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java +++ b/src/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java @@ -5,6 +5,7 @@ import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.List; +import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.GenericContext; import de.dhbwstuttgart.parser.scope.GenericTypeName; @@ -45,7 +46,11 @@ public class ASTFactory { java.lang.Class superjreClass = jreClass.getSuperclass(); RefType superClass; if(superjreClass != null){ - superClass = (RefType) createType(superjreClass, name, ""); + List params = new ArrayList<>(); + for(TypeVariable tv : superjreClass.getTypeParameters()){ + params.add(new GenericRefType(new GenericTypeName(new GenericContext( name, null),tv.getName()), new NullToken())); + } + superClass = new RefType(new JavaClassName(superjreClass.getName()), params, new NullToken()); }else{//Jede Klasse und jedes Interface erbt von Object: (auch Object selbst!) superClass = (RefType) createType(java.lang.Object.class, name, ""); } @@ -83,13 +88,12 @@ public class ASTFactory { return null; } - return new de.dhbwstuttgart.syntaxtree.Constructor(constructor.getModifiers(), name,returnType, modifier, parameterList, block, gtvDeclarations, offset, new ArrayList<>(), - createType(inClass.getSuperclass())); + return new de.dhbwstuttgart.syntaxtree.Constructor(modifier, name,returnType, parameterList, block, gtvDeclarations, offset, new ArrayList<>()); } - private static RefType createType(Class classType) { - return createClass(classType).getType(); - } + //private static RefType createType(Class classType) { + // return createClass(classType).getType(); + //} public static Method createMethod(java.lang.reflect.Method jreMethod, java.lang.Class inClass){ String name = jreMethod.getName(); @@ -105,9 +109,8 @@ public class ASTFactory { Block block = new Block(new ArrayList(), new NullToken()); GenericDeclarationList gtvDeclarations = createGenerics(jreMethod.getTypeParameters(), inClass, jreMethod.getName()); Token offset = new NullToken(); - int modifier = jreMethod.getModifiers(); - return new Method(jreMethod.getModifiers(), name,returnType, modifier, parameterList, block, gtvDeclarations, offset); + return new Method(jreMethod.getModifiers(), name,returnType, parameterList, block, gtvDeclarations, offset); } public static GenericDeclarationList createGenerics(TypeVariable[] typeParameters, Class context, String methodName){ @@ -182,6 +185,9 @@ public class ASTFactory { public static ClassOrInterface createObjectClass() { return createClass(Object.class); } + public static RefType createObjectType() { + return new RefType(createClass(Object.class).getClassName(), new NullToken()); + } /* public Constructor createEmptyConstructor(Class parent){ diff --git a/src/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java b/src/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java index c154e86f4..a962c2bc5 100644 --- a/src/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java +++ b/src/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java @@ -6,37 +6,36 @@ import java.util.stream.Collectors; import de.dhbwstuttgart.exceptions.DebugException; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.FCGenerator; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.syntaxtree.type.Void; +import de.dhbwstuttgart.syntaxtree.type.WildcardType; +import de.dhbwstuttgart.typeinference.constraints.Constraint; import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; import de.dhbwstuttgart.typeinference.constraints.Pair; -import de.dhbwstuttgart.typeinference.result.PairTPHequalRefType; +import de.dhbwstuttgart.typeinference.result.PairTPHEqualTPH; +import de.dhbwstuttgart.typeinference.result.PairTPHequalRefTypeOrWildcardType; import de.dhbwstuttgart.typeinference.result.PairTPHsmallerTPH; import de.dhbwstuttgart.typeinference.result.ResultPair; -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; - +import de.dhbwstuttgart.typeinference.unify.model.*; public class UnifyTypeFactory { - public static FiniteClosure generateFC(List fromAvailableClasses){ - HashSet pairs = new HashSet<>(); - for(ClassOrInterface cl : fromAvailableClasses){ - UnifyType t1 = UnifyTypeFactory.convert(cl.getType()); - UnifyType t2 = UnifyTypeFactory.convert(cl.getSuperClass()); - pairs.add(generateSmallerPair(t1, t2)); - } - return new FiniteClosure(pairs); + public static FiniteClosure generateFC(List fromClasses) throws ClassNotFoundException { + /* + Die transitive Hülle muss funktionieren. + Man darf schreiben List extends AL + und Vector extends List + hier muss dann aber dennoch die Vererbung V < L < AL + hergestellt werden. + In einem solchen Vererbungsbaum dürfen die TPH auch die gleichen Namen haben. + Generell dürfen sie immer die gleichen Namen haben. + TODO: die transitive Hülle bilden + */ + return new FiniteClosure(FCGenerator.toFC(fromClasses)); } public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr){ @@ -105,7 +104,7 @@ public class UnifyTypeFactory { } public static UnifyType convert(GenericRefType t){ - return new ReferenceType(t.getUniqueIdentifier()); + return new ReferenceType(t.getParsedName()); } public static UnifyType convert(WildcardType t){ @@ -121,6 +120,10 @@ public class UnifyTypeFactory { return constraints.map(UnifyTypeFactory::convert); } + public static Constraint convert(Constraint constraint){ + return constraint.stream().map(UnifyTypeFactory::convert).collect(Collectors.toCollection(Constraint::new)); + } + public static UnifyPair convert(Pair p) { if(p.GetOperator().equals(PairOperator.SMALLERDOT)) { UnifyPair ret = generateSmallerDotPair(UnifyTypeFactory.convert(p.TA1) @@ -148,12 +151,19 @@ public class UnifyTypeFactory { RefTypeOrTPHOrWildcardOrGeneric tr = UnifyTypeFactory.convert(mp.getRhsType(), tphs); if(tl instanceof TypePlaceholder){ if(tr instanceof TypePlaceholder) { - if(mp.getPairOp().equals(PairOperator.EQUALSDOT)) - throw new DebugException("TPH =. TPH ist ein ungültiges Ergebnis"); - else + + if(mp.getPairOp().equals(PairOperator.EQUALSDOT)) { + return new PairTPHEqualTPH((TypePlaceholder)tl, (TypePlaceholder)tr); + //Einfach ignorieren TODO: Das hier muss ausgebessert werden: + //return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, ASTFactory.createObjectType()); + }else{ return new PairTPHsmallerTPH((TypePlaceholder)tl, (TypePlaceholder)tr); - } - return new PairTPHequalRefType((TypePlaceholder)tl, (RefType) tr); + } + }else if(tr instanceof RefType){ + return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (RefType) tr); + }else if(tr instanceof WildcardType){ + return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (WildcardType) tr); + }else throw new NotImplementedException(); }else throw new NotImplementedException(); } diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/Assign.java b/src/de/dhbwstuttgart/syntaxtree/statement/Assign.java index ed385c255..3af2de6ff 100644 --- a/src/de/dhbwstuttgart/syntaxtree/statement/Assign.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/Assign.java @@ -4,7 +4,6 @@ package de.dhbwstuttgart.syntaxtree.statement; import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; -import de.dhbwstuttgart.typeinference.constraints.ConstraintsFactory; import de.dhbwstuttgart.typeinference.unify.model.PairOperator; import org.antlr.v4.runtime.Token; diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/FieldVar.java b/src/de/dhbwstuttgart/syntaxtree/statement/FieldVar.java index ba56fc5a5..9380e9516 100644 --- a/src/de/dhbwstuttgart/syntaxtree/statement/FieldVar.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/FieldVar.java @@ -7,7 +7,6 @@ import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; import de.dhbwstuttgart.typeinference.constraints.Constraint; import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; -import de.dhbwstuttgart.typeinference.constraints.ConstraintsFactory; import de.dhbwstuttgart.typeinference.unify.model.PairOperator; import org.antlr.v4.runtime.Token; diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java b/src/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java index 771423d8f..435b1b654 100644 --- a/src/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java @@ -8,7 +8,6 @@ import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; import de.dhbwstuttgart.typeinference.constraints.Constraint; import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; -import de.dhbwstuttgart.typeinference.constraints.ConstraintsFactory; import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; import de.dhbwstuttgart.typeinference.constraints.Pair; import de.dhbwstuttgart.typeinference.unify.model.PairOperator; diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/NewClass.java b/src/de/dhbwstuttgart/syntaxtree/statement/NewClass.java index 258da2e51..d29f3d53b 100644 --- a/src/de/dhbwstuttgart/syntaxtree/statement/NewClass.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/NewClass.java @@ -15,7 +15,6 @@ import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; import de.dhbwstuttgart.typeinference.constraints.Constraint; import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; -import de.dhbwstuttgart.typeinference.constraints.ConstraintsFactory; import de.dhbwstuttgart.typeinference.constraints.Pair; import de.dhbwstuttgart.typeinference.unify.model.PairOperator; import org.antlr.v4.runtime.Token; diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/Return.java b/src/de/dhbwstuttgart/syntaxtree/statement/Return.java index 434f1ce9b..5a6a53120 100644 --- a/src/de/dhbwstuttgart/syntaxtree/statement/Return.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/Return.java @@ -1,9 +1,6 @@ package de.dhbwstuttgart.syntaxtree.statement; import de.dhbwstuttgart.syntaxtree.StatementVisitor; -import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; -import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; -import de.dhbwstuttgart.typeinference.constraints.ConstraintsFactory; import org.antlr.v4.runtime.Token; diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/This.java b/src/de/dhbwstuttgart/syntaxtree/statement/This.java index 81899052d..d35e77973 100644 --- a/src/de/dhbwstuttgart/syntaxtree/statement/This.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/This.java @@ -3,14 +3,7 @@ package de.dhbwstuttgart.syntaxtree.statement; import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; -import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; -import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; -import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation; -import de.dhbwstuttgart.typeinference.constraints.ConstraintsFactory; -import de.dhbwstuttgart.typeinference.constraints.Pair; -import de.dhbwstuttgart.typeinference.unify.model.PairOperator; import org.antlr.v4.runtime.Token; -import org.antlr.v4.runtime.atn.SemanticContext; import de.dhbwstuttgart.exceptions.NotImplementedException; public class This extends Expression diff --git a/src/de/dhbwstuttgart/syntaxtree/type/ExtendsWildcardType.java b/src/de/dhbwstuttgart/syntaxtree/type/ExtendsWildcardType.java index 1852b3238..d5abd93b8 100644 --- a/src/de/dhbwstuttgart/syntaxtree/type/ExtendsWildcardType.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/ExtendsWildcardType.java @@ -40,6 +40,11 @@ public class ExtendsWildcardType extends WildcardType{ visitor.visit(this); } + @Override + public A acceptTV(TypeVisitor visitor) { + return visitor.visit(this); + } + @Override public void accept(ResultSetVisitor visitor) { visitor.visit(this); diff --git a/src/de/dhbwstuttgart/syntaxtree/type/GenericRefType.java b/src/de/dhbwstuttgart/syntaxtree/type/GenericRefType.java index 121a6c99c..a5d394aaa 100644 --- a/src/de/dhbwstuttgart/syntaxtree/type/GenericRefType.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/GenericRefType.java @@ -20,7 +20,7 @@ public class GenericRefType extends RefTypeOrTPHOrWildcardOrGeneric return name; } - public String getUniqueIdentifier(){ + public String getParsedName(){ return name.toString(); } @@ -29,6 +29,11 @@ public class GenericRefType extends RefTypeOrTPHOrWildcardOrGeneric visitor.visit(this); } + @Override + public A acceptTV(TypeVisitor visitor) { + return visitor.visit(this); + } + @Override public void accept(ResultSetVisitor visitor) { visitor.visit(this); diff --git a/src/de/dhbwstuttgart/syntaxtree/type/RefType.java b/src/de/dhbwstuttgart/syntaxtree/type/RefType.java index b28761199..4cf852977 100644 --- a/src/de/dhbwstuttgart/syntaxtree/type/RefType.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/RefType.java @@ -6,6 +6,7 @@ import de.dhbwstuttgart.typeinference.result.ResultSetVisitor; import org.antlr.v4.runtime.Token; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; @@ -28,7 +29,15 @@ public class RefType extends RefTypeOrTPHOrWildcardOrGeneric @Override public String toString(){ - return this.name.toString(); + String params = "<"; + Iterator it = parameter.iterator(); + while(it.hasNext()){ + RefTypeOrTPHOrWildcardOrGeneric param = it.next(); + params += param.toString(); + if(it.hasNext())params += ", "; + } + params += ">"; + return this.name.toString() + params; } @Override @@ -100,6 +109,11 @@ public class RefType extends RefTypeOrTPHOrWildcardOrGeneric visitor.visit(this); } + @Override + public A acceptTV(TypeVisitor visitor) { + return visitor.visit(this); + } + @Override public void accept(ResultSetVisitor visitor) { visitor.visit(this); diff --git a/src/de/dhbwstuttgart/syntaxtree/type/RefTypeOrTPHOrWildcardOrGeneric.java b/src/de/dhbwstuttgart/syntaxtree/type/RefTypeOrTPHOrWildcardOrGeneric.java index 75638712d..8a573d160 100644 --- a/src/de/dhbwstuttgart/syntaxtree/type/RefTypeOrTPHOrWildcardOrGeneric.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/RefTypeOrTPHOrWildcardOrGeneric.java @@ -13,5 +13,6 @@ public abstract class RefTypeOrTPHOrWildcardOrGeneric extends SyntaxTreeNode{ @Override public abstract void accept(ASTVisitor visitor); + public abstract A acceptTV(TypeVisitor visitor); public abstract void accept(ResultSetVisitor visitor); } diff --git a/src/de/dhbwstuttgart/syntaxtree/type/SuperWildcardType.java b/src/de/dhbwstuttgart/syntaxtree/type/SuperWildcardType.java index 3fc8ffb98..f630583e9 100644 --- a/src/de/dhbwstuttgart/syntaxtree/type/SuperWildcardType.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/SuperWildcardType.java @@ -50,6 +50,11 @@ public class SuperWildcardType extends WildcardType{ visitor.visit(this); } + @Override + public A acceptTV(TypeVisitor visitor) { + return visitor.visit(this); + } + @Override public void accept(ResultSetVisitor visitor) { visitor.visit(this); diff --git a/src/de/dhbwstuttgart/syntaxtree/type/TypePlaceholder.java b/src/de/dhbwstuttgart/syntaxtree/type/TypePlaceholder.java index 99a34cd56..ab4414fd2 100644 --- a/src/de/dhbwstuttgart/syntaxtree/type/TypePlaceholder.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/TypePlaceholder.java @@ -73,6 +73,11 @@ public class TypePlaceholder extends RefTypeOrTPHOrWildcardOrGeneric visitor.visit(this); } + @Override + public A acceptTV(TypeVisitor visitor) { + return visitor.visit(this); + } + @Override public void accept(ResultSetVisitor visitor) { visitor.visit(this); diff --git a/src/de/dhbwstuttgart/syntaxtree/type/TypeVisitor.java b/src/de/dhbwstuttgart/syntaxtree/type/TypeVisitor.java new file mode 100644 index 000000000..a3b7796f4 --- /dev/null +++ b/src/de/dhbwstuttgart/syntaxtree/type/TypeVisitor.java @@ -0,0 +1,13 @@ +package de.dhbwstuttgart.syntaxtree.type; + +public interface TypeVisitor { + A visit(RefType refType); + + A visit(SuperWildcardType superWildcardType); + + A visit(TypePlaceholder typePlaceholder); + + A visit(ExtendsWildcardType extendsWildcardType); + + A visit(GenericRefType genericRefType); +} diff --git a/src/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java b/src/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java index 4b4ac7dc2..d56c39d8c 100644 --- a/src/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java +++ b/src/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java @@ -11,7 +11,7 @@ import de.dhbwstuttgart.syntaxtree.type.*; import java.lang.reflect.Modifier; import java.util.Iterator; -public class OutputGenerator implements ASTVisitor { +public class OutputGenerator implements ASTVisitor{ private static final String TAB = " "; String tabs = ""; protected final StringBuilder out; @@ -81,7 +81,7 @@ public class OutputGenerator implements ASTVisitor { @Override public void visit(Method method) { - method.getType().accept(this); + method.getReturnType().accept(this); out.append(" " + method.getName()); method.getParameterList().accept(this); if(method.block != null) diff --git a/src/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java b/src/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java index b9eea3c69..29492c317 100644 --- a/src/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java +++ b/src/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java @@ -100,7 +100,12 @@ class TypeToInsertString implements ResultSetVisitor{ } @Override - public void visit(PairTPHequalRefType p) { + public void visit(PairTPHequalRefTypeOrWildcardType p) { + + } + + @Override + public void visit(PairTPHEqualTPH p) { } diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java b/src/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java index 88b2bd4a9..62867a264 100644 --- a/src/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java +++ b/src/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java @@ -1,24 +1,31 @@ package de.dhbwstuttgart.typeinference.assumptions; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.TypeScope; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.constraints.GenericsResolver; public class FieldAssumption extends Assumption{ - private RefTypeOrTPHOrWildcardOrGeneric receiverType; + private ClassOrInterface receiverClass; private RefTypeOrTPHOrWildcardOrGeneric type; - public FieldAssumption(RefTypeOrTPHOrWildcardOrGeneric receiverType, + public FieldAssumption(ClassOrInterface receiverType, RefTypeOrTPHOrWildcardOrGeneric type, TypeScope scope){ super(scope); this.type = type; - this.receiverType = receiverType; + this.receiverClass = receiverType; } - public RefTypeOrTPHOrWildcardOrGeneric getReceiverType() { - return receiverType; + public ClassOrInterface getReceiverClass() { + return receiverClass; } - public RefTypeOrTPHOrWildcardOrGeneric getType() { - return type; + public RefTypeOrTPHOrWildcardOrGeneric getType(GenericsResolver resolver) { + return resolver.resolve(type); + } + + public RefTypeOrTPHOrWildcardOrGeneric getReceiverType(GenericsResolver resolver) { + + return null; } } diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/FunNClass.java b/src/de/dhbwstuttgart/typeinference/assumptions/FunNClass.java new file mode 100644 index 000000000..0eba225d1 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/assumptions/FunNClass.java @@ -0,0 +1,43 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import com.sun.org.apache.regexp.internal.RE; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.GenericContext; +import de.dhbwstuttgart.parser.scope.GenericTypeName; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.GenericDeclarationList; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.syntaxtree.factory.NameGenerator; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import org.antlr.v4.runtime.Token; + +import java.util.ArrayList; +import java.util.List; + +public class FunNClass extends ClassOrInterface { + public FunNClass(List funNParams) { + super(0, new JavaClassName("Fun"+(funNParams.size()-1)), new ArrayList<>(), + createMethods(funNParams), new ArrayList<>(), createGenerics(funNParams), + ASTFactory.createObjectType(), true, new ArrayList<>(), new NullToken()); + + + } + + private static GenericDeclarationList createGenerics(List funNParams) { + List generics = new ArrayList<>(); + for(RefTypeOrTPHOrWildcardOrGeneric param : funNParams){ + generics.add(new GenericTypeVar(new GenericTypeName(new GenericContext( + new JavaClassName("Fun"+(funNParams.size()-1)), null), NameGenerator.makeNewName()), + new ArrayList<>(), new NullToken(), new NullToken())); + } + return new GenericDeclarationList(generics, new NullToken()); + } + + private static List createMethods(List funNParams) { + return null; + } +} diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java b/src/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java index bbeff0d71..066c3246f 100644 --- a/src/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java +++ b/src/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java @@ -1,20 +1,27 @@ package de.dhbwstuttgart.typeinference.assumptions; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.ParameterList; import de.dhbwstuttgart.syntaxtree.TypeScope; import de.dhbwstuttgart.syntaxtree.statement.Assign; +import de.dhbwstuttgart.syntaxtree.type.FunN; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.constraints.GenericsResolver; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class MethodAssumption extends Assumption{ - private RefType receiver; + private ClassOrInterface receiver; private RefTypeOrTPHOrWildcardOrGeneric retType; List params; - public MethodAssumption(RefType receiver, RefTypeOrTPHOrWildcardOrGeneric retType, + public MethodAssumption(ClassOrInterface receiver, RefTypeOrTPHOrWildcardOrGeneric retType, List params, TypeScope scope){ super(scope); this.receiver = receiver; @@ -22,7 +29,14 @@ public class MethodAssumption extends Assumption{ this.params = params; } + /* public RefType getReceiverType() { + + return receiver; + } + */ + + public ClassOrInterface getReceiver(){ return receiver; } @@ -30,7 +44,35 @@ public class MethodAssumption extends Assumption{ return retType; } - public List getArgTypes() { - return params; + public List getArgTypes(GenericsResolver resolver) { + List ret = new ArrayList<>(); + for(RefTypeOrTPHOrWildcardOrGeneric param : params){ + if(param instanceof GenericRefType){ //Generics in den Assumptions müssen umgewandelt werden. + param = resolver.resolve((GenericRefType) param); + } + ret.add(param); + } + return ret; + } + + /** + * + * @param resolver + * @return + */ + public RefTypeOrTPHOrWildcardOrGeneric getReceiverType(GenericsResolver resolver) { + List params = new ArrayList<>(); + for(GenericTypeVar gtv : receiver.getGenerics()){ + //Die Generics werden alle zu TPHs umgewandelt. + params.add(resolver.resolve(new GenericRefType(gtv.getName(), new NullToken()))); + } + RefTypeOrTPHOrWildcardOrGeneric receiverType; + if(receiver instanceof FunNClass){ + receiverType = new FunN(params); + }else{ + receiverType = new RefType(receiver.getClassName(), params, new NullToken()); + } + + return receiverType; } } diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/TypeInferenceInformation.java b/src/de/dhbwstuttgart/typeinference/assumptions/TypeInferenceInformation.java index 90548e6d3..737cd0c47 100644 --- a/src/de/dhbwstuttgart/typeinference/assumptions/TypeInferenceInformation.java +++ b/src/de/dhbwstuttgart/typeinference/assumptions/TypeInferenceInformation.java @@ -46,7 +46,8 @@ public class TypeInferenceInformation { for(ClassOrInterface cl : classes){ for(Field m : cl.getFieldDecl()){ if(m.getName().equals(name)){ - ret.add(new FieldAssumption(cl.getType(), checkGTV(m.getType()), new TypeScopeContainer(cl, m))); + + ret.add(new FieldAssumption(cl, checkGTV(m.getType()), new TypeScopeContainer(cl, m))); } } } diff --git a/src/de/dhbwstuttgart/typeinference/constraints/ConstraintsFactory.java b/src/de/dhbwstuttgart/typeinference/constraints/ConstraintsFactory.java deleted file mode 100644 index 3d1058da2..000000000 --- a/src/de/dhbwstuttgart/typeinference/constraints/ConstraintsFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -package de.dhbwstuttgart.typeinference.constraints; - -import de.dhbwstuttgart.exceptions.DebugException; -import de.dhbwstuttgart.syntaxtree.GenericTypeVar; -import de.dhbwstuttgart.syntaxtree.TypeScope; -import de.dhbwstuttgart.syntaxtree.type.GenericRefType; -import de.dhbwstuttgart.syntaxtree.type.RefType; -import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; -import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; -import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; -import de.dhbwstuttgart.typeinference.unify.model.PairOperator; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ConstraintsFactory { - - public static Pair createPair(RefTypeOrTPHOrWildcardOrGeneric t1, RefTypeOrTPHOrWildcardOrGeneric t2, - PairOperator equalsdot, TypeScope currentScope, TypeScope additionalScope, - GenericsResolver resolver){ - //Check whether Generics are in the same class and resolve all other generics: - return new Pair(checkGeneric(t1, currentScope, additionalScope,resolver), - checkGeneric(t2, currentScope,additionalScope, resolver), equalsdot); - } - public static Pair createPair(RefTypeOrTPHOrWildcardOrGeneric t1, - RefTypeOrTPHOrWildcardOrGeneric t2, TypeScope currentScope, TypeScope additionalScope, - GenericsResolver resolver){ - return createPair(t1,t2,PairOperator.SMALLERDOT, currentScope, additionalScope, resolver); - } - - private static RefTypeOrTPHOrWildcardOrGeneric checkGeneric(RefTypeOrTPHOrWildcardOrGeneric type, - TypeScope currentScope, TypeScope additionalScope, - GenericsResolver resolver){ - if(type instanceof GenericRefType){ - //TODO: Für Generics müssen auch noch Constraints generiert werden - for(GenericTypeVar genericTypeVar : currentScope.getGenerics()){ - if(genericTypeVar.getName().toString().equals(((GenericRefType)type).getName().toString())){ - return new RefType(((GenericRefType)type).getName(),type.getOffset()); - } - } - //Nicht in den Generics in diesem Kontext enthalten: - TypePlaceholder ret = null; - for(GenericTypeVar genericTypeVar : additionalScope.getGenerics()){ - if(genericTypeVar.getName().equals(((GenericRefType)type).getName())){ - ret = resolver.resolve(genericTypeVar); - } - } - if(ret == null) - throw new DebugException("Der Generic " + ((GenericRefType) type).getName() + " kommt in keine TypeScope vor!"); - return ret; - }else{ - return type; - } - } - -} diff --git a/src/de/dhbwstuttgart/typeinference/constraints/GenericsResolver.java b/src/de/dhbwstuttgart/typeinference/constraints/GenericsResolver.java index d72b6835a..59bcd4b4c 100644 --- a/src/de/dhbwstuttgart/typeinference/constraints/GenericsResolver.java +++ b/src/de/dhbwstuttgart/typeinference/constraints/GenericsResolver.java @@ -1,6 +1,8 @@ package de.dhbwstuttgart.typeinference.constraints; import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; /** @@ -8,5 +10,5 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; * TODO: Erklörung! */ public interface GenericsResolver { - public TypePlaceholder resolve(GenericTypeVar generic); + public RefTypeOrTPHOrWildcardOrGeneric resolve(RefTypeOrTPHOrWildcardOrGeneric generic); } diff --git a/src/de/dhbwstuttgart/typeinference/constraints/Pair.java b/src/de/dhbwstuttgart/typeinference/constraints/Pair.java index c7e1f6b65..ab0cb3ea7 100644 --- a/src/de/dhbwstuttgart/typeinference/constraints/Pair.java +++ b/src/de/dhbwstuttgart/typeinference/constraints/Pair.java @@ -104,5 +104,8 @@ public class Pair implements Serializable return eOperator; } + public boolean OperatorSmallerDot() { + return eOperator == PairOperator.SMALLERDOT; + } } // ino.end diff --git a/src/de/dhbwstuttgart/typeinference/result/PairTPHEqualTPH.java b/src/de/dhbwstuttgart/typeinference/result/PairTPHEqualTPH.java new file mode 100644 index 000000000..64d0ce0be --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/result/PairTPHEqualTPH.java @@ -0,0 +1,15 @@ +package de.dhbwstuttgart.typeinference.result; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +public class PairTPHEqualTPH extends ResultPair { + public PairTPHEqualTPH(TypePlaceholder tl, TypePlaceholder tr) { + super(tl, tr); + } + + @Override + public void accept(ResultSetVisitor visitor) { + visitor.visit(this); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/result/PairTPHequalRefType.java b/src/de/dhbwstuttgart/typeinference/result/PairTPHequalRefTypeOrWildcardType.java similarity index 68% rename from src/de/dhbwstuttgart/typeinference/result/PairTPHequalRefType.java rename to src/de/dhbwstuttgart/typeinference/result/PairTPHequalRefTypeOrWildcardType.java index bf29ce528..ef6dd00a0 100644 --- a/src/de/dhbwstuttgart/typeinference/result/PairTPHequalRefType.java +++ b/src/de/dhbwstuttgart/typeinference/result/PairTPHequalRefTypeOrWildcardType.java @@ -7,11 +7,11 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; /** * Steht für A =. RefType */ -public class PairTPHequalRefType extends ResultPair{ +public class PairTPHequalRefTypeOrWildcardType extends ResultPair{ public final TypePlaceholder left; - public final RefType right; + public final RefTypeOrTPHOrWildcardOrGeneric right; - public PairTPHequalRefType(TypePlaceholder left, RefType right){ + public PairTPHequalRefTypeOrWildcardType(TypePlaceholder left, RefTypeOrTPHOrWildcardOrGeneric right){ super(left, right); this.left = left; this.right = right; diff --git a/src/de/dhbwstuttgart/typeinference/result/ResultPair.java b/src/de/dhbwstuttgart/typeinference/result/ResultPair.java index 4c7541980..4415a9397 100644 --- a/src/de/dhbwstuttgart/typeinference/result/ResultPair.java +++ b/src/de/dhbwstuttgart/typeinference/result/ResultPair.java @@ -5,22 +5,22 @@ import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; /** * Paare, welche das Unifikationsergebnis darstellen */ -public abstract class ResultPair { - private final RefTypeOrTPHOrWildcardOrGeneric left; - private final RefTypeOrTPHOrWildcardOrGeneric right; +public abstract class ResultPair { + private final A left; + private final B right; public abstract void accept(ResultSetVisitor visitor); - public ResultPair(RefTypeOrTPHOrWildcardOrGeneric left, RefTypeOrTPHOrWildcardOrGeneric right){ + public ResultPair(A left, B right){ this.left = left; this.right = right; } - public RefTypeOrTPHOrWildcardOrGeneric getLeft() { + public A getLeft() { return left; } - public RefTypeOrTPHOrWildcardOrGeneric getRight() { + public B getRight() { return right; } } diff --git a/src/de/dhbwstuttgart/typeinference/result/ResultSet.java b/src/de/dhbwstuttgart/typeinference/result/ResultSet.java index f3c81b551..19701d7b7 100644 --- a/src/de/dhbwstuttgart/typeinference/result/ResultSet.java +++ b/src/de/dhbwstuttgart/typeinference/result/ResultSet.java @@ -1,16 +1,10 @@ package de.dhbwstuttgart.typeinference.result; import de.dhbwstuttgart.exceptions.NotImplementedException; -import de.dhbwstuttgart.syntaxtree.ASTVisitor; -import de.dhbwstuttgart.syntaxtree.AbstractASTWalker; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.type.*; -import de.dhbwstuttgart.typeinference.constraints.Pair; -import javax.xml.transform.Result; -import java.lang.reflect.Type; -import java.util.ArrayList; import java.util.HashSet; -import java.util.List; import java.util.Set; public class ResultSet { @@ -22,6 +16,7 @@ public class ResultSet { public ResolvedType resolveType(RefTypeOrTPHOrWildcardOrGeneric type) { if(type instanceof TypePlaceholder) return new Resolver(this).resolve((TypePlaceholder)type); + if(type instanceof GenericRefType)return new ResolvedType(type, new HashSet<>()); if(type instanceof RefType){ RelatedTypeWalker related = new RelatedTypeWalker(null, this); type.accept(related); @@ -49,6 +44,11 @@ class Resolver implements ResultSetVisitor { public ResolvedType resolve(TypePlaceholder tph){ toResolve = tph; resolved = null; + for(ResultPair resultPair : result.results){ + if(resultPair instanceof PairTPHEqualTPH && ((PairTPHEqualTPH) resultPair).getLeft().equals(toResolve)){ + return resolve(((PairTPHEqualTPH) resultPair).getRight()); + } + } for(ResultPair resultPair : result.results){ resultPair.accept(this); } @@ -70,7 +70,7 @@ class Resolver implements ResultSetVisitor { } @Override - public void visit(PairTPHequalRefType p) { + public void visit(PairTPHequalRefTypeOrWildcardType p) { if(p.left.equals(toResolve)){ resolved = p.right; RelatedTypeWalker related = new RelatedTypeWalker(null, result); @@ -79,6 +79,11 @@ class Resolver implements ResultSetVisitor { } } + @Override + public void visit(PairTPHEqualTPH p) { + //Do nothing. Dieser Fall wird in der resolve-Methode abgefangen + } + @Override public void visit(RefType refType) { @@ -134,7 +139,7 @@ class TPHResolver implements ResultSetVisitor { } @Override - public void visit(PairTPHequalRefType p) { + public void visit(PairTPHequalRefTypeOrWildcardType p) { TypePlaceholder otherSide = null; if(p.right.equals(tph)){ otherSide = p.left; @@ -146,6 +151,11 @@ class TPHResolver implements ResultSetVisitor { } } + @Override + public void visit(PairTPHEqualTPH p) { + //ignorieren. Wird vom Resolver behandelt + } + @Override public void visit(RefType refType) { @@ -209,12 +219,17 @@ class RelatedTypeWalker implements ResultSetVisitor { } @Override - public void visit(PairTPHequalRefType p) { + public void visit(PairTPHequalRefTypeOrWildcardType p) { if(p.getLeft().equals(toResolve)){ p.getRight().accept(this); } } + @Override + public void visit(PairTPHEqualTPH p) { + //Kann ignoriert werden. Diese Fälle werden vom Resolver behandelt + } + /* Die folgenden Funktionen fügen alle TPHs an die relatedTPHs an, denen sie begegnen: Das wird verwendet, wenn alle relatedTPHs aus den Parametern eines RefTypes angefügt werden sollen diff --git a/src/de/dhbwstuttgart/typeinference/result/ResultSetVisitor.java b/src/de/dhbwstuttgart/typeinference/result/ResultSetVisitor.java index 3f21ae314..bed742dd6 100644 --- a/src/de/dhbwstuttgart/typeinference/result/ResultSetVisitor.java +++ b/src/de/dhbwstuttgart/typeinference/result/ResultSetVisitor.java @@ -4,7 +4,8 @@ import de.dhbwstuttgart.syntaxtree.type.*; public interface ResultSetVisitor { void visit(PairTPHsmallerTPH p); - void visit(PairTPHequalRefType p); + void visit(PairTPHequalRefTypeOrWildcardType p); + void visit(PairTPHEqualTPH p); void visit(RefType refType); @@ -15,4 +16,5 @@ public interface ResultSetVisitor { void visit(TypePlaceholder typePlaceholder); void visit(ExtendsWildcardType extendsWildcardType); + } diff --git a/src/de/dhbwstuttgart/typeinference/typeAlgo/GenericsResolverSameName.java b/src/de/dhbwstuttgart/typeinference/typeAlgo/GenericsResolverSameName.java new file mode 100644 index 000000000..f8754e638 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/typeAlgo/GenericsResolverSameName.java @@ -0,0 +1,56 @@ +package de.dhbwstuttgart.typeinference.typeAlgo; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.*; +import de.dhbwstuttgart.typeinference.constraints.GenericsResolver; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * Ein GenericsResolver, welcher Generics mit dem selben Namen den selben TPH zuordnet + */ +public class GenericsResolverSameName implements GenericsResolver, TypeVisitor{ + + HashMap map = new HashMap<>(); + + @Override + public RefTypeOrTPHOrWildcardOrGeneric resolve(RefTypeOrTPHOrWildcardOrGeneric generic) { + return generic.acceptTV(this); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(RefType refType) { + List params = new ArrayList<>(); + for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){ + params.add(param.acceptTV(this)); + } + RefType ret = new RefType(refType.getName(), params, refType.getOffset()); + return ret; + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(SuperWildcardType superWildcardType) { + return new SuperWildcardType(superWildcardType.getInnerType().acceptTV(this), superWildcardType.getOffset()); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(TypePlaceholder typePlaceholder) { + return typePlaceholder; + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(ExtendsWildcardType extendsWildcardType) { + return new SuperWildcardType(extendsWildcardType.getInnerType().acceptTV(this), extendsWildcardType.getOffset()); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(GenericRefType genericRefType) { + String name = genericRefType.getParsedName(); + if(!map.containsKey(name)){ + map.put(name, TypePlaceholder.fresh(genericRefType.getOffset())); + } + return map.get(name); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index bf063d710..3448e8e3d 100644 --- a/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -6,15 +6,14 @@ import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.exceptions.TypeinferenceException; import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.parser.antlr.Java8Parser; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.statement.literal.Literal; import de.dhbwstuttgart.syntaxtree.statement.literal.Null; -import de.dhbwstuttgart.syntaxtree.type.FunN; -import de.dhbwstuttgart.syntaxtree.type.RefType; -import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; -import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption; +import de.dhbwstuttgart.typeinference.assumptions.FunNClass; import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; import de.dhbwstuttgart.typeinference.constraints.*; @@ -36,14 +35,15 @@ public class TYPEStmt implements StatementVisitor{ return constraintsSet; } + /** + * Erstellt einen neuen GenericResolver + * Die Idee dieser Datenstruktur ist es, GTVs einen eindeutigen TPH zuzuweisen. + * Bei Methodenaufrufen oder anderen Zugriffen, bei denen alle benutzten GTVs jeweils einen einheitlichen TPH bekommen müssen + * kann diese Klasse eingesetzt werden. Wichtig ist, dass hierfür jeweils eine frische Instanz benutzt wird. + * @return + */ private static GenericsResolver getResolverInstance(){ - Map map = new HashMap<>(); - return generic -> { - if(map.containsKey(generic))return map.get(generic); - TypePlaceholder ret = TypePlaceholder.fresh(generic.getOffset()); - map.put(generic, ret); - return ret; - }; + return new GenericsResolverSameName(); } private static TypeScope createTypeScope(ClassOrInterface cl, Method method) { @@ -64,11 +64,11 @@ public class TYPEStmt implements StatementVisitor{ //lambdaParams.add(tphRetType); lambdaParams.add(0,tphRetType); constraintsSet.addUndConstraint( - ConstraintsFactory.createPair(lambdaExpression.getType(), - new FunN(lambdaParams),PairOperator.EQUALSDOT,info.getCurrentTypeScope(), createNullTypeScope(), getResolverInstance())); + new Pair(lambdaExpression.getType(), + new FunN(lambdaParams),PairOperator.EQUALSDOT)); constraintsSet.addUndConstraint( - ConstraintsFactory.createPair(lambdaExpression.getReturnType(), - tphRetType,info.getCurrentTypeScope(), createNullTypeScope(), getResolverInstance())); + new Pair(lambdaExpression.getReturnType(), + tphRetType,PairOperator.EQUALSDOT)); //Constraints des Bodys generieren: TYPEStmt lambdaScope = new TYPEStmt(new TypeInferenceBlockInformation(info, lambdaExpression)); @@ -80,8 +80,8 @@ public class TYPEStmt implements StatementVisitor{ public void visit(Assign assign) { assign.lefSide.accept(this); assign.rightSide.accept(this); - constraintsSet.addUndConstraint(ConstraintsFactory.createPair( - assign.rightSide.getType(), assign.lefSide.getType(), PairOperator.SMALLERDOT, info.getCurrentTypeScope(), createNullTypeScope(), getResolverInstance())); + constraintsSet.addUndConstraint(new Pair( + assign.rightSide.getType(), assign.lefSide.getType(), PairOperator.SMALLERDOT)); } @Override @@ -113,15 +113,21 @@ public class TYPEStmt implements StatementVisitor{ for(FieldAssumption fieldAssumption : info.getFields(fieldVar.fieldVarName)){ Constraint constraint = new Constraint(); GenericsResolver resolver = getResolverInstance(); + /*TODO Hier muss der Typ der Klasse ermittelt werden. In diesem müssen Generics mit TPHs ausgetauscht werden constraint.add(ConstraintsFactory.createPair( fieldVar.receiver.getType(),fieldAssumption.getReceiverType(), info.getCurrentTypeScope(), fieldAssumption.getTypeScope(), resolver)); - constraint.add(ConstraintsFactory.createPair( - fieldVar.getType(),fieldAssumption.getType(), info.getCurrentTypeScope(), fieldAssumption.getTypeScope(), resolver)); + */ + constraint.add(new Pair(fieldVar.receiver.getType(), fieldAssumption.getReceiverType(resolver), PairOperator.EQUALSDOT)); + constraint.add(new Pair( + fieldVar.getType(), fieldAssumption.getType(resolver), PairOperator.EQUALSDOT)); oderConstraints.add(constraint); } if(oderConstraints.size() == 0) throw new TypeinferenceException("Kein Feld "+fieldVar.fieldVarName+ " gefunden", fieldVar.getOffset()); constraintsSet.addOderConstraint(oderConstraints); + + //Wegen dem Problem oben: + throw new NotImplementedException(); } @Override @@ -156,8 +162,7 @@ public class TYPEStmt implements StatementVisitor{ Set methodConstraints = new HashSet<>(); for(MethodAssumption m : this.getMethods(methodCall.name, methodCall.arglist, info)){ GenericsResolver resolver = getResolverInstance(); - TypeScope additionalScope = m.getTypeScope(); - methodConstraints.add(generateConstraint(methodCall, m, info, getResolverInstance())); + methodConstraints.add(generateConstraint(methodCall, m, info, resolver)); } if(methodConstraints.size()<1){ throw new TypeinferenceException("Methode "+methodCall.name+" ist nicht vorhanden!",methodCall.getOffset()); @@ -191,9 +196,7 @@ public class TYPEStmt implements StatementVisitor{ @Override public void visit(Return returnExpr) { returnExpr.retexpr.accept(this); - constraintsSet.addUndConstraint(ConstraintsFactory.createPair( - returnExpr.getType(),info.getCurrentTypeScope().getReturnType(), PairOperator.EQUALSDOT, - info.getCurrentTypeScope(), createNullTypeScope(), getResolverInstance())); + constraintsSet.addUndConstraint(new Pair(returnExpr.getType(),info.getCurrentTypeScope().getReturnType(), PairOperator.SMALLERDOT)); } @Override @@ -213,9 +216,15 @@ public class TYPEStmt implements StatementVisitor{ @Override public void visit(This aThis) { - constraintsSet.addUndConstraint(ConstraintsFactory.createPair( - aThis.getType(), info.getCurrentClass().getType(), PairOperator.EQUALSDOT, info.getCurrentTypeScope(), - createNullTypeScope(), getResolverInstance())); + //Im Falle von this, müssen die Generics in der Klasse als RefTypes behandelt werden. + ClassOrInterface currentClass = info.getCurrentClass(); + List params = new ArrayList<>(); + for(GenericTypeVar gtv : currentClass.getGenerics()){ + params.add(new GenericRefType(gtv.getName(), aThis.getOffset())); + } + RefType thisType = new RefType(currentClass.getClassName(), params, aThis.getOffset()); + constraintsSet.addUndConstraint(new Pair( + aThis.getType(), thisType, PairOperator.EQUALSDOT)); } private static TypeScope createNullTypeScope() { @@ -280,10 +289,20 @@ public class TYPEStmt implements StatementVisitor{ protected Constraint generateConstraint(MethodCall forMethod, MethodAssumption assumption, TypeInferenceBlockInformation info, GenericsResolver resolver){ Constraint methodConstraint = new Constraint(); - methodConstraint.add(ConstraintsFactory.createPair(forMethod.receiver.getType(), assumption.getReceiverType(), - PairOperator.SMALLERDOT, info.getCurrentTypeScope(), assumption.getTypeScope(), resolver)); - methodConstraint.add(ConstraintsFactory.createPair(assumption.getReturnType(), forMethod.getType(), - PairOperator.EQUALSDOT, info.getCurrentTypeScope(), assumption.getTypeScope(), resolver)); + ClassOrInterface receiverCl = assumption.getReceiver(); + /* + List params = new ArrayList<>(); + for(GenericTypeVar gtv : receiverCl.getGenerics()){ + //Die Generics werden alle zu TPHs umgewandelt. + params.add(resolver.resolve(gtv.getParsedName())); + } + + RefTypeOrTPHOrWildcardOrGeneric receiverType = new RefType(assumption.getReceiver().getClassName(), params, forMethod.getOffset()); + */ + methodConstraint.add(new Pair(forMethod.receiver.getType(), assumption.getReceiverType(resolver), + PairOperator.SMALLERDOT)); + methodConstraint.add(new Pair(assumption.getReturnType(), forMethod.getType(), + PairOperator.EQUALSDOT)); methodConstraint.addAll(generateParameterConstraints(forMethod, assumption, info, resolver)); return methodConstraint; } @@ -293,8 +312,9 @@ public class TYPEStmt implements StatementVisitor{ Set ret = new HashSet<>(); for(int i = 0;i getMethods(String name, int numArgs, TypeInferenceBlockInformation info) { List ret = new ArrayList<>(); + //TODO: apply Methoden wieder anfügen. Diese könnten möglicherweise auch in den Assumptions auftauchen (überdenken) if(name.equals("apply")){ List funNParams = new ArrayList<>(); for(int i = 0; i< numArgs + 1 ; i++){ funNParams.add(TypePlaceholder.fresh(new NullToken())); } - ret.add(new MethodAssumption(new FunN(funNParams), funNParams.get(0), funNParams.subList(1, funNParams.size()), + ret.add(new MethodAssumption(new FunNClass(funNParams), funNParams.get(0), funNParams.subList(1, funNParams.size()), new TypeScope() { @Override public Iterable getGenerics() { @@ -324,9 +345,9 @@ public class TYPEStmt implements StatementVisitor{ for(Method m : cl.getMethods()){ if(m.getName().equals(name) && m.getParameterList().getFormalparalist().size() == numArgs){ - RefTypeOrTPHOrWildcardOrGeneric retType = info.checkGTV(m.getType()); + RefTypeOrTPHOrWildcardOrGeneric retType = info.checkGTV(m.getReturnType()); - ret.add(new MethodAssumption(cl.getType(), retType, convertParams(m.getParameterList(),info), + ret.add(new MethodAssumption(cl, retType, convertParams(m.getParameterList(),info), createTypeScope(cl, m))); } } @@ -361,7 +382,7 @@ public class TYPEStmt implements StatementVisitor{ if(cl.getClassName().equals(ofType.getName())){ for(Method m : cl.getConstructors()){ if(m.getParameterList().getFormalparalist().size() == argList.getArguments().size()){ - ret.add(new MethodAssumption(cl.getType(), ofType, convertParams(m.getParameterList(), + ret.add(new MethodAssumption(cl, ofType, convertParams(m.getParameterList(), info), createTypeScope(cl, m))); } } @@ -373,8 +394,8 @@ public class TYPEStmt implements StatementVisitor{ protected Constraint generateConstructorConstraint(NewClass forConstructor, MethodAssumption assumption, TypeInferenceBlockInformation info, GenericsResolver resolver){ Constraint methodConstraint = new Constraint(); - methodConstraint.add(ConstraintsFactory.createPair(assumption.getReturnType(), forConstructor.getType(), - PairOperator.SMALLERDOT, info.getCurrentTypeScope(), assumption.getTypeScope(), resolver)); + methodConstraint.add(new Pair(assumption.getReturnType(), forConstructor.getType(), + PairOperator.SMALLERDOT)); methodConstraint.addAll(generateParameterConstraints(forConstructor, assumption, info, resolver)); return methodConstraint; } diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java b/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java index 9ace0e515..aba3d3f6a 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java @@ -17,17 +17,18 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; * @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 */ @@ -38,7 +39,7 @@ public class FiniteClosure implements IFiniteClosure { */ public FiniteClosure(Set pairs) { this.pairs = new HashSet<>(pairs); - inheritanceGraph = new HashMap>(); + inheritanceGraph = new HashMap>(); // Build the transitive closure of the inheritance tree for(UnifyPair pair : pairs) { @@ -46,7 +47,7 @@ public class FiniteClosure implements IFiniteClosure { continue; // Add nodes if not already in the graph - if(!inheritanceGraph.containsKey(pair.getLhsType())) + 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())); @@ -61,7 +62,7 @@ public class FiniteClosure implements IFiniteClosure { 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()) { @@ -75,7 +76,7 @@ public class FiniteClosure implements IFiniteClosure { /** * 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) @@ -156,7 +157,7 @@ public class FiniteClosure implements IFiniteClosure { /** * 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) @@ -240,7 +241,7 @@ public class FiniteClosure implements IFiniteClosure { return type.grArg(this); } - @Override + @Override public Set grArg(ReferenceType type) { Set result = new HashSet(); result.add(type); @@ -249,7 +250,7 @@ public class FiniteClosure implements IFiniteClosure { return result; } - @Override + @Override public Set grArg(FunNType type) { Set result = new HashSet(); result.add(type); @@ -267,7 +268,7 @@ public class FiniteClosure implements IFiniteClosure { return result; } - @Override + @Override public Set grArg(SuperType type) { Set result = new HashSet(); result.add(type); @@ -276,11 +277,11 @@ public class FiniteClosure implements IFiniteClosure { return result; } - @Override + @Override public Set grArg(PlaceholderType type) { HashSet result = new HashSet<>(); result.add(type); - return result; + return result; } @Override @@ -288,12 +289,12 @@ public class FiniteClosure implements IFiniteClosure { return type.smArg(this); } - @Override + @Override public Set smArg(ReferenceType type) { Set result = new HashSet(); result.add(type); return result; - } + } @Override public Set smArg(FunNType type) { @@ -316,7 +317,7 @@ public class FiniteClosure implements IFiniteClosure { } - @Override + @Override public Set smArg(SuperType type) { Set result = new HashSet(); result.add(type); @@ -329,20 +330,20 @@ public class FiniteClosure implements IFiniteClosure { return result; } - @Override + @Override public Set smArg(PlaceholderType type) { HashSet result = new HashSet<>(); - result.add(type); + result.add(type); return result; } - @Override - public Set getAllTypesByName(String typeName) { + @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)) @@ -392,7 +393,7 @@ public class FiniteClosure implements IFiniteClosure { * @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) { + 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; diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java b/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java index fd87eecc2..dc90847b7 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java @@ -24,8 +24,10 @@ public final class TypeParams implements Iterable{ */ public TypeParams(List types){ typeParams = new UnifyType[types.size()]; - for(int i=0;i{ if(other.size() != this.size()) return false; - + + for(int i = 0; i < this.size(); i++){ + //if(this.get(i) == null) + //System.out.print("s"); + } for(int i = 0; i < this.size(); i++) if(!(this.get(i).equals(other.get(i)))) return false; diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java b/src/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java index 567181984..1080f03b6 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java @@ -96,4 +96,14 @@ public abstract class UnifyType { ret.addAll(typeParams.getInvolvedPlaceholderTypes()); return ret; } + + @Override + public int hashCode() { + return this.toString().hashCode(); + } + + @Override + public boolean equals(Object obj) { + return this.toString().equals(obj.toString()); + } } \ No newline at end of file diff --git a/test/asp/ClingoTest.java b/test/asp/ClingoTest.java new file mode 100644 index 000000000..dbfa70d8d --- /dev/null +++ b/test/asp/ClingoTest.java @@ -0,0 +1,46 @@ +package asp; + +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.sat.asp.writer.ASPGenerator; +import de.dhbwstuttgart.sat.asp.Clingo; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import org.junit.Test; + +import java.io.*; +import java.util.*; + +public class ClingoTest { + public static final String rootDirectory = "~/Sync/HiwiJob/ResearchPapers/MasterarbeitStadelmeier/asp/unifyWithoutWildcards"; + public static final String tempDirectory = "/tmp/"; + + @Test + public void test() throws IOException, InterruptedException { + String content = ""; + content = new ASPGenerator(this.getPairs(), this.getFC()).getASP(); + + PrintWriter writer = new PrintWriter(tempDirectory + "test.lp", "UTF-8"); + writer.println(content); + writer.close(); + + Clingo clingo = new Clingo(Arrays.asList(new File(tempDirectory + "test.lp"))); + System.out.println(clingo.runClingo()); + } + + public Collection getFC() { + Set ret = new HashSet<>(); + ret.add(ASTFactory.createObjectClass()); + ret.add(ASTFactory.createClass(java.util.List.class)); + return ret; + } + + public ConstraintSet getPairs() { + ConstraintSet ret = new ConstraintSet<>(); + ret.addUndConstraint(new Pair(TypePlaceholder.fresh(new NullToken()), ASTFactory.createObjectType(), PairOperator.SMALLERDOT)); + return ret; + } +} diff --git a/test/asp/typeinference/ASPTest.java b/test/asp/typeinference/ASPTest.java new file mode 100644 index 000000000..b41d94054 --- /dev/null +++ b/test/asp/typeinference/ASPTest.java @@ -0,0 +1,68 @@ +package asp.typeinference; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.sat.asp.writer.ASPGenerator; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +public class ASPTest { + + public static final String rootDirectory = System.getProperty("user.dir")+"/test/javFiles/"; + private static final List filesToTest = new ArrayList<>(); + protected File fileToTest = null; + + public ASPTest(){ + } + + + @Test + public void test() throws IOException, ClassNotFoundException { + if(fileToTest != null)filesToTest.add(fileToTest); + else return; + //filesToTest.add(new File(rootDirectory+"Faculty.jav")); + //filesToTest.add(new File(rootDirectory+"mathStruc.jav")); + //filesToTest.add(new File(rootDirectory+"test.jav")); + filesToTest.add(new File(rootDirectory+"EmptyMethod.jav")); + //filesToTest.add(new File(rootDirectory+"fc.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda2.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda3.jav")); + //filesToTest.add(new File(rootDirectory+"Vector.jav")); + //filesToTest.add(new File(rootDirectory+"Generics.jav")); + //filesToTest.add(new File(rootDirectory+"MethodsEasy.jav")); + //filesToTest.add(new File(rootDirectory+"Matrix.jav")); + //filesToTest.add(new File(rootDirectory+"Import.jav")); + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + List allClasses = new ArrayList<>(); + for(SourceFile sf : compiler.sourceFiles.values()) { + //allClasses.addAll(compiler.getAvailableClasses(sf)); + } + for(SourceFile sf : compiler.sourceFiles.values()) { + allClasses.addAll(sf.getClasses()); + } + + final ConstraintSet cons = compiler.getConstraints(); + ASPGenerator generator = new ASPGenerator(cons, allClasses); + System.out.println(generator.getASP()); + } + + static String readFile(String path, Charset encoding) + throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } + +} + diff --git a/test/asp/typeinference/GenericsTest.java b/test/asp/typeinference/GenericsTest.java new file mode 100644 index 000000000..b0f0330a9 --- /dev/null +++ b/test/asp/typeinference/GenericsTest.java @@ -0,0 +1,9 @@ +package asp.typeinference; + +import java.io.File; + +public class GenericsTest extends ASPTest { + public GenericsTest() { + this.fileToTest = new File(rootDirectory+"Generics.jav"); + } +} \ No newline at end of file diff --git a/test/asp/typeinference/VectorTest.java b/test/asp/typeinference/VectorTest.java new file mode 100644 index 000000000..77ff49597 --- /dev/null +++ b/test/asp/typeinference/VectorTest.java @@ -0,0 +1,9 @@ +package asp.typeinference; + +import java.io.File; + +public class VectorTest extends ASPTest { + public VectorTest() { + this.fileToTest = new File(rootDirectory+"Vector.jav"); + } +} \ No newline at end of file diff --git a/test/asp/unifywithoutwildcards/ASPTests.java b/test/asp/unifywithoutwildcards/ASPTests.java new file mode 100644 index 000000000..80e7bb785 --- /dev/null +++ b/test/asp/unifywithoutwildcards/ASPTests.java @@ -0,0 +1,10 @@ +package asp.unifywithoutwildcards; + +import org.junit.Test; + +public class ASPTests { + @Test + public void test(){ + + } +} diff --git a/test/bytecode/DuMethod.jav b/test/bytecode/DuMethod.jav new file mode 100644 index 000000000..b56f6c55c --- /dev/null +++ b/test/bytecode/DuMethod.jav @@ -0,0 +1,11 @@ +public class DuMethod{ + + method(a){ + return a; + } + + method(a){ + return a; + } + +} \ No newline at end of file diff --git a/test/bytecode/EmptyMethod.jav b/test/bytecode/EmptyMethod.jav new file mode 100644 index 000000000..961989df4 --- /dev/null +++ b/test/bytecode/EmptyMethod.jav @@ -0,0 +1,8 @@ +public class EmptyMethod{ + + public void m1(){ + System.out.println("test"); + } + + public void m2(){} +} diff --git a/test/bytecode/Faculty.jav b/test/bytecode/Faculty.jav new file mode 100644 index 000000000..5742d720d --- /dev/null +++ b/test/bytecode/Faculty.jav @@ -0,0 +1,14 @@ +class Faculty { + + Integer mul(Integer x, Integer y) { + return x; + } + + m () { + + var fact = (Integer x) -> { + return mul(x, x); + }; + return fact; + } +} diff --git a/test/bytecode/Faculty2.jav b/test/bytecode/Faculty2.jav new file mode 100644 index 000000000..828f06f50 --- /dev/null +++ b/test/bytecode/Faculty2.jav @@ -0,0 +1,10 @@ +class Faculty2 { + + m () { + + var fact = (Integer x) -> { + return x; + }; + return fact; + } +} \ No newline at end of file diff --git a/test/bytecode/Gen.jav b/test/bytecode/Gen.jav new file mode 100644 index 000000000..1f8739192 --- /dev/null +++ b/test/bytecode/Gen.jav @@ -0,0 +1,5 @@ +public class Gen{ + Vector m(Vector v){ + return v; + } +} \ No newline at end of file diff --git a/test/bytecode/Generics.jav b/test/bytecode/Generics.jav new file mode 100644 index 000000000..bb7b2af51 --- /dev/null +++ b/test/bytecode/Generics.jav @@ -0,0 +1,17 @@ + +class Generics { + Generics(B b){ + } + B mt1(B b){ + return mt1(b); + } +} + + +/* +Problem: +auto test = new List(); +auto test2 = new List(); +... //code, welcher möglicherweise test und test2 vertauscht +test.add("hallo"); +*/ \ No newline at end of file diff --git a/test/bytecode/Generics2.jav b/test/bytecode/Generics2.jav new file mode 100644 index 000000000..52d5caa23 --- /dev/null +++ b/test/bytecode/Generics2.jav @@ -0,0 +1,6 @@ +class Generics2{ + B m1(B b){ + return b; + } + +} \ No newline at end of file diff --git a/test/bytecode/Generics2Test.java b/test/bytecode/Generics2Test.java new file mode 100644 index 000000000..26e52665d --- /dev/null +++ b/test/bytecode/Generics2Test.java @@ -0,0 +1,7 @@ +package bytecode; + +public class Generics2Test extends JavaTXCompilerTest{ + public Generics2Test() { + this.fileName = "Generics2"; + } +} diff --git a/test/bytecode/GenericsTest.java b/test/bytecode/GenericsTest.java new file mode 100644 index 000000000..cca161296 --- /dev/null +++ b/test/bytecode/GenericsTest.java @@ -0,0 +1,7 @@ +package bytecode; + +public class GenericsTest extends JavaTXCompilerTest { + public GenericsTest() { + this.fileName = "Generics"; + } +} diff --git a/test/bytecode/IfTest.jav b/test/bytecode/IfTest.jav new file mode 100644 index 000000000..806e21578 --- /dev/null +++ b/test/bytecode/IfTest.jav @@ -0,0 +1,10 @@ +public class IfTest{ + Integer m1(Boolean b) { + Integer i; + if(b) { + return i; + } + + return i; + } +} \ No newline at end of file diff --git a/test/bytecode/Interface1.jav b/test/bytecode/Interface1.jav new file mode 100644 index 000000000..b741819c0 --- /dev/null +++ b/test/bytecode/Interface1.jav @@ -0,0 +1,3 @@ +public interface Interface1{ + public void test(); +} \ No newline at end of file diff --git a/test/bytecode/InterfaceTest.java b/test/bytecode/InterfaceTest.java new file mode 100644 index 000000000..ed3781271 --- /dev/null +++ b/test/bytecode/InterfaceTest.java @@ -0,0 +1,7 @@ +package bytecode; + +public class InterfaceTest extends JavaTXCompilerTest{ + public InterfaceTest() { + this.fileName = "Interface1"; + } +} diff --git a/test/bytecode/JavaTXCompilerTest.java b/test/bytecode/JavaTXCompilerTest.java index 9ca91abb9..f017e23e6 100644 --- a/test/bytecode/JavaTXCompilerTest.java +++ b/test/bytecode/JavaTXCompilerTest.java @@ -3,6 +3,8 @@ package bytecode; import de.dhbwstuttgart.bytecode.BytecodeGen; import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.typeinference.result.ResultPair; +import de.dhbwstuttgart.typeinference.result.ResultSet; import org.junit.Test; import java.io.File; @@ -21,45 +23,62 @@ import static org.junit.Assert.*; public class JavaTXCompilerTest { - private static final String rootDirectory = System.getProperty("user.dir")+"/test/javFiles/"; + private static final String rootDirectory = System.getProperty("user.dir")+"/test/bytecode/"; private static final List filesToTest = new ArrayList<>(); - + + protected String fileName = ""; + @Test public void test() throws IOException, java.lang.ClassNotFoundException { System.out.println(rootDirectory); - filesToTest.add(new File(rootDirectory+"EmptyClass.jav")); + filesToTest.add(new File(rootDirectory+fileName+".jav")); + System.out.println(rootDirectory+fileName+".jav"); JavaTXCompiler compiler = new JavaTXCompiler(filesToTest); System.out.println("test"); for(File f : filesToTest){ String content = readFile(f.getPath(), StandardCharsets.UTF_8); - HashMap bytecode = this.getBytecode(compiler.sourceFiles.get(f)); - this.writeClassFile(bytecode, "EmptyClass"); + List typeinferenceResult = compiler.typeInference(); + HashMap bytecode = this.getBytecode(compiler.sourceFiles.get(f), typeinferenceResult.get(0)); + + for(ResultPair ep : typeinferenceResult.get(0).results) { + System.out.println(ep.getLeft() + " ->" + ep.getRight()); + } + + String name = ""; + int pos = f.getName().lastIndexOf("."); + if(pos != -1) { + name = f.getName().substring(0, pos); + } + this.writeClassFile(bytecode); } } - public HashMap getBytecode(SourceFile sf) { + public HashMap getBytecode(SourceFile sf, ResultSet resultSet) { HashMap classFiles = new HashMap<>(); - BytecodeGen bytecodeGen = new BytecodeGen(classFiles); + BytecodeGen bytecodeGen = new BytecodeGen(classFiles,resultSet); bytecodeGen.visit(sf); return bytecodeGen.getClassFiles(); } - public void writeClassFile(HashMap classFiles, String name) { + public void writeClassFile(HashMap classFiles) { FileOutputStream output; - byte[] bytecode = classFiles.get(name); - try { - System.out.println("generating .class file"); - output = new FileOutputStream(new File(System.getProperty("user.dir") + "/testBytecode/" +name+".class")); - output.write(bytecode); - output.close(); - System.out.println(".class file generated"); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } + for(String name : classFiles.keySet()) { + byte[] bytecode = classFiles.get(name); + try { + System.out.println("generating"+name+ ".class file"); + output = new FileOutputStream(new File(System.getProperty("user.dir") + "/testBytecode/generatedBC/" +name+".class")); + output.write(bytecode); + output.close(); + System.out.println(name+".class file generated"); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } static String readFile(String path, Charset encoding) diff --git a/test/bytecode/LamAssign.jav b/test/bytecode/LamAssign.jav new file mode 100644 index 000000000..3df81780f --- /dev/null +++ b/test/bytecode/LamAssign.jav @@ -0,0 +1,13 @@ +class LamAssign { + + m () { + var lam1 = (Integer x) -> { + return x; + }; + return lam1; + } +} + +interface Fun1{ + A apply(B b); +} diff --git a/test/bytecode/LamAssignTest.java b/test/bytecode/LamAssignTest.java new file mode 100644 index 000000000..3442c1d1a --- /dev/null +++ b/test/bytecode/LamAssignTest.java @@ -0,0 +1,7 @@ +package bytecode; + +public class LamAssignTest extends JavaTXCompilerTest{ + public LamAssignTest() { + this.fileName = "LamAssign"; + } +} diff --git a/test/bytecode/LamRunnable.jav b/test/bytecode/LamRunnable.jav new file mode 100644 index 000000000..451858f24 --- /dev/null +++ b/test/bytecode/LamRunnable.jav @@ -0,0 +1,9 @@ +public class LamRunnable{ + + public LamRunnable(){ + + Runnable lam = () -> {System.out.println("lambda");}; + lam.run(); + } +} + \ No newline at end of file diff --git a/test/bytecode/Lambda.jav b/test/bytecode/Lambda.jav new file mode 100644 index 000000000..378eb4d3e --- /dev/null +++ b/test/bytecode/Lambda.jav @@ -0,0 +1,18 @@ +class Lambda{ + +methode(){ + return ((f) -> f); +} +} +/* +interface Fun0{ + A apply(); +} + +interface Fun1{ + A apply(B b); +} +*/ +interface Fun2{ + A apply(B b, C c); +} \ No newline at end of file diff --git a/test/bytecode/Lambda2.jav b/test/bytecode/Lambda2.jav new file mode 100644 index 000000000..fbcdaf55b --- /dev/null +++ b/test/bytecode/Lambda2.jav @@ -0,0 +1,32 @@ + +public class Lambda2 +{ + public static void main(List args){ + var listOfStrings = new List(); + var listOfObjects; + listOfObjects = map(listOfStrings, (a) -> a); +} + +public map(a , b){ + b.apply(a); + return a; +} + +/* +public static List map(List input, Function func) { + List output; + output = new List(); + output.add(func.apply(input.get())); + return output; +} +*/ +} + +class List{ + A get(); + void add(A); +} + +class Function{ + B apply(A a); +} \ No newline at end of file diff --git a/test/bytecode/Lambda3.jav b/test/bytecode/Lambda3.jav new file mode 100644 index 000000000..9c4e960cd --- /dev/null +++ b/test/bytecode/Lambda3.jav @@ -0,0 +1,23 @@ + +public class Lambda2 +{ + /* + public static List map(List input, + Function func){ + input.add(func.apply(input.get())); + } + */ + public map(input,func){ + input.add(func.apply(input.get())); + return map(new List(), func); + } +} + +class List{ + A get(); + void add(A); +} + +class Function{ + B apply(A a); +} \ No newline at end of file diff --git a/test/bytecode/RecursiveMeth.jav b/test/bytecode/RecursiveMeth.jav new file mode 100644 index 000000000..be35a43cc --- /dev/null +++ b/test/bytecode/RecursiveMeth.jav @@ -0,0 +1,5 @@ +public class RecursiveMeth{ + public Integer test(){ + return this.test(); + } +} \ No newline at end of file diff --git a/test/bytecode/ReturnMethod.jav b/test/bytecode/ReturnMethod.jav new file mode 100644 index 000000000..38386d0da --- /dev/null +++ b/test/bytecode/ReturnMethod.jav @@ -0,0 +1,6 @@ +class ReturnMethod{ + Integer r; + Integer mul(Integer x, Integer y) { + return r; + } +} \ No newline at end of file diff --git a/test/bytecode/VoidMeth.jav b/test/bytecode/VoidMeth.jav new file mode 100644 index 000000000..6b3ab212e --- /dev/null +++ b/test/bytecode/VoidMeth.jav @@ -0,0 +1,4 @@ +public class VoidMeth{ + public void test(){ + } +} \ No newline at end of file diff --git a/test/javFiles/Generics.jav b/test/javFiles/Generics.jav index 958025e61..c76b40aa5 100644 --- a/test/javFiles/Generics.jav +++ b/test/javFiles/Generics.jav @@ -1,6 +1,7 @@ class Generics { - A mt1(A a, B b){ + // A mt1(A a, B b){ + B mt1(B a, B b){ return mt1(a, a); } } diff --git a/test/javFiles/LambdaRunnable.jav b/test/javFiles/LambdaRunnable.jav new file mode 100644 index 000000000..982680c3b --- /dev/null +++ b/test/javFiles/LambdaRunnable.jav @@ -0,0 +1,11 @@ + +public class LamRunnable{ + + public LamRunnable(){ + + + Runnable lam = () -> {System.out.println("lambda");}; + lam.run(); + } +} + diff --git a/test/javFiles/Matrix.jav b/test/javFiles/Matrix.jav index 65dc465a9..e6aa84cd4 100644 --- a/test/javFiles/Matrix.jav +++ b/test/javFiles/Matrix.jav @@ -1,5 +1,16 @@ import java.util.Vector; +class Matrix extends Vector> { + + methode(Matrix m) { + Vector> i; + methode(i); + } + } + +/* +import java.util.Vector; + class Matrix extends Vector> { Matrix mul_rec(Matrix m) { @@ -39,4 +50,5 @@ class Matrix extends Vector> { } return ret; } -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/test/javFiles/fc.jav b/test/javFiles/fc.jav index cb8c17997..a3278cbcc 100644 --- a/test/javFiles/fc.jav +++ b/test/javFiles/fc.jav @@ -1,13 +1,14 @@ -import java.util.*; +import java.util.List; class Test{ methode(param1, param2, param3) { - return param1.meth(param2.add(param3)); + param2.add(param3); + return param1.meth(param2); } } interface Klasse1{ - Klasse1 meth(Klasse1 p); + Klasse1 meth(List p); Klasse1 meth(Klasse2 p); } diff --git a/test/typeinference/FiniteClosureTest.java b/test/typeinference/FiniteClosureTest.java index d3e1fdb02..8b62e4e5d 100644 --- a/test/typeinference/FiniteClosureTest.java +++ b/test/typeinference/FiniteClosureTest.java @@ -4,6 +4,6 @@ import java.io.File; public class FiniteClosureTest extends JavaTXCompilerTest{ public FiniteClosureTest() { - this.fileToTest = new File(rootDirectory+"fc.jav"); +// this.fileToTest = new File(rootDirectory+"fc.jav"); } } \ No newline at end of file diff --git a/test/typeinference/GenericsTest.java b/test/typeinference/GenericsTest.java index 3811883d8..abcef0133 100644 --- a/test/typeinference/GenericsTest.java +++ b/test/typeinference/GenericsTest.java @@ -2,6 +2,7 @@ package typeinference; import java.io.File; +//TODO: Hier gibt es einen Fehler. Das erstellte ConstraintSet stimmt nicht public class GenericsTest extends JavaTXCompilerTest{ public GenericsTest() { this.fileToTest = new File(rootDirectory+"Generics.jav"); diff --git a/test/typeinference/JavaTXCompilerTest.java b/test/typeinference/JavaTXCompilerTest.java index 4b79b8c5d..f46229541 100644 --- a/test/typeinference/JavaTXCompilerTest.java +++ b/test/typeinference/JavaTXCompilerTest.java @@ -10,13 +10,12 @@ import org.junit.Test; import java.io.File; import java.io.IOException; -import java.net.URL; -import java.net.URLClassLoader; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -28,15 +27,15 @@ public class JavaTXCompilerTest { public JavaTXCompilerTest(){ } - @Test - public void test() throws IOException, java.lang.ClassNotFoundException { + public void test() throws IOException, ClassNotFoundException { if(fileToTest != null)filesToTest.add(fileToTest); - else return; + else return; //filesToTest.add(new File(rootDirectory+"Faculty.jav")); //filesToTest.add(new File(rootDirectory+"mathStruc.jav")); //filesToTest.add(new File(rootDirectory+"test.jav")); filesToTest.add(new File(rootDirectory+"EmptyMethod.jav")); + //filesToTest.add(new File(rootDirectory+"fc.jav")); //filesToTest.add(new File(rootDirectory+"Lambda.jav")); //filesToTest.add(new File(rootDirectory+"Lambda2.jav")); //filesToTest.add(new File(rootDirectory+"Lambda3.jav")); @@ -46,6 +45,7 @@ public class JavaTXCompilerTest { //filesToTest.add(new File(rootDirectory+"Matrix.jav")); //filesToTest.add(new File(rootDirectory+"Import.jav")); JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + List results = compiler.typeInference(); for(File f : compiler.sourceFiles.keySet()){ @@ -53,14 +53,18 @@ public class JavaTXCompilerTest { System.out.println(ASTTypePrinter.print(sf)); //List results = compiler.typeInference(); PL 2017-10-03 vor die For-Schleife gezogen assert results.size()>0; + Set insertedTypes = new HashSet<>(); for(ResultSet resultSet : results){ Set result = TypeInsertFactory.createTypeInsertPoints(sf, resultSet); assert result.size()>0; String content = readFile(f.getPath(), StandardCharsets.UTF_8); for(TypeInsert tip : result){ - System.out.println(tip.insert(content)); + insertedTypes.add(tip.insert(content)); } } + for(String s : insertedTypes){ + System.out.println(s); + } } } diff --git a/test/typeinference/MatrixTest.java b/test/typeinference/MatrixTest.java new file mode 100644 index 000000000..8cc587c9b --- /dev/null +++ b/test/typeinference/MatrixTest.java @@ -0,0 +1,9 @@ +package typeinference; + +import java.io.File; + +public class MatrixTest extends JavaTXCompilerTest{ + public MatrixTest() { + this.fileToTest = new File(rootDirectory+"Matrix.jav"); + } +} \ No newline at end of file diff --git a/test/typeinference/RunnableTest.java b/test/typeinference/RunnableTest.java new file mode 100644 index 000000000..bc0c52ad1 --- /dev/null +++ b/test/typeinference/RunnableTest.java @@ -0,0 +1,9 @@ +package typeinference; + +import java.io.File; + +public class RunnableTest extends JavaTXCompilerTest{ + public RunnableTest() { + this.fileToTest = new File(rootDirectory+"LambdaRunnable.jav"); + } +} \ No newline at end of file diff --git a/testBytecode/LamRun.java b/testBytecode/LamRun.java index f49207008..fdaf0852e 100644 --- a/testBytecode/LamRun.java +++ b/testBytecode/LamRun.java @@ -1,6 +1,6 @@ public class LamRun{ - public LamRun(){ + public void mRun(){ Runnable lam = () -> System.out.println("lambda"); lam.run(); diff --git a/testBytecode/TestMyTest.java b/testBytecode/TestMyTest.java index 1b3db5880..e1305f761 100644 --- a/testBytecode/TestMyTest.java +++ b/testBytecode/TestMyTest.java @@ -5,6 +5,7 @@ public static void main(String[] a){ //test if statement //new TestIf(new Boolean(true)); // test lambda - new TestClass(); + //new TestClass(); + new LamRun(); } } diff --git a/testBytecode/generatedBC/.gitignore b/testBytecode/generatedBC/.gitignore new file mode 100644 index 000000000..5e7d2734c --- /dev/null +++ b/testBytecode/generatedBC/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore diff --git a/testBytecode/manually/Fac1.java b/testBytecode/manually/Fac1.java new file mode 100644 index 000000000..e36ad3aed --- /dev/null +++ b/testBytecode/manually/Fac1.java @@ -0,0 +1,6 @@ +class Fuc1{ + + Integer mul(Integer x, Integer y) { + return x; + } +} diff --git a/testBytecode/manually/Fac2.java b/testBytecode/manually/Fac2.java new file mode 100644 index 000000000..dbf307b83 --- /dev/null +++ b/testBytecode/manually/Fac2.java @@ -0,0 +1,14 @@ +import java.util.function.Function; +class Fac2 { + + Integer mul(Integer x, Integer y) { + return x; + } + + Function m () { + Function fact = (Integer x) -> { + return mul(x, x); + }; + return fact; + } +} diff --git a/testBytecode/manually/LamAssign.java b/testBytecode/manually/LamAssign.java new file mode 100644 index 000000000..8d45a6415 --- /dev/null +++ b/testBytecode/manually/LamAssign.java @@ -0,0 +1,10 @@ +import java.util.function.Function; +class LamAssign { + + Function m () { + Function lam1 = (Integer x) -> { + return x; + }; + return lam1; + } +} diff --git a/testBytecode/manually/LamAssignWithM.java b/testBytecode/manually/LamAssignWithM.java new file mode 100644 index 000000000..61077d275 --- /dev/null +++ b/testBytecode/manually/LamAssignWithM.java @@ -0,0 +1,12 @@ +import java.util.function.Function; +class LamAssignWithM { + Integer mul(Integer x, Integer y) { + return x; + } + Function m () { + Function lam1 = (Integer x) -> { + return mul(x,x); + }; + return lam1; + } +} diff --git a/testBytecode/manually/LamWithAnField.java b/testBytecode/manually/LamWithAnField.java new file mode 100644 index 000000000..ae6da4fc1 --- /dev/null +++ b/testBytecode/manually/LamWithAnField.java @@ -0,0 +1,14 @@ +import java.util.function.Function; +class LamWithAnField { + Integer mul(Integer x, Integer y) { + return x; + } + LamWithField temp= new LamWithField(); + Function m () { + Function lam1 = (Integer x) -> { + return temp.res*x; + }; + return lam1; + } +} + diff --git a/testBytecode/manually/LamWithField.java b/testBytecode/manually/LamWithField.java new file mode 100644 index 000000000..dacdca8bf --- /dev/null +++ b/testBytecode/manually/LamWithField.java @@ -0,0 +1,14 @@ +import java.util.function.Function; +class LamWithField { + Integer mul(Integer x, Integer y) { + return x; + } + Integer res = new Integer(5); + Function m () { + Function lam1 = (Integer x) -> { + return res*x; + }; + return lam1; + } +} + diff --git a/testBytecode/manually/ReturnM1.java b/testBytecode/manually/ReturnM1.java new file mode 100644 index 000000000..3f89147dd --- /dev/null +++ b/testBytecode/manually/ReturnM1.java @@ -0,0 +1,6 @@ +class ReturnM1{ + Integer r; + Integer mul(Integer x, Integer y) { + return r; + } +}