diff --git a/.gitignore b/.gitignore index edec9626..a897efd8 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,6 @@ bin .project .settings/ /target/ + +# +manually/ diff --git a/README.md b/README.md new file mode 100644 index 00000000..8b1e7ddd --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ + + +# plugin site erstellen +* die JAvaTXCOmpiler DAtei in ein plugin umwandeln und deployen. +* siehe: http://www.vogella.com/tutorials/EclipseJarToPlugin/article.html#convert-jar-files-to-osgi-bundles-with-the-p2-maven-plugin +* AUsführung: + * mvn deploy #erstellt die JAR-Datei und steckt sie in ein lokales Repo (maven-repository) + * mvn p2:site + * mvn package # hier wird die ZIP-Filf zum Einbinden in Eclipse erstellt + +# Einbinden in Eclipse +* In Eclipse kann die Zip-FIle wie ein Plugin installiert werden +* Hier tritt FEhler auf. Reflections-Library kann nicht installiert werden. Möglicherweise wird sie auch nicht gebraucht +* Nach dem installieren de.dhbwstuttagrt.JavaTXcompiler zu den DEpendencies des plugins hinzufügen +* Anschließend unter "Overview" auf "Updata Classpath" klicken + +# Windows +* JAVA_HOME setzen: + * export JAVA_HOME=/c/Program\ Files/Java/jdk1.8.0_102/ diff --git a/Website/JavaTXExamples.zip b/Website/JavaTXExamples.zip new file mode 100644 index 00000000..db9eb324 Binary files /dev/null and b/Website/JavaTXExamples.zip differ diff --git a/Website/index.html b/Website/index.html new file mode 100644 index 00000000..0253da16 --- /dev/null +++ b/Website/index.html @@ -0,0 +1,88 @@ + + +Java-TX Plugin +
+

Java-TX Plugin

+
+

Content

+ + +
+

Introduction

+Java-TX (Java Type eXtended) is an extension of Java in which a global type inference algorithm and real function types are added. Since the end of the nineties features from functional program- ming languages have been transferred to Java. Parametric polymorphism extended by wildcards, called generics, were transfered to Java 5.0. Higher-order functions and lambda expression were introduced in Java 8. Java 8 uses functional interfaces as target types of lambda expressions in contrast to real function types as in functional programming languages. +The powerful feature type inference from functional programming languages is incorporated into Java, as into other object-oriented +languages, i.e. only in a restricted way called local type inference. Local type inference allows certain type annotations to be omitted. For instance, it is often not necessary to specify the type of a variable. Type parameters of classes in the new-statement can be left out. Return types of methods can often also be omitted. Local type inference is at its most pronounced in Scala. In Java 10 an extention of local type inference is introduced, where types of local variables can be replaced by the keyword var and inferred automatically during the compilation. In contrast to global type inference, local type inference allows types of recursive methods and lambda expressions not to be omitted.
+The Java-TX project contributes to the design of object-oriented languages by developing global type inference algorithms for Java-like languages. + +

First Example

+The class Id has the method id. The type annotations are omitted. +
+ +
 
+  class Id {
+      id(x) {
+          return x;
+      }
+  } 
+ 
+The type inference algorithm inferrs the types, such that Id can be applied: +
+    new Id().id(1);
+
+    new Id().id("hallo");
+
+ +

More complex example

+
+  import java.lang.Integer;
+  import java.lang.Double; 
+  import java.lang.String; 
+
+
+  class OL {
+     m(x) { return x + x; }
+	
+  }
+    
+         
+  class OLMain {
+     main(x) { 
+	var ol;
+	ol = new OL(); 
+	return ol.m(x); 
+     }  
+  }
+
+The type inference mechanism considers only imported types. Therefore Integer Double, and String are imported. +
+As the operator + is overloaded by all numeric types and String the methods m in the class OL and main in the class OLMain, respectively, gets all these types. The generated classfile demonstrates this: +
+> javap OL.class 
+Compiled from "OL.jav"
+class OL {
+  public OL();
+  public java.lang.Integer m(java.lang.Integer);
+  public java.lang.Double m(java.lang.Double);
+}
+
+> javap OLMain.class 
+Compiled from "OLMain.jav"
+class OLMain {
+  public OLMain();
+  public java.lang.Integer main(java.lang.Integer);
+  public java.lang.Double main(java.lang.Double);
+}
+
+ + +
+
+Last modified: Fri Jun 1 16:43:55 CEST 2018 + diff --git a/Website/install/Restart.png b/Website/install/Restart.png new file mode 100644 index 00000000..5d3c3efc Binary files /dev/null and b/Website/install/Restart.png differ diff --git a/Website/install/availableSoftware1.png b/Website/install/availableSoftware1.png new file mode 100644 index 00000000..22097efe Binary files /dev/null and b/Website/install/availableSoftware1.png differ diff --git a/Website/install/availableSoftware2.png b/Website/install/availableSoftware2.png new file mode 100644 index 00000000..7bdb93cc Binary files /dev/null and b/Website/install/availableSoftware2.png differ diff --git a/Website/install/instal.html b/Website/install/instal.html new file mode 100644 index 00000000..4b4e91c7 --- /dev/null +++ b/Website/install/instal.html @@ -0,0 +1,40 @@ + + +Install Java-TX Plugin + + + +

Install Java-TX Plugin

+
    +
  1. Select "Install New Software ..."
    + + +
  2. +
  3. Add ...
    + +
  4. +
  5. Insert address
    + +
  6. +
  7. Select installation
    + +
  8. +
  9. Installation details
    + +
  10. +
  11. Accept license agreement
    + +
  12. +
  13. Install anyway
    + +
  14. +
  15. Restart
    + +
  16. +
+ + +
+
+Last modified: Fri Jun 1 11:57:15 CEST 2018 + diff --git a/Website/install/install.html b/Website/install/install.html new file mode 100644 index 00000000..11801117 --- /dev/null +++ b/Website/install/install.html @@ -0,0 +1,40 @@ + + +Install Java-TX Plugin + + + +

Install Java-TX Plugin

+
    +
  1. Select "Install New Software ..."
    + + +
  2. +
  3. Add ...
    + +
  4. +
  5. Insert address
    + +
  6. +
  7. Select installation
    + +
  8. +
  9. Installation details
    + +
  10. +
  11. Accept license agreement
    + +
  12. +
  13. Install anyway
    + +
  14. +
  15. Restart
    + +
  16. +
+ + +
+
+Last modified: Fri Jun 1 12:05:43 CEST 2018 + diff --git a/Website/install/installAnyway.png b/Website/install/installAnyway.png new file mode 100644 index 00000000..1e879655 Binary files /dev/null and b/Website/install/installAnyway.png differ diff --git a/Website/install/installationDetails.png b/Website/install/installationDetails.png new file mode 100644 index 00000000..3032caa3 Binary files /dev/null and b/Website/install/installationDetails.png differ diff --git a/Website/install/licenseAgreement.png b/Website/install/licenseAgreement.png new file mode 100644 index 00000000..4c20ccbb Binary files /dev/null and b/Website/install/licenseAgreement.png differ diff --git a/Website/install/newsoftware.png b/Website/install/newsoftware.png new file mode 100644 index 00000000..65c7005f Binary files /dev/null and b/Website/install/newsoftware.png differ diff --git a/Website/install/selectInstallation.png b/Website/install/selectInstallation.png new file mode 100644 index 00000000..eb9a3cdf Binary files /dev/null and b/Website/install/selectInstallation.png differ diff --git a/Website/newJavaTXProject/addLibrary2.png b/Website/newJavaTXProject/addLibrary2.png new file mode 100644 index 00000000..e008eeab Binary files /dev/null and b/Website/newJavaTXProject/addLibrary2.png differ diff --git a/Website/newJavaTXProject/buildPath1.png b/Website/newJavaTXProject/buildPath1.png new file mode 100644 index 00000000..e008eeab Binary files /dev/null and b/Website/newJavaTXProject/buildPath1.png differ diff --git a/Website/newJavaTXProject/buildPath2.png b/Website/newJavaTXProject/buildPath2.png new file mode 100644 index 00000000..920cc968 Binary files /dev/null and b/Website/newJavaTXProject/buildPath2.png differ diff --git a/Website/newJavaTXProject/buildPath3.png b/Website/newJavaTXProject/buildPath3.png new file mode 100644 index 00000000..8a7877c6 Binary files /dev/null and b/Website/newJavaTXProject/buildPath3.png differ diff --git a/Website/newJavaTXProject/buildPath4.png b/Website/newJavaTXProject/buildPath4.png new file mode 100644 index 00000000..1c3dd338 Binary files /dev/null and b/Website/newJavaTXProject/buildPath4.png differ diff --git a/Website/newJavaTXProject/newJavFile.png b/Website/newJavaTXProject/newJavFile.png new file mode 100644 index 00000000..85049267 Binary files /dev/null and b/Website/newJavaTXProject/newJavFile.png differ diff --git a/Website/newJavaTXProject/newJavFolder1.png b/Website/newJavaTXProject/newJavFolder1.png new file mode 100644 index 00000000..73e82fee Binary files /dev/null and b/Website/newJavaTXProject/newJavFolder1.png differ diff --git a/Website/newJavaTXProject/newJavFolder2.png b/Website/newJavaTXProject/newJavFolder2.png new file mode 100644 index 00000000..47e33951 Binary files /dev/null and b/Website/newJavaTXProject/newJavFolder2.png differ diff --git a/Website/newJavaTXProject/newJavaTXProject.html b/Website/newJavaTXProject/newJavaTXProject.html new file mode 100644 index 00000000..263e4044 --- /dev/null +++ b/Website/newJavaTXProject/newJavaTXProject.html @@ -0,0 +1,34 @@ + + + + +

New Java-TX project in eclipse

+
    +
  1. New -> Java Project
    + +
  2. +
    +
  3. Generate a jav-File folder
    +

    + +
  4. +
    +
  5. Add jav-File folder as library
    + At the moment no package system is implemented, Therefore the compiled class files are in the jav-File folder. This has to be added as library:
    +

    +

    +

    +
    + + +
  6. +
+ +

+ + + +
+
+Last modified: Fri Jun 1 16:50:02 CEST 2018 + diff --git a/Website/newJavaTXProject/newJavaTXProject.png b/Website/newJavaTXProject/newJavaTXProject.png new file mode 100644 index 00000000..57fc7727 Binary files /dev/null and b/Website/newJavaTXProject/newJavaTXProject.png differ diff --git a/Website/usePlugin/usePlugin.html b/Website/usePlugin/usePlugin.html new file mode 100644 index 00000000..45e744cf --- /dev/null +++ b/Website/usePlugin/usePlugin.html @@ -0,0 +1,24 @@ + + +Using the plugin + +

Using the plugin

+
    +
  1. Overview
    + +
  2. +
    +
  3. Select types
    + If the method is overloaded the user can select types in the outline the right mouse button:

    +
    +
  4. +
+ +

