From dce3ed8051e14320dbe9353b8d08609696f693e4 Mon Sep 17 00:00:00 2001
From: Daniel Holle <dholle@hb.dhbw-stuttgart.de>
Date: Thu, 1 Jun 2023 16:13:03 +0200
Subject: [PATCH] Some fixes for the plugin

---
 resources/javFiles/OL.jav                     | 16 ++++++
 .../de/dhbwstuttgart/bytecode/Codegen.java    |  2 -
 .../dhbwstuttgart/bytecode/FunNGenerator.java | 32 ++++++------
 .../de/dhbwstuttgart/core/JavaTXCompiler.java | 16 ++++--
 .../environment/CompilationEnvironment.java   |  1 +
 .../target/generate/ASTToTargetAST.java       | 49 +++++++++++++------
 .../typedeployment/TypeInsertFactory.java     |  5 +-
 src/test/java/targetast/TestComplete.java     |  6 +++
 8 files changed, 90 insertions(+), 37 deletions(-)
 create mode 100644 resources/javFiles/OL.jav

diff --git a/resources/javFiles/OL.jav b/resources/javFiles/OL.jav
new file mode 100644
index 00000000..66c72d53
--- /dev/null
+++ b/resources/javFiles/OL.jav
@@ -0,0 +1,16 @@
+import java.lang.Integer;
+import java.lang.Double;
+import java.lang.String;
+import java.lang.Long;
+
+class OL {
+    m (x) { return x + x; }
+}
+
+class OLMain {
+	main(x) {
+		var ol;
+		ol = new OL();
+		return ol.m(x);
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java
index 34dcd929..156a10d7 100644
--- a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java
+++ b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java
@@ -1030,8 +1030,6 @@ public class Codegen {
             mv.visitAttribute(new JavaTXSignatureAttribute(method.getTXSignature()));
         }
 
-        System.out.println(method.getDescriptor());
-        System.out.println(method.getSignature());
         mv.visitCode();
         var state = new State(method.signature().returnType(), mv, method.isStatic() ? 0 : 1);
         for (var param: method.signature().parameters())
diff --git a/src/main/java/de/dhbwstuttgart/bytecode/FunNGenerator.java b/src/main/java/de/dhbwstuttgart/bytecode/FunNGenerator.java
index bf4c6730..ac1dbd84 100644
--- a/src/main/java/de/dhbwstuttgart/bytecode/FunNGenerator.java
+++ b/src/main/java/de/dhbwstuttgart/bytecode/FunNGenerator.java
@@ -6,10 +6,7 @@ import org.objectweb.asm.ClassWriter;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Type;
 
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -31,23 +28,31 @@ public class FunNGenerator {
     private static final String objectSuperType = Type.getInternalName(Object.class).replace('.','/');
     private static final String objectSignature = applySignature(TargetType.Object);
 
+    public static class GenericParameters {
+        int start;
+        public List<TargetType> parameters = new ArrayList<>();
+    }
 
-    private static String applyDescriptor(TargetType type, int[] start) {
+    private static String applyDescriptor(TargetType type, GenericParameters gep) {
         var res = "L" + type.getInternalName();
-        if (type instanceof TargetSpecializedType a)
+        if (type instanceof TargetSpecializedType a) {
             if (a.params().size() > 0) {
                 res += "<";
                 for (var param : a.params()) {
                     if (param instanceof TargetGenericType gp) {
-                        res += "TT" + start[0] + ";";
-                        start[0] += 1;
+                        gep.parameters.add(param);
+                        res += "TT" + gep.start + ";";
+                        gep.start += 1;
                     } else {
-                        res += applyDescriptor(param, start);
+                        res += applyDescriptor(param, gep);
                     }
                 }
                 res += ">";
             }
-        else return type.toDescriptor();
+        } else {
+            gep.parameters.add(null);
+            return type.toDescriptor();
+        }
         res += ";";
 
         return res;
@@ -85,17 +90,16 @@ public class FunNGenerator {
         return String.format("Fun%d$$", numberArguments);
     }
 
-    public static byte[] generateSpecializedBytecode(List<TargetType> argumentTypes, TargetType returnType) {
+    public static byte[] generateSpecializedBytecode(List<TargetType> argumentTypes, TargetType returnType, GenericParameters gep) {
         List<TargetType> parameters = Stream
                 .concat(argumentTypes.stream(), Stream.of(returnType))
                 .toList();
 
-        var start = new int[]{0};
-        StringBuilder funNClassSignature = new StringBuilder(objectSignature + applyDescriptor(new TargetRefType(getSuperClassName(argumentTypes.size()), parameters), start));
+        StringBuilder funNClassSignature = new StringBuilder(objectSignature + applyDescriptor(new TargetRefType(getSuperClassName(argumentTypes.size()), parameters), gep));
         boolean containsGeneric = false;
 
         String genericSignature = "<";
-        for (var i = 0; i < start[0]; i++) {
+        for (var i = 0; i < gep.start; i++) {
             genericSignature += String.format("T%d:%s", i, objectSignature);
             containsGeneric = true;
         }
diff --git a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java
index 7e802569..19d32cc5 100644
--- a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java
+++ b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java
@@ -548,7 +548,17 @@ public class JavaTXCompiler {
 			SourceFile sf = sourceFiles.get(f);
 			allClasses.addAll(getAvailableClasses(sf));
 			allClasses.addAll(sf.getClasses());
-			allClasses.addAll(CompilationEnvironment.loadDefaultPackageClasses(f,classLoader).stream().map(ASTFactory::createClass).collect(Collectors.toList()));
+			var newClasses = CompilationEnvironment.loadDefaultPackageClasses(f,classLoader).stream().map(ASTFactory::createClass).collect(Collectors.toList());
+			for (var clazz : newClasses) {
+				var found = false;
+				for (var old : allClasses) {
+					if (clazz.getClassName().equals(old.getClassName())) {
+						found = true;
+						break;
+					}
+				}
+				if (!found) newClasses.add(clazz);
+			}
 		}
 
 		final ConstraintSet<Pair> cons = getConstraints();
@@ -883,7 +893,7 @@ public class JavaTXCompiler {
 		}
 	}
 
-	public Map<JavaClassName, byte[]> generateBytecode(SourceFile sf, List<ResultSet> typeInferenceResult) {
+	public synchronized Map<JavaClassName, byte[]> generateBytecode(SourceFile sf, List<ResultSet> typeInferenceResult) {
 		var converter = new ASTToTargetAST(typeInferenceResult, sf, classLoader);
 		var generatedClasses = new HashMap<JavaClassName, byte[]>();
 		for (var clazz : sf.getClasses()) {
@@ -898,7 +908,7 @@ public class JavaTXCompiler {
 		return generatedClasses;
 	}
 
-	public void writeClassFile(Map<JavaClassName, byte[]> classFiles, File path) throws IOException {
+	public synchronized void writeClassFile(Map<JavaClassName, byte[]> classFiles, File path) throws IOException {
 		FileOutputStream output;
 		for (JavaClassName name : classFiles.keySet()) {
 			byte[] bytecode = classFiles.get(name);
diff --git a/src/main/java/de/dhbwstuttgart/environment/CompilationEnvironment.java b/src/main/java/de/dhbwstuttgart/environment/CompilationEnvironment.java
index 746d1e85..9ca471cb 100644
--- a/src/main/java/de/dhbwstuttgart/environment/CompilationEnvironment.java
+++ b/src/main/java/de/dhbwstuttgart/environment/CompilationEnvironment.java
@@ -84,6 +84,7 @@ public class CompilationEnvironment {
 		File [] files = dir.listFiles((dir1, name) -> name.endsWith(".class"));
 		if(files != null)for (File classFile : files) {
 			String className = classFile.getName().substring(0,classFile.getName().length()-6);
+			if (className.matches("Fun\\d+\\$\\$.*")) continue;
 			ret.add(classLoader.loadClass(packageName + className));
         }
 		return ret;
diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java
index 7fb10f76..7be48f1d 100644
--- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java
+++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java
@@ -1111,7 +1111,6 @@ public class ASTToTargetAST {
                 parameterSet.add(params);
             }
         }
-
         return result;
     }
 
@@ -1133,7 +1132,7 @@ public class ASTToTargetAST {
         );
     }
 
-    private final Set<String> usedFunN = new HashSet<>();
+    private final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
     private final Set<Integer> usedFunNSuperTypes = new HashSet<>();
 
     public Map<String, byte[]> auxiliaries = new HashMap<>();
@@ -1142,17 +1141,33 @@ public class ASTToTargetAST {
         return convert(input, generics.javaGenerics);
     }
 
-    static TargetType flattenFunNType(List<TargetType> params) {
-        var newParams = new ArrayList<TargetType>();
-        for (var i = 0; i < params.size(); i++) {
-            var param = params.get(i);
+    private static void collectArguments(TargetSpecializedType tspec, List<TargetType> newParams) {
+        for (var i = 0; i < tspec.params().size(); i++) {
+            var param = tspec.params().get(i);
             if (param instanceof TargetSpecializedType fn) {
-                newParams.addAll(fn.params());
+                collectArguments(tspec, newParams);
             } else {
                 newParams.add(param);
             }
         }
-        return TargetFunNType.fromParams(params, newParams);
+    }
+
+    static TargetType flattenFunNType(List<TargetType> params, FunNGenerator.GenericParameters gep) {
+        var newParams = new ArrayList<TargetType>();
+        for (var i = 0; i < params.size(); i++) {
+            var param = params.get(i);
+            if (param instanceof TargetSpecializedType fn) {
+                collectArguments(fn, newParams);
+            } else {
+                newParams.add(param);
+            }
+        }
+        var filteredParams = new ArrayList<TargetType>();
+        for (var i = 0; i < newParams.size(); i++) {
+            if (gep.parameters.get(i) != null)
+                filteredParams.add(newParams.get(i));
+        }
+        return TargetFunNType.fromParams(params, filteredParams);
     }
 
     protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
@@ -1168,16 +1183,18 @@ public class ASTToTargetAST {
                     if (!usedFunNSuperTypes.contains(params.size())) {
                         usedFunNSuperTypes.add(params.size());
                         var code = FunNGenerator.generateSuperBytecode(params.size() - 1);
-                        var clazz = classLoader.loadClass(code);
-                        auxiliaries.put(clazz.getName(), code);
+                        auxiliaries.put(FunNGenerator.getSuperClassName(params.size() - 1), code);
                     }
-                    if (!usedFunN.contains(className)) {
-                        usedFunN.add(className);
-                        var code = FunNGenerator.generateSpecializedBytecode(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params));
-                        var clazz = classLoader.loadClass(code);
-                        auxiliaries.put(clazz.getName(), code);
+                    FunNGenerator.GenericParameters gep = null;
+                    if (!usedFunN.containsKey(className)) {
+                        gep = new FunNGenerator.GenericParameters();
+                        var code = FunNGenerator.generateSpecializedBytecode(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params), gep);
+                        usedFunN.put(className, gep);
+                        auxiliaries.put(className, code);
+                    } else {
+                        gep = usedFunN.get(className);
                     }
-                    return flattenFunNType(params);
+                    return flattenFunNType(params, gep);
                 }
                 return new TargetRefType(name, params);
             }
diff --git a/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java b/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java
index be49fde2..660fc494 100644
--- a/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java
+++ b/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java
@@ -190,9 +190,10 @@ class TypeToInsertString implements ResultSetVisitor{
         if (constraints != null)
             resultPair = constraints.getResultPairFor(typePlaceholder).orElse(null);
         if (resultPair == null)
-            resultPair = classConstraints.getResultPairFor(typePlaceholder).get();
+            resultPair = classConstraints.getResultPairFor(typePlaceholder).orElse(null);
 
-        insert += ((TypePlaceholder)resultPair.getLeft()).getName();
+        if (resultPair != null)
+            insert += ((TypePlaceholder)resultPair.getLeft()).getName();
     }
 
     @Override
diff --git a/src/test/java/targetast/TestComplete.java b/src/test/java/targetast/TestComplete.java
index a5c56828..d5f6d455 100644
--- a/src/test/java/targetast/TestComplete.java
+++ b/src/test/java/targetast/TestComplete.java
@@ -635,4 +635,10 @@ public class TestComplete {
         var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Pair.jav");
         var instance = classFiles.get("Pair").getDeclaredConstructor().newInstance();
     }
+
+    @Test
+    public void olTest() throws Exception {
+        var classFiles = generateClassFiles(new ByteArrayClassLoader(), "OL.jav");
+        var instance = classFiles.get("OL").getDeclaredConstructor().newInstance();
+    }
 }