forked from JavaTX/JavaCompilerCore
Merge remote-tracking branch 'origin/bytecode2' into plugin
# Conflicts: # pom.xml # src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java # src/test/resources/testBytecode/generatedBC/.gitignore # test/bytecode/FacultyTest.java # test/bytecode/LambdaTest.java # test/bytecode/MatrixOpTest.java # test/bytecode/YTest.java
This commit is contained in:
commit
a867231348
142
pom.xml
142
pom.xml
@ -5,27 +5,18 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>de.dhbwstuttgart</groupId>
|
||||
<artifactId>JavaTXcompiler</artifactId>
|
||||
<version>0.1.0</version>
|
||||
<name>JavaTXcompiler</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<tycho.version>1.2.0</tycho.version>
|
||||
</properties>
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>maven-repository</id>
|
||||
<name>MyCo Internal Repository</name>
|
||||
<url>file:///${project.basedir}/maven-repository/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
|
||||
|
||||
<version>0.1</version>
|
||||
<name>JavaTXcompiler</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.antlr</groupId>
|
||||
<artifactId>antlr4</artifactId>
|
||||
@ -39,24 +30,32 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>27.0.1-jre</version>
|
||||
<version>22.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.reflections</groupId>
|
||||
<artifactId>reflections</artifactId>
|
||||
<version>0.9.11</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm -->
|
||||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm</artifactId>
|
||||
<version>[6.1.1,)</version>
|
||||
<version>7.0</version>
|
||||
</dependency>
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm-all</artifactId>
|
||||
<version>[4.0.0,)</version>
|
||||
</dependency>
|
||||
-->
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>org.bitbucket.mstrobel</groupId>
|
||||
<artifactId>procyon-reflection</artifactId>
|
||||
<version>[0.5.32,)</version>
|
||||
</dependency> -->
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@ -64,6 +63,8 @@
|
||||
<outputDirectory>target/classes</outputDirectory>
|
||||
<finalName>${project.artifactId}-${project.version}</finalName>
|
||||
<testOutputDirectory>target/test-classes</testOutputDirectory>
|
||||
<sourceDirectory>src/</sourceDirectory>
|
||||
<testSourceDirectory>test/</testSourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.antlr</groupId>
|
||||
@ -76,12 +77,9 @@
|
||||
<goal>antlr4</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sourceDirectory>src/main/antlr4/java8</sourceDirectory>
|
||||
<outputDirectory>${project.basedir}/target/generated-sources/antlr4/de/dhbwstuttgart/parser/antlr</outputDirectory>
|
||||
<arguments>
|
||||
<argument>-package</argument>
|
||||
<argument>de.dhbwstuttgart.parser.antlr</argument>
|
||||
</arguments>
|
||||
<sourceDirectory>src/de/dhbwstuttgart/parser/antlr/</sourceDirectory>
|
||||
<outputDirectory>src/de/dhbwstuttgart/parser/antlr/</outputDirectory>
|
||||
<arguments> <argument>-package</argument> <argument>de.dhbwstuttgart.parser.antlr</argument> </arguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
@ -90,8 +88,8 @@
|
||||
<goal>antlr4</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sourceDirectory>src/main/antlr4/sat/</sourceDirectory>
|
||||
<outputDirectory>${project.basedir}/target/generated-sources/antlr4/de/dhbwstuttgart/sat/asp/parser/antlr</outputDirectory>
|
||||
<sourceDirectory>src/de/dhbwstuttgart/sat/asp/parser/antlr/</sourceDirectory>
|
||||
<outputDirectory>src/de/dhbwstuttgart/sat/asp/parser/antlr/</outputDirectory>
|
||||
<arguments>
|
||||
<argument>-package</argument>
|
||||
<argument>de.dhbwstuttgart.sat.asp.parser.antlr</argument>
|
||||
@ -101,14 +99,6 @@
|
||||
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0-M1</version>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
@ -125,20 +115,10 @@
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>3.7.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.reficio</groupId>
|
||||
<artifactId>p2-maven-plugin</artifactId>
|
||||
<version>1.3.0</version>
|
||||
<version>1.1.2-SNAPSHOT</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-cli</id>
|
||||
@ -149,54 +129,36 @@
|
||||
<artifact>
|
||||
<id>de.dhbwstuttgart:JavaTXcompiler:0.1</id>
|
||||
</artifact>
|
||||
<artifact>
|
||||
<id>org.reflections:reflections:0.9.11</id>
|
||||
</artifact>
|
||||
<artifact>
|
||||
<id>com.google.guava:guava:27.0.1-jre</id>
|
||||
</artifact>
|
||||
<artifact>
|
||||
<id>javax.annotation:javax.annotation-api:1.3.1</id>
|
||||
</artifact>
|
||||
<artifact>
|
||||
<id>org.glassfish:javax.annotation:3.1.1</id>
|
||||
</artifact>
|
||||
<artifact><id>org.reflections:reflections:0.9.11</id></artifact>
|
||||
<artifact><id>com.google.guava:guava:22.0</id></artifact>
|
||||
<artifact><id>javax.annotation:javax.annotation-api:1.3.1</id></artifact>
|
||||
<artifact><id>org.glassfish:javax.annotation:3.1.1</id></artifact>
|
||||
</artifacts>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>9.4.14.v20181114</version>
|
||||
<configuration>
|
||||
<scanIntervalSeconds>10</scanIntervalSeconds>
|
||||
<webAppSourceDirectory>${basedir}/target/repository/</webAppSourceDirectory>
|
||||
<webApp>
|
||||
<contextPath>/site</contextPath>
|
||||
</webApp>
|
||||
<supportedPackagings>
|
||||
<supportedPackaging>jar</supportedPackaging>
|
||||
</supportedPackagings>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>tycho-p2-repository-plugin</artifactId>
|
||||
<version>${tycho.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>p2:site</phase>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>archive-repository</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.0</version> <configuration> <source>9</source> <target>9</target>
|
||||
</configuration> </plugin -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>9</source>
|
||||
<target>9</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<pluginRepositories>
|
||||
@ -204,10 +166,6 @@
|
||||
<id>reficio</id>
|
||||
<url>http://repo.reficio.org/maven/</url>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>repo2_maven_org</id>
|
||||
<url>http://repo2.maven.org/maven2</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
<repositories>
|
||||
<repository>
|
||||
@ -215,4 +173,16 @@
|
||||
<url>file:///${project.basedir}/target</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<tycho.version>0.23.0</tycho.version>
|
||||
</properties>
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>maven-repository</id>
|
||||
<name>MyCo Internal Repository</name>
|
||||
<url>file:///${project.basedir}/maven-repository/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
</project>
|
||||
|
78
src/de/dhbwstuttgart/bytecode/TPHExtractor.java
Normal file
78
src/de/dhbwstuttgart/bytecode/TPHExtractor.java
Normal file
@ -0,0 +1,78 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package de.dhbwstuttgart.bytecode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint;
|
||||
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint;
|
||||
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation;
|
||||
import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH;
|
||||
import de.dhbwstuttgart.syntaxtree.AbstractASTWalker;
|
||||
import de.dhbwstuttgart.syntaxtree.Method;
|
||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
import de.dhbwstuttgart.typeinference.result.GenericInsertPair;
|
||||
import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||
|
||||
/**
|
||||
* @author Fayez Abu Alia
|
||||
*
|
||||
*/
|
||||
public class TPHExtractor extends AbstractASTWalker{
|
||||
// Alle TPHs der Felder werden iKopf der Klasse definiert
|
||||
// alle TPHs der Klasse: (TPH, is in Method?)
|
||||
final HashMap<TypePlaceholder,Boolean> allTPHS = new HashMap<>();
|
||||
MethodAndTPH methodAndTph;
|
||||
Boolean inMethod = false;
|
||||
public final ArrayList<MethodAndTPH> ListOfMethodsAndTph = new ArrayList<>();
|
||||
final ArrayList<GenericInsertPair> allPairs = new ArrayList<>();
|
||||
public final ArrayList<TPHConstraint> allCons = new ArrayList<>();
|
||||
private ResultSet resultSet;
|
||||
|
||||
public TPHExtractor() {
|
||||
|
||||
}
|
||||
|
||||
public void setResultSet(ResultSet resultSet) {
|
||||
this.resultSet = resultSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(TypePlaceholder tph) {
|
||||
if(resultSet.resolveType(tph).resolvedType instanceof TypePlaceholder) {
|
||||
TypePlaceholder resolvedTPH = (TypePlaceholder) resultSet.resolveType(tph).resolvedType;
|
||||
if(inMethod)
|
||||
methodAndTph.getTphs().add(resolvedTPH.getName());
|
||||
|
||||
allTPHS.put(resolvedTPH,inMethod);
|
||||
resultSet.resolveType(tph).additionalGenerics.forEach(ag ->{
|
||||
if(ag.contains(resolvedTPH)&&ag.TA1.equals(resolvedTPH)&&!contains(allPairs,ag)) {
|
||||
if(inMethod)
|
||||
methodAndTph.getPairs().add(ag);
|
||||
allPairs.add(ag);
|
||||
TPHConstraint con = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS);
|
||||
allCons.add(con);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
private boolean contains(ArrayList<GenericInsertPair> pairs, GenericInsertPair genPair) {
|
||||
for(int i=0; i<pairs.size();++i) {
|
||||
GenericInsertPair p = pairs.get(i);
|
||||
if(p.TA1.equals(genPair.TA1) && p.TA2.equals(genPair.TA2))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public void visit(Method method) {
|
||||
inMethod = true;
|
||||
methodAndTph = new MethodAndTPH(method.name);
|
||||
super.visit(method);
|
||||
inMethod = false;
|
||||
ListOfMethodsAndTph.add(methodAndTph);
|
||||
}
|
||||
|
||||
}
|
@ -6,6 +6,7 @@ import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||
@ -47,6 +48,7 @@ public class BytecodeGen implements ASTVisitor {
|
||||
|
||||
String type;
|
||||
|
||||
public static RefTypeOrTPHOrWildcardOrGeneric THISTYPE = null;
|
||||
String className;
|
||||
private boolean isInterface;
|
||||
private List<ResultSet> listOfResultSets;
|
||||
@ -54,6 +56,8 @@ public class BytecodeGen implements ASTVisitor {
|
||||
private SourceFile sf;
|
||||
private String path;
|
||||
|
||||
private Optional<Constructor> fieldInitializations;
|
||||
|
||||
private int indexOfFirstParam = 0;
|
||||
|
||||
private String superClass;
|
||||
@ -118,6 +122,7 @@ public class BytecodeGen implements ASTVisitor {
|
||||
|
||||
int acc = isInterface?classOrInterface.getModifiers()+Opcodes.ACC_ABSTRACT:classOrInterface.getModifiers()+Opcodes.ACC_SUPER;
|
||||
|
||||
fieldInitializations = classOrInterface.getfieldInitializations();
|
||||
|
||||
// resultSet = listOfResultSets.get(0);
|
||||
boolean isConsWithNoParamsVisited = false;
|
||||
@ -125,6 +130,7 @@ public class BytecodeGen implements ASTVisitor {
|
||||
for(ResultSet rs : listOfResultSets) {
|
||||
superClass = classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor());
|
||||
resultSet = rs;
|
||||
tphExtractor.setResultSet(resultSet);
|
||||
// Nur einmal ausführen!!
|
||||
if(!isVisited) {
|
||||
classOrInterface.accept(tphExtractor);
|
||||
@ -154,10 +160,12 @@ public class BytecodeGen implements ASTVisitor {
|
||||
}
|
||||
|
||||
for(Constructor c : classOrInterface.getConstructors()) {
|
||||
if(!isConsWithNoParamsVisited)
|
||||
// if(!isConsWithNoParamsVisited) {
|
||||
c.accept(this);
|
||||
if(!c.getParameterList().iterator().hasNext())
|
||||
isConsWithNoParamsVisited = true;
|
||||
// }
|
||||
|
||||
// if(!c.getParameterList().iterator().hasNext())
|
||||
// isConsWithNoParamsVisited = true;
|
||||
}
|
||||
|
||||
for(Method m : classOrInterface.getMethods()) {
|
||||
@ -201,6 +209,7 @@ public class BytecodeGen implements ASTVisitor {
|
||||
}
|
||||
|
||||
if(methodNameAndParamsT.contains(methParamTypes)) {
|
||||
System.out.println("ignore - Method: "+field.name +" , paramsType: "+methParamTypes);
|
||||
return;
|
||||
}
|
||||
methodNameAndParamsT.add(methParamTypes);
|
||||
@ -223,13 +232,18 @@ public class BytecodeGen implements ASTVisitor {
|
||||
Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes,resultSet,constraints);
|
||||
sig = signature.toString();
|
||||
}
|
||||
if(field.getParameterList().iterator().hasNext())
|
||||
System.out.println(field.getParameterList().iterator().next().getType().acceptTV(new TypeToDescriptor()));
|
||||
|
||||
NormalConstructor constructor = new NormalConstructor(field,genericsAndBounds,hasGen);
|
||||
desc = constructor.accept(new DescriptorToString(resultSet));
|
||||
System.out.println("Constructor: " + field.getName() + " Sig: "+ sig + " Desc: " + desc);
|
||||
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", desc, sig, null);
|
||||
mv.visitCode();
|
||||
Block block = fieldInitializations.get().block;
|
||||
BytecodeGenMethod gen = new BytecodeGenMethod(className,superClass,resultSet,field, mv,paramsAndLocals,cw,
|
||||
genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles, sf,path);
|
||||
if(!field.getParameterList().iterator().hasNext()) {
|
||||
genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles, sf,path, block);
|
||||
if(!field.getParameterList().iterator().hasNext() && !(field.block.statements.get(field.block.statements.size()-1) instanceof ReturnVoid)) {
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
}
|
||||
mv.visitMaxs(0, 0);
|
||||
@ -558,52 +572,5 @@ public class BytecodeGen implements ASTVisitor {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public class TPHExtractor extends AbstractASTWalker{
|
||||
// Alle TPHs der Felder werden iKopf der Klasse definiert
|
||||
// alle TPHs der Klasse: (TPH, is in Method?)
|
||||
final HashMap<TypePlaceholder,Boolean> allTPHS = new HashMap<>();
|
||||
MethodAndTPH methodAndTph;
|
||||
Boolean inMethod = false;
|
||||
public final ArrayList<MethodAndTPH> ListOfMethodsAndTph = new ArrayList<>();
|
||||
final ArrayList<GenericInsertPair> allPairs = new ArrayList<>();
|
||||
public final ArrayList<TPHConstraint> allCons = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void visit(TypePlaceholder tph) {
|
||||
if(resultSet.resolveType(tph).resolvedType instanceof TypePlaceholder) {
|
||||
TypePlaceholder resolvedTPH = (TypePlaceholder) resultSet.resolveType(tph).resolvedType;
|
||||
if(inMethod)
|
||||
methodAndTph.getTphs().add(resolvedTPH);
|
||||
|
||||
allTPHS.put(resolvedTPH,inMethod);
|
||||
resultSet.resolveType(tph).additionalGenerics.forEach(ag ->{
|
||||
if(ag.contains(resolvedTPH)&&ag.TA1.equals(resolvedTPH)&&!contains(allPairs,ag)) {
|
||||
if(inMethod)
|
||||
methodAndTph.getPairs().add(ag);
|
||||
allPairs.add(ag);
|
||||
TPHConstraint con = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS);
|
||||
allCons.add(con);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
private boolean contains(ArrayList<GenericInsertPair> pairs, GenericInsertPair genPair) {
|
||||
for(int i=0; i<pairs.size();++i) {
|
||||
GenericInsertPair p = pairs.get(i);
|
||||
if(p.TA1.equals(genPair.TA1) && p.TA2.equals(genPair.TA2))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public void visit(Method method) {
|
||||
inMethod = true;
|
||||
methodAndTph = new MethodAndTPH(method.name);
|
||||
super.visit(method);
|
||||
inMethod = false;
|
||||
ListOfMethodsAndTph.add(methodAndTph);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -75,6 +75,8 @@ public class BytecodeGenMethod implements StatementVisitor {
|
||||
|
||||
private boolean needDUP = false;
|
||||
|
||||
private Block blockFieldInit = null;
|
||||
private boolean isBlockFieldInitVisited = false;
|
||||
// for tests **
|
||||
private String fieldName;
|
||||
private String fieldDesc;
|
||||
@ -85,6 +87,31 @@ public class BytecodeGenMethod implements StatementVisitor {
|
||||
private HashMap<String, byte[]> classFiles;
|
||||
|
||||
private ArrayList<RefTypeOrTPHOrWildcardOrGeneric> varsFunInterface = new ArrayList<>();;
|
||||
// generate bytecode for constructor
|
||||
public BytecodeGenMethod(String className, String superClass,ResultSet resultSet, Method m, MethodVisitor mv,
|
||||
HashMap<String, Integer> paramsAndLocals, ClassWriter cw, HashMap<String, String> genericsAndBoundsMethod,
|
||||
HashMap<String, String> genericsAndBounds, boolean isInterface, HashMap<String, byte[]> classFiles,
|
||||
SourceFile sf,String path, Block block) {
|
||||
|
||||
this.className = className;
|
||||
this.superClass = superClass;
|
||||
this.resultSet = resultSet;
|
||||
this.m = m;
|
||||
this.mv = mv;
|
||||
this.paramsAndLocals = paramsAndLocals;
|
||||
this.cw = cw;
|
||||
this.genericsAndBoundsMethod = genericsAndBoundsMethod;
|
||||
this.genericsAndBounds = genericsAndBounds;
|
||||
this.isInterface = isInterface;
|
||||
this.classFiles = classFiles;
|
||||
this.sf = sf;
|
||||
this.path = path;
|
||||
if(block != null)
|
||||
this.blockFieldInit = block;
|
||||
this.m.block.accept(this);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public BytecodeGenMethod(String className, String superClass,ResultSet resultSet, Method m, MethodVisitor mv,
|
||||
HashMap<String, Integer> paramsAndLocals, ClassWriter cw, HashMap<String, String> genericsAndBoundsMethod,
|
||||
@ -109,8 +136,8 @@ public class BytecodeGenMethod implements StatementVisitor {
|
||||
|
||||
}
|
||||
|
||||
public BytecodeGenMethod(LambdaExpression lambdaExpression, ResultSet resultSet, MethodVisitor mv,
|
||||
int indexOfFirstParamLam, boolean isInterface, HashMap<String, byte[]> classFiles, String path, int lamCounter) {
|
||||
public BytecodeGenMethod(LambdaExpression lambdaExpression, ArrayList<String> usedVars, ResultSet resultSet, MethodVisitor mv,
|
||||
int indexOfFirstParamLam, boolean isInterface, HashMap<String, byte[]> classFiles, String path, int lamCounter, SourceFile sf) {
|
||||
|
||||
this.resultSet = resultSet;
|
||||
this.mv = mv;
|
||||
@ -118,8 +145,15 @@ public class BytecodeGenMethod implements StatementVisitor {
|
||||
this.classFiles = classFiles;
|
||||
this.path = path;
|
||||
this.lamCounter = lamCounter;
|
||||
this.sf = sf;
|
||||
Iterator<FormalParameter> itr = lambdaExpression.params.iterator();
|
||||
int i = indexOfFirstParamLam;
|
||||
|
||||
for(String var : usedVars) {
|
||||
this.paramsAndLocals.put(var, i);
|
||||
i++;
|
||||
}
|
||||
|
||||
while (itr.hasNext()) {
|
||||
FormalParameter fp = itr.next();
|
||||
this.paramsAndLocals.put(fp.getName(), i);
|
||||
@ -154,6 +188,17 @@ public class BytecodeGenMethod implements StatementVisitor {
|
||||
superCall.arglist.accept(this);
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, this.superClass, superCall.name, "()V",
|
||||
isInterface);
|
||||
|
||||
if(blockFieldInit!=null && !isBlockFieldInitVisited) {
|
||||
isBlockFieldInitVisited =true;
|
||||
//blockFieldInit.accept(this);
|
||||
for(Statement stmt : blockFieldInit.statements) {
|
||||
if(stmt instanceof SuperCall)
|
||||
continue;
|
||||
|
||||
stmt.accept(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ??
|
||||
@ -378,6 +423,12 @@ public class BytecodeGenMethod implements StatementVisitor {
|
||||
case BIGGEREQUAL:
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPLT, branchLabel);
|
||||
break;
|
||||
case EQUAL:
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPNE, branchLabel);
|
||||
break;
|
||||
case NOTEQUAL:
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, branchLabel);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -403,6 +454,12 @@ public class BytecodeGenMethod implements StatementVisitor {
|
||||
case BIGGEREQUAL:
|
||||
mv.visitJumpInsn(Opcodes.IFLT, branchLabel);
|
||||
break;
|
||||
case EQUAL:
|
||||
mv.visitJumpInsn(Opcodes.IFNE, branchLabel);
|
||||
break;
|
||||
case NOTEQUAL:
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, branchLabel);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -547,16 +604,31 @@ public class BytecodeGenMethod implements StatementVisitor {
|
||||
this.kindOfLambda = new KindOfLambda(lambdaExpression);
|
||||
|
||||
if (kindOfLambda.isInstanceCapturingLambda()) {
|
||||
// if(!kindOfLambda.getArgumentList().contains(BytecodeGen.THISTYPE))
|
||||
// kindOfLambda.getArgumentList().add(0, BytecodeGen.THISTYPE);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
for(String v : kindOfLambda.getUsedVars()) {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(v));
|
||||
}
|
||||
staticOrSpecial = Opcodes.H_INVOKESPECIAL;
|
||||
indexOfFirstParamLam = 1;
|
||||
} else {
|
||||
staticOrSpecial = Opcodes.H_INVOKESTATIC;
|
||||
staticOrInstance = Opcodes.ACC_STATIC;
|
||||
}
|
||||
String newDesc = "(";
|
||||
int pos = 0;
|
||||
if(kindOfLambda.isHasThis()) {
|
||||
pos = 1;
|
||||
}
|
||||
|
||||
for(int i=pos;i<kindOfLambda.getArgumentList().size();i++) {
|
||||
String t = "L" + getResolvedType(kindOfLambda.getArgumentList().get(i)) + ";";
|
||||
newDesc += t;
|
||||
}
|
||||
newDesc += lamDesc.substring(1);
|
||||
// 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, newDesc, false);
|
||||
// Descriptor of functional interface methode
|
||||
SamMethod samMethod = new SamMethod(kindOfLambda.getArgumentList(), lambdaExpression.getType());
|
||||
// Desc: (this/nothing)TargetType
|
||||
@ -564,10 +636,12 @@ public class BytecodeGenMethod implements StatementVisitor {
|
||||
mv.visitInvokeDynamicInsn("apply", fiMethodDesc, bootstrap, arg1, arg2, arg3);
|
||||
|
||||
MethodVisitor mvLambdaBody = cw.visitMethod(Opcodes.ACC_PRIVATE + staticOrInstance + Opcodes.ACC_SYNTHETIC,
|
||||
methodName, arg3.toString(), null, null);
|
||||
methodName, newDesc, null, null);
|
||||
|
||||
new BytecodeGenMethod(lambdaExpression, this.resultSet, mvLambdaBody, indexOfFirstParamLam, isInterface,
|
||||
classFiles,this.path, lamCounter);
|
||||
ArrayList<String> usedVars = kindOfLambda.getUsedVars();
|
||||
|
||||
new BytecodeGenMethod(lambdaExpression, usedVars,this.resultSet, mvLambdaBody, indexOfFirstParamLam, isInterface,
|
||||
classFiles,this.path, lamCounter, sf);
|
||||
|
||||
mvLambdaBody.visitMaxs(0, 0);
|
||||
mvLambdaBody.visitEnd();
|
||||
@ -642,6 +716,9 @@ public class BytecodeGenMethod implements StatementVisitor {
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, getResolvedType(fieldVar.receiver.getType()), fieldName, fieldDesc);
|
||||
}
|
||||
|
||||
if (isBinaryExp) {
|
||||
doUnboxing(getResolvedType(fieldVar.getType()));
|
||||
}
|
||||
// mv.visitFieldInsn(Opcodes.GETSTATIC,
|
||||
// fieldVar.receiver.getType().toString().replace(".", "/"),
|
||||
// fieldVar.fieldVarName, fieldVar.getType().toString());
|
||||
@ -794,11 +871,13 @@ public class BytecodeGenMethod implements StatementVisitor {
|
||||
if(methodRefl != null && !methodRefl.getReturnType().isPrimitive()) {
|
||||
if(methodRefl.getReturnType().equals(Object.class)) {
|
||||
String checkCast = getResolvedType(methodCall.getType());
|
||||
if(!checkCast.contains("TPH ")) {
|
||||
int pos = checkCast.length();
|
||||
if(checkCast.contains("<"))
|
||||
pos = checkCast.indexOf("<");
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST,checkCast.substring(0,pos));
|
||||
}
|
||||
}
|
||||
if(isBinaryExp)
|
||||
doUnboxing(getResolvedType(methodCall.getType()));
|
||||
}
|
||||
@ -850,11 +929,13 @@ public class BytecodeGenMethod implements StatementVisitor {
|
||||
// methCallType = "L"+methCallType+";";
|
||||
// }
|
||||
for(java.lang.reflect.Method m : methods) {
|
||||
if(name.equals(m.getName()) && i == m.getParameterCount() && methCallType.equals(m.getReturnType().getName().replace(".", "/"))) {
|
||||
if(name.equals(m.getName()) && i == m.getParameterCount() &&
|
||||
(methCallType.equals(m.getReturnType().getName().replace(".", "/")) ||
|
||||
m.getReturnType().getName().replace(".", "/").equals(Type.getInternalName(Object.class)))) {
|
||||
boolean typesEqual = true;
|
||||
Class<?>[] pTypes = m.getParameterTypes();
|
||||
for(int j = 0; j<typesOfParams.length; ++j) {
|
||||
if(!typesOfParams[j].equals(pTypes[j])) {
|
||||
if(!typesOfParams[j].equals(pTypes[j].getName().replaceAll(".", "/")) && !pTypes[j].getName().replace(".", "/").equals(Type.getInternalName(Object.class))) {
|
||||
typesEqual = false;
|
||||
break;
|
||||
}
|
||||
@ -1064,6 +1145,10 @@ public class BytecodeGenMethod implements StatementVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(This aThis) {
|
||||
|
||||
if(BytecodeGen.THISTYPE == null)
|
||||
BytecodeGen.THISTYPE = aThis.getType();
|
||||
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ import de.dhbwstuttgart.syntaxtree.Constructor;
|
||||
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
|
||||
import de.dhbwstuttgart.syntaxtree.Method;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
|
||||
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
@ -331,14 +332,16 @@ public class Signature {
|
||||
|
||||
case "EWC":
|
||||
System.out.println("EWC---Signature");
|
||||
SuperWildcardType ewc = (SuperWildcardType) t;
|
||||
ExtendsWildcardType ewc = (ExtendsWildcardType) t;
|
||||
String esigInner = ewc.getInnerType().acceptTV(new TypeToSignature());
|
||||
System.out.println(esigInner);
|
||||
if(ewc.getInnerType() instanceof TypePlaceholder) {
|
||||
sv.visitTypeArgument('+').visitTypeVariable(esigInner.substring(1, esigInner.length()));
|
||||
} else if(ewc.getInnerType() instanceof RefType) {
|
||||
if(esigInner.contains("$$")) {
|
||||
sv.visitTypeArgument('+').visitInterface().visitClassType(esigInner.substring(1,esigInner.length()));
|
||||
}else {
|
||||
// sv.visitClassType(esigInner.substring(1,esigInner.length()));
|
||||
sv.visitTypeArgument('+').visitClassType(esigInner.substring(1,esigInner.length()));
|
||||
}
|
||||
}else {
|
||||
|
@ -4,22 +4,34 @@ import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
|
||||
import de.dhbwstuttgart.syntaxtree.FormalParameter;
|
||||
import de.dhbwstuttgart.syntaxtree.ParameterList;
|
||||
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.Literal;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
|
||||
public class KindOfLambda implements StatementVisitor{
|
||||
private ParameterList params;
|
||||
private boolean isInstanceCapturingLambda = false;
|
||||
private List<RefTypeOrTPHOrWildcardOrGeneric> argumentList = new ArrayList<>();
|
||||
private ArrayList<String> usedVars = new ArrayList<>();
|
||||
private boolean hasThis = false;
|
||||
private ArrayList<String> definedLocals = new ArrayList<>();
|
||||
|
||||
public KindOfLambda(LambdaExpression lambdaExpression) {
|
||||
this.params = lambdaExpression.params;
|
||||
lambdaExpression.methodBody.accept(this);
|
||||
|
||||
}
|
||||
|
||||
public ArrayList<String> getUsedVars() {
|
||||
return usedVars;
|
||||
}
|
||||
|
||||
public boolean isInstanceCapturingLambda() {
|
||||
return this.isInstanceCapturingLambda;
|
||||
}
|
||||
@ -28,6 +40,10 @@ public class KindOfLambda implements StatementVisitor{
|
||||
return argumentList;
|
||||
}
|
||||
|
||||
public boolean isHasThis() {
|
||||
return hasThis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ArgumentList argumentList) {
|
||||
// TODO Auto-generated method stub
|
||||
@ -95,14 +111,31 @@ public class KindOfLambda implements StatementVisitor{
|
||||
|
||||
@Override
|
||||
public void visit(LocalVar localVar) {
|
||||
// TODO Auto-generated method stub
|
||||
if(!contain(params, localVar.name) && !definedLocals.contains(localVar.name)) {
|
||||
argumentList.add(localVar.getType());
|
||||
if(hasThis) {
|
||||
usedVars.add(1, localVar.name);
|
||||
} else {
|
||||
usedVars.add(0, localVar.name);
|
||||
}
|
||||
if(!isInstanceCapturingLambda)
|
||||
isInstanceCapturingLambda=true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean contain(ParameterList params2, String name) {
|
||||
Iterator<FormalParameter> itr = params2.iterator();
|
||||
while(itr.hasNext()) {
|
||||
FormalParameter fp = itr.next();
|
||||
if(fp.getName().equals(name))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LocalVarDecl localVarDecl) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
definedLocals.add(localVarDecl.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -157,9 +190,13 @@ public class KindOfLambda implements StatementVisitor{
|
||||
|
||||
@Override
|
||||
public void visit(This aThis) {
|
||||
if(!hasThis) {
|
||||
hasThis = true;
|
||||
this.argumentList.add(0,aThis.getType());
|
||||
}
|
||||
if(!isInstanceCapturingLambda) {
|
||||
this.isInstanceCapturingLambda = true;
|
||||
this.argumentList.add(aThis.getType());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,14 +8,14 @@ import de.dhbwstuttgart.typeinference.result.GenericInsertPair;
|
||||
public class MethodAndTPH {
|
||||
|
||||
private String name;
|
||||
private final ArrayList<TypePlaceholder> tphs = new ArrayList<>();
|
||||
private final ArrayList<String> tphs = new ArrayList<>();
|
||||
private final ArrayList<GenericInsertPair> pairs = new ArrayList<>();
|
||||
|
||||
public MethodAndTPH(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public ArrayList<TypePlaceholder> getTphs() {
|
||||
public ArrayList<String> getTphs() {
|
||||
return tphs;
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ import java.util.LinkedList;
|
||||
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import de.dhbwstuttgart.bytecode.BytecodeGen.TPHExtractor;
|
||||
import de.dhbwstuttgart.bytecode.TPHExtractor;
|
||||
import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint;
|
||||
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint;
|
||||
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation;
|
||||
@ -16,7 +16,7 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
public class Simplify {
|
||||
|
||||
public static HashMap<TPHConstraint, HashSet<String>> simplifyConstraints(String name, TPHExtractor tphExtractor) {
|
||||
// 1. check if there are any cycles like L<R and R<L:
|
||||
// 1. check if there are any simple cycles like L<R and R<L:
|
||||
// a) yes => set L=R and:
|
||||
// * remove both constraints
|
||||
// * substitute L with R in all constraint
|
||||
@ -28,8 +28,10 @@ public class Simplify {
|
||||
// b) no
|
||||
// 3. is
|
||||
|
||||
// all constraints that will be simplified
|
||||
ArrayList<TPHConstraint> allCons = tphExtractor.allCons;
|
||||
ArrayList<TPHConstraint> consToRemove = new ArrayList<>();
|
||||
|
||||
// step 1:
|
||||
for(TPHConstraint c : allCons) {
|
||||
|
||||
@ -39,12 +41,16 @@ public class Simplify {
|
||||
TPHConstraint revCon = getReverseConstraint(allCons,left,right);
|
||||
if(revCon != null) {
|
||||
revCon.setRel(Relation.EQUAL);
|
||||
// the reverse constraint is removed because
|
||||
// otherwise there is twice the same constraint
|
||||
// (e.g. A<B and B<A => A=B and B=A)
|
||||
consToRemove.add(revCon);
|
||||
c.setRel(Relation.EQUAL);
|
||||
substituteTPH(allCons,left, right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("NEW ALL CONST: " + allCons.size());
|
||||
allCons.forEach(c->System.out.println(c.toString()));
|
||||
@ -59,17 +65,99 @@ public class Simplify {
|
||||
System.out.println("----------------");
|
||||
HashMap<TPHConstraint, HashSet<String>> result = new HashMap<>();
|
||||
|
||||
// check if there is any long cycle (e.g. A<B<C<A)
|
||||
|
||||
// to save all types that are in relation
|
||||
LinkedList<String> allTypes = new LinkedList<>();
|
||||
// we will put all constraints which are in the cycle, in this ArrayList.
|
||||
// Later these contraints will be converted to equal-constraints
|
||||
ArrayList<TPHConstraint> constraints = new ArrayList<>(size);
|
||||
int visited = 0;
|
||||
|
||||
// contains all constraints
|
||||
HashMap<String,String> ss1 = new HashMap<>();
|
||||
|
||||
for(TPHConstraint constr : allCons) {
|
||||
ss1.put(constr.getLeft(), constr.getRight());
|
||||
}
|
||||
|
||||
for(TPHConstraint c : allCons) {
|
||||
|
||||
if(visited >= size)
|
||||
break;
|
||||
// Only extends-constraints will be checked
|
||||
if(c.getRel() == Relation.EXTENDS) {
|
||||
++visited;
|
||||
|
||||
String left = c.getLeft();
|
||||
String right = c.getRight();
|
||||
// put the types in linked list
|
||||
allTypes.add(left);
|
||||
allTypes.add(right);
|
||||
|
||||
constraints.add(c);
|
||||
|
||||
boolean isCycle = false;
|
||||
|
||||
// iterate through the map to check if there is a cycle
|
||||
while(ss1.containsKey(right)) {
|
||||
++visited;
|
||||
String oldRight = right;
|
||||
right = ss1.get(right);
|
||||
|
||||
TPHConstraint toAdd = getConstraint(oldRight, right, allCons);
|
||||
|
||||
if(toAdd != null)
|
||||
constraints.add(toAdd);
|
||||
|
||||
if(left.equals(right)) {
|
||||
isCycle = true;
|
||||
break;
|
||||
}
|
||||
|
||||
allTypes.add(right);
|
||||
}
|
||||
|
||||
if(isCycle) {
|
||||
// convert all constraints to equal constraints
|
||||
setAllEqual(constraints);
|
||||
// these constraints will be removed from allCons
|
||||
consToRemove.addAll(constraints);
|
||||
// all equal types will be substitute with one type
|
||||
substituteAllTPH(allCons,constraints,left);
|
||||
|
||||
HashSet<String> eq = new HashSet<>();
|
||||
// put all equal types in a set
|
||||
for(String t:allTypes) {
|
||||
eq.add(t);
|
||||
}
|
||||
// generate a new constraint (left < Object)
|
||||
TPHConstraint constraint = new ExtendsConstraint(left, Type.getInternalName(Object.class), Relation.EXTENDS);
|
||||
// put the generated constraint and its equal set into result set
|
||||
result.put(constraint, eq);
|
||||
constraints.clear();
|
||||
}
|
||||
allTypes.clear();
|
||||
}
|
||||
}
|
||||
// build an equal set that contains all types
|
||||
// which are equal and for each equal constraint put left side and right side
|
||||
// in this set Then generate a constraint type < Object and put it
|
||||
// with the equal set into the result.
|
||||
for(TPHConstraint c : allCons) {
|
||||
if(c.getRel()==Relation.EQUAL) {
|
||||
if(!isTPHInResEqual(result, c.getLeft())) {
|
||||
HashSet<String> equalTPHs = getEqualsTPHs(result, c);
|
||||
TPHConstraint constraint = getKeyConstraint(result,c);
|
||||
equalTPHs.add(c.getLeft());
|
||||
equalTPHs.add(c.getRight());
|
||||
result.put(constraint, equalTPHs);
|
||||
}
|
||||
consToRemove.add(c);
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Step 2 Result: ");
|
||||
result.forEach((c,hs)->{
|
||||
System.out.print(c.toString() + " -> ");
|
||||
@ -79,7 +167,9 @@ public class Simplify {
|
||||
System.out.println();
|
||||
});
|
||||
System.out.println("----------------");
|
||||
// remove all equal-constraints
|
||||
allCons.removeAll(consToRemove);
|
||||
// add all generated constraints to allCons
|
||||
allCons.addAll(result.keySet());
|
||||
|
||||
if(!allCons.isEmpty() && allCons.size()<2) {
|
||||
@ -91,19 +181,23 @@ public class Simplify {
|
||||
}
|
||||
|
||||
size += result.keySet().size();
|
||||
|
||||
// all constraints which have Object on the right side will
|
||||
// be ignored, because they are simplified and can not be changed.
|
||||
for(TPHConstraint c : allCons) {
|
||||
if(c.getRight().equals(Type.getInternalName(Object.class)))
|
||||
size--;
|
||||
}
|
||||
ArrayList<TypePlaceholder> methodTphs = new ArrayList<>();
|
||||
// get all tph of the method
|
||||
ArrayList<String> methodTphs = new ArrayList<>();
|
||||
for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) {
|
||||
if(m.getName().equals(name)) {
|
||||
methodTphs = m.getTphs();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check if there are multiple constraint with the same left side.
|
||||
// if yes => check if the super type in the method, if not
|
||||
// then ignore it.
|
||||
HashMap<String, String> subAndSuper = new HashMap<>();
|
||||
for(TPHConstraint c : allCons) {
|
||||
if(subAndSuper.containsKey(c.getLeft())) {
|
||||
@ -155,6 +249,8 @@ public class Simplify {
|
||||
// Die größte Supertype
|
||||
String superTphRes = tphInRel.getLast();
|
||||
|
||||
// if there is any constraint X < subTph, then
|
||||
// add X at the beginning of the list.
|
||||
while(subAndSuper.containsValue(subTphRes)) {
|
||||
for(String tph : subAndSuper.keySet()) {
|
||||
if(containTPH(methodTphs,tph) && subAndSuper.get(tph).equals(subTphRes)) {
|
||||
@ -165,12 +261,18 @@ public class Simplify {
|
||||
if(subTphRes.equals(tphInRel.getFirst())) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(isTPHInConstraint(result, subTphRes))
|
||||
break;
|
||||
|
||||
tphInRel.addFirst(subTphRes);
|
||||
numOfVisitedPairs++;
|
||||
}
|
||||
|
||||
subTphRes = tphInRel.getFirst();
|
||||
|
||||
// if the last type in the list not a type in method-types
|
||||
// then find the last type in front of this type, which is
|
||||
// a type in method-types
|
||||
int i = 2;
|
||||
while(!containTPH(methodTphs,superTphRes) && (tphInRel.size()-i) >0) {
|
||||
superTphRes = tphInRel.get(tphInRel.size()-i);
|
||||
@ -181,13 +283,14 @@ public class Simplify {
|
||||
result.put(new ExtendsConstraint(subTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null);
|
||||
} else {
|
||||
result.put(new ExtendsConstraint(subTphRes, superTphRes, Relation.EXTENDS), null);
|
||||
if(!isTPHInConstraint(result, superTphRes))
|
||||
result.put(new ExtendsConstraint(superTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null);
|
||||
}
|
||||
}
|
||||
|
||||
for(TypePlaceholder tph : methodTphs) {
|
||||
if(!isTPHInConstraint(result, tph.getName())) {
|
||||
result.put(new ExtendsConstraint(tph.getName(), Type.getInternalName(Object.class), Relation.EXTENDS), null);
|
||||
for(String tph : methodTphs) {
|
||||
if(!isTPHInConstraint(result, tph)) {
|
||||
result.put(new ExtendsConstraint(tph, Type.getInternalName(Object.class), Relation.EXTENDS), null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,6 +314,44 @@ public class Simplify {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static TPHConstraint getConstraint(String oldRight, String right, ArrayList<TPHConstraint> allCons) {
|
||||
for(TPHConstraint c : allCons) {
|
||||
if(c.getLeft().equals(oldRight) && c.getRight().equals(right))
|
||||
return c;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isTPHInResEqual(HashMap<TPHConstraint, HashSet<String>> result, String left) {
|
||||
for(HashSet<String> eq : result.values()) {
|
||||
if(eq.contains(left)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void substituteAllTPH(ArrayList<TPHConstraint> allCons, ArrayList<TPHConstraint> constraints,
|
||||
String first) {
|
||||
for(TPHConstraint c : allCons) {
|
||||
for(TPHConstraint c2 : constraints) {
|
||||
if(c.getRel() == Relation.EXTENDS) {
|
||||
if(c2.getLeft().equals(c.getLeft()) || c2.getRight().equals(c.getLeft()))
|
||||
c.setLeft(first);
|
||||
if(c2.getLeft().equals(c.getRight()) || c2.getRight().equals(c.getRight()))
|
||||
c.setRight(first);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void setAllEqual(ArrayList<TPHConstraint> constraints) {
|
||||
for(TPHConstraint c:constraints) {
|
||||
c.setRel(Relation.EQUAL);
|
||||
}
|
||||
}
|
||||
|
||||
public static HashMap<TPHConstraint, HashSet<String>> simplifyContraints(HashMap<TPHConstraint, HashSet<String>> allConstraints) {
|
||||
// 1. check if there are any cycles like L<R and R<L:
|
||||
// a) yes => set L=R and:
|
||||
@ -406,9 +547,9 @@ public class Simplify {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean containTPH(ArrayList<TypePlaceholder> methodTphs, String sub) {
|
||||
for(TypePlaceholder tph : methodTphs) {
|
||||
if(tph.getName().equals(sub))
|
||||
private static boolean containTPH(ArrayList<String> methodTphs, String sub) {
|
||||
for(String tph : methodTphs) {
|
||||
if(tph.equals(sub))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -119,6 +119,13 @@ public class JavaTXCompiler {
|
||||
|
||||
TypeUnify unify = new TypeUnify();
|
||||
Set<Set<UnifyPair>> 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<List<Constraint<UnifyPair>>> cardProd = unifyCons.cartesianProduct();
|
||||
for (List<Constraint<UnifyPair>> xCons : cardProd ){
|
||||
Set<UnifyPair> xConsSet = new HashSet<>();
|
||||
@ -127,12 +134,21 @@ public class JavaTXCompiler {
|
||||
}
|
||||
//.collect(Collectors.toCollection(ArrayList::new))))
|
||||
System.out.println(xConsSet);
|
||||
Set<String> paraTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist()
|
||||
Set<String> methodParaTypeVarNames = 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<String>(), (a,b) -> { a.addAll(b); return a;}, (a,b) -> { a.addAll(b); return a;} ) )
|
||||
.reduce(new HashSet<String>(), (a,b) -> { a.addAll(b); return a;} );
|
||||
|
||||
Set<String> constructorParaTypeVarNames = allClasses.stream().map(x -> x.getConstructors().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<String>(), (a,b) -> { a.addAll(b); return a;}, (a,b) -> { a.addAll(b); return a;} ) )
|
||||
.reduce(new HashSet<String>(), (a,b) -> { a.addAll(b); return a;} );
|
||||
|
||||
Set<String> paraTypeVarNames = methodParaTypeVarNames;
|
||||
paraTypeVarNames.addAll(constructorParaTypeVarNames);
|
||||
|
||||
Set<String> 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();
|
||||
|
||||
|
@ -151,7 +151,7 @@ public class SyntaxTreeGenerator{
|
||||
block = stmtGen.convert(body.block(),true);
|
||||
}
|
||||
if(parentClass.equals(new JavaClassName(name))){
|
||||
return new Constructor(modifiers, name, retType, parameterList, block, gtvDeclarations, header.getStart(), fieldInitializations);
|
||||
return new Constructor(modifiers, name, retType, parameterList, block, gtvDeclarations, header.getStart() /*, fieldInitializations geloescht PL 2018-11-24 */);
|
||||
}else{
|
||||
return new Method(modifiers, name, retType, parameterList,block, gtvDeclarations, header.getStart());
|
||||
}
|
||||
@ -198,14 +198,18 @@ public class SyntaxTreeGenerator{
|
||||
}
|
||||
List<Field> fielddecl = convertFields(ctx.classBody(), generics);
|
||||
//fieldInitializations = generateFieldInitializations(ctx.classBody(), generics);
|
||||
List<Method> methods = convertMethods(ctx.classBody(), name, superClass, generics);
|
||||
List<Method> methodsAndConstructors = convertMethods(ctx.classBody(), name, superClass, generics);
|
||||
List<Method> methods = new ArrayList<>();
|
||||
List<Constructor> konstruktoren = new ArrayList<>();
|
||||
for(int i = 0; i<methods.size();i++){
|
||||
Method m = methods.get(i);
|
||||
//int noOfMethods = methods.size();
|
||||
for(int i = 0; i < methodsAndConstructors.size(); i++){
|
||||
Method m = methodsAndConstructors.get(i);
|
||||
if(m instanceof Constructor){
|
||||
methods.remove(i);
|
||||
konstruktoren.add((Constructor) m);
|
||||
}
|
||||
else {
|
||||
methods.add(m);
|
||||
}
|
||||
}
|
||||
if(konstruktoren.size()<1){//Standardkonstruktor anfügen:
|
||||
konstruktoren.add(
|
||||
@ -217,7 +221,10 @@ public class SyntaxTreeGenerator{
|
||||
|
||||
Boolean isInterface = false;
|
||||
List<RefType> implementedInterfaces = convert(ctx.superinterfaces(), generics);
|
||||
return new ClassOrInterface(modifiers, name, fielddecl, methods, konstruktoren, genericClassParameters, superClass,
|
||||
|
||||
return new ClassOrInterface(modifiers, name, fielddecl,
|
||||
Optional.of(this.generatePseudoConstructor(ctx.Identifier().getText(), name, superClass, genericClassParameters, offset)),
|
||||
methods, konstruktoren, genericClassParameters, superClass,
|
||||
isInterface, implementedInterfaces, offset);
|
||||
}
|
||||
|
||||
@ -267,7 +274,15 @@ public class SyntaxTreeGenerator{
|
||||
RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset);
|
||||
ParameterList params = new ParameterList(new ArrayList<>(), offset);
|
||||
Block block = new Block(new ArrayList<>(), offset);
|
||||
return new Constructor(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset, fieldInitializations);
|
||||
return new Constructor(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset /*, fieldInitializations geloescht PL 2018-11-24 */);
|
||||
}
|
||||
|
||||
/* fieldInitializations werden in einem Psedokonstruktor in der abstrakten Syntax gespeichert */
|
||||
private Constructor generatePseudoConstructor(String className, JavaClassName parentClass, RefType superClass, GenericDeclarationList classGenerics, Token offset){
|
||||
RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset);
|
||||
ParameterList params = new ParameterList(new ArrayList<>(), offset);
|
||||
Block block = new Block(new ArrayList<>(fieldInitializations), offset);
|
||||
return new Constructor(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset /*, fieldInitializations geloescht PL 2018-11-24 */);
|
||||
}
|
||||
|
||||
private RefType convert(Java8Parser.SuperclassContext superclass) {
|
||||
@ -441,7 +456,7 @@ public class SyntaxTreeGenerator{
|
||||
|
||||
List<RefType> extendedInterfaces = convert(ctx.extendsInterfaces(), generics);
|
||||
|
||||
return new ClassOrInterface(modifiers, name, fields, methods, new ArrayList<>(),
|
||||
return new ClassOrInterface(modifiers, name, fields, Optional.empty(), methods, new ArrayList<>(),
|
||||
genericParams, superClass, true, extendedInterfaces, ctx.getStart());
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package de.dhbwstuttgart.syntaxtree;
|
||||
import de.dhbwstuttgart.core.IItemWithOffset;
|
||||
import de.dhbwstuttgart.exceptions.DebugException;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.Statement;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
|
||||
@ -16,6 +17,7 @@ import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces
|
||||
@ -24,6 +26,7 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
|
||||
protected int modifiers;
|
||||
protected JavaClassName name;
|
||||
private List<Field> fields = new ArrayList<>();
|
||||
private Optional<Constructor> fieldInitializations; //PL 2018-11-24: Noetig, um Bytecode fuer initializators nur einmal zu erzeugen
|
||||
private List<Method> methods = new ArrayList<>();
|
||||
private GenericDeclarationList genericClassParameters;
|
||||
private RefType superClass;
|
||||
@ -31,13 +34,14 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
|
||||
private List<RefType> implementedInterfaces;
|
||||
private List<Constructor> constructors;
|
||||
|
||||
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters,
|
||||
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters,
|
||||
RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, Token offset){
|
||||
super(offset);
|
||||
if(isInterface && !Modifier.isInterface(modifiers))modifiers += Modifier.INTERFACE;
|
||||
this.modifiers = modifiers;
|
||||
this.name = name;
|
||||
this.fields = fielddecl;
|
||||
this.fieldInitializations= fieldInitializations;
|
||||
this.genericClassParameters = genericClassParameters;
|
||||
this.superClass = superClass;
|
||||
this.isInterface = isInterface;
|
||||
@ -59,6 +63,11 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
|
||||
public List<Field> getFieldDecl(){
|
||||
return this.fields;
|
||||
}
|
||||
|
||||
public Optional<Constructor> getfieldInitializations(){
|
||||
return this.fieldInitializations;
|
||||
}
|
||||
|
||||
public List<Method> getMethods(){
|
||||
return this.methods;
|
||||
}
|
||||
|
@ -15,8 +15,8 @@ public class Constructor extends Method {
|
||||
|
||||
//TODO: Constructor braucht ein super-Statement
|
||||
public Constructor(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block codeInsideConstructor,
|
||||
GenericDeclarationList gtvDeclarations, Token offset, List<Statement> fieldInitializations) {
|
||||
super(modifier, name, returnType, parameterList, prepareBlock(codeInsideConstructor,fieldInitializations), gtvDeclarations, offset);
|
||||
GenericDeclarationList gtvDeclarations, Token offset /*, List<Statement> fieldInitializations geloescht PL 2018-11-24 */) {
|
||||
super(modifier, name, returnType, parameterList, /*codeInsideConstructor,*/ prepareBlock(codeInsideConstructor ) /*,fieldInitializations )geloescht PL 2018-11-24 )*/, gtvDeclarations, offset);
|
||||
|
||||
}
|
||||
|
||||
@ -25,10 +25,10 @@ public class Constructor extends Method {
|
||||
* welche die Felder der zugehörigen Klasse dieses
|
||||
* Konstruktor initialisieren
|
||||
*/
|
||||
protected static Block prepareBlock(Block constructorBlock, List<Statement> fieldInitializations){
|
||||
protected static Block prepareBlock(Block constructorBlock /*, List<Statement> fieldInitializations new ArrayList<>() geloescht PL 2018-11-24 */){
|
||||
List<Statement> statements = constructorBlock.getStatements();
|
||||
statements.add(0, new SuperCall(constructorBlock.getOffset()));
|
||||
statements.addAll(fieldInitializations);
|
||||
/* statements.addAll(fieldInitializations); geloescht PL 2018-11-24 */
|
||||
return new Block(statements, constructorBlock.getOffset());
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import java.lang.reflect.*;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
@ -65,7 +66,7 @@ public class ASTFactory {
|
||||
|
||||
Token offset = new NullToken(); //Braucht keinen Offset, da diese Klasse nicht aus einem Quellcode geparst wurde
|
||||
|
||||
return new ClassOrInterface(modifier, name, felder, methoden, konstruktoren, genericDeclarationList, superClass,isInterface, implementedInterfaces, offset);
|
||||
return new ClassOrInterface(modifier, name, felder, Optional.empty() /* eingefuegt PL 2018-11-24 */,methoden, konstruktoren, genericDeclarationList, superClass,isInterface, implementedInterfaces, offset);
|
||||
}
|
||||
|
||||
private static Field createField(java.lang.reflect.Field field, JavaClassName jreClass) {
|
||||
@ -98,7 +99,7 @@ public class ASTFactory {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new de.dhbwstuttgart.syntaxtree.Constructor(modifier, name,returnType, parameterList, block, gtvDeclarations, offset, new ArrayList<>());
|
||||
return 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, java.lang.Class inClass){
|
||||
|
@ -17,10 +17,11 @@ import org.antlr.v4.runtime.Token;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class FunNClass extends ClassOrInterface {
|
||||
public FunNClass(List<GenericRefType> funNParams) {
|
||||
super(0, new JavaClassName("Fun"+(funNParams.size())), new ArrayList<>(),
|
||||
super(0, new JavaClassName("Fun"+(funNParams.size())), new ArrayList<>(), Optional.empty() /* eingefuegt PL 2018-11-24 */,
|
||||
createMethods(funNParams), new ArrayList<>(), createGenerics(funNParams),
|
||||
ASTFactory.createObjectType(), true, new ArrayList<>(), new NullToken());
|
||||
|
||||
|
@ -38,6 +38,9 @@ public class TYPE {
|
||||
for(Constructor m : cl.getConstructors()){
|
||||
ret.addAll(getConstraintsConstructor(m,info, cl));
|
||||
}
|
||||
if (cl.getfieldInitializations().isPresent()) {
|
||||
ret.addAll(getConstraintsConstructor(cl.getfieldInitializations().get(), info, cl));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
@ -61,6 +64,7 @@ public class TYPE {
|
||||
return new TypeInferenceInformation(classes);
|
||||
}
|
||||
*/
|
||||
|
||||
private ConstraintSet getConstraintsMethod(Method m, TypeInferenceInformation info, ClassOrInterface currentClass) {
|
||||
if(m.block == null)return new ConstraintSet(); //Abstrakte Methoden generieren keine Constraints
|
||||
TypeInferenceBlockInformation blockInfo = new TypeInferenceBlockInformation(info.getAvailableClasses(), currentClass, m);
|
||||
|
43
src/test/resources/bytecode/LambdaCapturetest.java
Normal file
43
src/test/resources/bytecode/LambdaCapturetest.java
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package bytecode;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
|
||||
/**
|
||||
* @author fayez
|
||||
*
|
||||
*/
|
||||
public class LambdaCapturetest {
|
||||
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;
|
||||
|
||||
@Test
|
||||
public void generateBC() throws Exception {
|
||||
path = System.getProperty("user.dir")+"/test/bytecode/javFiles/LambdaCapture.jav";
|
||||
fileToTest = new File(path);
|
||||
compiler = new JavaTXCompiler(fileToTest);
|
||||
compiler.generateBytecode(System.getProperty("user.dir")+"/testBytecode/generatedBC/");
|
||||
pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/";
|
||||
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
|
||||
classToTest = loader.loadClass("LambdaCapture");
|
||||
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
|
||||
}
|
||||
|
||||
}
|
76
src/test/resources/bytecode/simplifyalgo/CycleTest.java
Normal file
76
src/test/resources/bytecode/simplifyalgo/CycleTest.java
Normal file
@ -0,0 +1,76 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package bytecode.simplifyalgo;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import de.dhbwstuttgart.bytecode.TPHExtractor;
|
||||
import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint;
|
||||
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint;
|
||||
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation;
|
||||
import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH;
|
||||
import de.dhbwstuttgart.bytecode.utilities.Simplify;
|
||||
|
||||
/**
|
||||
* @author Fayez Abu Alia
|
||||
*
|
||||
*/
|
||||
public class CycleTest {
|
||||
|
||||
private static TPHExtractor tphExtractor;
|
||||
private static String methName;
|
||||
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
tphExtractor = new TPHExtractor();
|
||||
// A < B
|
||||
TPHConstraint c1 = new ExtendsConstraint("A", "B", Relation.EXTENDS);
|
||||
// B < C
|
||||
TPHConstraint c2 = new ExtendsConstraint("B", "C", Relation.EXTENDS);
|
||||
// C < D
|
||||
TPHConstraint c3 = new ExtendsConstraint("C", "D", Relation.EXTENDS);
|
||||
// D < A
|
||||
TPHConstraint c4 = new ExtendsConstraint("D", "A", Relation.EXTENDS);
|
||||
// name
|
||||
methName = "m";
|
||||
MethodAndTPH mtph = new MethodAndTPH("m");
|
||||
mtph.getTphs().add("A");
|
||||
mtph.getTphs().add("B");
|
||||
mtph.getTphs().add("C");
|
||||
mtph.getTphs().add("D");
|
||||
tphExtractor.ListOfMethodsAndTph.add(mtph);
|
||||
tphExtractor.allCons.add(c1);
|
||||
tphExtractor.allCons.add(c2);
|
||||
tphExtractor.allCons.add(c3);
|
||||
tphExtractor.allCons.add(c4);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
HashMap<TPHConstraint, HashSet<String>> result = new HashMap<>();
|
||||
HashSet<String> equals = new HashSet<>();
|
||||
equals.add("A");
|
||||
equals.add("B");
|
||||
equals.add("C");
|
||||
equals.add("D");
|
||||
TPHConstraint k = new ExtendsConstraint("A", Type.getInternalName(Object.class), Relation.EXTENDS);
|
||||
result.put(k, equals);
|
||||
|
||||
HashMap<TPHConstraint, HashSet<String>> sim = Simplify.simplifyConstraints(methName, tphExtractor);
|
||||
boolean areEquals = SimpleCycle.areMapsEqual(result, sim);
|
||||
assertTrue(areEquals);
|
||||
}
|
||||
|
||||
}
|
97
src/test/resources/bytecode/simplifyalgo/SameLeftSide.java
Normal file
97
src/test/resources/bytecode/simplifyalgo/SameLeftSide.java
Normal file
@ -0,0 +1,97 @@
|
||||
package bytecode.simplifyalgo;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import de.dhbwstuttgart.bytecode.TPHExtractor;
|
||||
import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint;
|
||||
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint;
|
||||
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation;
|
||||
import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH;
|
||||
import de.dhbwstuttgart.bytecode.utilities.Simplify;
|
||||
import de.dhbwstuttgart.typedeployment.TypeInsertPlacer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Fayez Abu Alia
|
||||
*
|
||||
*/
|
||||
public class SameLeftSide {
|
||||
// Typeplaceholders können nicht definiert werden, da die Konstruktor
|
||||
// private ist => Test geht nicht
|
||||
private static TPHExtractor tphExtractor;
|
||||
private static String methName;
|
||||
private static String methName2;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
tphExtractor = new TPHExtractor();
|
||||
// A < B
|
||||
TPHConstraint c1 = new ExtendsConstraint("A", "B", Relation.EXTENDS);
|
||||
// A < C
|
||||
TPHConstraint c2 = new ExtendsConstraint("A", "C", Relation.EXTENDS);
|
||||
// B < D
|
||||
TPHConstraint c3 = new ExtendsConstraint("B", "D", Relation.EXTENDS);
|
||||
// C < E
|
||||
TPHConstraint c4 = new ExtendsConstraint("C", "E", Relation.EXTENDS);
|
||||
// name
|
||||
methName = "m1";
|
||||
MethodAndTPH m1 = new MethodAndTPH("m1");
|
||||
|
||||
methName2 = "m2";
|
||||
MethodAndTPH m2 = new MethodAndTPH("m2");
|
||||
|
||||
m1.getTphs().add("A");
|
||||
m1.getTphs().add("B");
|
||||
m1.getTphs().add("D");
|
||||
|
||||
m2.getTphs().add("C");
|
||||
m2.getTphs().add("E");
|
||||
|
||||
tphExtractor.ListOfMethodsAndTph.add(m1);
|
||||
tphExtractor.ListOfMethodsAndTph.add(m2);
|
||||
|
||||
tphExtractor.allCons.add(c1);
|
||||
tphExtractor.allCons.add(c2);
|
||||
tphExtractor.allCons.add(c3);
|
||||
tphExtractor.allCons.add(c4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testM1() {
|
||||
HashMap<TPHConstraint, HashSet<String>> result = new HashMap<>();
|
||||
|
||||
TPHConstraint d = new ExtendsConstraint("D", Type.getInternalName(Object.class), Relation.EXTENDS);
|
||||
TPHConstraint a = new ExtendsConstraint("A", "D", Relation.EXTENDS);
|
||||
TPHConstraint b = new ExtendsConstraint("B", "D", Relation.EXTENDS);
|
||||
result.put(d, null);
|
||||
result.put(a, null);
|
||||
result.put(b, null);
|
||||
|
||||
HashMap<TPHConstraint, HashSet<String>> sim = Simplify.simplifyConstraints(methName, tphExtractor);
|
||||
boolean areEquals = SimpleCycle.areMapsEqual(result, sim);
|
||||
assertTrue(areEquals);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testM2() {
|
||||
HashMap<TPHConstraint, HashSet<String>> result = new HashMap<>();
|
||||
|
||||
TPHConstraint e = new ExtendsConstraint("E", Type.getInternalName(Object.class), Relation.EXTENDS);
|
||||
TPHConstraint c = new ExtendsConstraint("C", "E", Relation.EXTENDS);
|
||||
|
||||
result.put(e, null);
|
||||
result.put(c, null);
|
||||
|
||||
HashMap<TPHConstraint, HashSet<String>> sim = Simplify.simplifyConstraints(methName2, tphExtractor);
|
||||
boolean areEquals = SimpleCycle.areMapsEqual(result, sim);
|
||||
assertTrue(areEquals);
|
||||
}
|
||||
|
||||
}
|
79
src/test/resources/bytecode/simplifyalgo/SimpleCycle.java
Normal file
79
src/test/resources/bytecode/simplifyalgo/SimpleCycle.java
Normal file
@ -0,0 +1,79 @@
|
||||
package bytecode.simplifyalgo;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import de.dhbwstuttgart.bytecode.TPHExtractor;
|
||||
import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint;
|
||||
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint;
|
||||
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation;
|
||||
import de.dhbwstuttgart.bytecode.utilities.Simplify;
|
||||
/**
|
||||
*
|
||||
* @author Fayez Abu Alia
|
||||
*
|
||||
*/
|
||||
public class SimpleCycle {
|
||||
private static TPHExtractor tphExtractor;
|
||||
private static String methName;
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
tphExtractor = new TPHExtractor();
|
||||
// A < B
|
||||
TPHConstraint c1 = new ExtendsConstraint("A", "B", Relation.EXTENDS);
|
||||
// B < A
|
||||
TPHConstraint c2 = new ExtendsConstraint("B", "A", Relation.EXTENDS);
|
||||
// name
|
||||
methName = "m";
|
||||
tphExtractor.allCons.add(c1);
|
||||
tphExtractor.allCons.add(c2);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
HashMap<TPHConstraint, HashSet<String>> result = new HashMap<>();
|
||||
HashSet<String> equals = new HashSet<>();
|
||||
equals.add("A");
|
||||
equals.add("B");
|
||||
TPHConstraint k = new ExtendsConstraint("B", Type.getInternalName(Object.class), Relation.EXTENDS);
|
||||
result.put(k, equals);
|
||||
|
||||
HashMap<TPHConstraint, HashSet<String>> sim = Simplify.simplifyConstraints(methName, tphExtractor);
|
||||
boolean areEquals = areMapsEqual(result, sim);
|
||||
assertTrue(areEquals);
|
||||
}
|
||||
|
||||
public static boolean areMapsEqual(HashMap<TPHConstraint, HashSet<String>> m1, HashMap<TPHConstraint, HashSet<String>> m2) {
|
||||
|
||||
for(TPHConstraint c : m1.keySet()) {
|
||||
for(TPHConstraint c2 : m2.keySet()) {
|
||||
if(c.getLeft().equals(c2.getLeft()) && c.getRight().equals(c2.getRight()) && c.getRel()==c2.getRel()) {
|
||||
HashSet<String> eq1 = m1.get(c);
|
||||
HashSet<String> eq2 = m2.get(c2);
|
||||
|
||||
if((eq1 == null && eq2 != null) || (eq1 != null && eq2 == null))
|
||||
return false;
|
||||
if(eq1 != null) {
|
||||
if(eq1.size() != eq2.size())
|
||||
return false;
|
||||
|
||||
for(String tph:eq1) {
|
||||
if(!eq2.contains(tph))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -4,10 +4,8 @@ public class Faculty {
|
||||
public fact;
|
||||
Faculty() {
|
||||
fact = (x) -> {
|
||||
if(x<0) {
|
||||
return 0;
|
||||
}else if (x < 1) {
|
||||
return x;
|
||||
if (x == 1) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return x * (fact.apply(x-1));
|
||||
@ -15,6 +13,10 @@ public class Faculty {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public getFact(x) {
|
||||
return fact.apply(x);
|
||||
}
|
||||
// m (x) {
|
||||
//
|
||||
//// var fact = (x) -> {
|
||||
|
12
src/test/resources/javFiles/bytecode/LambdaCapture.jav
Normal file
12
src/test/resources/javFiles/bytecode/LambdaCapture.jav
Normal file
@ -0,0 +1,12 @@
|
||||
import java.lang.Integer;
|
||||
public class LambdaCapture {
|
||||
Integer i = 8;
|
||||
f;
|
||||
public LambdaCapture(){
|
||||
Integer w = 7;
|
||||
f = j ->{
|
||||
return w+i;};
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -20,4 +20,3 @@ public class OLMain {
|
||||
return ol.m(x);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,8 @@ public class Tph {
|
||||
|
||||
m(a,b){
|
||||
var c = m2(b);
|
||||
return a;
|
||||
// return m2(b);
|
||||
// return a;
|
||||
return m2(b);
|
||||
}
|
||||
|
||||
m2(b){
|
||||
|
58
test/bytecode/FacultyTest.java
Normal file
58
test/bytecode/FacultyTest.java
Normal file
@ -0,0 +1,58 @@
|
||||
package bytecode;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
|
||||
public class FacultyTest {
|
||||
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;
|
||||
|
||||
@Test
|
||||
public void generateBC() throws Exception {
|
||||
path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Faculty.jav";
|
||||
fileToTest = new File(path);
|
||||
compiler = new JavaTXCompiler(fileToTest);
|
||||
compiler.generateBytecode(System.getProperty("user.dir")+"/testBytecode/generatedBC/");
|
||||
pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/";
|
||||
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
|
||||
classToTest = loader.loadClass("Faculty");
|
||||
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
|
||||
|
||||
Method getFact = classToTest.getDeclaredMethod("getFact", Integer.class);
|
||||
// Field fact = classToTest.getDeclaredField("fact");
|
||||
// Class<?> lambda = m.invoke(instanceOfClass).getClass();
|
||||
// Class<?> lambda = fact.getType();
|
||||
// System.out.println(fact.getType().getName());
|
||||
// Method apply = lambda.getMethod("apply", Object.class);
|
||||
// System.out.println(lambda.getMethods()[0]);
|
||||
// System.out.println(instanceOfClass.toString());
|
||||
// // Damit man auf die Methode zugreifen kann
|
||||
// apply.setAccessible(true);
|
||||
// Field value
|
||||
// Object fieldVal = fact.get(instanceOfClass);
|
||||
Integer i = 3;
|
||||
// Method applyFromField = fieldVal.getClass().getDeclaredMethod("apply", Object.class);
|
||||
// applyFromField.setAccessible(true);
|
||||
// Integer result = (Integer) apply.invoke(lambda,i);
|
||||
Integer result = (Integer) getFact.invoke(instanceOfClass,i);
|
||||
|
||||
assertEquals(6, result);
|
||||
}
|
||||
|
||||
|
||||
}
|
50
test/bytecode/LambdaTest.java
Normal file
50
test/bytecode/LambdaTest.java
Normal file
@ -0,0 +1,50 @@
|
||||
package bytecode;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
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.Test;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
|
||||
public class LambdaTest {
|
||||
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;
|
||||
|
||||
@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(System.getProperty("user.dir")+"/testBytecode/generatedBC/");
|
||||
pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/";
|
||||
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
|
||||
classToTest = loader.loadClass("Lambda");
|
||||
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
|
||||
|
||||
Method m = classToTest.getDeclaredMethod("m");
|
||||
Class<?> lambda = m.invoke(instanceOfClass).getClass();
|
||||
Method apply = lambda.getMethod("apply", Object.class);
|
||||
|
||||
// Damit man auf die Methode zugreifen kann
|
||||
apply.setAccessible(true);
|
||||
|
||||
Integer i = 77;
|
||||
System.out.println(m.invoke(instanceOfClass).toString());
|
||||
Integer result = (Integer) apply.invoke(m.invoke(instanceOfClass), i);
|
||||
|
||||
assertEquals(77, result);
|
||||
}
|
||||
|
||||
|
||||
}
|
91
test/bytecode/MatrixOpTest.java
Normal file
91
test/bytecode/MatrixOpTest.java
Normal file
@ -0,0 +1,91 @@
|
||||
package bytecode;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
|
||||
public class MatrixOpTest {
|
||||
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_m1;
|
||||
private static Object instanceOfClass_m2;
|
||||
private static Object instanceOfClass_m3;
|
||||
|
||||
@Test
|
||||
public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, IOException, InstantiationException {
|
||||
path = System.getProperty("user.dir")+"/test/bytecode/javFiles/MatrixOP.jav";
|
||||
fileToTest = new File(path);
|
||||
compiler = new JavaTXCompiler(fileToTest);
|
||||
pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/";
|
||||
compiler.generateBytecode(pathToClassFile);
|
||||
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
|
||||
classToTest = loader.loadClass("MatrixOP");
|
||||
/*
|
||||
Vector<Vector<Integer>> vv = new Vector<Vector<Integer>>();
|
||||
Vector<Integer> v1 = new Vector<Integer> ();
|
||||
v1.addElement(2);
|
||||
v1.addElement(2);
|
||||
Vector<Integer> v2 = new Vector<Integer> ();
|
||||
v2.addElement(3);
|
||||
v2.addElement(3);
|
||||
//Matrix m1 = new Matrix();
|
||||
//m1.addElement(v1);
|
||||
//m1.addElement(v2);
|
||||
vv.addElement(v1);
|
||||
vv.addElement(v2);
|
||||
instanceOfClass_m1 = classToTest.getDeclaredConstructor(Vector.class).newInstance(vv); //Matrix m1 = new Matrix(vv);
|
||||
|
||||
Vector<Vector<Integer>> vv1 = new Vector<Vector<Integer>>();
|
||||
Vector<Integer> v3 = new Vector<Integer> ();
|
||||
v3.addElement(2);
|
||||
v3.addElement(2);
|
||||
Vector<Integer> v4 = new Vector<Integer> ();
|
||||
v4.addElement(3);
|
||||
v4.addElement(3);
|
||||
//Matrix m2 = new Matrix();
|
||||
//m2.addElement(v3);
|
||||
//m2.addElement(v4);
|
||||
vv1.addElement(v3);
|
||||
vv1.addElement(v4);
|
||||
instanceOfClass_m2 = classToTest.getDeclaredConstructor(Vector.class).newInstance(vv1);//Matrix m2 = new Matrix(vv1);
|
||||
|
||||
|
||||
|
||||
//Matrix m3 = m1.mul(vv1);
|
||||
Method mul = classToTest.getDeclaredMethod("mul", Vector.class);
|
||||
Object result = mul.invoke(instanceOfClass_m1, instanceOfClass_m2);
|
||||
System.out.println(instanceOfClass_m1.toString() + " * " + instanceOfClass_m2.toString() + " = " + result.toString());
|
||||
|
||||
Vector<Vector<Integer>> res = new Vector<Vector<Integer>>();
|
||||
Vector<Integer> v5 = new Vector<Integer> ();
|
||||
v5.addElement(10);
|
||||
v5.addElement(10);
|
||||
Vector<Integer> v6 = new Vector<Integer> ();
|
||||
v6.addElement(15);
|
||||
v6.addElement(15);
|
||||
//Matrix m2 = new Matrix();
|
||||
//m2.addElement(v3);
|
||||
//m2.addElement(v4);
|
||||
res.addElement(v5);
|
||||
res.addElement(v6);
|
||||
instanceOfClass_m3 = classToTest.getDeclaredConstructor(Vector.class).newInstance(res);
|
||||
assertEquals(result, instanceOfClass_m3);
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
52
test/bytecode/YTest.java
Normal file
52
test/bytecode/YTest.java
Normal file
@ -0,0 +1,52 @@
|
||||
package bytecode;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
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.Test;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
|
||||
public class YTest {
|
||||
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;
|
||||
|
||||
@Test
|
||||
public void generateBC() throws Exception {
|
||||
path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Y.jav";
|
||||
fileToTest = new File(path);
|
||||
// compiler = new JavaTXCompiler(fileToTest);
|
||||
// compiler.generateBytecode(System.getProperty("user.dir")+"/testBytecode/generatedBC/");
|
||||
// pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/";
|
||||
// loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
|
||||
// classToTest = loader.loadClass("Y");
|
||||
/*
|
||||
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
|
||||
|
||||
Method m = classToTest.getDeclaredMethod("m");
|
||||
Class<?> lambda = m.invoke(instanceOfClass).getClass();
|
||||
Method apply = lambda.getMethod("apply", Object.class);
|
||||
|
||||
// Damit man auf die Methode zugreifen kann
|
||||
apply.setAccessible(true);
|
||||
|
||||
Integer i = 77;
|
||||
|
||||
Integer result = (Integer) apply.invoke(m.invoke(instanceOfClass), i);
|
||||
|
||||
assertEquals(77, result);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user