+ + + +
+
+Last modified: Fri Jun 1 16:51:28 CEST 2018 + diff --git a/Website/usePlugin/usePlugin1.png b/Website/usePlugin/usePlugin1.png new file mode 100644 index 00000000..c6f47149 Binary files /dev/null and b/Website/usePlugin/usePlugin1.png differ diff --git a/Website/usePlugin/usePlugin2.png b/Website/usePlugin/usePlugin2.png new file mode 100644 index 00000000..aefeb0bf Binary files /dev/null and b/Website/usePlugin/usePlugin2.png differ diff --git a/pom.xml b/pom.xml index 9f184c4f..dcb720ec 100644 --- a/pom.xml +++ b/pom.xml @@ -7,6 +7,7 @@ de.dhbwstuttgart JavaTXcompiler jar + 0.1 JavaTXcompiler http://maven.apache.org @@ -53,7 +54,7 @@ target target/classes - ${artifactId}-${version} + ${project.artifactId}-${project.version} target/test-classes src/ test/ @@ -71,10 +72,7 @@ src/de/dhbwstuttgart/parser/antlr/ src/de/dhbwstuttgart/parser/antlr/ - - -package - de.dhbwstuttgart.parser.antlr - + -package de.dhbwstuttgart.parser.antlr @@ -93,19 +91,91 @@ + + + maven-assembly-plugin + + + package + + single + + + + + + jar-with-dependencies + + + + org.reficio + p2-maven-plugin + 1.1.2-SNAPSHOT + + + default-cli + + + + + + de.dhbwstuttgart:JavaTXcompiler:0.1 + + org.reflections:reflections:0.9.11 + com.google.guava:guava:22.0 + javax.annotation:javax.annotation-api:1.3.1 + org.glassfish:javax.annotation:3.1.1 + + + + + + + org.eclipse.tycho + tycho-p2-repository-plugin + ${tycho.version} + + + package + + archive-repository + + + + org.apache.maven.plugins maven-compiler-plugin - 8 - 8 + 9 + 9 + + + reficio + http://repo.reficio.org/maven/ + + + + + maven-repository + file:///${project.basedir}/target + + 1.8 1.8 + 0.23.0 + + + maven-repository + MyCo Internal Repository + file:///${project.basedir}/maven-repository/ + + diff --git a/src/de/dhbwstuttgart/bytecode/AStatement.java b/src/de/dhbwstuttgart/bytecode/AStatement.java new file mode 100644 index 00000000..5c28bf43 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/AStatement.java @@ -0,0 +1,30 @@ +package de.dhbwstuttgart.bytecode; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr; +import de.dhbwstuttgart.syntaxtree.statement.Expression; + +public abstract class AStatement implements IStatement { + protected Expression expr; + + public AStatement(Expression expr) { + this.expr = expr; + } + + @Override + public boolean isExprBinary() { + return (expr instanceof BinaryExpr); + } + + @Override + public void genBCForRelOp(MethodVisitor mv,Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod) { + mv.visitInsn(Opcodes.ICONST_1); + mv.visitJumpInsn(Opcodes.GOTO, endLabel); + mv.visitLabel(branchLabel); + mv.visitInsn(Opcodes.ICONST_0); + mv.visitLabel(endLabel); + } +} diff --git a/src/de/dhbwstuttgart/bytecode/ArgumentExpr.java b/src/de/dhbwstuttgart/bytecode/ArgumentExpr.java new file mode 100644 index 00000000..b396e8d1 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/ArgumentExpr.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.bytecode; + +import de.dhbwstuttgart.syntaxtree.statement.Expression; + +public class ArgumentExpr extends AStatement { + + public ArgumentExpr(Expression expr) { + super(expr); + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/AssignStmt.java b/src/de/dhbwstuttgart/bytecode/AssignStmt.java new file mode 100644 index 00000000..366c450a --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/AssignStmt.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.bytecode; + +import de.dhbwstuttgart.syntaxtree.statement.Expression; + +public class AssignStmt extends AStatement { + + public AssignStmt(Expression rightSide) { + super(rightSide); + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java index f24bb3fd..f9bf72ed 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -1,7 +1,9 @@ package de.dhbwstuttgart.bytecode; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.syntaxtree.statement.*; @@ -9,11 +11,14 @@ 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 de.dhbwstuttgart.bytecode.descriptor.DescriptorToString; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; import de.dhbwstuttgart.bytecode.signature.Signature; import de.dhbwstuttgart.bytecode.signature.TypeToString; +import de.dhbwstuttgart.bytecode.utilities.NormalConstructor; +import de.dhbwstuttgart.bytecode.utilities.NormalMethod; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.statement.Literal; @@ -23,6 +28,7 @@ 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.ResultPair; import de.dhbwstuttgart.typeinference.result.ResultSet; public class BytecodeGen implements ASTVisitor { @@ -30,9 +36,10 @@ public class BytecodeGen implements ASTVisitor { ClassWriter cw =new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS); String type; - + String className; private boolean isInterface; + private List listOfResultSets; private ResultSet resultSet; private int indexOfFirstParam = 0; @@ -47,16 +54,18 @@ public class BytecodeGen implements ASTVisitor { byte[] bytecode; HashMap classFiles; - public BytecodeGen(HashMap classFiles, ResultSet resultSet) { + ArrayList methodNameAndParamsT = new ArrayList<>(); + + public BytecodeGen(HashMap classFiles, List listOfResultSets) { this.classFiles = classFiles; - this.resultSet = resultSet; + this.listOfResultSets = listOfResultSets; } @Override public void visit(SourceFile sourceFile) { for(ClassOrInterface cl : sourceFile.getClasses()) { System.out.println("in Class: " + cl.getClassName().toString()); - BytecodeGen classGen = new BytecodeGen(classFiles, resultSet); + BytecodeGen classGen = new BytecodeGen(classFiles, listOfResultSets); cl.accept(classGen); classGen.writeClass(cl.getClassName().toString()); } @@ -101,18 +110,27 @@ public class BytecodeGen implements ASTVisitor { 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()) { f.accept(this); } +// resultSet = listOfResultSets.get(0); + boolean isConsWithNoParamsVisited = false; + for(ResultSet rs : listOfResultSets) { + resultSet = rs; + + for(Constructor c : classOrInterface.getConstructors()) { + if(!isConsWithNoParamsVisited) + c.accept(this); + if(!c.getParameterList().iterator().hasNext()) + isConsWithNoParamsVisited = true; + } + + for(Method m : classOrInterface.getMethods()) { + m.accept(this); + } - for(Constructor c : classOrInterface.getConstructors()) { - c.accept(this); } - for(Method m : classOrInterface.getMethods()) { - m.accept(this); - } } @Override @@ -146,23 +164,40 @@ public class BytecodeGen implements ASTVisitor { 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 + String retType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); + String methParamTypes = retType+method.name+"%%"; method.getParameterList().accept(this); + Iterator itr = method.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+";"; + } + + if(methodNameAndParamsT.contains(methParamTypes)) { + return; + } + methodNameAndParamsT.add(methParamTypes); + System.out.println("Method: "+method.name +" , paramsType: "+methParamTypes); String methDesc = null; // Method getModifiers() ? int acc = isInterface?Opcodes.ACC_ABSTRACT:method.modifier; + System.out.println(acc); - boolean hasGenInParameterList = genericsAndBounds.containsKey(resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())); + /*Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist*/ + boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.subSequence(0, 4).equals("TPH "); + /*Wenn die Rückgabe-Type eine Typ-variable ist, erzeuge direkt die Signature, wenn nicht, + * prüfe, ob einer der Parameter Typ-Variable als Typ hat*/ if(!hasGenInParameterList) { for(String paramName : methodParamsAndTypes.keySet()) { String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToDescriptor()); - if(genericsAndBounds.containsKey(typeOfParam)) { + if(genericsAndBounds.containsKey(typeOfParam)||typeOfParam.substring(0, 4).equals("TPH ")) { hasGenInParameterList = true; break; } @@ -170,27 +205,31 @@ public class BytecodeGen implements ASTVisitor { } //TODO: Test if the return-type or any of the parameter is a parameterized type. (VP) - //than create the descriptor with the new syntax. + //then create the descriptor with the new syntax. String sig = null; + /* method.getGenerics: <....> RT method(..) + * */ boolean hasGen = method.getGenerics().iterator().hasNext() || hasGenInParameterList; /* if method has generics or return type is TPH, create signature */ + // zwite operand muss weggelassen werden if(hasGen||method.getReturnType().acceptTV(new TypeToString()).equals("TPH")) { // resultset hier zum testen Signature signature = new Signature(method, genericsAndBoundsMethod, methodParamsAndTypes,resultSet); sig = signature.toString(); } - System.out.println(sig); +// System.out.println(sig); NormalMethod meth = new NormalMethod(method,genericsAndBounds,genericsAndBoundsMethod,hasGen); methDesc = meth.accept(new DescriptorToString(resultSet)); - System.out.println(methDesc); + +// System.out.println(methDesc); MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC+acc, method.getName(), methDesc, sig, null); mv.visitCode(); - BytecodeGenMethod gen = new BytecodeGenMethod(className,resultSet,method, mv,paramsAndLocals,cw, - genericsAndBounds,genericsAndBounds,isInterface,classFiles); + genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles); + mv.visitMaxs(0, 0); mv.visitEnd(); } diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index df714015..468b079b 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -14,8 +14,12 @@ import java.util.Iterator; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.syntaxtree.statement.*; +import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr.Operator; +import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr.Operation; + import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Handle; +import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; @@ -25,46 +29,48 @@ import org.objectweb.asm.signature.SignatureWriter; import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; import de.dhbwstuttgart.bytecode.signature.Signature; -import de.dhbwstuttgart.bytecode.signature.TypeToSignature; -import de.dhbwstuttgart.bytecode.signature.TypeToString; +import de.dhbwstuttgart.bytecode.utilities.KindOfLambda; +import de.dhbwstuttgart.bytecode.utilities.Lambda; +import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall; +import de.dhbwstuttgart.bytecode.utilities.SamMethod; 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; - import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.typeinference.result.ResultSet; -public class BytecodeGenMethod implements StatementVisitor{ - +public class BytecodeGenMethod implements StatementVisitor { + private Method m; private MethodVisitor mv; - private HashMap paramsAndLocals = new HashMap<>(); + private HashMap paramsAndLocals = new HashMap<>(); private String className; private int lamCounter = -1; private ClassWriter cw; private ResultSet resultSet; private boolean isInterface; HashMap genericsAndBoundsMethod; - private HashMap genericsAndBounds; + private HashMap genericsAndBounds; private boolean isBinaryExp = false; - - //for tests ** + + private IStatement statement = null; + + // for tests ** private String fieldName; private String fieldDesc; private Expression rightSideTemp; + private boolean isRightSideALambda = false; private KindOfLambda kindOfLambda; private HashMap classFiles; - + private ArrayList varsFunInterface = new ArrayList<>();; - - public BytecodeGenMethod(String className,ResultSet resultSet, Method m, MethodVisitor mv, - HashMap paramsAndLocals, ClassWriter cw, HashMap genericsAndBoundsMethod, - HashMap genericsAndBounds, boolean isInterface, HashMap classFiles) { - + + public BytecodeGenMethod(String className, ResultSet resultSet, Method m, MethodVisitor mv, + HashMap paramsAndLocals, ClassWriter cw, HashMap genericsAndBoundsMethod, + HashMap genericsAndBounds, boolean isInterface, HashMap classFiles) { + this.className = className; this.resultSet = resultSet; this.m = m; @@ -75,15 +81,15 @@ public class BytecodeGenMethod implements StatementVisitor{ this.genericsAndBounds = genericsAndBounds; this.isInterface = isInterface; this.classFiles = classFiles; - - if(!isInterface) + + if (!isInterface) this.m.block.accept(this); - + } - - public BytecodeGenMethod(LambdaExpression lambdaExpression,ResultSet resultSet ,MethodVisitor mv, - int indexOfFirstParamLam, boolean isInterface, HashMap classFiles) { - + + public BytecodeGenMethod(LambdaExpression lambdaExpression, ResultSet resultSet, MethodVisitor mv, + int indexOfFirstParamLam, boolean isInterface, HashMap classFiles) { + this.resultSet = resultSet; this.mv = mv; this.isInterface = isInterface; @@ -91,42 +97,46 @@ public class BytecodeGenMethod implements StatementVisitor{ Iterator itr = lambdaExpression.params.iterator(); int i = indexOfFirstParamLam; - while(itr.hasNext()) { + 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.acceptTV(new TypeToDescriptor()); } - - + @Override public void visit(Block block) { - for(Statement stmt : block.getStatements()) { -// System.out.println(where); + for (Statement stmt : block.getStatements()) { stmt.accept(this); } } - + @Override public void visit(SuperCall superCall) { superCall.receiver.accept(this); superCall.arglist.accept(this); - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), superCall.name, "()V",isInterface); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), superCall.name, "()V", + isInterface); } - + // ?? @Override public void visit(LocalVar localVar) { + // wenn String + String zuerst wird ein StringBuilder initialisiert dann + // wird die lokale Var geladen. Sonst wird zuerst die lokale Var geladen. + mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name)); - if(isBinaryExp) { - getVlaue(getResolvedType(localVar.getType())); + + if (isBinaryExp) { + doUnboxing(getResolvedType(localVar.getType())); } } + // ?? @Override public void visit(LocalVarDecl localVarDecl) { @@ -135,188 +145,467 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(Assign assign) { + statement = new AssignStmt(assign.rightSide); // if the right side is a lambda => the left side must be a functional interface - if(assign.rightSide instanceof LambdaExpression) { + if (assign.rightSide instanceof LambdaExpression) { isRightSideALambda = true; - }else { + } else { isRightSideALambda = false; } - - if(assign.rightSide instanceof BinaryExpr) - isBinaryExp = true; - - if(assign.lefSide instanceof AssignToField) { + + isBinaryExp = statement.isExprBinary(); + + if (assign.lefSide instanceof AssignToField) { // load_0, ldc or .. then putfield this.rightSideTemp = assign.rightSide; - }else { + } else { assign.rightSide.accept(this); } - if(isBinaryExp) { - doAssign(getResolvedType(assign.lefSide.getType())); + if (isBinaryExp) { + BinaryExpr binary = (BinaryExpr) assign.rightSide; + String binaryType = getResolvedType(binary.getType()); + doBoxing(binaryType); isBinaryExp = false; } assign.lefSide.accept(this); + + statement = null; } - + @Override public void visit(BinaryExpr binary) { + + String lexpType = getResolvedType(binary.lexpr.getType()); + String rexpType = getResolvedType(binary.rexpr.getType()); + + String largerType = getLargerType(lexpType, rexpType); + String typeOfBinary = getResolvedType(binary.getType()); + + if (typeOfBinary.equals(Type.getInternalName(String.class))) { + mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(StringBuilder.class)); + mv.visitInsn(Opcodes.DUP); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(StringBuilder.class), "", "()V", + false); + } + + Label endLabel = new Label(); + // this case for while loops + if (statement instanceof LoopStmt) + mv.visitLabel(endLabel); + binary.lexpr.accept(this); + + if (!lexpType.equals(rexpType) && !lexpType.equals(largerType)) + doCast(lexpType, largerType); + binary.rexpr.accept(this); - switch (binary.operation.toString()) { - case "ADD": - mv.visitInsn(Opcodes.IADD); + + if (!lexpType.equals(rexpType) && !rexpType.equals(largerType)) + doCast(rexpType, largerType); + + Operator op = binary.operation; + + switch (op) { + case ADD: + doVisitAddOpInsn(largerType); + break; + + case SUB: + doVisitSubOpInsn(typeOfBinary); + break; + + case MUL: + doVisitMulOpInsn(typeOfBinary); + break; + + case DIV: + doVisitDivOpInsn(typeOfBinary); + break; + + case MOD: + doVisitModOpInsn(typeOfBinary); + break; + + case LESSTHAN: + case LESSEQUAL: + case BIGGERTHAN: + case BIGGEREQUAL: + Label branchLabel = new Label(); + doVisitRelOpInsn(op, largerType, branchLabel, endLabel); break; default: break; } - + } - + + /* + * Diese Methode wird nicht mehr gebraucht, da es jetzt nicht möglich ist, dass + * solche Fälle: Integer -> Integer (OP) Short ,... usw, nicht vorkommen! + */ + private String getLargerType(String lexpType, String rexpType) { + if (lexpType.equals(Type.getInternalName(String.class)) + || rexpType.equals(Type.getInternalName(String.class))) { + return Type.getInternalName(String.class); + } else if (lexpType.equals(Type.getInternalName(Double.class)) + || rexpType.equals(Type.getInternalName(Double.class))) { + return Type.getInternalName(Double.class); + } else if (lexpType.equals(Type.getInternalName(Float.class)) + || rexpType.equals(Type.getInternalName(Float.class))) { + return Type.getInternalName(Float.class); + } else if (lexpType.equals(Type.getInternalName(Long.class)) + || rexpType.equals(Type.getInternalName(Long.class))) { + return Type.getInternalName(Long.class); + } else { + return Type.getInternalName(Integer.class); + } + } + + private void doCast(String sourceType, String dest) { + switch (dest) { + case "java/lang/Long": + mv.visitInsn(Opcodes.I2L); + break; + + case "java/lang/Double": + if (sourceType.equals(Type.getInternalName(Long.class))) { + mv.visitInsn(Opcodes.L2D); + } else if (sourceType.equals(Type.getInternalName(Float.class))) { + mv.visitInsn(Opcodes.F2D); + } else { + mv.visitInsn(Opcodes.I2D); + } + break; + + case "java/lang/Float": + if (sourceType.equals(Type.getInternalName(Long.class))) { + mv.visitInsn(Opcodes.L2F); + } else { + mv.visitInsn(Opcodes.I2F); + } + break; + // braucht man eigentlic nicht, muss getestet werden + case "java/lang/String": + if (sourceType.equals(Type.getInternalName(Double.class))) { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", + "(D)Ljava/lang/String;", false); + } else if (sourceType.equals(Type.getInternalName(Long.class))) { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", + "(J)Ljava/lang/String;", false); + } else if (sourceType.equals(Type.getInternalName(Float.class))) { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", + "(F)Ljava/lang/String;", false); + } else { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", + "(I)Ljava/lang/String;", false); + } + break; + default: + break; + } + } + + private void doVisitRelOpInsn(Operator op, String typeOfBinary, Label branchLabel, Label endLabel) { + + switch (typeOfBinary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LCMP); + doVisitIfInRelOp(op, branchLabel, endLabel); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DCMPG); + doVisitIfInRelOp(op, branchLabel, endLabel); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FCMPG); + doVisitIfInRelOp(op, branchLabel, endLabel); + break; + default: + switch (op) { + case LESSTHAN: + mv.visitJumpInsn(Opcodes.IF_ICMPGE, branchLabel); + break; + case LESSEQUAL: + mv.visitJumpInsn(Opcodes.IF_ICMPGT, branchLabel); + break; + case BIGGERTHAN: + mv.visitJumpInsn(Opcodes.IF_ICMPLE, branchLabel); + break; + case BIGGEREQUAL: + mv.visitJumpInsn(Opcodes.IF_ICMPLT, branchLabel); + break; + default: + break; + } + + statement.genBCForRelOp(mv, branchLabel, endLabel, this); + + break; + } + } + + private void doVisitIfInRelOp(Operator op, Label branchLabel, Label endLabel) { + + switch (op) { + case LESSTHAN: + mv.visitJumpInsn(Opcodes.IFGE, branchLabel); + break; + case LESSEQUAL: + mv.visitJumpInsn(Opcodes.IFGT, branchLabel); + break; + case BIGGERTHAN: + mv.visitJumpInsn(Opcodes.IFLE, branchLabel); + break; + case BIGGEREQUAL: + mv.visitJumpInsn(Opcodes.IFLT, branchLabel); + break; + default: + break; + } + + statement.genBCForRelOp(mv, branchLabel, endLabel, this); + } + + private void doVisitModOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LREM); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DREM); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FREM); + break; + default: + mv.visitInsn(Opcodes.IREM); + break; + } + } + + private void doVisitDivOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LDIV); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DDIV); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FDIV); + break; + default: + mv.visitInsn(Opcodes.IDIV); + break; + } + } + + private void doVisitMulOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LMUL); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DMUL); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FMUL); + break; + default: + mv.visitInsn(Opcodes.IMUL); + break; + } + } + + private void doVisitSubOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LSUB); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DSUB); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FSUB); + break; + default: + mv.visitInsn(Opcodes.ISUB); + break; + } + + } + + private void doVisitAddOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case "java/lang/Byte": + mv.visitInsn(Opcodes.IADD); + break; + case "java/lang/Short": + mv.visitInsn(Opcodes.IADD); + break; + case "java/lang/Integer": + mv.visitInsn(Opcodes.IADD); + break; + case "java/lang/Long": + mv.visitInsn(Opcodes.LADD); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DADD); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FADD); + break; + default: + break; + } + } + @Override public void visit(LambdaExpression lambdaExpression) { this.lamCounter++; - + 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 + // 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); - + MethodType.class, MethodType.class, MethodHandle.class, MethodType.class); - Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", - "metafactory", mt.toMethodDescriptorString(), false); + Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", + mt.toMethodDescriptorString(), false); String methodName = "lambda$new$" + this.lamCounter; - - // Für die Parameter-Typen und Return-Typ braucht man die Bounds (für die Typlöschung) - + + // Für die Parameter-Typen und Return-Typ braucht man die Bounds (für die + // Typlöschung) + String typeErasure = "("; Iterator itr = lambdaExpression.params.iterator(); - while(itr.hasNext()) { + while (itr.hasNext()) { itr.next(); - typeErasure += "L"+Type.getInternalName(Object.class) + ";"; + typeErasure += "L" + Type.getInternalName(Object.class) + ";"; } - - typeErasure += ")L"+Type.getInternalName(Object.class) + ";"; + + typeErasure += ")L" + Type.getInternalName(Object.class) + ";"; // Type erasure Type arg1 = Type.getMethodType(typeErasure); -// Type arg1 = Type.getMethodType(lamDesc); + // Type arg1 = Type.getMethodType(lamDesc); // real Type Type arg3 = Type.getMethodType(lamDesc); - - int staticOrSpecial=0; - int staticOrInstance=0; + + int staticOrSpecial = 0; + int staticOrInstance = 0; int indexOfFirstParamLam = 0; this.kindOfLambda = new KindOfLambda(lambdaExpression); - if(kindOfLambda.isInstanceCapturingLambda()) { + if (kindOfLambda.isInstanceCapturingLambda()) { mv.visitVarInsn(Opcodes.ALOAD, 0); staticOrSpecial = Opcodes.H_INVOKESPECIAL; indexOfFirstParamLam = 1; - }else { + } 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); + 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, + 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, this.resultSet, mvLambdaBody, indexOfFirstParamLam, isInterface, classFiles); - + 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); - -// generateBCForFunN(lambdaExpression,typeErasure); + + generateBCForFunN(lambdaExpression, typeErasure); } private void generateBCForFunN(LambdaExpression lambdaExpression, String methDesc) { - ClassWriter classWriter =new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS); - + ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + SignatureWriter methSig = new SignatureWriter(); - + int numberOfParams = 0; SignatureVisitor paramVisitor = methSig.visitParameterType(); Iterator itr = lambdaExpression.params.iterator(); - while(itr.hasNext()) { + while (itr.hasNext()) { numberOfParams++; // getBounds - paramVisitor.visitTypeVariable("T"+numberOfParams); + paramVisitor.visitTypeVariable("T" + numberOfParams); itr.next(); } methSig.visitReturnType().visitTypeVariable("R"); // ")"+lam.getReturn.getBounds - Signature sig = new Signature(lambdaExpression,numberOfParams); - String name = "Fun"+numberOfParams; - classWriter.visit(Opcodes.V1_8, Opcodes.ACC_INTERFACE+Opcodes.ACC_ABSTRACT, name, - sig.toString(), Type.getInternalName(Object.class), null); - MethodVisitor mvApply = classWriter.visitMethod(Opcodes.ACC_PUBLIC+Opcodes.ACC_ABSTRACT, "apply", - methDesc, methSig.toString(), null); + Signature sig = new Signature(lambdaExpression, numberOfParams); + String name = "Fun" + numberOfParams + "$$"; + classWriter.visit(Opcodes.V1_8, Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(), + Type.getInternalName(Object.class), null); + MethodVisitor mvApply = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "apply", methDesc, + methSig.toString(), null); mvApply.visitEnd(); - writeClassFile(classWriter.toByteArray(),name); + writeClassFile(classWriter.toByteArray(), name); } - + public void writeClassFile(byte[] bytecode, String name) { FileOutputStream output; try { - System.out.println("generating "+name+ ".class file..."); - output = new FileOutputStream(new File(System.getProperty("user.dir") + "/testBytecode/generatedBC/examples/" +name+".class")); + 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"); + System.out.println(name + ".class file generated"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } - -} + + } @Override public void visit(CastExpr castExpr) { // TODO Auto-generated method stub - + } @Override public void visit(EmptyStmt emptyStmt) { // TODO Auto-generated method stub - + } @Override public void visit(FieldVar fieldVar) { - + fieldName = fieldVar.fieldVarName; - fieldDesc = "L"+getResolvedType(fieldVar.getType())+";"; - + fieldDesc = "L" + getResolvedType(fieldVar.getType()) + ";"; + fieldVar.receiver.accept(this); // test (if) - if(!fieldVar.receiver.getClass().equals(StaticClassName.class)) { - mv.visitFieldInsn(Opcodes.GETFIELD,getResolvedType(fieldVar.receiver.getType()), - fieldName ,fieldDesc); + if (!fieldVar.receiver.getClass().equals(StaticClassName.class)) { + mv.visitFieldInsn(Opcodes.GETFIELD, getResolvedType(fieldVar.receiver.getType()), fieldName, fieldDesc); } - -// mv.visitFieldInsn(Opcodes.GETSTATIC, fieldVar.receiver.getType().toString().replace(".", "/"), -// fieldVar.fieldVarName, fieldVar.getType().toString()); + + // mv.visitFieldInsn(Opcodes.GETSTATIC, + // fieldVar.receiver.getType().toString().replace(".", "/"), + // fieldVar.fieldVarName, fieldVar.getType().toString()); } @Override public void visit(ForStmt forStmt) { // TODO Auto-generated method stub - + } @Override @@ -327,52 +616,53 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(InstanceOf instanceOf) { // TODO Auto-generated method stub - + } @Override public void visit(MethodCall methodCall) { + methodCall.receiver.accept(this); methodCall.arglist.accept(this); - + MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), - genericsAndBoundsMethod,genericsAndBounds); + genericsAndBoundsMethod, genericsAndBounds); String mDesc = method.accept(new DescriptorToString(resultSet)); - + // is methodCall.receiver functional Interface)? - if(varsFunInterface.contains(methodCall.receiver.getType())) { - mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()), - methodCall.name, mDesc, false); - }else { - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, getResolvedType(methodCall.receiver.getType()), - methodCall.name, mDesc, isInterface); + if (varsFunInterface.contains(methodCall.receiver.getType())) { + mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()), methodCall.name, + mDesc, false); + } else { + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, getResolvedType(methodCall.receiver.getType()), methodCall.name, + mDesc, isInterface); } // test -// if(!methodCall.getType().toString().equals("V")) { -// mv.visitInsn(Opcodes.POP); -// } + // if(!methodCall.getType().toString().equals("V")) { + // mv.visitInsn(Opcodes.POP); + // } } @Override public void visit(NewClass methodCall) { - + mv.visitTypeInsn(Opcodes.NEW, methodCall.name.replace(".", "/")); mv.visitInsn(Opcodes.DUP); // creates Descriptor methodCall.arglist.accept(this); String d = "("; - for(Expression e : methodCall.arglist.getArguments()) { - d = d + "L"+getResolvedType(e.getType()) + ";"; + for (Expression e : methodCall.arglist.getArguments()) { + d = d + "L" + getResolvedType(e.getType()) + ";"; } d += ")V"; - + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, methodCall.name.replace(".", "/"), "", d, isInterface); } @Override public void visit(NewArray newArray) { // TODO Auto-generated method stub - + } @Override @@ -382,13 +672,101 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(UnaryExpr unaryExpr) { - System.out.println(unaryExpr.operation.toString()); + unaryExpr.expr.accept(this); + Operation op = unaryExpr.operation; + + String typeOfUnary = getResolvedType(unaryExpr.getType()); + + boolean isIncOrDec = false; + + switch (op) { + case POSTDECREMENT: + case POSTINCREMENT: + if (statement instanceof AssignStmt) + mv.visitInsn(Opcodes.DUP); + genBCForIncAndDec(op, typeOfUnary); + doBoxing(typeOfUnary); + isIncOrDec = true; + break; + case PREDECREMENT: + case PREINCREMENT: + genBCForIncAndDec(op, typeOfUnary); + doBoxing(typeOfUnary); + if (statement instanceof AssignStmt) + mv.visitInsn(Opcodes.DUP); + isIncOrDec = true; + break; + + case MINUS: + doVisitNegIns(typeOfUnary); + break; + default: + break; + } + + // Für Byte und Short muss noch einen Cast geben i2b, i2s + // das wird später gemacht, da bytecode für cast noch nicht erzeugt wird + + if (isIncOrDec && (unaryExpr.expr instanceof LocalVar)) { + LocalVar local = (LocalVar) unaryExpr.expr; + mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.get(local.name)); + } + } + + private void doVisitNegIns(String typeOfUnary) { + switch (typeOfUnary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LNEG); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DNEG); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FNEG); + break; + default: + mv.visitInsn(Opcodes.INEG); + break; + } + + } + + private void genBCForIncAndDec(Operation op, String typeOfUnary) { + + doUnboxing(typeOfUnary); + loadValue(typeOfUnary, 1.0, true); + + switch (op) { + case POSTDECREMENT: + case PREDECREMENT: + doVisitSubOpInsn(typeOfUnary); + break; + + case POSTINCREMENT: + case PREINCREMENT: + doVisitAddOpInsn(typeOfUnary); + break; + + default: + break; + } } @Override public void visit(Return aReturn) { + statement = new ReturnStmt(aReturn.retexpr); + isBinaryExp = statement.isExprBinary(); + aReturn.retexpr.accept(this); + + if (isBinaryExp) { + BinaryExpr binary = (BinaryExpr) aReturn.retexpr; + doBoxing(getResolvedType(binary.getType())); + isBinaryExp = false; + } + mv.visitInsn(Opcodes.ARETURN); + statement = null; } @Override @@ -398,10 +776,12 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(StaticClassName staticClassName) { -// mv.visitMethodInsn(Opcodes.INVOKESTATIC, staticClassName.getType().toString().replace(".", "/"), -// staticClassName.toString(), staticClassName.getType().toString(), false); - mv.visitFieldInsn(Opcodes.GETSTATIC, getResolvedType(staticClassName.getType()), - fieldName, fieldDesc); + // mv.visitMethodInsn(Opcodes.INVOKESTATIC, + // staticClassName.getType().toString().replace(".", "/"), + // staticClassName.toString(), staticClassName.getType().toString(), false); + // mv.visitFieldInsn(Opcodes.GETSTATIC, + // getResolvedType(staticClassName.getType()), fieldName, fieldDesc); + throw new NotImplementedException("Static noch nicht implementiert!"); } @Override @@ -416,63 +796,66 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(WhileStmt whileStmt) { + statement = new LoopStmt(whileStmt.expr, whileStmt.loopBlock); + isBinaryExp = statement.isExprBinary(); whileStmt.expr.accept(this); - whileStmt.loopBlock.accept(this); + isBinaryExp = false; + statement = null; } @Override public void visit(DoStmt whileStmt) { - // TODO Auto-generated method stub - + whileStmt.expr.accept(this); + // TODO: } @Override public void visit(Literal literal) { Object value = literal.value; - String typeOfLiteral = resultSet.resolveType(literal.getType()).resolvedType.acceptTV(new TypeToDescriptor()); - if(this.isBinaryExp) { - getVlaue(typeOfLiteral); - }else { - doAssign(typeOfLiteral, value); - } - - + String typeOfLiteral = getResolvedType(literal.getType()); + // Der Wert des Literals wird auf den Stack geladen und + // geboxt, wenn es nötig ist. + loadValue(typeOfLiteral, value, false); } - - private void getVlaue(String typeOfLiteral) { - switch (typeOfLiteral) { + + // Unboxing: RefType -> prim + private void doUnboxing(String type) { + switch (type) { case "java/lang/String": + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(StringBuilder.class), "append", + "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); + break; case "java/lang/Boolean": break; case "java/lang/Byte": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", - "(B)Ljava/lang/Byte;", false); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false); break; case "java/lang/Short": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", - "(S)Ljava/lang/Short;", false); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false); break; case "java/lang/Integer": - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", - "()I", false); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false); break; case "java/lang/Long": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", - "(J)Ljava/lang/Long;", false); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false); break; case "java/lang/Float": + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false); break; case "java/lang/Double": + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false); break; case "java/lang/Character": break; default: + // mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", + // "()I", false); break; } } - private void doAssign(String type, Object value) { + private void loadValue(String type, Object value, boolean isOperator) { switch (type) { case "java/lang/String": mv.visitLdcInsn(String.valueOf(value)); @@ -481,25 +864,17 @@ public class BytecodeGenMethod implements StatementVisitor{ visitBooleanLiteral((Boolean) value); break; case "java/lang/Byte": - visitByteLiteral(((Double) value).byteValue(),false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", - "(B)Ljava/lang/Byte;", false); + visitByteLiteral(((Double) value).byteValue(), false); break; case "java/lang/Short": - visitShortLiteral(((Double) value).shortValue(),false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", - "(S)Ljava/lang/Short;", false); + visitShortLiteral(((Double) value).shortValue(), false); break; case "java/lang/Integer": - //zweite Argument isLong + // zweite Argument isLong visitIntegerLiteral(((Double) value).intValue(), false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", - "(I)Ljava/lang/Integer;", false); break; case "java/lang/Long": visitLongLiteral(((Double) value).longValue(), true); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", - "(J)Ljava/lang/Long;", false); break; case "java/lang/Float": visitFloatLiteral(((Double) value).floatValue()); @@ -511,37 +886,50 @@ public class BytecodeGenMethod implements StatementVisitor{ visitCharLiteral((Character) value); break; default: + // wenn die Typ des Literals = Number ist, wird integer-value + // verwendet +// visitIntegerLiteral(((Double) value).intValue(), false); break; } + // Boxing + if (!type.equals("java/lang/String") && !type.equals("java/lang/Boolean")) { + if (!this.isBinaryExp && !isOperator) + doBoxing(type); + } + } - - private void doAssign(String type) { + + // Boxing: prim -> RefType + private void doBoxing(String type) { switch (type) { case "java/lang/String": + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", + false); break; case "java/lang/Boolean": + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); break; case "java/lang/Byte": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", - "(B)Ljava/lang/Byte;", false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false); break; case "java/lang/Short": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", - "(S)Ljava/lang/Short;", false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false); break; case "java/lang/Integer": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", - "(I)Ljava/lang/Integer;", false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); break; case "java/lang/Long": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", - "(J)Ljava/lang/Long;", false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); break; case "java/lang/Float": + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); break; case "java/lang/Double": + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); break; case "java/lang/Character": + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", + false); break; default: break; @@ -550,111 +938,115 @@ public class BytecodeGenMethod implements StatementVisitor{ private void visitCharLiteral(Character value) { mv.visitIntInsn(Opcodes.BIPUSH, (int) value); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", - "(C)Ljava/lang/Character;", false); + } private void visitDoubleLiteral(Double value) { - if(value == 0) { + if (value == 0) { mv.visitInsn(Opcodes.DCONST_0); - }else if(value == 1) { + } else if (value == 1) { mv.visitInsn(Opcodes.DCONST_1); - }else { + } else { mv.visitLdcInsn(value); } - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", - "(D)Ljava/lang/Double;", false); } private void visitFloatLiteral(Float value) { - if(value.intValue()>-1 && value.intValue() < 3) { - //Opcodes.FCONST_0 = 11, Opcodes.FCONST_1 = 12, usw - mv.visitInsn(value.intValue()+11); - }else { + if (value.intValue() > -1 && value.intValue() < 3) { + // Opcodes.FCONST_0 = 11, Opcodes.FCONST_1 = 12, usw + mv.visitInsn(value.intValue() + 11); + } else { mv.visitLdcInsn(value); } - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", - "(F)Ljava/lang/Float;", false); } private void visitLongLiteral(Long value, boolean isLong) { - if(value=-Math.pow(2, 15))&&value<-128) { - visitShortLiteral(value.shortValue(),isLong); - }else { + if (value < Math.pow(2, 15) || (value >= -Math.pow(2, 15)) && value < -128) { + visitShortLiteral(value.shortValue(), isLong); + } else { mv.visitLdcInsn(value); } } - private void visitShortLiteral(Short value,boolean isLong) { - if(value< 128 || (value>-129 && value<-1)) { + private void visitShortLiteral(Short value, boolean isLong) { + if (value < 128 || (value > -129 && value < -1)) { visitByteLiteral(value.byteValue(), isLong); - }else if(value=-Math.pow(2, 15))&&value<-128) { + } else if (value < Math.pow(2, 15) || (value >= -Math.pow(2, 15)) && value < -128) { mv.visitIntInsn(Opcodes.SIPUSH, value); } } private void visitByteLiteral(Byte value, boolean isLong) { - - if(!isLong && value<6 && value>-1) { - //Opcodes.ICONST_0 = 3, Opcodes.ICONST_1 = 4, usw - mv.visitInsn(value+3); - }else if(isLong && value>-1 && value<2){ - //Opcodes.LCONST_0 = 9, Opcodes.LCONST_1 = 10 - mv.visitInsn(value+9); - }else { + + if (!isLong && value < 6 && value > -1) { + // Opcodes.ICONST_0 = 3, Opcodes.ICONST_1 = 4, usw + mv.visitInsn(value + 3); + } else if (isLong && value > -1 && value < 2) { + // Opcodes.LCONST_0 = 9, Opcodes.LCONST_1 = 10 + mv.visitInsn(value + 9); + } else { mv.visitIntInsn(Opcodes.BIPUSH, value); } - + } private void visitIntegerLiteral(Integer value, boolean isLong) { - - if(value=-Math.pow(2, 15))&&value<-128) { - visitShortLiteral(value.shortValue(),isLong); - }else { + + if (value < Math.pow(2, 15) || (value >= -Math.pow(2, 15)) && value < -128) { + visitShortLiteral(value.shortValue(), isLong); + } else { mv.visitLdcInsn(value); } } private void visitBooleanLiteral(Boolean b) { - if(b) { + if (b) { mv.visitInsn(Opcodes.ICONST_1); - }else { + } else { mv.visitInsn(Opcodes.ICONST_0); } - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", - "(Z)Ljava/lang/Boolean;", false); + // muss noch getestet werden. + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); } @Override public void visit(ArgumentList argumentList) { - for(Expression al : argumentList.getArguments()) { + for (Expression al : argumentList.getArguments()) { + statement = new ArgumentExpr(al); al.accept(this); + statement = null; } } @Override public void visit(AssignToField assignLeftSide) { -// temporäre Lösung für testen, bis ich weiss wie man funktionale -// interfaces erkennt - if(isRightSideALambda) + // 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. + // 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, getResolvedType(assignLeftSide.field.receiver.getType()), + mv.visitFieldInsn(Opcodes.PUTFIELD, getResolvedType(assignLeftSide.field.receiver.getType()), assignLeftSide.field.fieldVarName, getResolvedType(assignLeftSide.field.getType())); } @Override public void visit(AssignToLocal assignLeftSide) { - if(isRightSideALambda) + if (isRightSideALambda) varsFunInterface.add(assignLeftSide.localVar.getType()); - paramsAndLocals.put(assignLeftSide.localVar.name, paramsAndLocals.size()+1); + int index = paramsAndLocals.size(); + String var = assignLeftSide.localVar.name; + if (!paramsAndLocals.containsKey(var)) { + paramsAndLocals.put(var, index + 1); + } else { + paramsAndLocals.put(var, index); + } + mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.size()); // Debug::: - + } } diff --git a/src/de/dhbwstuttgart/bytecode/IStatement.java b/src/de/dhbwstuttgart/bytecode/IStatement.java new file mode 100644 index 00000000..f8d61097 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/IStatement.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.bytecode; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; + +public interface IStatement { + public boolean isExprBinary(); + public void genBCForRelOp(MethodVisitor mv, Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod); +} diff --git a/src/de/dhbwstuttgart/bytecode/LoopStmt.java b/src/de/dhbwstuttgart/bytecode/LoopStmt.java new file mode 100644 index 00000000..109efd34 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/LoopStmt.java @@ -0,0 +1,25 @@ +package de.dhbwstuttgart.bytecode; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.syntaxtree.statement.Statement; + +public class LoopStmt extends AStatement { + + private Statement loopBlock; + + public LoopStmt(Expression expr, Statement loopBlock) { + super(expr); + this.loopBlock = loopBlock; + } + + @Override + public void genBCForRelOp(MethodVisitor mv,Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod) { + this.loopBlock.accept(bytecodeGenMethod); + mv.visitJumpInsn(Opcodes.GOTO, endLabel); + mv.visitLabel(branchLabel); + } +} diff --git a/src/de/dhbwstuttgart/bytecode/ReturnStmt.java b/src/de/dhbwstuttgart/bytecode/ReturnStmt.java new file mode 100644 index 00000000..bd747720 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/ReturnStmt.java @@ -0,0 +1,14 @@ +package de.dhbwstuttgart.bytecode; + +import org.objectweb.asm.MethodVisitor; + +import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr; +import de.dhbwstuttgart.syntaxtree.statement.Expression; + +public class ReturnStmt extends AStatement { + + public ReturnStmt(Expression retexpr) { + super(retexpr); + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java b/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java index c9725a82..0e97ca4c 100644 --- a/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java +++ b/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java @@ -2,12 +2,12 @@ package de.dhbwstuttgart.bytecode.descriptor; import java.util.Iterator; -import de.dhbwstuttgart.bytecode.Lambda; -import de.dhbwstuttgart.bytecode.MethodFromMethodCall; -import de.dhbwstuttgart.bytecode.NormalConstructor; -import de.dhbwstuttgart.bytecode.NormalMethod; -import de.dhbwstuttgart.bytecode.SamMethod; import de.dhbwstuttgart.bytecode.signature.TypeToSignature; +import de.dhbwstuttgart.bytecode.utilities.Lambda; +import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall; +import de.dhbwstuttgart.bytecode.utilities.NormalConstructor; +import de.dhbwstuttgart.bytecode.utilities.NormalMethod; +import de.dhbwstuttgart.bytecode.utilities.SamMethod; import de.dhbwstuttgart.syntaxtree.FormalParameter; import de.dhbwstuttgart.syntaxtree.statement.Expression; import de.dhbwstuttgart.syntaxtree.type.RefType; @@ -46,12 +46,19 @@ public class DescriptorToString implements DescriptorVisitor{ }else if(method.getGenericsAndBounds().containsKey(fpDesc)){ desc += "L"+method.getGenericsAndBounds().get(fpDesc)+ ";"; }else { - desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; +// desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + String resType = resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + if(resType.subSequence(0, 4).equals("TPH ")) { + desc += "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";"; + } else { + desc += "L"+resType+ ";"; + } } } -// else if(((RefType) fp.getType()).getParaList().size() > 0){ -// desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "%").replace("<", "%%").replace(">", "%%")+ ";"; -// } + //TODO: generate a class java%% ... %% + else if(resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()).contains("<")){ + desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "$$").replace("<", "$$$").replace(">", "$$$")+ ";"; + } else { desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; } @@ -67,7 +74,12 @@ public class DescriptorToString implements DescriptorVisitor{ }else if(method.getGenericsAndBounds().containsKey(ret)){ desc += ")L"+method.getGenericsAndBounds().get(ret)+ ";"; }else { - desc += ")" + "L"+resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + String resType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); + if(resType.subSequence(0, 4).equals("TPH ")) { + desc += ")" + "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";"; + } else { + desc += ")" + "L"+resType+ ";"; + } } }else { desc += ")" + "L"+resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; diff --git a/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorVisitor.java b/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorVisitor.java index 6bc57f21..35f1423e 100644 --- a/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorVisitor.java +++ b/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorVisitor.java @@ -1,10 +1,10 @@ package de.dhbwstuttgart.bytecode.descriptor; -import de.dhbwstuttgart.bytecode.Lambda; -import de.dhbwstuttgart.bytecode.MethodFromMethodCall; -import de.dhbwstuttgart.bytecode.NormalConstructor; -import de.dhbwstuttgart.bytecode.NormalMethod; -import de.dhbwstuttgart.bytecode.SamMethod; +import de.dhbwstuttgart.bytecode.utilities.Lambda; +import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall; +import de.dhbwstuttgart.bytecode.utilities.NormalConstructor; +import de.dhbwstuttgart.bytecode.utilities.NormalMethod; +import de.dhbwstuttgart.bytecode.utilities.SamMethod; public interface DescriptorVisitor { public String visit(NormalMethod method); diff --git a/src/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java b/src/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java index e374bb93..69ac6d13 100644 --- a/src/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java +++ b/src/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java @@ -13,6 +13,8 @@ public class TypeToDescriptor implements TypeVisitor{ @Override public String visit(RefType refType) { return refType.getName().toString().replace(".", "/"); +// String t = refType.getName().toString().replace(".", "/"); +// return t.equals("Fun1")?(t+"$$"):t; } @Override @@ -27,7 +29,8 @@ public class TypeToDescriptor implements TypeVisitor{ @Override public String visit(ExtendsWildcardType extendsWildcardType) { - throw new NotImplementedException(); + return extendsWildcardType.getInnerType().toString().replace(".", "/"); + //throw new NotImplementedException(); } @Override diff --git a/src/de/dhbwstuttgart/bytecode/signature/Signature.java b/src/de/dhbwstuttgart/bytecode/signature/Signature.java index 46202cb1..48804661 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/Signature.java +++ b/src/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -59,10 +59,7 @@ public class Signature { private void createSignatureForFunN(LambdaExpression lambdaExpression, int numberOfParams) { - sw.visitFormalTypeParameter("R"); - // getBounds vom Return-Type - sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); - sw.visitClassBound().visitEnd(); +// sw.visitClassBound().visitEnd(); for(int i = 0;i wird eine Formal Type Parameter K$ erzeugt und Bound = Object + String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); + if(ret.substring(0,4).equals("TPH ")) { + String g = ret.substring(4)+"$"; + sw.visitFormalTypeParameter(g); + sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); + genericsAndBoundsMethod.put(g, Type.getInternalName(Object.class)); + sw.visitClassBound().visitEnd(); + } + + for(String paramName : methodParamsAndTypes.keySet()) { + RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName); + String pT = t.acceptTV(new TypeToSignature()); + // S.o + if(pT.substring(0,4).equals("TPH ") && !genericsAndBoundsMethod.containsKey(pT)) { + String gP = pT.substring(4)+"$"; + sw.visitFormalTypeParameter(gP); + sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); + genericsAndBoundsMethod.put(gP, Type.getInternalName(Object.class)); + sw.visitClassBound().visitEnd(); + } + } + + // visit each method-parameter to create the signature for(String paramName : methodParamsAndTypes.keySet()) { RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName); // parameter type deswegen ist true @@ -99,6 +125,15 @@ public class Signature { if(isConstructor) { sw.visitReturnType().visitBaseType('V'); }else { +// String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); +// if(ret.substring(0,4).equals("TPH ")) { +// String g = ret.substring(4); +// if(!genericsAndBoundsMethod.containsKey(g)) { +// genericsAndBoundsMethod.put(g, Type.getInternalName(Object.class)); +// } else { +// genericsAndBoundsMethod.put(g+"_", Type.getInternalName(Object.class)); +// } +// } RefTypeOrTPHOrWildcardOrGeneric returnType = method.getReturnType(); // return type deswegen ist false doVisitParamsOrReturn(returnType, false); @@ -130,10 +165,16 @@ public class Signature { break; case "TPH": RefTypeOrTPHOrWildcardOrGeneric r = resultSet.resolveType(t).resolvedType; - if(!r.acceptTV(new TypeToSignature()).substring(0, 4).equals("TPH ")) - sv.visitInterface().visitClassType(r.acceptTV(new TypeToSignature())); -// sv.visitClassType(r.acceptTV(new TypeToSignature())); - System.out.println(r.getClass()+" Signature TPH: "+r.acceptTV(new TypeToSignature())); + // der Fall wenn die Type eine Interface ist, muss betrachtet werden + // Deswegen muss in ResutSet noch enthalten werden, ob die Type eine + // Interface oder eine Klasse ist. + if(!r.acceptTV(new TypeToSignature()).substring(0, 4).equals("TPH ")) { +// sv.visitInterface().visitClassType(r.acceptTV(new TypeToSignature())); + sv.visitClassType(r.acceptTV(new TypeToSignature())); + } else { + System.out.println(r.getClass()+" Signature TPH: "+r.acceptTV(new TypeToSignature())); + sv.visitTypeVariable(r.acceptTV(new TypeToSignature()).substring(4)+"$"); + } break; default: if(!isParameterType) diff --git a/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java b/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java index 78b2fb22..a1357d4c 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java +++ b/src/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java @@ -27,6 +27,8 @@ public class TypeToSignature implements TypeVisitor { } params += ";>"; } +// String t = refType.getName().toString().replace(".", "/"); +// return t.equals("Fun1")?t+"$$"+params+";":t+params+";"; return refType.getName().toString().replace(".", "/") + params+";"; } diff --git a/src/de/dhbwstuttgart/bytecode/KindOfLambda.java b/src/de/dhbwstuttgart/bytecode/utilities/KindOfLambda.java similarity index 98% rename from src/de/dhbwstuttgart/bytecode/KindOfLambda.java rename to src/de/dhbwstuttgart/bytecode/utilities/KindOfLambda.java index 1cc8e386..d2f7ee5b 100644 --- a/src/de/dhbwstuttgart/bytecode/KindOfLambda.java +++ b/src/de/dhbwstuttgart/bytecode/utilities/KindOfLambda.java @@ -1,4 +1,4 @@ -package de.dhbwstuttgart.bytecode; +package de.dhbwstuttgart.bytecode.utilities; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.syntaxtree.statement.*; diff --git a/src/de/dhbwstuttgart/bytecode/Lambda.java b/src/de/dhbwstuttgart/bytecode/utilities/Lambda.java similarity index 93% rename from src/de/dhbwstuttgart/bytecode/Lambda.java rename to src/de/dhbwstuttgart/bytecode/utilities/Lambda.java index c3b4e8f5..6371c618 100644 --- a/src/de/dhbwstuttgart/bytecode/Lambda.java +++ b/src/de/dhbwstuttgart/bytecode/utilities/Lambda.java @@ -1,4 +1,4 @@ -package de.dhbwstuttgart.bytecode; +package de.dhbwstuttgart.bytecode.utilities; import de.dhbwstuttgart.bytecode.descriptor.DescriptorVisitor; import de.dhbwstuttgart.syntaxtree.ParameterList; diff --git a/src/de/dhbwstuttgart/bytecode/MethodFromMethodCall.java b/src/de/dhbwstuttgart/bytecode/utilities/MethodFromMethodCall.java similarity index 96% rename from src/de/dhbwstuttgart/bytecode/MethodFromMethodCall.java rename to src/de/dhbwstuttgart/bytecode/utilities/MethodFromMethodCall.java index 0f781b46..cd8f5372 100644 --- a/src/de/dhbwstuttgart/bytecode/MethodFromMethodCall.java +++ b/src/de/dhbwstuttgart/bytecode/utilities/MethodFromMethodCall.java @@ -1,4 +1,4 @@ -package de.dhbwstuttgart.bytecode; +package de.dhbwstuttgart.bytecode.utilities; import java.util.HashMap; diff --git a/src/de/dhbwstuttgart/bytecode/NormalConstructor.java b/src/de/dhbwstuttgart/bytecode/utilities/NormalConstructor.java similarity index 95% rename from src/de/dhbwstuttgart/bytecode/NormalConstructor.java rename to src/de/dhbwstuttgart/bytecode/utilities/NormalConstructor.java index a9aa482a..3a16fb00 100644 --- a/src/de/dhbwstuttgart/bytecode/NormalConstructor.java +++ b/src/de/dhbwstuttgart/bytecode/utilities/NormalConstructor.java @@ -1,4 +1,4 @@ -package de.dhbwstuttgart.bytecode; +package de.dhbwstuttgart.bytecode.utilities; import java.util.HashMap; diff --git a/src/de/dhbwstuttgart/bytecode/NormalMethod.java b/src/de/dhbwstuttgart/bytecode/utilities/NormalMethod.java similarity index 97% rename from src/de/dhbwstuttgart/bytecode/NormalMethod.java rename to src/de/dhbwstuttgart/bytecode/utilities/NormalMethod.java index 5afc31fb..4e5bc887 100644 --- a/src/de/dhbwstuttgart/bytecode/NormalMethod.java +++ b/src/de/dhbwstuttgart/bytecode/utilities/NormalMethod.java @@ -1,4 +1,4 @@ -package de.dhbwstuttgart.bytecode; +package de.dhbwstuttgart.bytecode.utilities; import java.util.HashMap; diff --git a/src/de/dhbwstuttgart/bytecode/SamMethod.java b/src/de/dhbwstuttgart/bytecode/utilities/SamMethod.java similarity index 94% rename from src/de/dhbwstuttgart/bytecode/SamMethod.java rename to src/de/dhbwstuttgart/bytecode/utilities/SamMethod.java index f14d5407..1c1b883c 100644 --- a/src/de/dhbwstuttgart/bytecode/SamMethod.java +++ b/src/de/dhbwstuttgart/bytecode/utilities/SamMethod.java @@ -1,4 +1,4 @@ -package de.dhbwstuttgart.bytecode; +package de.dhbwstuttgart.bytecode.utilities; import java.util.List; diff --git a/src/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/de/dhbwstuttgart/core/JavaTXCompiler.java index 56f2200f..8af14f1c 100644 --- a/src/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -11,8 +11,14 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import de.dhbwstuttgart.bytecode.BytecodeGen; import de.dhbwstuttgart.environment.CompilationEnvironment; import de.dhbwstuttgart.parser.JavaTXParser; +<<<<<<< HEAD +======= +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.scope.GenericsRegistry; +>>>>>>> e0d5699ae7f35d8b7af47aeb4adfb33a5167cd00 import de.dhbwstuttgart.parser.SyntaxTreeGenerator.SyntaxTreeGenerator; import de.dhbwstuttgart.parser.antlr.Java8Parser.CompilationUnitContext; import de.dhbwstuttgart.parser.scope.GenericsRegistry; @@ -27,20 +33,29 @@ import de.dhbwstuttgart.strucTypes.exception.InconsistentConstraintsException; import de.dhbwstuttgart.strucTypes.model.InferredTypes; import de.dhbwstuttgart.strucTypes.model.SolvedClass; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.ParameterList; import de.dhbwstuttgart.syntaxtree.SourceFile; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; import de.dhbwstuttgart.typeinference.constraints.Constraint; import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; import de.dhbwstuttgart.typeinference.constraints.Pair; import de.dhbwstuttgart.typeinference.result.ResultSet; import de.dhbwstuttgart.typeinference.typeAlgo.TYPE; +import de.dhbwstuttgart.typeinference.unify.RuleSet; import de.dhbwstuttgart.typeinference.unify.TypeUnify; +<<<<<<< HEAD import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +======= +import de.dhbwstuttgart.typeinference.unify.distributeVariance; +>>>>>>> e0d5699ae7f35d8b7af47aeb4adfb33a5167cd00 import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +<<<<<<< HEAD public class JavaTXCompiler { final CompilationEnvironment environment; @@ -172,5 +187,240 @@ public class JavaTXCompiler { SourceFile ret = generator.convert(tree, environment.packageCrawler); return ret; } +======= +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; -} \ No newline at end of file +public class JavaTXCompiler { + + final CompilationEnvironment environment; + public final Map sourceFiles = new HashMap<>(); + Boolean log = true; //gibt an ob ein Log-File nach System.getProperty("user.dir")+"/test/logFiles/log" geschrieben werden soll? + + public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException { + this(Arrays.asList(sourceFile)); + } + + public JavaTXCompiler(File sourceFile, Boolean log) throws IOException, ClassNotFoundException { + this(sourceFile); + this.log = log; + } + + public JavaTXCompiler(List sources) throws IOException, ClassNotFoundException { + environment = new CompilationEnvironment(sources); + for (File s : sources) { + sourceFiles.put(s, parse(s)); + } + } + + public ConstraintSet getConstraints() throws ClassNotFoundException { + List allClasses = new ArrayList<>();//environment.getAllAvailableClasses(); + 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()) { + //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 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<>(); + try { + FileWriter logFile = new FileWriter(new File(System.getProperty("user.dir")+"/test/logFiles/"+"log")); + logFile.write("FC:\\" + finiteClosure.toString()+"\n"); + for(SourceFile sf : this.sourceFiles.values()) { + logFile.write(ASTTypePrinter.print(sf)); + } + logFile.flush(); + Set>> cardProd = unifyCons.cartesianProduct(); + for (List> xCons : cardProd ){ + Set xConsSet = new HashSet<>(); + for (Constraint constraint : xCons) { + xConsSet.addAll(constraint); + } + //.collect(Collectors.toCollection(ArrayList::new)))) + System.out.println(xConsSet); + Set paraTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist() + .stream().filter(z -> z.getType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder)z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))) + .reduce(new HashSet(), (a,b) -> { a.addAll(b); return a;}, (a,b) -> { a.addAll(b); return a;} ) ) + .reduce(new HashSet(), (a,b) -> { a.addAll(b); return a;} ); + + Set returnTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get(); + + + xConsSet = xConsSet.stream().map(x -> { + //Hier muss ueberlegt werden, ob + //1. alle Argument- und Retuntyp-Variablen in allen UnifyPairs + // mit disableWildcardtable() werden. + //2. alle Typvariablen mit Argument- oder Retuntyp-Variablen + //in Beziehung auch auf disableWildcardtable() gesetzt werden muessen + //PL 2018-04-23 + if ((x.getLhsType() instanceof PlaceholderType)) { + if (paraTypeVarNames.contains(x.getLhsType().getName())) { + ((PlaceholderType)x.getLhsType()).setVariance((byte)1); + ((PlaceholderType)x.getLhsType()).disableWildcardtable(); + } + if (returnTypeVarNames.contains(x.getLhsType().getName())) { + ((PlaceholderType)x.getLhsType()).setVariance((byte)-1); + ((PlaceholderType)x.getLhsType()).disableWildcardtable(); + } + } + if ((x.getRhsType() instanceof PlaceholderType)) { + if (paraTypeVarNames.contains(x.getRhsType().getName())) { + ((PlaceholderType)x.getRhsType()).setVariance((byte)1); + ((PlaceholderType)x.getRhsType()).disableWildcardtable(); + } + if (returnTypeVarNames.contains(x.getRhsType().getName())) { + ((PlaceholderType)x.getRhsType()).setVariance((byte)-1); + ((PlaceholderType)x.getRhsType()).disableWildcardtable(); + } + } + return x;//HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE JEWEILS ANDERE SEITE + }).map( y -> { + if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { + if (((PlaceholderType)y.getLhsType()).getVariance() != 0 && ((PlaceholderType)y.getRhsType()).getVariance() == 0) { + ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType()).getVariance()); + } + if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { + ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType()).getVariance()); + } + } + return y; } ) + .collect(Collectors.toCollection(HashSet::new)); + varianceInheritance(xConsSet); + Set> result = unify.unifySequential(xConsSet, finiteClosure, logFile, log); + //Set> result = unify.unify(xConsSet, finiteClosure); + System.out.println("RESULT: " + result); + logFile.write("RES: " + result.toString()+"\n"); + logFile.flush(); + results.addAll(result); + } + } + catch (IOException e) { } + + return results.stream().map((unifyPairs -> + new ResultSet(UnifyTypeFactory.convert(unifyPairs, generateTPHMap(cons))))).collect(Collectors.toList()); + } + + /** + * Vererbt alle Variancen + * @param eq The set of constraints + */ + private void varianceInheritance(Set eq) { + Set usedTPH = new HashSet<>(); + Set phSet = eq.stream().map(x -> { + Set pair = new HashSet<>(); + if (x.getLhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getLhsType()); + if (x.getRhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getRhsType()); + return pair; + }).reduce(new HashSet<>(), (a,b) -> { a.addAll(b); return a;} , (c,d) -> { c.addAll(d); return c;}); + + ArrayList phSetVariance = new ArrayList<>(phSet); + phSetVariance.removeIf(x -> (x.getVariance() == 0)); + while(!phSetVariance.isEmpty()) { + PlaceholderType a = phSetVariance.remove(0); + usedTPH.add(a); + //HashMap ht = new HashMap<>(); + //ht.put(a, a.getVariance()); + Set eq1 = new HashSet<>(eq); + eq1.removeIf(x -> !(x.getLhsType() instanceof PlaceholderType && ((PlaceholderType)x.getLhsType()).equals(a))); + eq1.stream().forEach(x -> { x.getRhsType().accept(new distributeVariance(), a.getVariance());}); + eq1 = new HashSet<>(eq); + eq1.removeIf(x -> !(x.getRhsType() instanceof PlaceholderType && ((PlaceholderType)x.getRhsType()).equals(a))); + eq1.stream().forEach(x -> { x.getLhsType().accept(new distributeVariance(), a.getVariance());}); + phSetVariance = new ArrayList<>(phSet); + phSetVariance.removeIf(x -> (x.getVariance() == 0 || usedTPH.contains(x))); + } +} + + 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); + } + if (p.TA2 instanceof TypePlaceholder) { + ret.put(((TypePlaceholder) p.TA2).getName(), (TypePlaceholder) p.TA2); + } + return null; + }); + return ret; + } + + 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, environment.packageCrawler); + return ret; + } + + public void generateBytecode() throws ClassNotFoundException, IOException { + for(File f : sourceFiles.keySet()) { + HashMap classFiles = new HashMap<>(); + SourceFile sf = sourceFiles.get(f); + List typeinferenceResult = this.typeInference(); + BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult); +// BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult.get(0)); + bytecodeGen.visit(sf); + this.writeClassFile(bytecodeGen.getClassFiles()); + } + } + + private void writeClassFile(HashMap classFiles) throws IOException { + FileOutputStream output; + for(String name : classFiles.keySet()) { + byte[] bytecode = classFiles.get(name); + 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"); + } + } +} diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index 5310d13b..15f2268d 100644 --- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -832,7 +832,7 @@ public class StatementGenerator { }else if(literal.StringLiteral()!=null){ RefType type = new RefType(reg.getName("java.lang.String"),literal.getStart()); return new Literal(type, - literal.StringLiteral().getText(), + literal.StringLiteral().getText().substring(1, literal.StringLiteral().getText().length()-1), literal.getStart()); }else if(literal.NullLiteral() != null){ return new Literal(TypePlaceholder.fresh(literal.getStart()), null, @@ -904,7 +904,7 @@ public class StatementGenerator { funNParams.add(TypePlaceholder.fresh(expression.getStart()))); RefTypeOrTPHOrWildcardOrGeneric lambdaType = TypePlaceholder.fresh(expression.getStart()); //RefType lambdaType = new RefType(reg.getName("Fun"+params.getFormalparalist().size()), - //funNParams, name.getStart()); + //funNParams, name.getStart()); return new LambdaExpression(lambdaType, params, block, expression.getStart()); } } diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java index 1754dde7..371a5d79 100644 --- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java +++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java @@ -22,18 +22,20 @@ import java.util.List; public class TypeGenerator { public static RefTypeOrTPHOrWildcardOrGeneric convert(Java8Parser.UnannClassOrInterfaceTypeContext unannClassOrInterfaceTypeContext, JavaClassRegistry reg, GenericsRegistry generics) { - String name; - if(unannClassOrInterfaceTypeContext.unannInterfaceType_lfno_unannClassOrInterfaceType() != null){ - name = unannClassOrInterfaceTypeContext.unannInterfaceType_lfno_unannClassOrInterfaceType().unannClassType_lfno_unannClassOrInterfaceType().Identifier().getText(); - } Java8Parser.TypeArgumentsContext arguments; if(unannClassOrInterfaceTypeContext.unannClassType_lfno_unannClassOrInterfaceType() != null){ - name = unannClassOrInterfaceTypeContext.unannClassType_lfno_unannClassOrInterfaceType().Identifier().getText(); arguments = unannClassOrInterfaceTypeContext.unannClassType_lfno_unannClassOrInterfaceType().typeArguments(); }else{// if(unannClassOrInterfaceTypeContext.unannInterfaceType_lfno_unannClassOrInterfaceType() != null){ - name = unannClassOrInterfaceTypeContext.unannInterfaceType_lfno_unannClassOrInterfaceType().unannClassType_lfno_unannClassOrInterfaceType().getText(); arguments = unannClassOrInterfaceTypeContext.unannInterfaceType_lfno_unannClassOrInterfaceType().unannClassType_lfno_unannClassOrInterfaceType().typeArguments(); } + /** + * Problem sind hier die verschachtelten Typen mit verschachtelten Typargumenten + * Beispiel: Typ.InnererTyp + */ + String name = unannClassOrInterfaceTypeContext.getText(); + if(name.contains("<")){ + name = name.split("<")[0]; //Der Typ ist alles vor den ersten Argumenten + } return convertTypeName(name, arguments, unannClassOrInterfaceTypeContext.getStart(), reg, generics); } diff --git a/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java b/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java index 74accd30..86f7d5c6 100644 --- a/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java +++ b/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java @@ -114,4 +114,8 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{ public List getSuperInterfaces() { return implementedInterfaces; } + + public String toString() { + return this.name.toString() + this.genericClassParameters.toString(); + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java b/src/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java index c7ac2c30..ab0d7f24 100644 --- a/src/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java +++ b/src/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java @@ -38,8 +38,13 @@ public class GenericDeclarationList extends SyntaxTreeNode implements Iterable PLACEHOLDERS = new ArrayList<>(); public static FiniteClosure generateFC(List fromClasses) throws ClassNotFoundException { /* @@ -49,6 +51,10 @@ public class UnifyTypeFactory { return new UnifyPair(tl, tr, PairOperator.SMALLERDOT); } + public static UnifyPair generateSmallNotEqualDotPair(UnifyType tl, UnifyType tr){ + return new UnifyPair(tl, tr, PairOperator.SMALLERNEQDOT); + } + public static UnifyPair generateEqualDotPair(UnifyType tl, UnifyType tr){ return new UnifyPair(tl, tr, PairOperator.EQUALSDOT); } @@ -113,7 +119,15 @@ public class UnifyTypeFactory { } public static UnifyType convert(TypePlaceholder tph){ - return new PlaceholderType(tph.getName()); + PlaceholderType ntph = new PlaceholderType(tph.getName()); + int in = PLACEHOLDERS.indexOf(ntph); + if (in == -1) { + PLACEHOLDERS.add(ntph); + return ntph; + } + else { + return PLACEHOLDERS.get(in); + } } public static UnifyType convert(GenericRefType t){ @@ -142,6 +156,10 @@ public class UnifyTypeFactory { UnifyPair ret = generateSmallerDotPair(UnifyTypeFactory.convert(p.TA1) , UnifyTypeFactory.convert(p.TA2)); return ret; + }else if(p.GetOperator().equals(PairOperator.SMALLERNEQDOT)) { + UnifyPair ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(p.TA1) + , UnifyTypeFactory.convert(p.TA2)); + return ret; }else if(p.GetOperator().equals(PairOperator.EQUALSDOT)) { UnifyPair ret = generateEqualDotPair(UnifyTypeFactory.convert(p.TA1) , UnifyTypeFactory.convert(p.TA2)); diff --git a/src/de/dhbwstuttgart/typeinference/constraints/Pair.java b/src/de/dhbwstuttgart/typeinference/constraints/Pair.java index ab0cb3ea..98679f7d 100644 --- a/src/de/dhbwstuttgart/typeinference/constraints/Pair.java +++ b/src/de/dhbwstuttgart/typeinference/constraints/Pair.java @@ -11,6 +11,7 @@ public class Pair implements Serializable public final RefTypeOrTPHOrWildcardOrGeneric TA2; private PairOperator eOperator = PairOperator.SMALLER; + public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2 ) { @@ -41,14 +42,16 @@ public class Pair implements Serializable if( TA2 != null ) strElement2 = TA2.toString(); + /* PL ausskommentiert 2018-05-24 if(OperatorEqual()) Operator = "="; if(OperatorSmaller()) Operator = "<."; if(OperatorSmallerExtends()) Operator = " lambdaParams = lambdaExpression.params.getFormalparalist().stream().map((formalParameter -> formalParameter.getType())).collect(Collectors.toList()); - //lambdaParams.add(tphRetType); - lambdaParams.add(0,tphRetType); + lambdaParams.add(tphRetType); + //lambdaParams.add(0,tphRetType); constraintsSet.addUndConstraint( new Pair(lambdaExpression.getType(), new FunN(lambdaParams),PairOperator.EQUALSDOT)); @@ -185,6 +185,12 @@ public class TYPEStmt implements StatementVisitor{ } private final RefType number = new RefType(ASTFactory.createClass(Number.class).getClassName(), new NullToken()); + private final RefType longg = new RefType(ASTFactory.createClass(Long.class).getClassName(), new NullToken()); + private final RefType integer = new RefType(ASTFactory.createClass(Integer.class).getClassName(), new NullToken()); + private final RefType shortt = new RefType(ASTFactory.createClass(Short.class).getClassName(), new NullToken()); + private final RefType bytee = new RefType(ASTFactory.createClass(Byte.class).getClassName(), new NullToken()); + private final RefType floatt = new RefType(ASTFactory.createClass(Float.class).getClassName(), new NullToken()); + private final RefType doublee = new RefType(ASTFactory.createClass(Double.class).getClassName(), new NullToken()); private final RefType string = new RefType(ASTFactory.createClass(String.class).getClassName(), new NullToken()); private final RefType bool = new RefType(ASTFactory.createClass(Boolean.class).getClassName(), new NullToken()); @Override @@ -205,18 +211,47 @@ public class TYPEStmt implements StatementVisitor{ @Override public void visit(BinaryExpr binary) { - + binary.lexpr.accept(this); + binary.rexpr.accept(this); if(binary.operation.equals(BinaryExpr.Operator.DIV) || binary.operation.equals(BinaryExpr.Operator.MUL)|| binary.operation.equals(BinaryExpr.Operator.MOD)|| binary.operation.equals(BinaryExpr.Operator.ADD)){ - Set numericAdditionOrStringConcatenation = new HashSet<>(); - Constraint numeric = new Constraint<>(); + Set> numericAdditionOrStringConcatenation = new HashSet<>(); + //Zuerst der Fall für Numerische AusdrücPairOpnumericeratorke, das sind Mul, Mod und Div immer: //see: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17 //Expression muss zu Numeric Convertierbar sein. also von Numeric erben - numeric.add(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERDOT)); - numeric.add(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERDOT)); + Constraint numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), bytee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), bytee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), integer, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), shortt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), shortt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), integer, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), integer, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), integer, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), integer, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), longg, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), longg, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), longg, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), floatt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), floatt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), floatt, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), doublee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), doublee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), doublee, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); /* In Java passiert bei den binären Operatoren eine sogenannte Type Promotion: https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2 @@ -237,10 +272,54 @@ public class TYPEStmt implements StatementVisitor{ binary.operation.equals(BinaryExpr.Operator.BIGGEREQUAL) || binary.operation.equals(BinaryExpr.Operator.BIGGERTHAN) || binary.operation.equals(BinaryExpr.Operator.LESSTHAN)){ - constraintsSet.addUndConstraint(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERDOT)); - constraintsSet.addUndConstraint(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERDOT)); + /* //eingefuegt PL 2018-05-24 + Set> numericRelationConcatenation = new HashSet<>(); + Constraint numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), bytee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), bytee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT)); + numericRelationConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), shortt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), shortt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT)); + numericRelationConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), integer, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), integer, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT)); + numericRelationConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), longg, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), longg, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT)); + numericRelationConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), floatt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), floatt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT)); + numericRelationConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), doublee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), doublee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT)); + numericRelationConcatenation.add(numeric); + + //***ACHTUNG: Moeglicherweise oder und und-Contraint falsch + constraintsSet.addOderConstraint(numericRelationConcatenation); + //***ACHTUNG: Moeglicherweise oder und und-Contraint falsch + */ + //Testeise eingefuegt PL 2018-05-24 + constraintsSet.addUndConstraint(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERNEQDOT)); + constraintsSet.addUndConstraint(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERNEQDOT)); //Rückgabetyp ist Boolean - constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.SMALLERDOT)); + + //auskommentiert PL 2018-05-24 + //constraintsSet.addUndConstraint(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERDOT)); + //constraintsSet.addUndConstraint(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERDOT)); + //Rückgabetyp ist Boolean + //constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT)); }else{ throw new NotImplementedException(); } diff --git a/src/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java b/src/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java index 1c75ea99..087b8943 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java +++ b/src/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java @@ -94,7 +94,8 @@ public class MartelliMontanariUnify implements IUnify { // SUBST - Rule if(lhsType instanceof PlaceholderType) { mgu.add((PlaceholderType) lhsType, rhsType); - termsList = termsList.stream().map(mgu::apply).collect(Collectors.toCollection(ArrayList::new)); + //PL 2018-04-01 nach checken, ob es richtig ist, dass keine Substitutionen uebergeben werden muessen. + termsList = termsList.stream().map(x -> mgu.apply(x)).collect(Collectors.toCollection(ArrayList::new)); idx = idx+1 == termsList.size() ? 0 : idx+1; continue; } diff --git a/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java b/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java index 8c41660b..b40dee30 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java +++ b/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java @@ -24,13 +24,27 @@ import de.dhbwstuttgart.typeinference.unify.model.Unifier; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; import de.dhbwstuttgart.typeinference.unify.model.UnifyType; import de.dhbwstuttgart.typeinference.unify.model.WildcardType; +import de.dhbwstuttgart.typeinference.unify.distributeVariance; + +import java.io.FileWriter; +import java.io.IOException; /** * Implementation of the type inference rules. * @author Florian Steurer * */ -public class RuleSet implements IRuleSet{ +public class RuleSet implements IRuleSet{ + + FileWriter logFile; + + RuleSet() { + super(); + } + + RuleSet(FileWriter logFile) { + this.logFile = logFile; + } @Override public Optional reduceUp(UnifyPair pair) { @@ -47,7 +61,7 @@ public class RuleSet implements IRuleSet{ return Optional.empty(); // Rule is applicable, unpack the SuperType - return Optional.of(new UnifyPair(lhsType, ((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT)); + return Optional.of(new UnifyPair(lhsType, ((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -65,7 +79,7 @@ public class RuleSet implements IRuleSet{ return Optional.empty(); // Rule is applicable, unpack the ExtendsType - return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), rhsType, PairOperator.SMALLERDOT)); + return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), rhsType, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -83,7 +97,7 @@ public class RuleSet implements IRuleSet{ return Optional.empty(); // Rule is applicable, unpack both sides - return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(),((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT)); + return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(),((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -117,7 +131,7 @@ public class RuleSet implements IRuleSet{ if(x instanceof ExtendsType) xFromFc = new ExtendsType(xFromFc); - UnifyType extYFromFc = fc.grArg(xFromFc).stream().filter(t -> t.getName().equals(extY.getName())).filter(t -> t.getTypeParams().arePlaceholders()).findAny().orElse(null); + UnifyType extYFromFc = fc.grArg(xFromFc, new HashSet<>()).stream().filter(t -> t.getName().equals(extY.getName())).filter(t -> t.getTypeParams().arePlaceholders()).findAny().orElse(null); if(extYFromFc == null || extYFromFc.getTypeParams() != xFromFc.getTypeParams()) return Optional.empty(); @@ -133,7 +147,7 @@ public class RuleSet implements IRuleSet{ Set result = new HashSet<>(); for(int rhsIdx = 0; rhsIdx < extYParams.size(); rhsIdx++) - result.add(new UnifyPair(xParams.get(pi[rhsIdx]), extYParams.get(rhsIdx), PairOperator.SMALLERDOTWC)); + result.add(new UnifyPair(xParams.get(pi[rhsIdx]), extYParams.get(rhsIdx), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); return Optional.of(result); } @@ -169,7 +183,7 @@ public class RuleSet implements IRuleSet{ if(x instanceof SuperType) xFromFc = new SuperType(xFromFc); - UnifyType supYFromFc = fc.grArg(xFromFc).stream().filter(t -> t.getName().equals(supY.getName())).filter(t -> t.getTypeParams().arePlaceholders()).findAny().orElse(null); + UnifyType supYFromFc = fc.grArg(xFromFc, new HashSet<>()).stream().filter(t -> t.getName().equals(supY.getName())).filter(t -> t.getTypeParams().arePlaceholders()).findAny().orElse(null); if(supYFromFc == null || supYFromFc.getTypeParams() != xFromFc.getTypeParams()) return Optional.empty(); @@ -184,7 +198,7 @@ public class RuleSet implements IRuleSet{ return Optional.empty(); for(int rhsIdx = 0; rhsIdx < supYParams.size(); rhsIdx++) - result.add(new UnifyPair(supYParams.get(rhsIdx), xParams.get(pi[rhsIdx]), PairOperator.SMALLERDOTWC)); + result.add(new UnifyPair(supYParams.get(rhsIdx), xParams.get(pi[rhsIdx]), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); return Optional.of(result); } @@ -215,7 +229,7 @@ public class RuleSet implements IRuleSet{ TypeParams rhsTypeParams = rhsType.getTypeParams(); for(int i = 0; i < lhsTypeParams.size(); i++) - result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT)); + result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); return Optional.of(result); } @@ -236,19 +250,53 @@ public class RuleSet implements IRuleSet{ ReferenceType lhsSType = (ReferenceType) c; ReferenceType rhsSType = (ReferenceType) d; + //try { + // logFile.write("PAIR Rules: " + pair + "\n"); + // logFile.flush(); + //} + //catch (IOException e) { } + if(lhsSType.getTypeParams().empty() || lhsSType.getTypeParams().size() != rhsSType.getTypeParams().size()) return Optional.empty(); UnifyType cFromFc = fc.getLeftHandedType(c.getName()).orElse(null); + //2018-02-23: liefert Vector>: Das kann nicht sein. + + //NOCHMAL UEBERPRUEFEN + //PL 18-02-09 Eingfuegt Anfang + //C und D koennen auch gleich sein. + if (c.getName().equals(d.getName())) { + Set result = new HashSet<>(); + TypeParams rhsTypeParams = d.getTypeParams(); + TypeParams lhsTypeParams = c.getTypeParams(); + for(int rhsIdx = 0; rhsIdx < c.getTypeParams().size(); rhsIdx++) + result.add(new UnifyPair(lhsTypeParams.get(rhsIdx), rhsTypeParams.get(rhsIdx), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); + + return Optional.of(result); + } + //PL 18-02-09 Eingfuegt ENDE + + //try { + // logFile.write("cFromFc: " + cFromFc); + // logFile.flush(); + //} + //catch (IOException e) { } if(cFromFc == null || !cFromFc.getTypeParams().arePlaceholders()) return Optional.empty(); UnifyType dFromFc = fc.getAncestors(cFromFc).stream().filter(x -> x.getName().equals(d.getName())).findAny().orElse(null); + //try { + // logFile.write("cFromFc: " + cFromFc); + // logFile.flush(); + //} + //catch (IOException e) { } + if(dFromFc == null || !dFromFc.getTypeParams().arePlaceholders() || dFromFc.getTypeParams().size() != cFromFc.getTypeParams().size()) return Optional.empty(); - + //System.out.println("cFromFc: " + cFromFc); + //System.out.println("dFromFc: " + dFromFc); int[] pi = pi(cFromFc.getTypeParams(), dFromFc.getTypeParams()); if(pi.length == 0) @@ -259,7 +307,7 @@ public class RuleSet implements IRuleSet{ Set result = new HashSet<>(); for(int rhsIdx = 0; rhsIdx < rhsTypeParams.size(); rhsIdx++) - result.add(new UnifyPair(lhsTypeParams.get(pi[rhsIdx]), rhsTypeParams.get(rhsIdx), PairOperator.SMALLERDOTWC)); + result.add(new UnifyPair(lhsTypeParams.get(pi[rhsIdx]), rhsTypeParams.get(rhsIdx), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); return Optional.of(result); } @@ -314,16 +362,31 @@ public class RuleSet implements IRuleSet{ TypeParams rhsTypeParams = rhsSType.getTypeParams(); TypeParams lhsTypeParams = lhsSType.getTypeParams(); for(int i = 0; i < rhsTypeParams.size(); i++) - result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT)); + result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); return Optional.of(result); } @Override public boolean erase1(UnifyPair pair, IFiniteClosure fc) { - if(pair.getPairOp() != PairOperator.SMALLERDOT) + if((pair.getPairOp() != PairOperator.SMALLERDOT) && (pair.getPairOp() != PairOperator.SMALLERNEQDOT)) return false; + if (pair.getPairOp() == PairOperator.SMALLERNEQDOT) { + UnifyType lhs = pair.getLhsType(); + UnifyType rhs = pair.getRhsType(); + if (lhs instanceof WildcardType) { + lhs = ((WildcardType)lhs).getWildcardedType(); + } + if (rhs instanceof WildcardType) { + rhs = ((WildcardType)rhs).getWildcardedType(); + } + + if (lhs.equals(rhs)){ + return false; + } + } + UnifyType lhsType = pair.getLhsType(); if(!(lhsType instanceof ReferenceType) && !(lhsType instanceof PlaceholderType)) return false; @@ -332,7 +395,7 @@ public class RuleSet implements IRuleSet{ if(!(rhsType instanceof ReferenceType) && !(rhsType instanceof PlaceholderType)) return false; - return fc.greater(lhsType).contains(rhsType); + return fc.greater(lhsType, new HashSet<>()).contains(rhsType); } @Override @@ -343,7 +406,7 @@ public class RuleSet implements IRuleSet{ UnifyType lhsType = pair.getLhsType(); UnifyType rhsType = pair.getRhsType(); - return fc.grArg(lhsType).contains(rhsType); + return fc.grArg(lhsType, new HashSet<>()).contains(rhsType); } @Override @@ -365,7 +428,7 @@ public class RuleSet implements IRuleSet{ if(!(pair.getRhsType() instanceof PlaceholderType)) return Optional.empty(); - return Optional.of(new UnifyPair(pair.getRhsType(), pair.getLhsType(), PairOperator.EQUALSDOT)); + return Optional.of(new UnifyPair(pair.getRhsType(), pair.getLhsType(), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -407,11 +470,19 @@ public class RuleSet implements IRuleSet{ TypeParams typeDParams = typeD.getTypeParams(); TypeParams typeDgenParams = typeDgen.getTypeParams(); + //System.out.println("Pair: " +pair); + //System.out.println("typeD: " +typeD); + //System.out.println("typeDParams: " +typeDParams); + //System.out.println("typeDgen: " +typeD); + //System.out.println("typeDgenParams: " +typeDgenParams); Unifier unif = Unifier.identity(); - for(int i = 0; i < typeDParams.size(); i++) + for(int i = 0; i < typeDParams.size(); i++) { + //System.out.println("ADAPT" +typeDgenParams); + if (typeDgenParams.get(i) instanceof PlaceholderType) unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i)); - - return Optional.of(new UnifyPair(unif.apply(newLhs), typeDs, PairOperator.SMALLERDOT)); + else System.out.println("ERROR"); + } + return Optional.of(new UnifyPair(unif.apply(newLhs), typeDs, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -441,7 +512,7 @@ public class RuleSet implements IRuleSet{ if(typeDgen == null) return Optional.empty(); - Set grArg = fc.grArg(typeDgen); + Set grArg = fc.grArg(typeDgen, new HashSet<>()); Optional opt = grArg.stream().filter(x -> x.getName().equals(typeExtDs.getName())).findAny(); @@ -457,7 +528,7 @@ public class RuleSet implements IRuleSet{ for(int i = 1; i < typeDParams.size(); i++) unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i)); - return Optional.of(new UnifyPair(unif.apply(newLhs), typeExtDs, PairOperator.SMALLERDOTWC)); + return Optional.of(new UnifyPair(unif.apply(newLhs), typeExtDs, PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -487,7 +558,7 @@ public class RuleSet implements IRuleSet{ // Use of smArg instead of grArg because // a in grArg(b) => b in smArg(a) - Set smArg = fc.smArg(typeSupDgen); + Set smArg = fc.smArg(typeSupDgen, new HashSet<>()); opt = smArg.stream().filter(x -> x.getName().equals(typeDs.getName())).findAny(); if(!opt.isPresent()) @@ -509,7 +580,7 @@ public class RuleSet implements IRuleSet{ for(int i = 1; i < typeDParams.size(); i++) unif.add((PlaceholderType) typeSupDsgenParams.get(i), typeDParams.get(i)); - return Optional.of(new UnifyPair(unif.apply(newLhs), newRhs, PairOperator.SMALLERDOTWC)); + return Optional.of(new UnifyPair(unif.apply(newLhs), newRhs, PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); } /** @@ -581,8 +652,8 @@ public class RuleSet implements IRuleSet{ && typeMap.get(lhsType) > 1 // The type occurs in more pairs in the set than just the recent pair. && !rhsType.getTypeParams().occurs(lhsType)) { Unifier uni = new Unifier(lhsType, rhsType); - result = result.stream().map(uni::apply).collect(Collectors.toCollection(ArrayList::new)); - result1 = result1.stream().map(uni::apply).collect(Collectors.toCollection(LinkedList::new)); + result = result.stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(ArrayList::new)); + result1 = result1.stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(LinkedList::new)); applied = true; } @@ -602,7 +673,7 @@ public class RuleSet implements IRuleSet{ if(!(lhsType instanceof ExtendsType) || !(rhsType instanceof ExtendsType)) return Optional.empty(); - return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT)); + return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -615,7 +686,7 @@ public class RuleSet implements IRuleSet{ if(!(lhsType instanceof ReferenceType) || !(rhsType instanceof ExtendsType)) return Optional.empty(); - return Optional.of(new UnifyPair(lhsType, ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT)); + return Optional.of(new UnifyPair(lhsType, ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -628,7 +699,7 @@ public class RuleSet implements IRuleSet{ if(!(lhsType instanceof SuperType) || !(rhsType instanceof SuperType)) return Optional.empty(); - return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), ((SuperType) lhsType).getSuperedType(), PairOperator.SMALLERDOT)); + return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), ((SuperType) lhsType).getSuperedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -641,9 +712,11 @@ public class RuleSet implements IRuleSet{ if(!(lhsType instanceof ReferenceType) || !(rhsType instanceof SuperType)) return Optional.empty(); - return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), lhsType, PairOperator.SMALLERDOTWC)); + return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), lhsType, PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); } + /* PL 2018-03-06 auskommentiert sind mutmaßlich falsch + * vgl. JAVA_BSP/Wildcard6.java @Override public Optional reduceWildcardLowUp(UnifyPair pair) { if(pair.getPairOp() != PairOperator.SMALLERDOTWC) @@ -670,6 +743,7 @@ public class RuleSet implements IRuleSet{ return Optional.of(new UnifyPair(((SuperType) lhsType).getSuperedType(), ((ExtendsType) rhsType).getExtendedType(), PairOperator.EQUALSDOT)); } + @Override public Optional reduceWildcardLeft(UnifyPair pair) { if(pair.getPairOp() != PairOperator.SMALLERDOTWC) @@ -686,7 +760,7 @@ public class RuleSet implements IRuleSet{ return Optional.empty(); } - + */ @Override public Optional> reduceFunN(UnifyPair pair) { if((pair.getPairOp() != PairOperator.SMALLERDOT) @@ -709,13 +783,19 @@ public class RuleSet implements IRuleSet{ Set result = new HashSet(); - result.add(new UnifyPair(funNLhsType.getTypeParams().get(0), funNRhsType.getTypeParams().get(0), PairOperator.SMALLERDOT)); - for(int i = 1; i < funNLhsType.getTypeParams().size(); i++) - result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT)); - + result.add(new UnifyPair(funNLhsType.getTypeParams().get(funNLhsType.getTypeParams().size()-1), funNRhsType.getTypeParams().get(funNRhsType.getTypeParams().size()-1), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + for(int i = 0; i < funNLhsType.getTypeParams().size()-1; i++) { + result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + result.stream().forEach(x -> { UnifyType l = x.getLhsType(); + if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); } + UnifyType r = x.getRhsType(); + if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); } + } ); return Optional.of(result); } - + + @Override public Optional> greaterFunN(UnifyPair pair) { if(pair.getPairOp() != PairOperator.SMALLERDOT) @@ -731,15 +811,29 @@ public class RuleSet implements IRuleSet{ Set result = new HashSet(); + Integer variance = ((PlaceholderType)rhsType).getVariance(); + Integer inversVariance = distributeVariance.inverseVariance(variance); + UnifyType[] freshPlaceholders = new UnifyType[funNLhsType.getTypeParams().size()]; - for(int i = 0; i < freshPlaceholders.length; i++) + for(int i = 0; i < freshPlaceholders.length-1; i++) { freshPlaceholders[i] = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)freshPlaceholders[i]).setVariance(inversVariance); + } + freshPlaceholders[freshPlaceholders.length-1] = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)freshPlaceholders[freshPlaceholders.length-1]).setVariance(variance); + result.add(new UnifyPair(funNLhsType.getTypeParams().get(funNLhsType.getTypeParams().size()-1), freshPlaceholders[funNLhsType.getTypeParams().size()-1], PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); - result.add(new UnifyPair(funNLhsType.getTypeParams().get(0), freshPlaceholders[0], PairOperator.SMALLERDOT)); - for(int i = 1; i < funNLhsType.getTypeParams().size(); i++) - result.add(new UnifyPair(freshPlaceholders[i], funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT)); - result.add(new UnifyPair(rhsType, funNLhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT)); + for(int i = 0; i < funNLhsType.getTypeParams().size()-1; i++) { + result.add(new UnifyPair(freshPlaceholders[i], funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + result.add(new UnifyPair(rhsType, funNLhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + + result.stream().forEach(x -> { UnifyType l = x.getLhsType(); + if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); } + UnifyType r = x.getRhsType(); + if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); } + } ); return Optional.of(result); } @@ -758,15 +852,30 @@ public class RuleSet implements IRuleSet{ Set result = new HashSet(); + Integer variance = ((PlaceholderType)lhsType).getVariance(); + Integer inversVariance = distributeVariance.inverseVariance(variance); + UnifyType[] freshPlaceholders = new UnifyType[funNRhsType.getTypeParams().size()]; - for(int i = 0; i < freshPlaceholders.length; i++) + for(int i = 0; i < freshPlaceholders.length-1; i++) { freshPlaceholders[i] = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)freshPlaceholders[i]).setVariance(inversVariance); + } + freshPlaceholders[freshPlaceholders.length-1] = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)freshPlaceholders[freshPlaceholders.length-1]).setVariance(variance); - result.add(new UnifyPair(freshPlaceholders[0], funNRhsType.getTypeParams().get(0), PairOperator.SMALLERDOT)); - for(int i = 1; i < funNRhsType.getTypeParams().size(); i++) - result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), freshPlaceholders[i], PairOperator.SMALLERDOT)); - result.add(new UnifyPair(lhsType, funNRhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT)); + result.add(new UnifyPair(freshPlaceholders[funNRhsType.getTypeParams().size()-1], funNRhsType.getTypeParams().get(funNRhsType.getTypeParams().size()-1), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + for(int i = 0; i < funNRhsType.getTypeParams().size()-1; i++) { + result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), freshPlaceholders[i], PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + + result.add(new UnifyPair(lhsType, funNRhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + + result.stream().forEach(x -> { UnifyType l = x.getLhsType(); + if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); } + UnifyType r = x.getRhsType(); + if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); } + } ); return Optional.of(result); } @@ -780,7 +889,7 @@ public class RuleSet implements IRuleSet{ if(!(lhsType instanceof PlaceholderType) || !(rhsType instanceof ReferenceType)) return Optional.empty(); - return Optional.of(new UnifyPair(lhsType, rhsType, PairOperator.EQUALSDOT)); + return Optional.of(new UnifyPair(lhsType, rhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); } @Override @@ -799,11 +908,11 @@ public class RuleSet implements IRuleSet{ Set result = new HashSet<>(); if(isGen) - result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT)); + result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); else { UnifyType freshTph = PlaceholderType.freshPlaceholder(); - result.add(new UnifyPair(rhsType, new ExtendsType(freshTph), PairOperator.EQUALSDOT)); - result.add(new UnifyPair(extendedType, freshTph, PairOperator.SMALLERDOT)); + result.add(new UnifyPair(rhsType, new ExtendsType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + result.add(new UnifyPair(extendedType, freshTph, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } return Optional.of(result); @@ -825,11 +934,11 @@ public class RuleSet implements IRuleSet{ Set result = new HashSet<>(); if(isGen) - result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT)); + result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); else { UnifyType freshTph = PlaceholderType.freshPlaceholder(); - result.add(new UnifyPair(rhsType, new SuperType(freshTph), PairOperator.EQUALSDOT)); - result.add(new UnifyPair(freshTph, superedType, PairOperator.SMALLERDOT)); + result.add(new UnifyPair(rhsType, new SuperType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + result.add(new UnifyPair(freshTph, superedType, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); } return Optional.of(result); diff --git a/src/de/dhbwstuttgart/typeinference/unify/TypeUnify.java b/src/de/dhbwstuttgart/typeinference/unify/TypeUnify.java index f457fbb8..fa190cb7 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/TypeUnify.java +++ b/src/de/dhbwstuttgart/typeinference/unify/TypeUnify.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.typeinference.unify; +import java.io.FileWriter; import java.util.Set; import java.util.concurrent.ForkJoinPool; @@ -7,16 +8,16 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; public class TypeUnify { - public Set> unify(Set eq, IFiniteClosure fc) { - TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, true); + public Set> unify(Set eq, IFiniteClosure fc, FileWriter logFile, Boolean log) { + TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, true, logFile, log); ForkJoinPool pool = new ForkJoinPool(); pool.invoke(unifyTask); Set> res = unifyTask.join(); return res; } - public Set> unifySequential(Set eq, IFiniteClosure fc) { - TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, false); + public Set> unifySequential(Set eq, IFiniteClosure fc, FileWriter logFile, Boolean log) { + TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, false, logFile, log); Set> res = unifyTask.compute(); return res; } diff --git a/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java b/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java index e51679e2..0545fb95 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java +++ b/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java @@ -3,7 +3,9 @@ package de.dhbwstuttgart.typeinference.unify; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; @@ -11,7 +13,9 @@ import java.util.Map.Entry; import java.util.Optional; import java.util.Set; import java.util.concurrent.RecursiveTask; +import java.util.function.BinaryOperator; import java.util.stream.Collectors; +import java.util.stream.Stream; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet; @@ -25,16 +29,28 @@ import de.dhbwstuttgart.typeinference.unify.model.TypeParams; import de.dhbwstuttgart.typeinference.unify.model.Unifier; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; import de.dhbwstuttgart.typeinference.unify.model.UnifyType; +import de.dhbwstuttgart.typeinference.unify.model.OrderingUnifyPair; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import com.google.common.collect.Ordering; /** * Implementation of the type unification algorithm * @author Florian Steurer */ -public class TypeUnifyTask extends RecursiveTask>> { +public class TypeUnifyTask extends RecursiveTask>> { private static final long serialVersionUID = 1L; private static int i = 0; + private boolean printtag = false; + Boolean log = true; //gibt an ob ein Log-File nach System.getProperty("user.dir")+"/test/logFiles/log" geschrieben werden soll? + + public static final String rootDirectory = System.getProperty("user.dir")+"/test/logFiles/"; + FileWriter logFile; /** * The implementation of setOps that will be used during the unification @@ -49,23 +65,76 @@ public class TypeUnifyTask extends RecursiveTask>> { /** * The implementation of the rules that will be used during the unification. */ - protected IRuleSet rules = new RuleSet(); + protected IRuleSet rules; protected Set eq; protected IFiniteClosure fc; + protected Ordering> oup; + protected boolean parallel; - public TypeUnifyTask(Set eq, IFiniteClosure fc, boolean parallel) { + Integer nOfUnify = 0; + + Integer noUndefPair = 0; + + Integer noAllErasedElements = 0; + + Integer noBacktracking = 0; + + public TypeUnifyTask() { + rules = new RuleSet(); + } + + public TypeUnifyTask(Set eq, IFiniteClosure fc, boolean parallel, FileWriter logFile, Boolean log) { this.eq = eq; this.fc = fc; + this.oup = new OrderingUnifyPair(fc); this.parallel = parallel; + this.logFile = logFile; + this.log = log; + rules = new RuleSet(logFile); } - + + + /** + * Vererbt alle Variancen + * @param eq The set of constraints + */ + /* PL 2018-05- 17 verschoben nach JavaTXCompiler + private void varianceInheritance(Set eq) { + Set usedTPH = new HashSet<>(); + Set phSet = eq.stream().map(x -> { + Set pair = new HashSet<>(); + if (x.getLhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getLhsType()); + if (x.getRhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getRhsType()); + return pair; + }).reduce(new HashSet<>(), (a,b) -> { a.addAll(b); return a;} , (c,d) -> { c.addAll(d); return c;}); + + ArrayList phSetVariance = new ArrayList<>(phSet); + phSetVariance.removeIf(x -> (x.getVariance() == 0)); + while(!phSetVariance.isEmpty()) { + PlaceholderType a = phSetVariance.remove(0); + usedTPH.add(a); + //HashMap ht = new HashMap<>(); + //ht.put(a, a.getVariance()); + Set eq1 = new HashSet<>(eq); + eq1.removeIf(x -> !(x.getLhsType() instanceof PlaceholderType && ((PlaceholderType)x.getLhsType()).equals(a))); + eq1.stream().forEach(x -> { x.getRhsType().accept(new distributeVariance(), a.getVariance());}); + eq1 = new HashSet<>(eq); + eq1.removeIf(x -> !(x.getRhsType() instanceof PlaceholderType && ((PlaceholderType)x.getRhsType()).equals(a))); + eq1.stream().forEach(x -> { x.getLhsType().accept(new distributeVariance(), a.getVariance());}); + phSetVariance = new ArrayList<>(phSet); + phSetVariance.removeIf(x -> (x.getVariance() == 0 || usedTPH.contains(x))); + } +} +*/ @Override protected Set> compute() { - return unify(eq, fc, parallel); + Set> res = unify(eq, fc, parallel); + if (isUndefinedPairSetSet(res)) { return new HashSet<>(); } + else return res; } /** @@ -74,11 +143,38 @@ public class TypeUnifyTask extends RecursiveTask>> { * @param fc The finite closure * @return The set of all principal type unifiers */ - protected Set> unify(Set eq, IFiniteClosure fc, boolean parallel) { + protected Set> unify(Set eq, IFiniteClosure fc, boolean parallel) { + Set aas = eq.stream().filter(x -> x.getLhsType().getName().equals("AA") //&& x.getPairOp().equals(PairOperator.SMALLERDOT) + ).collect(Collectors.toCollection(HashSet::new)); + writeLog(nOfUnify.toString() + " AA: " + aas.toString()); + if (aas.isEmpty()) { + System.out.println(""); + } /* * Step 1: Repeated application of reduce, adapt, erase, swap */ - //System.out.println("Unifikation: " + eq); + nOfUnify++; + writeLog(nOfUnify.toString() + " Unifikation: " + eq.toString()); + //eq = eq.stream().map(x -> {x.setVariance((byte)-1); return x;}).collect(Collectors.toCollection(HashSet::new)); + + /* + * Variancen auf alle Gleichungen vererben + */ + //PL 2018-05-17 nach JavaTXCompiler verschoben + //varianceInheritance(eq); + + /* + * ? extends ? extends Theta rausfiltern + */ + Set doubleExt = eq.stream().filter(x -> (x.wrongWildcard())).map(x -> { x.setUndefinedPair(); return x;}) + .collect(Collectors.toCollection(HashSet::new)); + if (doubleExt.size() > 0) { + Set> ret = new HashSet<>(); + ret.add(doubleExt); + return ret; + } + + Set eq0 = applyTypeUnificationRules(eq, fc); /* @@ -99,7 +195,7 @@ public class TypeUnifyTask extends RecursiveTask>> { // cartesian product of the sets created by pattern matching. List>> topLevelSets = new ArrayList<>(); - System.out.println(eq2s); + //System.out.println(eq2s); if(eq1s.size() != 0) { // Do not add empty sets or the cartesian product will always be empty. Set> wrap = new HashSet<>(); @@ -122,22 +218,34 @@ public class TypeUnifyTask extends RecursiveTask>> { // Sets that originate from pair pattern matching // Sets of the "second level" Set undefinedPairs = new HashSet<>(); + if (printtag) System.out.println("eq2s " + eq2s); + //writeLog("BufferSet: " + bufferSet.toString()+"\n"); Set>>> secondLevelSets = calculatePairSets(eq2s, fc, undefinedPairs); //PL 2017-09-20: Im calculatePairSets wird möglicherweise O .< java.lang.Integer //nicht ausgewertet Faculty Beispiel im 1. Schritt //PL 2017-10-03 geloest, muesste noch mit FCs mit kleineren //Typen getestet werden. + if (printtag) System.out.println("secondLevelSets:" +secondLevelSets); // If pairs occured that did not match one of the cartesian product cases, // those pairs are contradictory and the unification is impossible. - if(!undefinedPairs.isEmpty()) - return new HashSet<>(); + if(!undefinedPairs.isEmpty()) { + noUndefPair++; + for (UnifyPair up : undefinedPairs) { + writeLog(noUndefPair.toString() + " UndefinedPairs; " + up); + writeLog("BasePair; " + up.getBasePair()); + } + Set> error = new HashSet<>(); + undefinedPairs = undefinedPairs.stream().map(x -> { x.setUndefinedPair(); return x;}).collect(Collectors.toCollection(HashSet::new)); + error.add(undefinedPairs); + return error; + } /* Up to here, no cartesian products are calculated. * filters for pairs and sets can be applied here */ - // Sub cartesian products of the second level (pattern matched) sets + // Alternative: Sub cartesian products of the second level (pattern matched) sets // "the big (x)" - for(Set>> secondLevelSet : secondLevelSets) { + /* for(Set>> secondLevelSet : secondLevelSets) { //System.out.println("secondLevelSet "+secondLevelSet.size()); List>> secondLevelSetList = new ArrayList<>(secondLevelSet); Set>> cartResult = setOps.cartesianProduct(secondLevelSetList); @@ -153,62 +261,108 @@ public class TypeUnifyTask extends RecursiveTask>> { flat1.addAll(s1); flat.add(flat1); } - topLevelSets.add(flat); + //topLevelSets.add(flat); } + */ + //Alternative KEIN KARTESISCHES PRODUKT der secondlevel Ebene bilden + for(Set>> secondLevelSet : secondLevelSets) { + for (Set> secondlevelelem : secondLevelSet) { + topLevelSets.add(secondlevelelem); + } + } + //System.out.println(topLevelSets); + //System.out.println(); + + + //Aufruf von computeCartesianRecursive ANFANG + return computeCartesianRecursive(new HashSet<>(), new ArrayList<>(topLevelSets), eq, fc, parallel); + + } + + + Set> unify2(Set> setToFlatten, Set eq, IFiniteClosure fc, boolean parallel) { + //Aufruf von computeCartesianRecursive ENDE + + //keine Ahnung woher das kommt + //Set> setToFlatten = topLevelSets.stream().map(x -> x.iterator().next()).collect(Collectors.toCollection(HashSet::new)); + + //Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG // Cartesian product over all (up to 10) top level sets - Set>> eqPrimeSet = setOps.cartesianProduct(topLevelSets) - .stream().map(x -> new HashSet<>(x)) - .collect(Collectors.toCollection(HashSet::new)); + //Set>> eqPrimeSet = setOps.cartesianProduct(topLevelSets) + // .stream().map(x -> new HashSet<>(x)) + // .collect(Collectors.toCollection(HashSet::new)); + //Muss auskommentiert werden, wenn computeCartesianRecursive ENDE Set> eqPrimePrimeSet = new HashSet<>(); Set forks = new HashSet<>(); - for(Set> setToFlatten : eqPrimeSet) { + + //Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG + //for(Set> setToFlatten : eqPrimeSet) { // Flatten the cartesian product + //Muss auskommentiert werden, wenn computeCartesianRecursive ENDE Set eqPrime = new HashSet<>(); setToFlatten.stream().forEach(x -> eqPrime.addAll(x)); /* * Step 5: Substitution */ - System.out.println("vor Subst: " + eqPrime); + //System.out.println("vor Subst: " + eqPrime); Optional> eqPrimePrime = rules.subst(eqPrime); /* * Step 6 a) Restart (fork) for pairs where subst was applied */ if(parallel) { - if //(eqPrime.equals(eq)) //PL 2017-09-29 auskommentiert und durch - (!eqPrimePrime.isPresent()) //PL 2071-09-29 dies ersetzt - //Begruendung: Wenn in der Substitution keine Veraenderung - //(!eqPrimePrime.isPresent()) erfolgt ist, ist das Ergebnis erzielt. + if (eqPrime.equals(eq) && !eqPrimePrime.isPresent()) //PL 2017-09-29 //(!eqPrimePrime.isPresent()) auskommentiert und durch + //PL 2017-09-29 dies ersetzt //(!eqPrimePrime.isPresent()) + //PL 2018-05-18 beide Bedingungen muessen gelten, da eqPrime Veränderungen in allem ausser subst + //eqPrimePrime Veraenderungen in subst repraesentieren. eqPrimePrimeSet.add(eqPrime); else if(eqPrimePrime.isPresent()) { - System.out.println("nextStep: " + eqPrimePrime.get()); - TypeUnifyTask fork = new TypeUnifyTask(eqPrimePrime.get(), fc, true); + //System.out.println("nextStep: " + eqPrimePrime.get()); + TypeUnifyTask fork = new TypeUnifyTask(eqPrimePrime.get(), fc, true, logFile, log); forks.add(fork); fork.fork(); } else { - System.out.println("nextStep: " + eqPrime); - TypeUnifyTask fork = new TypeUnifyTask(eqPrime, fc, true); + //System.out.println("nextStep: " + eqPrime); + TypeUnifyTask fork = new TypeUnifyTask(eqPrime, fc, true, logFile, log); forks.add(fork); fork.fork(); } } else { // sequentiell (Step 6b is included) - if //(eqPrime.equals(eq)) //PL 2017-09-29 auskommentiert und durch - (!eqPrimePrime.isPresent()) //PL 2071-09-29 dies ersetzt - //Begruendung: Wenn in der Substitution keine Veraenderung - //(!eqPrimePrime.isPresent()) erfolgt ist, ist das Ergebnis erzielt. + if (printtag) System.out.println("nextStep: " + eqPrimePrime); + if (eqPrime.equals(eq) && !eqPrimePrime.isPresent()) { //PL 2017-09-29 //(!eqPrimePrime.isPresent()) auskommentiert und durch + //PL 2017-09-29 dies ersetzt //(!eqPrimePrime.isPresent()) + //PL 2018-05-18 beide Bedingungen muessen gelten, da eqPrime Veränderungen in allem ausser subst + //eqPrimePrime Veraenderungen in subst repraesentieren. + try { + if (isSolvedForm(eqPrime)) { + logFile.write(eqPrime.toString()+"\n"); + logFile.flush(); + } + } + catch (IOException e) { } eqPrimePrimeSet.add(eqPrime); - else if(eqPrimePrime.isPresent()) - eqPrimePrimeSet.addAll(unify(eqPrimePrime.get(), fc, false)); - else - eqPrimePrimeSet.addAll(unify(eqPrime, fc, false)); + } + else if(eqPrimePrime.isPresent()) { + Set> unifyres = unify(eqPrimePrime.get(), fc, false); + + eqPrimePrimeSet.addAll(unifyres); + } + else { + Set> unifyres = unify(eqPrime, fc, false); + + + eqPrimePrimeSet.addAll(unifyres); + } } - } + //Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG + //} + //Muss auskommentiert werden, wenn computeCartesianRecursive ENDE /* * Step 6 b) Build the union over everything. @@ -221,10 +375,236 @@ public class TypeUnifyTask extends RecursiveTask>> { /* * Step 7: Filter empty sets; */ - return eqPrimePrimeSet.stream().filter(x -> isSolvedForm(x)).collect(Collectors.toCollection(HashSet::new)); - + eqPrimePrimeSet = eqPrimePrimeSet.stream().filter(x -> isSolvedForm(x) || this.isUndefinedPairSet(x)).collect(Collectors.toCollection(HashSet::new)); + if (!eqPrimePrimeSet.isEmpty() && !isUndefinedPairSetSet(eqPrimePrimeSet)) + writeLog("Result1 " + eqPrimePrimeSet.toString()); + return eqPrimePrimeSet; } + + + Set> computeCartesianRecursive(Set> fstElems, ArrayList>> topLevelSets, Set eq, IFiniteClosure fc, boolean parallel) { + //ArrayList>> remainingSets = new ArrayList<>(topLevelSets); + fstElems.addAll(topLevelSets.stream() + .filter(x -> x.size()==1) + .map(y -> y.stream().findFirst().get()) + .collect(Collectors.toCollection(HashSet::new))); + ArrayList>> remainingSets = topLevelSets.stream() + .filter(x -> x.size()>1) + .collect(Collectors.toCollection(ArrayList::new)); + if (remainingSets.isEmpty()) {//Alle Elemente sind 1-elementig + Set> result = unify2(fstElems, eq, fc, parallel); + return result; + } + Set> nextSet = remainingSets.remove(0); + writeLog("nextSet: " + nextSet.toString()); + List> nextSetasList =new ArrayList<>(nextSet); + try { + //List> + //nextSetasList = oup.sortedCopy(nextSet);//new ArrayList<>(nextSet); + } + catch (java.lang.IllegalArgumentException e) { + System.out.print(""); + } + Set> result = new HashSet<>(); + int variance = 0; + Optional xi = nextSetasList.stream().map(x -> x.stream().filter(y -> y.getLhsType() instanceof PlaceholderType) + .filter(z -> ((PlaceholderType)z.getLhsType()).getVariance() != 0) + .map(c -> ((PlaceholderType)c.getLhsType()).getVariance()) + .reduce((a,b)-> {if (a==b) return a; else return 0; })) + .filter(d -> d.isPresent()) + .map(e -> e.get()) + .findAny(); + if (xi.isPresent()) { + variance = xi.get(); + } + //if (variance == 1 && nextSetasList.size() > 1) { + // List> al = new ArrayList<>(nextSetasList.size()); + // for (int ii = 0; ii < nextSetasList.size();ii++) { + // al.add(0,nextSetasList.get(ii)); + // } + // nextSetasList = al; + //} + //Set a = nextSetasListIt.next(); + /*if (nextSetasList.size()>1) {zu loeschen + if (nextSetasList.iterator().next().iterator().next().getLhsType().getName().equals("D")) + System.out.print(""); + if (variance == 1) { + a_next = oup.max(nextSetasList.iterator()); + } + else if (variance == -1) { + a_next = oup.min(nextSetasList.iterator()); + } + else if (variance == 0) { + a_next = nextSetasList.iterator().next(); + } + } + else { + a_next = nextSetasList.iterator().next(); + } + */ + if (!nextSetasList.iterator().hasNext()) + System.out.print(""); + if (nextSetasList.iterator().next().stream().filter(x -> x.getLhsType().getName().equals("D")).findFirst().isPresent() && nextSetasList.size()>1) + System.out.print(""); + while (nextSetasList.size() > 0) { //(nextSetasList.size() != 0) { + Set a = null; + if (variance == 1) { + a = oup.max(nextSetasList.iterator()); + nextSetasList.remove(a); + } + else if (variance == -1) { + a = oup.min(nextSetasList.iterator()); + nextSetasList.remove(a); + } + else if (variance == 0) { + a = nextSetasList.remove(0); + } + //writeLog("nextSet: " + nextSetasList.toString()+ "\n"); + //nextSetasList.remove(a); + /* zu loeschen + if (nextSetasList.size() > 0) { + if (nextSetasList.size()>1) { + if (variance == 1) { + a_next = oup.max(nextSetasList.iterator()); + } + else if (variance == -1) { + a_next = oup.min(nextSetasList.iterator()); + } + else { + a_next = nextSetasList.iterator().next(); + } + } + else { + a_next = nextSetasList.iterator().next(); + } + } + */ + //PL 2018-03-01 + //TODO: 1. Maximum und Minimum unterscheiden + //TODO: 2. compare noch für alle Elmemente die nicht X =. ty sind erweitern + //for(Set a : newSet) { + i++; + Set> elems = new HashSet>(fstElems); + elems.add(a); + //if (remainingSets.isEmpty()) {//muss immer gegeben sein, weil nur 1 Element der topLevelSets mehr als ein Elemet enthaelt + Set> res = unify2(elems, eq, fc, parallel); + if (!isUndefinedPairSetSet(res) && isUndefinedPairSetSet(result)) { + //wenn korrektes Ergebnis gefunden alle Fehlerfaelle loeschen + result = res; + } + else { + if ((isUndefinedPairSetSet(res) && isUndefinedPairSetSet(result)) + || (!isUndefinedPairSetSet(res) && !isUndefinedPairSetSet(result)) + || result.isEmpty()) { + //alle Fehlerfaelle und alle korrekten Ergebnis jeweils adden + result.addAll(res); + } + //else { + //wenn Korrekte Ergebnisse da und Feherfälle dazukommen Fehlerfälle ignorieren + // if (isUndefinedPairSetSet(res) && !isUndefinedPairSetSet(result)) { + // result = result; + // } + //} + } + + //} + //else {//duerfte gar nicht mehr vorkommen PL 2018-04-03 + //result.addAll(computeCartesianRecursive(elems, remainingSets, eq, fc, parallel)); + //} + + if (!result.isEmpty() && !isUndefinedPairSetSet(res)) { + if (nextSetasList.iterator().hasNext() && nextSetasList.iterator().next().stream().filter(x -> x.getLhsType().getName().equals("D")).findFirst().isPresent() && nextSetasList.size()>1) + System.out.print(""); + Iterator> nextSetasListIt = new ArrayList>(nextSetasList).iterator(); + if (variance == 1) { + System.out.println(""); + while (nextSetasListIt.hasNext()) { + Set a_next = nextSetasListIt.next(); + if (a.equals(a_next) || + (oup.compare(a, a_next) == 1)) { + nextSetasList.remove(a_next); + } + } + } + else { if (variance == -1) { + System.out.println(""); + while (nextSetasListIt.hasNext()) { + Set a_next = nextSetasListIt.next(); + if (a.equals(a_next) || + (oup.compare(a, a_next) == -1)) { + nextSetasList.remove(0); + } + } + } + else if (variance == 0) { + break; + } + } + } + if (isUndefinedPairSetSet(res)) { + Set abhSubst = res.stream() + .map(b -> + b.stream() + .map(x -> x.getAllSubstitutions()) + .reduce((y,z) -> { y.addAll(z); return y;}).get()) + .reduce((y,z) -> { y.addAll(z); return y;}).get(); + Set b = a;//effective final a + Set durchschnitt = abhSubst.stream() + .filter(x -> b.contains(x)) + //.filter(y -> abhSubst.contains(y)) + .collect(Collectors.toCollection(HashSet::new)); + Set vars = durchschnitt.stream().map(x -> (PlaceholderType)x.getLhsType()).collect(Collectors.toCollection(HashSet::new)); + int len = nextSetasList.size(); + nextSetasList = nextSetasList.stream().filter(x -> { + //Boolean ret = false; + //for (PlaceholderType var : vars) { + // ret = ret || x.stream().map(b -> b.getLhsType().equals(var)).reduce((c,d) -> c || d).get(); + //} + return (!x.containsAll(durchschnitt)); + }).collect(Collectors.toCollection(ArrayList::new)); + writeLog("abhSubst: " + abhSubst.toString()); + writeLog("a: " + a.toString()); + writeLog("Durchschnitt: " + durchschnitt.toString()); + writeLog("nextSet: " + nextSet.toString()); + writeLog("nextSetasList: " + nextSetasList.toString()); + writeLog("Number erased Elements (undef): " + (len - nextSetasList.size())); + noAllErasedElements = noAllErasedElements + (len - nextSetasList.size()); + writeLog("Number erased Elements (undef): " + noAllErasedElements.toString()); + noBacktracking++; + writeLog("Number of Backtracking: " + noBacktracking); + System.out.println(""); + } + //if (nextSetasList.size() == 0 && isUndefinedPairSetSet(result) && nextSet.size() > 1) { + // return result; + //} + //else { + // result.removeIf(y -> isUndefinedPairSet(y)); + //} + //else result.stream().filter(y -> !isUndefinedPairSet(y)); + } + return result; + } + + + protected boolean isUndefinedPairSet(Set s) { + if (s.size() >= 1 ) { + Boolean ret = s.stream().map(x -> x.isUndefinedPair()).reduce(true, (x,y)-> (x && y)); + return ret; + } + else { + return false; + } + } + + protected boolean isUndefinedPairSetSet(Set> s) { + if (s.size() >= 1) { + Boolean ret = s.stream(). map(x -> isUndefinedPairSet(x)).reduce(true, (x,y)-> (x && y)); + return ret; + } + return false; + + } /** * Checks whether a set of pairs is in solved form. * @param eqPrimePrime The set of pair @@ -250,7 +630,7 @@ public class TypeUnifyTask extends RecursiveTask>> { * This is step one of the unification algorithm. * @return The set of pairs that results from repeated application of the inference rules. */ - protected Set applyTypeUnificationRules(Set eq, IFiniteClosure fc) { + public Set applyTypeUnificationRules(Set eq, IFiniteClosure fc) { /* * Rule Application Strategy: @@ -287,9 +667,10 @@ public class TypeUnifyTask extends RecursiveTask>> { opt = opt.isPresent() ? opt : rules.reduceWildcardLowRight(pair); opt = opt.isPresent() ? opt : rules.reduceWildcardUp(pair); opt = opt.isPresent() ? opt : rules.reduceWildcardUpRight(pair); - opt = opt.isPresent() ? opt : rules.reduceWildcardLowUp(pair); - opt = opt.isPresent() ? opt : rules.reduceWildcardUpLow(pair); - opt = opt.isPresent() ? opt : rules.reduceWildcardLeft(pair); + //PL 2018-03-06 auskommentiert muesste falsch sein vgl. JAVA_BSP/Wildcard6.java + //opt = opt.isPresent() ? opt : rules.reduceWildcardLowUp(pair); + //opt = opt.isPresent() ? opt : rules.reduceWildcardUpLow(pair); + //opt = opt.isPresent() ? opt : rules.reduceWildcardLeft(pair); // Reduce TPH opt = opt.isPresent() ? opt : rules.reduceTph(pair); @@ -301,6 +682,12 @@ public class TypeUnifyTask extends RecursiveTask>> { } // Reduce1, Reduce2, ReduceExt, ReduceSup, ReduceEq + //try { + // logFile.write("PAIR1 " + pair + "\n"); + // logFile.flush(); + //} + //catch (IOException e) { } + Optional> optSet = rules.reduce1(pair, fc); optSet = optSet.isPresent() ? optSet : rules.reduce2(pair); optSet = optSet.isPresent() ? optSet : rules.reduceExt(pair, fc); @@ -324,6 +711,11 @@ public class TypeUnifyTask extends RecursiveTask>> { } // Adapt, AdaptExt, AdaptSup + //try { + // logFile.write("PAIR2 " + pair + "\n"); + // logFile.flush(); + //} + //catch (IOException e) { } opt = rules.adapt(pair, fc); opt = opt.isPresent() ? opt : rules.adaptExt(pair, fc); opt = opt.isPresent() ? opt : rules.adaptSup(pair, fc); @@ -385,26 +777,88 @@ public class TypeUnifyTask extends RecursiveTask>> { // Init all 8 cases for(int i = 0; i < 8; i++) result.add(new HashSet<>()); - - for(UnifyPair pair : eq2s) { + ArrayList eq2sprime = new ArrayList<>(eq2s); + Iterator eq2sprimeit = eq2sprime.iterator(); + ArrayList eq2sAsList = new ArrayList<>(); + while(eq2sprimeit.hasNext()) {// alle mit Variance != 0 nach vorne schieben + UnifyPair up = eq2sprimeit.next(); + if ((up.getLhsType() instanceof PlaceholderType && ((PlaceholderType)up.getLhsType()).getVariance() != 0) + || (up.getRhsType() instanceof PlaceholderType && ((PlaceholderType)up.getRhsType()).getVariance() != 0)) { + eq2sAsList.add(up); + eq2s.remove(up); + } + } + eq2sAsList.addAll(eq2s); + Boolean first = true; + for(UnifyPair pair : eq2sAsList) { PairOperator pairOp = pair.getPairOp(); UnifyType lhsType = pair.getLhsType(); UnifyType rhsType = pair.getRhsType(); // Case 1: (a <. Theta') - if(pairOp == PairOperator.SMALLERDOT && lhsType instanceof PlaceholderType) { - System.out.println(pair); - Set> x1 = unifyCase1((PlaceholderType) pair.getLhsType(), pair.getRhsType(), fc); - System.out.println(x1); - result.get(0).add(x1); + if (((pairOp == PairOperator.SMALLERDOT) || (pairOp == PairOperator.SMALLERNEQDOT)) && lhsType instanceof PlaceholderType) { + //System.out.println(pair); + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase1(pair, fc); + if (pairOp == PairOperator.SMALLERNEQDOT) { + Set remElem = new HashSet<>(); + remElem.add(new UnifyPair(pair.getLhsType(), pair.getRhsType(), PairOperator.EQUALSDOT)); + x1.remove(remElem); + remElem = new HashSet<>(); + remElem.add(new UnifyPair(pair.getLhsType(), new ExtendsType(pair.getRhsType()), PairOperator.EQUALSDOT)); + x1.remove(remElem); + remElem = new HashSet<>(); + remElem.add(new UnifyPair(pair.getLhsType(), new SuperType(pair.getRhsType()), PairOperator.EQUALSDOT)); + x1.remove(remElem); + } + //System.out.println(x1); + result.get(0).add(x1); + if (x1.isEmpty()) { + undefined.add(pair); //Theta ist nicht im FC => Abbruch + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(0).add(s2); + } + } // Case 2: (a <.? ? ext Theta') else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof ExtendsType) - result.get(1).add(unifyCase2((PlaceholderType) pair.getLhsType(), (ExtendsType) pair.getRhsType(), fc)); + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase2(pair, fc); + result.get(1).add(x1); + if (x1.isEmpty()) { + undefined.add(pair); //Theta ist nicht im FC + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(1).add(s2); + } // Case 3: (a <.? ? sup Theta') else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof SuperType) - result.get(2).add(unifyCase3((PlaceholderType) lhsType, (SuperType) rhsType, fc)); + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase3(pair, fc); + result.get(2).add(x1); + if (x1.isEmpty()) { + undefined.add(pair); //Theta ist nicht im FC + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(2).add(s2); + } // Case 4 was replaced by an inference rule // Case 4: (a <.? Theta') @@ -412,8 +866,21 @@ public class TypeUnifyTask extends RecursiveTask>> { // result.get(3).add(unifyCase4((PlaceholderType) lhsType, rhsType, fc)); // Case 5: (Theta <. a) - else if(pairOp == PairOperator.SMALLERDOT && rhsType instanceof PlaceholderType) - result.get(4).add(unifyCase5(lhsType, (PlaceholderType) rhsType, fc)); + else if ((pairOp == PairOperator.SMALLERDOT) && rhsType instanceof PlaceholderType) + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase5(pair, fc); + result.get(4).add(x1); + if (x1.isEmpty()) { + undefined.add(pair); //Theta ist nicht im FC + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(4).add(s2); + } // Case 6 was replaced by an inference rule. // Case 6: (? ext Theta <.? a) @@ -427,7 +894,20 @@ public class TypeUnifyTask extends RecursiveTask>> { // Case 8: (Theta <.? a) else if(pairOp == PairOperator.SMALLERDOTWC && rhsType instanceof PlaceholderType) - result.get(7).add(unifyCase8(lhsType, (PlaceholderType) rhsType, fc)); + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase8(pair, fc); + result.get(7).add(x1); + if (x1.isEmpty()) { + undefined.add(pair); //Theta ist nicht im FC + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(7).add(s2); + } // Case unknown: If a pair fits no other case, then the type unification has failed. // Through application of the rules, every pair should have one of the above forms. // Pairs that do not have one of the aboves form are contradictory. @@ -436,6 +916,7 @@ public class TypeUnifyTask extends RecursiveTask>> { undefined.add(pair); break; } + first = false; } // Filter empty sets or sets that only contain an empty set. @@ -443,10 +924,15 @@ public class TypeUnifyTask extends RecursiveTask>> { .filter(x -> x.size() > 0).collect(Collectors.toCollection(HashSet::new)); } + //TODO: Wenn Theta' nicht im FC muss ein Fehler produziert werden PL 18-04-20 /** * Cartesian product Case 1: (a <. Theta') */ - protected Set> unifyCase1(PlaceholderType a, UnifyType thetaPrime, IFiniteClosure fc) { + protected Set> unifyCase1(UnifyPair pair, IFiniteClosure fc) { + PlaceholderType a = (PlaceholderType)pair.getLhsType(); + UnifyType thetaPrime = pair.getRhsType(); + byte variance = pair.getVariance(); + Set> result = new HashSet<>(); boolean allGen = thetaPrime.getTypeParams().size() > 0; @@ -458,13 +944,25 @@ public class TypeUnifyTask extends RecursiveTask>> { Set cs = fc.getAllTypesByName(thetaPrime.getName());//cs= [java.util.Vector, java.util.Vector>, ????java.util.Vector???] + + //PL 18-02-06 entfernt, kommt durch unify wieder rein //cs.add(thetaPrime); //PL 18-02-06 entfernt - for(UnifyType c : cs) { + //cs muessen fresh Typvars gesetzt werden PL 2018-03-18 + Set csPHRenamed = cs.stream().map(x -> { + BinaryOperator> combiner = (aa,b) -> { aa.putAll(b); return aa;}; + HashMap hm = x.getInvolvedPlaceholderTypes().stream() + .reduce(new HashMap(), + (aa, b)-> { aa.put(b,PlaceholderType.freshPlaceholder()); return aa; }, combiner); + return x.accept(new freshPlaceholder(), hm); + }).collect(Collectors.toCollection(HashSet::new)); + + + for(UnifyType c : csPHRenamed) { //PL 18-02-05 getChildren durch smaller ersetzt in getChildren werden die Varianlen nicht ersetzt. - Set thetaQs = fc.smaller(c).stream().collect(Collectors.toCollection(HashSet::new)); + Set thetaQs = fc.smaller(c, new HashSet<>()).stream().collect(Collectors.toCollection(HashSet::new)); //Set thetaQs = fc.getChildren(c).stream().collect(Collectors.toCollection(HashSet::new)); //thetaQs.add(thetaPrime); //PL 18-02-05 wieder geloescht //PL 2017-10-03: War auskommentiert habe ich wieder einkommentiert, @@ -482,31 +980,43 @@ public class TypeUnifyTask extends RecursiveTask>> { ArrayList> candidateParams = new ArrayList<>(); for(UnifyType param : cParams) - candidateParams.add(fc.grArg(param)); + candidateParams.add(fc.grArg(param, new HashSet<>())); for(TypeParams tp : permuteParams(candidateParams)) thetaQPrimes.add(c.setTypeParams(tp)); } for(UnifyType tqp : thetaQPrimes) { - //System.out.println(tqp.toString()); - //i++; - //System.out.println(i); - //if (i == 62) - // System.out.println(tqp.toString()); Optional opt = stdUnify.unify(tqp, thetaPrime); - if (!opt.isPresent()) + if (!opt.isPresent()) { continue; - + } + Unifier unifier = opt.get(); unifier.swapPlaceholderSubstitutions(thetaPrime.getTypeParams()); Set substitutionSet = new HashSet<>(); - for (Entry sigma : unifier) - substitutionSet.add(new UnifyPair(sigma.getKey(), sigma.getValue(), PairOperator.EQUALSDOT)); - + for (Entry sigma : unifier) { + substitutionSet.add(new UnifyPair(sigma.getKey(), sigma.getValue(), PairOperator.EQUALSDOT, + //TODO: nochmals ueberlegen ob hier pair.getSubstitution() korrekt ist, oder ob leere Menge hin müsste + //alle folgenden New UnifyPair ebenfalls ueberpruefen PL 2018-04-19 + pair.getSubstitution(), pair)); + } //List freshTphs = new ArrayList<>(); PL 18-02-06 in die For-Schleife verschoben for (UnifyType tq : thetaQs) { - Set smaller = fc.smaller(unifier.apply(tq)); + Set smaller = fc.smaller(unifier.apply(tq), new HashSet<>()); + //eingefuegt PL 2018-03-29 Anfang ? ext. theta hinzufuegen + if (a.isWildcardable()) { + Set smaller_ext = smaller.stream().filter(x -> !(x instanceof ExtendsType) && !(x instanceof SuperType)) + .map(x -> { + //BinaryOperator> combiner = (aa,b) -> { aa.putAll(b); return aa;}; //Variablenumbenennung rausgenommen + //HashMap hm = x.getInvolvedPlaceholderTypes().stream() //Variablen muessen wahrscheinlich erhalten bleiben + // .reduce(new HashMap(), + // (aa, b)-> { aa.put(b,PlaceholderType.freshPlaceholder()); return aa; }, combiner); + return new ExtendsType (x);})//.accept(new freshPlaceholder(), hm));} + .collect(Collectors.toCollection(HashSet::new)); + smaller.addAll(smaller_ext); + } + //eingefuegt PL 2018-03-29 Ende ? ext. theta hinzufuegen for(UnifyType theta : smaller) { List freshTphs = new ArrayList<>(); Set resultPrime = new HashSet<>(); @@ -514,15 +1024,27 @@ public class TypeUnifyTask extends RecursiveTask>> { for(int i = 0; !allGen && i < theta.getTypeParams().size(); i++) { if(freshTphs.size()-1 < i) freshTphs.add(PlaceholderType.freshPlaceholder()); - resultPrime.add(new UnifyPair(freshTphs.get(i), theta.getTypeParams().get(i), PairOperator.SMALLERDOTWC)); + resultPrime.add(new UnifyPair(freshTphs.get(i), theta.getTypeParams().get(i), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair)); } - if(allGen) - resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT)); - else - resultPrime.add(new UnifyPair(a, theta.setTypeParams(new TypeParams(freshTphs.toArray(new UnifyType[0]))), PairOperator.EQUALSDOT)); + if(allGen) { + UnifyPair up = new UnifyPair(a, theta, PairOperator.EQUALSDOT, pair.getSubstitution(), pair); + Iterator upit = up.getRhsType().getTypeParams().iterator(); + while (upit.hasNext()) ((PlaceholderType)upit.next()).setVariance(a.getVariance()); + resultPrime.add(up); + } + else { + UnifyPair up = new UnifyPair(a, theta.setTypeParams(new TypeParams(freshTphs.toArray(new UnifyType[0]))), PairOperator.EQUALSDOT, pair.getSubstitution(), pair); + Iterator upit = up.getRhsType().getTypeParams().iterator(); + while (upit.hasNext()) ((PlaceholderType)upit.next()).setVariance(a.getVariance()); + resultPrime.add(up); + } resultPrime.addAll(substitutionSet); + //writeLog("Substitution: " + substitutionSet.toString()); + resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new)); result.add(resultPrime); + //writeLog("Result: " + resultPrime.toString()); + //writeLog("MAX: " + oup.max(resultPrime.iterator()).toString()); } } @@ -535,40 +1057,53 @@ public class TypeUnifyTask extends RecursiveTask>> { /** * Cartesian Product Case 2: (a <.? ? ext Theta') */ - private Set> unifyCase2(PlaceholderType a, ExtendsType extThetaPrime, IFiniteClosure fc) { + private Set> unifyCase2(UnifyPair pair, IFiniteClosure fc) { + PlaceholderType a = (PlaceholderType) pair.getLhsType(); + ExtendsType extThetaPrime = (ExtendsType) pair.getRhsType(); + byte variance = pair.getVariance(); Set> result = new HashSet<>(); UnifyType aPrime = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)aPrime).setVariance(((PlaceholderType)a).getVariance()); UnifyType extAPrime = new ExtendsType(aPrime); UnifyType thetaPrime = extThetaPrime.getExtendedType(); Set resultPrime = new HashSet<>(); - resultPrime.add(new UnifyPair(a, thetaPrime, PairOperator.SMALLERDOT)); + resultPrime.add(new UnifyPair(a, thetaPrime, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); result.add(resultPrime); resultPrime = new HashSet<>(); - resultPrime.add(new UnifyPair(a, extAPrime, PairOperator.EQUALSDOT)); - resultPrime.add(new UnifyPair(aPrime, thetaPrime, PairOperator.SMALLERDOT)); + resultPrime.add(new UnifyPair(a, extAPrime, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(aPrime, thetaPrime, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); + resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new)); result.add(resultPrime); + //writeLog("Result: " + resultPrime.toString()); return result; } /** * Cartesian Product Case 3: (a <.? ? sup Theta') */ - private Set> unifyCase3(PlaceholderType a, SuperType subThetaPrime, IFiniteClosure fc) { + private Set> unifyCase3(UnifyPair pair, IFiniteClosure fc) { + PlaceholderType a = (PlaceholderType) pair.getLhsType(); + SuperType subThetaPrime = (SuperType) pair.getRhsType(); + byte variance = pair.getVariance(); Set> result = new HashSet<>(); UnifyType aPrime = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)aPrime).setVariance(((PlaceholderType)a).getVariance()); UnifyType supAPrime = new SuperType(aPrime); UnifyType thetaPrime = subThetaPrime.getSuperedType(); Set resultPrime = new HashSet<>(); - resultPrime.add(new UnifyPair(thetaPrime, a, PairOperator.SMALLERDOT)); + resultPrime.add(new UnifyPair(thetaPrime, a, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); result.add(resultPrime); + //writeLog(resultPrime.toString()); resultPrime = new HashSet<>(); - resultPrime.add(new UnifyPair(a, supAPrime, PairOperator.EQUALSDOT)); - resultPrime.add(new UnifyPair(thetaPrime, aPrime, PairOperator.SMALLERDOT)); + resultPrime.add(new UnifyPair(a, supAPrime, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(thetaPrime, aPrime, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); + resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new)); result.add(resultPrime); + //writeLog(resultPrime.toString()); return result; } @@ -576,7 +1111,10 @@ public class TypeUnifyTask extends RecursiveTask>> { /** * Cartesian Product Case 5: (Theta <. a) */ - private Set> unifyCase5(UnifyType theta, PlaceholderType a, IFiniteClosure fc) { + private Set> unifyCase5(UnifyPair pair, IFiniteClosure fc) { + UnifyType theta = pair.getLhsType(); + PlaceholderType a = (PlaceholderType) pair.getRhsType(); + byte variance = pair.getVariance(); Set> result = new HashSet<>(); boolean allGen = theta.getTypeParams().size() > 0; @@ -586,20 +1124,23 @@ public class TypeUnifyTask extends RecursiveTask>> { break; } - for(UnifyType thetaS : fc.greater(theta)) { + for(UnifyType thetaS : fc.greater(theta, new HashSet<>())) { Set resultPrime = new HashSet<>(); UnifyType[] freshTphs = new UnifyType[thetaS.getTypeParams().size()]; for(int i = 0; !allGen && i < freshTphs.length; i++) { freshTphs[i] = PlaceholderType.freshPlaceholder(); - resultPrime.add(new UnifyPair(thetaS.getTypeParams().get(i), freshTphs[i], PairOperator.SMALLERDOTWC)); + ((PlaceholderType)freshTphs[i]).setVariance(((PlaceholderType)a).getVariance()); + resultPrime.add(new UnifyPair(thetaS.getTypeParams().get(i), freshTphs[i], PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair)); } if(allGen) - resultPrime.add(new UnifyPair(a, thetaS, PairOperator.EQUALSDOT)); + resultPrime.add(new UnifyPair(a, thetaS, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); else - resultPrime.add(new UnifyPair(a, thetaS.setTypeParams(new TypeParams(freshTphs)), PairOperator.EQUALSDOT)); + resultPrime.add(new UnifyPair(a, thetaS.setTypeParams(new TypeParams(freshTphs)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new)); result.add(resultPrime); + //writeLog(resultPrime.toString()); } return result; @@ -608,23 +1149,32 @@ public class TypeUnifyTask extends RecursiveTask>> { /** * Cartesian Product Case 8: (Theta <.? a) */ - private Set> unifyCase8(UnifyType theta, PlaceholderType a, IFiniteClosure fc) { + private Set> unifyCase8(UnifyPair pair, IFiniteClosure fc) { + UnifyType theta = pair.getLhsType(); + PlaceholderType a = (PlaceholderType) pair.getRhsType(); + byte variance = pair.getVariance(); Set> result = new HashSet<>(); //for(UnifyType thetaS : fc.grArg(theta)) { Set resultPrime = new HashSet<>(); - resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT)); + resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); result.add(resultPrime); + //writeLog(resultPrime.toString()); UnifyType freshTph = PlaceholderType.freshPlaceholder(); + + ((PlaceholderType)freshTph).setVariance(a.getVariance()); resultPrime = new HashSet<>(); - resultPrime.add(new UnifyPair(a, new ExtendsType(freshTph), PairOperator.EQUALSDOT)); - resultPrime.add(new UnifyPair(theta, freshTph, PairOperator.SMALLERDOT)); + resultPrime.add(new UnifyPair(a, new ExtendsType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(theta, freshTph, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); result.add(resultPrime); + //writeLog(resultPrime.toString()); resultPrime = new HashSet<>(); - resultPrime.add(new UnifyPair(a, new SuperType(freshTph), PairOperator.EQUALSDOT)); - resultPrime.add(new UnifyPair(freshTph, theta, PairOperator.SMALLERDOT)); + resultPrime.add(new UnifyPair(a, new SuperType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(freshTph, theta, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); + resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new)); result.add(resultPrime); + //writeLog(resultPrime.toString()); //} return result; @@ -662,4 +1212,15 @@ public class TypeUnifyTask extends RecursiveTask>> { permuteParams(candidates, idx+1, result, current); } } + + void writeLog(String str) { + if (log) { + try { + logFile.write(str+"\n"); + logFile.flush(); + + } + catch (IOException e) { } + } + } } diff --git a/src/de/dhbwstuttgart/typeinference/unify/distributeVariance.java b/src/de/dhbwstuttgart/typeinference/unify/distributeVariance.java new file mode 100644 index 00000000..1779c941 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/distributeVariance.java @@ -0,0 +1,54 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.TypeParams; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; + +public class distributeVariance extends visitUnifyTypeVisitor { + + public static int inverseVariance(int variance) { + Integer ret = 0; + if (variance == 1) { + ret = -1; + } + if (variance == -1) { + ret = 1; + } + return ret; + } + + + @Override + public PlaceholderType visit(PlaceholderType phty, Integer ht) { + if (ht != 0) { + if (phty.getVariance() == 0) { + phty.setVariance(ht); + } + //PL 2018-05-17 urspruengliche Variance nicht veraendern + //else if (phty.getVariance() != ht) { + // phty.setVariance(0); + //} + } + return phty; + } + + public FunNType visit(FunNType funnty, Integer ht) { + List param = new ArrayList<>(funnty.getTypeParams().get().length); + param.addAll(Arrays.asList(funnty.getTypeParams().get())); + UnifyType resultType = param.remove(param.size()-1); + Integer htInverse = inverseVariance(ht); + param = param.stream() + .map(x -> x.accept(this, htInverse)) + .collect(Collectors.toCollection(ArrayList::new)); + param.add(resultType.accept(this, ht)); + return FunNType.getFunNType(new TypeParams(param)); + } + + +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/freshPlaceholder.java b/src/de/dhbwstuttgart/typeinference/unify/freshPlaceholder.java new file mode 100644 index 00000000..69870bd5 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/freshPlaceholder.java @@ -0,0 +1,15 @@ +package de.dhbwstuttgart.typeinference.unify; + + +import java.util.HashMap; + +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; + + +public class freshPlaceholder extends visitUnifyTypeVisitor> { + + @Override + public PlaceholderType visit(PlaceholderType phty, HashMap ht) { + return ht.get(phty); + } +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java index dcb6c4d1..3e20f433 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java +++ b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java @@ -5,6 +5,7 @@ import java.util.Set; import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; import de.dhbwstuttgart.typeinference.unify.model.FunNType; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; import de.dhbwstuttgart.typeinference.unify.model.SuperType; @@ -20,45 +21,47 @@ public interface IFiniteClosure { * Returns all types of the finite closure that are subtypes of the argument. * @return The set of subtypes of the argument. */ - public Set smaller(UnifyType type); + public Set smaller(UnifyType type, Set fBounded); /** * Returns all types of the finite closure that are supertypes of the argument. * @return The set of supertypes of the argument. */ - public Set greater(UnifyType type); + public Set greater(UnifyType type, Set fBounded); /** * Wo passt Type rein? * @param type * @return */ - public Set grArg(UnifyType type); + public Set grArg(UnifyType type, Set fBounded); /** * Was passt in Type rein? * @param type * @return */ - public Set smArg(UnifyType type); + public Set smArg(UnifyType type, Set fBounded); - public Set grArg(ReferenceType type); - public Set smArg(ReferenceType type); + public Set grArg(ReferenceType type, Set fBounded); + public Set smArg(ReferenceType type, Set fBounded); - public Set grArg(ExtendsType type); - public Set smArg(ExtendsType type); + public Set grArg(ExtendsType type, Set fBounded); + public Set smArg(ExtendsType type, Set fBounded); - public Set grArg(SuperType type); - public Set smArg(SuperType type); + public Set grArg(SuperType type, Set fBounded); + public Set smArg(SuperType type, Set fBounded); - public Set grArg(PlaceholderType type); - public Set smArg(PlaceholderType type); + public Set grArg(PlaceholderType type, Set fBounded); + public Set smArg(PlaceholderType type, Set fBounded); - public Set grArg(FunNType type); - public Set smArg(FunNType type); + public Set grArg(FunNType type, Set fBounded); + public Set smArg(FunNType type, Set fBounded); public Optional getLeftHandedType(String typeName); public Set getAncestors(UnifyType t); public Set getChildren(UnifyType t); - public Set getAllTypesByName(String typeName); + public Set getAllTypesByName(String typeName); + + public int compare(UnifyType rhsType, UnifyType rhsType2, PairOperator pairop); } diff --git a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IMatch.java b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IMatch.java index 5e201dd7..ab88f33b 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IMatch.java +++ b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IMatch.java @@ -13,23 +13,17 @@ import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; /** * Match * @author Martin Pluemicke + * abgeleitet aus IUnify.java */ public interface IMatch { /** - * Finds the most general unifier sigma of the set {t1,...,tn} so that - * sigma(t1) = sigma(t2) = ... = sigma(tn). - * @param terms The set of terms to be unified - * @return An optional of the most general unifier if it exists or an empty optional if there is no unifier. + * Finds the most general matcher sigma of the set {t1 =. t1',...,tn =. tn'} so that + * sigma(t1) = t1' , ... sigma(tn) = tn'. + * @param terms The set of terms to be matched + * @return An optional of the most general matcher if it exists or an empty optional if there is no matcher. */ public Optional match(ArrayList termsList); - - /** - * Finds the most general unifier sigma of the set {t1,...,tn} so that - * sigma(t1) = sigma(t2) = ... = sigma(tn). - * @param terms The set of terms to be unified - * @return An optional of the most general unifier if it exists or an empty optional if there is no unifier. - */ } diff --git a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java index 62c9649f..a2b647c6 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java +++ b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java @@ -27,9 +27,13 @@ public interface IRuleSet { public Optional reduceWildcardLowRight(UnifyPair pair); public Optional reduceWildcardUp(UnifyPair pair); public Optional reduceWildcardUpRight(UnifyPair pair); + + /* + * vgl. JAVA_BSP/Wildcard6.java public Optional reduceWildcardLowUp(UnifyPair pair); public Optional reduceWildcardUpLow(UnifyPair pair); public Optional reduceWildcardLeft(UnifyPair pair); + */ /* * Additional Rules which replace cases of the cartesian product diff --git a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IUnify.java b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IUnify.java index 524608f5..57b41736 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IUnify.java +++ b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IUnify.java @@ -15,16 +15,16 @@ import de.dhbwstuttgart.typeinference.unify.model.Unifier; public interface IUnify { /** - * Finds the most general unifier sigma of the set {t1,...,tn} so that - * sigma(t1) = sigma(t2) = ... = sigma(tn). + * Finds the most general unifier sigma of the set {t1 =. t1',...,tn =. tn'} so that + * sigma(t1) = sigma(t1') , ... sigma(tn) = sigma(tn'). * @param terms The set of terms to be unified * @return An optional of the most general unifier if it exists or an empty optional if there is no unifier. */ public Optional unify(Set terms); /** - * Finds the most general unifier sigma of the set {t1,...,tn} so that - * sigma(t1) = sigma(t2) = ... = sigma(tn). + * Finds the most general unifier sigma of the set {t1 =. t1',...,tn =. tn'} so that + * sigma(t1) = sigma(t1') , ... sigma(tn) = sigma(tn'). * @param terms The set of terms to be unified * @return An optional of the most general unifier if it exists or an empty optional if there is no unifier. */ diff --git a/src/de/dhbwstuttgart/typeinference/unify/interfaces/UnifyTypeVisitor.java b/src/de/dhbwstuttgart/typeinference/unify/interfaces/UnifyTypeVisitor.java new file mode 100644 index 00000000..8d06b3e1 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/interfaces/UnifyTypeVisitor.java @@ -0,0 +1,23 @@ +package de.dhbwstuttgart.typeinference.unify.interfaces; + +import java.util.HashMap; + +import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; +import de.dhbwstuttgart.typeinference.unify.model.SuperType; + +public interface UnifyTypeVisitor { + + public ReferenceType visit(ReferenceType refty, T ht); + + public PlaceholderType visit(PlaceholderType phty, T ht); + + public FunNType visit(FunNType funnty, T ht); + + public SuperType visit(SuperType suty, T ht); + + public ExtendsType visit(ExtendsType extty, T ht); + +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/ExtendsType.java b/src/de/dhbwstuttgart/typeinference/unify/model/ExtendsType.java index 33f32e07..e9b805c1 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/ExtendsType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/ExtendsType.java @@ -2,21 +2,30 @@ package de.dhbwstuttgart.typeinference.unify.model; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.Set; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; /** * An extends wildcard type "? extends T". */ public final class ExtendsType extends WildcardType { + public UnifyType accept(UnifyTypeVisitor visitor, T ht) { + return visitor.visit(this, ht); + } + /** * Creates a new extends wildcard type. * @param extendedType The extended type e.g. Integer in "? extends Integer" */ public ExtendsType(UnifyType extendedType) { - super("? extends " + extendedType.getName(), extendedType); + super("? extends " + extendedType.getName(), extendedType); + if (extendedType instanceof ExtendsType) { + System.out.print(""); + } } /** @@ -38,13 +47,13 @@ public final class ExtendsType extends WildcardType { } @Override - Set smArg(IFiniteClosure fc) { - return fc.smArg(this); + Set smArg(IFiniteClosure fc, Set fBounded) { + return fc.smArg(this, fBounded); } @Override - Set grArg(IFiniteClosure fc) { - return fc.grArg(this); + Set grArg(IFiniteClosure fc, Set fBounded) { + return fc.grArg(this, fBounded); } @Override diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java b/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java index dcffbee6..5eef0308 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java @@ -4,15 +4,21 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.Hashtable; import java.util.Optional; import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.BinaryOperator; import java.util.stream.Collectors; -//PL 18-02-05 Unifier durch Matcher ersetzt -//mus greater noch erstezt werden +import com.google.common.collect.Ordering; + +//PL 18-02-05/18-04-05 Unifier durch Matcher ersetzt +//muss greater noch ersetzt werden ja erledigt 18--04-05 import de.dhbwstuttgart.typeinference.unify.MartelliMontanariUnify; import de.dhbwstuttgart.typeinference.unify.Match; +import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; @@ -20,7 +26,7 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; * The finite closure for the type unification * @author Florian Steurer */ -public class FiniteClosure implements IFiniteClosure { +public class FiniteClosure extends Ordering implements IFiniteClosure { /** * A map that maps every type to the node in the inheritance graph that contains that type. @@ -89,36 +95,43 @@ public class FiniteClosure implements IFiniteClosure { * @return The set of subtypes of the argument. */ @Override - public Set smaller(UnifyType type) { + public Set smaller(UnifyType type, Set fBounded) { if(type instanceof FunNType) - return computeSmallerFunN((FunNType) type); + return computeSmallerFunN((FunNType) type, fBounded); - Set ts = new HashSet<>(); - ts.add(type); + Set>> ts = new HashSet<>(); + ts.add(new Pair<>(type, fBounded)); return computeSmaller(ts); } /** * Computes the smaller functions for every type except FunNTypes. */ - private Set computeSmaller(Set types) { - HashSet result = new HashSet<>(); + private Set computeSmaller(Set>> types) { + Set>> result = new HashSet<>(); //PL 18-02-05 Unifier durch Matcher ersetzt //IUnify unify = new MartelliMontanariUnify(); Match match = new Match(); - for(UnifyType t : types) { + for(Pair> pt : types) { + UnifyType t = pt.getKey(); + Set fBounded = pt.getValue().get(); // if T = T' then T <* T' - result.add(t); + try { + result.add(new Pair<>(t, fBounded)); + } + catch (StackOverflowError e) { + System.out.println(""); + } // if C<...> <* C<...> then ... (third case in definition of <*) if(t.getTypeParams().size() > 0) { ArrayList> paramCandidates = new ArrayList<>(); for (int i = 0; i < t.getTypeParams().size(); i++) - paramCandidates.add(smArg(t.getTypeParams().get(i))); - permuteParams(paramCandidates).forEach(x -> result.add(t.setTypeParams(x))); + paramCandidates.add(smArg(t.getTypeParams().get(i), fBounded)); + permuteParams(paramCandidates).forEach(x -> result.add(new Pair<>(t.setTypeParams(x), fBounded))); } if(!strInheritanceGraph.containsKey(t.getName())) @@ -144,19 +157,20 @@ public class FiniteClosure implements IFiniteClosure { Set theta1Set = candidate.getContentOfDescendants(); for(UnifyType theta1 : theta1Set) - result.add(theta1.apply(sigma)); + result.add(new Pair<>(theta1.apply(sigma), fBounded)); } } - if(result.equals(types)) - return result; + HashSet resut = result.stream().map(x -> x.getKey()).collect(Collectors.toCollection(HashSet::new)); + if(resut.equals(types.stream().map(x -> x.getKey()).collect(Collectors.toCollection(HashSet::new)))) + return resut; return computeSmaller(result); } /** * Computes the smaller-Function for FunNTypes. */ - private Set computeSmallerFunN(FunNType type) { + private Set computeSmallerFunN(FunNType type, Set fBounded) { Set result = new HashSet<>(); // if T = T' then T <=* T' @@ -165,47 +179,152 @@ public class FiniteClosure implements IFiniteClosure { // Because real function types are implicitly variant // it is enough to permute the params with the values of greater / smaller. ArrayList> paramCandidates = new ArrayList<>(); - paramCandidates.add(smaller(type.getTypeParams().get(0))); + paramCandidates.add(smaller(type.getTypeParams().get(0), fBounded)); for (int i = 1; i < type.getTypeParams().size(); i++) - paramCandidates.add(greater(type.getTypeParams().get(i))); + paramCandidates.add(greater(type.getTypeParams().get(i), new HashSet<>())); permuteParams(paramCandidates).forEach(x -> result.add(type.setTypeParams(x))); return result; } - + /** * Returns all types of the finite closure that are supertypes of the argument. * @return The set of supertypes of the argument. */ @Override - public Set greater(UnifyType type) { - if(type instanceof FunNType) - return computeGreaterFunN((FunNType) type); + //Eingefuegt PL 2018-05-24 F-Bounded Problematik + public Set greater(UnifyType type, Set fBounded) { - Set ts = new HashSet<>(); - ts.add(type); + if(type instanceof FunNType) { + return computeGreaterFunN((FunNType) type, fBounded); + } + + Set result = new HashSet<>(); + Set>> PairResultFBounded = new HashSet<>(); + + Match match = new Match(); + + + // if T = T' then T <=* T' + result.add(type); + if(!strInheritanceGraph.containsKey(type.getName())) + return result; + + // if T <* T' then sigma(T) <* sigma(T') + Set> candidates = strInheritanceGraph.get(type.getName()); + for(Node candidate : candidates) { + UnifyType theta1 = candidate.getContent(); + + //PL 18-04-05 Unifier durch Matcher ersetzt ANFANG + ArrayList termList= new ArrayList(); + termList.add(new UnifyPair(theta1,type, PairOperator.EQUALSDOT)); + Optional optSigma = match.match(termList); + //PL 18-04-05 Unifier durch Matcher ersetzt ENDE + if(!optSigma.isPresent()) + continue; + + Unifier sigma = optSigma.get(); + sigma.swapPlaceholderSubstitutionsReverse(theta1.getTypeParams()); + + Set fBoundedNew = new HashSet<>(fBounded); + fBoundedNew.add(theta1); + Set theta2Set = candidate.getContentOfPredecessors(); + //System.out.println(""); + for(UnifyType theta2 : theta2Set) { + result.add(theta2.apply(sigma)); + PairResultFBounded.add(new Pair<>(theta2.apply(sigma), fBoundedNew)); + } + } + + for(Pair> pt : PairResultFBounded) { + UnifyType t = pt.getKey(); + Set lfBounded = pt.getValue().get(); + + // if C<...> <* C<...> then ... (third case in definition of <*) + //TypeParams typeparams = t.getTypeParams(); + if(t.getTypeParams().size() > 0) { + ArrayList> paramCandidates = new ArrayList<>(); + + for (int i = 0; i < t.getTypeParams().size(); i++) { + //UnifyType parai = t.getTypeParams().get(i); + int i_ef = i; + BiFunction f = (x,y) -> + { + ArrayList termList = new ArrayList(); + termList.add(new UnifyPair(y,t.getTypeParams().get(i_ef), PairOperator.EQUALSDOT)); + return ((match.match(termList).isPresent()) || x); + }; + //if (parai.getName().equals("java.lang.Integer")) { + // System.out.println(""); + //} + BinaryOperator bo = (a,b) -> (a || b); + if (lfBounded.stream().reduce(false,f,bo)) { + //F-Bounded Endlosrekursion + HashSet res = new HashSet(); + paramCandidates.add(res); + } + else { + paramCandidates.add(grArg(t.getTypeParams().get(i), new HashSet<>(fBounded) )); + } + } + permuteParams(paramCandidates).forEach(x -> result.add(t.setTypeParams(x))); + //System.out.println(""); + } + } + return result; + } + + /* auskommentiert PL 2018-05-24 + /** + * Returns all types of the finite closure that are supertypes of the argument. + * @return The set of supertypes of the argument. + * + //@Override + public Set oldgreater(UnifyType type, Set fBounded) { + if(type instanceof FunNType) + return computeGreaterFunN((FunNType) type, fBounded); + + Set>> ts = new HashSet<>(); + ts.add(new Pair<>(type, fBounded)); return computeGreater(ts); } /** * Computes the greater function for all types except function types. - */ - protected Set computeGreater(Set types) { - HashSet result = new HashSet<>(); + * + protected Set computeGreater(Set>> types) { + Set>> result = new HashSet<>(); - IUnify unify = new MartelliMontanariUnify(); + //PL 18-04-05 Unifier durch Matcher ersetzt + //IUnify unify = new MartelliMontanariUnify(); + Match match = new Match(); - for(UnifyType t : types) { - + for(Pair> pt : types) { + UnifyType t = pt.getKey(); + Set fBounded = pt.getValue().get(); // if T = T' then T <=* T' - result.add(t); + result.add(pt); // if C<...> <* C<...> then ... (third case in definition of <*) if(t.getTypeParams().size() > 0) { ArrayList> paramCandidates = new ArrayList<>(); - for (int i = 0; i < t.getTypeParams().size(); i++) - paramCandidates.add(grArg(t.getTypeParams().get(i))); - permuteParams(paramCandidates).forEach(x -> result.add(t.setTypeParams(x))); + for (int i = 0; i < t.getTypeParams().size(); i++) { + UnifyType parai = t.getTypeParams().get(i); + int i_ef = i; + BiFunction f = (x,y) -> + { + ArrayList termList = new ArrayList(); + termList.add(new UnifyPair(y,t.getTypeParams().get(i_ef), PairOperator.EQUALSDOT)); + return ((match.match(termList).isPresent()) || x); + }; + if (parai.getName().equals("java.lang.Integer")) { + System.out.println(""); + } + BinaryOperator bo = (a,b) -> (a || b); + if (fBounded.stream().reduce(false,f,bo)) continue; //F-Bounded Endlosrekursion + paramCandidates.add(grArg(t.getTypeParams().get(i), new HashSet<>(fBounded) )); + } + permuteParams(paramCandidates).forEach(x -> result.add(new Pair<>(t.setTypeParams(x), new HashSet<>(fBounded)))); } if(!strInheritanceGraph.containsKey(t.getName())) @@ -215,30 +334,40 @@ public class FiniteClosure implements IFiniteClosure { Set> candidates = strInheritanceGraph.get(t.getName()); for(Node candidate : candidates) { UnifyType theta1 = candidate.getContent(); - Optional optSigma = unify.unify(theta1, t); + + //PL 18-04-05 Unifier durch Matcher ersetzt ANFANG + ArrayList termList= new ArrayList(); + termList.add(new UnifyPair(theta1,t, PairOperator.EQUALSDOT)); + Optional optSigma = match.match(termList); + //PL 18-04-05 Unifier durch Matcher ersetzt ENDE if(!optSigma.isPresent()) continue; Unifier sigma = optSigma.get(); sigma.swapPlaceholderSubstitutionsReverse(theta1.getTypeParams()); + Set fBoundedNew = new HashSet<>(fBounded); + fBoundedNew.add(theta1); Set theta2Set = candidate.getContentOfPredecessors(); for(UnifyType theta2 : theta2Set) - result.add(theta2.apply(sigma)); + result.add(new Pair<>(theta2.apply(sigma), fBoundedNew)); } } - if(result.equals(types)) - return result; + HashSet resut = result.stream().map(x -> x.getKey()).collect(Collectors.toCollection(HashSet::new)); + System.out.println(resut); + if(resut.equals(types.stream().map(x -> x.getKey()).collect(Collectors.toCollection(HashSet::new)))) + return resut; return computeGreater(result); } + */ /** * Computes the greater function for FunN-Types */ - protected Set computeGreaterFunN(FunNType type) { + protected Set computeGreaterFunN(FunNType type, Set fBounded) { Set result = new HashSet<>(); // if T = T' then T <=* T' @@ -247,88 +376,88 @@ public class FiniteClosure implements IFiniteClosure { // Because real function types are implicitly variant // it is enough to permute the params with the values of greater / smaller. ArrayList> paramCandidates = new ArrayList<>(); - paramCandidates.add(greater(type.getTypeParams().get(0))); + paramCandidates.add(greater(type.getTypeParams().get(0), new HashSet<>())); for (int i = 1; i < type.getTypeParams().size(); i++) - paramCandidates.add(smaller(type.getTypeParams().get(i))); + paramCandidates.add(smaller(type.getTypeParams().get(i), fBounded)); permuteParams(paramCandidates).forEach(x -> result.add(type.setTypeParams(x))); return result; } @Override - public Set grArg(UnifyType type) { - return type.grArg(this); + public Set grArg(UnifyType type, Set fBounded) { + return type.grArg(this, fBounded); } @Override - public Set grArg(ReferenceType type) { + public Set grArg(ReferenceType type, Set fBounded) { Set result = new HashSet(); result.add(type); - smaller(type).forEach(x -> result.add(new SuperType(x))); - greater(type).forEach(x -> result.add(new ExtendsType(x))); + smaller(type, fBounded).forEach(x -> result.add(new SuperType(x))); + greater(type,fBounded).forEach(x -> result.add(new ExtendsType(x))); return result; } @Override - public Set grArg(FunNType type) { + public Set grArg(FunNType type, Set fBounded) { Set result = new HashSet(); result.add(type); - smaller(type).forEach(x -> result.add(new SuperType(x))); - greater(type).forEach(x -> result.add(new ExtendsType(x))); + smaller(type, fBounded).forEach(x -> result.add(new SuperType(x))); + greater(type, fBounded).forEach(x -> result.add(new ExtendsType(x))); return result; } @Override - public Set grArg(ExtendsType type) { + public Set grArg(ExtendsType type, Set fBounded) { Set result = new HashSet(); result.add(type); UnifyType t = type.getExtendedType(); - greater(t).forEach(x -> result.add(new ExtendsType(x))); + greater(t, fBounded).forEach(x -> result.add(new ExtendsType(x))); return result; } @Override - public Set grArg(SuperType type) { + public Set grArg(SuperType type, Set fBounded) { Set result = new HashSet(); result.add(type); UnifyType t = type.getSuperedType(); - smaller(t).forEach(x -> result.add(new SuperType(x))); + smaller(t, fBounded).forEach(x -> result.add(new SuperType(x))); return result; } @Override - public Set grArg(PlaceholderType type) { + public Set grArg(PlaceholderType type, Set fBounded) { HashSet result = new HashSet<>(); result.add(type); return result; } @Override - public Set smArg(UnifyType type) { - return type.smArg(this); + public Set smArg(UnifyType type, Set fBounded) { + return type.smArg(this, fBounded); } @Override - public Set smArg(ReferenceType type) { + public Set smArg(ReferenceType type, Set fBounded) { Set result = new HashSet(); result.add(type); return result; } @Override - public Set smArg(FunNType type) { + public Set smArg(FunNType type, Set fBounded) { Set result = new HashSet(); result.add(type); return result; } @Override - public Set smArg(ExtendsType type) { + public Set smArg(ExtendsType type, Set fBounded) { Set result = new HashSet(); result.add(type); UnifyType t = type.getExtendedType(); result.add(t); - smaller(t).forEach(x -> { + smaller(t, fBounded).forEach(x -> { result.add(new ExtendsType(x)); result.add(x); }); @@ -337,12 +466,13 @@ public class FiniteClosure implements IFiniteClosure { @Override - public Set smArg(SuperType type) { + public Set smArg(SuperType type, Set fBounded) { Set result = new HashSet(); result.add(type); UnifyType t = type.getSuperedType(); result.add(t); - greater(t).forEach(x -> { +//*** ACHTUNG das koennte FALSCH sein PL 2018-05-23 evtl. HashSet durch smArg durchschleifen + greater(t, fBounded).forEach(x -> { result.add(new SuperType(x)); result.add(x); }); @@ -350,7 +480,7 @@ public class FiniteClosure implements IFiniteClosure { } @Override - public Set smArg(PlaceholderType type) { + public Set smArg(PlaceholderType type, Set fBounded) { HashSet result = new HashSet<>(); result.add(type); return result; @@ -369,7 +499,7 @@ public class FiniteClosure implements IFiniteClosure { return Optional.empty(); for(UnifyPair pair : pairs) - if(pair.getLhsType().getName().equals(typeName)) + if(pair.getLhsType().getName().equals(typeName) && pair.getLhsType().typeParams.arePlaceholders()) return Optional.of(pair.getLhsType()); return Optional.empty(); @@ -430,4 +560,33 @@ public class FiniteClosure implements IFiniteClosure { public String toString(){ return this.inheritanceGraph.toString(); } + + public int compare (UnifyType left, UnifyType right) { + return compare(left, right, PairOperator.SMALLERDOT); + } + + public int compare (UnifyType left, UnifyType right, PairOperator pairop) { + if ((left instanceof ExtendsType && right instanceof ReferenceType) + || (right instanceof ExtendsType && left instanceof ReferenceType)) + System.out.println(""); + UnifyPair up = new UnifyPair(left, right, pairop); + TypeUnifyTask unifyTask = new TypeUnifyTask(); + HashSet hs = new HashSet<>(); + hs.add(up); + Set smallerRes = unifyTask.applyTypeUnificationRules(hs, this); + //Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok. + long smallerLen = smallerRes.stream().filter(x -> !(x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType)).count(); + if (smallerLen == 0) return -1; + else { + up = new UnifyPair(right, left, pairop); + //TypeUnifyTask unifyTask = new TypeUnifyTask(); + hs = new HashSet<>(); + hs.add(up); + Set greaterRes = unifyTask.applyTypeUnificationRules(hs, this); + //Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok. + long greaterLen = greaterRes.stream().filter(x -> !(x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType)).count(); + if (greaterLen == 0) return 1; + else return 0; + } + } } diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/FunNType.java b/src/de/dhbwstuttgart/typeinference/unify/model/FunNType.java index cf2c86ae..3e9f2ae6 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/FunNType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/FunNType.java @@ -1,8 +1,12 @@ package de.dhbwstuttgart.typeinference.unify.model; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import java.util.Set; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; /** * A real function type in java. @@ -10,6 +14,10 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; */ public class FunNType extends UnifyType { + public UnifyType accept(UnifyTypeVisitor visitor, T ht) { + return visitor.visit(this, ht); + } + /** * Creates a FunN-Type with the specified TypeParameters. */ @@ -47,13 +55,13 @@ public class FunNType extends UnifyType { } @Override - Set smArg(IFiniteClosure fc) { - return fc.smArg(this); + Set smArg(IFiniteClosure fc, Set fBounded) { + return fc.smArg(this, fBounded); } @Override - Set grArg(IFiniteClosure fc) { - return fc.grArg(this); + Set grArg(IFiniteClosure fc, Set fBounded) { + return fc.grArg(this, fBounded); } @Override @@ -67,11 +75,18 @@ public class FunNType extends UnifyType { return new FunNType(newParams); } + @Override + public Boolean wrongWildcard() { + return (new ArrayList(Arrays.asList(getTypeParams() + .get())).stream().filter(x -> (x instanceof WildcardType)).findFirst().isPresent()); + } + @Override public int hashCode() { return 181 + typeParams.hashCode(); } + @Override public boolean equals(Object obj) { if(!(obj instanceof FunNType)) diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/OrderingUnifyPair.java b/src/de/dhbwstuttgart/typeinference/unify/model/OrderingUnifyPair.java new file mode 100644 index 00000000..8cebdd8a --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/OrderingUnifyPair.java @@ -0,0 +1,228 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Optional; +import java.util.Set; +import java.util.function.BinaryOperator; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.google.common.collect.Ordering; + +import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; + + + +public class OrderingUnifyPair extends Ordering> { + + protected IFiniteClosure fc; + + public OrderingUnifyPair(IFiniteClosure fc) { + this.fc = fc; + } + + /* + * vergleicht Paare (a =. Theta) und (a =. Theta') + * in dem compare(Theta, Theta') aufgerufen wird. + */ + public int compareEq (UnifyPair left, UnifyPair right) { + if (left.getRhsType() instanceof WildcardType || right.getRhsType() instanceof WildcardType) { + return fc.compare(left.getRhsType(), right.getRhsType(), PairOperator.SMALLERDOTWC); + } + else { + return fc.compare(left.getRhsType(), right.getRhsType(), PairOperator.SMALLERDOT); + } + } + /* + public int compareEq (UnifyPair left, UnifyPair right) { + if (left == null || right == null) + System.out.println("Fehler"); + if (left.getLhsType() instanceof PlaceholderType) { + return fc.compare(left.getRhsType(), right.getRhsType(), left.getPairOp()); + } + else { + return fc.compare(left.getLhsType(), right.getLhsType(), left.getPairOp()); + } + } + */ + + public Pair> compare (UnifyType left, UnifyType right) { + UnifyPair up; + if (left instanceof WildcardType || right instanceof WildcardType) { + up = new UnifyPair(left, right, PairOperator.SMALLERDOTWC); + } + else { + up = new UnifyPair(left, right, PairOperator.SMALLERDOT); + } + TypeUnifyTask unifyTask = new TypeUnifyTask(); + HashSet hs = new HashSet<>(); + hs.add(up); + Set smallerRes = unifyTask.applyTypeUnificationRules(hs, fc); + long smallerLen = smallerRes.stream().filter(x -> !(x.getLhsType() instanceof PlaceholderType && x.getRhsType() instanceof PlaceholderType)).count(); + if (smallerLen == 0) return new Pair<>(-1, smallerRes); + else { + if (left instanceof WildcardType || right instanceof WildcardType) { + up = new UnifyPair(right, left, PairOperator.SMALLERDOTWC); + } + else { + up = new UnifyPair(right, left, PairOperator.SMALLERDOT); + } + //TypeUnifyTask unifyTask = new TypeUnifyTask(); + hs = new HashSet<>(); + hs.add(up); + Set greaterRes = unifyTask.applyTypeUnificationRules(hs, fc); + long greaterLen = greaterRes.stream().filter(x -> !(x.getLhsType() instanceof PlaceholderType && x.getRhsType() instanceof PlaceholderType)).count(); + if (greaterLen == 0) return new Pair<>(1, greaterRes); + else return new Pair<>(0, new HashSet<>()); + } + } + + /* TODO muss noch verifiziert werden PL 2018-03-21 + * (non-Javadoc) + * fuehrt zu Fehlern bei Arrays.sort (contract nicht erfuellt) + * @see com.google.common.collect.Ordering#compare(java.lang.Object, java.lang.Object) + */ + public int compare (Set left, Set right) { + Set lefteq = left.stream() + .filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT)) + .collect(Collectors.toCollection(HashSet::new)); + Set righteq = right.stream() + .filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT)) + .collect(Collectors.toCollection(HashSet::new)); + Set leftle = left.stream() + .filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType) + && x.getPairOp() == PairOperator.SMALLERDOT)) + .collect(Collectors.toCollection(HashSet::new)); + Set rightle = right.stream() + .filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType) + && x.getPairOp() == PairOperator.SMALLERDOT)) + .collect(Collectors.toCollection(HashSet::new)); + Set leftlewc = left.stream() + .filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType) + && x.getPairOp() == PairOperator.SMALLERDOTWC)) + .collect(Collectors.toCollection(HashSet::new)); + Set rightlewc = right.stream() + .filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType) + && x.getPairOp() == PairOperator.SMALLERDOTWC)) + .collect(Collectors.toCollection(HashSet::new)); + //System.out.println(left.toString()); + //Fall 2 und 3 + //if (lefteq.iterator().next().getLhsType().getName().equals("AJO")) { + // System.out.print(""); + //} + if (lefteq.size() == 1 && leftle.size() == 1 && righteq.size() == 0 && rightle.size() == 1) { + return 1; + } + //Fall 2 und 3 + if (lefteq.size() == 0 && leftle.size() == 1 && righteq.size() == 1 && rightle.size() == 1) { + return -1; + } + //Fall 5 + if (lefteq.size() == 1 && leftle.size() == 0 && righteq.size() == 1 && rightle.size() == 1) { + return -1; + } + //Fall 5 + if (lefteq.size() == 1 && leftle.size() == 1 && righteq.size() == 1 && rightle.size() == 0) { + return 1; + } + //Fall 5 + if (lefteq.size() == 1 && leftle.size() == 1 && righteq.size() == 1 && rightle.size() == 1) { + return 0; + } + // Nur Paare a =. Theta + if (leftle.size() == 0 && rightle.size() == 0 && leftlewc.size() == 0 && rightlewc.size() ==0) { + Stream lseq = lefteq.stream(); //left.filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT)); + Stream rseq = righteq.stream(); //right.filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT)); + BinaryOperator> combiner = (x,y) -> { x.putAll(y); return x;}; + HashMap hm = rseq.reduce(new HashMap(), (x, y)-> { x.put(y.getLhsType(),y); return x; }, combiner); + lseq = lseq.filter(x -> !(hm.get(x.getLhsType()) == null));//NOCHMALS UEBERPRUEFEN!!!! + lseq = lseq.filter(x -> !x.equals(hm.get(x.getLhsType()))); //Elemente die gleich sind muessen nicht verglichen werden + Optional si = lseq.map(x -> compareEq(x, hm.get(x.getLhsType()))).reduce((x,y)-> { if (x == y) return x; else return 0; } ); + if (!si.isPresent()) return 0; + else return si.get(); + } + //Fall 1 und 4 + if (lefteq.size() >= 1 && righteq.size() >= 1 && (leftlewc.size() > 0 || rightlewc.size() > 0)) { + if (lefteq.iterator().next().getLhsType().getName().equals("D")) + System.out.print(""); + //Set varsleft = lefteq.stream().map(x -> (PlaceholderType)x.getLhsType()).collect(Collectors.toCollection(HashSet::new)); + //Set varsright = righteq.stream().map(x -> (PlaceholderType)x.getLhsType()).collect(Collectors.toCollection(HashSet::new)); + //filtern des Paares a = Theta, das durch a <. Thata' generiert wurde (nur im Fall 1 relevant) + lefteq.removeIf(x -> !(x.getLhsType().getName().equals(x.getBasePair().getLhsType().getName()) + ||x.getLhsType().getName().equals(x.getBasePair().getRhsType().getName())));//removeIf(x -> !varsright.contains(x.getLhsType())); + righteq.removeIf(x -> !(x.getLhsType().getName().equals(x.getBasePair().getLhsType().getName()) + ||x.getLhsType().getName().equals(x.getBasePair().getRhsType().getName())));//.removeIf(x -> !varsleft.contains(x.getLhsType())); + UnifyPair lseq = lefteq.iterator().next(); + UnifyPair rseq = righteq.iterator().next(); + if (lseq.getRhsType().getName().equals("Object")) { + if (rseq.getRhsType().getName().equals("Object")) return 0; + else return 1; + } + else { + if (rseq.getRhsType().getName().equals("Object")) return -1; + } + if (leftlewc.size() == rightlewc.size()) { + //TODO: Hier wird bei Wildcards nicht das richtige compare aufgerufen PL 18-04-20 + Pair> int_Unifier = compare(lseq.getRhsType(), rseq.getRhsType()); + Unifier uni = new Unifier(); + int_Unifier.getValue().get().forEach(x -> uni.add((PlaceholderType) x.getLhsType(), x.getRhsType())); + if (!lseq.getRhsType().getName().equals(rseq.getRhsType().getName()) + || leftlewc.size() == 0 || rightlewc.size() == 0) return int_Unifier.getKey(); + else { + Set lsleuni = leftlewc.stream().map(x -> uni.apply(x)).collect(Collectors.toCollection(HashSet::new)); + Set rsleuni = rightlewc.stream().map(x -> uni.apply(x)).collect(Collectors.toCollection(HashSet::new)); + BinaryOperator> combiner = (x,y) -> { x.putAll(y); return x;}; + + HashMap hm; + Optional si; + //1. Fall + if (leftlewc.iterator().next().getLhsType() instanceof PlaceholderType) { + hm = rsleuni.stream().reduce(new HashMap(), (x, y)-> { x.put(y.getLhsType(),y); return x; }, combiner); + Stream lslewcstr = lsleuni.stream().filter(x -> !(hm.get(x.getLhsType()) == null)); + si = lslewcstr.map(x -> fc.compare(x.getRhsType(), hm.get(x.getLhsType()).getRhsType(), PairOperator.SMALLERDOTWC)).reduce((x,y)-> { if (x == y) return x; else return 0; } ); + } + //4. Fall + else { + hm = rsleuni.stream().reduce(new HashMap(), (x, y)-> { x.put(y.getRhsType(),y); return x; }, combiner); + Stream lslewcstr = lsleuni.stream().filter(x -> !(hm.get(x.getRhsType()) == null)); + si = lslewcstr.map(x -> fc.compare(x.getLhsType(), hm.get(x.getRhsType()).getLhsType(), PairOperator.SMALLERDOTWC)).reduce((x,y)-> { if (x == y) return x; else return 0; } ); + } + if (!si.isPresent()) return 0; + else return si.get(); + } + } else { + if (leftlewc.size() > 0) { + Set subst; + if (leftlewc.iterator().next().getLhsType() instanceof PlaceholderType) { + subst = leftlewc.stream().map(x -> new UnifyPair(x.getLhsType(), x.getRhsType(), PairOperator.EQUALSDOT)).collect(Collectors.toCollection(HashSet::new)); + } + else { + subst = leftlewc.stream().map(x -> new UnifyPair(x.getRhsType(), x.getLhsType(), PairOperator.EQUALSDOT)).collect(Collectors.toCollection(HashSet::new)); + } + Unifier uni = new Unifier(); + subst.stream().forEach(x -> uni.add((PlaceholderType) x.getLhsType(), x.getRhsType())); + lseq = uni.apply(lseq); + } + else { + Set subst; + if (rightlewc.iterator().next().getLhsType() instanceof PlaceholderType) { + subst = rightlewc.stream().map(x -> new UnifyPair(x.getLhsType(), x.getRhsType(), PairOperator.EQUALSDOT)).collect(Collectors.toCollection(HashSet::new)); + } + else { + subst = rightlewc.stream().map(x -> new UnifyPair(x.getRhsType(), x.getLhsType(), PairOperator.EQUALSDOT)).collect(Collectors.toCollection(HashSet::new)); + } + Unifier uni = new Unifier(); + subst.stream().forEach(x -> uni.add((PlaceholderType) x.getLhsType(), x.getRhsType())); + rseq = uni.apply(rseq); + } + return compareEq(lseq, rseq); + } + } + return 0; + } +} + diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/Pair.java b/src/de/dhbwstuttgart/typeinference/unify/model/Pair.java new file mode 100644 index 00000000..08c4aa1c --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/model/Pair.java @@ -0,0 +1,21 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.Optional; + +public class Pair { + private final T key; + private final T1 value; + + public Pair(T a, T1 b) { + this.value = b; + this.key = a; + } + + public Optional getValue() { + return Optional.of(value); + } + + public T getKey() { + return key; + } +} diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/PairOperator.java b/src/de/dhbwstuttgart/typeinference/unify/model/PairOperator.java index fd18f6c0..ea323c79 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/PairOperator.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/PairOperator.java @@ -17,6 +17,12 @@ public enum PairOperator { */ SMALLERDOT, + /** + * The smallernedot operator for arguments (T / ... with the Supertype Number + */ + SMALLERNEQDOT, + /** * The smallerdot operator for arguments (T <.? P) is used to express that * T is an element of smArg(P) (or P is an element of grArg(T)) in a CONSTRAINT @@ -35,6 +41,7 @@ public enum PairOperator { switch (this) { case SMALLER: return "<"; case SMALLERDOT: return "<."; + case SMALLERNEQDOT: return " UnifyType accept(UnifyTypeVisitor visitor, T ht) { + return visitor.visit(this, ht); + } + /** * Creates a fresh placeholder type with a name that does so far not exist. * A user could later instantiate a type using the same name that is equivalent to this type. @@ -67,6 +89,7 @@ public final class PlaceholderType extends UnifyType{ return new PlaceholderType(name, true); } + /** * True if this placeholder is auto-generated, false if it is user-generated. */ @@ -74,14 +97,29 @@ public final class PlaceholderType extends UnifyType{ return IsGenerated; } + public void setVariance(int v) { + variance = v; + } + + public int getVariance() { + return variance; + } + + public Boolean isWildcardable() { + return wildcardable; + } + public void disableWildcardtable() { + wildcardable = false; + } + @Override - Set smArg(IFiniteClosure fc) { - return fc.smArg(this); + Set smArg(IFiniteClosure fc, Set fBounded) { + return fc.smArg(this, fBounded); } @Override - Set grArg(IFiniteClosure fc) { - return fc.grArg(this); + Set grArg(IFiniteClosure fc, Set fBounded) { + return fc.grArg(this, fBounded); } @Override @@ -96,8 +134,13 @@ public final class PlaceholderType extends UnifyType{ @Override UnifyType apply(Unifier unif) { - if(unif.hasSubstitute(this)) - return unif.getSubstitute(this); + if(unif.hasSubstitute(this)) { + UnifyType ret = unif.getSubstitute(this); + //PL 2018-05-17 Auskommentierung muesste korrekt sein, + //bereits in JavaTXComplier Variancen gesetzt werden. + //ret.accept(new distributeVariance(), this.getVariance()); + return ret; + } return this; } diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java b/src/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java index 02ab38a0..5b17538e 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java @@ -1,8 +1,10 @@ package de.dhbwstuttgart.typeinference.unify.model; +import java.util.HashMap; import java.util.Set; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; /** * A reference type e.q. Integer or List. @@ -16,6 +18,11 @@ public final class ReferenceType extends UnifyType { */ private final int hashCode; + + public UnifyType accept(UnifyTypeVisitor visitor, T ht) { + return visitor.visit(this, ht); + } + public ReferenceType(String name, UnifyType... params) { super(name, new TypeParams(params)); hashCode = 31 + 17 * typeName.hashCode() + 17 * typeParams.hashCode(); @@ -27,13 +34,13 @@ public final class ReferenceType extends UnifyType { } @Override - Set smArg(IFiniteClosure fc) { - return fc.smArg(this); + Set smArg(IFiniteClosure fc, Set fBounded) { + return fc.smArg(this, fBounded); } @Override - Set grArg(IFiniteClosure fc) { - return fc.grArg(this); + Set grArg(IFiniteClosure fc, Set fBounded) { + return fc.grArg(this, fBounded); } @Override diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/SuperType.java b/src/de/dhbwstuttgart/typeinference/unify/model/SuperType.java index 4f78602f..fa519995 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/SuperType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/SuperType.java @@ -1,8 +1,10 @@ package de.dhbwstuttgart.typeinference.unify.model; +import java.util.HashMap; import java.util.Set; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; /** * A super wildcard type e.g. ? super Integer. @@ -10,6 +12,10 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; */ public final class SuperType extends WildcardType { + public UnifyType accept(UnifyTypeVisitor visitor, T ht) { + return visitor.visit(this, ht); + } + /** * Creates a new instance "? extends superedType" * @param superedType The type that is supered e.g. Integer in "? super Integer" @@ -42,13 +48,13 @@ public final class SuperType extends WildcardType { } @Override - Set smArg(IFiniteClosure fc) { - return fc.smArg(this); + Set smArg(IFiniteClosure fc, Set fBounded) { + return fc.smArg(this, fBounded); } @Override - Set grArg(IFiniteClosure fc) { - return fc.grArg(this); + Set grArg(IFiniteClosure fc, Set fBounded) { + return fc.grArg(this, fBounded); } @Override diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java b/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java index 3d5fc278..973a2785 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java @@ -115,6 +115,14 @@ public final class TypeParams implements Iterable{ return typeParams[i]; } + /** + * Returns the parameters of this object. + * PL 2018-03-17 + */ + public UnifyType[] get() { + return typeParams; + } + /** * Sets the the type t as the i-th parameter and returns a new object * that equals this object, except for the i-th type. diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java b/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java index 061ba588..8f594844 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java @@ -1,8 +1,10 @@ package de.dhbwstuttgart.typeinference.unify.model; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.Map.Entry; +import java.util.Set; import java.util.function.Function; /** @@ -63,7 +65,44 @@ public class Unifier implements Function, Iterable suniUnifyPair = new HashSet<>(); + suniUnifyPair.addAll(thisAsPair.getAllSubstitutions()); + suniUnifyPair.add(thisAsPair); + if (p.getLhsType() instanceof PlaceholderType //&& newLhs instanceof PlaceholderType entfernt PL 2018-04-13 + && p.getPairOp() == PairOperator.EQUALSDOT) { + suniUnifyPair.add(p); //p koennte auch subsitution sein + } + return new UnifyPair(newLhs, newRhs, p.getPairOp(), suniUnifyPair, p); + } + return new UnifyPair(newLhs, newRhs, p.getPairOp(), p.getSubstitution(), p.getBasePair()); } /** diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java b/src/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java index 0909690a..19dee99f 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java @@ -2,7 +2,10 @@ package de.dhbwstuttgart.typeinference.unify.model; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; + /** * A pair which contains two types and an operator, e.q. (Integer <. a). @@ -25,6 +28,29 @@ public class UnifyPair { */ private PairOperator pairOp; + /** wieder loesecn wird nicht mehr benoetigt PL 2018-03-31 + * variance shows the variance of the pair + * -1: contravariant + * 1 covariant + * 0 invariant + * PL 2018-03-21 + */ + private byte variance = 0; + + private boolean undefinedPair = false; + + /** + * Unifier/substitute that generated this pair + * PL 2018-03-15 + */ + private Set substitution; + + /** + * Base on which the the unifier is applied + * PL 2018-03-15 + */ + private UnifyPair basePair; + private final int hashCode; /** @@ -37,6 +63,20 @@ public class UnifyPair { this.lhs = lhs; this.rhs = rhs; pairOp = op; + substitution = new HashSet<>(); + + // Caching hashcode + hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode(); + } + + public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, Set uni, UnifyPair base) { + this.lhs = lhs; + this.rhs = rhs; + pairOp = op; + substitution = uni; + basePair = base; + this.variance = variance; + // Caching hashcode hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode(); @@ -63,6 +103,41 @@ public class UnifyPair { return pairOp; } + public byte getVariance() { + return variance; + } + + public void setVariance(byte v) { + variance = v; + } + + public void setUndefinedPair() { + undefinedPair = true; + } + public Set getSubstitution() { + return substitution; + } + + public UnifyPair getBasePair() { + return basePair; + } + public boolean isUndefinedPair() { + return undefinedPair; + } + + public Set getAllSubstitutions () { + Set ret = new HashSet<>(); + ret.addAll(getSubstitution()); + if (basePair != null) { + ret.addAll(basePair.getAllSubstitutions()); + } + return ret; + } + + public Boolean wrongWildcard() { + return lhs.wrongWildcard() || rhs.wrongWildcard(); + } + @Override public boolean equals(Object obj) { if(!(obj instanceof UnifyPair)) @@ -73,6 +148,16 @@ public class UnifyPair { UnifyPair other = (UnifyPair) obj; + if (isUndefinedPair()) { + if (other.getBasePair() != basePair || (other.getBasePair() == null && basePair == null)) { + return false; + } + if (!other.getBasePair().equals(basePair) || + !other.getAllSubstitutions().equals(getAllSubstitutions())) { + return false; + } + } + return other.getPairOp() == pairOp && other.getLhsType().equals(lhs) && other.getRhsType().equals(rhs); @@ -85,7 +170,14 @@ public class UnifyPair { @Override public String toString() { - return "(" + lhs + " " + pairOp + " " + rhs + ")"; + String ret = ""; + if (lhs instanceof PlaceholderType) { + ret = new Integer(((PlaceholderType)lhs).getVariance()).toString(); + } + if (rhs instanceof PlaceholderType) { + ret = ret + ", " + new Integer(((PlaceholderType)rhs).getVariance()).toString(); + } + return "(" + lhs + " " + pairOp + " " + rhs + ", " + ret + ")"; } /* diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java b/src/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java index 1080f03b..bb7bc1c6 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java @@ -2,10 +2,13 @@ package de.dhbwstuttgart.typeinference.unify.model; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Set; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; /** * Represents a java type. @@ -33,6 +36,9 @@ public abstract class UnifyType { typeParams = p; } + + abstract public UnifyType accept(UnifyTypeVisitor visitor, T ht); + /** * Returns the name of the type. * @return The name e.q. List for List, Integer or ? extends Integer @@ -62,7 +68,7 @@ public abstract class UnifyType { * @param fc The FC that is called. * @return The set that is smArg(this) */ - abstract Set smArg(IFiniteClosure fc); + abstract Set smArg(IFiniteClosure fc, Set fBounded); /** * Implementation of the visitor-pattern. Returns the set of grArg @@ -70,7 +76,7 @@ public abstract class UnifyType { * @param fc The FC that is called. * @return The set that is grArg(this) */ - abstract Set grArg(IFiniteClosure fc); + abstract Set grArg(IFiniteClosure fc, Set fBounded); /** * Applies a unifier to this object. @@ -96,6 +102,10 @@ public abstract class UnifyType { ret.addAll(typeParams.getInvolvedPlaceholderTypes()); return ret; } + + public Boolean wrongWildcard() {//default + return false; + } @Override public int hashCode() { diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/WildcardType.java b/src/de/dhbwstuttgart/typeinference/unify/model/WildcardType.java index 2bc51460..81999492 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/WildcardType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/WildcardType.java @@ -40,6 +40,11 @@ public abstract class WildcardType extends UnifyType { return wildcardedType.getTypeParams(); } + @Override + public Boolean wrongWildcard () {//This is an error + return (wildcardedType instanceof WildcardType); + } + @Override public int hashCode() { return wildcardedType.hashCode() + getName().hashCode() + 17; diff --git a/src/de/dhbwstuttgart/typeinference/unify/visitUnifyTypeVisitor.java b/src/de/dhbwstuttgart/typeinference/unify/visitUnifyTypeVisitor.java new file mode 100644 index 00000000..9ea3dc59 --- /dev/null +++ b/src/de/dhbwstuttgart/typeinference/unify/visitUnifyTypeVisitor.java @@ -0,0 +1,47 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.HashMap; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; +import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; +import de.dhbwstuttgart.typeinference.unify.model.SuperType; +import de.dhbwstuttgart.typeinference.unify.model.TypeParams; + +public class visitUnifyTypeVisitor implements UnifyTypeVisitor { + + public ReferenceType visit(ReferenceType refty, T ht) { + return new ReferenceType(refty.getName(), + new TypeParams( + Arrays.stream(refty.getTypeParams().get()) + .map(x -> x.accept(this, ht)) + .collect(Collectors.toCollection(ArrayList::new)))); + } + + public PlaceholderType visit(PlaceholderType phty, T ht) { + return phty; + } + + public FunNType visit(FunNType funnty, T ht) { + return FunNType.getFunNType( + new TypeParams( + Arrays.stream(funnty.getTypeParams().get()) + .map(x -> x.accept(this, ht)) + .collect(Collectors.toCollection(ArrayList::new))) + ); + } + + public SuperType visit(SuperType suty, T ht) { + return new SuperType(suty.getWildcardedType().accept(this, ht)); + } + + public ExtendsType visit(ExtendsType extty, T ht) { + return new ExtendsType(extty.getWildcardedType().accept(this, ht)); + } +} diff --git a/target/JavaTXcompiler-0.1-jar-with-dependencies.jar b/target/JavaTXcompiler-0.1-jar-with-dependencies.jar new file mode 100644 index 00000000..88d0644c Binary files /dev/null and b/target/JavaTXcompiler-0.1-jar-with-dependencies.jar differ diff --git a/target/repository/.gitignore b/target/repository/.gitignore new file mode 100644 index 00000000..5e7d2734 --- /dev/null +++ b/target/repository/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore diff --git a/test/bytecode/ATest.java b/test/bytecode/ATest.java deleted file mode 100644 index 14dbacbf..00000000 --- a/test/bytecode/ATest.java +++ /dev/null @@ -1,8 +0,0 @@ -package bytecode; - -public class ATest extends JavaTXCompilerTest { - public ATest() { - fileName = "Example"; - } - -} diff --git a/test/bytecode/AssignToLitTest.java b/test/bytecode/AssignToLitTest.java deleted file mode 100644 index dc5d397b..00000000 --- a/test/bytecode/AssignToLitTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class AssignToLitTest extends JavaTXCompilerTest { - public AssignToLitTest() { - this.fileName = "AssignToLit"; - } -} diff --git a/test/bytecode/BinaryTest.java b/test/bytecode/BinaryTest.java new file mode 100644 index 00000000..7f2f5fa4 --- /dev/null +++ b/test/bytecode/BinaryTest.java @@ -0,0 +1,40 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class BinaryTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/BinaryInMeth.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("BinaryInMeth"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() { + fail("Not yet implemented"); + } + +} diff --git a/test/bytecode/DuMethodTest.java b/test/bytecode/DuMethodTest.java deleted file mode 100644 index a4c8a226..00000000 --- a/test/bytecode/DuMethodTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class DuMethodTest extends JavaTXCompilerTest{ - public DuMethodTest() { - this.fileName = "DuMethod"; - } -} diff --git a/test/bytecode/FacTest.java b/test/bytecode/FacTest.java new file mode 100644 index 00000000..0875db05 --- /dev/null +++ b/test/bytecode/FacTest.java @@ -0,0 +1,44 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class FacTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Fac.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Fac"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method getFac = classToTest.getDeclaredMethod("getFac", Integer.class); + Integer result = (Integer) getFac.invoke(instanceOfClass,3); + assertEquals(result, 6); + } + +} diff --git a/test/bytecode/ForTest.java b/test/bytecode/ForTest.java deleted file mode 100644 index c95138d3..00000000 --- a/test/bytecode/ForTest.java +++ /dev/null @@ -1,11 +0,0 @@ -package bytecode; - -import org.objectweb.asm.Opcodes; - -public class ForTest extends JavaTXCompilerTest { - - public ForTest() { - this.fileName = "For"; - } - -} diff --git a/test/bytecode/GenTest.java b/test/bytecode/GenTest.java new file mode 100644 index 00000000..d0067d08 --- /dev/null +++ b/test/bytecode/GenTest.java @@ -0,0 +1,41 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class GenTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Gen.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Gen"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() { + fail("Not yet implemented"); + } + +} diff --git a/test/bytecode/Generics2Test.java b/test/bytecode/Generics2Test.java deleted file mode 100644 index 26e52665..00000000 --- a/test/bytecode/Generics2Test.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class Generics2Test extends JavaTXCompilerTest{ - public Generics2Test() { - this.fileName = "Generics2"; - } -} diff --git a/test/bytecode/GenericsTest.java b/test/bytecode/GenericsTest.java deleted file mode 100644 index cca16129..00000000 --- a/test/bytecode/GenericsTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class GenericsTest extends JavaTXCompilerTest { - public GenericsTest() { - this.fileName = "Generics"; - } -} diff --git a/test/bytecode/GreaterEqualTest.java b/test/bytecode/GreaterEqualTest.java new file mode 100644 index 00000000..c65a4015 --- /dev/null +++ b/test/bytecode/GreaterEqualTest.java @@ -0,0 +1,140 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class GreaterEqualTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/GreaterEqual.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("File://"+pathToClassFile)}); + classToTest = loader.loadClass("GreaterEqual"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testName() { + assertEquals("GreaterEqual", classToTest.getName()); + } + @Test + public void testIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 7, 5); + assertTrue(result); + } + + @Test + public void testIntegers2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5, 7); + assertFalse(result); + } + + @Test + public void testEqIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5, 5); + assertTrue(result); + } + + @Test + public void testLongs() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Long.class, Long.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 10L,7L); + assertTrue(result); + } + + @Test + public void testFloats() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Float.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5F,7F); + assertFalse(result); + } + + @Test + public void testDoubles() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Double.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5.0,7.0); + assertFalse(result); + } + + @Test + public void testLongInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Long.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 15L,7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5F,7); + assertFalse(result); + } + + @Test + public void testDoubleInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 25.0,17); + assertTrue(result); + } + + @Test + public void testFloatLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Long.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 75F,70L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Long.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5.0,7L); + assertFalse(result); + } + + @Test + public void testEqDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 7.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 15.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 9.0,17F); + assertFalse(result); + } + +} diff --git a/test/bytecode/GreaterThanTest.java b/test/bytecode/GreaterThanTest.java new file mode 100644 index 00000000..8ab07ff1 --- /dev/null +++ b/test/bytecode/GreaterThanTest.java @@ -0,0 +1,139 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class GreaterThanTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/GreaterThan.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("File://"+pathToClassFile)}); + classToTest = loader.loadClass("GreaterThan"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testName() { + assertEquals("GreaterThan", classToTest.getName()); + } + + public void testIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 7, 5); + assertTrue(result); + } + + @Test + public void testIntegers2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5, 7); + assertFalse(result); + } + + @Test + public void testEqIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5, 5); + assertFalse(result); + } + + @Test + public void testLongs() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Long.class, Long.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 10L,7L); + assertTrue(result); + }@Test + + public void testFloats() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Float.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5F,7F); + assertFalse(result); + } + + @Test + public void testDoubles() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Double.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5.0,7.0); + assertFalse(result); + } + + @Test + public void testLongInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Long.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 15L,7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5F,7); + assertFalse(result); + } + + @Test + public void testDoubleInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 25.0,17); + assertTrue(result); + } + + @Test + public void testFloatLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Long.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 75F,70L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Long.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5.0,7L); + assertFalse(result); + } + + @Test + public void testEqDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 7.0,7F); + assertFalse(result); + } + + @Test + public void testDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 15.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 9.0,17F); + assertFalse(result); + } + +} diff --git a/test/bytecode/ImportTest.java b/test/bytecode/ImportTest.java deleted file mode 100644 index b7244e15..00000000 --- a/test/bytecode/ImportTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class ImportTest extends JavaTXCompilerTest{ - public ImportTest() { - this.fileName = "Import"; - } -} diff --git a/test/bytecode/InterfaceTest.java b/test/bytecode/InterfaceTest.java deleted file mode 100644 index ed378127..00000000 --- a/test/bytecode/InterfaceTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class InterfaceTest extends JavaTXCompilerTest{ - public InterfaceTest() { - this.fileName = "Interface1"; - } -} diff --git a/test/bytecode/JavaTXCompilerTest.java b/test/bytecode/JavaTXCompilerTest.java deleted file mode 100644 index 623fc96e..00000000 --- a/test/bytecode/JavaTXCompilerTest.java +++ /dev/null @@ -1,90 +0,0 @@ -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; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -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.HashMap; -import java.util.List; - -import static org.junit.Assert.*; - -public class JavaTXCompilerTest { - - 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+fileName+".jav")); - System.out.println(rootDirectory+fileName+".jav"); - JavaTXCompiler compiler = new JavaTXCompiler(filesToTest); - for(File f : filesToTest){ - String content = readFile(f.getPath(), StandardCharsets.UTF_8); - 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, ResultSet resultSet) { - HashMap classFiles = new HashMap<>(); - BytecodeGen bytecodeGen = new BytecodeGen(classFiles,resultSet); - bytecodeGen.visit(sf); - return bytecodeGen.getClassFiles(); - } - - public void writeClassFile(HashMap classFiles) { - FileOutputStream output; - 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) - throws IOException - { - byte[] encoded = Files.readAllBytes(Paths.get(path)); - return new String(encoded, encoding); - } - -} \ No newline at end of file diff --git a/test/bytecode/LamAssignTest.java b/test/bytecode/LamAssignTest.java deleted file mode 100644 index 3442c1d1..00000000 --- a/test/bytecode/LamAssignTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class LamAssignTest extends JavaTXCompilerTest{ - public LamAssignTest() { - this.fileName = "LamAssign"; - } -} diff --git a/test/bytecode/LambdaTest.java b/test/bytecode/LambdaTest.java new file mode 100644 index 00000000..f29690cb --- /dev/null +++ b/test/bytecode/LambdaTest.java @@ -0,0 +1,23 @@ +package bytecode; + +import java.io.File; + +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class LambdaTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Lambda.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + } + + +} diff --git a/test/bytecode/LessEqualTest.java b/test/bytecode/LessEqualTest.java new file mode 100644 index 00000000..de9cdb8c --- /dev/null +++ b/test/bytecode/LessEqualTest.java @@ -0,0 +1,133 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class LessEqualTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/LessEqual.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("LessEqual"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testName() { + assertEquals("LessEqual", classToTest.getName()); + } + + @Test + public void testIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Integer.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5,7); + assertTrue(result); + } + + @Test + public void testEqualIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Integer.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5,5); + assertTrue(result); + } + + @Test + public void testLongs() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Long.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5L,7L); + assertTrue(result); + }@Test + + public void testFloats() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5F,7F); + assertTrue(result); + } + + @Test + public void testDoubles() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Double.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5.0,7.0); + assertTrue(result); + } + + @Test + public void testLongInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Long.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5L,7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5F,7); + assertTrue(result); + } + + @Test + public void testDoubleInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5.0,7); + assertTrue(result); + } + + @Test + public void testFloatLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5F,7L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5.0,7L); + assertTrue(result); + } + + @Test + public void testEqDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 7.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 9.0,7F); + assertFalse(result); + } + +} diff --git a/test/bytecode/LessThanTest.java b/test/bytecode/LessThanTest.java new file mode 100644 index 00000000..6846f820 --- /dev/null +++ b/test/bytecode/LessThanTest.java @@ -0,0 +1,141 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class LessThanTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/LessThan.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("LessThan"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testClassName() { + assertEquals("LessThan", classToTest.getName()); + } + + @Test + public void testLessThanInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class,Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 5, 7); + assertTrue(result); + } + + @Test + public void testLessThanInt2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7, 5); + assertFalse(result); + } + + @Test + public void testLessThanInt3() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 5, 5); + assertFalse(result); + } + + @Test + public void testLessThanLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class,Long.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 5L, 7L); + assertTrue(result); + } + + @Test + public void testLessThanLong2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7L, 5L); + assertFalse(result); + } + + @Test + public void testLessThanLong3() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 5L, 5L); + assertFalse(result); + } + + @Test + public void testLessThanFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Float.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7F, 5F); + assertFalse(result); + } + + @Test + public void testLessThanDouble() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Double.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7.0, 5.0); + assertFalse(result); + } + + @Test + public void testLessThanLongInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7L, 5); + assertFalse(result); + } + + @Test + public void testLessThanFloatInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7F, 5); + assertFalse(result); + } + + @Test + public void testLessThanDoubleInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7.0, 5); + assertFalse(result); + } + + @Test + public void testLessThanFloatLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7F, 5L); + assertFalse(result); + } + + @Test + public void testLessThanDoubleLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7.0, 5L); + assertFalse(result); + } + + @Test + public void testLessThanDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Float.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7.0, 5F); + assertFalse(result); + } + +} diff --git a/test/bytecode/MatrixTest.java b/test/bytecode/MatrixTest.java new file mode 100644 index 00000000..98884151 --- /dev/null +++ b/test/bytecode/MatrixTest.java @@ -0,0 +1,40 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class MatrixTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Matrix.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Matrix"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() { + fail("Not yet implemented"); + } + +} diff --git a/test/bytecode/MethodsTest.java b/test/bytecode/MethodsTest.java deleted file mode 100644 index 11195b71..00000000 --- a/test/bytecode/MethodsTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class MethodsTest extends JavaTXCompilerTest { - public MethodsTest() { - this.fileName = "Methods"; - } -} diff --git a/test/bytecode/OLTest.java b/test/bytecode/OLTest.java new file mode 100644 index 00000000..ff91073e --- /dev/null +++ b/test/bytecode/OLTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class OLTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/OL.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("OL"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + @Test + public void test() { + fail("Not yet implemented"); + } + +} diff --git a/test/bytecode/Op.jav b/test/bytecode/Op.jav deleted file mode 100644 index 9c05b0a2..00000000 --- a/test/bytecode/Op.jav +++ /dev/null @@ -1,12 +0,0 @@ -import java.lang.Integer; - -class Op { - m(Integer a, Integer b) { - Integer c = a+b; -// d = a-b; -// e = a*b; -// f = a/b; - - return c; - } -} \ No newline at end of file diff --git a/test/bytecode/OpTest.java b/test/bytecode/OpTest.java index cd8fee06..1d213a78 100644 --- a/test/bytecode/OpTest.java +++ b/test/bytecode/OpTest.java @@ -1,7 +1,61 @@ package bytecode; -public class OpTest extends JavaTXCompilerTest { - public OpTest() { - this.fileName = "Op"; +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.objectweb.asm.Opcodes; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class OpTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Op.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Op"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); } + + @Test + public void testAddString() throws NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException, InstantiationException { + + Method m = classToTest.getDeclaredMethod("m", String.class,String.class); + + String result = (String) m.invoke(instanceOfClass, "Byte","Code"); + + assertEquals("ByteCode", result); + } + + @Test + public void testAddInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException, InstantiationException { + + Method m = classToTest.getDeclaredMethod("m", Integer.class,Integer.class); + + Integer result = (Integer) m.invoke(instanceOfClass, 7,3); + + assertEquals(10, result); + } + + } diff --git a/test/bytecode/OverlaodGenTest.java b/test/bytecode/OverlaodGenTest.java deleted file mode 100644 index 72bde4f9..00000000 --- a/test/bytecode/OverlaodGenTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class OverlaodGenTest extends JavaTXCompilerTest { - public OverlaodGenTest() { - this.fileName = "OverlaodGen"; - } -} diff --git a/test/bytecode/OverloadingTest.java b/test/bytecode/OverloadingTest.java new file mode 100644 index 00000000..294bf533 --- /dev/null +++ b/test/bytecode/OverloadingTest.java @@ -0,0 +1,57 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class OverloadingTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + private static Class classOL2; + private static Object instanceOfClassOL2; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Overloading.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Overloading"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + classOL2 = loader.loadClass("Overloading2"); + instanceOfClassOL2 = classOL2.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method meth = classToTest.getDeclaredMethod("test", classToTest); + String res = (String) meth.invoke(instanceOfClass, instanceOfClass); + assertEquals("Overloading", res); + } + + @Test + public void test2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method meth = classToTest.getDeclaredMethod("test", classOL2); + String res = (String) meth.invoke(instanceOfClass, instanceOfClassOL2); + assertEquals("Overloading2", res); + } + +} diff --git a/test/bytecode/PlusTest.java b/test/bytecode/PlusTest.java new file mode 100644 index 00000000..51503c58 --- /dev/null +++ b/test/bytecode/PlusTest.java @@ -0,0 +1,54 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class PlusTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Plus.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Plus"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testAddInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException, InstantiationException { + Method addInt = classToTest.getDeclaredMethod("m", Integer.class,Integer.class); + Number result = (Number) addInt.invoke(instanceOfClass, 7,3); + assertEquals(10, result); + } + + @Test + public void testAddString() throws NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException, InstantiationException { + Method addString = classToTest.getDeclaredMethod("m", String.class,String.class); + String result = (String) addString.invoke(instanceOfClass, "Byte","Code"); + assertEquals("ByteCode", result); + } + +} diff --git a/test/bytecode/PostIncTest.java b/test/bytecode/PostIncTest.java new file mode 100644 index 00000000..36e63816 --- /dev/null +++ b/test/bytecode/PostIncTest.java @@ -0,0 +1,65 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class PostIncTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/PostIncDec.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("PostIncDec"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testM1() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(1, res); + } + + @Test + public void testM2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(0, res); + } + + @Test + public void testD1() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("d"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(-1, res); + } + + @Test + public void testD2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("d2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(0, res); + } + +} diff --git a/test/bytecode/PreIncTest.java b/test/bytecode/PreIncTest.java new file mode 100644 index 00000000..434b88e1 --- /dev/null +++ b/test/bytecode/PreIncTest.java @@ -0,0 +1,65 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class PreIncTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/PreInc.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://" + pathToClassFile)}); + classToTest = loader.loadClass("PreInc"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testM() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(1, res); + } + + @Test + public void testM2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(1, res); + } + + @Test + public void testD() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("d"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(-1, res); + } + + @Test + public void testD2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("d2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(-1, res); + } + +} diff --git a/test/bytecode/RelOpsTest.java b/test/bytecode/RelOpsTest.java new file mode 100644 index 00000000..06b24630 --- /dev/null +++ b/test/bytecode/RelOpsTest.java @@ -0,0 +1,44 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class RelOpsTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/RelOps.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("RelOps"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", Integer.class,Integer.class); + Boolean result = (Boolean) m.invoke(instanceOfClass, 7,3); + assertFalse(result); + } + +} diff --git a/test/bytecode/StaticTest.java b/test/bytecode/StaticTest.java new file mode 100644 index 00000000..f639645c --- /dev/null +++ b/test/bytecode/StaticTest.java @@ -0,0 +1,41 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class StaticTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/StaticM.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://" + pathToClassFile)}); + classToTest = loader.loadClass("StaticM"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() { + fail("Not yet implemented"); + } + +} diff --git a/test/bytecode/TestIfTest.java b/test/bytecode/TestIfTest.java deleted file mode 100644 index 804a0616..00000000 --- a/test/bytecode/TestIfTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package bytecode; - -public class TestIfTest extends JavaTXCompilerTest{ - public TestIfTest() { - this.fileName = "IfTest"; - } -} diff --git a/test/bytecode/WhileTest.java b/test/bytecode/WhileTest.java new file mode 100644 index 00000000..5690facb --- /dev/null +++ b/test/bytecode/WhileTest.java @@ -0,0 +1,44 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class WhileTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/While.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("While"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", Integer.class); + Integer result = (Integer) m.invoke(instanceOfClass, 0); + assertEquals(2, result); + } + +} diff --git a/test/bytecode/AssignToLit.jav b/test/bytecode/javFiles/AssignToLit.jav similarity index 100% rename from test/bytecode/AssignToLit.jav rename to test/bytecode/javFiles/AssignToLit.jav diff --git a/test/bytecode/javFiles/BinaryInMeth.jav b/test/bytecode/javFiles/BinaryInMeth.jav new file mode 100644 index 00000000..f5a11798 --- /dev/null +++ b/test/bytecode/javFiles/BinaryInMeth.jav @@ -0,0 +1,11 @@ +import java.lang.Integer; +public class BinaryInMeth { + + m(a){ + return ++a; + } + + m2(a,b){ + return m(a+b); + } +} \ No newline at end of file diff --git a/test/bytecode/DuMethod.jav b/test/bytecode/javFiles/DuMethod.jav similarity index 100% rename from test/bytecode/DuMethod.jav rename to test/bytecode/javFiles/DuMethod.jav diff --git a/test/bytecode/EmptyMethod.jav b/test/bytecode/javFiles/EmptyMethod.jav similarity index 100% rename from test/bytecode/EmptyMethod.jav rename to test/bytecode/javFiles/EmptyMethod.jav diff --git a/test/bytecode/Example.jav b/test/bytecode/javFiles/Example.jav similarity index 100% rename from test/bytecode/Example.jav rename to test/bytecode/javFiles/Example.jav diff --git a/test/bytecode/Exceptions.jav b/test/bytecode/javFiles/Exceptions.jav similarity index 100% rename from test/bytecode/Exceptions.jav rename to test/bytecode/javFiles/Exceptions.jav diff --git a/test/bytecode/javFiles/Fac.jav b/test/bytecode/javFiles/Fac.jav new file mode 100644 index 00000000..baee231b --- /dev/null +++ b/test/bytecode/javFiles/Fac.jav @@ -0,0 +1,16 @@ +import java.lang.Integer; +import java.lang.Long; +import java.lang.Double; + +public class Fac { + + java.lang.Long getFac(n){ + var res = 1; + var i = 1; + while(i<=n) { + res = res * i; + i++; + } + return res; + } +} \ No newline at end of file diff --git a/test/bytecode/Faculty.jav b/test/bytecode/javFiles/Faculty.jav similarity index 86% rename from test/bytecode/Faculty.jav rename to test/bytecode/javFiles/Faculty.jav index 5742d720..cea028c1 100644 --- a/test/bytecode/Faculty.jav +++ b/test/bytecode/javFiles/Faculty.jav @@ -1,3 +1,5 @@ +import java.lang.Integer; + class Faculty { Integer mul(Integer x, Integer y) { diff --git a/test/bytecode/Faculty2.jav b/test/bytecode/javFiles/Faculty2.jav similarity index 100% rename from test/bytecode/Faculty2.jav rename to test/bytecode/javFiles/Faculty2.jav diff --git a/test/bytecode/For.jav b/test/bytecode/javFiles/For.jav similarity index 100% rename from test/bytecode/For.jav rename to test/bytecode/javFiles/For.jav diff --git a/test/bytecode/Gen.jav b/test/bytecode/javFiles/Gen.jav similarity index 57% rename from test/bytecode/Gen.jav rename to test/bytecode/javFiles/Gen.jav index 1f873919..3b58b188 100644 --- a/test/bytecode/Gen.jav +++ b/test/bytecode/javFiles/Gen.jav @@ -1,5 +1,8 @@ +import java.lang.Integer; +import java.util.Vector; + 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/javFiles/Generics.jav similarity index 100% rename from test/bytecode/Generics.jav rename to test/bytecode/javFiles/Generics.jav diff --git a/test/bytecode/Generics2.jav b/test/bytecode/javFiles/Generics2.jav similarity index 100% rename from test/bytecode/Generics2.jav rename to test/bytecode/javFiles/Generics2.jav diff --git a/test/bytecode/javFiles/GreaterEqual.jav b/test/bytecode/javFiles/GreaterEqual.jav new file mode 100644 index 00000000..3ec69e8a --- /dev/null +++ b/test/bytecode/javFiles/GreaterEqual.jav @@ -0,0 +1,57 @@ +import java.lang.Integer; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; + +public class GreaterEqual { + + gE(Integer a, Integer b){ + var c = a>=b; + return c; + } + + gE(Long a, Long b){ + var c = a>=b; + return c; + } + + gE(Float a, Float b){ + var c = a>=b; + return c; + } + + gE(Double a, Double b){ + var c = a>=b; + return c; + } + + gE(Long a, Integer b){ + var c = a>=b; + return c; + } + + gE(Float a, Integer b){ + var c = a>=b; + return c; + } + + gE(Double a, Integer b){ + var c = a>=b; + return c; + } + + gE(Float a, Long b){ + var c = a>=b; + return c; + } + + gE(Double a, Long b){ + var c = a>=b; + return c; + } + + gE(Double a, Float b){ + var c = a>=b; + return c; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/GreaterThan.jav b/test/bytecode/javFiles/GreaterThan.jav new file mode 100644 index 00000000..9077f5b1 --- /dev/null +++ b/test/bytecode/javFiles/GreaterThan.jav @@ -0,0 +1,56 @@ +import java.lang.Integer; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; + +public class GreaterThan { + gT(Integer a, Integer b){ + var c = a>b; + return c; + } + + gT(Long a, Long b){ + var c = a>b; + return c; + } + + gT(Float a, Float b){ + var c = a>b; + return c; + } + + gT(Double a, Double b){ + var c = a>b; + return c; + } + + gT(Long a, Integer b){ + var c = a>b; + return c; + } + + gT(Float a, Integer b){ + var c = a>b; + return c; + } + + gT(Double a, Integer b){ + var c = a>b; + return c; + } + + gT(Float a, Long b){ + var c = a>b; + return c; + } + + gT(Double a, Long b){ + var c = a>b; + return c; + } + + gT(Double a, Float b){ + var c = a>b; + return c; + } +} \ No newline at end of file diff --git a/test/bytecode/IfTest.jav b/test/bytecode/javFiles/IfTest.jav similarity index 100% rename from test/bytecode/IfTest.jav rename to test/bytecode/javFiles/IfTest.jav diff --git a/test/bytecode/Import.jav b/test/bytecode/javFiles/Import.jav similarity index 100% rename from test/bytecode/Import.jav rename to test/bytecode/javFiles/Import.jav diff --git a/test/bytecode/Interface1.jav b/test/bytecode/javFiles/Interface1.jav similarity index 100% rename from test/bytecode/Interface1.jav rename to test/bytecode/javFiles/Interface1.jav diff --git a/test/bytecode/LamRunnable.jav b/test/bytecode/javFiles/LamRunnable.jav similarity index 100% rename from test/bytecode/LamRunnable.jav rename to test/bytecode/javFiles/LamRunnable.jav diff --git a/test/bytecode/LamAssign.jav b/test/bytecode/javFiles/Lambda.jav similarity index 63% rename from test/bytecode/LamAssign.jav rename to test/bytecode/javFiles/Lambda.jav index 82bb31b1..3aeded25 100644 --- a/test/bytecode/LamAssign.jav +++ b/test/bytecode/javFiles/Lambda.jav @@ -1,6 +1,6 @@ import java.lang.Integer; -class LamAssign { +public class Lambda { m () { var lam1 = (Integer x) -> { @@ -9,7 +9,3 @@ class LamAssign { return lam1; } } - -interface Fun1{ - public A apply(B b); -} \ No newline at end of file diff --git a/test/bytecode/Lambda2.jav b/test/bytecode/javFiles/Lambda2.jav similarity index 90% rename from test/bytecode/Lambda2.jav rename to test/bytecode/javFiles/Lambda2.jav index fbcdaf55..92f32b71 100644 --- a/test/bytecode/Lambda2.jav +++ b/test/bytecode/javFiles/Lambda2.jav @@ -1,3 +1,4 @@ +import java.lang.String; public class Lambda2 { @@ -23,10 +24,12 @@ public static List map(List input, Function func) { } class List{ - A get(); + /* A get(); void add(A); + */ } - +/* class Function{ B apply(A a); -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/test/bytecode/Lambda3.jav b/test/bytecode/javFiles/Lambda3.jav similarity index 100% rename from test/bytecode/Lambda3.jav rename to test/bytecode/javFiles/Lambda3.jav diff --git a/test/bytecode/Lambda.jav b/test/bytecode/javFiles/Lambda4.jav similarity index 100% rename from test/bytecode/Lambda.jav rename to test/bytecode/javFiles/Lambda4.jav diff --git a/test/bytecode/javFiles/LessEqual.jav b/test/bytecode/javFiles/LessEqual.jav new file mode 100644 index 00000000..2e3b7024 --- /dev/null +++ b/test/bytecode/javFiles/LessEqual.jav @@ -0,0 +1,56 @@ +import java.lang.Integer; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; + +public class LessEqual { + lessEqual(Integer a, Integer b){ + var c = a<=b; + return c; + } + + lessEqual(Long a, Long b){ + var c = a<=b; + return c; + } + + lessEqual(Float a, Float b){ + var c = a<=b; + return c; + } + + lessEqual(Double a, Double b){ + var c = a<=b; + return c; + } + + lessEqual(Long a, Integer b){ + var c = a<=b; + return c; + } + + lessEqual(Float a, Integer b){ + var c = a<=b; + return c; + } + + lessEqual(Double a, Integer b){ + var c = a<=b; + return c; + } + + lessEqual(Float a, Long b){ + var c = a<=b; + return c; + } + + lessEqual(Double a, Long b){ + var c = a<=b; + return c; + } + + lessEqual(Double a, Float b){ + var c = a<=b; + return c; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/LessThan.jav b/test/bytecode/javFiles/LessThan.jav new file mode 100644 index 00000000..04e1e83e --- /dev/null +++ b/test/bytecode/javFiles/LessThan.jav @@ -0,0 +1,57 @@ +import java.lang.Integer; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; + +public class LessThan { + + lessThan(Integer a, Integer b){ + var c = a> { + mul(m) { + var ret = new Matrix(); + var i = 0; + while(i < size()) { +// var v1 = this.elementAt(i); +// var v2 = new Vector(); +// var j = 0; +// while(j < v1.size()) { +// var erg = 0; +// var k = 0; +// while(k < v1.size()) { +// erg = erg + v1.elementAt(k) +// * m.elementAt(k).elementAt(j); +// k++; } +// v2.addElement(new Integer(erg)); +// j++; } +// ret.addElement(v2); + i++; + } + return ret; + } +} diff --git a/test/bytecode/Methods.jav b/test/bytecode/javFiles/Methods.jav similarity index 100% rename from test/bytecode/Methods.jav rename to test/bytecode/javFiles/Methods.jav diff --git a/test/bytecode/javFiles/OL.jav b/test/bytecode/javFiles/OL.jav new file mode 100644 index 00000000..6489d572 --- /dev/null +++ b/test/bytecode/javFiles/OL.jav @@ -0,0 +1,21 @@ +import java.lang.Integer; +import java.lang.Double; +import java.lang.String; + + +class OL { + + m(x) { return x + x; } + +} + + +class OLMain { + + main(x) { + var ol; + ol = new OL(); + return ol.m(x); + } +} + diff --git a/test/bytecode/javFiles/Op.jav b/test/bytecode/javFiles/Op.jav new file mode 100644 index 00000000..082f48d8 --- /dev/null +++ b/test/bytecode/javFiles/Op.jav @@ -0,0 +1,16 @@ +import java.lang.Integer; +import java.lang.String; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; +import java.lang.Boolean; +import java.lang.Short; +import java.lang.Byte; + +public class Op { + + m(a, b) { + //var c = a+b; + return a+b; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/Op2.jav b/test/bytecode/javFiles/Op2.jav new file mode 100644 index 00000000..9d446eb2 --- /dev/null +++ b/test/bytecode/javFiles/Op2.jav @@ -0,0 +1,11 @@ +import java.lang.Integer; +import java.lang.String; + +public class Op2 { + m(){ + var x = ""; + var a = 5+x; + + return a; + } +} \ No newline at end of file diff --git a/test/bytecode/OverlaodGen.jav b/test/bytecode/javFiles/OverlaodGen.jav similarity index 100% rename from test/bytecode/OverlaodGen.jav rename to test/bytecode/javFiles/OverlaodGen.jav diff --git a/test/bytecode/javFiles/Overloading.jav b/test/bytecode/javFiles/Overloading.jav new file mode 100644 index 00000000..fb48fe0f --- /dev/null +++ b/test/bytecode/javFiles/Overloading.jav @@ -0,0 +1,18 @@ +import java.lang.String; + +public class Overloading{ + + test(x){ + return x.methode(); + } + + methode(){ + return "Overloading"; + } +} + +public class Overloading2{ + methode(){ + return "Overloading2"; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/Plus.jav b/test/bytecode/javFiles/Plus.jav new file mode 100644 index 00000000..4d425bf0 --- /dev/null +++ b/test/bytecode/javFiles/Plus.jav @@ -0,0 +1,8 @@ +import java.lang.Integer; + +public class Plus { + + m(a,b) { + return a+b; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/PostIncDec.jav b/test/bytecode/javFiles/PostIncDec.jav new file mode 100644 index 00000000..29c2ef17 --- /dev/null +++ b/test/bytecode/javFiles/PostIncDec.jav @@ -0,0 +1,27 @@ +import java.lang.Integer; + +public class PostIncDec { + m() { + var i = 0; + i++; + return i; + } + + m2() { + var i = 0; + var j = i++; + return j; + } + + d() { + var i = 0; + i--; + return i; + } + + d2() { + var i = 0; + var j = i--; + return j; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/PreInc.jav b/test/bytecode/javFiles/PreInc.jav new file mode 100644 index 00000000..011501f1 --- /dev/null +++ b/test/bytecode/javFiles/PreInc.jav @@ -0,0 +1,28 @@ +import java.lang.Integer; + +public class PreInc { + m() { + var i = 0; + ++i; + return i; + } + + m2() { + var i = 0; + var j = ++i; + return j; + } + + d() { + var i = 0; + --i; + return i; + } + + d2() { + var i = 0; + var j = --i; + return j; + } + +} \ No newline at end of file diff --git a/test/bytecode/RecursiveMeth.jav b/test/bytecode/javFiles/RecursiveMeth.jav similarity index 100% rename from test/bytecode/RecursiveMeth.jav rename to test/bytecode/javFiles/RecursiveMeth.jav diff --git a/test/bytecode/javFiles/RelOps.jav b/test/bytecode/javFiles/RelOps.jav new file mode 100644 index 00000000..0fdd2cff --- /dev/null +++ b/test/bytecode/javFiles/RelOps.jav @@ -0,0 +1,8 @@ +import java.lang.Integer; +import java.lang.Boolean; + +public class RelOps { + m(a,b){ + return a Deswegen kann +// nicht auf den Stack geladen. +import java.lang.Long; + +public class While { + Integer m(x) { + while(x < 2) { + x = x+1; + } + return x; + } +} \ No newline at end of file diff --git a/test/javFiles/AddLong.jav b/test/javFiles/AddLong.jav index ceb31228..d6d47e9f 100644 --- a/test/javFiles/AddLong.jav +++ b/test/javFiles/AddLong.jav @@ -2,7 +2,7 @@ import java.lang.Integer; import java.lang.Long; public class AddLong{ - add(Integer a, Long b) { + Long add(Integer a, Long b) { Long c = a+b; return c; } diff --git a/test/javFiles/FC_Matrix.jav b/test/javFiles/FC_Matrix.jav new file mode 100644 index 00000000..75ead472 --- /dev/null +++ b/test/javFiles/FC_Matrix.jav @@ -0,0 +1,10 @@ +import java.util.Vector; + +class Matrix extends Vector> { + + methode(m) { + m.add(1); + Matrix i; + methode(i); + } + } diff --git a/test/javFiles/Lambda.jav b/test/javFiles/Lambda.jav index 378eb4d3..553dc496 100644 --- a/test/javFiles/Lambda.jav +++ b/test/javFiles/Lambda.jav @@ -1,18 +1,13 @@ -class Lambda{ +import java.lang.Integer; +import java.lang.Number; -methode(){ - return ((f) -> f); -} -} -/* -interface Fun0{ - A apply(); +public class Lambda { + + m () { + var lam1 = (x) -> { + return x; + }; + return lam1; + } } -interface Fun1{ - A apply(B b); -} -*/ -interface Fun2{ - A apply(B b, C c); -} \ No newline at end of file diff --git a/test/javFiles/Lambda2.jav b/test/javFiles/Lambda2.jav index fbcdaf55..cf1e910b 100644 --- a/test/javFiles/Lambda2.jav +++ b/test/javFiles/Lambda2.jav @@ -1,3 +1,4 @@ +import java.lang.String; public class Lambda2 { diff --git a/test/javFiles/Lambda3.jav b/test/javFiles/Lambda3.jav index 9c4e960c..9e22f302 100644 --- a/test/javFiles/Lambda3.jav +++ b/test/javFiles/Lambda3.jav @@ -1,3 +1,4 @@ +import java.lang.String; public class Lambda2 { diff --git a/test/javFiles/LambdaField.jav b/test/javFiles/LambdaField.jav new file mode 100644 index 00000000..4eb53738 --- /dev/null +++ b/test/javFiles/LambdaField.jav @@ -0,0 +1,6 @@ +public class LambdaField { + + f = x -> x; + +} + diff --git a/test/javFiles/Matrix.jav b/test/javFiles/Matrix.jav index aa8966c9..4c55c410 100644 --- a/test/javFiles/Matrix.jav +++ b/test/javFiles/Matrix.jav @@ -1,26 +1,28 @@ import java.util.Vector; import java.lang.Integer; -import java.lang.Boolean; class Matrix extends Vector> { + Integer mul1(Integer x, Integer y) { return x;} + Integer add1(Integer x, Integer y) { return x;} mul(m) { var ret = new Matrix(); var i = 0; - //while(i < size()) { + while(i < size()) { var v1 = this.elementAt(i); - //var v2 = new Vector(); - //var j = 0; - //while(j < v1.size()) { - //var erg = 0; - //var k = 0; - //while(k < v1.size()) { - //erg = erg + v1.elementAt(k) - // * m.elementAt(k).elementAt(j); - //k++; } - //v2.addElement(new Integer(erg)); - //j++; } - //ret.addElement(v2); - //i++; } + var v2 = new Vector(); + var j = 0; + while(j < v1.size()) { + var erg = 0; + var k = 0; + while(k < v1.size()) { + erg = erg + v1.elementAt(k) * m.elementAt(k).elementAt(j); + // erg = add1(erg, mul1(v1.elementAt(k), + // m.elementAt(k).elementAt(j))); + k++; } + v2.addElement(new Integer(erg)); + j++; } + ret.addElement(v2); + i++; } return ret; } } diff --git a/test/javFiles/Meth_Gen.jav b/test/javFiles/Meth_Gen.jav new file mode 100644 index 00000000..056dd82f --- /dev/null +++ b/test/javFiles/Meth_Gen.jav @@ -0,0 +1,11 @@ +class Meth_Gen { + + m1(x, y) { + m2(x); + x = y; + } + + m2(y) { + m1(y, y); + } +} \ No newline at end of file diff --git a/test/parser/PackageNameTest.jav b/test/parser/PackageNameTest.jav new file mode 100644 index 00000000..53c889b7 --- /dev/null +++ b/test/parser/PackageNameTest.jav @@ -0,0 +1,9 @@ +import java.lang.Integer; +import java.lang.Comparable; + +class PackageNameTest{ +java.lang.Integer test(a){return a;} + +Comparable test2(a){return a;} + +} \ No newline at end of file diff --git a/test/typeinference/JavaTXCompilerTest.java b/test/typeinference/JavaTXCompilerTest.java index ba004cb5..122f2359 100644 --- a/test/typeinference/JavaTXCompilerTest.java +++ b/test/typeinference/JavaTXCompilerTest.java @@ -104,7 +104,11 @@ public class JavaTXCompilerTest { // //filesToTest.add(new File(rootDirectory+"mathStruc.jav")); // //filesToTest.add(new File(rootDirectory+"test.jav")); JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); - + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + } List results = compiler.typeInference(); for(File f : compiler.sourceFiles.keySet()){ diff --git a/test/typeinference/Meth_GenTest.java b/test/typeinference/Meth_GenTest.java new file mode 100644 index 00000000..f5e64f9f --- /dev/null +++ b/test/typeinference/Meth_GenTest.java @@ -0,0 +1,139 @@ +package typeinference; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +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; + +public class Meth_GenTest { + + public static final String rootDirectory = System.getProperty("user.dir")+"/test/javFiles/"; +/* + @Test + public void finiteClosure() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"fc.jav")); + } + @Test + public void lambda() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda.jav")); + } + @Test + public void lambda2() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda2.jav")); + } + @Test + public void lambda3() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda3.jav")); + } + @Test + public void mathStruc() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"mathStruc.jav")); + } + @Test + public void generics() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Generics.jav")); + } + + @Test + public void faculty() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Faculty.jav")); + } + + @Test + public void facultyTyped() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"FacultyTyped.jav")); + } +*/ + @Test + public void matrix() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Meth_Gen.jav")); + } +/* + @Test + public void vector() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Vector.jav")); + } + @Test + public void lambdaRunnable() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"LambdaRunnable.jav")); + } + @Test + public void expressions() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Expressions.jav")); + } + @Test + public void matrixFC() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"FC_Matrix.jav")); + } +*/ + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException { + //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")); + // //filesToTest.add(new File(rootDirectory+"Faculty.jav")); + // //filesToTest.add(new File(rootDirectory+"mathStruc.jav")); + // //filesToTest.add(new File(rootDirectory+"test.jav")); + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + } + List results = compiler.typeInference(); + + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.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){ + insertedTypes.add(tip.insert(content)); + } + } + for(String s : insertedTypes){ + System.out.println(s); + } + } + return new TestResultSet(); + } + + 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/typeinference/UnifyTest.java b/test/typeinference/UnifyTest.java new file mode 100644 index 00000000..2a496166 --- /dev/null +++ b/test/typeinference/UnifyTest.java @@ -0,0 +1,158 @@ +package typeinference; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +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; + +public class UnifyTest { + + public static final String rootDirectory = System.getProperty("user.dir")+"/test/javFiles/"; +/* + @Test + public void finiteClosure() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"fc.jav")); + } + */ +/* + @Test + public void lambda() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda.jav")); + } +*/ + /* + @Test + public void lambda2() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda2.jav")); + } + */ +/* + @Test + public void lambda3() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda3.jav")); + } + + @Test + public void lambdafield() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"LambdaField.jav")); + } + + @Test + public void mathStruc() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"mathStruc.jav")); + } + @Test + public void generics() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Generics.jav")); + } +*/ +/* + @Test + public void faculty() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Faculty.jav")); + } +*/ +/* + @Test + public void facultyTyped() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"FacultyTyped.jav")); + } + */ + + + @Test + public void matrix() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Matrix.jav")); + //JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"Matrix.jav")); + //compiler.generateBytecode(); + } + +/* + @Test + public void vector() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Vector.jav")); + } + @Test + public void lambdaRunnable() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"LambdaRunnable.jav")); + } + @Test + public void expressions() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Expressions.jav")); + } + @Test + public void matrixFC() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"FC_Matrix.jav")); + } +*/ + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException { + //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")); + // //filesToTest.add(new File(rootDirectory+"Faculty.jav")); + // //filesToTest.add(new File(rootDirectory+"mathStruc.jav")); + // //filesToTest.add(new File(rootDirectory+"test.jav")); + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + } + List results = compiler.typeInference(); + + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.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){ + insertedTypes.add(tip.insert(content)); + } + } + for(String s : insertedTypes){ + System.out.println(s); + } + } + return new TestResultSet(); + } + + static String readFile(String path, Charset encoding) + throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } + +} +