diff --git a/pom.xml b/pom.xml index f356ce82..120f4204 100644 --- a/pom.xml +++ b/pom.xml @@ -29,14 +29,14 @@ http://maven.apache.org/maven-v4_0_0.xsd"> 2.6 - com.google.guava - guava - 22.0 + io.github.classgraph + classgraph + 4.8.172 - org.reflections - reflections - 0.9.11 + com.google.guava + guava + 33.2.0-jre diff --git a/resources/AllgemeinTest/Box.jav b/resources/AllgemeinTest/Box.jav new file mode 100644 index 00000000..b2716354 --- /dev/null +++ b/resources/AllgemeinTest/Box.jav @@ -0,0 +1,8 @@ +class Box { + + A a; + + public Box(A a) { + this.a = a; + } +} \ No newline at end of file diff --git a/resources/bytecode/javFiles/Box.jav b/resources/bytecode/javFiles/Box.jav index 4859d611..95b869ab 100644 --- a/resources/bytecode/javFiles/Box.jav +++ b/resources/bytecode/javFiles/Box.jav @@ -1,7 +1,9 @@ -class B { } -class Box_Main extends B { - m(b) { - b.m(new Box_Main()); - b.m(new B()); - } -} +public class Box { + + A a; + + public Box() { } + public Box(A a) { + //this.a = a; + } +} \ No newline at end of file diff --git a/resources/bytecode/javFiles/Bug325.jav b/resources/bytecode/javFiles/Bug325.jav new file mode 100644 index 00000000..6a3a29b1 --- /dev/null +++ b/resources/bytecode/javFiles/Bug325.jav @@ -0,0 +1,13 @@ +import java.lang.Integer; +import java.util.function.Function; +import java.util.List; +import java.util.ArrayList; +import java.util.stream.Stream; + +public class Bug325 { + public main() { + List list = new ArrayList<>(List.of(1,2,3,4,5)); + var func = x -> x*2; + return list.stream().map(func).toList(); + } +} \ No newline at end of file diff --git a/resources/bytecode/javFiles/Bug326.jav b/resources/bytecode/javFiles/Bug326.jav new file mode 100644 index 00000000..6329fe6b --- /dev/null +++ b/resources/bytecode/javFiles/Bug326.jav @@ -0,0 +1,8 @@ +import java.lang.Integer; + +public class Bug326 { + public Bug326() { + var func = x -> y -> x * y; + return func.apply(3).apply(4); + } +} diff --git a/resources/bytecode/javFiles/Bug328.jav b/resources/bytecode/javFiles/Bug328.jav new file mode 100644 index 00000000..c2cc1dbb --- /dev/null +++ b/resources/bytecode/javFiles/Bug328.jav @@ -0,0 +1,8 @@ +import java.lang.Integer; +import Bug328B; + +public class Bug328 extends Bug328B { + public Bug328() { + super(1); + } +} \ No newline at end of file diff --git a/resources/bytecode/javFiles/Bug328B.class b/resources/bytecode/javFiles/Bug328B.class new file mode 100644 index 00000000..f8ff35fa Binary files /dev/null and b/resources/bytecode/javFiles/Bug328B.class differ diff --git a/resources/bytecode/javFiles/Bug328B.java b/resources/bytecode/javFiles/Bug328B.java new file mode 100644 index 00000000..1859d218 --- /dev/null +++ b/resources/bytecode/javFiles/Bug328B.java @@ -0,0 +1,3 @@ +public class Bug328B { + public Bug328B(int a) {} +} diff --git a/resources/bytecode/javFiles/Bug333.jav b/resources/bytecode/javFiles/Bug333.jav new file mode 100644 index 00000000..244e8a66 --- /dev/null +++ b/resources/bytecode/javFiles/Bug333.jav @@ -0,0 +1,11 @@ +import java.lang.String; + +public class Bug333 { + public static String Bar = "Bar"; +} + +class Bar { + public bar() { + String s = Bug333.Bar; + } +} \ No newline at end of file diff --git a/resources/bytecode/javFiles/ImportWildcard.jav b/resources/bytecode/javFiles/ImportWildcard.jav new file mode 100644 index 00000000..a64e9ae2 --- /dev/null +++ b/resources/bytecode/javFiles/ImportWildcard.jav @@ -0,0 +1,5 @@ +import java.lang.*; + +public class ImportWildcard { + m(a, b) { return a * b; } +} \ No newline at end of file diff --git a/resources/bytecode/javFiles/Matrix.jav b/resources/bytecode/javFiles/Matrix.jav index 35d65d51..63bd8bb4 100644 --- a/resources/bytecode/javFiles/Matrix.jav +++ b/resources/bytecode/javFiles/Matrix.jav @@ -1,3 +1,5 @@ +import java.util.List; +import java.util.AbstractList; import java.util.Vector; import java.lang.Integer; //import java.lang.Float; @@ -30,8 +32,8 @@ public class Matrix extends Vector> { var erg = 0; var k = 0; while(k < v1.size()) { - erg = erg + v1.elementAt(k) - * m.elementAt(k).elementAt(j); + erg = erg + v1.get(k) + * m.get(k).get(j); k++; } // v2.addElement(new Integer(erg)); v2.addElement(erg); diff --git a/resources/bytecode/javFiles/While.jav b/resources/bytecode/javFiles/While.jav index df259cf5..cdd41f51 100644 --- a/resources/bytecode/javFiles/While.jav +++ b/resources/bytecode/javFiles/While.jav @@ -9,4 +9,13 @@ public class While { } return x; } + + public m2() { + int i = 0; + do { + ++i; + } while(i < 10); + + return i; + } } \ 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 ee39830a..8df566b9 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java @@ -784,9 +784,12 @@ public class Codegen { var descriptor = TargetMethod.getDescriptor(state.contextType, params.toArray(TargetType[]::new)); mv.visitVarInsn(ALOAD, 0); - for (var capture : lambda.captures()) { + for (var index = 0; index < lambda.captures().size(); index++) { + var capture = lambda.captures().get(index); var pattern = (TargetTypePattern) capture.pattern(); - mv.visitVarInsn(ALOAD, state.scope.get(pattern.name()).index); + var variable = state.scope.get(pattern.name()); + mv.visitVarInsn(ALOAD, variable.index); + mv.visitTypeInsn(CHECKCAST, capture.pattern().type().getInternalName()); } mv.visitInvokeDynamicInsn(methodName, descriptor, bootstrap, Type.getType(signature.getSignature()), handle, Type.getType(signature.getDescriptor())); @@ -975,6 +978,27 @@ public class Codegen { mv.visitLabel(end); break; } + case TargetDo _do: { + Label start = new Label(); + Label end = new Label(); + Label check = new Label(); + + var env = new BreakEnv(); + env.startLabel = check; + env.endLabel = end; + + mv.visitLabel(start); + state.breakStack.push(env); + generate(state, _do.body()); + state.breakStack.pop(); + + mv.visitLabel(check); + generate(state, _do.cond()); + mv.visitJumpInsn(IFEQ, end); + mv.visitJumpInsn(GOTO, start); + mv.visitLabel(end); + break; + } case TargetIf _if: { generate(state, _if.cond()); Label _else = new Label(); diff --git a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java index a77ff228..62d69b16 100644 --- a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -66,7 +66,7 @@ public class JavaTXCompiler { Boolean resultmodel = true; public final Map sourceFiles = new HashMap<>(); - Boolean log = false; //gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll? + Boolean log = true; //gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll? public volatile UnifyTaskModel usedTasks = new UnifyTaskModel(); public final DirectoryClassLoader classLoader; @@ -98,7 +98,7 @@ public class JavaTXCompiler { } if (outputPath != null) path.add(outputPath); classLoader = new DirectoryClassLoader(path, ClassLoader.getSystemClassLoader()); - environment = new CompilationEnvironment(sources); + environment = new CompilationEnvironment(sources, classLoader); classPath = path; this.outputPath = outputPath; @@ -207,7 +207,7 @@ public class JavaTXCompiler { cl.getMethods().add(new Method(m.modifier, m.name, m.getReturnType().acceptTV(new TypeExchanger(gtvs)), newParaList, m.block, // new GenericDeclarationList(newGenericsList, // ((GenericDeclarationList)m.getGenerics()).getOffset()), - (GenericDeclarationList) m.getGenerics(), m.getOffset(), true)); + (GenericDeclarationList) m.getGenerics(), m.getOffset(), true, false)); } } @@ -666,6 +666,7 @@ public class JavaTXCompiler { public final Map loadedClasses = new HashMap<>(); private SourceFile parse(File sourceFile) throws IOException, java.lang.ClassNotFoundException { + if (sourceFiles.containsKey(sourceFile)) return sourceFiles.get(sourceFile); SourceFileContext tree = JavaTXParser.parse(sourceFile); environment.addClassesToRegistry(classRegistry, tree, sourceFile, this); SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), sourceFile.getName()); @@ -740,7 +741,9 @@ public class JavaTXCompiler { var sf = sourceFiles.get(sourceFile); if (sf.isGenerated()) return null; List typeinferenceResult = this.typeInference(sourceFile); - return generateBytecode(sf, typeinferenceResult); + var classes = generateBytecode(sf, typeinferenceResult); + sf.setGenerated(); + return classes; } private Map> generatedGenerics = new HashMap<>(); diff --git a/src/main/java/de/dhbwstuttgart/environment/CompilationEnvironment.java b/src/main/java/de/dhbwstuttgart/environment/CompilationEnvironment.java index 4b802fe5..ad16e766 100644 --- a/src/main/java/de/dhbwstuttgart/environment/CompilationEnvironment.java +++ b/src/main/java/de/dhbwstuttgart/environment/CompilationEnvironment.java @@ -34,7 +34,7 @@ public class CompilationEnvironment { * * @param sourceFiles die zu kompilierenden Dateien */ - public CompilationEnvironment(List sourceFiles) { + public CompilationEnvironment(List sourceFiles, DirectoryClassLoader classLoader) { /** * Java 9 bringt einige Änderungen am Classloader So funktioniert der BootClassLoader nicht mehr. hier gibts ein paar Quellen zum nachlesen: http://java9.wtf/class-loading/ https://stackoverflow.com/questions/46494112/classloaders-hierarchy-in-java-9 * @@ -54,7 +54,7 @@ public class CompilationEnvironment { // librarys = Arrays.asList(loader.getURLs()); this.sourceFiles = sourceFiles; - this.packageCrawler = new PackageCrawler(librarys); + this.packageCrawler = new PackageCrawler(classLoader); } public void addClassesToRegistry(JavaClassRegistry registry, SourceFileContext tree, File sourceFile, JavaTXCompiler compiler) throws ClassNotFoundException, IOException { @@ -104,12 +104,4 @@ public class CompilationEnvironment { return packageName; } - public List getAllAvailableClasses() { - List ret = new ArrayList<>(); - for (Class c : new PackageCrawler(librarys).getAllAvailableClasses()) { - ret.add(ASTFactory.createClass(c)); - } - return ret; - } - } diff --git a/src/main/java/de/dhbwstuttgart/environment/DirectoryClassLoader.java b/src/main/java/de/dhbwstuttgart/environment/DirectoryClassLoader.java index f3d87641..8fba019a 100644 --- a/src/main/java/de/dhbwstuttgart/environment/DirectoryClassLoader.java +++ b/src/main/java/de/dhbwstuttgart/environment/DirectoryClassLoader.java @@ -5,31 +5,61 @@ import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; -import java.nio.file.Files; -import java.nio.file.Path; +import java.nio.file.*; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class DirectoryClassLoader extends URLClassLoader implements IByteArrayClassLoader { - public DirectoryClassLoader(File directory, java.lang.ClassLoader parent) { - super(generateURLArray(dirToURL(directory)), parent); - } +// public DirectoryClassLoader(File directory, java.lang.ClassLoader parent) { +// super(generateURLArray(dirToURL(directory)), parent); +// } public DirectoryClassLoader(List directory, java.lang.ClassLoader parent) { - super(directory.stream().map(DirectoryClassLoader::dirToURL).collect(Collectors.toList()).toArray(new URL[0]), parent); + super(directory.stream().map(DirectoryClassLoader::dirToURL).flatMap(List::stream).collect(Collectors.toList()).toArray(new URL[0]), parent.getParent()); } private static URL[] generateURLArray(URL url) { return new URL[]{url}; } - private static URL dirToURL(File url){ - if(!url.isDirectory())throw new RuntimeException(url.toString() + " is not a directory"); - try { - return url.toURI().toURL(); - } catch (MalformedURLException e) { - throw new RuntimeException(e); + private static List dirToURL(File file) { + //if(!url.isDirectory())throw new RuntimeException(url.toString() + " is not a directory"); + + Path dir; + if (file.isDirectory()) { + try { + return List.of(file.toURI().toURL()); // if file is a directory, use it as is + } catch (MalformedURLException e) { + e.printStackTrace(); + return List.of(); + } } + + dir = file.toPath().getParent(); // if file is not a directory, get its parent directory + String pattern = file.toPath().getFileName().toString(); // use the file name as a glob pattern + + List urls = new ArrayList<>(); + + try { + urls = Files.walk(dir) + .filter(Files::isRegularFile) // only consider files (not directories) + .filter(path -> { + PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern); + return matcher.matches(path.getFileName()); // match the file name against the pattern + }) + .map(path -> { + try { + return path.toUri().toURL(); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + }) // convert the path to a URL + .toList(); // print the path of each matching file + } catch (IOException | RuntimeException e) { + e.printStackTrace(); + } + return urls; } @Override diff --git a/src/main/java/de/dhbwstuttgart/environment/PackageCrawler.java b/src/main/java/de/dhbwstuttgart/environment/PackageCrawler.java index 646440b1..f645c3e9 100644 --- a/src/main/java/de/dhbwstuttgart/environment/PackageCrawler.java +++ b/src/main/java/de/dhbwstuttgart/environment/PackageCrawler.java @@ -1,17 +1,10 @@ package de.dhbwstuttgart.environment; -import java.net.URL; +import io.github.classgraph.ClassGraph; +import io.github.classgraph.ScanResult; + import java.util.*; -import org.reflections.Reflections; -import org.reflections.scanners.ResourcesScanner; -import org.reflections.scanners.SubTypesScanner; -import org.reflections.util.ConfigurationBuilder; -import org.reflections.util.FilterBuilder; - -import de.dhbwstuttgart.parser.scope.JavaClassName; -import org.reflections.vfs.SystemDir; - /** * Hilft beim Durchsuchen von Packages * Benutzt die Reflections-Library (https://github.com/ronmamo/reflections) @@ -19,48 +12,30 @@ import org.reflections.vfs.SystemDir; */ public class PackageCrawler { - final URL[] urls; - public PackageCrawler(List urlList) { - urls = urlList.toArray(new URL[0]); + final DirectoryClassLoader classLoader; + public PackageCrawler(DirectoryClassLoader classLoader) { + this.classLoader = classLoader; } - public Set> getClassesInPackage(String packageName){ - /* - List classLoadersList = new LinkedList(); - classLoadersList.add(Thread.currentThread().getContextClassLoader()); - classLoadersList.add(ClasspathHelper.staticClassLoader()); - classLoadersList.add(Thread.currentThread().getContextClassLoader().getParent()); - classLoadersList.add(DirectoryClassLoader.getSystemClassLoader()); - String bootClassPath = System.getProperty("sun.boot.class.path"); - ArrayList urlList = new ArrayList<>(); - for(String path : bootClassPath.split(";")) { - try { - urlList.add(new URL("file:"+path)); - } catch (MalformedURLException e) { - new DebugException("Fehler im Classpath auf diesem System"); - } - } - URL[] urls = urlList.toArray(new URL[0]); - classLoadersList.add(new URLClassLoader(urls, DirectoryClassLoader.getSystemClassLoader())); - */ - Reflections reflections = new Reflections(new ConfigurationBuilder() - .setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner()) - .setUrls(urls) - .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix(packageName)))); + public Set> getClassesInPackage(String packageName) { + var res = new HashSet>(); - Set> classes = reflections.getSubTypesOf(Object.class); + try (ScanResult result = new ClassGraph() + .enableClassInfo() + .enableSystemJarsAndModules() + .addClassLoader(classLoader) + .acceptPackages(packageName) + .scan()) { - return classes; - } + for (var info : result.getAllClasses()) { + try { + var clazz = Class.forName(info.getName()); + res.add(clazz); + } catch (ClassNotFoundException ignored) {} + } + }; - public Set> getAllAvailableClasses(){ - Reflections reflections = new Reflections(new ConfigurationBuilder() - .setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner()) - .setUrls(urls)); - - Set> classes = reflections.getSubTypesOf(Object.class); - - return classes; + return res; } public Map getClassNames(String packageName){ diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index b9aae9d3..f4587b6b 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -279,7 +279,7 @@ public class StatementGenerator { if (!Objects.isNull(creator.classCreatorRest())) { ArgumentList args = convertArguments(creator.classCreatorRest().arguments().expressionList()); - ArrayList argTypes = args.getArguments().stream().map(x -> TypePlaceholder.fresh(creator.getStart())).collect(Collectors.toCollection(ArrayList::new)); + ArrayList argTypes = args.getArguments().stream().map(x -> TypePlaceholder.fresh(creator.getStart())).collect(Collectors.toCollection(ArrayList::new)); argTypes.add(TypePlaceholder.fresh(creator.getStart())); // return type Statement ret = new NewClass(newclass, args, null, argTypes, creator.getStart()); ret.setStatement(); @@ -311,7 +311,7 @@ public class StatementGenerator { IdentifierContext identifier = innercreator.identifier(); RefType newclass = (RefType) TypeGenerator.convertTypeName(identifier.getText(), genericArgs, identifier.getStart(), reg, generics); ArgumentList args = convertArguments(innercreator.classCreatorRest().arguments().expressionList()); - ArrayList argTypes = args.getArguments().stream().map(x -> TypePlaceholder.fresh(innercreator.getStart())).collect(Collectors.toCollection(ArrayList::new)); + ArrayList argTypes = args.getArguments().stream().map(x -> TypePlaceholder.fresh(innercreator.getStart())).collect(Collectors.toCollection(ArrayList::new)); Statement ret = new NewClass(newclass, args, null, argTypes, innercreator.getStart()); ret.setStatement(); return ret; @@ -597,8 +597,12 @@ public class StatementGenerator { } private Statement convert(Java17Parser.ContinuestmtContext stmt) { - // TODO - throw new NotImplementedException(); + Token offset = stmt.getStart(); + if (!Objects.isNull(stmt.identifier())) { + return new Continue(localVars.get(stmt.identifier().getText()), offset); + } else { + return new Continue(TypePlaceholder.fresh(offset), offset); + } } private Statement convert(Java17Parser.SemistmtContext stmt) { @@ -712,7 +716,7 @@ public class StatementGenerator { } ArgumentList argumentList = convertArguments(expr.expressionList()); - ArrayList signature = argumentList.getArguments().stream().map(x -> (RefTypeOrTPHOrWildcardOrGeneric) TypePlaceholder.fresh(offset)).collect(Collectors.toCollection(ArrayList::new)); + ArrayList signature = argumentList.getArguments().stream().map(x -> TypePlaceholder.fresh(offset)).collect(Collectors.toCollection(ArrayList::new)); signature.add(TypePlaceholder.fresh(offset)); // return type MethodCall ret; @@ -737,7 +741,7 @@ public class StatementGenerator { name = expr.SUPER().getText(); } ArgumentList argumentList = convertArguments(expr.expressionList()); - ArrayList signature = argumentList.getArguments().stream().map(x -> (RefTypeOrTPHOrWildcardOrGeneric) TypePlaceholder.fresh(offset)).collect(Collectors.toCollection(ArrayList::new)); + ArrayList signature = argumentList.getArguments().stream().map(x -> TypePlaceholder.fresh(offset)).collect(Collectors.toCollection(ArrayList::new)); signature.add(TypePlaceholder.fresh(offset)); // return type MethodCall ret = new MethodCall(TypePlaceholder.fresh(offset), getReceiver(receiver), name, argumentList, TypePlaceholder.fresh(offset), signature, offset); ret.setStatement(); @@ -804,6 +808,7 @@ public class StatementGenerator { // Check for Classname: if (reg.contains(whole)) { receiver = generateStaticClassName(whole, offset); + break; } whole += "."; } diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java index 111bf11c..de36c9f0 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java @@ -71,10 +71,6 @@ import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.Void; -import de.dhbwstuttgart.typeinference.constraints.GenericsResolver; -import javassist.compiler.SyntaxError; - -import javax.swing.text.html.Option; public class SyntaxTreeGenerator { private JavaClassRegistry reg; @@ -452,8 +448,8 @@ public class SyntaxTreeGenerator { protected static Block prepareBlock(Block constructorBlock, RefType superClass) { List statements = constructorBlock.getStatements(); if (statements.isEmpty() || !(statements.get(0) instanceof SuperCall || statements.get(0) instanceof ThisCall)) { - var signature = new ArrayList(); - signature.add(new Void(new NullToken())); + var signature = new ArrayList(); + signature.add(TypePlaceholder.fresh(new NullToken())); statements.add(0, new SuperCall(superClass, signature, constructorBlock.getOffset())); } /* statements.addAll(fieldInitializations); geloescht PL 2018-11-24 */ diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java b/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java index bc963fb3..2b4fff9f 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java @@ -236,6 +236,11 @@ public abstract class AbstractASTWalker implements ASTVisitor { aBreak.accept(this); } + @Override + public void visit(Continue aContinue) { + aContinue.accept(this); + } + @Override public void visit(StaticClassName staticClassName) { diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/Method.java b/src/main/java/de/dhbwstuttgart/syntaxtree/Method.java index 97b18bcd..27c17b2e 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/Method.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/Method.java @@ -33,6 +33,7 @@ public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope private GenericDeclarationList generics; private final RefTypeOrTPHOrWildcardOrGeneric returnType; public final Boolean isInherited; + public final Boolean isImplemented; /* * its Constraints @@ -50,10 +51,11 @@ public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope this.block = block; this.generics = gtvDeclarations; this.isInherited = false; + this.isImplemented = false; } public Method(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block block, - GenericDeclarationList gtvDeclarations, Token offset, Boolean isInherited) { + GenericDeclarationList gtvDeclarations, Token offset, Boolean isInherited, Boolean isOverridden) { super(offset); this.name = name; this.modifier = modifier; @@ -62,6 +64,7 @@ public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope this.block = block; this.generics = gtvDeclarations; this.isInherited = isInherited; + this.isImplemented = isOverridden; } public ParameterList getParameterList() { @@ -107,4 +110,10 @@ public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope public int hashCode() { return Objects.hash(name, parameterlist, returnType); } + + @Override + public String toString() { + return name; + + } } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java b/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java index 1f1dc61c..78148964 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java @@ -53,6 +53,8 @@ public interface StatementVisitor { void visit(Break aBreak); + void visit(Continue aContinue); + void visit(Yield aYield); void visit(StaticClassName staticClassName); diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java index 020eb6a0..63767c4d 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java @@ -105,11 +105,46 @@ public class ASTFactory { allInheritedMethods.removeAll(allDeclaredMethods); for (java.lang.reflect.Method method : allDeclaredMethods) { var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method))); - methoden.add(createMethod(method, signature, jreClass, false)); - } + if (jreClass.getSuperclass()==null) { + methoden.add(createMethod(method, signature, jreClass, false, false)); + } + else { + Boolean isImplemented = false; + isImplemented = Arrays.stream(jreClass.getInterfaces()). + reduce(false, + (x,y) -> { + try { + y.getDeclaredMethod(method.getName(), method.getParameterTypes()); + return true; + } + catch (java.lang.NoSuchMethodException e) { + return false; + }}, + (x,y) -> (x || y) + ); + + if (isImplemented) { + methoden.add(createMethod(method, signature, jreClass, false, true)); + } + else { + if (Modifier.isAbstract(jreClass.getSuperclass().getModifiers())) { + try { + jreClass.getSuperclass().getDeclaredMethod(method.getName(), method.getParameterTypes()); + methoden.add(createMethod(method, signature, jreClass, false, true)); + } + catch (java.lang.NoSuchMethodException e) { + methoden.add(createMethod(method, signature, jreClass, false, false)); + } + } + else { + methoden.add(createMethod(method, signature, jreClass, false, false)); + } + + } + }} for (java.lang.reflect.Method method : allInheritedMethods) { var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method))); - methoden.add(createMethod(method, signature, jreClass, true)); + methoden.add(createMethod(method, signature, jreClass, true, false)); } List felder = new ArrayList<>(); for (java.lang.reflect.Field field : jreClass.getDeclaredFields()) { @@ -192,7 +227,7 @@ public class ASTFactory { return Optional.of(new de.dhbwstuttgart.syntaxtree.Constructor(modifier, name, returnType, parameterList, block, gtvDeclarations, offset /* , new ArrayList<>() geloescht PL 2018-11-24 */)); } - public static Method createMethod(java.lang.reflect.Method jreMethod, String signature, java.lang.Class inClass, Boolean isInherited) { + public static Method createMethod(java.lang.reflect.Method jreMethod, String signature, java.lang.Class inClass, Boolean isInherited, Boolean isImplemented) { String name = jreMethod.getName(); RefTypeOrTPHOrWildcardOrGeneric returnType; Type jreRetType; @@ -218,7 +253,7 @@ public class ASTFactory { GenericDeclarationList gtvDeclarations = createGenerics(jreMethod.getTypeParameters(), inClass, jreMethod.getName(), signature); Token offset = new NullToken(); - return new Method(jreMethod.getModifiers(), name, returnType, parameterList, block, gtvDeclarations, offset, isInherited); + return new Method(jreMethod.getModifiers(), name, returnType, parameterList, block, gtvDeclarations, offset, isInherited, isImplemented); } public static GenericDeclarationList createGenerics(TypeVariable[] typeParameters, Class context, String methodName, String signature) { diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Continue.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Continue.java new file mode 100644 index 00000000..7da44743 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Continue.java @@ -0,0 +1,18 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import org.antlr.v4.runtime.Token; + +public class Continue extends Statement { + + public Continue(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) { + super(type, offset); + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } + +} diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java index e1deca0f..9dab74b2 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java @@ -27,10 +27,10 @@ public class MethodCall extends Statement public RefTypeOrTPHOrWildcardOrGeneric receiverType; //sind Tphs, repraesentieren im Resultset die Signatur der aufgerufenen Methoden, letztes Element ist der Returntyp - public final ArrayList signature; + public final ArrayList signature; public MethodCall(RefTypeOrTPHOrWildcardOrGeneric retType, Receiver receiver, String methodName, ArgumentList argumentList, - RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList signature, Token offset){ + RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList signature, Token offset){ super(retType,offset); this.arglist = argumentList; this.name = methodName; @@ -40,7 +40,7 @@ public class MethodCall extends Statement if (signature == null) throw new NullPointerException(); } - public List signatureArguments() { + public List signatureArguments() { return signature.subList(0, signature.size() - 1); } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/NewClass.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/NewClass.java index f27bc3e8..005ef001 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/NewClass.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/NewClass.java @@ -11,6 +11,7 @@ import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; import de.dhbwstuttgart.typeinference.constraints.Constraint; @@ -30,9 +31,9 @@ public class NewClass extends MethodCall * @param start */ public NewClass(RefType newClass, ArgumentList args, RefTypeOrTPHOrWildcardOrGeneric receiverType, - ArrayList argTypes, Token start) { + ArrayList signature, Token start) { super(newClass, new ExpressionReceiver(new EmptyStmt(start)), newClass.getName().toString(), - args, receiverType, argTypes, start); + args, receiverType, signature, start); } @Override diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java index e4a7ea01..ebd8cf17 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java @@ -4,6 +4,7 @@ import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.Void; import org.antlr.v4.runtime.Token; @@ -16,12 +17,12 @@ import java.util.List; public class SuperCall extends MethodCall { public SuperCall(RefTypeOrTPHOrWildcardOrGeneric receiverType, - ArrayList argTypes, Token offset){ + ArrayList argTypes, Token offset){ this(new ArgumentList(new ArrayList(), offset), receiverType, argTypes, offset); } public SuperCall(ArgumentList argumentList, RefTypeOrTPHOrWildcardOrGeneric receiverType, - ArrayList argTypes, Token offset){ + ArrayList argTypes, Token offset){ super(new Void(offset), new ExpressionReceiver(new Super(receiverType, offset)), "", argumentList, receiverType, argTypes, offset); } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java index ee4acc96..8739a619 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java @@ -3,6 +3,7 @@ package de.dhbwstuttgart.syntaxtree.statement; import de.dhbwstuttgart.syntaxtree.Constructor; import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.Void; import org.antlr.v4.runtime.Token; @@ -11,7 +12,7 @@ import java.util.ArrayList; public class ThisCall extends MethodCall { - public ThisCall(ArgumentList argumentList, RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList argTypes, Token offset) { + public ThisCall(ArgumentList argumentList, RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList argTypes, Token offset) { super(new Void(offset), new ExpressionReceiver(new This(offset)), "", argumentList, receiverType, argTypes, offset); } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java b/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java index c84b95a1..7297dd87 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java @@ -333,6 +333,11 @@ public class OutputGenerator implements ASTVisitor { out.append("break"); } + @Override + public void visit(Continue aContinue) { + out.append("continue"); + } + @Override public void visit(StaticClassName staticClassName) { @@ -380,6 +385,7 @@ public class OutputGenerator implements ASTVisitor { out.append("super("); superCall.arglist.accept(this); out.append(")"); + out.append(" Signature: " + superCall.signature); } @Override @@ -387,6 +393,7 @@ public class OutputGenerator implements ASTVisitor { out.append("this("); thisCall.arglist.accept(this); out.append(")"); + out.append(" Signature: " + thisCall.signature); } @Override diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 74f0fe89..7e50585a 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -228,6 +228,7 @@ public class StatementToTargetExpression implements ASTVisitor { isInterface = receiverClass.isInterface(); } + System.out.println(argList); result = new TargetMethodCall(converter.convert(methodCall.getType()), returnType, argList, converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), receiverType, methodCall.name, isStatic, isInterface, isPrivate); } @@ -260,6 +261,11 @@ public class StatementToTargetExpression implements ASTVisitor { result = new TargetBreak(); } + @Override + public void visit(Continue aContinue) { + result = new TargetContinue(); + } + @Override public void visit(StaticClassName staticClassName) { result = new TargetClassName(converter.convert(staticClassName.getType())); @@ -282,7 +288,7 @@ public class StatementToTargetExpression implements ASTVisitor { @Override public void visit(DoStmt whileStmt) { - throw new NotImplementedException(); + result = new TargetDo(converter.convert(whileStmt.expr), converter.convert(whileStmt.loopBlock)); } // TODO These two might not be necessary @@ -300,9 +306,20 @@ public class StatementToTargetExpression implements ASTVisitor { public void visit(SuperCall superCall) { var aSuper = converter.convert(superCall.receiver.getType()); var type = converter.convert(superCall.getType()); - var parameters = superCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList(); + var receiverName = new JavaClassName(converter.convert(superCall.receiver.getType()).name()); + var clazz = converter.compiler.getClass(receiverName); + var signature = superCall.signatureArguments().stream().map(converter::convert).toList(); + var method = converter.findConstructor(clazz, signature); + var params = superCall.getArgumentList().getArguments().stream().map(converter::convert).toList(); - result = new TargetMethodCall(type, type, parameters, new TargetSuper(aSuper), superCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aSuper, superCall.name, false, false, false); + List argList; + if (method.isPresent()) { + argList = method.get().getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList(); + } else { + argList = params.stream().map(TargetExpression::type).toList(); + } + + result = new TargetMethodCall(type, null, argList, new TargetSuper(aSuper), params, aSuper, superCall.name, false, false, false); } @Override diff --git a/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java index 7b6f2a5f..d26cbbd9 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java @@ -124,6 +124,11 @@ public abstract class TracingStatementVisitor implements StatementVisitor { } + @Override + public void visit(Continue aContinue) { + + } + @Override public void visit(StaticClassName staticClassName) { diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetDo.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetDo.java new file mode 100644 index 00000000..7329b2ea --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetDo.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.target.tree.expression; + +public record TargetDo(TargetExpression cond, TargetExpression body) implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java index e0bbc523..b82cfd79 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java @@ -3,7 +3,7 @@ package de.dhbwstuttgart.target.tree.expression; import de.dhbwstuttgart.target.tree.type.*; public sealed interface TargetExpression - permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetPattern, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetThrow, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield { + permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetDo, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetPattern, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetThrow, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield { default TargetType type() { return null; diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java index e1a3690c..463702bd 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java @@ -1,6 +1,4 @@ package de.dhbwstuttgart.target.tree.expression; -import de.dhbwstuttgart.target.tree.type.TargetType; - public record TargetWhile(TargetExpression cond, TargetExpression body) implements TargetExpression { } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java b/src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java index e4a92c02..b03ff1dd 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java @@ -20,14 +20,16 @@ public class MethodAssumption extends Assumption{ private RefTypeOrTPHOrWildcardOrGeneric retType; List params; private final Boolean isInherited; + private final Boolean isOverridden; public MethodAssumption(ClassOrInterface receiver, RefTypeOrTPHOrWildcardOrGeneric retType, - List params, TypeScope scope, Boolean isInherited){ + List params, TypeScope scope, Boolean isInherited, Boolean isOverridden){ super(scope); this.receiver = receiver; this.retType = retType; this.params = params; this.isInherited = isInherited; + this.isOverridden = isOverridden; } /* @@ -74,4 +76,8 @@ public class MethodAssumption extends Assumption{ public Boolean isInherited() { return isInherited; } + + public Boolean isOverridden() { + return isOverridden; + } } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/assumptions/TypeInferenceBlockInformation.java b/src/main/java/de/dhbwstuttgart/typeinference/assumptions/TypeInferenceBlockInformation.java index 6b9f54a5..7fe843d1 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/assumptions/TypeInferenceBlockInformation.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/assumptions/TypeInferenceBlockInformation.java @@ -35,7 +35,6 @@ public class TypeInferenceBlockInformation extends TypeInferenceInformation { public ClassOrInterface getSuperClass() { for (var clazz : getAvailableClasses()) { - System.out.println(currentClass.getSuperClass().getName()); if (clazz.getClassName().equals(currentClass.getSuperClass().getName())) return clazz; } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java b/src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java index ffac994b..970cffef 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java @@ -8,7 +8,8 @@ import java.util.Set; public class Constraint extends HashSet { private static final long serialVersionUID = 1L; - private Boolean isInherited = false;//wird nur für die Method-Constraints benoetigt + private Boolean isInherited = false;//wird beides nur für die Method-Constraints benoetigt + private Boolean isImplemented = false; /* * wird verwendet um bei der Codegenerierung die richtige Methoden - Signatur @@ -22,12 +23,14 @@ public class Constraint extends HashSet { super(); } - public Constraint(Boolean isInherited) { + public Constraint(Boolean isInherited, Boolean isImplemented) { this.isInherited = isInherited; + this.isImplemented = isImplemented; } - public Constraint(Boolean isInherited, Constraint extendConstraint, Set methodSignatureConstraint) { + public Constraint(Boolean isInherited, Boolean isImplemented, Constraint extendConstraint, Set methodSignatureConstraint) { this.isInherited = isInherited; + this.isImplemented = isImplemented; this.extendConstraint = extendConstraint; this.methodSignatureConstraint = methodSignatureConstraint; } @@ -40,6 +43,10 @@ public class Constraint extends HashSet { return isInherited; } + public Boolean isImplemented() { + return isImplemented; + } + public Constraint getExtendConstraint() { return extendConstraint; } @@ -57,7 +64,8 @@ public class Constraint extends HashSet { } public String toString() { - return super.toString() + "\nisInherited = " + isInherited + return super.toString() + "\nisInherited = " + isInherited + " isOveridden = " + isImplemented + + methodSignatureConstraint //" + extendsContraint: " + (extendConstraint != null ? extendConstraint.toStringBase() : "null" ) + "\n" ; } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java b/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java index f52001b3..14821895 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java @@ -71,12 +71,13 @@ public class ConstraintSet { for(Set> oderConstraint : oderConstraints){ newOder.add( - oderConstraint.parallelStream().map((Constraint as) -> { + oderConstraint.stream().map((Constraint as) -> { Constraint newConst = as.stream() .map(o) .collect(Collectors.toCollection(( () -> new Constraint (as.isInherited(), + as.isImplemented(), (as.getExtendConstraint() != null) ? as.getExtendConstraint().stream().map(o).collect(Collectors.toCollection(Constraint::new)) : null, diff --git a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index 417c44a8..e068d9b2 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -514,6 +514,11 @@ public class TYPEStmt implements StatementVisitor { } + @Override + public void visit(Continue aContinue) { + + } + @Override public void visit(StaticClassName staticClassName) { // Hier entstehen keine Constraints @@ -569,7 +574,10 @@ public class TYPEStmt implements StatementVisitor { @Override public void visit(DoStmt whileStmt) { - throw new NotImplementedException(); + RefType booleanType = new RefType(ASTFactory.createClass(java.lang.Boolean.class).getClassName(), new NullToken()); + whileStmt.expr.accept(this); + constraintsSet.addUndConstraint(new Pair(whileStmt.expr.getType(), booleanType, PairOperator.EQUALSDOT, loc(whileStmt.expr.getOffset()))); + whileStmt.loopBlock.accept(this); } @Override @@ -591,7 +599,7 @@ public class TYPEStmt implements StatementVisitor { for (var ctor : clazz.getConstructors()) { var params = convertParams(ctor.getParameterList(), info); if (params.size() != superCall.arglist.getArguments().size()) continue; - var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(clazz, ctor), ctor.isInherited); + var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(clazz, ctor), ctor.isInherited, false); GenericsResolver resolver = getResolverInstance(); Set> oneMethodConstraints = generateConstraint(superCall, assumption, info, resolver); @@ -607,7 +615,7 @@ public class TYPEStmt implements StatementVisitor { for (var ctor : info.getCurrentClass().getConstructors()) { var params = convertParams(ctor.getParameterList(), info); if (params.size() != thisCall.arglist.getArguments().size()) continue; - var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(info.getCurrentClass(), ctor), ctor.isInherited); + var assumption = new MethodAssumption(null, new Void(new NullToken()), params, createTypeScope(info.getCurrentClass(), ctor), ctor.isInherited, false); GenericsResolver resolver = getResolverInstance(); Set> oneMethodConstraints = generateConstraint(thisCall, assumption, info, resolver); @@ -640,8 +648,8 @@ public class TYPEStmt implements StatementVisitor { protected Set> generateConstraint(MethodCall forMethod, MethodAssumption assumption, TypeInferenceBlockInformation info, GenericsResolver resolver) { Constraint methodConstraint, extendsMethodConstraint; - methodConstraint = new Constraint<>(assumption.isInherited()); - extendsMethodConstraint = new Constraint<>(assumption.isInherited());// PL 2023-01-24: Ersetzt die Dopplung in visit(MethodCall) + methodConstraint = new Constraint<>(assumption.isInherited(), assumption.isOverridden()); + extendsMethodConstraint = new Constraint<>(assumption.isInherited(), assumption.isOverridden());// PL 2023-01-24: Ersetzt die Dopplung in visit(MethodCall) ClassOrInterface receiverCl = assumption.getReceiver(); /* @@ -716,7 +724,6 @@ public class TYPEStmt implements StatementVisitor { Set ret = new HashSet<>(); for (int i = 0; i < foMethod.arglist.getArguments().size(); i++) { - // Zuordnung von MethoCall.signature (Argumenttypen) zu der Argumenttypen der ausgewaehlten Methode (assumption.params) ret.add(new Pair(foMethod.signature.get(i), assumption.getArgTypes().get(i), PairOperator.EQUALSDOT)); @@ -747,14 +754,14 @@ public class TYPEStmt implements StatementVisitor { public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { throw new NotImplementedException(); } - }, false)); + }, false, false)); } for (ClassOrInterface cl : info.getAvailableClasses()) { for (Method m : cl.getMethods()) { if (m.getName().equals(name) && m.getParameterList().getFormalparalist().size() == numArgs) { RefTypeOrTPHOrWildcardOrGeneric retType = m.getReturnType();// info.checkGTV(m.getReturnType()); - ret.add(new MethodAssumption(cl, retType, convertParams(m.getParameterList(), info), createTypeScope(cl, m), m.isInherited)); + ret.add(new MethodAssumption(cl, retType, convertParams(m.getParameterList(), info), createTypeScope(cl, m), m.isInherited, m.isImplemented)); } } } @@ -786,7 +793,7 @@ public class TYPEStmt implements StatementVisitor { for (Method m : cl.getConstructors()) { if (m.getParameterList().getFormalparalist().size() == argList.getArguments().size()) { var params = convertParams(m.getParameterList(), info); - ret.add(new MethodAssumption(cl, cl.generateTypeOfThisClass(), params, createTypeScope(cl, m), m.isInherited)); + ret.add(new MethodAssumption(cl, cl.generateTypeOfThisClass(), params, createTypeScope(cl, m), m.isInherited, m.isImplemented)); } } } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java index a3d2474c..275755b2 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java @@ -702,9 +702,10 @@ public class RuleSet implements IRuleSet{ x -> uni.apply(pair,x)).collect(Collectors.toCollection((b.getExtendConstraint() != null) ? () -> new Constraint( b.isInherited(), + b.isImplemented(), b.getExtendConstraint().stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(Constraint::new)), b.getmethodSignatureConstraint().stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(HashSet::new))) - : () -> new Constraint(b.isInherited()) + : () -> new Constraint(b.isInherited(), b.isImplemented()) )); oderConstraints.replaceAll(oc -> oc.stream().map(applyUni).collect(Collectors.toCollection(HashSet::new))); /* diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java index 130658dc..6cbfddb0 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java @@ -253,13 +253,14 @@ public class TypeUnifyTask extends RecursiveTask>> { one = true; Set neweq = new HashSet<>(eq); /* 1-elementige Oder-Constraints werden in und-Constraints umgewandelt */ + Set methodSignatureConstraint = new HashSet<>(); oderConstraintsField.stream() .filter(x -> x.size()==1) - .map(y -> y.stream().findFirst().get()).forEach(x -> neweq.addAll(x)); + .map(y -> y.stream().findFirst().get()).forEach(x -> { neweq.addAll(x); methodSignatureConstraint.addAll(x.getmethodSignatureConstraint());} ); ArrayList>> remainingOderconstraints = oderConstraintsField.stream() .filter(x -> x.size()>1) .collect(Collectors.toCollection(ArrayList::new)); - Set> res = unify(neweq, remainingOderconstraints, fc, parallel, rekTiefeField, new HashSet<>()); + Set> res = unify(neweq, remainingOderconstraints, fc, parallel, rekTiefeField, methodSignatureConstraint); noOfThread--; try { logFile.close(); @@ -598,11 +599,13 @@ public class TypeUnifyTask extends RecursiveTask>> { eqPrimePrimeSet.forEach(x -> x.addAll(methodSignatureConstraint)); //Substitutionen in methodcontraintsets werdne ausgeführt + /* PL auskommentiert 2024-05-02 eqPrimePrimeSet = eqPrimePrimeSet.stream().map( x -> { Optional> help = rules.subst(x); return help.isPresent() ? help.get(): x; }).collect(Collectors.toSet()); + */ /* * Ende */ @@ -813,6 +816,7 @@ public class TypeUnifyTask extends RecursiveTask>> { writeLog("nextSetasList: " + nextSetasList.toString()); if (variance == 1) { a = oup.max(nextSetasList.iterator()); + writeLog("Max: a in " + variance + " "+ a); nextSetasList.remove(a); if (oderConstraint) { nextSetasListOderConstraints.add(((Constraint)a).getExtendConstraint()); @@ -1350,12 +1354,15 @@ public class TypeUnifyTask extends RecursiveTask>> { while(aParDefIt.hasNext()) { Set a_new = aParDefIt.next(); List> smallerSetasList = oup.smallerThan(a_new, nextSetasList); + writeLog("smallerSetasList: " + smallerSetasList); List> notInherited = smallerSetasList.stream() - .filter(x -> !((Constraint)x).isInherited()) + .filter(x -> !((Constraint)x).isInherited() && !((Constraint)x).isImplemented()) .collect(Collectors.toCollection(ArrayList::new)); + writeLog("notInherited: " + notInherited+"\n"); List> notErased = new ArrayList<>(); notInherited.stream().forEach(x -> { notErased.addAll(oup.smallerEqThan(x, smallerSetasList)); }); List> erased = new ArrayList<>(smallerSetasList); + writeLog("notErased: " + notErased+"\n"); erased.removeAll(notErased); nextSetasList.removeAll(erased); diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java index 4ef94fba..d6514c67 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java @@ -36,6 +36,7 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; import de.dhbwstuttgart.util.Pair; import org.antlr.v4.runtime.Token; +import org.apache.commons.io.output.NullWriter; /** * The finite closure for the type unification @@ -140,6 +141,10 @@ implements IFiniteClosure { } } + public FiniteClosure(Set constraints, Writer writer) { + this(constraints, writer, null); + } + void testSmaller() { UnifyType tq1, tq2, tq3; tq1 = new ExtendsType(PlaceholderType.freshPlaceholder()); @@ -694,7 +699,7 @@ implements IFiniteClosure { */ public int compare (UnifyType left, UnifyType right, PairOperator pairop) { - //try {logFile.write("left: "+ left + " right: " + right + " pairop: " + pairop);} catch (IOException ie) {} + try {logFile.write("left: "+ left + " right: " + right + " pairop: " + pairop +"\n");} catch (IOException ie) {} if (left.getName().equals("Matrix") || right.getName().equals("Matrix")) System.out.println(""); /* @@ -751,15 +756,15 @@ implements IFiniteClosure { HashSet hs = new HashSet<>(); hs.add(up); Set smallerRes = unifyTask.applyTypeUnificationRules(hs, this); - /* - //if (left.getName().equals("Matrix") || right.getName().equals("Matrix")) + + //if (left.getName().equals("Vector") || right.getName().equals("AbstractList")) {try { logFile.write("\nsmallerRes: " + smallerRes);//"smallerHash: " + greaterHash.toString()); logFile.flush(); } catch (IOException e) { System.err.println("no LogFile");}} - */ + //Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok. Predicate delFun = x -> !((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType) @@ -767,6 +772,12 @@ implements IFiniteClosure { ((WildcardType)x.getLhsType()).getWildcardedType().equals(x.getRhsType())) ); long smallerLen = smallerRes.stream().filter(delFun).count(); + try { + logFile.write("\nsmallerLen: " + smallerLen +"\n"); + logFile.flush(); + } + catch (IOException e) { + System.err.println("no LogFile");} if (smallerLen == 0) return -1; else { up = new UnifyPair(right, left, pairop); @@ -774,15 +785,15 @@ implements IFiniteClosure { hs = new HashSet<>(); hs.add(up); Set greaterRes = unifyTask.applyTypeUnificationRules(hs, this); - /* - //if (left.getName().equals("Matrix") || right.getName().equals("Matrix")) + + //if (left.getName().equals("Vector") || right.getName().equals("AbstractList")) {try { logFile.write("\ngreaterRes: " + greaterRes);//"smallerHash: " + greaterHash.toString()); logFile.flush(); } catch (IOException e) { System.err.println("no LogFile");}} - */ + //Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok. long greaterLen = greaterRes.stream().filter(delFun).count(); if (greaterLen == 0) return 1; diff --git a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java index 0b1f50c8..62465b1a 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java @@ -34,6 +34,12 @@ public class ReferenceType extends UnifyType { this.genericTypeVar = genericTypeVar; } + public ReferenceType(String name, UnifyType... params) { + super(name, new TypeParams(params)); + hashCode = 31 + 17 * typeName.hashCode() + 17 * typeParams.hashCode(); + genericTypeVar = false; + } + public ReferenceType(String name, TypeParams params) { super(name, params); hashCode = 31 + 17 * typeName.hashCode() + 17 * typeParams.hashCode(); diff --git a/src/test/java/AllgemeinTest.java b/src/test/java/AllgemeinTest.java index 2d89ec83..adc91ad6 100644 --- a/src/test/java/AllgemeinTest.java +++ b/src/test/java/AllgemeinTest.java @@ -1,6 +1,7 @@ import static org.junit.Assert.*; +import static targetast.TestCodegen.generateClassFiles; import java.io.File; import java.lang.reflect.Field; @@ -14,6 +15,7 @@ import org.junit.Test; import com.google.common.collect.Lists; import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.environment.ByteArrayClassLoader; public class AllgemeinTest { @@ -62,7 +64,9 @@ public class AllgemeinTest { //String className = "Cycle"; //String className = "TripleTest"; //String className = "WildcardList"; - String className = "List"; + //String className = "List"; + //String className = "Box"; + String className = "GenBox"; //PL 2019-10-24: genutzt fuer unterschiedliche Tests path = System.getProperty("user.dir")+"/resources/AllgemeinTest/" + className + ".jav"; //path = System.getProperty("user.dir")+"/src/test/resources/AllgemeinTest/Overloading_Generics.jav"; @@ -74,7 +78,7 @@ public class AllgemeinTest { Lists.newArrayList(new File(System.getProperty("user.dir")+"/resources/bytecode/classFiles/")), new File(System.getProperty("user.dir")+"/resources/bytecode/classFiles/")); //*/ - compiler.generateBytecode(new File(path)); + compiler.generateBytecode(); pathToClassFile = System.getProperty("user.dir")+"/resources/bytecode/classFiles/"; loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); classToTest = loader.loadClass(className); diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index 3058ac14..fd4b8b5e 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -4,6 +4,7 @@ import org.junit.Ignore; import org.junit.Test; import java.lang.reflect.*; +import java.util.AbstractList; import java.util.Arrays; import java.util.List; import java.util.Vector; @@ -180,7 +181,7 @@ public class TestComplete { } @Test - @Ignore() + //@Ignore() public void matrixOpTest() throws Exception { var classFiles = generateClassFiles(new ByteArrayClassLoader(), "MatrixOP.jav"); var matrixOP = classFiles.get("MatrixOP"); @@ -263,7 +264,7 @@ public class TestComplete { var instanceOfClass_m2 = matrix.getDeclaredConstructor(Vector.class).newInstance(vv1); - var mul = matrix.getDeclaredMethod("mul", Vector.class); + var mul = matrix.getDeclaredMethod("mul", List.class); var result = mul.invoke(instanceOfClass_m1, instanceOfClass_m2); System.out.println(instanceOfClass_m1.toString() + " * " + instanceOfClass_m2.toString() + " = " + result.toString()); @@ -605,10 +606,10 @@ public class TestComplete { } @Test - @Ignore("This one isn't working") + //@Ignore("This one isn't working") public void boxTest() throws Exception { var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Box.jav"); - var instance = classFiles.get("Box_Main").getDeclaredConstructor().newInstance(); + var instance = classFiles.get("Box").getDeclaredConstructor().newInstance(); } @Test @@ -924,6 +925,22 @@ public class TestComplete { assertEquals(clazz.getDeclaredMethod("main", Integer.class).invoke(instance, 5), "small"); } + @Test + public void testWhile() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "While.jav"); + var clazz = classFiles.get("While"); + var instance = clazz.getDeclaredConstructor().newInstance(); + assertEquals(clazz.getDeclaredMethod("m", Integer.class).invoke(instance, 5), 5); + assertEquals(clazz.getDeclaredMethod("m2").invoke(instance), 10); + } + + @Test + public void testImportWildcard() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "ImportWildcard.jav"); + var clazz = classFiles.get("ImportWildcard"); + var instance = clazz.getDeclaredConstructor().newInstance(); + } + @Test public void testBug122() throws Exception { var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug122.jav"); @@ -1085,6 +1102,37 @@ public class TestComplete { assertEquals(res, List.of(6, 7, 8)); } + @Test + public void testBug325() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug325.jav"); + var clazz = classFiles.get("Bug325"); + var instance = clazz.getDeclaredConstructor().newInstance(); + clazz.getDeclaredMethod("main").invoke(instance); + } + + @Test + public void testBug326() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug326.jav"); + var clazz = classFiles.get("Bug326"); + var instance = clazz.getDeclaredConstructor().newInstance(); + } + + @Test + public void testBug328() throws Exception { + var loader = new ByteArrayClassLoader(); + loader.loadClass(TestCodegen.path.resolve("Bug328B.class")); + var classFiles = generateClassFiles(loader, "Bug328.jav"); + var clazz = classFiles.get("Bug328"); + var instance = clazz.getDeclaredConstructor().newInstance(); + } + + @Test + public void testBug333() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug333.jav"); + var clazz = classFiles.get("Bug333"); + var instance = clazz.getDeclaredConstructor().newInstance(); + } + @Test public void testBug338() throws Exception { var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug338.jav"); diff --git a/src/test/java/targetast/ASTToTypedTargetAST.java b/src/test/java/targetast/ASTToTypedTargetAST.java index a4fa2ff0..3c4c7fed 100644 --- a/src/test/java/targetast/ASTToTypedTargetAST.java +++ b/src/test/java/targetast/ASTToTypedTargetAST.java @@ -57,7 +57,7 @@ public class ASTToTypedTargetAST { var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Tph2.jav").toFile(); var compiler = new JavaTXCompiler(file); var resultSet = compiler.typeInference(file); - var converter = new ASTToTargetAST(resultSet); + var converter = new ASTToTargetAST(compiler, resultSet); var classes = compiler.sourceFiles.get(file).getClasses(); var tphAndGenerics = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); @@ -68,7 +68,7 @@ public class ASTToTypedTargetAST { var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Cycle.jav").toFile(); var compiler = new JavaTXCompiler(file); var resultSet = compiler.typeInference(file); - var converter = new ASTToTargetAST(resultSet); + var converter = new ASTToTargetAST(compiler, resultSet); var classes = compiler.sourceFiles.get(file).getClasses(); var cycle = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); @@ -79,7 +79,7 @@ public class ASTToTypedTargetAST { var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Infimum.jav").toFile(); var compiler = new JavaTXCompiler(file); var resultSet = compiler.typeInference(file); - var converter = new ASTToTargetAST(resultSet); + var converter = new ASTToTargetAST(compiler, resultSet); var classes = compiler.sourceFiles.get(file).getClasses(); var infimum = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); @@ -90,7 +90,7 @@ public class ASTToTypedTargetAST { var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Gen.jav").toFile(); var compiler = new JavaTXCompiler(file); var resultSet = compiler.typeInference(file); - var converter = new ASTToTargetAST(resultSet); + var converter = new ASTToTargetAST(compiler, resultSet); var classes = compiler.sourceFiles.get(file).getClasses(); var generics = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); @@ -124,7 +124,7 @@ public class ASTToTypedTargetAST { var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Generics2.jav").toFile(); var compiler = new JavaTXCompiler(file); var resultSet = compiler.typeInference(file); - var converter = new ASTToTargetAST(resultSet); + var converter = new ASTToTargetAST(compiler, resultSet); var classes = compiler.sourceFiles.get(file).getClasses(); var generics2 = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); @@ -140,7 +140,7 @@ public class ASTToTypedTargetAST { var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Generics3.jav").toFile(); var compiler = new JavaTXCompiler(file); var resultSet = compiler.typeInference(file); - var converter = new ASTToTargetAST(resultSet); + var converter = new ASTToTargetAST(compiler, resultSet); var classes = compiler.sourceFiles.get(file).getClasses(); var generics3 = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader());